# wsy-plugins
**Repository Path**: wxquan/wsy-plugins
## Basic Information
- **Project Name**: wsy-plugins
- **Description**: 插件集合、Swagger枚举支持、Swagger扫描包处理、Validation枚举验证、Aop请求日志处理、Aop慢日志处理、Mvc统一返回结果处理。
- **Primary Language**: Java
- **License**: GPL-3.0
- **Default Branch**: master
- **Homepage**: https://www.wangshouyu.com
- **GVP Project**: No
## Statistics
- **Stars**: 24
- **Forks**: 4
- **Created**: 2022-01-06
- **Last Updated**: 2024-09-13
## Categories & Tags
**Categories**: logging
**Tags**: Swagger, MVC, aop, validation, Enum
## README
插件处理集合
## Maven dependency
[](http://mvnrepository.com/artifact/com.wangshouyu/wsy-plugins)
```xml
com.wangshouyu
wsy-plugins
${lastest.version}
```
## 慢方法日志
慢方法日志,指在方法执行时,超过设定的阈值,默认情况下系统自动触发打印warn级别的日志。日志执行内容为“执行方法名称,execTime:xxxms”。此应用实现原理通过AOP来进行扫描注解来实现哪些类进行打印慢方法日志。
### 启用慢方法日志
只需要在启动类上加@EnableSlowMethodAopLog即可
```java
@EnableSlowMethodAopLog
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
```
### 配置哪些方法打印慢方法日志
只要在要打印慢方法的类上加@AopSlowMethodLog即可
```java
@AopSlowMethodLog(value=3000,logLevel=LogLevel.ERROR,printLog=true)
@RestController
public class AopSlowLogController{
}
```
#### 方法执行时间设定
默认超过1000ms执行时间视为慢方法,独立设置超时时间`@AopSlowMethodLog(value=3000)`,如果在方法上加上`@AopSlowMethodLog(value=5000)`,那么判断标准会以5000ms来进行判断。
#### 方法打印日志级别
默认打印日志级别为warn,独立设置日志级别`@AopSlowMethodLog(logLevel=LogLevel.ERROR)`,如果在方法上加上`@AopSlowMethodLog(logLevel=LogLevel.INFO)`,那么打印标准会按照INFO来进行执行。
#### 方法关闭打印日志
默认加@AopSlowMethodLog系统会开启打印日志,可以通过设置`@AopSlowMethodLog(printLog=false)`来设定关闭打印日志,如果在方法上加上`@AopSlowMethodLog(printLog=true)`,那么这个类中的所有方法会仅有该方法打印日志。
## 请求日志
请求日志记录内容为请求方式、请求地址、请求参数、访问ip、请求方法信息等,实现方式通过检测@RestController来进行实现整体日志拦截功能。
### 请求日志开启
```java
@EnableRequestAopLog
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
```
#### 记录独立日志参数
需要在要记录的方法上添加@AopRequestLog注解。
```java
@AopRequestLog(args={"orderId"})
public String pay(String orderId, String uid){
return null;
}
```
以上方法设置直接展示出orderId的信息,并不会在日志中打印出uid信息。
#### 不记录返回值信息
```java
@AopRequestLog(printResult=flase)
public String pay(String orderId, String uid){
return null;
}
```
在需要设置的方法上添加printResult=false时,自动不执行记录返回结果。
#### 修改日志级别
```java
@AopRequestLog(logLevel=LogLevel.DEBUG)
public String pay(String orderId, String uid){
return null;
}
```
通过设置logLevel方式来进行设置日志等级打印。
#### 注意
当@AopRequestLog注解作用在类上时,只有logLevel,和printResult会生效。
### 同时开启访问日志和慢查询日志
```java
@EnableAopLog
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
```
### 自定义日志打印方式
现有默认的日志打印`DefaultLogPrint`来实现,可以通过实现LogPrint接口来实现自定义打印。
```java
public class MyLogPrint implements LogPrint {
@Override
public void request(LogLevel logLevel, Method method, Object[] arguments, String[] parameterNames) {
}
@Override
public void result(LogLevel logLevel, Object object) {
}
@Override
public void slow(LogLevel logLevel, String method, Long execTime) {
}
}
```
- request方法 请求日志
- result方法 响应结果日志
- slow方法 慢日志
## 统一返回结果
在传统的项目中,处理请求结果需要进行包装处理结果,对原始的代码有一定的入侵。通过mvc进行处理统一的返回结果,减少代码入侵,增强代码可读性!
### 快速入门
#### 启动统一返回结果
只需要在启动类上加@EnableResponseResult即可
```java
@EnableResponseResult
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
```
#### 配置哪些类需要使用统一返回结果
只要在要在类上加@ResponseBodyResult即可
```java
@ResponseBodyResult
@RestController
public class ResponseBodyResultController{
}
```
或者可以通过@RestResultControllerMapping注解来实现整体的返回结果,可以直接免去添加@RequestMapping和@RestController
```java
@RestResultControllerMapping("/mvc")
public class ResponseBodyResultController{
}
```
#### 指定方法返回统一结果
```java
@ResponseBodyResult
@GetMapping(value = "/hello")
public Map sayHello(){
Map map = new HashMap<>();
map.put("hello", "world");
return map;
}
```
### 自定义返回结果
`ResponseBodyResultHandler`为统一返回结果的处理接口,系统默认通过`DefaultResponseBodyResultHandler`类来进行实现统一返回结果。您可以自己实现`ResponseBodyResultHandler`接口来进行处理统一返回结果。
```java
/**
* @author 王守钰
* @date 2020年11月20日 13:57
* @description 默认响应结果处理器
*/
public class DefaultResponseBodyResultHandler implements ResponseBodyResultHandler{
@Override
public Object handle(Object body) {
// 重复包装判断
if(body instanceof DefaultResponseResult || body instanceof String){
return body;
}
return DefaultResponseResult.success(body);
}
}
```
#### 默认统一返回结果包装类
```java
public class DefaultResponseResult implements Serializable {
/**
* 响应数据
*/
private T data;
/**
* 响应消息
*/
private String message;
/**
* 响应码
*/
private Integer code;
/**
* 成功状态码
*/
public static final Integer SUCCESS_CODE = 200;
/**
* 成功消息
*/
public static final String SUCCESS_MESSAGE = "success";
/**
* 失败状态码
*/
public static final Integer FAIL_CODE = 500;
/**
* 失败消息
*/
public static final String FAIL_MESSAGE = "fail";
public DefaultResponseResult(T data, String message, Integer code) {
this.data = data;
this.message = message;
this.code = code;
}
public DefaultResponseResult() {
}
public static DefaultResponseResult success(T data) {
return new DefaultResponseResult(data, SUCCESS_MESSAGE, SUCCESS_CODE);
}
public static DefaultResponseResult fail(T data) {
return new DefaultResponseResult(data, FAIL_MESSAGE, FAIL_CODE);
}
// …… getter setter 省略
}
```
#### 排除包装结果
```java
if(body instanceof DefaultResponseResult){
return body;
}
```
#### 排除默认返回String字符串
系统默认情况下会使用`AbstractMessageConverterMethodProcessor`类中的`writeWithMessageConverters`方法来进行处理返回结果。当处理字符串时,系统默认会使用`StringHttpMessageConverter`来实现转换。当系统调用到下面这行代码时
```java
body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType,
(Class extends HttpMessageConverter>>) converter.getClass(),
inputMessage, outputMessage);
```
系统会将body的类型变为我们自定的包装类,这时就不是String类型了,所以处理的时候会报数据类型转换错误。如果非要转换返回String数据为包装类型的话可以考虑重写`AbstractMessageConverterMethodProcessor`类中的`writeWithMessageConverters`方法,或者在mvc启动时候排除`StringHttpMessageConverter`,如果排除了StringHttpMessageConverter,默认情况下使用jackson的convert会导致字符串加上双引号也需要具体处理。
## Swagger枚举插件
swagger解决了java文档标识的问题,但是在处理枚举交互的过程中并不能完全展示出key-value的结构,前后端交互带来麻烦,需要手动进行添加处理,这样对开发的成本进行增加。所以开发swagger的插件来解决前后端交互问题,以及减小开发的成本。
### 使用方法
枚举类
```java
public enum MyEnum{
HI("HI","您好"),
BYE("BYE","再见"),
;
@Getter
String desc;
@Getter
String code;
MyEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
}
```
实体类
```java
@Data
public class MyEntity{
/**
* 订单状态
*/
@SwaggerDisplayEnum(key = "code",value = "desc", clazz = MyEnum.class)
@ApiModelProperty(value = "朋友状态", example = "HI", allowableValues ="HI,BYE", required = true)
private String status;
}
```
### 注意
`SwaggerDisplayEnum`注解中的`key`代表的就是展示的`key`;`value`对应的是展示的值信息;`clazz`对应的是枚举对象,其中`key`,`value`对应的枚举中的列信息。
### 关闭插件
```yml
swagger:
plugin:
enum-support: false
```
## Swagger版本信息插件
开发swagger接口某些字段,或者某个接口并不能标识从某一个版本开始进行使用,所以新增版本字段,来实现版本的信息展示。
### 版本插件使用方法
接口使用
```java
@PostMapping(value = "/myData")
@ApiVersion(value = "v1.2")
@ApiOperation(value = "查询我的数据")
public Response data(@Valid @RequestBody QueryData query){
return Response.ok().body(dataService.data(query));
}
```
字段使用
```java
@Data
public class MyEntity{
/**
* 订单状态
*/
@ApiVersion(value = "v1.2")
@ApiModelProperty(value = "朋友状态", example = "HI", allowableValues ="HI,BYE", required = true)
private String status;
}
```
### 版本插件注意
版本的值,可以封装到具体的常量中进行维护,这样的话就能保证版本的数据对其。
### 关闭版本插件
```yml
swagger:
plugin:
version-support: false
```