本次斗殴事件起因全部归iOS,为啥这么说,http请求都不会发,瞎写的什么玩意(ps:他应该不会看到。。。)。 在处理本次冲突中,意外发现了另外一个存在已久的bug,我们先说说这个玩意,再说我们之间的恩怨。因为这是息息相关的。SpringBoot中的过滤器 过滤器这东西应该很常见了,但是你的过滤器真的起到拦截的作用了吗?这里就算你起到拦截的作用了,但是你的过滤器能拦截到指定的路径吗?先看一下我原始写法。 谨慎参考:WebFilter(filterNamebaseFilter,urlPatterns)publicclassBaseFilterimplementsFilter{OverridepublicvoiddoFilter(ServletRequestreq,ServletResponseresp,FilterChainfilterChain){System。out。println(baseFilter拦截了);filterChain。doFilter(req,resp);}} 首先这里说下,如果你这是特别单纯的加个WebFilter就以为ok了,那我告诉你,脸会被打的很疼的。 因为这个注解是servlet的,所以你一定要记得在启动类上加ServletComponentScan此注解,这样在应用启动的时候,过滤器才会被扫描到。 我们写了一个Controller的接口访问了下,可以看到拦截器确实拦截到了我们的请求。 你以为的只是你以为 我们项目有时候大了,不知道引入了什么东西,有时候会导致这个过滤器呢就无法被注入,看到那行报错呢可能脑子还没反应过来,但是CV大法已经打开了度娘,找到了问题原因,度娘说你加个Commponent注解好了。然后也确实好了,然后接下来他都如何操作。ComponentWebFilter(filterNamebaseFilter,urlPatternsuser)publicclassBaseFilterimplementsFilter{OverridepublicvoiddoFilter(ServletRequestreq,ServletResponseresp,FilterChainfilterChain){HttpServletRequestrequest(HttpServletRequest)req;Stringurlrequest。getRequestURL()。toString();System。out。println(url);System。out。println(baseFilter拦截了);filterChain。doFilter(req,resp);}} 然而,不巧的是加了Component注解虽然解决了问题,但是呢urlPatterns拦截的指定路径却没有生效。 我这里是一个pub开头的请求,拦截器拦截的user开头的,然后如下: 他居然将所有的请求给我拦截了下来,不是我想象的那样,那我们该如何解决这种问题呢?往下看同学。SpringBoot如何注入过滤器 这里我就不列举众多的注入方式了,以免混淆大家,我就直接告诉你们怎么正确注入就ok了,本人已经亲测,而且管理起来很是方便。过滤器写法 过滤器除了实现Filter之外,不要加任何的东西,就是这么简单。publicclassBaseFilterimplementsFilter{OverridepublicvoiddoFilter(ServletRequestreq,ServletResponseresp,FilterChainfilterChain){HttpServletRequestrequest(HttpServletRequest)req;Stringurlrequest。getRequestURL()。toString();System。out。println(url);System。out。println(baseFilter拦截了);filterChain。doFilter(req,resp);}}过滤器注入 我们这里直接通过配置类的方式将过滤器注入,这样呢,我们这里也一目了然,看到我们所有的过滤器,以及过滤器规则。 下面的这些参数都是基本配置,基本都是必填,name你就写过滤器的类名,首字母小写就好了,order就是过滤器的执行顺序,数字越小,越先执行。 这样我们一个完整的过滤器就配置好了。当你再访问pub接口时,是不会被BaseFilter拦截到的。 这里也推荐大家以后尽量这样去配置。ConfigurationpublicclassFilterConfig{BeanpublicFilterRegistrationBeanBaseFilterbaseFilter(){FilterRegistrationBeanBaseFilterfilterBeannewFilterRegistrationBean();filterBean。setFilter(newBaseFilter());filterBean。setName(baseFilter);filterBean。addUrlPatterns(user);filterBean。setOrder(1);returnfilterBean;}}我与iOS的一战 我们先看报的错,再来聊聊这次的锅我是怎么甩的RequestRejectedException:TherequestwasrejectedbecausetheURLwasnotnormalized。 看到没因为网址不标准,导致请求被拒绝。 非说我接口有问题,本来想奋起反抗,看到对方比我身材威猛,想想还是抓到实质性证据在甩他吧。 既然说请求网址不正确,我猜测就是请求路径中是不是有什么猫腻,那我们就抓包呗。 最后在我们各种手段之下拿到了真凭实据。诸位法官请看:他的请求路径:http:127。0。0。1:8080userlist 他的请求路径中出现了双斜杠,这样肯定报错啊。这里需要说明下,报错是因为引入了Security安全框架。 既然已经确定问题,那我必须奋起反抗,找他甩锅,当他看到这个时候,对吧自己也无话可说,只能默默的把锅背上。 就这样我这次又顺利的甩锅成功。解决与反思 虽然锅甩出去了,但是问题还是要解决的。 其实按正常逻辑来说,不管我们引入了什么东西,只要请求路径正确,即使路径中出现再多的斜杠,我们也应该做好处理,不能影响用户的访问。所以我们就通过过滤器进行一个处理。publicclassUriFormatFilterextendsOncePerRequestFilter{OverrideprotectedvoiddoFilterInternal(HttpServletRequestreq,HttpServletResponseres,FilterChainfilterChain)throwsServletException,IOException{路径隔离符号StringseparateSymbol;Stringurireq。getRequestURI();StringBuildernewUrlnewStringBuilder();String〔〕splituri。split(separateSymbol);for(Strings:split){if(StringUtils。isNotBlank(s)){newUrl。append(separateSymbol)。append(s);}}reqnewHttpServletRequestWrapper(req){OverridepublicStringgetRequestURI(){returnnewUrl。toString();}};filterChain。doFilter(req,res);}} 最后将过滤器注入 这里order为啥写100,如果你写1,你以为它会是第一个执行,其实不然,在执行他之前,可能框架的一些过滤器会先执行,所以为了保险起见,我们就设置为100,确保请求进来之后先走它。BeanpublicFilterRegistrationBeanUriFormatFilteruriFormatFilter(){FilterRegistrationBeanUriFormatFilterfilterBeannewFilterRegistrationBean();filterBean。setFilter(newUriFormatFilter());filterBean。setName(uriFormatFilter);filterBean。addUrlPatterns();filterBean。setOrder(100);returnfilterBean;}注意 如果你在过滤器中注入了一些Mapper、Service之类的话,可能会出现问题,调用的时候被注入的对象可能是个null,这就涉及到类的加载顺序,我就不在这里bibi了,真有人遇到了再说。反正我已经解决了〔Doge〕。撕逼阶段 开发中,特别是小公司,很需要会多端的人来协调问题;有时候这种问题恶心之处在于:后端可以解决,移动端也可以解决,谁处理了显得就是谁的问题。 各位你们平时都是怎么拉扯的呢?