一、关系图理解 二、区别1。过滤器过滤器是在web应用启动的时候初始化一次,在web应用停止的时候销毁可以对请求的URL进行过滤,对敏感词过滤挡在拦截器的外层实现的是javax。servlet。Filter接口,是Servlet规范的一部分在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后依赖Web容器会多次执行1。1HttpServletRequestWrapper 在请求到达之前对request进行修改packagecom。dingwen。lir。importlombok。extern。slf4j。Slf4j;importjavax。servlet。http。HttpServletRimportjavax。servlet。http。HttpServletRequestWimportjava。util。A在请求到达之前对request进行修改authordingwenSlf4jpublicclassRequestWrapperextendsHttpServletRequestWrapper{publicRequestWrapper(HttpServletRequestrequest){super(request);log。info(RequestWrapper);}OverridepublicStringgetParameter(Stringname){可以对请求参数进行过滤returnsuper。getParameter(name);}OverridepublicString〔〕getParameterValues(Stringname){对请求参数值进行过滤String〔〕valuessuper。getRequest()。getParameterValues(name);returnsuper。getParameterValues(name);returntest。split();}}1。2OncePerRequestFilter OncePerRequestFilter,顾名思义,它能够确保在一次请求中只通过一次filterpackagecom。dingwen。lir。importlombok。extern。slf4j。Slf4j;importorg。springframework。web。filter。OncePerRequestFimportjavax。servlet。FilterCimportjavax。servlet。ServletEimportjavax。servlet。http。HttpServletRimportjavax。servlet。http。HttpServletRimportjava。io。IOEimportjava。io。PrintWimportjava。util。A请求过滤器OncePerRequestFilter:OncePerRequestFilter,顾名思义,它能够确保在一次请求中只通过一次filter。大家常识上都认为,一次请求本来就只filter一次,为什么还要由此特别限定呢,往往我们的常识和实际的实现并不真的一样,经过一番资料的查阅,此方法是为了兼容不同的webcontainer,也就是说并不是所有的container都入我们期望的只过滤一次,servlet版本不同,执行过程也不同,因此,为了兼容各种不同运行环境和版本,默认filter继承OncePerRequestFilter是一个比较稳妥的选择。authordingwenSlf4jpublicclassRequestFilterextendsOncePerRequestFilter{Overridepublicvoiddestroy(){super。destroy();log。info(RequestFilterdestroy);}OncePerRequestFilter。doFilter方法中通过request。getAttribute判断当前过滤器是否已执行若未执行过,则调用doFilterInternal方法,交由其子类实现OverrideprotectedvoiddoFilterInternal(HttpServletRequesthttpServletRequest,HttpServletResponsehttpServletResponse,FilterChainfilterChain)throwsServletException,IOException{try{RequestWrapperrequestWrappernewRequestWrapper(httpServletRequest);filterChain。doFilter(requestWrapper,httpServletResponse);log。info(RequestFilter);log。info(Arrays。toString(requestWrapper。getParameterValues(name)));}catch(Exceptionexception){httpServletResponse。setCharacterEncoding(utf8);httpServletResponse。setContentType(charsetutf8);PrintWriterwriterhttpServletResponse。getWriter();writer。write(exception。toString());}}}1。3配置packagecom。dingwen。lir。importcom。dingwen。lir。filter。RequestFimportcom。dingwen。lir。filter。RequestWimportorg。springframework。boot。web。servlet。FilterRegistrationBimportorg。springframework。context。annotation。Bimportorg。springframework。context。annotation。Cimportjavax。servlet。F过滤器配置类authordingwenConfigurationpublicclassFilterConfig{BeanpublicRequestFilterrequestFilter(){returnnewRequestFilter();}BeanpublicFilterRegistrationBeanRequestFilterregistrationBean(){FilterRegistrationBeanRequestFilterregistrationBeannewFilterRegistrationBean();registrationBean。setFilter(requestFilter());registrationBean。addUrlPatterns(filter);registrationBean。setName(RequestFilter);过滤器的级别,值越小级别越高越先执行registrationBean。setOrder(1);returnregistrationB}}2。拦截器实现org。springframework。web。servlet。HandlerInterceptor接口,动态代理拦截器应用场景,性能分析,权限检查,日志记录是一个Spring组件,并由Spring容器管理,并不不依赖Tomcat等容器,是可以单独使用的。不仅能应用在web程序中,也可以用于Application、Swing等程序中是在请求进入servlet后,在进入Controller之前进行预处理的,Controller中渲染了对应的视图之后请求结束2。1登录拦截packagecom。dingwen。lir。importcom。dingwen。lir。entity。Uimportorg。springframework。stereotype。Cimportorg。springframework。util。ObjectUimportorg。springframework。web。servlet。HandlerIimportjavax。servlet。http。HttpServletRimportjavax。servlet。http。HttpServletRimportjava。io。IOE登录拦截authordingwenComponentpublicclassPageInterceptorimplementsHandlerInterceptor{OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{Useruser(User)request。getSession()。getAttribute(user);if(!ObjectUtils。isEmpty(user)){}else{不管是转发还是重定向,必须返回false。否则出现多次提交响应的错误redirect(request,response);}}对于请求是ajax请求重定向问题的处理方法paramrequestparamresponsepublicvoidredirect(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{if(XMLHttpRequest。equals(request。getHeader(XRequestedWith))){ajax获取当前请求的路径response。setHeader(AccessControlExposeHeaders,REDIRECT,CONTENTPATH);告诉ajax我是重定向response。setHeader(REDIRECT,REDIRECT);告诉ajax我重定向的路径StringBufferurlrequest。getRequestURL();StringcontextPathrequest。getContextPath();response。setHeader(CONTENTPATH,url。replace(url。indexOf(contextPath)contextPath。length(),url。length(),)。toString());}else{httpresponse。sendRedirect(pagelogin);}response。getWriter()。write(403);response。setStatus(HttpServletResponse。SCFORBIDDEN);}}2。2配置packagecom。dingwen。lir。importcom。dingwen。lir。interceptor。PageIimportorg。springframework。context。annotation。Cimportorg。springframework。web。servlet。config。annotation。InterceptorRimportorg。springframework。web。servlet。config。annotation。ResourceHandlerRimportorg。springframework。web。servlet。config。annotation。ViewControllerRimportorg。springframework。web。servlet。config。annotation。WebMvcCmvc控制器配置MyWebMvcConfigurer:Springboot2。x以后版本使用authordingwenConfigurationpublicclassMyWebMvcConfigurerimplementsWebMvcConfigurer{拦截器依赖于Spring容器,此处拦截了所有,需要对静态资源进行放行OverridepublicvoidaddInterceptors(InterceptorRegistryregistry){拦截器默认的执行顺序,就是它的注册顺序,也可以通过Order手动设置控制,值越小越先执行。registry。addInterceptor(newPageInterceptor())。addPathPatterns()。order()registry。addInterceptor(newPageInterceptor())。addPathPatterns()。excludePathPatterns(pagelogin,userlogin,pageajax,static);}不要要写控制器即可完成页面跳转访问paramregistryOverridepublicvoidaddViewControllers(ViewControllerRegistryregistry){registry。addViewController(pageajax)。setViewName(ajax);}自定义静态资源映射SpringBoot默认为我们提供了静态资源映射:classpath:METAINFresourcesclasspath:resourcesclasspath:staticclasspath:public优先级:METAINFresourcesresourcesstaticpublicparamregistryOverridepublicvoidaddResourceHandlers(ResourceHandlerRegistryregistry){registry。addResourceHandler(static)。addResourceLocations(classpath:static);registry。addResourceHandler(static)。addResourceLocations(file:E:static);}}3。监听器 实现javax。servlet。ServletRequestListener,javax。servlet。http。HttpSessionListener,javax。servlet。ServletContextListener等等接口 主要用来监听对象的创建与销毁的发生,比如session的创建销毁,request的创建销毁,ServletContext创建销毁三、注意1。静态资源问题 SpringBoot2。x以后版本拦截器也会拦截静态资源,在配置拦截器是需要将姿态资源放行。拦截器依赖于Spring容器,此处拦截了所有,需要对静态资源进行放行OverridepublicvoidaddInterceptors(InterceptorRegistryregistry){registry。addInterceptor(newPageInterceptor())。addPathPatterns()。excludePathPatterns(pagelogin,userlogin,pageajax,static);} SpringBoot2。x自定义静态资源映射spring:mvc:staticpathpattern:static 默认目录classpath:METAINFresourcesclasspath:resourcesclasspath:staticclasspath:public 优先级:METAINFresourcesresourcesstaticpublic2。登录拦截ajax重定向 由于ajax是异步的,还在当前页面进行的局部请求。当拦截到登录请求时,即使重定向也无法生效。需采用服务端给地址由前端进行跳转。详细见登录拦截器代码。前端处理!DOCTYPEhtmlhtmllangenheadmetacharsetUTF8titleAJAXtitleheadbodybuttonUSERbuttonbodyhtml四、测试 代码地址: https:gitee。comdingwengiteefilterinterceptorstudy。git1。拦截器测试1。1启动项目访问首页 http:localhost:8080pageindex 由于没有登录,直接重定向到了登录页 1。2输入用户名密码完成登录,调转到用户页 此时在访问首页 1。2退出登录 成功退出后,访问为授权的页面也相对会被重定向到登录页 1。3ajax未授权访问测试 点击访问user,由于未登录,没有全权访问。在前端进行了页面跳转,转到了登录页。 2。过滤器测试 可以看到过滤器进行了相对应的处理,重写的getParameterValues()也生效了。配合使用HttpServletRequestWrapperOncePerRequestFilter实现了对request的修改。 原文链接:https:mp。weixin。qq。comstKZDqPuOWbqrDyBhVRwoA