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

 

posted @   挑战者V  阅读(2174)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示