您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“過(guò)濾器Filter和攔截器HandlerIntercepter的區(qū)別及用法”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
最近在代碼中,看到有同事既在用攔截器又在用過(guò)濾器做登錄校驗(yàn),就覺(jué)得很暈,似乎二者都可以實(shí)現(xiàn)業(yè)務(wù)需求,但是到底采用哪種方式較好呢,二者又有什么區(qū)別?
依賴(lài)于servlet容器,在實(shí)現(xiàn)上基于函數(shù)回調(diào),可以對(duì)幾乎所有請(qǐng)求進(jìn)行過(guò)濾,一個(gè)過(guò)濾器實(shí)例只能在容器初始化時(shí)調(diào)用,它是隨你的web應(yīng)用啟動(dòng)而啟動(dòng)的,只初始化一次,以后就可以攔截相關(guān)的請(qǐng)求,只有當(dāng)你的web應(yīng)用停止或重新部署的時(shí)候才能銷(xiāo)毀。
使用過(guò)濾器的目的是用來(lái)做一些過(guò)濾操作,獲取我們想要獲取的數(shù)據(jù),比如:在過(guò)濾器中修改字符編碼;在過(guò)濾器中修改HttpServletRequest的一些參數(shù),包括:過(guò)濾低俗文字、危險(xiǎn)字符等。
依賴(lài)于web框架,在SpringMVC中就是依賴(lài)于SpringMVC框架。在實(shí)現(xiàn)上基于Java的反射機(jī)制,屬于面向切面編程(AOP)的一種運(yùn)用。
由于攔截器是基于web框架的調(diào)用,因此可以使用Spring的依賴(lài)注入(DI)進(jìn)行一些業(yè)務(wù)操作,而不用修改handler自身的實(shí)現(xiàn)。但是缺點(diǎn)是只能對(duì)controller請(qǐng)求進(jìn)行攔截,對(duì)其他的一些比如直接訪(fǎng)問(wèn)靜態(tài)資源的請(qǐng)求則沒(méi)辦法進(jìn)行攔截處理。
①攔截器是基于java的反射機(jī)制的,而過(guò)濾器是基于函數(shù)回調(diào)。
②攔截器不依賴(lài)與servlet容器,過(guò)濾器依賴(lài)與servlet容器。
③攔截器只能對(duì)action請(qǐng)求起作用,而過(guò)濾器則可以對(duì)幾乎所有的請(qǐng)求起作用。
④攔截器可以訪(fǎng)問(wèn)action上下文、值棧里的對(duì)象,而過(guò)濾器不能訪(fǎng)問(wèn)。
⑤在action的生命周期中,攔截器可以多次被調(diào)用(這里是指攔截器里的三個(gè)方法是可以在一次action中的不同時(shí)期調(diào)用,細(xì)粒度控制),而過(guò)濾器只能一次請(qǐng)求過(guò)濾一次,不能在不同的生命周期里作用。
⑥攔截器可以獲取IOC容器中的各個(gè)bean,而過(guò)濾器就不行,這點(diǎn)很重要,在攔截器里注入一個(gè)service,可以調(diào)用業(yè)務(wù)邏輯。
在javax.servlet.Filter接口中定義了3個(gè)方法: void init(FilterConfig filterConfig) 用于完成過(guò)濾器的初始化 void destroy() 用于過(guò)濾器銷(xiāo)毀前,完成某些資源的回收 void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) 實(shí)現(xiàn)過(guò)濾功能,該方法對(duì)每個(gè)請(qǐng)求增加額外的處理
public class FilterUtil implements Filter{ @SuppressWarnings("unused") private FilterConfig filterConfig; @Override public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; System.out.println("過(guò)濾器Filter初始化"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse)) { throw new ServletException("FilterUtil just supports HTTP requests"); } HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; httpRequest.setCharacterEncoding(this.filterConfig.getInitParameter("encoding")); httpResponse.setCharacterEncoding(this.filterConfig.getInitParameter("encoding")); chain.doFilter(httpRequest, httpResponse); } @Override public void destroy() { System.out.println("過(guò)濾器Filter銷(xiāo)毀"); } }
web.xml配置:
<filter> <filter-name>encodingFilter</filter-name> <!-- <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> --> <filter-class>com.cn.util.FilterUtil</filter-class> <async-supported>true</async-supported> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
chain.doFilter(request, response)這個(gè)方法的調(diào)用作為分水嶺。事實(shí)上調(diào)用Servlet的doService()方法是在chain.doFilter(request, response)這個(gè)方法中進(jìn)行的。
preHandle()這個(gè)方法是在過(guò)濾器的chain.doFilter(request, response)方法的前一步執(zhí)行。 postHandle()方法之后,在return ModelAndView之前進(jìn)行,可以操控Controller的ModelAndView內(nèi)容。 afterCompletion()方法是在過(guò)濾器返回給前端前一步執(zhí)行,也就是在[chain.doFilter(request, response)][System.out.println("after...")]之間執(zhí)行。
注意:重定向:會(huì)在當(dāng)前頁(yè)面代碼執(zhí)行完畢后,跳轉(zhuǎn)到指定的頁(yè)面執(zhí)行其他代碼。 轉(zhuǎn) 發(fā):在本頁(yè)面代碼執(zhí)行到轉(zhuǎn)發(fā)語(yǔ)句后,即跳轉(zhuǎn)到指定的頁(yè)面執(zhí)行其他代碼,執(zhí)行完畢后返回接著執(zhí)行轉(zhuǎn)發(fā)語(yǔ)句后的代碼。
/** * 用戶(hù)身份認(rèn)證的攔截器 */ public class LoginInterceptor implements HandlerInterceptor { @Value("${TT_TOKEN_KEY}") private String TT_TOKEN_KEY; @Value("${SSO_URL}") private String SSO_URL; @Autowired private UserLoginService loginservice; //在進(jìn)入目標(biāo)方法之前執(zhí)行 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //用戶(hù)的身份認(rèn)證在此驗(yàn)證 //1.取cookie中的token //1.從cookie中獲取用戶(hù)的token String token = CookieUtils.getCookieValue(request, TT_TOKEN_KEY); //2.判斷token是否存在, if(StringUtils.isEmpty(token)){ //3.如果不存在,說(shuō)明沒(méi)登錄 ---》重定向到登錄的頁(yè)面 //request.getRequestURL().toString():就是訪(fǎng)問(wèn)的URL localhost:8092/order/order-cart.html response.sendRedirect(SSO_URL+"/page/login?redirect="+request.getRequestURL().toString()); return false; } //4.如果token存在,調(diào)用SSO的服務(wù) 查詢(xún)用戶(hù)的信息(看是否用戶(hù)已經(jīng)過(guò)期) TAotaoresult result = loginservice.getUserByToken(token); if(result.getStatus()!=200){ //5.用戶(hù)已經(jīng)過(guò)期 --》重定向到登錄的頁(yè)面 response.sendRedirect(SSO_URL+"/page/login?redirect="+request.getRequestURL().toString()); return false; } //6.用戶(hù)沒(méi)過(guò)期(說(shuō)明登錄了)--》放行 //設(shè)置用戶(hù)信息到request中 ,目標(biāo)方法的request就可以獲取用戶(hù)的信息 request.setAttribute("USER_INFO", result.getData()); return true; } //在進(jìn)入目標(biāo)方法之后,在返回modelandview之前執(zhí)行 //共用變量的一些設(shè)置。 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // TODO Auto-generated method stub } //返回modelandview之后,渲染到頁(yè)面之前 //異常處理 ,清理工作 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // TODO Auto-generated method stub } }
SpringMVC的機(jī)制是由同一個(gè)Servlet來(lái)分發(fā)請(qǐng)求給不同的Controller,其實(shí)這一步是在Servlet的service()方法中執(zhí)行的。所以過(guò)濾器、攔截器、service()方法,dispatche'r()方法的執(zhí)行順序如下
攔截器更加適合做細(xì)粒度的Handler控制,尤其是一些公共處理代碼,授權(quán)校驗(yàn)等,過(guò)濾器更加適合請(qǐng)求內(nèi)容和視圖內(nèi)容的相關(guān)處理,比如multipart 表單,GZIP壓縮等。 回頭在看之前的疑惑,最佳的解決方案是使用攔截器做登錄校驗(yàn)。
“過(guò)濾器Filter和攔截器HandlerIntercepter的區(qū)別及用法”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。