项目中AOP的实例应用
其中包括了权限管理、表单验证、事务管理、信息过滤、拦截器、过滤器、页面转发等等。
公司项目的应用:(涉及用户验证登录以及用户是否有管理员权限、心理用户权限等),还有涉及的其他日志管理代码就不一一举例了;
/** * 登录拦截器(登录判断) * @author alex * */ public class LoginInterceptor extends HandlerInterceptorAdapter { @Autowired private UserService userService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; //check login Login login = handlerMethod.getMethodAnnotation(Login.class); if (null == login) { return true; } int userId = 0; String uid = CookieUtil.getValueByName(request, CookieUtil.SESSION_USER); if(NumberUtils.isNumber(uid)){ userId = Integer.valueOf(uid); } if(userId==0 || !userService.isLogined(userId, CookieUtil.getValueByName(request, CookieUtil.SESSION_ID))){ response.sendRedirect("/login"); return false; } //set user info User user = userService.getUserById(userId); request.setAttribute("userSession", user); request.setAttribute("loginUsername",user.getUsername()); request.setAttribute("loginUserId",user.getId()); //******* 是内部测试的心理账户 request.setAttribute("psychologyUser", user.getType == *** || "*******".equals(user.getCellphone())); //check admin permission Admin admin = handlerMethod.getMethodAnnotation(Admin.class); if (admin!=null && !user.isAdmin()) { response.sendRedirect("/error/no_permission"); return false; } return true; } return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
/** * 登录注解 * @author Alex * */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Login { int value() default 0; } /** * 管理员注解 * @author Alex * */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Admin { int value() default 0; }
一般情况下,对来自浏览器的请求的拦截,是利用Filter实现的,这种方式可以实现Bean预处理、后处理。
Spring MVC的拦截器不仅可实现Filter的所有功能,还可以更精确的控制拦截精度。
Spring为我们提供了org.springframework.web.servlet.handler.HandlerInterceptorAdapter这个适配器,继承此类,可以非常方便的实现自己的拦截器。他有三个方法:
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
- throws Exception {
- return true;
- }
- public void postHandle(
- HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
- throws Exception {
- }
- public void afterCompletion(
- HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
- throws Exception {
- }
分别实现预处理、后处理(调用了Service并返回ModelAndView,但未进行页面渲染)、返回处理(已经渲染了页面)
preHandle:预处理回调方法,实现处理器的预处理(如登录检查),第三个参数为响应的处理器;
返回值:true表示继续流程(如调用下一个拦截器或处理器);
false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应;
postHandle:后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。
AOP相关配置:
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**" /> <mvc:exclude-mapping path="/css/**,/js/**,/img/**,/fonts/**,/stylesheets/**,/javascripts/**,/images/**,/ueditor/**" /> <bean class="com.zhaozhi.writing.service.interceptor.AssetsInterceptor" /> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**" /> <mvc:exclude-mapping path="/css/**,/js/**,/img/**,/fonts/**,/stylesheets/**,/javascripts/**,/images/**,/ueditor/**" /> <bean class="com.zhaozhi.writing.service.interceptor.LoginInterceptor" /> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**" /> <mvc:exclude-mapping path="/css/**,/js/**,/img/**,/fonts/**,/stylesheets/**,/javascripts/**,/images/**,/ueditor/**" /> <bean class="com.zhaozhi.writing.service.interceptor.RoleInterceptor" /> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**" /> <mvc:exclude-mapping path="/css/**,/js/**,/img/**,/fonts/**,/stylesheets/**,/javascripts/**,/images/**,/ueditor/**" /> <bean class="com.zhaozhi.writing.service.interceptor.HitlogInterceptor" /> </mvc:interceptor> </mvc:interceptors>