项目的功能构架

1.1 项目背景

受互联网+概念的催化,当今中国在线教育市场的发展可谓是百花齐放、如火如荼。 按照市场领域细分为:学前教育、K12教育、高等教育、留学教育、职业教育、语言教育、兴趣教育以及综合平台,其中,职业教育和语言教育 的市场优势突出。   根据Analysys易观发布的数据显示,预计2019年中国互联网教育市场交易规模将达到3718亿元人民币,未来三年互联网教育市场规模保持高速增长。

eb34786a05a19dd5864174a827e59432_MD5

 

学成在线借鉴了MOOC(大型开放式网络课程,即MOOC(massive open online courses))的设计思想,是一个提供IT职业课程在线学习的平台,它为即将和已经加入IT领域的技术人才提供在线学习服务,用户通过在线学   习、在线练习、在线考试等学习内容,最终掌握所学的IT技能,并能在工作中熟练应用。

1.2 功能模块

当前市场的在线教育模式多种多样,包括:B2C、C2C、B2B2C等业务模式,学成在线采用B2B2C业务模式,即向 企业或个人提供在线教育平台提供教学服务,老师和学生通过平台完成整个教学和学习的过程,市场上类似的平台 有:网易云课堂、腾讯课堂等,学成在线的特点是IT职业课程在线教学。

学成在线包括门户、学习中心、教学管理中、社交系统、系统管理等功能模块。

4336084a08e81a6224402622001f8343_MD5

  1a9b431312d8afe6f02ca1b0d9c69515_MD5

1.3 项目原型

通过项目原型进一步了解项目的功能,包括:门户首页、课程搜索页、在线学习页面、个人中心等 参考“项目原型”。

项目的技术架构

2.1 技术架构

学成在线采用当前流行的前后端分离架构开发,由用户层、UI层、微服务层、数据层等部分组成,为PC、App、

H5等客户端用户提供服务。下图是系统的技术架构图:

e653e37cf9d53c9e26d5a8b9d8a11c1e_MD5

 

业务流程举例:

1、用户可以通过pc、手机等客户端访问系统进行在线学习。

2、 系统应用CDN技术,对一些图片、CSS、视频等资源从CDN调度访问。

3、所有的请求全部经过负载均衡器。

4、对于PC、H5等客户端请求,首先请求UI层,渲染用户界面。

5、客户端UI请求服务层获取进行具体的业务操作。

6、服务层将数据持久化到数据库。

各模块说明如下:

1 用户层

用户层描述了本系统所支持的用户类型包括:pc用户、app用户、h5用户。pc用户通过 浏览器访问系统、app用户通过android、ios手机访问系统,H5用户通过h5页面访问系 统。

2 CDN

CDN全称Content Delivery Network,即内容分发网络,本系统所有静态资源全部通过CDN加速来提高访问速度。系统静态资源包括:html页面、js文件、css文件、image图 片、pdf和ppt及doc教学文档、video视频等。

3 负载均衡

系统的CDN层、UI层、服务层及数据层均设置了负载均衡服务,上图仅在UI层前边标注 了负载均衡。    每一层的负载均衡会根据系统的需求来确定负载均衡器的类型,系统支持4层负载均衡+7层负载均衡结合的方式,4层负载均衡是指在网络传输层进行流程转发, 根据IP和端口进行转发,7层负载均衡完成HTTP协议负载均衡及反向代理的功能,根据 url进行请求转发。

4 UI层

UI层描述了系统向pc用户、app用户、h5用户提供的产品界面。根据系统功能模块特点 确定了UI层包括如下产品界面类型: 1)面向pc用户的门户系统、学习中心系统、教学管理系统、系统管理中心。 2)面向h5用户的门户系统、学习中心系统。 3)面向app 用户的门户系统、学习中心系统未在上图标注,在app项目中有详细说明。

5 微服务层

微服务层将系统服务分类三类:前端服务、后端服务及系统服务。 前端服务:主要为学习用户提供学习服务。 后端服务:主要为管理用户提供教学管理服务。 系统服务:公共服务,为系统的所有微服务提供公共服务功能。     服务网关:提供服务路由、负载均衡、认证授权等服务。

6 数据层

数据层描述了系统的数据存储的内容类型,持久化的业务数据使用MySQL和MongoDB 保存,其中MongoDB中主要保存系统日志信息。   

消息队列:存储系统服务间通信的消息,本身提供消息存取服务,与微服务层的系统服务连接。

索引库:存储课程信息的索引信息,本身提供索引维护及搜索的服务,与微服务层的系统服务连接。

缓存:作为系统的缓存服务,存储课程信息、分类信息、用户信息等,与微服务层的所有服务连接。 

文件存储:提供系统静态资源文件的分布式存储服务,文件存储服务器作为CDN服务器 的数据来源,CDN上的静态资源将最终在文件存储服务器上保存多份。    

流媒体服务: 作为流媒体服务器,存储所有的流媒体文件。

7 外部系统接口

1)微信、QQ、微博登录接口,本系统和微信、QQ、微博系统对接,用户输入微信、 QQ、微博的账号和密码即可登录本系统。 2)微信、QQ、微博分享接口,本系统和微信、QQ、微博系统对接,可直接将本系统的课程资源信息分享到微信、QQ、微博。  3)支付宝、微信、网银支付接口,本系统提供支付宝、微信、网银三种支付接口。

4)短信接口,本系统与第三方平台对接短信发送接口。   

5)邮件接口,本系统需要连接第三方的smpt邮件服务器对外发送电子邮件。   

6)微信公众号,本系统与微信公众号平台接口,用户通过微信公众号访问H5页面。

7)点播、直播,前期视频点播与直播采用第三方服务方式,本系统与第三方点、直播服务对接,对外提供视频点播与直播服

务。

8)OSS存储 ,前期静态资源文件的存储采用第三方服务方式,本系统与第三方提供的OSS存储服务对接,将系统的静态资源文件存储到第三方提供的OSS存储服务器上。

9)CDN,本系统与第三方CDN服务对接,使用CDN加速服务来提高本系统的访问速度。

8 DevOps

DevOps(英文Development和Operations的组合)是一组过程、方法与系统的统称, 用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、 协作与整合。本项目供了许多开发、运营、维护支撑的系统,包括:     Eureka服务治理 中心:提供服务治理服务,包括:服务注册、服务获取等。   

Spring Cloud Config服务配置管理中心:提供服务配置管理服务,包括:配置文件更新、配置文件下发等。

Hystrix Dashboard服务熔断监控:监控熔断的请求响应时间、成功率等 。 Zipkin服务追踪监控:监控服务调用链路健康情况。    

Jenkins持续集成服务:提供系统持续集成服 务。

Git/GitLab代码管理服务:提供git代码管理服务。

ELK日志分析服务:提供elk日志分析服务,包括系统运行日志分析、告警服务。   

Docker容器化部署服务:将本系统所有服务采用容器化部署方式。

Maven项目管理工具:提供管理项目所有的Java包依赖、项目工程打包服务。

2.2 技术栈

下图是项目技术架构的简图,通过简图了解项目所使用的技术栈。

4f357532634d4a62cc459d7345f6380c_MD5

 

重点了解微服务技术栈:

学成在线服务端基于Spring Boot构建,采用Spring Cloud微服务框架。持久层:MySQL、MongoDB、Redis、ElasticSearch

数据访问层:使用Spring Data JPA 、Mybatis、Spring Data Mongodb等

业务层:Spring IOC、Aop事务控制、Spring Task任务调度、Feign、Ribbon、Spring AMQP、Spring Data Redis 等。

控制层:Spring MVC、FastJSON、RestTemplate、Spring Security Oauth2+JWT等微服务治理:Eureka、Zuul、Hystrix、Spring Cloud Config等

2.3 开发步骤

项目是基于前后端分离的架构进行开发,前后端分离架构总体上包括前端和服务端,通常是多人协作并行开发,开 发步骤如下:

1、需求分析

梳理用户的需求,分析业务流程

2、接口定义

根据需求分析定义接口

3、服务端和前端并行开发

依据接口进行服务端接口开发。

前端开发用户操作界面,并请求服务端接口完成业务处理。

4、前后端集成测试

最终前端调用服务端接口完成业务。

CMS需求分析

3.1 什么是CMS

1、CMS是什么 ?

CMS (Content Management System)即内容管理系统,不同的项目对CMS的定位不同,比如:一个在线教育网站,有些公司认为CMS系统是对所有的课程资源进行管理,而在早期网站刚开始盛行时很多公司的业务是网站制    作,当时对CMS的定位是创建网站,即对网站的页面、图片等静态资源进行管理。

2、CMS有哪些类型?

上边也谈到每个公司对每个项目的CMS定位不同,CMS基本上分为:针对后台数据内容的管理、针对前端页面的 管理、针对样式风格的管理等 。比如:一个给企业做网站的公司,其CMS系统主要是网站页面管理及样式风格的管理。

3、本项目CMS的定位是什么?

本项目作为一个大型的在线教育平台,对CMS系统的定位是对各各网站(子站点)页面的管理,主要管理由于运营 需要而经常变动的页面,从而实现根据运营需要快速进行页面开发、上线的需求。

3.2 静态门户工程搭建

本项目CMS是对页面进行管理,对页面如何进行管理呢?我们首先搭建学成网的静态门户工程,根据门户的页面结 构来分析页面的管理方案。

门户,是一个网站的入口,一般网站都有一个对外的门户,学成在线门户效果图如下:

5b0f1260cead37f62e2eb04584c618bd_MD5

 

3.2.1 导入门户工程

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

00864c2de58dad8ff4da79cf8c2fbc91_MD5

 

3、导入门户工程

将课程资料中的门户工程拷贝到代码目录。

b839870f59b4a82179cee94c21e4e44d_MD5 [[Extras/Media/b839870f59b4a82179cee94c21e4e44d_MD5.jpg|]]

使用WebStorm打开门户工程目录,目录的结构如下,后期会根据开发的推进进行扩充。

3.2.2 配置虚拟主机

在nginx中配置虚拟主机:

48c6c5bfd6cae66a45e3125f7aeef877_MD5

F:/teach/xcEdu/xcEduUI/xc-ui-pc-static-portal/ 本目录即为门户的主目录。

5、配置hosts文件

本教程的开发环境使用Windows  7,修改C:\Windows\System32\drivers\etc\hosts文件

73d7707e5073acd0df51edaaaefd4a5d_MD5

 

进入浏览器,输入http://www.xuecheng.com

3.3 SSI服务端包含技术

本节分析首页的管理方案。

1、页面内容多如何管理?

将页面拆分成一个一个的小页面,通过cms去管理这些小页面,当要更改部分页面内容时只需要更改具体某个小页 面即可。

2、页面拆出来怎么样通过web服务浏览呢?

使用web服务(例如nginx)的SSI技术,将多个子页面合并渲染输出。

3、SSI是什么?

f76a53c54a16e0a0de9f32ef753523f0_MD5

 

ssi包含类似于jsp页面中的incluce指令,ssi是在web服务端将include指定    的页面包含在网页中,渲染html网页响应给客户端 。nginx、apache等多数web容器都支持SSI指令。

ssi指令如下:

281f27d15919dc9ebaea2f13f6d08b70_MD5

 

4、将首页拆分成

f6a844bb237e00c4d54c6c1fb8486582_MD5

 

5、在nginx虚拟主机中开通SSI

c51293bf865751480769a98f8e2a8aa5_MD5

 

ssi的配置参数如下: ssi on: 开启ssi支持

ssi_silent_errors on:默认为off,设置为on则在处理SSI文件出错时不输出错误信息

ssi_types:默认为 ssi_types text/html,如果需要支持shtml(服务器执行脚本,类似于jsp)则需要设置为ssi_types text/shtml

6、测试

去掉某个#include查看页面效果。

3.3 CMS页面管理需求

1、这些页面的管理流程是什么?

1) 创建站点:

一个网站有很多子站点,比如:学成在线有主门户、学习中心、问答系统等子站点。具体的哪个页面是归属于具体 的站点,所以要管理页面,先要管理页面所属的站点。

2) 创建模板:

页面如何创建呢?比如电商网站的商品详情页面,每个页面的内容布局、板式是相同的,不同的只是内容,这个页 面的布局、板式就是页面模板,模板+数据就组成一个完整的页面,最终要创建一个页面文件需要先定义此页面的 模板,最终拿到页面的数据再结合模板就拼装成一个完整的页面。

3) 创建页面:

创建页面是指填写页面的基本信息,如:页面的名称、页面的url地址等。

4) 页面预览:

页面预览是页面发布前的一项工作,页面预览使用静态化技术根据页面模板和数据生成页面内容,并通过浏览器预 览页面。页面发布前进行页面预览的目是为了保证页面发布后的正确性。

5) 页面发布:

使用计算机技术将页面发送到页面所在站点的服务器,页面发布成功就可以通过浏览器来访问了。

2、本项目要实现什么样的功能?

1) 页面管理

管理员在后台添加、修改、删除页面信息

2) 页面预览

管理员通过页面预览功能预览页面发布后的效果。

3) 页面发布

管理员通过页面发布功能将页面发布到远程门户服务器。

页面发布成功,用户即可在浏览器浏览到最新发布的页面,整个页面添加、发布的过程由于软件自动执行,无需人 工登录服务器操作。

CMS服务端工程搭建

4.1 开发工具配置

服务端工程使用IntellijIDEA开发。

1、创建工程代码目录 XcEduCode(本教程创建XcEduCode01目录),并且IDEA打开。

2、配置maven环境

拷贝老师提供的maven仓库,setting.xml文件中配置maven仓库,maven仓库的目录位置不要去使用中文。

b6150781c6807ecf9064b4a43f7a6a5a_MD5

 

f9b4517adcd77150362e255060613d0f_MD5

3、配置编码

4、配置JDK1.8

安装JDK1.8,并设置环境变量在IDEA配置JDK1.8

98164de79a8e6c66c450aae6a0db765d_MD5

5、配置快捷键

a933617a1eb38aaa6d13f8669c383f46_MD5

IDEA可以集成Eclipse的快捷键

如需自定义则点击“copy”复制一份进行修改

6、自动导入包 快捷方式:

idea可以自动优化导入包,但是有多个同名的类调用不同的包,必须自己手动Alt+Enter设置 设置idea导入包

e5ed1a263998568483025cfeb94c99b5_MD5

 

7、代码模板

bff3017455cbefb0630682e3fac27ad9_MD5

自定义自己的代码模板

8、提示忽略大小写

11ec2ed0c5de2e87d570b5c9891bbf97_MD5

默认IDEA的提示是区分大小写的,这里设置为提示忽略大小写

9、配置虚拟机内存

修改idea64.exe.vmoptions(64位电脑选择此文件)

一个例子,电脑内存8G,设置如下:

-Xms1024m -Xmx4096m -XX:MaxPermSize=1024m -XX:ReservedCodeCacheSize=1024m

4.2 导入基础工程

4.2.1 工程结构

CMS及其它服务端工程基于maven进行构建,首先需要创建如下基础工程: 

parent工程:父工程,提供依赖管理。

common工程:通用工程,提供各层封装

model工程:模型工程,提供统一的模型类管理

utils工程:工具类工程,提供本项目所使用的工具类

Api工程:接口工程,统一管理本项目的服务接口。

工程结果如下:

f7acae8243e08c9f73111060e1f2eff0_MD5

 

基础工程代码及pom.xml配置参考课程资料“基础工程”。

4.2.2 导入父工程

1、将课程资料中的parent工程拷贝到代码目录 2、点击Import Model,选择parent工程目录

fe3514f4e66dc74460c65bc4e849e292_MD5

 

选择Maven,下一步。

e9c9c2bf5473c59c882f8f7267c06204_MD5

 

3、导入成功

fafd6b85e670c70ccb1bafd7f1d71af7_MD5

 

4.2.3 导入其它工程

2d164bf2a5cb953151520f3e7bef7a44_MD5

依次导入utils、model、common、api工程,方法同parent工和的导入。

4.3 MongoDB入门

4.3.1 安装MongoDB

CMS采用MongoDB数据库存储CMS页面信息,CMS选用Mongodb的原因如下: 

1、Mongodb是非关系型数据库,存储Json格式数据 ,数据格式灵活。

2、相比课程管理等核心数据CMS数据不重要,且没有事务管理要求。

参考“mongodb安装.md”安装Mongodb Server及 Studio 3T客户端软件。

4.3.2 MongoDB入门

参考mongodb安装文档进行学习。

4.4 导入CMS数据库

导入cms数据库:

b22d7a07cbc931699b8551deca7dd4e7_MD5

使用Studio 3T软件导入cms数据库

1、创建xc_cms数据库

2、导入 cms数据库

右键数据库,点击导入数据库

2614e3bcdd373c03ffd7ac2d487e5618_MD5

 

打开窗口,选择第一个 json。

下一步,选择要导入的数据文件(json文件)

e3fdcd6b3ec8cd38f787e1350abb3c86_MD5

 

9e45417a903c939e0add81d979e1062c_MD5

下一步操作即可完成。导入成功:

页面查询接口定义

5.1 定义模型

5.1.1 需求分析

在梳理完用户需求后就要去定义前后端的接口,接口定义后前端和后端就可以依据接口去开发功能了。 本次定义页面查询接口,本接口供前端请求查询页面列表,支持分页及自定义条件查询方式。

具体需求如下:

1、分页查询CmsPage 集合下的数据

2、根据站点Id、模板Id、页面别名查询页面信息 

3、接口基于Http Get请求,响应Json数据

5.1.2 模型类介绍

接口的定义离不开数据模型,根据前边对需求的分析,整个页面管理模块的数据模型如下:

e7b4212b7a5d0010ccd0eaecfe683f68_MD5

 

CmsSite:站点模型CmsTemplate:

页面模板CmsPage:页面信息

页面信息如下:

3b6d46022a5cd769a56f5d2ed9d217c7_MD5

 

1d1b4b71eec287d4e9f72ea79706d2ce_MD5

属性说明:

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注解生成通用方法。

42561f94dab2f328eacd5e97372e4a5d_MD5

 

2、在IDEA开发工具中添加Lombok插件

6841bae16d0f608aa897ce285e477a60_MD5

作用:使用IDEA开发时根据Lombok注解生成通用方法,不报错。

b029ef2e20b775260a7035beb31836df_MD5

 

5.2 定义接口

5.2.1 定义请求及响应类型

a16d9824267811e99c8c5b1459cbe770_MD5

1、定义请求模型QueryPageRequest,此模型作为查询条件类型为后期扩展需求,请求类型统一继承RequestData类型。

2、响应结果类型,分页查询统一使用QueryResponseResult

5.2.2 定义接口

在Api接口工程专门定义接口,在Api工程单独定义接口的原因如下:

1、接口集中管理

5109a1a2745ae3bb003034935efce340_MD5

2、Api工程的接口将作为各微服务远程调用使用

页面查询接口定义如下:

此接口编写后会在CMS服务工程编写Controller类实现此接口。

页面查询服务端开发

6.1 创建CMS服务工程

6.1.1 创建CMS工程结构

7bf2a54f1e82e63299b826395f3039b3_MD5

创建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"](http://maven.apache.org/POM/4.0.0) [xmlns:xsi="http://www.w3.org/2001/XMLSchema‐instance"](http://www.w3.org/2001/XMLSchema) [xsi:schemaLocation="http://maven.apache.org/POM/4.0.0](http://maven.apache.org/POM/4.0.0)
 
[http://maven.apache.org/xsd/maven‐4.0.0.xsd">](http://maven.apache.org/xsd/maven)
 
<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所以需要在在cms服务端工程添加如下依赖: 

项目使用spring data mongodb操作mongodb数据库

 
<dependency>
 
<groupId>org.springframework.boot</groupId>
 
<artifactId>spring‐boot‐starter‐data‐mongodb</artifactId>
 
</dependency>

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类目录

c9b0e820b0ece131e19023f94ca7ca49_MD5

工程结构如下:

3、配置文件

在classpath下配置application.yml

fffc00e17adcaa9ff980fac0220098d2_MD5

 

另外从课程资料下“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包下 :

0a700feee827960150edf1da930db4df_MD5

关于maven多项目编译出错: maven 依赖的项目报错 Could not resolve dependencies for project

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;
 
}
 
}

使用浏览器测试

输入:http://localhost:31001/cms/page/list/1/10   查询第1页,每页显示10条记录。

6.2 Dao

6.2.1 分页查询测试

6.2.1.1 定义Dao接口

本项目使用Spring Data Mongodb完成Mongodb数据库的查询,Spring Data Mongodb提供一套快捷操作mongodb的方法。

创建Dao,继承MongoRepository,并指定实体类型和主键类型。

84d76a231776d83c965f19520a4420cb_MD5

 

6.2.1.2 编写测试类

75ae5e65d7096d6d691e1d1ec5cd865c_MD5

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;
}

6.2.1.3 分页查询测试

32944d20c8a6af780029b2ea71f33439_MD5

 

6.2.2 基础方法测试

这里Dao接口继承了MongoRepository,在MongoRepository中定义了很多现成的方法,如save、delete等,通过下边的代码来测试这里父类方法。

此小节内容请同学们自行测试。

6.2.3.1 添加

541fbd185833c8c1d028c2ee95396c5f_MD5

 

6.2.3.2 删除

3682c51d8ef69c50e348ca9193baa9a1_MD5

6.2.3.3 修改

fc4c360ddfd6bd3b06a374734f362969_MD5

 

关于Optional:

Optional是jdk1.8引入的类型,Optional是一个容器对象,它包括了我们需要的对象,使用isPresent方法判断所包 含对象是否为空,isPresent方法返回false则表示Optional包含对象为空,否则可以使用get()取出对象进行操作。

Optional的优点是:

1、提醒你非空判断。

2、将对象非空检测标准化。

6.2.3.4 自定义Dao方法

同Spring Data JPA一样Spring Data mongodb也提供自定义方法的规则,如下:

按照findByXXX,findByXXXAndYYY、countByXXXAndYYY等规则定义方法,实现查询操作。

efd0ca28851235bac49f13754fe0c16c_MD5

6.3 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的接口将页码减1 if (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);
 
}
 
}

6.4 Controller

使用springMVC完成接口实现开发。

a0845496f55bad9bc7442f052a5ca6c1_MD5

 

使用浏览器测试

输入:http://localhost:31001/cms/page/list/1/10   查询第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”)

页面查询接口测试

上边的代码是基于服务端编写接口,如果前端人员等待服务端人员将接口开发完毕再去开发前端内容这样做效率是 非常低下的,所以当接口定义完成,可以使用工具生成接口文档,前端人员查看接口文档即可进行前端开发,这样 前端和服务人员并行开发,大大提高了生产效率。

本章节介绍两种接口开发工具,Swagger和Postman。

7.1 Swagger

7.1.1 Swagger介绍

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项目下快速构建项目的框架。

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属性:

83dd2141be45fc40b1a241528835e35f_MD5

7.1.3 Swagger接口定义

修改接口工程中页面查询接口,添加Swagger注解。

67593205ca0827199e6dec4c4d240a07_MD5

 

在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工程中的Swagger2Configuration类

2、在此类中指定了包路径com.xuecheng,找到在此包下及子包下标记有@RestController注解的controller类    

3、根据controller类中的Swagger注解生成接口文档。

启动cms服务工程,查看接口文档,请求:http://localhost:31001/swagger-ui.html

f0138e6fea68f3085ee48230d32f1c39_MD5

 

点击“分页查询页面列表”,打开接口详情

2fc009a614fe8a09dd095a9bf8e18543_MD5

 

使用Swagger工具测试服务接口:

1) 在cms服务接口中打断点

2) 

7c123fb1af6908d29680ba1f4cca5a6f_MD5

打开接口文档页面,输入请求参数,点击“Try it out”发起请求。

7.5 Postman

Postman是一款功能强大的http接口测试工具,使用postman可以完成http各种请求的功能测试。官方地址:https://www.getpostman.com/

1、安装Postman

本教程使用,双击打开 Postman-win64-6.0.10-Setup.exe

新建一个Postman窗口

158030075ed273850afa9e269f5283a2_MD5

180c4763dbcc36f7c725c472ddc99dce_MD5

 

98daadb33fd64db05f158e7ae407b542_MD5

2、使用postman测试http接口

3、请求参数设置

1) get请求参数设置

5603df31f28699a0f83855f928358feb_MD5

 

2) 

9e9ed35f7d96452e09c5cfb700870f2f_MD5

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,可用于上传文件。