spring攔截器的簡單實現Interceptor


原文鏈接:http://lixuanbin.iteye.com/blog/2250100

1. 需求描述

   某內部管理系統采用Spring MVC搭建,用戶可以登錄系統進行CRUD以及其他的一些日常管理操作。現在希望對某些敏感操作(譬如修改重要數據)進行攔截,在日志中記錄下該操作的執行人,操作時間,操作名稱,傳入參數以及返回結果等信息,以便萬一出問題后追究查驗。

   

2. 解決思路

   有兩種方案:

(1)把對應的MVC方法使用AOP去攔截,這個是方法級別的攔截;

(2)使用Spring MVC Interceptor去攔截,這個是基於URL的攔截。

   那么,如何選擇呢?考慮到我們這個是WEB項目,只有登錄用戶才能執行管理操作,而登錄用戶的用戶信息一般放在Session里,使用基於URL攔截的方法便於提取Session數據;而且,被Spring MVC @Controller注解的類,都被AnnotationMethodHandlerAdapter給代理了,使用AOP進行攔截的話需要做些特殊處理。所以,在這里我們選擇使用Interceptor攔截。

 

3. 具體實現

(1)Spring配置文件

   在beans頭部標簽加入:

...

xmlns:mvc="http://www.springframework.org/schema/mvc"

...

xsi:schemaLocation="...

http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd

..."

   然后加上mvc:interceptors攔截聲明:

 

Xml代碼   收藏代碼
 1 <mvc:interceptors>  
 2     <mvc:interceptor>  
 3         <mvc:mapping path="/**"/><!--攔截所有controller-->  
 4         <mvc:exclude-mapping  path="/js/**" />  
 5         <mvc:exclude-mapping  path="/css/**" />  
 6         <mvc:exclude-mapping  path="/img/**" />  
 7         <mvc:exclude-mapping  path="*.woff" />  
 8         <mvc:exclude-mapping  path="*.ico" />  
 9         <mvc:exclude-mapping  path="*.swf" />  
10         <mvc:exclude-mapping  path="*.png" />  
11         <bean id="log4UpdateOrDeleteInterceptor"  
12 class="com.XXX.testmvc.interceptor.Log4UpdateOrDeleteInterceptor"></bean>  
13     </mvc:interceptor>  
14 </mvc:interceptors>  

 

    Spring的攔截路徑采用了AntPathMatcher的方式。以下是引用自官方的說明:

The mapping matches URLs using the following rules:

  • ? matches one character
  • * matches zero or more characters
  • ** matches zero or more 'directories' in a path

Some examples:

  • com/t?st.jsp - matches com/test.jsp but also com/tast.jsp or com/txst.jsp
  • com/*.jsp - matches all .jsp files in the com directory
  • com/**/test.jsp - matches all test.jsp files underneath the com path
  • org/springframework/**/*.jsp - matches all .jsp files underneath the org/springframework path
  • org/**/servlet/bla.jsp - matches org/springframework/servlet/bla.jsp but also org/springframework/testing/servlet/bla.jsp and org/servlet/bla.jsp

(2)實現攔截器

   繼承HandlerInterceptorAdapter並按需覆寫里面的preHandle和postHandle方法即可。

 

Java代碼   收藏代碼
 1 /** 
 2  * 攔截敏感操作並記錄到日志 
 3  *  
 4  * @author 5  */  
 6 public class Log4UpdateOrDeleteInterceptor extends HandlerInterceptorAdapter {  
 7     protected static final Logger log = Logger.getLogger(Log4UpdateOrDeleteInterceptor.class);  
 8   
 9     public boolean preHandle(HttpServletRequest request, HttpServletResponse response,  
10             Object handler) throws Exception {  
11         HttpSession session = request.getSession();  
12         String requestUri = request.getRequestURI();  
13         log.debug("request uri:" + requestUri);  
14         String contextPath = request.getContextPath();  
15         String url = requestUri.substring(contextPath.length());  
16         if (StringUtils.contains(url, "add") || StringUtils.contains(url, "edit")  
17                 || StringUtils.contains(url, "delete")) {  
18             String user = session.getAttribute(SessionKey.USERNAME_SESSION_NAME) != null ? (String) session  
19                     .getAttribute(SessionKey.USERNAME_SESSION_NAME) : null;  
20             StringBuffer sb = new StringBuffer();  
21             Enumeration<String> a = null;  
22             a = request.getParameterNames();  
23             while (a.hasMoreElements()) {  
24                 String key = a.nextElement();  
25                 sb.append(key + ":" + request.getParameter(key) + ", ");  
26             }  
27             log.warn(String.format("FBI request warning! user: %s, url: %s, params: {%s}", user,  
28                     url, StringUtils.removeEnd(StringUtils.trim(sb.toString()), ",")));  
29         }  
30         return true;  
31     }  
32   
33     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o,  
34             ModelAndView mav) throws Exception {  
35         HttpSession session = request.getSession();  
36         String requestUri = request.getRequestURI();  
37         log.debug("request uri:" + requestUri);  
38         String contextPath = request.getContextPath();  
39         String url = requestUri.substring(contextPath.length());  
40         if ((StringUtils.contains(url, "add") || StringUtils.contains(url, "edit") || StringUtils  
41                 .contains(url, "delete")) && mav != null) {  
42             String user = session.getAttribute(SessionKey.USERNAME_SESSION_NAME) != null ? (String) session  
43                     .getAttribute(SessionKey.USERNAME_SESSION_NAME) : null;  
44             Map<String, Object> map = mav.getModel();  
45             StringBuffer sb = new StringBuffer();  
46             for (Map.Entry<String, Object> entry : map.entrySet()) {  
47                 sb.append(entry.getKey() + ":"  
48                         + (entry.getValue() != null ? entry.getValue().toString() : null) + ", ");  
49             }  
50             log.warn(String.format("FBI response warning! user: %s, url: %s, models: {%s}", user,  
51                     url, StringUtils.removeEnd(StringUtils.trim(sb.toString()), ",")));  
52         }  
53     }  
54   
55     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o,  
56             Exception excptn) throws Exception {  
57         // System.out.println("afterCompletion");  
58     }  
59   
60 }  

 

    本例檢查URI是否含有敏感操作來判斷是否需要進行日志記錄,如果您采用了REST接口,也可以加上request method的校驗。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM