学成在线采用当前流行的前后端分离架构开发,由用户层、UI层、微服务层、数据层等部分组成,为PC、App、 H5等客户端用户提供服务。下图是系统的技术架构图:
各模块说明如下
项目是基于前后端分离的架构进行开发,前后端分离架构总体上包括前端和服务端,通常是多人协作并行开发,开 发步骤如下:
1、需求分析 梳理用户的需求,分析业务流程
2、接口定义 根据需求分析定义接口
3、服务端和前端并行开发 依据接口进行服务端接口开发。 前端开发用户操作界面,并请求服务端接口完成业务处理。
4、前后端集成测试 最终前端调用服务端接口完成业务。
1、CMS是什么 ?
CMS (Content Management System)即内容管理系统,不同的项目对CMS的定位不同,比如:一个在线教育网 站,有些公司认为CMS系统是对所有的课程资源进行管理,而在早期网站刚开始盛行时很多公司的业务是网站制 作,当时对CMS的定位是创建网站,即对网站的页面、图片等静态资源进行管理。
2、CMS有哪些类型?
上边也谈到每个公司对每个项目的CMS定位不同,CMS基本上分为:针对后台数据内容的管理、针对前端页面的 管理、针对样式风格的管理等 。比如:一个给企业做网站的公司,其CMS系统主要是网站页面管理及样式风格的 管理。
3、本项目CMS的定位是什么?
本项目作为一个大型的在线教育平台,对CMS系统的定位是对各各网站(子站点)页面的管理,主要管理由于运营 需要而经常变动的页面,从而实现根据运营需要快速进行页面开发、上线的需求。
1、安装WebStorm 参考“WebStorm安装手册.md”安装WebStorm-2018.2.3.exe
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
server{
listen 80;
server_name www.xuecheng.com;
ssi on;
ssi_silent_errors on;
location / {
alias F:/teach/xcEdu/xcEduUI/xc‐ui‐pc‐static‐portal/;
index index.html;
}
}
F:/teach/xcEdu/xcEduUI/xc-ui-pc-static-portal/
本目录即为门户的主目录。
5、配置hosts文件
本教程的开发环境使用Windows ,修改C:\Windows\System32\drivers\etc\hosts文件
127.0.0.1 www.xuecheng.com
进入浏览器,输入http://www.xuecheng.com
1、这些页面的管理流程是什么?
1)创建站点: 一个网站有很多子站点,比如:学成在线有主门户、学习中心、问答系统等子站点。具体的哪个页面是归属于具体 的站点,所以要管理页面,先要管理页面所属的站点。
2)创建模板: 页面如何创建呢?比如电商网站的商品详情页面,每个页面的内容布局、板式是相同的,不同的只是内容,这个页 面的布局、板式就是页面模板,模板+数据就组成一个完整的页面,最终要创建一个页面文件需要先定义此页面的 模板,最终拿到页面的数据再结合模板就拼装成一个完整的页面。
3)创建页面: 创建页面是指填写页面的基本信息,如:页面的名称、页面的url地址等。
4)页面预览: 页面预览是页面发布前的一项工作,页面预览使用静态化技术根据页面模板和数据生成页面内容,并通过浏览器预 览页面。页面发布前进行页面预览的目是为了保证页面发布后的正确性。
5)页面发布: 使用计算机技术将页面发送到页面所在站点的服务器,页面发布成功就可以通过浏览器来访问了。
2、本项目要实现什么样的功能?
1)页面管理 管理员在后台添加、修改、删除页面信息
2)页面预览 管理员通过页面预览功能预览页面发布后的效果。
3)页面发布 管理员通过页面发布功能将页面发布到远程门户服务器。 页面发布成功,用户即可在浏览器浏览到最新发布的页面,整个页面添加、发布的过程由于软件自动执行,无需人 工登录服务器操作。
3)创建页面: 创建页面是指填写页面的基本信息,如:页面的名称、页面的url地址等。
4)页面预览: 页面预览是页面发布前的一项工作,页面预览使用静态化技术根据页面模板和数据生成页面内容,并通过浏览器预 览页面。页面发布前进行页面预览的目是为了保证页面发布后的正确性。
5)页面发布: 使用计算机技术将页面发送到页面所在站点的服务器,页面发布成功就可以通过浏览器来访问了。
2、本项目要实现什么样的功能?
1)页面管理 管理员在后台添加、修改、删除页面信息
2)页面预览 管理员通过页面预览功能预览页面发布后的效果。
3)页面发布 管理员通过页面发布功能将页面发布到远程门户服务器。 页面发布成功,用户即可在浏览器浏览到最新发布的页面,整个页面添加、发布的过程由于软件自动执行,无需人 工登录服务器操作。
服务端工程使用IntellijIDEA开发。
1、创建工程代码目录 XcEduCode(本教程创建XcEduCode01目录),并且IDEA打开。
2、配置maven环境 拷贝老师提供的maven仓库,setting.xml文件中配置maven仓库,maven仓库的目录位置不要去使用中文。
9、配置虚拟机内存 修改idea64.exe.vmoptions(64位电脑选择此文件)
一个例子,电脑内存8G,设置如下:
-Xms1024m -Xmx4096m -XX:MaxPermSize=1024m -XX:ReservedCodeCacheSize=1024m
CMS及其它服务端工程基于maven进行构建,首先需要创建如下基础工程:
parent工程:父工程,提供依赖管理。
common工程:通用工程,提供各层封装
model工程:模型工程,提供统一的模型类管理
utils工程:工具类工程,提供本项目所使用的工具类
Api工程:接口工程,统一管理本项目的服务接口。
1、将课程资料中的parent工程拷贝到代码目录
2、点击Import Model,选择parent工程目录
CMS采用MongoDB数据库存储CMS页面信息,CMS选用Mongodb的原因如下:
1、Mongodb是非关系型数据库,存储Json格式数据 ,数据格式灵活。
2、相比课程管理等核心数据CMS数据不重要,且没有事务管理要求。
参考“mongodb安装.md”安装Mongodb Server及 Studio 3T客户端软件。
参考“mongodb安装及入门”文档进行学习。
在梳理完用户需求后就要去定义前后端的接口,接口定义后前端和后端就可以依据接口去开发功能了。 本次定义页面查询接口,本接口供前端请求查询页面列表,支持分页及自定义条件查询方式。 具体需求如下:
1、分页查询CmsPage 集合下的数据
2、根据站点Id、模板Id、页面别名查询页面信息
3、接口基于Http Get请求,响应Json数据
@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<CmsPageParam> pageParams;
//模版文件Id
// private String templateFileId;
//静态文件Id
private String htmlFileId;
//数据Url
private String dataUrl;
}
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
在Api接口工程专门定义接口,在Api工程单独定义接口的原因如下:
1、接口集中管理
2、Api工程的接口将作为各微服务远程调用使用。 页面查询接口定义如下:
public interface CmsPageControllerApi {
public QueryResponseResult findList(int page, int size, QueryPageRequest queryPageRequest) ;
}
此接口编写后会在CMS服务工程编写Controller类实现此接口。
创建maven工程, CMS工程的名称为 xc-service-manage-cms,父工程为xc-framework-parent。 pom.xml如下:
<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‐parentartifactId>
<groupId>com.xuechenggroupId>
<version>1.0‐SNAPSHOTversion>
<relativePath>../xc‐framework‐parent/pom.xmlrelativePath>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>xc‐service‐manage‐cmsartifactId>
<dependencies>
<dependency>
<groupId>com.xuechenggroupId>
<artifactId>xc‐service‐apiartifactId>
<version>1.0‐SNAPSHOTversion>
dependency>
<dependency>
<groupId>com.xuechenggroupId>
<artifactId>xc‐framework‐modelartifactId>
<version>1.0‐SNAPSHOTversion>
dependency>
<dependency>
<groupId>com.xuechenggroupId>
<artifactId>xc‐framework‐utilsartifactId>
<version>1.0‐SNAPSHOTversion>
dependency>
<dependency>
<groupId>com.xuechenggroupId>
<artifactId>xc‐framework‐commonartifactId>
<version>1.0‐SNAPSHOTversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring‐boot‐starter‐webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring‐boot‐starter‐freemarkerartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring‐boot‐starter‐data‐mongodbartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring‐boot‐starter‐amqpartifactId>
dependency>
<dependency>
<groupId>com.squareup.okhttp3groupId>
<artifactId>okhttpartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring‐boot‐starter‐testartifactId>
dependency>
dependencies>
project>
由于cms工程要连接mongodb所以需要在在cms服务端工程添加如下依赖:
项目使用spring data mongodb操作mongodb数据库
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring‐boot‐starter‐data‐mongodbartifactId>
dependency>
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
另外从课程资料下“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);
}
}
使用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;
}
}
使用浏览器测试
输入:http://localhost:31001/cms/page/list/1/10 查询第1页,每页显示10条记录。
为了严格按照接口进行开发,提高效率,对请求及响应格式进行规范化。
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。
Api定义使用SpringMVC来完成,由于此接口后期将作为微服务远程调用使用,在定义接口时有如下限制:
1、@PathVariable 统一指定参数名称,如:@PathVariable(“id”)
2、@RequestParam统一指定参数名称,如: @RequestParam(“id”)
上边的代码是基于服务端编写接口,如果前端人员等待服务端人员将接口开发完毕再去开发前端内容这样做效率是 非常低下的,所以当接口定义完成,可以使用工具生成接口文档, 前端人员查看接口文档即可进行前端开发,这样 前端和服务人员并行开发,大大提高了生产效率。 本章节介绍两种接口开发工具,Swagger和Postman。
OpenAPI规范(OpenAPI Specification 简称OAS)是Linux基金会的一个项目,试图通过定义一种用来描述API格 式或API定义的语言,来规范RESTful服务开发过程,目前版本是V3.0,并且已经发布并开源在github上。
(https://github.com/OAI/OpenAPI-Specification)
Swagger是全球最大的OpenAPI规范(OAS)API开发工具框架,支持从设计和文档到测试和部署的整个API生命周 期的开发。 (https://swagger.io/)
Spring Boot 可以集成Swagger,生成Swagger接口,Spring Boot是Java领域的神器,它是Spring项目下快速构建 项目的框架。
在Java类中添加Swagger的注解即可生成Swagger接口,常用Swagger注解如下:
@Api:修饰整个类,描述Controller的作用
@ApiOperation:描述一个类的一个方法,或者说一个接口
@ApiParam:单个参数描述
@ApiModel:用对象来接收参数
@ApiModelProperty:用对象接收参数时,描述对 象的一个字段
@ApiResponse:HTTP响应其中1个描述
@ApiResponses:HTTP响应整体描述
@ApiIgnore:使用 该注解忽略这个API
@ApiError :发生错误返回的信息
@ApiImplicitParam:一个请求参数
@ApiImplicitParams:多个请求参数
@ApiImplicitParam属性:
@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;
}
https://www.getpostman.com/ 安装即用,模拟前端http请求