<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.7.6version>
<relativePath/>
parent>
<groupId>com.bubagroupId>
<artifactId>WeChatMiNiartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>WeChatMiNiname>
<description>WeChatMiNidescription>
<properties>
<java.version>13java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-amqpartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-mailartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-quartzartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>3.0.0version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>com.mysqlgroupId>
<artifactId>mysql-connector-jartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.2.15version>
dependency>
<dependency>
<groupId>com.auth0groupId>
<artifactId>java-jwtartifactId>
<version>3.3.0version>
dependency>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-spring-boot-starterartifactId>
<version>1.5.3version>
dependency>
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.0.7version>
dependency>
<dependency>
<groupId>com.google.zxinggroupId>
<artifactId>coreartifactId>
<version>3.4.0version>
dependency>
<dependency>
<groupId>com.google.zxinggroupId>
<artifactId>javaseartifactId>
<version>3.4.0version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-aopartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpclientartifactId>
<version>4.5.2version>
dependency>
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpcoreartifactId>
<version>4.4.5version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
exclude>
excludes>
configuration>
plugin>
plugins>
build>
project>
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3307/WeChatMiNi?useUnicode=true&serverTimezone=Asia/Shanghai
username: root
password: 123456
initial-size: 8
max-active: 16
min-idle: 8
max-wait: 60000
test-while-idle: true
test-on-borrow: false
test-on-return: false
data:
redis:
database: 0
host: localhost
port: 6379
password:
jedis:
pool:
max-active: 1000
max-wait: -1ms
max-idle: 16
min-idle: 8
main:
allow-bean-definition-overriding: true
mybatis:
mapper-locations: classpath*:mappers/*.xml
type-aliases-package: com.buba.wechatmini.pojo
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #输出日志规则
map-underscore-to-camel-case: true #支持驼峰命名
logging:
level:
root: info
com.example.emos.wx.db.dao : warn
pattern:
console: "%d{HH:mm:ss} %-5level %msg%n"
WeChatMiNi:
jwt:
#密钥
secret: buba123456
#令牌期时间
expire: 7
#令牌缓存时间(天)
cache-expire: 10
mybatis:
mapper-locations: classpath*:mappers/*.xml
type-aliases-package: com.buba.wechatmini.pojo
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #输出日志规则
map-underscore-to-camel-case: true #支持驼峰命名
logging:
level:
root: info
com.example.emos.wx.db.dao : warn
pattern:
console: "%d{HH:mm:ss} %-5level %msg%n"
因为后台Java项目是Web工程,所以有异常消息,我们要在原有异常消息的基础之上,封装状态
码,所以需要我们自己创建一个异常类。
自定义异常类继承的父类,我没有选择Exception。因为Exception类型的异常,我们必须要手动
显式处理,要么上抛,要么捕获。我希望我定义的异常采用既可以采用显式处理,也可以隐式处
理,所以我选择继承RuntimeException这个父类。RuntimeException类型的异常可以被虚拟机隐
式处理,这样就省去了我们很多手动处理异常的麻烦。
package com.buba.wechatmini.exception;
/**
* @author qlx
*/
public class WechatminiException extends RuntimeException{
private String msg;
private int code = 500;
public WechatminiException(String msg) {
super(msg);
this.msg = msg;
}
public WechatminiException(String msg, Throwable e) {
super(msg, e);
this.msg = msg;
}
public WechatminiException(String msg, int code) {
super(msg);
this.msg = msg;
this.code = code;
}
public WechatminiException(String msg, int code, Throwable e) {
super(msg, e);
this.msg = msg;
this.code = code;
}
}
虽然SpringMVC的Controller可以自动把对象转换成JSON返回给客户端,但是我们需要制定一个
统一的标准,保证所有Controller返回的数据格式一致。最简便的办法就是定义封装类,来统一封
装返回给客户端的数据。
修改 pom.xml 文件,添加依赖库。 Apache 的 httpcomponents 库里面的 HttpStatus 类封装了
很多状态码,所以我们在Web返回对象中封装状态吗,可以用到这些状态码。
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpcoreartifactId>
<version>4.4.13version>
dependency>
package com.buba.wechatmini.common.utils;
import org.apache.http.HttpStatus;
import java.util.HashMap;
import java.util.Map;
/**
* @author qlx
*/
public class Result extends HashMap<String, Object> {
public Result() {
put("code", HttpStatus.SC_OK);
put("msg", "success");
}
public static Result error() {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
}
public static Result error(String msg) {
return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
}
public static Result error(int code, String msg) {
Result r = new Result();
r.put("code", code);
r.put("msg", msg);
return r;
}
public static Result ok(String msg) {
Result r = new Result();
r.put("msg", msg);
return r;
}
public static Result ok(Map<String, Object> map) {
Result r = new Result();
r.putAll(map);
return r;
}
public static Result ok() {
return new Result();
}
@Override
public Result put(String key, Object value) {
super.put(key, value);
return this;
}
}
开发前后端分离架构的项目,往往调试后端Web接口需要用到POSTMAN工具。虽然POSTMAN
工具的功能非常强大,但是请求参数很多的情况下,我们手写这些参数和数据还是非常麻烦的。
因此我们需要一个调试后端Web接口更加简便的方法。恰好Swagger提供了REST API调用方
式,我们不需要借助任何工具的情况下,访问Swagger页面,就可以对Web接口进行调用和调
试,这种调试方式的效率要远超POSTMAN软件。
在 pom.xml 文件中添加Swagger依赖库,这里我们使用的是Swagger2版本,在UI方面,比
Swagger1版本要好看很多。
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>2.9.2version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger-uiartifactId>
<version>2.9.2version>
dependency>
package com.buba.wechatmini.common.utils;
/**
* @author qlx
*/
import io.swagger.annotations.ApiOperation;
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.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.ApiSelectorBuilder;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
Docket docket = new Docket(DocumentationType.SWAGGER_2);
// ApiInfoBuilder 用于在Swagger界面上添加各种信息
ApiInfoBuilder builder = new ApiInfoBuilder();
builder.title("BUBA在线办公系统");
ApiInfo apiInfo = builder.build();
docket.apiInfo(apiInfo);
// ApiSelectorBuilder 用来设置哪些类中的方法会生成到REST API中
ApiSelectorBuilder selectorBuilder = docket.select();
selectorBuilder.paths(PathSelectors.any()); //所有包下的类
//使用@ApiOperation的方法会被提取到REST API中
selectorBuilder.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class));
docket = selectorBuilder.build();
/*
* 下面的语句是开启对JWT的支持,当用户用Swagger调用受JWT认证保护的方法,
* 必须要先提交参数(例如令牌)
*/
//存储用户必须提交的参数
List<ApiKey> apikey = new ArrayList();
//规定用户需要输入什么参数
apikey.add(new ApiKey("token", "token", "header"));
docket.securitySchemes(apikey);
//如果用户JWT认证通过,则在Swagger中全局有效
AuthorizationScope scope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] scopeArray = {scope};
//存储令牌和作用域
SecurityReference reference = new SecurityReference("token", scopeArray);
List refList = new ArrayList();
refList.add(reference);
SecurityContext context =
SecurityContext.builder().securityReferences(refList).build();
List cxtList = new ArrayList();
cxtList.add(context);
docket.securityContexts(cxtList);
return docket;
}
}
Springboot2.6以后将SpringMVC 默认路径匹配策略从AntPathMatcher 更改为PathPatternParser,导致出错如下:
ERROR Application run failed org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
解决上述问题需要application.yml配置如下
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
package com.buba.wechatmini.controller;
import com.buba.wechatmini.common.utils.JwtUtil;
import com.buba.wechatmini.common.utils.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
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.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
/**
* @author qlx
*/
@RestController
@RequestMapping("/test")
@Api("测试Web接口")
public class TestController {
@Autowired
private JwtUtil jwtUtil;
@ApiOperation("最简单的测试方法")
@GetMapping("/get1")
public Result get1(){
Map map = new HashMap();
map.put("msa","aaaaaaa");
return Result.ok(map);
}
@RequestMapping(value = "/getToken",method = RequestMethod.OPTIONS)
public Result getToken() throws UnsupportedEncodingException {
Map map = new HashMap();
map.put("token",jwtUtil.createToken(123));
return Result.ok(map);
}
}
浏览器访问地址:http://127.0.0.1:8080/swagger-ui.html