javascript
Spring MVC中的拦截器/过滤器HandlerInterceptorAdapter的使用
轉(zhuǎn)載自?https://www.cnblogs.com/EasonJim/p/7704740.html
一般情況下,對來自瀏覽器的請求的攔截,是利用Filter實現(xiàn)的
而在Spring中,基于Filter這種方式可以實現(xiàn)Bean預處理、后處理。?比如注入FilterRegistrationBean,然后在這個Bean上傳遞自己繼承Filter實現(xiàn)的自定義Filter進入即可。
而Spring MVC也有攔截器,不僅可實現(xiàn)Filter的所有功能,還可以更精確的控制攔截精度。?
Spring MVC提供的org.springframework.web.servlet.handler.HandlerInterceptorAdapter這個適配器,繼承此類,可以非常方便的實現(xiàn)自己的攔截器。
它有三個方法:
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception { return true; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception { } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception { }preHandle在業(yè)務處理器處理請求之前被調(diào)用。預處理,可以進行編碼、安全控制等處理;?
postHandle在業(yè)務處理器處理請求執(zhí)行完成后,生成視圖之前執(zhí)行。后處理(調(diào)用了Service并返回ModelAndView,但未進行頁面渲染),有機會修改ModelAndView;?
afterCompletion在DispatcherServlet完全處理完請求后被調(diào)用,可用于清理資源等。返回處理(已經(jīng)渲染了頁面),可以根據(jù)ex是否為null判斷是否發(fā)生了異常,進行日志記錄;
如果基于XML配置使用Spring MVC,可以利用SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping進行Url映射(相當于struts的path映射)和攔截請求(注入interceptors)。
如果基于注解使用Spring MVC,可以使用DefaultAnnotationHandlerMapping注入interceptors。
注意無論基于XML還是基于注解,HandlerMapping Bean都是需要在XML中配置的。?
示例一:
在這個例子中,我們假設UserController中的注冊操作只在9:00-12:00開放,那么就可以使用攔截器實現(xiàn)這個功能。?
public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter { private int openingTime; private int closingTime; private String mappingURL;//利用正則映射到需要攔截的路徑 public void setOpeningTime(int openingTime) { this.openingTime = openingTime; } public void setClosingTime(int closingTime) { this.closingTime = closingTime; } public void setMappingURL(String mappingURL) { this.mappingURL = mappingURL; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String url=request.getRequestURL().toString(); if(mappingURL==null || url.matches(mappingURL)){ Calendar c=Calendar.getInstance(); c.setTime(new Date()); int now=c.get(Calendar.HOUR_OF_DAY); if(now<openingTime || now>closingTime){ request.setAttribute("msg", "注冊開放時間:9:00-12:00"); request.getRequestDispatcher("/msg.jsp").forward(request, response); return false; } return true; } return true; } }XML配置:
<bean id="timeBasedAccessInterceptor" class="com.spring.handler.TimeBasedAccessInterceptor"> <property name="openingTime" value="9" /> <property name="closingTime" value="12" /> <property name="mappingURL" value=".*/user\.do\?action=reg.*" /> </bean> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="interceptors"> <list> <ref bean="timeBasedAccessInterceptor"/> </list> </property> </bean>這里我們定義了一個mappingURL屬性,實現(xiàn)利用正則表達式對url進行匹配,從而更細粒度的進行攔截。當然如果不定義mappingURL,則默認攔截所有對Controller的請求。?
UserController:
@Controller @RequestMapping("/user.do") public class UserController{ @Autowired private UserService userService; @RequestMapping(params="action=reg") public ModelAndView reg(Users user) throws Exception { userService.addUser(user); return new ModelAndView("profile","user",user); } // other option ... }也可以配置多個攔截器,每個攔截器進行不同的分工。
示例二:
主要是XML配置不一樣
<!--配置攔截器, 多個攔截器,順序執(zhí)行 --> <mvc:interceptors> <mvc:interceptor> <!-- 匹配的是url路徑, 如果不配置或/**,將攔截所有的Controller --> <mvc:mapping path="/" /> <mvc:mapping path="/user/**" /> <mvc:mapping path="/test/**" /> <bean class="com.alibaba.interceptor.CommonInterceptor"></bean> </mvc:interceptor> <!-- 當設置多個攔截器時,先按順序調(diào)用preHandle方法,然后逆序調(diào)用每個攔截器的postHandle和afterCompletion方法 --> </mvc:interceptors> package com.alibaba.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import com.alibaba.util.RequestUtil; public class CommonInterceptor extends HandlerInterceptorAdapter{ private final Logger log = LoggerFactory.getLogger(CommonInterceptor.class); public static final String LAST_PAGE = "com.alibaba.lastPage"; /* * 利用正則映射到需要攔截的路徑 private String mappingURL; public void setMappingURL(String mappingURL) { this.mappingURL = mappingURL; } */ /** * 在業(yè)務處理器處理請求之前被調(diào)用 * 如果返回false * 從當前的攔截器往回執(zhí)行所有攔截器的afterCompletion(),再退出攔截器鏈 * 如果返回true * 執(zhí)行下一個攔截器,直到所有的攔截器都執(zhí)行完畢 * 再執(zhí)行被攔截的Controller * 然后進入攔截器鏈, * 從最后一個攔截器往回執(zhí)行所有的postHandle() * 接著再從最后一個攔截器往回執(zhí)行所有的afterCompletion() */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if ("GET".equalsIgnoreCase(request.getMethod())) { RequestUtil.saveRequest(); } log.info("==============執(zhí)行順序: 1、preHandle================"); String requestUri = request.getRequestURI(); String contextPath = request.getContextPath(); String url = requestUri.substring(contextPath.length()); log.info("requestUri:"+requestUri); log.info("contextPath:"+contextPath); log.info("url:"+url); String username = (String)request.getSession().getAttribute("user"); if(username == null){ log.info("Interceptor:跳轉(zhuǎn)到login頁面!"); request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response); return false; }else return true; } /** * 在業(yè)務處理器處理請求執(zhí)行完成后,生成視圖之前執(zhí)行的動作 * 可在modelAndView中加入數(shù)據(jù),比如當前時間 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { log.info("==============執(zhí)行順序: 2、postHandle================"); if(modelAndView != null){ //加入當前時間 modelAndView.addObject("var", "測試postHandle"); } } /** * 在DispatcherServlet完全處理完請求后被調(diào)用,可用于清理資源等 * * 當有攔截器拋出異常時,會從當前攔截器往回執(zhí)行所有的攔截器的afterCompletion() */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { log.info("==============執(zhí)行順序: 3、afterCompletion================"); } }?
參考:
http://blog.csdn.net/liuwenbo0920/article/details/7283757(以上內(nèi)容部分轉(zhuǎn)自此篇文章)
http://www.cnblogs.com/xingele0917/p/4318008.html
http://blog.csdn.net/ye_sheng/article/details/48395663?(以上內(nèi)容部分轉(zhuǎn)自此篇文章)
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的Spring MVC中的拦截器/过滤器HandlerInterceptorAdapter的使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringBoot的@SpringBo
- 下一篇: GC算法基础