MP实战系列(八)之SpringBoot+Swagger2
SpringBoot一个原则,爱好编程的朋友们都知道,那就是"习惯优于配置"。
今天一上来主要说的还是代码,个人比较喜欢来的实战系列的,不过有的时候还是比较偏重于理论,理论是造轮子的基础之一,尽管前人先辈们或者其他编程界的大牛们已经为我们造了不少轮子,大牛们造的轮子在广义上是比较通用的,例如jeecg的插件式开发等。
不过对于项目需求而言,有些时候不一定开源的就一定可以复用,有些时候我们必须要在此创新。
记得我一个朋友,他们公司给他的一个业务是测试框架,该测试框架必须匹配公司各个业务场景,他在开源上找了不少项目,但是发现还是不行,有些只能解解燃眉之急,但是风险不可控。所以我这位朋友他决定为了更好的匹配公司的业务,他决定自己造轮子,不过当然还是站在前人的肩膀上。他用技术还是Java的反射和Google的一个技术,记得我跟我提过,不过此时我不记得了。
最终他还是成功造轮子,在这里我想表达的不是,造轮子,对于现有的轮子,如果我要采用必先满足我个人这些要求:
(1)文档丰富;
(2)开源项目活跃;
(3)风险可控;
(4)学习成本低;
当然最主要的是前三项,当然如果是开发赶进度的话,第四项不得不考虑进来。
毕竟一项技术,一个团队再用,如果学习成本毕竟高的话,到时项目遇到各种各样的问题,光解决问题就会花不少时间。
前三项就不用特别说了,文档丰富,例如Spring文档就很丰富。活跃,项目活跃至少可以和开源项目的开发人员进行交流。风险可控,对于企业而言,风险不可控意味着非常大的隐患,特别是金融方面的。
闲话不多说了,下面贴代码:
一、导入依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | < 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"> < modelVersion >4.0.0</ modelVersion > < groupId >cn.blog</ groupId > < artifactId >blog001</ artifactId > < version >0.0.1-SNAPSHOT</ version > < packaging >war</ packaging > < parent > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-parent</ artifactId > < version >1.5.9.RELEASE</ version > </ parent > < repositories > <!--阿里云仓库--> < repository > < id >aliyun</ id > < url >http://maven.aliyun.com/nexus/content/groups/public/</ url > </ repository > <!--快照版本使用,正式版本无需添加此仓库--> < repository > < id >snapshots</ id > < url >https://oss.sonatype.org/content/repositories/snapshots/</ url > </ repository > </ repositories > < properties > < project.build.sourceEncoding >UTF-8</ project.build.sourceEncoding > < maven.compiler.source >1.8</ maven.compiler.source > < maven.compiler.target >1.8</ maven.compiler.target > < mybatis-plus-boot-starter.version >2.1.9</ mybatis-plus-boot-starter.version > < mybatisplus.version >2.1.8</ mybatisplus.version > < HikariCP.version >2.4.13</ HikariCP.version > < fastjson.version >1.2.39</ fastjson.version > < druid.version >1.1.0</ druid.version > </ properties > < dependencies > <!-- shiro --> < dependency > < groupId >org.apache.shiro</ groupId > < artifactId >shiro-core</ artifactId > < version >1.2.2</ version > </ dependency > <!-- shiro+spring --> < dependency > < groupId >org.apache.shiro</ groupId > < artifactId >shiro-spring</ artifactId > < version >1.3.2</ version > </ dependency > <!-- swagger-ui相关 --> < dependency > < groupId >io.springfox</ groupId > < artifactId >springfox-swagger2</ artifactId > < version >2.2.2</ version > </ dependency > < dependency > < groupId >io.springfox</ groupId > < artifactId >springfox-swagger-ui</ artifactId > < version >2.2.2</ version > </ dependency > <!-- slf4j --> < dependency > < groupId >org.slf4j</ groupId > < artifactId >slf4j-api</ artifactId > < version >1.7.19</ version > </ dependency > <!-- Druid --> < dependency > < groupId >com.alibaba</ groupId > < artifactId >druid</ artifactId > < version >${druid.version}</ 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-tomcat</ artifactId > < scope >provided</ scope > </ dependency > < dependency > < groupId >org.apache.tomcat.embed</ groupId > < artifactId >tomcat-embed-jasper</ artifactId > < scope >provided</ scope > </ dependency > < dependency > < groupId >com.zaxxer</ groupId > < artifactId >HikariCP-java7</ artifactId > < version >${HikariCP.version}</ version > </ dependency > < dependency > < groupId >com.alibaba</ groupId > < artifactId >fastjson</ artifactId > < version >${fastjson.version}</ version > </ dependency > <!-- mybatis-plus begin --> < dependency > < groupId >com.baomidou</ groupId > < artifactId >mybatis-plus-boot-starter</ artifactId > < version >${mybatis-plus-boot-starter.version}</ version > < exclusions > < exclusion > < artifactId >tomcat-jdbc</ artifactId > < groupId >org.apache.tomcat</ groupId > </ exclusion > </ exclusions > </ dependency > <!-- mybatis-plus end --> <!-- JUnit test dependency --> < dependency > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-starter-test</ artifactId > < scope >test</ scope > </ dependency > < dependency > < groupId >com.jayway.restassured</ groupId > < artifactId >rest-assured</ artifactId > < version >2.9.0</ version > < scope >test</ scope > </ dependency > <!-- Code generator test sample--> < dependency > < groupId >org.apache.velocity</ groupId > < artifactId >velocity</ artifactId > < version >1.7</ version > < scope >test</ scope > </ dependency > < dependency > < groupId >mysql</ groupId > < artifactId >mysql-connector-java</ artifactId > < version >5.1.21</ version > </ dependency > </ dependencies > < build > < plugins > < plugin > < groupId >org.springframework.boot</ groupId > < artifactId >spring-boot-maven-plugin</ artifactId > </ plugin > </ plugins > </ build > </ project > |
二、编写Java代码
Application.java 启动类
package com.blog.springboot; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.Banner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.transaction.annotation.EnableTransactionManagement; @EnableTransactionManagement @SpringBootApplication public class Application { protected final static Logger logger = LoggerFactory.getLogger(Application.class); public static void main(String[] args) { SpringApplication app = new SpringApplication(Application.class); app.setBannerMode(Banner.Mode.OFF); app.run(args); logger.info("Application is success!"); } }
MyMetaObjectHandler.java
package com.blog.springboot; import com.baomidou.mybatisplus.mapper.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 注入公共字段自动填充,任选注入方式即可 */ //@Component public class MyMetaObjectHandler extends MetaObjectHandler { protected final static Logger logger = LoggerFactory.getLogger(Application.class); @Override public void insertFill(MetaObject metaObject) { logger.info("新增"); } @Override public void updateFill(MetaObject metaObject) { logger.info("更新"); } }
MybatisPlusConfig.java(扫描Mapper文件)
package com.blog.springboot.config; import java.util.ArrayList; import java.util.List; import com.baomidou.mybatisplus.incrementer.H2KeyGenerator; import com.baomidou.mybatisplus.incrementer.IKeyGenerator; import com.baomidou.mybatisplus.mapper.ISqlInjector; import com.baomidou.mybatisplus.mapper.LogicSqlInjector; import com.baomidou.mybatisplus.mapper.MetaObjectHandler; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.baomidou.mybatisplus.plugins.PaginationInterceptor; import com.baomidou.mybatisplus.plugins.PerformanceInterceptor; import com.baomidou.mybatisplus.plugins.parser.ISqlParser; import com.baomidou.mybatisplus.plugins.parser.tenant.TenantHandler; import com.baomidou.mybatisplus.plugins.parser.tenant.TenantSqlParser; import com.blog.springboot.MyMetaObjectHandler; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.LongValue; @Configuration @MapperScan("com.blog.springboot.mapper*") public class MybatisPlusConfig { /** * mybatis-plus SQL执行效率插件【生产环境可以关闭】 */ @Bean public PerformanceInterceptor performanceInterceptor() { return new PerformanceInterceptor(); } @Bean public MetaObjectHandler metaObjectHandler(){ return new MyMetaObjectHandler(); } /** * 注入主键生成器 */ @Bean public IKeyGenerator keyGenerator(){ return new H2KeyGenerator(); } /** * 注入sql注入器 */ @Bean public ISqlInjector sqlInjector(){ return new LogicSqlInjector(); } }
Swagger2.java
package com.blog.springboot.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 public class Swagger2 { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.blog.springboot")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("博客系统") .description("世界因编程而美好,编程改变世界") .termsOfServiceUrl("http://520.cn") .contact("yy") .version("1.0") .build(); } }
WebConfig.java
package com.blog.springboot.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.InternalResourceViewResolver; /** * <p> * WEB 初始化相关配置 * </p> */ @ControllerAdvice @Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Bean public ViewResolver getViewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/view/"); resolver.setSuffix(".jsp"); return resolver; } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { //将所有/static/** 访问都映射到classpath:/static/ 目录下 registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); } }
UserEntity.java
package com.blog.springboot.entity; import java.io.Serializable; import com.baomidou.mybatisplus.activerecord.Model; import com.baomidou.mybatisplus.annotations.TableField; import com.baomidou.mybatisplus.annotations.TableId; import com.baomidou.mybatisplus.annotations.TableName; import com.baomidou.mybatisplus.enums.IdType; /** * <p> * * </p> * * @author youcong123 * @since 2018-05-19 */ @TableName("user") public class UserEntity extends Model<UserEntity> { /** * 用户ID */ @TableId(value = "user_id", type = IdType.AUTO) private Integer user_id; /** * 用户名 */ private String username; /** * 性别 */ private Integer sex; /** * 电话 */ private String phone; /** * 密码 */ private String password; /** * 等级 */ private Integer level; /** * 用户创建时间 */ @TableField("create_time") private String createTime; /** * 邮箱 */ private String email; /** * 登录标识 */ private Integer logo; /** * 登录时间 */ @TableField("login_time") private String loginTime; public Integer getUserId() { return user_id; } public void setUserId(Integer user_id) { this.user_id = user_id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Integer getSex() { return sex; } public void setSex(Integer sex) { this.sex = sex; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getLevel() { return level; } public void setLevel(Integer level) { this.level = level; } public String getCreateTime() { return createTime; } public void setCreateTime(String createTime) { this.createTime = createTime; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Integer getLogo() { return logo; } public void setLogo(Integer logo) { this.logo = logo; } public String getLoginTime() { return loginTime; } public void setLoginTime(String loginTime) { this.loginTime = loginTime; } @Override public String toString() { return "User{" + "userId=" + user_id + ", username=" + username + ", sex=" + sex + ", phone=" + phone + ", password=" + password + ", level=" + level + ", createTime=" + createTime + ", email=" + email + ", logo=" + logo + ", loginTime=" + loginTime + "}"; } @Override protected Serializable pkVal() { // TODO Auto-generated method stub return this.user_id; } }
UserDao.java
package com.blog.springboot.mapper; import com.blog.springboot.entity.UserEntity; import com.baomidou.mybatisplus.mapper.BaseMapper; /** * <p> * Mapper 接口 * </p> * * @author youcong123 * @since 2018-05-19 */ public interface UserDao extends BaseMapper<UserEntity> { }
UserService.java
package com.blog.springboot.service; import com.blog.springboot.entity.UserEntity; import com.baomidou.mybatisplus.service.IService; /** * <p> * 服务类 * </p> * * @author youcong123 * @since 2018-05-19 */ public interface UserService extends IService<UserEntity> { }
UserServiceImpl.java
package com.blog.springboot.service.impl; import com.blog.springboot.entity.UserEntity; import com.blog.springboot.mapper.UserDao; import com.blog.springboot.service.UserService; import com.baomidou.mybatisplus.service.impl.ServiceImpl; import org.springframework.stereotype.Service; /** * <p> * 服务实现类 * </p> * * @author youcong123 * @since 2018-05-19 */ @Service public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService { }
UserController.java
package com.blog.springboot.controller; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.alibaba.fastjson.JSON; import com.blog.springboot.entity.UserEntity; import com.blog.springboot.service.UserService; import io.swagger.annotations.ApiOperation; /** * <p> * 前端控制器 * </p> * * @author youcong123 * @since 2018-05-19 */ @Controller @RequestMapping("/user") public class UserController { @GetMapping(value="/test") public String index() { return "index"; } @Autowired private UserService userService; @ApiOperation(value="获取用户列表", notes="") @GetMapping(value="/list",produces="application/json;charset=utf-8") @ResponseBody public String list(Map<String,Object> map) { List<UserEntity> list = userService.selectList(null); map.put("list", list); return JSON.toJSONString(map); } }
UserDao.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.blog.springboot.mapper.UserDao">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.blog.springboot.entity.UserEntity">
<id column="user_id" property="user_id" />
<result column="username" property="username" />
<result column="sex" property="sex" />
<result column="phone" property="phone" />
<result column="password" property="password" />
<result column="level" property="level" />
<result column="create_time" property="createTime" />
<result column="email" property="email" />
<result column="logo" property="logo" />
<result column="login_time" property="loginTime" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
user_id AS userId, username, sex, phone, password, level, create_time AS createTime, email, logo, login_time AS loginTime
</sql>
</mapper>
三、编写配置文件
application.yml
#app server: port: 8080 spring: devtools: restart: enabled: false datasource: url: jdbc:mysql://localhost:3306/blog?autoReconnect=true&useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false username: root password: 1234 db-name: blog filters: log4j,wall,mergeStat1 #mybatis mybatis-plus: mapper-locations: classpath:/mapper/*Dao.xml #实体扫描,多个package用逗号或者分号分隔 typeAliasesPackage: com.blog.springboot.entity global-config: #主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID"; id-type: 2 #字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断" field-strategy: 2 #驼峰下划线转换 db-column-underline: true #刷新mapper 调试神器 refresh-mapper: true #数据库大写下划线转换 #capital-mode: true #逻辑删除配置(下面3个配置) logic-delete-value: 0 logic-not-delete-value: 1 #自定义sql注入器,不在推荐使用此方式进行配置,请使用自定义bean注入 sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector #自定义填充策略接口实现,不在推荐使用此方式进行配置,请使用自定义bean注入 meta-object-handler: com.blog.springboot.MyMetaObjectHandler #自定义SQL注入器 #sql-injector: com.baomidou.springboot.xxx # SQL 解析缓存,开启后多租户 @SqlParser 注解生效 sql-parser-cache: true configuration: map-underscore-to-camel-case: true cache-enabled: false #logging logging: level: warn
四、添加swagger-ui相关界面
swagger-ui界面可以去github下载,地址为:https://github.com/swagger-api/swagger-ui
我个人下载的是如上红色标记处,最新版
下载完毕后将其解压,并在dist目录的所有文件放置在static文件夹下的swagger-ui文件夹下
五、启动Application,访问
swagger界面
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述