文章目錄
- 0.定義CMS
- 1.CMS頁面管理
- 2.需求分析
- 3.模型類介紹
- 4.定義請求及響應類型
- 5.定義接口
- 6.創建CMS工程結構
- 7.Dao
- 1)創建Dao,繼承MongoRepository
- 2)編寫測試類
- 分頁查詢測試
- 添加
- 刪除
- 修改
- 8.Service
- 9.Controller
- 10.接口開發規范
0.定義CMS
1)CMS是什么 ?
CMS (Content Management System)即內容管理系統,不同的項目對CMS的定位不同,比如:一個在線教育網站,有些公司認為CMS系統是對所有的課程資源進行管理,而在早期網站剛開始盛行時很多公司的業務是網站制作,當時對CMS的定位是創建網站,即對網站的頁面、圖片等靜態資源進行管理。
2)CMS有哪些類型?
上邊也談到每個公司對每個項目的CMS定位不同,CMS基本上分為:針對后臺數據內容的管理、針對前端頁面的管理、針對樣式風格的管理等 。比如:一個給企業做網站的公司,其CMS系統主要是網站頁面管理及樣式風格的管理。
3)本項目CMS的定位是什么?
本項目作為一個大型的在線教育平臺,對CMS系統的定位是對各各網站(子站點)頁面的管理,主要管理由于運營需要而經常變動的頁面,從而實現根據運營需要快速進行頁面開發、上線的需求。
1.CMS頁面管理
本項目要實現什么樣的功能?
1)頁面管理
管理員在后臺添加、修改、刪除頁面信息。
2)頁面預覽
管理員通過頁面預覽功能預覽頁面發布后的效果。
3)頁面發布
管理員通過頁面發布功能將頁面發布到遠程門戶服務器。頁面發布成功,用戶即可在瀏覽器瀏覽到最新發布的頁面,整個頁面添加、發布的過程由于軟件自動執行,無需人工登錄服務器操作。
這些頁面的管理流程是什么?
1)創建站點:
一個網站有很多子站點,比如:學成在線有主門戶、學習中心、問答系統等子站點。具體的哪個頁面是歸屬于具體的站點,所以要管理頁面,先要管理頁面所屬的站點。
2)創建模板:
頁面如何創建呢?比如電商網站的商品詳情頁面,每個頁面的內容布局、板式是相同的,不同的只是內容,這個頁面的布局、板式就是頁面模板,模板+數據就組成一個完整的頁面,最終要創建一個頁面文件需要先定義此頁面的模板,最終拿到頁面的數據再結合模板就拼裝成一個完整的頁面。
3)創建頁面:
創建頁面是指填寫頁面的基本信息,如:頁面的名稱、頁面的url地址等。
4)頁面預覽:
頁面預覽是頁面發布前的一項工作,頁面預覽使用靜態化技術根據頁面模板和數據生成頁面內容,并通過瀏覽器預覽頁面。頁面發布前進行頁面預覽的目是為了保證頁面發布后的正確性。
5)頁面發布:
使用計算機技術將頁面發送到頁面所在站點的服務器,頁面發布成功就可以通過瀏覽器來訪問了。
2.需求分析
在梳理完用戶需求后就要去定義前后端的接口,接口定義后前端和后端就可以依據接口去開發功能。
具體需求如下:
1、分頁查詢CmsPage 集合下的數據
2、根據站點Id、模板Id、頁面別名查詢頁面信息
3、接口基于Http Get請求,響應Json數據
本次定義頁面查詢接口,本接口供前端請求查詢頁面列表,支持分頁及自定義條件查詢方式。
3.模型類介紹
接口的定義離不開數據模型,根據前邊對需求的分析,整個頁面管理模塊的數據模型如下:
CmsSite:站點模型
CmsTemplate:頁面模板
CmsPage:頁面信息
其中頁面信息CmsPage如下:
package com.xuecheng.framework.domain.cms;import lombok.Data;
import lombok.ToString;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;import java.util.Date;
import java.util.List;@Data
@ToString
@Document(collection = "cms_page")
public class CmsPage {/*** 頁面名稱、別名、訪問地址、類型(靜態/動態)、頁面模版、狀態*///站點IDprivate String siteId;//頁面ID@Idprivate String pageId;//頁面名稱private String pageName;//別名private String pageAliase;//訪問地址private String pageWebPath;//參數private String pageParameter;//物理路徑private String pagePhysicalPath;//類型(靜態/動態)private String pageType;//頁面模版private String pageTemplate;//頁面靜態化內容private String pageHtml;//狀態private String pageStatus;//創建時間private Date pageCreateTime;//模版idprivate String templateId;//參數列表private List<CmsPageParam> pageParams;//模版文件Id
// private String templateFileId;//靜態文件Idprivate String htmlFileId;//數據Urlprivate String dataUrl;
}
屬性說明:
1、定義一個頁面需要指定頁面所屬站點
一個站點包括多個頁面,比如:學成在線的門戶站點(網站)包括了多個頁面。
2、定義一個頁面需要指定頁面使用的模板
多個頁面可以使用相同的模板,比如:商品信息模板,每個商品就是一個頁面,所有商品使用同一個商品信息模板
注解說明:
@Data、@ToString:是Lombok提供的注解。
@Document:是Spring Data mongodb提供的注解,最終CMS的開發會使用Mongodb數據庫。
4.定義請求及響應類型
定義請求模型QueryPageRequest,此模型作為查詢條件類型
package com.xuecheng.framework.domain.cms.request;import io.swagger.annotations.ApiModelProperty;
import lombok.Data;@Data
public class QueryPageRequest {//接收頁面查詢的查詢條件//站點id//站點id@ApiModelProperty("站點id")private String siteId;//頁面IDprivate String pageId;//頁面名稱private String pageName;//別名private String pageAliase;//模版idprivate String templateId;//....
}
響應結果類型,分頁查詢統一使用QueryResponseResult
package com.xuecheng.framework.model.response;import lombok.Data;
import lombok.ToString;@Data
@ToString
public class QueryResponseResult extends ResponseResult {QueryResult queryResult;public QueryResponseResult(ResultCode resultCode,QueryResult queryResult){super(resultCode);this.queryResult = queryResult;}}
5.定義接口
在Api接口工程專門定義接口,在Api工程單獨定義接口的原因如下:
1、接口集中管理
2、Api工程的接口將作為各微服務遠程調用使用。
頁面查詢接口定義如下:
public interface CmsPageControllerApi {
public QueryResponseResult findList(int page, int size, QueryPageRequest queryPageRequest) ;
}
此接口編寫后會在CMS服務工程編寫Controller類實現此接口。
6.創建CMS工程結構
1)創建maven工程, CMS工程的名稱為 xc-service-manage-cms,父工程為xc-framework-parent。
pom.xml如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>xc-framework-parent</artifactId><groupId>com.xuecheng</groupId><version>1.0-SNAPSHOT</version><relativePath>../xc-framework-parent/pom.xml</relativePath></parent><modelVersion>4.0.0</modelVersion><artifactId>xc-service-manage-cms</artifactId><dependencies><dependency><groupId>com.xuecheng</groupId><artifactId>xc-service-api</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>com.xuecheng</groupId><artifactId>xc-framework-model</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>com.xuecheng</groupId><artifactId>xc-framework-utils</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>com.xuecheng</groupId><artifactId>xc-framework-common</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency></dependencies></project>
由于cms工程要連接mongodb,使用spring data mongodb操作mongodb數據庫,所以需要在在cms服務端工程添加依賴spring-boot-starter-data-mongodb。
2)創建基本的包結構:
com.xuecheng.manage_cms.config:配置類目錄,數據庫配置、MQ配置等
com.xuecheng.manage_cms.dao:dao接口目錄
com.xuecheng.manage_cms.service:service類目錄
com.xuecheng.manage_cms.web.controller:controller類目錄
3)配置文件
在classpath下配置application.yml
server:port: 31001
spring:application:name: xc-service-manage-cmsdata:mongodb:uri: mongodb://root:123@localhost:27017database: xc_cms
logback-spring.xml:
<?xml version="1.0" encoding="UTF-8"?><configuration><!--定義日志文件的存儲地址,使用絕對路徑--><property name="LOG_HOME" value="d:/logs"/><!-- Console 輸出設置 --><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日志消息,%n是換行符--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern><charset>utf8</charset></encoder></appender><!-- 按照每天生成日志文件 --><appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--日志文件輸出的文件名--><fileNamePattern>${LOG_HOME}/xc.%d{yyyy-MM-dd}.log</fileNamePattern></rollingPolicy><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern></encoder></appender><!-- 異步輸出 --><appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender"><!-- 不丟失日志.默認的,如果隊列的80%已滿,則會丟棄TRACT、DEBUG、INFO級別的日志 --><discardingThreshold>0</discardingThreshold><!-- 更改默認的隊列的深度,該值會影響性能.默認值為256 --><queueSize>512</queueSize><!-- 添加附加的appender,最多只能添加一個 --><appender-ref ref="FILE"/></appender><logger name="org.apache.ibatis.cache.decorators.LoggingCache" level="DEBUG" additivity="false"><appender-ref ref="CONSOLE"/></logger><logger name="org.springframework.boot" level="DEBUG"/><root level="info"><!--<appender-ref ref="ASYNC"/>--><appender-ref ref="FILE"/><appender-ref ref="CONSOLE"/></root>
</configuration>
4)SpringBoot 啟動類
Spring Boot應用需要創建一個應用啟動類,啟動過程中會掃描Bean并注入spring 容器
注意:此類創建在本工程com.xuecheng.manage_cms包下
package com.xuecheng.manage_cms;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;@SpringBootApplication
@EntityScan("com.xuecheng.framework.domain.cms")//掃描實體類
@ComponentScan(basePackages={"com.xuecheng.api"})//掃描接口
@ComponentScan(basePackages={"com.xuecheng.manage_cms"})//掃描本項目下的所有類
public class ManageCmsApplication {public static void main(String[] args) {SpringApplication.run(ManageCmsApplication.class,args);}
}
7.Dao
1)創建Dao,繼承MongoRepository
本項目使用Spring Data Mongodb完成Mongodb數據庫的查詢,Spring Data Mongodb提供一套快捷操作mongodb的方法。
創建Dao,繼承MongoRepository,并指定實體類型和主鍵類型。
package com.xuecheng.manage_cms.dao;import com.xuecheng.framework.domain.cms.CmsPage;
import org.springframework.data.mongodb.repository.MongoRepository;public interface CmsPageRepository extends MongoRepository<CmsPage,String> {//根據頁面名稱查詢CmsPage findByPageName(String pageName);
}
其中繼承的接口MongoRepository有以下方法:
2)編寫測試類
test下的包路徑與main下的包路徑保持一致。
測試程序使用@SpringBootTest和@RunWith(SpringRunner.class)注解,啟動測試類會從main下找springBoot啟
動類,加載spring容器。
測試代碼如下:
package com.xuecheng.manage_cms;
import com.xuecheng.framework.domain.cms.CmsPage;
import com.xuecheng.manage_cms.dao.CmsPageRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.*;
import org.springframework.test.context.junit4.SpringRunner;@SpringBootTest
@RunWith(SpringRunner.class)
public class CmsPageRepositoryTest {@Autowired
CmsPageRepository cmsPageRepository;}
分頁查詢測試
//分頁測試
@Test
public void testFindPage() {
int page = 0;//從0開始
int size = 10;//每頁記錄數
Pageable pageable = PageRequest.of(page,size);
Page<CmsPage> all = cmsPageRepository.findAll(pageable);
System.out.println(all);
}
添加
//添加
@Test
public void testInsert(){
//定義實體類
CmsPage cmsPage = new CmsPage();
cmsPage.setSiteId("s01");
cmsPage.setTemplateId("t01");
cmsPage.setPageName("測試頁面");
cmsPage.setPageCreateTime(new Date());
List<CmsPageParam> cmsPageParams = new ArrayList<>();
CmsPageParam cmsPageParam = new CmsPageParam();
cmsPageParam.setPageParamName("param1");
cmsPageParam.setPageParamValue("value1");
cmsPageParams.add(cmsPageParam);
cmsPage.setPageParams(cmsPageParams);
cmsPageRepository.save(cmsPage);
System.out.println(cmsPage);
}
刪除
//刪除
@Test
public void testDelete() {
cmsPageRepository.deleteById("5b17a2c511fe5e0c409e5eb3");
}
修改
/
/修改
@Test
public void testUpdate() {
Optional<CmsPage> optional = cmsPageRepository.findOne("5b17a34211fe5e2ee8c116c9");
if(optional.isPresent()){
CmsPage cmsPage = optional.get();
cmsPage.setPageName("測試頁面01");
cmsPageRepository.save(cmsPage);
}
}
關于Optional:
Optional是jdk1.8引入的類型,Optional是一個容器對象,它包括了我們需要的對象,使用isPresent方法判斷所包
含對象是否為空,isPresent方法返回false則表示Optional包含對象為空,否則可以使用get()取出對象進行操作。
Optional的優點是:
1、提醒你非空判斷。
2、將對象非空檢測標準化。
3)自定義Dao方法
同Spring Data JPA一樣Spring Data mongodb也提供自定義方法的規則,如下:
按照findByXXX,findByXXXAndYYY、countByXXXAndYYY等規則定義方法,實現查詢操作。
public interface CmsPageRepository extends MongoRepository<CmsPage,String> {
//根據頁面名稱查詢
CmsPage findByPageName(String pageName);
//根據頁面名稱和類型查詢
CmsPage findByPageNameAndPageType(String pageName,String pageType);
//根據站點和頁面類型查詢記錄數
int countBySiteIdAndPageType(String siteId,String pageType);
//根據站點和頁面類型分頁查詢
Page<CmsPage> findBySiteIdAndPageType(String siteId,String pageType, Pageable pageable);
}
8.Service
定義頁面查詢方法,根據條件查詢暫時不實現:
package com.xuecheng.manage_cms.service;
import com.xuecheng.framework.domain.cms.CmsPage;
import com.xuecheng.framework.domain.cms.request.QueryPageRequest;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.QueryResponseResult;
import com.xuecheng.framework.model.response.QueryResult;
import com.xuecheng.manage_cms.dao.CmsPageRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
@Service
public class PageService {
@Autowired
CmsPageRepository cmsPageRepository;
/**
* 頁面列表分頁查詢
* @param page 當前頁碼
* @param size 頁面顯示個數
* @param queryPageRequest 查詢條件
* @return 頁面列表
*/
public QueryResponseResult findList(int page,int size,QueryPageRequest queryPageRequest){if (queryPageRequest == null) {queryPageRequest = new QueryPageRequest();} if (page <= 0) {page = 1;} page = page ‐ 1;//為了適應mongodb的接口將頁碼減1if (size <= 0) {size = 20;} //分頁對象Pageable pageable = new PageRequest(page, size);//分頁查詢Page<CmsPage> all = cmsPageRepository.findAll(pageable);QueryResult<CmsPage> cmsPageQueryResult = new QueryResult<CmsPage>();cmsPageQueryResult.setList(all.getContent());cmsPageQueryResult.setTotal(all.getTotalElements());//返回結果return new QueryResponseResult(CommonCode.SUCCESS,cmsPageQueryResult);}
}
9.Controller
使用springMVC完成接口實現開發。
package com.xuecheng.manage_cms.web.controller;
import com.xuecheng.api.cms.CmsPageControllerApi;
import com.xuecheng.framework.domain.cms.request.QueryPageRequest;
import com.xuecheng.framework.model.response.QueryResponseResult;
import com.xuecheng.manage_cms.service.PageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class CmsPageController implements CmsPageControllerApi {
@Autowired
PageService pageService;
@Override
@GetMapping("/list/{page}/{size}")
public QueryResponseResult findList(@PathVariable("page") int page, @PathVariable("size")
int size, QueryPageRequest queryPageRequest) {
return pageService.findList(page,size,queryPageRequest);
}
}
使用瀏覽器測試
輸入:http://localhost:31001/cms/page/list/1/10 查詢第1頁,每頁顯示10條記錄。
10.接口開發規范
Api請求及響應規范
為了嚴格按照接口進行開發,提高效率,對請求及響應格式進行規范化。
1)get 請求時,采用key/value格式請求,SpringMVC可采用基本類型的變量接收,也可以采用對象接收。
2)Post請求時,可以提交form表單數據(application/x-www-form-urlencoded)和Json數據(ContentType=application/json),文件等多部件類型(multipart/form-data)三種數據格式,SpringMVC接收Json數據
使用@RequestBody注解解析請求的json數據。
3)響應結果統一信息為:是否成功、操作代碼、提示信息及自定義數據。
4)響應結果統一格式為json。
Api定義約束
Api定義使用SpringMVC來完成,由于此接口后期將作為微服務遠程調用使用,在定義接口時有如下限制:
1)@PathVariable 統一指定參數名稱,如:@PathVariable(“id”)
2)@RequestParam統一指定參數名稱,如:@RequestParam(“id”)