学成在线:项目环境搭建-MongoDB入门

1. 项目的技术架构

1.1 技术架构

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

业务流程举例:

  1. 用户可以通过pc、手机等客户端访问系统进行在线学习。
  2. 系统应用CDN技术,对一些图片、CSS、视频等资源从CDN调度访问。
  3. 所有的请求全部经过负载均衡器。
  4. 对于PC、H5等客户端请求,首先请求UI层,渲染用户界面。
  5. 客户端UI请求服务层获取进行具体的业务操作。
  6. 服务层将数据持久化到数据库。

1.2 技术栈

重点了解微服务技术栈:

  • 学成在线服务端基于Spring Boot构建,采用Spring Cloud微服务框架。
  • 持久层:MySQLMongoDBRedisElasticSearch
  • 数据访问层:使用Spring Data JPAMybatisSpring Data Mongodb
  • 业务层:Spring IOCAop事务控制、Spring Task任务调度、FeignRibbonSpring AMQPSpring Data Redis等。
  • 控制层:Spring MVCFastJSONRestTemplateSpring Security Oauth2+JWT
  • 微服务治理:EurekaZuulHystrixSpring Cloud Config

2. CMS需求分析

2.1 什么是CMS

  1. CMS是什么 ?

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

  2. CMS有哪些类型?

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

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

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

2.2 静态门户工程搭建

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

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

2.3 导入门户工程

  1. 安装WebStorm

  1. 安装Nginx

    本项目下载 nginx-1.14.0.zip(http://nginx.org/download/nginx-1.14.0.zip)

    解压nginx-1.14.0.zip到自己的计算机,双击nginx.exe即可运行。

    访问 :http://localhost

  1. 导入门户工程

2.4 配置虚拟主机

在nginx中配置虚拟主机:

server{
        listen       80;
        server_name  www.xuecheng.com;
        ssi  on;
        ssi_silent_errors on;
        location / {
        alias   E:/Users/WebstormProjects/xcEduUI/xc-ui-pc-static-portal/xc-ui-pc-static-portal/;
        index  index.html;
        }
    }

E:/Users/WebstormProjects/xcEduUI/xc-ui-pc-static-portal/xc-ui-pc-static-portal/本目录即为门户的主目录。

配置hosts文件:

修改C:\Windows\System32\drivers\etc\hosts文件

127.0.0.1 www.xuecheng.com

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

3. SSI 服务端包含技术

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

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

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

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

  3. SSI是什么?

    SSI(Server Side Include),通常称为服务器端嵌入,是一种类似于ASP的基于服务器的网页制作技术。大多数(尤其是基于Unix平台)的WEB服务器如Netscape Enterprise Server等均支持SSI命令。

    SSI工作原理:

    将内容发送到浏览器之前,可以使用“服务器端包含 (SSI)”指令将文本、图形或应用程序信息包含到网页中。例如,可以使用 SSI 包含时间/日期戳、版权声明或供客户填写并返回的表单。对于在多个文件中重复出现的文本或图形,使用包含文件是一种简便的方法。将内容存入一个包含文件中即可,而不必将内容输入所有文件。通过一个非常简单的语句即可调用包含文件,此语句指示 Web 服务器将内容插入适当网页。而且,使用包含文件时,对内容的所有更改只需在一个地方就能完成。

    因为包含 SSI 指令的文件要求特殊处理,所以必须为所有 SSI 文件赋予SSI 文件扩展名。默认扩展名是.stm、.shtm 和.shtml

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

  1. 将首页拆分成

    index.html:首页主体内容
    include/header.html:头部区域
    include/index_banner.html:轮播图
    include/index_category.html:左侧列表导航
    include/footer.html:页尾
    
  2. 在nginx虚拟主机中开通SSI

    server{
    listen       80;    
    server_name  www.xuecheng.com;    
    ssi on;    
    ssi_silent_errors on;    
    ...... 
    

    ssi的配置参数如下: ssi on: 开启ssi支持 ssi_silent_errors on:默认为off,设置为on则在处理SSI文件出错时不输出错误信息 ssi_types:默认为 ssi_types text/html,如果需要支持shtml(服务器执行脚本,类似于jsp)则需要设置为ssi_types text/shtml

  3. 测试

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

4. CMS 服务端工程搭建

4.1 导入基础工程

4.1.1 工程结构

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

  • parent工程:父工程,提供依赖管理。
  • common工程:通用工程,提供各层封装
  • model工程:模型工程,提供统一的模型类管理
  • utils工程:工具类工程,提供本项目所使用的工具类
  • Api工程:接口工程,统一管理本项目的服务接口。

工程结果如下:

4.1.2 导入父工程

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

选择Maven,下一步。

  1. 导入成功

4.1.3 导入其它工程

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

5. MongoDB 入门

5.1 安装MongoDB

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

  1. Mongodb是非关系型数据库,存储Json格式数据 ,数据格式灵活。
  2. 相比课程管理等核心数据CMS数据不重要,且没有事务管理要求。

官方地址:https://www.mongodb.com/
本教程下载 3.4版本:http://downloads.mongodb.org/win32/mongodb-win32-x86_64-2008plus-ssl-v3.4-latest-signed.msi

5.2 启动MongoDB

创建几个文件夹具体如下:数据库路径(data目录)、日志路径(logs目录)和日志文件(mongo.log文件)

创建配置文件 mongo.conf,文件内容如下:

#数据库路径 
dbpath=d:\MongoDB\Server\3.4\data 
#日志输出文件路径 
logpath=d:\MongoDB\Server\3.4\logs\mongo.log 
#错误日志采用追加模式 
logappend=true 
#启用日志文件,默认启用 
journal=true 
#这个选项可以过滤掉一些无用的日志信息,若需要调试使用请设置为false 
quiet=true 
#端口号 默认为27017 
port=27017

安装 MongoDB服务

通过执行bin/mongod.exe,使用--install选项来安装服务,使用--config选项来指定之前创建的配置文件。 cmd进
入d:\MongoDB\Server\3.4\bin

以管理员模式打开cmd,cd到mongodb bin目录下,运行:

mongod --config "D:\Mongo\mongo.conf"  --install --serviceName "MongoDB"

启动MongoDB服务

net start MongoDB

关闭MongoDB服务

net stop MongoDB

移除MongoDB服务

" d:\MongoDB\Server\3.4\bin\mongod.exe" ‐‐remove

启动mongodb服务,命令执行后,浏览器中输入http://127.0.0.1:27017看到如下界面即说明启动成功

5.3 安装studio3t

studio3t是mongodb优秀的客户端工具。官方地址在https://studio3t.com/

5.4 基础概念

在mongodb中是通过数据库、集合、文档的方式来管理数据,下边是mongodb与关系数据库的一些概念对比:

SQL 术语/概念 MongoDB术语/概念 解释/说明
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
table joins 表连接(MongoDB不支持)
primary key primary key 主键,MongoDB自动在每个集合中添加_id的主键
  1. 一个mongodb实例可以创建多个数据库
  2. 一个数据库可以创建多个集合
  3. 一个集合可以包括多个文档。

5.5 连接mongodb

mongodb的使用方式是客户服务器模式,即使用一个客户端连接mongodb数据库(服务端)。

  1. 命令格式
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?
options]]
  • mongodb:// 固定前缀
  • username:账号,可不填
  • password:密码,可不填
  • host:主机名或ip地址,只有host主机名为必填项。
  • port:端口,可不填,默认27017
  • /database:连接某一个数据库
  • ?options:连接参数,key/value对

例子:

mongodb://localhost 连接本地数据库27017端口 
mongodb://root:itcast@localhost 使用用户名root密码为itcast连接本地数据库27017端口 
mongodb://localhost,localhost:27018,localhost:27019,连接三台主从服务器,端口为27017、27018、27019
  1. 使用mongodb自带的javascript shell(mongo.exe)连接

windows 版本的mongodb安装成功,在安装目录下的bin目录有mongo.exe客户端程序

cmd状态执行mongo.exe:

此时就可以输入命令来操作mongodb数据库了,javascript shell可以运行javascript程序。

  1. 使用studio3T连接

  2. 使用java程序连接

    详细参数:http://mongodb.github.io/mongo-java-driver/3.4/driver/tutorials/connect-to-mongodb/

    添加依赖:

    <dependency>
        <groupId>org.mongodb</groupId>
        <artifactId>mongo‐java‐driver</artifactId>
        <version>3.4.3</version>
    </dependency>
    

    测试程序:

    @Test
    public void testConnection(){
        //创建mongodb 客户端
        MongoClient mongoClient = new MongoClient( "localhost" , 27017 );
        //或者采用连接字符串
        //MongoClientURI connectionString = new    
        MongoClientURI("mongodb://root:root@localhost:27017");
    
        //MongoClient mongoClient = new MongoClient(connectionString);    
        //连接数据库
        MongoDatabase database = mongoClient.getDatabase("test");
        // 连接collection
        MongoCollection<Document> collection = database.getCollection("student");
        //查询第一个文档
        Document myDoc = collection.find().first();
        //得到文件内容 json串
        String json = myDoc.toJson();
        System.out.println(json);
    }
    

    5.6 数据库

    1. 查询数据库

      show dbs 查询全部数据库
      db 显示当前数据库

    2. 创建数据库

      命令格式:

      use DATABASE_NAME
      

      例子:

      use test02
      

      有test02数据库则切换到此数据库,没有则创建。

      注意:

      新创建的数据库不显示,需要至少包括一个集合。

    3. 删除数据库(慎用!!!)

      命令格式:

      db.dropDatabase()
      

      例子:

      删除test02数据库

      先切换数据库:use test02

      再执行删除:db.dropDatabase()

5.6 集合

集合相当于关系数据库中的表,一个数据库可以创建多个集合,一个集合是将相同类型的文档管理起来。

  1. 创建集合

    db.createCollection(name, options)
    name: 新创建的集合名称
    options: 创建参数
    
  2. 删除集合

    db.collection.drop()
    

    例子:

    db.student.drop() 删除student集合
    

5.7 文档

5.7.1 插入文档

mongodb中文档的格式是json格式,下边就是一个文档,包括两个key:_id主键和name

{
    "_id" : ObjectId("5b2cc4bfa6a44812707739b5"),
    "name" : "黑马程序员"
}

插入命令:

db.COLLECTION_NAME.insert(document)

每个文档默认以_id作为主键,主键默认类型为ObjectId(对象类型),mongodb会自动生成主键值。

例子:

db.student.insert({"name":"黑马程序员","age":10})

注意:同一个集合中的文档的key可以不相同!但是建议设置为相同的。

5.7.2 更新文档

命令格式:

db.collection.update(
   <query>,
   <update>,
   <options>
)
query:查询条件,相当于sql语句的where
update:更新文档内容
options:选项
  1. 替换文档

    将符合条件 "name":"北京黑马程序"的第一个文档替换为{"name":"北京黑马程序员","age":10}。

    db.student.update({"name":"黑马程序员"},{"name":"北京黑马程序员","age":10})
    
  2. $set修改器

    使用$set修改器指定要更新的key,key不存在则创建,存在则更新。
    将符合条件 "name":"北京黑马程序"的所有文档更新name和age的值。

    db.student.update({"name":"黑马程序员"},{$set:{"name":"北京黑马程序员","age":10}},{multi:true})
    

    multi:false表示更新第一个匹配的文档,true表示更新所有匹配的文档。

5.7.3 删除文档

命令格式:

db.student.remove(<query>)
query:删除条件,相当于sql语句中的where
  1. 删除所有文档

    db.student.remove({})
    
  2. 删除符合条件的文档

    db.student.remove({"name":"黑马程序员"})
    

5.7.4 查询文档

命令格式:

db.collection.find(query, projection)
query:查询条件,可不填
projection:投影查询key,可不填
  1. 查询全部

    db.student.find()
    
  2. 查询符合条件的记录

    db.student.find({"name":"黑马程序员"})
    
  3. 投影查询

    只显示name和age两个key,_id主键不显示。

    db.student.find({"name":"黑马程序员"},{name:1,age:1,_id:0})
    

6. 用户

6.1 创建用户

语法格式:

mongo>db.createUser(
{ user: "<name>",
  pwd: "<cleartext password>",
  customData: { <any information> },
  roles: [
    { role: "<role>", db: "<database>" } | "<role>",
    ...
  ]}
)

例子:

创建root用户,角色为root

use admin
db.createUser(
     {
       user:"root",
       pwd:"root",
       roles:[{role:"root",db:"admin"}]
     }
  )

内置角色如下:

  1. 数据库用户角色:readreadWrite;
  2. 数据库管理角色:dbAdmindbOwneruserAdmin
  3. 集群管理角色:clusterAdminclusterManagerclusterMonitorhostManager
  4. 备份恢复角色:backuprestore
  5. 所有数据库角色:readAnyDatabasereadWriteAnyDatabaseuserAdminAnyDatabasedbAdminAnyDatabase
  6. 超级用户角色:root

6.2 查询用户

查询当前库下的所有用户:

show users

6.3 删除用户

语法格式:

db.dropUser("用户名")

例子:

删除root1用户

db.dropUser("root1")

6.4 修改用户

语法格式:

db.updateUser(
  "<username>",
  {
    customData : { <any information> },
    roles : [
              { role: "<role>", db: "<database>" } | "<role>",
              ...
            ],
    pwd: "<cleartext password>"
    },
    writeConcern: { <write concern> })

例子:

修改root用户的角色为readWriteAnyDatabase

use admin
db.updateUser("root",{roles:[{role:"readWriteAnyDatabase",db:"admin"}]})

6.5 修改密码

语法格式:

db.changeUserPassword("username","newPasswd")

例子:

修改root用户的密码为123

use admin
db.changeUserPassword("root","123")

6.6 认证登陆

为了安全需要,Mongodb要打开认证开关,即用户连接Mongodb要进行认证,其中就可以通过账号密码方式进行认证。

  1. 在mono.conf中设置auth=true

  2. 重启Mongodb

  3. 使用账号和密码连接数据库

    1. mongo.exe连接

      mongo.exe -u root -p 123 --authenticationDatabase admin
      
    2. Studio 3T连接

7. 导入CMS数据库

导入cms数据库:

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

  1. 创建xc_cms数据库

  2. 导入 cms数据库

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

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

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

8. 页面查询接口定义

8.1 需求分析

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

具体需求如下:

  1. 分页查询CmsPage 集合下的数据
  2. 根据站点Id、模板Id、页面别名查询页面信息
  3. 接口基于Http Get请求,响应Json数据

8.2 模型类介绍

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

  • CmsSite:站点模型
  • CmsTemplate:页面模板
  • CmsPage:页面信息

页面信息如下:

package com.xuecheng.framework.domain.cms;
@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. 定义一个页面需要指定页面所属站点

    一个站点包括多个页面,比如:学成在线的门户站点(网站)包括了多个页面。

  2. 定义一个页面需要指定页面使用的模板

    多个页面可以使用相同的模板,比如:商品信息模板,每个商品就是一个页面,所有商品使用同一个商品信息模板

  3. 注解说明:

    @Document:是Spring Data mongodb提供的注解,最终CMS的开发会使用Mongodb数据库。

8.3 定义请求及响应类型

定义请求模型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;
}

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

8.4 定义接口

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

  1. 接口集中管理
  2. Api工程的接口将作为各微服务远程调用使用。

页面查询接口定义如下:

package com.xuecheng.api.cms;
public interface CmsPageControllerApi {
    //页面查询
    QueryResponseResult findList(int page, int size, QueryPageRequest queryPageRequest);
}

以下规定了本项目响应的数据模型

QueryResponseResult继承ResponseResult

package com.xuecheng.framework.model.response;
@Data
@ToString
public class QueryResponseResult extends ResponseResult {

    QueryResult queryResult;

    public QueryResponseResult(ResultCode resultCode,QueryResult queryResult){
        super(resultCode);
       this.queryResult = queryResult;
    }
}
package com.xuecheng.framework.model.response;
@Data
@ToString
@NoArgsConstructor
public class ResponseResult implements Response {

    //操作是否成功
    boolean success = SUCCESS;

    //操作代码
    int code = SUCCESS_CODE;

    //提示信息
    String message;

    public ResponseResult(ResultCode resultCode){
        this.success = resultCode.success();
        this.code = resultCode.code();
        this.message = resultCode.message();
    }

    public static ResponseResult SUCCESS(){
        return new ResponseResult(CommonCode.SUCCESS);
    }
    public static ResponseResult FAIL(){
        return new ResponseResult(CommonCode.FAIL);
    }
}

QueryResult

package com.xuecheng.framework.model.response;
@Data
@ToString
public class QueryResult<T> {
    //数据列表
    private List<T> list;
    //数据总数
    private long total;
}

接口Response

package com.xuecheng.framework.model.response;
public interface Response {
    public static final boolean SUCCESS = true;
    public static final int SUCCESS_CODE = 10000;
}

CommonCode枚举

package com.xuecheng.framework.model.response;
@ToString
public enum CommonCode implements ResultCode{

    SUCCESS(true,10000,"操作成功!"),
    FAIL(false,11111,"操作失败!"),
    UNAUTHENTICATED(false,10001,"此操作需要登陆系统!"),
    UNAUTHORISE(false,10002,"权限不足,无权操作!"),
    SERVER_ERROR(false,99999,"抱歉,系统繁忙,请稍后重试!");
//    private static ImmutableMap<Integer, CommonCode> codes ;
    //操作是否成功
    boolean success;
    //操作代码
    int code;
    //提示信息
    String message;
    private CommonCode(boolean success,int code, String message){
        this.success = success;
        this.code = code;
        this.message = message;
    }

    @Override
    public boolean success() {
        return success;
    }
    @Override
    public int code() {
        return code;
    }

    @Override
    public String message() {
        return message;
    }
}

ResultCode接口:

package com.xuecheng.framework.model.response;

/**
 * Created by mrt on 2018/3/5.
 * 10000-- 通用错误代码
 * 22000-- 媒资错误代码
 * 23000-- 用户中心错误代码
 * 24000-- cms错误代码
 * 25000-- 文件系统
 */
public interface ResultCode {
    //操作是否成功,true为成功,false操作失败
    boolean success();
    //操作代码
    int code();
    //提示信息
    String message();
}

9. 页面查询服务端开发

9.1 创建CMS服务工程

创建maven工程, CMS工程的名称为 xc-service-manage-cms,父工程为xc-framework-parent。

pom.xml如下:

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

创建基本包结构

配置文件 application.yml

server:
  port: 31001
spring:
  application:
    name: xc‐service‐manage‐cms
  data:
    mongodb:
      uri: mongodb://root:123@localhost:27017
      database: xc_cms

SpringBoot 启动类

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

测试Controller

package com.xuecheng.manage_cms.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) {

       //暂时用静态数据
        //定义queryResult
        QueryResult<CmsPage> queryResult =new QueryResult<>();
        List<CmsPage> list = new ArrayList<>();
        CmsPage cmsPage = new CmsPage();
        cmsPage.setPageName("测试页面");
        list.add(cmsPage);
        queryResult.setList(list);
        queryResult.setTotal(1);

        QueryResponseResult queryResponseResult = new QueryResponseResult(CommonCode.SUCCESS,queryResult);
        return queryResponseResult;
        //调用service
        //return pageService.findList(page,size,queryPageRequest);
    }
}

10. Dao

10.1 分页查询测试

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

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

package com.xuecheng.manage_cms.dao;
public interface CmsPageRepository extends MongoRepository<CmsPage,String> {
}

10.1.1 编写测试类

test下的包路径与main下的包路径保持一致。

测试程序使用@SpringBootTest@RunWith(SpringRunner.class)注解,启动测试类会从main下找springBoot启动类,加载spring容器。

测试代码如下:

package com.xuecheng.manage_cms;
@SpringBootTest
@RunWith(SpringRunner.class)
public class CmsPageRepositoryTest {

    @Autowired
    CmsPageRepository cmsPageRepository;

    @Test
    public void testFindAll(){
        List<CmsPage> all = cmsPageRepository.findAll();
        System.out.println(all);

    }

    //分页查询
    @Test
    public void testFindPage(){
        //分页参数
        int page = 1;//从0开始
        int size = 10;
        Pageable pageable = PageRequest.of(page,size);
        Page<CmsPage> all = cmsPageRepository.findAll(pageable);
        System.out.println(all);
    }
}

10.1.2 基础方法测试

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

  1. 添加

    //添加@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);
    }
    
  2. 删除

    //删除@Test
    public void testDelete() { cmsPageRepository.deleteById("5b17a2c511fe5e0c409e5eb3");
    }
    
  3. 修改

    @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. 将对象非空检测标准化。

10.1.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);
}

11. Service

定义页面查询方法,根据条件查询暂时不实现:

package com.xuecheng.manage_cms.service;

@Service
public class PageService {
    @Autowired
    CmsPageRepository cmsPageRepository;
    /**
     * 页面查询方法
     * @param page 页码,从1开始记数
     * @param size 每页记录数
     * @param queryPageRequest 查询条件
     * @return
     */
    public QueryResponseResult findList(int page, int size, QueryPageRequest queryPageRequest){

        //分页参数
        if(page <=0){
            page = 1;
        }
        page = page -1;
        if(size<=0){
            size = 10;
        }
        Pageable pageable = PageRequest.of(page,size);
        Page<CmsPage> all = cmsPageRepository.findAll(pageable);
        QueryResult queryResult = new QueryResult();
        queryResult.setList(all.getContent());//数据列表
        queryResult.setTotal(all.getTotalElements());//数据总记录数
        QueryResponseResult queryResponseResult = new QueryResponseResult(CommonCode.SUCCESS,queryResult);
        return queryResponseResult;
    }
}

12. Controller

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

package com.xuecheng.manage_cms.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);
    }
}

使用浏览器测试

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 第一章 前言 1.1 知识体系分析 前端工程师:Web前端,也就是在Web应用中用户可以看得见碰得着的东西。包括W...
    whitsats阅读 865评论 0 3
  • MongoDB讲义 为0 何要学习MongoDB 灵活的数据模型 MongoDB的文档数据模型使开发人员和数...
    小虎_9f76阅读 425评论 1 3
  • 一、MongoDB简介 1.概述 ​ MongoDB是一个基于分布式文件存储的数据库,由C++语言编写。旨在为WE...
    郑元吉阅读 974评论 0 2
  • 背景: 阅读新闻 12C CDB模式下RMAN备份与恢复 [日期:2016-11-29] 来源:Linux社区 作...
    阳屯okyepd阅读 3,332评论 0 7
  • Mongodb数据库 课程介绍 Ø 数据库概述(了解) Ø NoSQL和MongoDB简介(了解) Ø Mongo...
    致自己_cb38阅读 1,749评论 0 4