通過攔截器Interceptor實現Spring MVC中Controller介面訪問資訊的記錄
阿新 • • 發佈:2019-02-05
java web工程專案使用了Spring+Spring MVC+Hibernate的結構,在Controller中的方法都是用於處理前端的訪問資訊,Controller通過呼叫Service進行業務處理後給前端返回ModelAndView物件或者只返回Json格式資料。如果能夠獲得Http請求在後端程式中處理的相關資訊,對於開發和除錯時十分方便的。工程中使用了Spring MVC的Interceptor對所有Http請求及其響應進行攔截,從而獲取到本次訪問介面資訊以及程式處理時長等資訊,特意在此記錄一下實現方式。
package com.api.web.interceptor;import java.util.Arrays;
import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.yijia.api.util.SimpleDateFormatCache;
/**
* 記錄資訊:</br> 訪問時間</br>Controller路徑</br>對應方法名</br>請求引數資訊</br>請求相對路徑</br>請求處理時長
*
* @author Administrator
*
*/
public class TimeCostInterceptor implements HandlerInterceptor {
// before the actual handler will be executed
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
long startTime = System.currentTimeMillis();
request.setAttribute("startTime", startTime);
if (handler instanceof HandlerMethod) {
StringBuilder sb = new StringBuilder(1000);
sb.append("-----------------------").append(SimpleDateFormatCache.getYmdhms().format(new Date()))
.append("-------------------------------------\n");
HandlerMethod h = (HandlerMethod) handler;
sb.append("Controller: ").append(h.getBean().getClass().getName()).append("\n");
sb.append("Method : ").append(h.getMethod().getName()).append("\n");
sb.append("Params : ").append(getParamString(request.getParameterMap())).append("\n");
sb.append("URI : ").append(request.getRequestURI()).append("\n");
System.out.println(sb.toString());
}
return true;
}
// after the handler is executed
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
long startTime = (Long) request.getAttribute("startTime");
long endTime = System.currentTimeMillis();
long executeTime = endTime - startTime;
if(handler instanceof HandlerMethod){
StringBuilder sb = new StringBuilder(1000);
sb.append("CostTime : ").append(executeTime).append("ms").append("\n");
sb.append("-------------------------------------------------------------------------------");
System.out.println(sb.toString());
}
}
private String getParamString(Map<String, String[]> map) {
StringBuilder sb = new StringBuilder();
for(Entry<String,String[]> e:map.entrySet()){
sb.append(e.getKey()).append("=");
String[] value = e.getValue();
if(value != null && value.length == 1){
sb.append(value[0]).append("\t");
}else{
sb.append(Arrays.toString(value)).append("\t");
}
}
return sb.toString();
}
public void afterCompletion(HttpServletRequest arg0,
HttpServletResponse arg1, Object arg2, Exception arg3)
throws Exception {
}
}
由於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物件中進行操作的問題都可以通過攔截器進行統一處理,常用的場景包括使用者登入控制、許可權檢查,跨域請求訪問許可權控制等。