最近项目收获
1、Web消息格式
前言
在Web项目开发中,我们都会和前端约定好,消息转换格式,便利于项目消息传输与使用,在此之前,我都是使用统一消息格式的类对象进行消息转换,而这次使用ResponseBodyAdvice接口,及逆行消息格式自动转换,并且自定义注解,在加上注解的类上或者是方法上,可以不进行消息类型的转换
ResponseBodyAdvice的使用
ResponseBodyAdvice接口和RequestBodyAdvice接口类似, RequestBodyAdvice是请求到Controller之前拦截,做相应的处理操作, 而ResponseBodyAdvice是对Controller返回的{@code @ResponseBody}or a {@code ResponseEntity}
后,{@code HttpMessageConverter}
类型转换之前拦截, 进行相应的处理操作后,再将结果返回给客户端.
源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public interface ResponseBodyAdvice<T> {
boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType);
@Nullable T beforeBodyWrite(@Nullable T body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response);
}
|
步骤
首先,制作统一返回消息格式
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
| package comm.xss.coupon.vo;
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data @NoArgsConstructor @AllArgsConstructor public class CommonResponse<T> implements Serializable {
private Integer code; private String msg; private T data;
public CommonResponse(Integer code, String msg) { this.code = code; this.msg = msg; } }
|
自定义注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package comm.xss.coupon.annotation;
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface IgnoreResponseAdvice { }
|
其次,实现ResponseBodyAdvice接口
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
| package comm.xss.coupon.advice;
import comm.xss.coupon.annotation.IgnoreResponseAdvice; import comm.xss.coupon.vo.CommonResponse; import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpResponse; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
@RestControllerAdvice @SuppressWarnings("all") public class CommonResponseDataAdvice implements ResponseBodyAdvice<Object> {
@Override public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
if (methodParameter.getDeclaringClass().isAnnotationPresent( IgnoreResponseAdvice.class )) { return false; }
if (methodParameter.getMethod().isAnnotationPresent( IgnoreResponseAdvice.class )) { return false; }
return true; }
@Override public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { CommonResponse<Object> response = new CommonResponse<>( 0, "" );
if (o == null) { return response; } else if (o instanceof CommonResponse) { response = (CommonResponse<Object>) o; } else { response.setData(o); }
return response; } }
|
2、全局异常处理,在Web消息格式的基础上
1、自定义异常
1 2 3 4 5 6 7 8 9 10 11
| package comm.xss.coupon.exception;
public class CouponException extends Exception {
public CouponException(String exception) { super(exception); } }
|
2、设置异常捕捉方法
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
| package comm.xss.coupon.advice;
import comm.xss.coupon.exception.CouponException; import comm.xss.coupon.vo.CommonResponse; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
import static comm.xss.coupon.businessenum.ExceptionEnum.CouponExceptionEnum;
@RestControllerAdvice public class GlobalExceptionAdvice {
@ExceptionHandler(CouponException.class) public CommonResponse<String> handlerCouponException( HttpServletRequest request, CouponException e ) { CommonResponse<String> commonResponse = new CommonResponse<>( CouponExceptionEnum.getCode(), CouponExceptionEnum.getMsg() );
commonResponse.setData(e.getMessage());
return commonResponse; } }
|
3、mybatis plus 在自定义序列化转换器
前言
例如、在我们实体类中,想要从java程序序列化到数据库,或者从数据库序列化到java程序,有些字段类型是我们java中自定义的类型,然后序列化到数据库,我们需要进行类型的转化,或者从数据库序列化到java程序,但是类型不匹配,下面就需要我们使用类型转换器了。
1、加注解
在@TableName上面,开启自动化返回结果
加上**@TableFild(typehandler = "类型转换器")
**
可以使用自己引入jar包的json转换器,例如fastjson的类型转换器,也可以自定义类型转换器
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
| @Data @NoArgsConstructor @AllArgsConstructor @TableName(value = "coupon_template", autoResultMap = true) @JsonSerialize(using = CouponTemplateSerialize.class) public class CouponTemplate implements Serializable { @TableField(exist = false) private static final long serialVersionUID = 1L;
@TableField(value = "product_line",typeHandler = ProductLineConverter.class) private ProductLine productLine;
@TableField(typeHandler = DistributeTargetConverter.class) private DistributeTarget target;
@TableField(value = "rule",typeHandler = FastjsonTypeHandler.class) private TemplateRule rule;
}
|
2、自定义类型转换器
实现TypeHandler接口,实现里面的方法,进行转换
加注解、需要加上两个注解,一个是标注数据库需要转换的类型,二是java程序中的类型
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
| package com.xss.coupon.converter;
import comm.xss.coupon.businessenum.CouponCategory; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.MappedJdbcTypes; import org.apache.ibatis.type.MappedTypes; import org.apache.ibatis.type.TypeHandler;
import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException;
@MappedTypes(CouponCategory.class) @MappedJdbcTypes(JdbcType.VARCHAR) public class CouponCategoryConverter implements TypeHandler<CouponCategory> {
@Override public void setParameter(PreparedStatement preparedStatement, int i, CouponCategory couponCategory, JdbcType jdbcType) throws SQLException { preparedStatement.setString(i, couponCategory.getCode()); }
@Override public CouponCategory getResult(ResultSet resultSet, String s) throws SQLException { return CouponCategory.of(resultSet.getString(s)); }
@Override public CouponCategory getResult(ResultSet resultSet, int i) throws SQLException { return CouponCategory.of(resultSet.getString(i)); }
@Override public CouponCategory getResult(CallableStatement callableStatement, int i) throws SQLException { return CouponCategory.of(callableStatement.getString(i)); } }
|
4、SpringBoot整合线程池资源
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
| package com.xss.coupon.config;
import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.AsyncConfigurer; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.lang.reflect.Method; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor;
@Slf4j @EnableAsync @Configuration public class AsyncPoolConfig implements AsyncConfigurer {
@Bean @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(20); executor.setQueueCapacity(20); executor.setKeepAliveSeconds(60); executor.setThreadNamePrefix("xss_coupon_pool");
executor.setWaitForTasksToCompleteOnShutdown(true); executor.setAwaitTerminationSeconds(60);
executor.setRejectedExecutionHandler( new ThreadPoolExecutor.CallerRunsPolicy() );
executor.initialize();
return executor; }
@Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return new AsyncExceptionHandler(); }
@SuppressWarnings("all") class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler{
@Override public void handleUncaughtException(Throwable throwable, Method method, Object... objects) { throwable.printStackTrace(); log.error("AnsyncError: {}, Method: {}, Param: {}", throwable.getMessage(), method.getName(), JSON.toJSONString(objects));
} } }
|