文章目录
- 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”)