自定義攔截器
SpringMVC可以使用攔截器對請求進行攔截處理,用戶可以自定義攔截器來實現(xiàn)特定的功能,自定義攔截器必須實現(xiàn)HandlerInterceptor接口。
步驟
- 編寫一個攔截器類,需要實現(xiàn)
HandlerInterceptor接口。
示例:
package com.cerr.springmvc.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("afterCompletion");
}
}
- 在配置文件中配置該攔截器,使用
<mvc:interceptors>來進行配置
配置示例:
<mvc:interceptors>
<!-- 配置自定義的攔截器-->
<bean class="com.cerr.springmvc.interceptor.FirstInterceptor"/>
</mvc:interceptors>
對HandlerInterceptor接口的三個方法的解析
public boolean preHandle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Object o){};
該方法在目標(biāo)方法執(zhí)行前被調(diào)用,該方法若返回值為true,則繼續(xù)調(diào)用后續(xù)的攔截器和目標(biāo)方法;若返回值為false,則不會再調(diào)用后續(xù)的攔截器和目標(biāo)方法。
可以考慮做權(quán)限,日志,事務(wù)等等。
public void postHandle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView){};
該方法在目標(biāo)方法執(zhí)行之后、渲染視圖之前被調(diào)用,可以對請求域中的屬性或視圖作出修改。
public void afterCompletion(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, Object o, Exception e){};
該方法在渲染視圖之后被調(diào)用,釋放資源。
攔截器方法執(zhí)行順序圖

從該圖我們可以看出,攔截器先調(diào)的
preHandle,然后再去調(diào)目標(biāo)方法,然后再調(diào)postHandle,然后再渲染視圖,最后調(diào)afterCompletion,然后結(jié)束。
關(guān)于攔截器的其他配置
上面中我們說了攔截器可以通過<mvc:interceptors>來配置,而對于這個標(biāo)簽中,里面還有一個子標(biāo)簽我們還沒說到,它就是<mvc:interceptor>。其里面有兩個子標(biāo)簽<mvc:mapping path=""/>和<mvc:exclude-mapping path=""/>。
-
<mvc:mapping path=""/>
表示該攔截器攔截該請求(path里面的值) -
<mvc:exclude-mapping path=""/>
表示該攔截器不攔截該請求(path里面的值)
例如我們配置如下:
<mvc:interceptors>
<!-- 配置自定義的攔截器-->
<bean class="com.cerr.springmvc.interceptor.FirstInterceptor"/>
<mvc:interceptor>
<mvc:mapping path="/emps"/>
<bean class="com.cerr.springmvc.interceptor.SecondInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
SecondInterceptor攔截器代碼:
package com.cerr.springmvc.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SecondInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
System.out.println("SecondInterceptor:preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
System.out.println("SecondInterceptor:postHandle");
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
System.out.println("SecondInterceptor:afterCompletion");
}
}
配置后,對于SecondInterceptor攔截器,只攔截emps請求,而emps請求會被FirstInterceptor和SecondInterceptor攔截。
運行后訪問emps結(jié)果如下:

紅框為第二個攔截器,綠框為第一個攔截器。
而如果訪問一個其他的(例如i18n)結(jié)果如下:

綠框為第一個攔截器,只被第一個攔截器所攔截。
多個攔截器的攔截方法執(zhí)行順序

從執(zhí)行順序圖我們可以看出,對于
preHandle方法,先配置的先執(zhí)行;對于postHandle方法,先配置的后執(zhí)行;對于afterCompletion方法,先配置的后執(zhí)行。
有一點需要注意的是:對于afterCompletion方法是否執(zhí)行是取決于preHandle方法的,在某一個攔截器的prehandle方法返回false前的所有攔截器都會執(zhí)行afterCompletion方法。例如現(xiàn)在有4個攔截器,而第三個攔截器的prehandle返回了false,所以會執(zhí)行afterCompletion方法的攔截器有攔截器1、攔截器2。