項目中AOP的實例應用
其中包括了權限管理、表單驗證、事務管理、信息過濾、攔截器、過濾器、頁面轉發等等。
公司項目的應用:(涉及用戶驗證登錄以及用戶是否有管理員權限、心理用戶權限等),還有涉及的其他日誌管理代碼就不一一舉例了;
/** * 登錄攔截器(登錄判斷) * @author alex * */ public class LoginInterceptor extends HandlerInterceptorAdapter { @Autowired private UserService userService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throwsException { 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相關配置:<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes> <tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="insert*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="del*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/> <tx:method name="find*" read-only="true" /> <tx:method name="get*" read-only="true" /> <tx:method name="select*" read-only="true" /> </tx:attributes> </tx:advice> <aop:config proxy-target-class="true"> <aop:advisor pointcut="execution( * com.zhaozhi.spider.service.service.*.*(..))" advice-ref="txAdvice" /> </aop:config>
//....
項目中AOP的實例應用