1:===== 开发步骤
项目是基于前后端分离的架构进行开发,前后端分离架构总体上包括前端和服务端,通常是多人协作并行开发,开
发步骤如下:
1、需求分析
梳理用户的需求,分析业务流程
2、接口定义
根据需求分析定义接口
3、服务端和前端并行开发
依据接口进行服务端接口开发。
前端开发用户操作界面,并请求服务端接口完成业务处理。
4、前后端集成测试
最终前端调用服务端接口完成业务。
2:=======CMS需求分析
1、CMS是什么 ?
CMS (Content Management System)即内容管理系统,不同的项目对CMS的定位不同,比如:一个在线教育网
站,有些公司认为CMS系统是对所有的课程资源进行管理,而在早期网站刚开始盛行时很多公司的业务是网站制
作,当时对CMS的定位是创建网站,即对网站的页面、图片等静态资源进行管理。
2、CMS有哪些类型?
上边也谈到每个公司对每个项目的CMS定位不同,CMS基本上分为:针对后台数据内容的管理、针对前端页面的
管理、针对样式风格的管理等 。比如:一个给企业做网站的公司,其CMS系统主要是网站页面管理及样式风格的
管理。
3:======静态门户工程搭建
3.1:导入门户工程
1、安装WebStorm
2、安装Nginx
下载nginx:http://nginx.org/en/download.html
本教程下载nginx-1.14.0.zip(http://nginx.org/download/nginx-1.14.0.zip)
解压nginx-1.14.0.zip到自己的计算机,双击nginx.exe即可运行。
访问 :http://localhost
3:导入门户工程
链接:https://pan.baidu.com/s/1i_7NWzVZz4DHpIvTI35c4g
提取码:aesa
3.1 使用webstrom 打开 xc-ui-pc-static-portal
3.2: 配置虚拟主机
修改nginx安装目录下的conf文件夹下的nginx.conf
将图1修改为图2
3.2.3;在nginx安装目录 进入cmd 窗口
输入 nginx.exe -s reload
3.2.4:、配置hosts文件
修改C:\Windows\System32\drivers\etc\hosts文件
127.0.0.1 www.xuecheng.com
3.3 SSI服务端包含技术
本节分析首页的管理方案。
1、页面内容多如何管理?
将页面拆分成一个一个的小页面,通过cms去管理这些小页面,当要更改部分页面内容时只需要更改具体某个小页
面即可。
2、页面拆出来怎么样通过web服务浏览呢?
使用web服务(例如nginx)的SSI技术,将多个子页面合并渲染输出。
3、SSI是什么?
ssi包含类似于jsp页面中的incluce指令,ssi是在web服务端将include指定 的页面包含在网页中,渲染html网页响
应给客户端 。nginx、apache等多数web容器都支持SSI指令。
ssi指令如下:
4、将首页拆分成
index.html:首页主体内容
include/header.html:头部区域
include/index_banner.html:轮播图
include/index_category.html:左侧列表导航
include/footer.html:页尾
5、在nginx虚拟主机中开通SSI
server{
listen 80;
server_name www.xuecheng.com;
ssi on;
ssi_silent_errors on;
......
ssi的配置参数如下: ssi on: 开启ssi支持 ssi_silent_errors on:默认为offff,设置为on则在处理SSI文件出错时不
输出错误信息 ssi_types:默认为 ssi_types text/html,如果需要支持shtml(服务器执行脚本,类似于jsp)则需
要设置为ssi_types text/shtml
6、测试
去掉某个#include查看页面效果。
3.4:CMS页面管理需求
1、这些页面的管理流程是什么?
1)创建站点:
一个网站有很多子站点,比如:学成在线有主门户、学习中心、问答系统等子站点。具体的哪个页面是归属于具体
的站点,所以要管理页面,先要管理页面所属的站点。
2)创建模板:
页面如何创建呢?比如电商网站的商品详情页面,每个页面的内容布局、板式是相同的,不同的只是内容,这个页
面的布局、板式就是页面模板,模板+数据就组成一个完整的页面,最终要创建一个页面文件需要先定义此页面的
模板,最终拿到页面的数据再结合模板就拼装成一个完整的页面。
3)创建页面:
创建页面是指填写页面的基本信息,如:页面的名称、页面的url地址等。
4)页面预览:
页面预览是页面发布前的一项工作,页面预览使用静态化技术根据页面模板和数据生成页面内容,并通过浏览器预
览页面。页面发布前进行页面预览的目是为了保证页面发布后的正确性。
5)页面发布:
使用计算机技术将页面发送到页面所在站点的服务器,页面发布成功就可以通过浏览器来访问了。
2、本项目要实现什么样的功能?
1)页面管理
管理员在后台添加、修改、删除页面信息
2)页面预览
管理员通过页面预览功能预览页面发布后的效果。
3)页面发布
管理员通过页面发布功能将页面发布到远程门户服务器。
页面发布成功,用户即可在浏览器浏览到最新发布的页面,整个页面添加、发布的过程由于软件自动执行,无需人
工登录服务器操作。
4 =============CMS服务端工程搭建
4.1:开发工具配置
1、创建工程代码目录 XcEduCode(本教程创建XcEduCode01目录),并且IDEA打开。
2、配置maven环境
setting.xml文件中配置maven仓库,maven仓库的目录位置不要去使用中文。
3、配置编码
4:配置JDK1.8
5: 、自动导入包 快捷方式:
idea可以自动优化导入包,但是有多个同名的类调用不同的包,必须自己手动Alt+Enter设置
设置idea导入包
6:代码模板
7:提示忽略大小写
默认IDEA的提示是区分大
8:配置虚拟机内存
修改idea64.exe.vmoptions(64位电脑选择此文件)
-Xms1024m -Xmx4096m -XX:MaxPermSize=1024m -XX:ReservedCodeCacheSize=1024m
4.2 导入基础工程
4.2.1 工程结构
CMS及其它服务端工程基于maven进行构建,首先需要创建如下基础工程:
parent工程:父工程,提供依赖管理。
common工程:通用工程,提供各层封装
model工程:模型工程,提供统一的模型类管理
utils工程:工具类工程,提供本项目所使用的工具类
Api工程:接口工程,统一管理本项目的服务接口。
工程结果如下:
4.2.2导入父工程
链接:https://pan.baidu.com/s/1EoIxNM9y671dSBgKJnX9lQ
提取码:r2i0
1: 将资料中的parent工程拷贝到代码目录
2、点击Import Model,选择parent工程目录
问题:添加module 到工程中 发现pop.xml 报错 或者有的依赖库 加载失败
1: 在本地maven安装目录下 conf中的setting 中加入
=========================
========================
2:在项目的pop.xml中添加
==============
==============
4.3.1 安装MongoDB
菜鸟教程:https://www.runoob.com/mongodb/mongodb-connections.html
CMS采用MongoDB数据库存储CMS页面信息,CMS选用Mongodb的原因如下:
1、Mongodb是非关系型数据库,存储Json格式数据 ,数据格式灵活。
2、相比课程管理等核心数据CMS数据不重要,且没有事务管理要求。
MongoDB 中文网:https://www.mongodb.org.cn/
下载:https://www.mongodb.com/download-center/community
3:安装成成功之后
在浏览器中输入:http://127.0.0.1:27017/
4:安装MongoDB连接客户端
链接:https://pan.baidu.com/s/1PtrMANH7Gl6F4WkodkkJ6A
提取码:zi5k
官网:https://studio3t.com/
下载完成:测试连接
4.1:创建数据库
4.1.1点击 Database 添加数据
4.2:导入数据库文件 json文件
4
5:页面查询接口定义
5.1 定义模型
5.1.1 需求分析
1、分页查询CmsPage 集合下的数据
2、根据站点Id、模板Id、页面别名查询页面信息
3、接口基于Http Get请求,响应Json数据
5.1.2 模型类介绍
接口的定义离不开数据模型,根据前边对需求的分析,整个页面管理模块的数据模型如下:
CmsSite:站点模型
CmsTemplate:页面模板
CmsPage:页面信息
页面信息如下:
======================================
@Data
@ToString
@Document(collection = "cms_page")
public class CmsPage {
/**
* 页面名称、别名、访问地址、类型(静态/动态)、页面模版、状态
*/
//站点ID
�private String siteId;
//页面ID
@Id
private 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;
//模版id
private String templateId;
//参数列表,暂不用
private List
//模版文件Id
// private String templateFileId;
//静态文件Id
private String htmlFileId;
//数据Url
private String dataUrl;
}
======================================
属性说明:
1、定义一个页面需要指定页面所属站点
一个站点包括多个页面,比如:学成在线的门户站点(网站)包括了多个页面。
2、定义一个页面需要指定页面使用的模板
多个页面可以使用相同的模板,比如:商品信息模板,每个商品就是一个页面,所有商品使用同一个商品信息模板
注解说明:
@Data、@ToString、@Document注解表示什么意思?
@Data、@ToString:是Lombok提供的注解,下边会介绍。
@Document:是Spring Data mongodb提供的注解,最终CMS的开发会使用Mongodb数据库。
5.2.3 Lombok
上边的Data注解表示什么意思呢?Data注解,ToString注解都是Lombok提供的注解。
Lombok是一个实用的java工具,使用它可以消除java代码的臃肿,Lombok提供一系列的注解,使用这些注解可
以不用定义getter/setter、equals、构造方法等,它会在编译时在字节码文件自动生成这些通用的方法,简化开发
人员的工作。
项目官方地址:https://www.projectlombok.org/
比如上节创建的UserTest模型,@Data注解可以自动生成getter/setter方法,@ToString生成tostring方法。
使用方法:
1、在项目中添加Lombok的依赖
作用:项目在编译时根据Lombok注解生成通用方法。
========
========
5.2定义接口
5.2.1 定义请求及响应类型
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
5.2.2 定义接口
在Api接口工程专门定义接口,在Api工程单独定义接口的原因如下:
1、接口集中管理
2、Api工程的接口将作为各微服务远程调用使用。
页面查询接口定义如下:
============================
public interface CmsPageControllerApi {
public QueryResponseResult findList(int page, int size, QueryPageRequest queryPageRequest) ;
}
============================
6 页面查询服务端开发
6.1 创建CMS服务工程
6.1.1 创建CMS工程结构
创建maven工程, CMS工程的名称为 xc-service-manage-cms,父工程为xc-framework-parent。
pom.xml如下:
=========================
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">
=========================
由于cms工程要连接mongodb所以需要在在cms服务端工程添加如下依赖:
项目使用spring data mongodb操作mongodb数据库
================
================
2、创建基本的包结构:
com.xuecheng.manage_cms.confifig:配置类目录,数据库配置、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‐cms
data:
mongodb:
uri: mongodb://root:123@localhost:27017
database: xc_cms
==================
logback-spring.xml,
==================
==================
4、SpringBoot 启动类
Spring Boot应用需要创建一个应用启动类,启动过程中会扫描Bean并注入spring 容器
注意:此类创建在本工程com.xuecheng.manage_cms包下
==================
@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);
}
}
==================
6.1.2 测试Controller
使用springMVC完成接口实现开发,这里暂时使用测试数据,稍后会让controller调用service来查询数据。
=====================
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 {
@Override
@GetMapping("/list/{page}/{size}")
public QueryResponseResult findList(@PathVariable("page") int page,@PathVariable("size") int
size,QueryPageRequest queryPageRequest) {
//暂时采用测试数据,测试接口是否可以正常运行
QueryResult queryResult = new QueryResult();
queryResult.setTotal(2);
//静态数据列表
List list = new ArrayList();
CmsPage cmsPage = new CmsPage();
cmsPage.setPageName("测试页面");
list.add(cmsPage)
queryResult.setList(list);
QueryResponseResult queryResponseResult = new
QueryResponseResult(CommonCode.SUCCESS,queryResult);
return queryResponseResult;
}
}
=====================
运行 ManageCmsApplication
在浏览器输入:http://localhost:31001/list/1/10
访问成功:
6.2 Dao
6.2.1 分页查询测试
6.2.1.1 定义Dao接口
本项目使用Spring Data Mongodb完成Mongodb数据库的查询,Spring Data Mongodb提供一套快捷操作
mongodb的方法。
创建Dao,继承MongoRepository,并指定实体类型和主键类型。
public interface CmsPageRepository extends MongoRepository
}
6.2.1.2编写测试类
*(注意)test下的包路径与main下的包路径保持一致。
测试程序使用@SpringBootTest和@RunWith(SpringRunner.class)注解,启动测试类会从main下找springBoot启
动类,加载spring容器。
测试代码如下:
===================== 查询
@SpringBootTest
@RunWith(SpringRunner.class)
public class CmsPageRepositoryTest {
@Autowired
CmsPageRepositorycmsPageRepository;
@Test
public void testFindPage() {
int page =0;//从0开始
int size =5;//每页记录数
Pageable pageable = PageRequest.of(page,size);
Page all =cmsPageRepository.findAll(pageable);
for(CmsPage c:all){
System.out.println("pppppppppp"+c );
}
}
}
====================修改
//修改
@Test
public void testUpdate() {
Optional optional =cmsPageRepository.findById("5a754adf6abb500ad05688d9");
if(optional.isPresent()){
CmsPage cmsPage = optional.get();
cmsPage.setPageAliase("首页1");
CmsPage save =cmsPageRepository.save(cmsPage);
}
}
===========================
关于Optional:
Optional是jdk1.8引入的类型,Optional是一个容器对象,它包括了我们需要的对象,使用isPresent方法判断所包
含对象是否为空,isPresent方法返回false则表示Optional包含对象为空,否则可以使用get()取出对象进行操作。
Optional的优点是:
1、提醒你非空判断。
2、将对象非空检测标准化。
6.2.3.4 自定义Dao方法
同Spring Data JPA一样Spring Data mongodb也提供自定义方法的规则,如下:
按照fifindByXXX,fifindByXXXAndYYY、countByXXXAndYYY等规则定义方法,实现查询操作。
public interface CmsPageRepository extends MongoRepository
//根据页面名称查询
CmsPage findByPageName(String pageName);
//根据页面名称和类型查询
CmsPage findByPageNameAndPageType(String pageName,String pageType);
//根据站点和页面类型查询记录数
int countBySiteIdAndPageType(String siteId,String pageType);
//根据站点和页面类型分页查询
Page
}
6.3 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的接口将页码减1
if (size <= 0) {
size = 20;
}
//分页对象
Pageable pageable = new PageRequest(page, size);
//分页查询
Page
QueryResult
cmsPageQueryResult.setList(all.getContent());
cmsPageQueryResult.setTotal(all.getTotalElements());
//返回结果
return new QueryResponseResult(CommonCode.SUCCESS,cmsPageQueryResult);
}
}
================
6.4 Controller
==================
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/list/1/10
访问成功:
6.6 接口开发规范
6.6.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.6.2 Api定义约束
Api定义使用SpringMVC来完成,由于此接口后期将作为微服务远程调用使用,在定义接口时有如下限制:
1、@PathVariable 统一指定参数名称,如:@PathVariable("id")
2、@RequestParam统一指定参数名称,如:@RequestParam("id")
7 页面查询接口测试
上边的代码是基于服务端编写接口,如果前端人员等待服务端人员将接口开发完毕再去开发前端内容这样做效率是
非常低下的,所以当接口定义完成,可以使用工具生成接口文档,前端人员查看接口文档即可进行前端开发,这样
前端和服务人员并行开发,大大提高了生产效率。
本章节介绍两种接口开发工具,Swagger和Postman。
7.1 Swagger
7.1.1 Swagger介绍
OpenAPI规范(OpenAPI Specifification 简称OAS)是Linux基金会的一个项目,试图通过定义一种用来描述API格
式或API定义的语言,来规范RESTful服务开发过程,目前版本是V3.0,并且已经发布并开源在github上。
(https://github.com/OAI/OpenAPI-Specifification)
Swagger是全球最大的OpenAPI规范(OAS)API开发工具框架,支持从设计和文档到测试和部署的整个API生命周
期的开发。 (https://swagger.io/)
Spring Boot 可以集成Swagger,生成Swagger接口,Spring Boot是Java领域的神器,它是Spring项目下快速构建
项目的框架。
7.1.2 Swagger常用注解
在Java类中添加Swagger的注解即可生成Swagger接口,常用Swagger注解如下:
@Api:修饰整个类,描述Controller的作用 @ApiOperation:描述一个类的一个方法,或者说一个接口
@ApiParam:单个参数描述 @ApiModel:用对象来接收参数 @ApiModelProperty:用对象接收参数时,描述对
象的一个字段 @ApiResponse:HTTP响应其中1个描述 @ApiResponses:HTTP响应整体描述 @ApiIgnore:使用
该注解忽略这个API @ApiError :发生错误返回的信息 @ApiImplicitParam:一个请求参数
@ApiImplicitParams:多个请求参数
@ApiImplicitParam属性:
7.1.3 Swagger接口定义
修改接口工程中页面查询接口,添加Swagger注解。
=========================
@Api(value="cms页面管理接口",description = "cms页面管理接口,提供页面的增、删、改、查")
public interface CmsPageControllerApi {
@ApiOperation("分页查询页面列表")
@ApiImplicitParams({
@ApiImplicitParam(name="page",value = "页
码",required=true,paramType="path",dataType="int"),
@ApiImplicitParam(name="size",value = "每页记录
数",required=true,paramType="path",dataType="int")
})
public QueryResponseResult findList(int page, int size, QueryPageRequest queryPageRequest) ;
}
在QueryPageRequest类中使用注解 ApiModelProperty 对属性注释:
@Data
public class QueryPageRequest extends RequestData {
//站点id
@ApiModelProperty("站点id")
private String siteId;
//页面ID
@ApiModelProperty("页面ID")
private String pageId;
//页面名称
@ApiModelProperty("页面名称")
private String pageName;
//页面别名
@ApiModelProperty("页面别名")
private String pageAliase;
//模版id
@ApiModelProperty("模版id")
private String templateId;
}
=========================
7.1.4 Swagger接口测试
Swagger接口生成工作原理:
1、系统启动,扫描到api工程中的Swagger2Confifiguration类
2、在此类中指定了包路径com.xuecheng,找到在此包下及子包下标记有@RestController注解的controller类
3、根据controller类中的Swagger注解生成接口文档。
启动cms服务工程,查看接口文档,请求:http://localhost:31001/swagger-ui.html
7.5 Postman
Postman是一款功能强大的http接口测试工具,使用postman可以完成http各种请求的功能测试。
官方地址:https://www.getpostman.com/
1、安装Postman
本教程使用,双击打开 Postman-win64-6.0.10-Setup.exe
新建一个Postman窗口
2、使用postman测试http接口
3、请求参数设置
1) get请求参数设置
2)post请求参数设置
form-data:将表单的数据转为键值对,并且可以包括文件
x-www-form-urlencoded: content-type为application/x-www-from-urlencoded,将表单的数据转为键值对
raw:请求text、json、xml、html,比如如果请求json数据则使用此格式
binary:content-type为application/octet-stream,可用于上传文件。