使用@Aspect
来定义了一个切面。
其中prefixReq,day
域可以自定义缓存请求号时的key
前缀以及缓存的时间。
最关键的一点是用
@Pointcut("@annotation(com.crossoverJie.request.anotation.CheckReqNo)")
定义了一个切入点,这样所有使用@CheckReqNo
的注解都会被拦截。
接下来的逻辑就比较简单了,在每次请求之前进行拦截。
先去Redis
中查看这个请求号(ps:反射获取
)是否存在,如果不存在则通过并将本次的请求号缓存起来。如果存在则抛出异常。
使用注解
可以在jdbc.properties
配置文件中自定义前缀和缓存时间
#redis前缀 redis.prefixReq=reqNo #redis缓存时间 默认单位为天 redis.day=1
不定义也可以,会使用默认值。
由于该注解是需要加到controller
层,因此我们得使用CGLIB
代理。
这里有一个坑,需要将开启CGLIB
的配置配置到我们web.xml
中的
<!-- Spring MVC servlet --> <servlet> <servlet-name>SpringMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet>
这里所定义的spring-mvc.xml
文件中,不然springMVC
所在的子容器是无法被父容器所加载的。
使用实例:
@CheckReqNo @RequestMapping(value = "/createRedisContent",method = RequestMethod.POST) @ResponseBody public BaseResponse<NULLBody> createRedisContent(@RequestBody RedisContentReq redisContentReq){ BaseResponse<NULLBody> response = new BaseResponse<NULLBody>() ; Rediscontent rediscontent = new Rediscontent() ; try { CommonUtil.setLogValueModelToModel(redisContentReq,rediscontent); rediscontentMapper.insertSelective(rediscontent) ; response.setReqNo(redisContentReq.getReqNo()); response.setCode(StatusEnum.SUCCESS.getCode()); response.setMessage(StatusEnum.SUCCESS.getMessage()); }catch (Exception e){ logger.error("system error",e); response.setReqNo(response.getReqNo()); response.setCode(StatusEnum.FAIL.getCode()); response.setMessage(StatusEnum.FAIL.getMessage()); } return response ; }
统一异常controller
/** * * ClassName: ErrorController <br/> * Function: 错误异常统一处理. <br/> * @author crossoverJie * @version * @since JDK 1.7 */ @ControllerAdvice public class ErrorController { private Logger logger = LoggerFactory.getLogger(this.getClass()); @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.OK) @ResponseBody public Object processUnauthenticatedException(NativeWebRequest request, Exception e) { logger.error("请求出现异常:", e); BaseResponse<NULLBody> response = new BaseResponse<NULLBody>(); response.setCode(StatusEnum.FAIL.getCode()); if (e instanceof RuntimeException){ response.setMessage(e.getMessage()); } else { response.setMessage(StatusEnum.FAIL.getMessage()); } return response ; } }
这样当controller层出现异常之后都会进入这里进行统一的返回。
总结
至此整个插件的流程已经全部OK,从中可以看出Spring AOP
在实际开发中的各种好处。
之前的几篇文章也有应用到:
不知不觉这个小白入门的SSM
系列已经更新了14篇了,在GitHub
也有了500多颗星了,期间也和不少朋友有过交流、探讨,感谢大家的支持。
接下来可能不太会更新这个系列了,由于博主现在所在的项目组采用的是目前比较流行的SpringBoot+SpringCloud
和Docker
的方式来进行架构的,所以之后的重心肯定会移到这方面,用过SpringBoot
之后相信大家肯定也回不去了。
所以之后我会继续更新SpringBoot+SpringCloud
相关的文章,欢迎持续关注,持续拍砖(ps:这个插件也会用springBoot重写一遍
)
个人博客地址:crossoverjie.top。