3 CMS需求分析
3.1 什麼是CMS
cms是一個內容管理系統,它的作用在本項目的定位是對各個子網站的頁面進行管理,主要管理由於運營需要而經常變動的頁面,從而實現根據運營需要快速進行頁面開發、上線的需求。
3.2 靜態門戶工程搭建
3.2.1 導入門戶工程
ngnix:
雙擊nginx.exe即可運行。訪問 :http://localhost
導入給好的門戶工程
3.2.2 配置虛擬主機
配置nginx-1.14.0/conf/nginx.cnf:(把原來server的那部分刪了添加下面部分)
server {
listen 80;
server_name www.xuecheng.com;
ssi on;
ssi_silent_errors on;
location / {
alias D:/Users/98524/Desktop/space/xc-import/xc-ui-pc-static-portal/;
index index.html;
}
}
D:/Users/98524/Desktop/space/xc-import/xc-ui-pc-static-portal/ 本目錄即爲門戶的主目錄。
修改完後重啓一下讓它加載修改的配置文件:
此時可用 localhost:80 訪問而不能用 www.xuecheng.com 訪問
配置hosts文件:
C:\Windows\System32\drivers\etc\hosts
127.0.0.1 www.xuecheng.com
進入瀏覽器,輸入http://www.xuecheng.com
3.3 SSI服務端包含技術
本節分析首頁的管理方案。
1、頁面內容多如何管理?
將頁面拆分成一個一個的小頁面(輪播圖、導航欄等等),通過cms去管理這些小頁面,當要更改部分頁面內容時只需要更改具體某個小頁面即可。
2、頁面拆出來怎麼樣通過web服務瀏覽呢?
使用web服務(例如nginx)的SSI技術,將多個子頁面合併渲染輸出。
ssi是一項web服務的技術(例如nginx),ssi包含類似於jsp頁面中的incluce指令,ssi是在web服務端將include指定 的頁面包含在網頁中,渲染html網頁響應給客戶端 。nginx、apache等多數web容器都支持SSI指令。
ssi指令如下:
<!‐‐#include virtual="/../....html"‐‐>
如果需要用到的話需要在虛擬主機中開起來:
ssi的配置參數如下:
ssi on: 開啓ssi支持
ssi_silent_errors on:默認爲off,設置爲on則在處理SSI文件出錯時不輸出錯誤信息
ssi_types:默認爲 ssi_types text/html,如果需要支持shtml(服務器執行腳本,類似於jsp)則需要設置爲ssi_types text/shtml
3.4 CMS頁面管理需求
你想在數據庫裏面添加一個頁面,先要創建它的站點,再創建它所使用的模板,然後才添加頁面信息,再採用靜態化技術根據模板和數據生成頁面內容進行頁面預覽,再進行頁面發佈
(創建模板的目的,進行頁面靜態化生成頁面內容)
4 CMS服務端工程搭建
4.1 開發工具配置
1、創建工程代碼目錄 XcEduCode01
目前爲止已經創建好服務端工程目錄和前端工程目錄
2、配置maven環境,拷貝老師提供的maven倉庫,setting.xml文件中配置maven倉庫
maven的下載包:
3、配置編碼
4、配置JDK1.8
6、自動導入包
idea可以自動優化導入包,但是有多個同名的類調用不同的包,必須自己手動Alt+Enter設置
9、配置虛擬機內存
修改idea64.exe.vmoptions(64位電腦選擇此文件)
一個例子,電腦內存8G,設置如下:
-Xms1024m -Xmx4096m -XX:MaxPermSize=1024m -XX:ReservedCodeCacheSize=1024m
4.2 導入基礎工程
4.2.1 工程結構
parent父工程只需要一個pom文件即可
model工程放的就是對應數據庫的類似bean的
解壓提供好的基礎工程放到服務端的目錄下:
4.2.2導入父工程及其他工程
結果:
再依次導入utils、model、common、api工程即可
4.3 MongoDB入門
CMS採用MongoDB數據庫存儲CMS頁面信息,CMS選用Mongodb的原因如下:
1、Mongodb是非關係型數據庫,存儲Json格式數據 ,數據格式靈活。
2、相比課程管理等核心數據CMS數據不重要,且沒有事務管理要求。
啓動mongodb:
創建幾個文件夾具體如下:數據庫路徑(data目錄)、日誌路徑(logs目錄)和日誌文件(mongo.log文件)
創建配置文件mongo.conf,文件內容如下:(注意修改上面兩個路徑)
#數據庫路徑
dbpath=D:\Program Files\MongoDB\Server\3.4\data
#日誌輸出文件路徑
logpath=D:\Program Files\MongoDB\Server\3.4\logs\mongo.log
#錯誤日誌採用追加模式
logappend=true
#啓用日誌文件,默認啓用
journal=true
#這個選項可以過濾掉一些無用的日誌信息,若需要調試使用請設置爲false
quiet=true
#端口號 默認爲27017
port=27017
然後重啓MongoDB服務
瀏覽器中輸入http://127.0.0.1:27017看到如下界面即說明啓動成功
再安裝一個客戶端工具 studio3t,然後連接:
4.4 導入CMS數據庫
1、創建xc_cms數據庫
2、導入 cms數據庫
5 頁面查詢接口定義(以下爲CMS開發部分)
5.1 定義模型
需求分析:
在梳理完用戶需求後就要去定義前後端的接口,接口定義後前端和後端就可以依據接口去開發功能了
本次定義頁面查詢接口,本接口供前端請求查詢頁面列表,支持分頁及自定義條件查詢方式。
具體需求如下:
1、分頁查詢CmsPage 集合下的數據
2、根據站點Id、模板Id、頁面別名查詢頁面信息
3、接口基於Http Get請求,響應Json數據
5.1.2 模型類介紹
我們用springdataMongoDB來操作MongoDB數據庫,在model工程下定義一個CmsPage類來和數據庫的屬性一一對應,用上@Document
一個站點有多個不同模板,同一個模板填不同數據可生成不同頁面
所以,頁面屬於模板屬於站點
5.2定義接口
關於Lombok:
Lombok是一個實用的java工具,使用它可以消除java代碼的臃腫,需要使用時添加Lombok依賴,然後在idea添加lombok插件
Lombok提供一系列的註解,使用這些註解可以不用定義getter/setter、equals、構造方法等,它會在編譯時在字節碼文件自動生成這些通用的方法,簡化開發人員的工作。
定義接口的時候,首先要識別出接口請求與響應的數據模型
5.2.1 定義請求及響應類型
首先在這個路徑下,定義請求模型QueryPageRequest,此模型作爲查詢條件類型:
爲後期擴展需求,請求類型統一繼承RequestData類型。
package com.xuecheng.framework.domain.cms.request;
import com.xuecheng.framework.model.request.RequestData;
import lombok.Data;
@Data
public class QueryPageRequest extends RequestData {
//站點id
private String siteId;
//頁面ID
private String pageId;
//頁面名稱
private String pageName;
//別名
private String pageAliase;
//模版id
private String templateId;
}
2、響應結果類型,分頁查詢統一使用QueryResponseResult(已提供),因爲它裏面已經寫好了一些屬性,作爲json輸出時方便查看信息
5.2.2 定義接口
在Api接口工程專門定義接口,在Api工程單獨定義接口的原因如下:
1、接口集中管理
2、Api工程的接口將作爲各微服務遠程調用使用。
頁面查詢接口定義如下:
public interface CmsPageControllerApi {
public QueryResponseResult findList(int page, int size, QueryPageRequest queryPageRequest) ;
}
接口編寫後會在CMS服務工程編寫Controller類實現此接口
6 頁面查詢服務端開發(接口實現)
6.1 創建CMS服務工程
6.1.1 創建CMS工程結構
創建maven工程, CMS工程的名稱爲 xc-service-manage-cms,父工程爲xc-framework-parent。
創建好後在pom.xml導入依賴:(主要導<dependencies>下面的)
<?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>
導完後右鍵打開刷新一下maven
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類目錄
這裏體現了每個微服務工程都是一個小的系統
然後寫配置文件。springboot的配置文件叫做application.yml:
server:
port: 31001
spring:
application:
name: xc-service-manage-cms
data:
mongodb:
uri: mongodb://localhost:27017(我沒有配置密碼所以沒有root)
database: xc_cms
再拷貝一個日誌配置文件
(springboot工程中這兩個文件是標配)
接着寫SpringBoot 啓動類
Spring Boot應用需要創建一個應用啓動類,啓動過程中會掃描Bean並注入spring 容器
注意創建的位置:
@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);
}
}
爲了能夠掃描到model和api工程下的cms包(因爲該工程依賴了其他兩個工程,有些包裏面的東西要用到),所以需要加 掃描實體類 和 掃描接口 的註解
然後爲了日後方便閱讀,讓人一看就知道掃描了哪些包,可以再加上一行掃描本項目的註解,讓別人一目瞭然。不加也沒事
6.1.2 測試Controller
寫完測試類後run啓動類,然後看端口,根據url得出結果:
對於一些不是自己寫的,封裝好的類的建議:在公司開發項目時,先熟悉一下它封裝好的類,一步步點進去看它的屬性,方法什麼的,不然連參數都都不知道傳什麼進去
由測試類引出的問題:
爲什麼要將接口單獨定義,並且單獨出來一個API工程呢?
答:因爲目前我們的Controller是用SpringMVC寫的,哪天我們要換了,只需要換技術即可,不需要換接口的代碼。
6.2 Dao
6.2.1 分頁查詢測試
6.2.1.1 定義Dao接口
使用Spring Data Mongodb完成Mongodb數據庫的查詢,Spring Data Mongodb提供一套快捷操作mongodb的方法。
public interface CmsPageRepository extends MongoRepository<CmsPage, String> {
}
MongoRepository是springMongoDB的。接口裏什麼都可以不寫,直接繼承springMongoDB給我們的類就可以用springMongoDB的方法了
6.2.1.2編寫測試類
test下的包路徑與main下的包路徑保持一致。
我這裏準備測試MongoRepository裏的findAll方法:
@SpringBootTest
@RunWith(SpringRunner.class)
public class CmsPageRepositoryTest {
@Autowired
CmsPageRepository cmsPageRepository;
@Test
public void testFindAll(){
List<CmsPage> all = cmsPageRepository.findAll();
System.out.println(all);
}
}
結果:
原理:
測試類使用@SpringBootTest和@RunWith(SpringRunner.class)註解。
運行了測試類裏的測試方法之後,它會從main下找springBoot啓動類(啓動類會進行掃描加載bean),加載spring容器。
拿到容器後用@Autowired拿Dao接口(通過掃描springDataMongoDB接口,它會生成接口的代理對象,然後我們可以通過@Autowired將代理對象注入到測試類當中,注入完後就可以調用這個對象所在的spring類給我們的方法了)
測試其他方法:
//修改
@Test
public void testUpdate() {
Optional<CmsPage> optional = cmsPageRepository.findById("5d7c55a65167790f2cec2ab9");
if(optional.isPresent()){ // 注意和if(null != )差不多,只是標準化了一下
CmsPage cmsPage = optional.get();
cmsPage.setPageName("測試頁面01");
cmsPageRepository.save(cmsPage);
}
}
關於Optional:
Optional是jdk1.8引入的類型,Optional是一個容器對象,它包括了我們需要的對象,使用isPresent方法判斷所包含對象是否爲空,isPresent方法返回false則表示Optional包含對象爲空,否則可以使用get()取出對象進行操作。
Optional的優點是:
1、提醒你非空判斷。
2、將對象非空檢測標準化。
6.2.2 自定義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);
}
自定義步驟:
首先先在Dao接口那裏寫好自己想要的方法(根據上面的規則來寫):
然後再在測試類裏實現:
6.3 Service
若無特殊要求,方法名和Controller方法名保持一致即可:
這樣做有什麼好處?
這樣做了之後方便在Controller裏調用service進行return:
service:
@Service
public class PageService {
@Autowired
private CmsPageRepository cmsPageRepository;
public QueryResponseResult findList(int page, int size, QueryPageRequest queryPageRequest) {
if (page <= 0) {
page = 1;
}
page = page - 1; //爲了適應mongodb的接口將頁碼減1
if (size <= 0) {
size = 10;
}
//分頁對象
Pageable pageable = PageRequest.of(page, size);
//分頁查詢
Page<CmsPage> all = cmsPageRepository.findAll(pageable);
QueryResult<CmsPage> cmsPageQueryResult = new QueryResult<>();
cmsPageQueryResult.setList(all.getContent());
cmsPageQueryResult.setTotal(all.getTotalElements());
//返回結果
return new QueryResponseResult(CommonCode.SUCCESS, cmsPageQueryResult);
}
}
controller:
@RestController
@RequestMapping("/cms/page")
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);
}
}
結果:
6.4 接口開發規範
6.4.1 Api請求及響應規範
爲了嚴格按照接口進行開發,提高效率,對請求及響應格式進行規範化:
1、get 請求時,採用key/value格式請求,SpringMVC可採用基本類型的變量接收,也可以採用對象接收。
2、Post請求時,可以提交form表單數據(application/x-www-form-urlencoded)和Json數據(Content-Type=application/json),文件等多部件類型(multipart/form-data)三種數據格式,SpringMVC接收Json數據,使用@RequestBody註解解析請求的json數據。
4、響應結果統一信息爲:是否成功、操作代碼、提示信息及自定義數據。
5、響應結果統一格式爲json。
6.4.2 Api定義約束
Api定義使用SpringMVC來完成,由於此接口後期將作爲微服務遠程調用使用,在定義接口時有如下限制:
1、@PathVariable 統一指定參數名稱,如:@PathVariable(“id”)
2、@RequestParam統一指定參數名稱,如:@RequestParam(“id”)
7 頁面查詢接口測試
上邊的代碼是基於服務端編寫接口,如果前端人員等待服務端人員將接口開發完畢再去開發前端內容這樣做效率是非常低下的,所以當接口定義完成,可以使用工具生成接口文檔,前端人員查看接口文檔即可進行前端開發,這樣前端和服務人員並行開發,大大提高了生產效率。
下面介紹兩種接口開發工具,Swagger和Postman。
7.1 Swagger
它是一個定義接口文檔的框架,可以集成到springboot中,用註解操作即可
具體原理:
寫了@EnableSwagger2,它就會去掃描 com.xuecheng 下邊的所有標記了@RestController註解的類,掃描這個類裏面的每一個方法,掃描完之後它就會自動生成一個接口文檔
生成的文檔中若要顯示屬性等對應中文意思就要加上相應註解
對應的swagger註解有:
@Api:修飾整個類,描述Controller的作用
@ApiOperation:描述一個類的一個方法,或者說一個接口
@ApiParam:單個參數描述
@ApiModel:用對象來接收參數
@ApiModelProperty:用對象接收參數時,描述對象的一個字段
@ApiResponse:HTTP響應其中1個描述
@ApiResponses:HTTP響應整體描述
@ApiIgnore:使用該註解忽略這個API
@ApiError :發生錯誤返回的信息
@ApiImplicitParam:一個請求參數
@ApiImplicitParams:多個請求參數
@ApiImplicitParam屬性:
使用過程:
現在我的項目裏只有一個@RestController:
修改接口工程中頁面查詢接口,添加Swagger註解:
啓動cms服務工程,查看接口文檔,請求:http://localhost:31001/swagger-ui.html(固定格式)
使用註解前:
使用註解後:
還可以在swagger中測試服務接口(直接在裏面寫上數據跑起來就行)
7.2 Postman
Postman是一款功能強大的http接口測試工具,使用postman可以完成http各種請求的功能測試,需要安裝客戶端