通過攔截器Interceptor實現Spring MVC中Controller介面訪問資訊的記錄,interceptormvc
java web工程項目使用了Spring+Spring MVC+Hibernate的結構,在Controller中的方法都是用於處理前端的訪問資訊,Controller通過調用Service進行業務處理後給前端返回ModelAndView對象或者只返回Json格式資料。如果能夠獲得Http請求在後端程式中處理的相關資訊,對於開發和調試時十分方便的。工程中使用了Spring MVC的Interceptor對所有Http請求及其響應進行攔截,從而擷取到本次提供者資訊以及程式處理時間長度等資訊,特意在此記錄一下實現方式。
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> 訪問時間</br>Controller路徑</br>對應方法名</br>請求參數資訊</br>請求相對路徑</br>請求處理時間長度20 * 21 * @author Administrator22 * 23 */24 public class TimeCostInterceptor implements HandlerInterceptor {25 26 // before the actual handler will be executed27 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 executed47 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 }
由於Interceptor是Spring MVC的功能組件,所以需要把此攔截器配置在springmvc的xml設定檔中(或者使用其他配置方式比如javaConfig):
<mvc:interceptors> <!-- 使用bean定義一個Interceptor,直接定義在mvc:interceptors根下面的Interceptor將攔截所有的請求 --> <mvc:interceptor> <mvc:mapping path="/**"/> <!-- 需排除攔截的地址 --> <mvc:exclude-mapping path="/" /> <mvc:exclude-mapping path="/test" /> <!-- 定義在mvc:interceptor下面的表示是對特定的請求才進行攔截的 --> <bean class="com.api.web.interceptor.TimeCostInterceptor"/> </mvc:interceptor> </mvc:interceptors>
定義並配置好好攔截器後,在程式Controller中的介面被訪問的時候,相關訪問資訊就會輸出到控制台上,也可以使用日誌將訪問資訊記錄到日誌中。
記錄效果如下所示:
總結:
攔截器通對使用者請求進行攔截可以對使用者的請求(HttpServletRequest)進行預先處理,也可以對返回給使用者的響應(HttpServletResponse)進行訪問後處理,還可以在請求完成後針對請求的異常資訊進行處理。能夠在request對象和response對象中進行操作的問題都可以通過攔截器進行統一處理,常用的情境包括使用者登入控制、許可權檢查,跨域請求存取權限控制等。