通過攔截器Interceptor實(shí)現(xiàn)Spring MVC中Controller接口訪問信息的記錄

java web工程項(xiàng)目使用了Spring+Spring MVC+Hibernate的結(jié)構(gòu),在Controller中的方法都是用于處理前端的訪問信息,Controller通過調(diào)用Service進(jìn)行業(yè)務(wù)處理后給前端返回ModelAndView對象或者只返回Json格式數(shù)據(jù)。如果能夠獲得Http請求在后端程序中處理的相關(guān)信息,對于開發(fā)和調(diào)試時(shí)十分方便的。工程中使用了Spring MVC的Interceptor對所有Http請求及其響應(yīng)進(jìn)行攔截,從而獲取到本次訪問接口信息以及程序處理時(shí)長等信息,特意在此記錄一下實(shí)現(xiàn)方式。

復(fù)制代碼
 1 package com.api.web.interceptor;  2  3 import java.util.Arrays;  4 import java.util.Date;  5 import java.util.Map;  6 import java.util.Map.Entry;  7  8 import javax.servlet.http.HttpServletRequest;  9 import javax.servlet.http.HttpServletResponse; 10 11 import org.apache.log4j.Logger; 12 import org.springframework.web.method.HandlerMethod; 13 import org.springframework.web.servlet.HandlerInterceptor; 14 import org.springframework.web.servlet.ModelAndView; 15 16 import com.yijia.api.util.SimpleDateFormatCache; 17 18 /** 19  * 記錄信息:</br> 訪問時(shí)間</br>Controller路徑</br>對應(yīng)方法名</br>請求參數(shù)信息</br>請求相對路徑</br>請求處理時(shí)長 20  * 21  * @author Administrator 22  * 23 */ 24 public class TimeCostInterceptor implements HandlerInterceptor { 25 26 // before the actual handler will be executed 27 public boolean preHandle(HttpServletRequest request, 28 HttpServletResponse response, Object handler) throws Exception { 29 long startTime = System.currentTimeMillis(); 30 request.setAttribute("startTime", startTime); 31 if (handler instanceof HandlerMethod) { 32 StringBuilder sb = new StringBuilder(1000); 33 34 sb.append("-----------------------").append(SimpleDateFormatCache.getYmdhms().format(new Date())) 35 .append("-------------------------------------\n"); 36 HandlerMethod h = (HandlerMethod) handler; 37 sb.append("Controller: ").append(h.getBean().getClass().getName()).append("\n"); 38 sb.append("Method    : ").append(h.getMethod().getName()).append("\n"); 39 sb.append("Params    : ").append(getParamString(request.getParameterMap())).append("\n"); 40 sb.append("URI       : ").append(request.getRequestURI()).append("\n"); 41  System.out.println(sb.toString()); 42  } 43 return true; 44  } 45 46 // after the handler is executed 47 public void postHandle(HttpServletRequest request, 48  HttpServletResponse response, Object handler, 49 ModelAndView modelAndView) throws Exception { 50 long startTime = (Long) request.getAttribute("startTime"); 51 long endTime = System.currentTimeMillis(); 52 long executeTime = endTime - startTime; 53 if(handler instanceof HandlerMethod){ 54 StringBuilder sb = new StringBuilder(1000); 55 sb.append("CostTime  : ").append(executeTime).append("ms").append("\n"); 56 sb.append("-------------------------------------------------------------------------------"); 57  System.out.println(sb.toString()); 58  } 59  } 60 61 private String getParamString(Map<String, String[]> map) { 62 StringBuilder sb = new StringBuilder(); 63 for(Entry<String,String[]> e:map.entrySet()){ 64 sb.append(e.getKey()).append("="); 65 String[] value = e.getValue(); 66 if(value != null && value.length == 1){ 67 sb.append(value[0]).append("\t"); 68 }else{ 69 sb.append(Arrays.toString(value)).append("\t"); 70  } 71  } 72 return sb.toString(); 73  } 74 75 public void afterCompletion(HttpServletRequest arg0, 76  HttpServletResponse arg1, Object arg2, Exception arg3) 77 throws Exception { 78 79  } 80 }
復(fù)制代碼

由于Interceptor是Spring MVC的功能組件,所以需要把此攔截器配置在springmvc的xml配置文件中(或者使用其他配置方式比如javaConfig):

復(fù)制代碼
 <mvc:interceptors>
        <!-- 使用bean定義一個(gè)Interceptor,直接定義在mvc:interceptors根下面的Interceptor將攔截所有的請求 -->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>            
            <!-- 需排除攔截的地址 -->  
            <mvc:exclude-mapping path="/" />
            <mvc:exclude-mapping path="/test" />
            <!-- 定義在mvc:interceptor下面的表示是對特定的請求才進(jìn)行攔截的 -->
            <bean class="com.api.web.interceptor.TimeCostInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
復(fù)制代碼

定義并配置好好攔截器后,在程序Controller中的接口被訪問的時(shí)候,相關(guān)訪問信息就會輸出到控制臺上,也可以使用日志將訪問信息記錄到日志中。

記錄效果如下所示:

 

總結(jié):

攔截器通對用戶請求進(jìn)行攔截可以對用戶的請求(HttpServletRequest)進(jìn)行預(yù)處理,也可以對返回給用戶的響應(yīng)(HttpServletResponse)進(jìn)行訪問后處理,還可以在請求完成后針對請求的異常信息進(jìn)行處理。能夠在request對象和response對象中進(jìn)行操作的問題都可以通過攔截器進(jìn)行統(tǒng)一處理,常用的場景包括用戶登錄控制、權(quán)限檢查,跨域請求訪問權(quán)限控制等。