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

2023-11-08 18:10

本文主要是介绍慕课项目开工!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:#访问端口8003port: 8003tomcat:#tomcat字符集UTF8uri-encoding: UTF-8#禁用,如果不禁用tomcat默认超过2M大小的文件不获取max-swallow-size: -1#配置项目信息
spring:application:name: service-userjackson:date-format: yyyy-MM-dd HH:mm:sstime-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, "操作失败!"),// 50xUN_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,"用户不存在!"),// 自定义系统级别异常 54xSYSTEM_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 管理系统 56xADMIN_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, "文章分类已存在,请换一个分类名!"),// 媒体中心 相关错误 58xARTICLE_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, "人脸登录失败!"),// 系统错误,未预期的错误 555SYSTEM_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=trueusername: rootpassword: 123456hikari: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分钟 1800000msconnection-test-query: SELECT 1jackson:date-format: yyyy-MM-dd HH:mm:sstime-zone: GMT+8driver-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@Beanpublic 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。

这篇关于慕课项目开工!part2:后端架构 (更新中。。。。)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/371598

相关文章

mybatis的整体架构

mybatis的整体架构分为三层: 1.基础支持层 该层包括:数据源模块、事务管理模块、缓存模块、Binding模块、反射模块、类型转换模块、日志模块、资源加载模块、解析器模块 2.核心处理层 该层包括:配置解析、参数映射、SQL解析、SQL执行、结果集映射、插件 3.接口层 该层包括:SqlSession 基础支持层 该层保护mybatis的基础模块,它们为核心处理层提供了良好的支撑。

百度/小米/滴滴/京东,中台架构比较

小米中台建设实践 01 小米的三大中台建设:业务+数据+技术 业务中台--从业务说起 在中台建设中,需要规范化的服务接口、一致整合化的数据、容器化的技术组件以及弹性的基础设施。并结合业务情况,判定是否真的需要中台。 小米参考了业界优秀的案例包括移动中台、数据中台、业务中台、技术中台等,再结合其业务发展历程及业务现状,整理了中台架构的核心方法论,一是企业如何共享服务,二是如何为业务提供便利。

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

hdu1689(线段树成段更新)

两种操作:1、set区间[a,b]上数字为v;2、查询[ 1 , n ]上的sum 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdl

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

AI行业应用(不定期更新)

ChatPDF 可以让你上传一个 PDF 文件,然后针对这个 PDF 进行小结和提问。你可以把各种各样你要研究的分析报告交给它,快速获取到想要知道的信息。https://www.chatpdf.com/