包含标签 Spring 的文章

参数校验

通过RestControllerAdvice和ExceptionHandler实现全局异常捕获 起因: 我么希望通过全局统一的异常处理将自定义错误码以json的形式发送给前端。 步骤: 1.定义一个统一结果返回类BaseRspVo import com.shizhongcai.business.common.domain.enums.ErrorCodesEnum; import com.shizhongcai.business.common.exception.BaseException; import lombok.Data; @Data public class BaseRspVo<T> { private boolean success; private String msg; private Integer errorCode; private T data; public BaseRspVo() { } public BaseRspVo (T data){ this.success = true; this.msg= ErrorCodesEnum.SUCCESS.getMsg(); this.errorCode = ErrorCodesEnum.SUCCESS.getCode(); this.data = data; } public BaseRspVo (boolean success, String msg, int errorCode) { this.success = success; this.msg = msg; this.errorCode = errorCode; } public BaseRspVo (boolean success, String msg, int errorCode, T data) { this(success,msg,errorCode); this.……

阅读全文

全局异常处理

通过RestControllerAdvice和ExceptionHandler实现全局异常捕获 起因: 我么希望通过全局统一的异常处理将自定义错误码以json的形式发送给前端。 步骤: 1.定义一个统一结果返回类BaseRspVo import com.shizhongcai.business.common.domain.enums.ErrorCodesEnum; import com.shizhongcai.business.common.exception.BaseException; import lombok.Data; @Data public class BaseRspVo<T> { private boolean success; private String msg; private Integer errorCode; private T data; public BaseRspVo() { } public BaseRspVo (T data){ this.success = true; this.msg= ErrorCodesEnum.SUCCESS.getMsg(); this.errorCode = ErrorCodesEnum.SUCCESS.getCode(); this.data = data; } public BaseRspVo (boolean success, String msg, int errorCode) { this.success = success; this.msg = msg; this.errorCode = errorCode; } public BaseRspVo (boolean success, String msg, int errorCode, T data) { this(success,msg,errorCode); this.……

阅读全文

Filter和Interceptor

#Filter - Filter是javax.servlet包中定义的接口,任何实现Filter接口的类都能称为过滤器。 - 主要用途:字符过滤集、控制权限、防止跨站脚本攻击(XSS)等等。 - 实现: 1. 如果是传统项目,需要在web.xml中配置filter <filter> <description>字符集过滤器</description> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <description>字符集编码</description> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> 2. 如果是springBoot项目,可以在定义好自己的filter类之后,需要使用filterRegisterationBean将filter进行注入。 public class MDCFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } } @Bean public FilterRegistrationBean mdcFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.……

阅读全文

JSR-303参数校验

JSR-303参数校验 步骤 1.创建校验参数类 import lombok.Data; import org.hibernate.validator.constraints.Range; import org.springframework.format.annotation.DateTimeFormat; import javax.validation.constraints.*; import java.util.Date; /** * 参数验证请求参数 * @Author shizhongcai * @Date 2019/11/20 15:35 */ @Data public class ValidatorReqVo{ @NotNull(message = "id不能为空") private Integer id; @NotNull @Future(message = "格式为yyyy-MM-dd,且为将来时间") @DateTimeFormat(pattern = "yyyy-MM-dd") private Date future; @NotNull @DecimalMin(value = "0.1") @DecimalMax(value = "1000") private Double doubleValue; @NotNull @Min(value = 1) @Max(value = 10) private Integer intValue; @NotNull @Range(min = 1,max = 10,message = "最小为1,最大为10") private Integer range; @NotBlank @Email private String email; @NotBlank @Size(min = 10,max = 20,message = "字符串长度在10-20之间") private String strSize; } 2.……

阅读全文

基于自定义注解的参数解析器

基于自定义注解的参数解析器 背景 在工作中,常会对接一些第三方应用,通常第三方会采用Rsa+Aes加密来通信,但是每个第三方的加密方式可能不一致。此时得好好规划一下实现方案了。因此我们采用注解+Spring自带了参数解析类,实现自己的参数解析器。 原理 通过HandlerMethodArgumentResolver实现自定义参数解析 实现 步骤1:创建注解,例如创建一个解析Aes加密的注解AesJson import java.lang.annotation.*; @Target({ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface AesJson { } 步骤2:创建加密参数实体类对象 传入的JSON数据格式为{“data”:“xxxxxxxxxx”} import lombok.Data; @Data public class AesBaseParams { private String data; } 步骤3:新建AesArgumentResolver类实现HandlerMethodArgumentResolver import com.alibaba.fastjson.JSON; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.MethodParameter; import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.ModelAndViewContainer; import javax.servlet.http.HttpServletRequest; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URLDecoder; import java.util.HashMap; import java.util.Map; import java.util.Objects; /** * aes加密算法加密的入参,通过@AesJson注解自动解析 */ public class AesArgumentResolver implements HandlerMethodArgumentResolver { private static final Logger logger = LoggerFactory.……

阅读全文

接口限流-令牌桶限流

guava之令牌桶算法实现接口限流 实现步骤 1.创建注解RateLimit import java.lang.annotation.*; /** * 自定义注解:限流令牌桶注解,用以创建令牌桶以及设定令牌桶大小 */ @Inherited @Documented @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface RateLimit { double limitNum() default 20; //默认每秒放入桶中20 } 2.创建令牌桶切面RateLimitAspect import com.google.common.util.concurrent.RateLimiter; import com.shizhongcai.business.common.annotation.RateLimit; import com.shizhongcai.business.common.domain.enums.ErrorCodesEnum; import com.shizhongcai.business.common.exception.BaseException; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.lang.reflect.Method; import java.util.concurrent.ConcurrentHashMap; /** * 令牌桶切面,桶中无令牌进行服务降级 * */ @Component @Scope @Aspect public class RateLimitAspect { //用来存放不同接口的RateLimiter令牌桶(key为接口名称,value为RateLimiter) //ConcurrentHashMap线程安全 private ConcurrentHashMap<String, RateLimiter> map = new ConcurrentHashMap<>(); //令牌桶 private RateLimiter rateLimiter; @Pointcut("@annotation(com.……

阅读全文

日志优化MDC

MDC(Mapped Diagnostic Context) 实现 步骤1:创建MDCFilter实现Filter filter(过滤器)作用于在intreceptor(拦截器)之前,不像intreceptor一样依赖于springmvc框架,只需要依赖于serverlet。 在过滤之前在reqId钟放入uuid并在结束之后remove import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.UUID; /** * @Author shizhongcai * @Date 2019/11/15 11:15 */ @Component public class MDCFilter implements Filter { private static final Logger LOG = LoggerFactory.getLogger(MDCFilter.class); public static final String MDC_ID = "reqId"; @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { boolean mdcFlag = false; try { MDC.……

阅读全文

统一返回对象

1.创建实体类BaseRspVo @Data public class BaseRspVo<T> { private boolean success; private String msg; private Integer errorCode; private T data; public BaseRspVo() { } public BaseRspVo (T data){ this.success = true; this.msg= ErrorCodesEnum.SUCCESS.getMsg(); this.errorCode = ErrorCodesEnum.SUCCESS.getCode(); this.data = data; } public BaseRspVo(ErrorCodesEnum errorCode) { if(errorCode == ErrorCodesEnum.SUCCESS) { this.success = true; } else { this.success = false; } this.msg = errorCode.getMsg(); this.errorCode = errorCode.getCode(); } } 错误Code枚举类 public enum ErrorCodesEnum { SUCCESS(10000,"成功"), SYS_ERROR(1000,"系统异常,请稍后再试"), DUPLICATE_KEY(10001,"数据库中已存在该记录"), NO_HANDLER_FOUND(10002,"路径不存在,请检查路径是否正确"), DEFAULT_FAIL(10003,"未知异常,请稍后再试"), DECRYPT_ERROR(10004,"解密出错"), ; /** * 错误码 */ private int code; /** * 错误描述 */ private String msg; ErrorCodesEnum(int code, String msg) { this.……

阅读全文

项目开发

Spring中Filter和Interceptor的区别 全局异常处理 统一返回结果对象 日志优化MDC(Mapped Diagnostic Context)的类(技术上使用了ThreadLocal实现,重点技术) 基于自定义注解的参数解析器(通过HandlerMethodArgumentResolver实现) 基于自定义注解的结果包装统一返回(通过HandlerMethodReturnValueHandler实现) 接口限流-令牌桶限流 参数校验-JSR-303 ……

阅读全文

项目开发

Spring中Filter和Interceptor的区别 全局异常处理 统一返回结果对象 日志优化MDC(Mapped Diagnostic Context)的类(技术上使用了ThreadLocal实现,重点技术) 基于自定义注解的参数解析器(通过HandlerMethodArgumentResolver实现) 基于自定义注解的结果包装统一返回(通过HandlerMethodReturnValueHandler实现) 接口限流-令牌桶限流 参数校验-JSR-303 ……

阅读全文