慕课项目开工!part2:后端架构 (更新中。。。。)

运行前端项目

先下载tomcat,并解压到本地。

img

因为我电脑上有8080端口占用,所以首先先修改conf目录下的server.xml文件,将端口改为9090

img

修改完就可以启动了。。。。

直接双击bin目录下的startup.bat文件,服务器就跑起来了。

img

既然启动了服务器,那必然可以挂载前端项目到服务器上了!(后期会把这些静态资源挂载到nginx的)

需要前端资源可以私信作者

img

在本地构建虚拟域名来访问

在我们平常的web项目中,通常都是localhost:port 或者 127.0.0.1:port访问,写的比较麻烦,在本地通过虚拟域名访问会清晰许多

下载一个switchhosts

img

下载地址:https://swh.app/zh/

首先看看自己的ip地址是多少吧

具体就是打开cmd输入“ipconfig”

将本地ip和你的接口或者访问路径连接。。

img

改完之后打开前端资源里的app.js,在这里有公用的请求资源,所以如果读者们像根据自己的需求修改端口,务必修改app.js里的数据

img

关于数据库的选型

项目老师使用的MariaDB,但是我懒得下载,就直接用mysql了

需要安装mysql和图形化界面sqlyog,具体地址就不贴出来了。。。

sqlyog长这个样子 img

然后就是sql文件了,想要的话私信我。。。

创建完成后,发现有6个表

admin_user,app_user,article,category,comments,fans

admin_user

admin_user是主要用与存储管理员信息的表

img

app_user

这个表用于存储用户的表

img

article

这个表是用来存储网站文章的表

img

category

新闻资讯文章的分类

img

comments

该表主要用于管理评论文章的用户,注意评论还可以被评论

img

fans

该表主要用于管理粉丝

img

构建maven聚合工程

示意图

img

主要就是在idea中建立一个Module顶级工程,其他的基础工程都是在顶级工程中拓展的。。

创建顶级工程

首先在idea中,勾中maven项目创建一个顶级工程

img

导入pom.xml

之后就是导入pom依赖啦,由于篇幅,pom文件也不在这里贴出来了

我们的依赖主要导入了:springcloud,一些springboot的基本启动类,mongodb依赖,mysql驱动,mybatis,分页工具,okhttp(网络请求框架),jackson(用于json数据的传输),apache的工具类,google工具类,swagger依赖(接口文档),文件上传fastdfs,

pom模块之间的规则
1	聚合工程可以分为顶级项目(顶级工程,父工程)与子工程(子module模块),
	这两者的关系其实就是父子继承的关系,子工程在maven中可以称之为module,
	模块与模块之间是平级的,是可以相互依赖的。
2	子模块可以使用顶级工程中所有的资源(依赖),子模块之间如果有要使用资源的话,必须构建依赖
3	一个顶级工程是可以由多个不同的子工程共同组合而成。
pom的一些小细节

注意

正如rabbitMq的rabbitmq和erlang一样,springcloud和springboot也有相对的版本对应,所以我们引入依赖的时候得导对。。

查看详情请前往spring的官网 : spring.io

img

该项目采用的依赖springboot的版本为2.2.5,所以自然需要Hoxton的springcloud

img

说到版本对应,我们所有以来的版本号都是放到properties中去管理的,properties管理非常方便,我们该版本就不需要一个一个找了,就比如我电脑的mysql版本是5.5.28,mysql驱动也得对应,就在properties中修改

img

img

dependencyManagement

看我们pom文件的最后一项dependencyManagement,这个标签有什么作用呢,因为这个工程是作为我们的顶级工程,其他工程都是在该工程下编写的,我们当然不需要我们原本的顶级工程也下载那么多jar包,这是没有意义的,刚才说了子工程可以继承父工程依赖,那么我们在子工程请求父工程依赖的时候,让他自己去外网下载,就非常好了,这也是他的作用。也就是说父模块只管理依赖的版本,并不管理依赖本身!

看看我们现在引入了这么多pom,但是项目中只有jdk的包

img

构建子模块

右键顶级工程,然后如下图

img

跟着提示,取你喜欢的名字,子模块就创建好了!

可以会看我们的**maven聚合工程示意图,**发现基础工程中的common,model,api是依赖的关系,所以我们要配置依赖

在model的pom文件中,去依赖common

img

在api的pom文件中,去依赖model

img

最后完成的Module骨架显示

img

创建完之后的测试

创建一个Controller

package com.imooc.user.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @version 1.0
 * @ClassName HelloController
 * @Description TODO
 * @Author 89255
 */
@RestController
public class HelloController {
    @RequestMapping("/hello")
    public Object Hello(){
        return "helloworld";
    }
}

application.yml

server:
  #访问端口8003
  port: 8003
  tomcat:
    #tomcat字符集UTF8
    uri-encoding: UTF-8
    #禁用,如果不禁用tomcat默认超过2M大小的文件不获取
    max-swallow-size: -1

#配置项目信息
spring:
  application:
    name: service-user
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8

测试结果,成功!正好把我们的虚拟网址测试了一下,发现是可以使用的,至此我们的聚合工程的基本框架就搭建好了

img

api接口暴露

我们的接口都会写在子模块api中,我们在api中创建一个接口

package user.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @version 1.0
 * @ClassName HelloController
 * @Description TODO
 * @Author 89255
 */
@RestController
public interface HelloControllerApi {
  
    @RequestMapping("/hello")
    public Object Hello();
}

在user模块中就可以去继承这个接口了!

package com.imooc.user.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import user.controller.HelloControllerApi;

/**
 * @version 1.0
 * @ClassName HelloController
 * @Description TODO
 * @Author 89255
 */
@RestController
public class HelloController implements HelloControllerApi {
    @RequestMapping("/hello")
    public Object Hello(){
        return "helloworld";
    }
}

为什么要这么做呢?

api的作用:

api 就相当于企业的领导,老板,部门经理

其他的服务层都是实现,他们就相当于员工,只做事情

老板(开发人员)来看一下每个人(服务)的进度,做什么事。老板不会去问员工,他只会对接部门经理。

那么这个里的所有的api接口就是统一在这里进行管理和调度的,微服务也是如此

运作:

现在的所有接口都在此暴露,实现都是在各自的微服务中

本项目只写接口,不写实现,实现在各自的微服务工程中,因为以业务来划分的微服务有很多controller也会分散在各个微服务工程中,一旦多了就很难统一管理和查看

其次,微服务之间的调用都是基于接口的

更多it视欢 ukoo

如果不这么做,微服务之间的调用就需要相互依赖了,

耦合度也就高了,接口的目的为了能够提供解耦。

此外,本工程的接口其实就是一套规范。实现都是由各自的工程去做的处理。目前我们使用springboot作为接口的实现的。

如果以后springboot被淘汰了,我们也不需要修改接口,只用修改实现就可以了。。

配置日志相关的配置

配置logback-spring.xml

别cv,记得修改日志存储路径

<?xml version="1.0" encoding="UTF-8"?>

<configuration>
    <!-- 指定日志文件的存储地址,使用绝对路径 -->
    <property name="LOG_HOME" value="D:\immoc-news-dev\imooc-news-dev-service-user\src\main\resources\logs"/>

    <!-- Console 输出设置 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%white(%d{mm:ss.SSS}) %green([%thread]) %cyan(%-5level) %yellow(%logger{36}) %magenta(-) %black(%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}/service-admin.%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>

    <!--<logger name="org.apache.ibatis.cache.decorators.LoggingCache" level="DEBUG" additivity="false">-->
        <!--<appender-ref ref="CONSOLE"/>-->
    <!--</logger>-->

    <root level="info">
        <appender-ref ref="FILE"/>
        <appender-ref ref="CONSOLE"/>
    </root>
</configuration>

yml多环境配置

创建多个环境的yml,例如开发环境(dev),测试环境(test),生产环境(pro)

img

然后再application中表明你现在是哪个环境

img

例如现在就是dev环境

封装返回结果

我们现在的开发环境都是前后端交互的,所以啊,你必须返回给前端一个json供他解析的,这个json就可以用对象来转换,所以我们需要创建一个公共的对象供我们返回,这个对象其实就是我们给前端的json了,例如前端怎么知道调用你的接口正确与否呢?你可以在公共返回对象中设置一个status,其中200代表正确,你每次返回给前端一个公共返回对象的String json形式,前端解析你的json,完事!

根据我们上边的说法,很容易就可以把这个公共返回类写出来了。。。

package com.imooc.grace.result;

/**
 *
 * @Title: JsonResult.java
 * @Package com.imooc.utils
 * @Description: 自定义响应数据结构
 * 				本类可提供给 H5/ios/安卓/公众号/小程序 使用
 * 				前端接受此类数据(json object)后,可自行根据业务去实现相关功能
 *
 * 				200:表示成功
 * 				500:表示错误,错误信息在msg字段中
 * 				501:bean验证错误,不管多少个错误都以map形式返回
 * 				502:拦截器拦截到用户token出错
 * 				555:异常抛出信息
 * 				556: 用户qq校验异常
 * 			    557: 校验用户是否在CAS登录,用户门票的校验
 * @Copyright: Copyright (c) 2020
 * @Company: www.imooc.com
 * @author 慕课网 - 风间影月
 * @version V1.0
 */
public class JsonResult {

    // 响应业务状态
    private Integer status;

    // 响应消息
    private String msg;

    // 响应中的数据
    private Object data;

    private String ok;	// 不使用

    public static JsonResult build(Integer status, String msg, Object data) {
        return new JsonResult(status, msg, data);
    }

    public static JsonResult build(Integer status, String msg, Object data, String ok) {
        return new JsonResult(status, msg, data, ok);
    }

    public static JsonResult ok(Object data) {
        return new JsonResult(data);
    }

    public static JsonResult ok() {
        return new JsonResult(null);
    }

    public static JsonResult errorMsg(String msg) {
        return new JsonResult(500, msg, null);
    }

    public static JsonResult errorUserTicket(String msg) {
        return new JsonResult(557, msg, null);
    }

    public static JsonResult errorMap(Object data) {
        return new JsonResult(501, "error", data);
    }

    public static JsonResult errorTokenMsg(String msg) {
        return new JsonResult(502, msg, null);
    }

    public static JsonResult errorException(String msg) {
        return new JsonResult(555, msg, null);
    }

    public static JsonResult errorUserQQ(String msg) {
        return new JsonResult(556, msg, null);
    }

    public JsonResult() {

    }

    public JsonResult(Integer status, String msg, Object data) {
        this.status = status;
        this.msg = msg;
        this.data = data;
    }

    public JsonResult(Integer status, String msg, Object data, String ok) {
        this.status = status;
        this.msg = msg;
        this.data = data;
        this.ok = ok;
    }

    public JsonResult(Object data) {
        this.status = 200;
        this.msg = "OK";
        this.data = data;
    }

    public Boolean isOK() {
        return this.status == 200;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public String getOk() {
        return ok;
    }

    public void setOk(String ok) {
        this.ok = ok;
    }

}

写完了用Controller返回一个我们的公共返回对象试试

img

成功!

其实不用把所有的错误方法写到一个公共返回类里,可以创建一个枚举类,然后让公共返回类去使用枚举类的数据,就可以解耦,也可以更优雅

GraceJsonResult

package result;

import java.util.Map;

/**
 * @version 1.0
 * @ClassName GraceJsonResult
 * @Description TODO
 * @Author 89255
 */
public class GraceJsonResult {
    // 响应业务状态码
    private Integer status;

    // 响应消息
    private String msg;

    // 是否成功
    private Boolean success;

    // 响应数据,可以是Object,也可以是List或Map等
    private Object data;

    /**
     * 成功返回,带有数据的,直接往OK方法丢data数据即可
     * @param data
     * @return
     */
    public static GraceJsonResult ok(Object data) {
        return new GraceJsonResult(data);
    }
    /**
     * 成功返回,不带有数据的,直接调用ok方法,data无须传入(其实就是null)
     * @return
     */
    public static GraceJsonResult ok() {
        return new GraceJsonResult(ResponseStatusEnum.SUCCESS);
    }
    public GraceJsonResult(Object data) {
        this.status = ResponseStatusEnum.SUCCESS.status();
        this.msg = ResponseStatusEnum.SUCCESS.msg();
        this.success = ResponseStatusEnum.SUCCESS.success();
        this.data = data;
    }


    /**
     * 错误返回,直接调用error方法即可,当然也可以在ResponseStatusEnum中自定义错误后再返回也都可以
     * @return
     */
    public static GraceJsonResult error() {
        return new GraceJsonResult(ResponseStatusEnum.FAILED);
    }

    /**
     * 错误返回,map中包含了多条错误信息,可以用于表单验证,把错误统一的全部返回出去
     * @param map
     * @return
     */
    public static GraceJsonResult errorMap(Map map) {
        return new GraceJsonResult(ResponseStatusEnum.FAILED, map);
    }

    /**
     * 错误返回,直接返回错误的消息
     * @param msg
     * @return
     */
    public static GraceJsonResult errorMsg(String msg) {
        return new GraceJsonResult(ResponseStatusEnum.FAILED, msg);
    }

    /**
     * 错误返回,token异常,一些通用的可以在这里统一定义
     * @return
     */
    public static GraceJsonResult errorTicket() {
        return new GraceJsonResult(ResponseStatusEnum.TICKET_INVALID);
    }

    /**
     * 自定义错误范围,需要传入一个自定义的枚举,可以到[ResponseStatusEnum.java[中自定义后再传入
     * @param responseStatus
     * @return
     */
    public static GraceJsonResult errorCustom(ResponseStatusEnum responseStatus) {
        return new GraceJsonResult(responseStatus);
    }
    public static GraceJsonResult exception(ResponseStatusEnum responseStatus) {
        return new GraceJsonResult(responseStatus);
    }

    public GraceJsonResult(ResponseStatusEnum responseStatus) {
        this.status = responseStatus.status();
        this.msg = responseStatus.msg();
        this.success = responseStatus.success();
    }
    public GraceJsonResult(ResponseStatusEnum responseStatus, Object data) {
        this.status = responseStatus.status();
        this.msg = responseStatus.msg();
        this.success = responseStatus.success();
        this.data = data;
    }
    public GraceJsonResult(ResponseStatusEnum responseStatus, String msg) {
        this.status = responseStatus.status();
        this.msg = msg;
        this.success = responseStatus.success();
    }

    public GraceJsonResult() {
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public Boolean getSuccess() {
        return success;
    }

    public void setSuccess(Boolean success) {
        this.success = success;
    }
}

ResposenEnum

package result;

/**
 * @version 1.0
 * @ClassName ResponseStatusEnum
 * @Description TODO
 * @Author 89255
 */
public enum  ResponseStatusEnum {

    SUCCESS(200, true, "操作成功!"),
    FAILED(500, false, "操作失败!"),

    // 50x
    UN_LOGIN(501,false,"请登录后再继续操作!"),
    TICKET_INVALID(502,false,"会话失效,请重新登录!"),
    NO_AUTH(503,false,"您的权限不足,无法继续操作!"),
    MOBILE_ERROR(504,false,"短信发送失败,请稍后重试!"),
    SMS_NEED_WAIT_ERROR(505,false,"短信发送太快啦~请稍后再试!"),
    SMS_CODE_ERROR(506,false,"验证码过期或不匹配,请稍后再试!"),
    USER_FROZEN(507,false,"用户已被冻结,请联系管理员!"),
    USER_UPDATE_ERROR(508,false,"用户信息更新失败,请联系管理员!"),
    USER_INACTIVE_ERROR(509,false,"请前往[账号设置]修改信息激活后再进行后续操作!"),
    FILE_UPLOAD_NULL_ERROR(510,false,"文件不能为空,请选择一个文件再上传!"),
    FILE_UPLOAD_FAILD(511,false,"文件上传失败!"),
    FILE_FORMATTER_FAILD(512,false,"文件图片格式不支持!"),
    FILE_MAX_SIZE_ERROR(513,false,"仅支持500kb大小以下的图片上传!"),
    FILE_NOT_EXIST_ERROR(514,false,"你所查看的文件不存在!"),
    USER_STATUS_ERROR(515,false,"用户状态参数出错!"),
    USER_NOT_EXIST_ERROR(516,false,"用户不存在!"),

    // 自定义系统级别异常 54x
    SYSTEM_INDEX_OUT_OF_BOUNDS(541, false, "系统错误,数组越界!"),
    SYSTEM_ARITHMETIC_BY_ZERO(542, false, "系统错误,无法除零!"),
    SYSTEM_NULL_POINTER(543, false, "系统错误,空指针!"),
    SYSTEM_NUMBER_FORMAT(544, false, "系统错误,数字转换异常!"),
    SYSTEM_PARSE(545, false, "系统错误,解析异常!"),
    SYSTEM_IO(546, false, "系统错误,IO输入输出异常!"),
    SYSTEM_FILE_NOT_FOUND(547, false, "系统错误,文件未找到!"),
    SYSTEM_CLASS_CAST(548, false, "系统错误,类型强制转换错误!"),
    SYSTEM_PARSER_ERROR(549, false, "系统错误,解析出错!"),
    SYSTEM_DATE_PARSER_ERROR(550, false, "系统错误,日期解析出错!"),

    // admin 管理系统 56x
    ADMIN_USERNAME_NULL_ERROR(561, false, "管理员登录名不能为空!"),
    ADMIN_USERNAME_EXIST_ERROR(562, false, "管理员登录名已存在!"),
    ADMIN_NAME_NULL_ERROR(563, false, "管理员负责人不能为空!"),
    ADMIN_PASSWORD_ERROR(564, false, "密码不能为空后者两次输入不一致!"),
    ADMIN_CREATE_ERROR(565, false, "添加管理员失败!"),
    ADMIN_PASSWORD_NULL_ERROR(566, false, "密码不能为空!"),
    ADMIN_NOT_EXIT_ERROR(567, false, "管理员不存在或密码错误!"),
    ADMIN_FACE_NULL_ERROR(568, false, "人脸信息不能为空!"),
    ADMIN_FACE_LOGIN_ERROR(569, false, "人脸识别失败,请重试!"),
    CATEGORY_EXIST_ERROR(570, false, "文章分类已存在,请换一个分类名!"),

    // 媒体中心 相关错误 58x
    ARTICLE_COVER_NOT_EXIST_ERROR(580, false, "文章封面不存在,请选择一个!"),
    ARTICLE_CATEGORY_NOT_EXIST_ERROR(581, false, "请选择正确的文章领域!"),
    ARTICLE_CREATE_ERROR(582, false, "创建文章失败,请重试或联系管理员!"),
    ARTICLE_QUERY_PARAMS_ERROR(583, false, "文章列表查询参数错误!"),
    ARTICLE_DELETE_ERROR(584, false, "文章删除失败!"),
    ARTICLE_WITHDRAW_ERROR(585, false, "文章撤回失败!"),
    ARTICLE_REVIEW_ERROR(585, false, "文章审核出错!"),
    ARTICLE_ALREADY_READ_ERROR(586, false, "文章重复阅读!"),

    // 人脸识别错误代码
    FACE_VERIFY_TYPE_ERROR(600, false, "人脸比对验证类型不正确!"),
    FACE_VERIFY_LOGIN_ERROR(601, false, "人脸登录失败!"),

    // 系统错误,未预期的错误 555
    SYSTEM_ERROR(555, false, "系统繁忙,请稍后再试!"),
    SYSTEM_OPERATION_ERROR(556, false, "操作失败,请重试或联系管理员"),
    SYSTEM_RESPONSE_NO_INFO(557, false, "");


    // 响应业务状态
    private Integer status;
    // 调用是否成功
    private Boolean success;
    // 响应消息,可以为成功或者失败的消息
    private String msg;

    ResponseStatusEnum(Integer status, Boolean success, String msg) {
        this.status = status;
        this.success = success;
        this.msg = msg;
    }

    public Integer status() {
        return status;
    }
    public Boolean success() {
        return success;
    }
    public String msg() {
        return msg;
    }
}

数据库的逆向生成

什么叫逆向生成呢。。我们知道当我们写业务代码的时候,通常要根据数据库的库来书写很多的包,service,controller,mapper,也会有很多的mybatis映射文件,这个逆向生成就帮我们省去了这些麻烦,会帮我们自动生成文件,十分便捷! 可以去了解一下mybatis-plus的generator,非常强大

首先将mybatis-gennerator-databases文件拷贝到目录下,这个其实可以去博客上找

结果拷贝过去一看,诶?怎么是黑色的,裂开

img

这个时候就可以打开idea旁边的maven,点击+号,然后在选中黑色的文件夹中的pom文件,idea就会帮我们处理好啦

img

然后修改一下generatorConfig-user.xml配置文件

主要使我们的url,和包名(如果你用的包名不一致是要修改的),我只修改了url图方便

最后点击UserGenerator的运行按钮,就自动生成了!真神奇!

img

点进去检查一下,发现属性和数据库中的字段都是一致的,区别就是数据库中是下划线,java是驼峰命名

整合mybatis

导入相关依赖

 <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql-connector-java.version}</version>
            </dependency>
            <!-- mybatis -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis-spring-boot-starter.version}</version>
            </dependency>
            <!-- 通用mapper逆向工具 -->
            <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>${mapper-spring-boot-starter.version}</version>
            </dependency>
            <!--pagehelper -->
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper-spring-boot-starter</artifactId>
                <version>${pagehelper-spring-boot-starter.version}</version>
            </dependency>

将逆向工程生成的pojo拷贝到Model里就好了,mapper放在user里,MyMapper的interface就放在存放接口的Api中(在mapper中的例如UserMqpper是实现MyMapper的)

在yml文件中配置数据源啥的

 datasource:                                         # 数据源的相关配置
    type: com.zaxxer.hikari.HikariDataSource          # 数据源类型:HikariCP    # mysql驱动
    url: jdbc:mysql://localhost:3306/mooc_project?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true
    username: root
    password: 123456
    hikari:
      connection-timeout: 30000       # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 默认:30秒
      minimum-idle: 5                 # 最小连接数
      maximum-pool-size: 20           # 最大连接数
      auto-commit: true               # 自动提交
      idle-timeout: 600000            # 连接超时的最大时长(毫秒),超时则被释放(retired),默认:10分钟
      pool-name: DateSourceHikariCP     # 连接池名字
      max-lifetime: 1800000           # 连接的生命时长(毫秒),超时而且没被使用则被释放(retired),默认:30分钟 1800000ms
      connection-test-query: SELECT 1
    jackson:
      date-format: yyyy-MM-dd HH:mm:ss
      time-zone: GMT+8
    driver-class-name: com.mysql.jdbc.Driver
mybatis:
  type-aliases-package: com.imooc.com.imooc.pojo          # 所有POJO类所在包路径
  mapper-locations: classpath:mapper/*.xml      # mapper映射文件

启动后发现报错,是因为没有加上mapperscan,没扫描到mapper接口,我们在启动类头上加mapperscan扫描我们的mapper接口所处的包就行了。。

整合swagger2

配置swagger配置类

package com.imooc.api.config;

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * @version 1.0
 * @ClassName Swagger2
 * @Description TODO
 * @Author 89255
 */
@Configuration
@EnableSwagger2
public class Swagger2 {

    //    http://localhost:8088/swagger-ui.html     原路径
    //    http://localhost:8088/doc.html            新路径

    // 配置swagger2核心配置 docket
    @Bean
    public Docket createRestApi() {
        Predicate<RequestHandler> adminPredicate = RequestHandlerSelectors.basePackage("com.imooc.admin.controller");
//        Predicate<RequestHandler> articlePredicate = RequestHandlerSelectors.basePackage("com.imooc.article.controller");
        Predicate<RequestHandler> userPredicate = RequestHandlerSelectors.basePackage("com.imooc.user.controller");
        Predicate<RequestHandler> filesPredicate = RequestHandlerSelectors.basePackage("com.imooc.files.controller");

        return new Docket(DocumentationType.SWAGGER_2)  // 指定api类型为swagger2
                .apiInfo(apiInfo())                 // 用于定义api文档汇总信息
                .select()
                .apis(Predicates.or(userPredicate, adminPredicate, filesPredicate))
//                .apis(Predicates.or(adminPredicate, articlePredicate, userPredicate, filesPredicate))
                .paths(PathSelectors.any())         // 所有controller
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("项目api")                       // 文档页标题
                .contact(new Contact("phm",
                        "https://blog.csdn.net/qq_46004291?spm=1001.2101.3001.5343",
                        "892552140@qq.com"))                   // 联系人信息
                .description("一个慕课网的项目")      // 详细信息
                .version("1.0.1")                               // 文档版本号
                .termsOfServiceUrl("https://blog.csdn.net/qq_46004291?spm=1001.2101.3001.5343")     // 网站地址
                .build();
    }
}

注意swagger测试的api,因为我们的controller的包是这样的com.imooc.user.controller下写我们的接口,这样的话我们就得写多个Predicate对象,因为我们不是controller包下分user,admin。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值