# 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 [![Maven Central](https://img.shields.io/maven-central/v/com.wangshouyu/wsy-plugins.svg)](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>) 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 ```