本次斗殴事件起因全副归 iOS,为啥这么说,http 申请都不会发,瞎写的什么玩意(ps:他应该不会看到 …)。
在解决本次抵触中,意外发现了另外一个存在已久的 bug,咱们先说说这个玩意,再说咱们之间的恩怨。因为这是非亲非故的。
SpringBoot 中的过滤器
过滤器这货色应该很常见了,然而你的过滤器真的起到拦挡的作用了,这里就算你起到拦挡的作用了,然而你的过滤器能拦挡到指定的门路吗?先看一下我原始写法。
审慎参考:
@WebFilter(filterName = "baseFilter", urlPatterns = "/*")
public class BaseFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) {System.out.println("baseFilter 拦挡了 /*");
filterChain.doFilter(req, resp);
}
}
首先这里说下,如果你这是特地单纯的加个 @WebFilter 就认为 ok 了,那我通知你,脸会被打的很疼的。
因为这个注解是 servlet 的,所以你肯定要记得在启动类上加 @ServletComponentScan 此注解,这样在利用启动的时候,过滤器才会被扫描到。
咱们写了一个 Controller 的接口拜访了下,能够看到拦截器的确拦挡到了咱们的申请。
你认为的只是你认为
咱们我的项目有时候大了,不晓得引入了什么货色,有时候会导致这个过滤器呢就无奈被注入,看到那行报错呢可能脑子还没反馈过去,然而 CV 大法曾经关上了度娘,找到了问题起因,度娘说你加个 @Commponent 注解好了。而后也的确好了,而后接下来他都如何操作。
@Component
@WebFilter(filterName = "baseFilter", urlPatterns = "/user/*")
public class BaseFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) {HttpServletRequest request = (HttpServletRequest) req;
String url = request.getRequestURL().toString();
System.out.println(url);
System.out.println("baseFilter 拦挡了 /*");
filterChain.doFilter(req, resp);
}
}
然而,不巧的是加了 @Component 注解尽管解决了问题,然而呢 urlPatterns 拦挡的指定门路却没有失效。
我这里是一个 pub 结尾的申请,拦截器拦挡的 user 结尾的,而后如下:
他竟然将所有的申请给我拦挡了下来,不是我设想的那样,那咱们该如何解决这种问题呢?往下看同学。
SpringBoot 如何注入过滤器
这里我就不列举泛滥的注入形式了,免得混同大家,我就间接通知你们怎么正确注入就 ok 了,自己曾经亲测,而且治理起来很是不便。
过滤器写法
过滤器除了实现 Filter 之外,不要加任何的货色,就是这么简略。
public class BaseFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) {HttpServletRequest request = (HttpServletRequest) req;
String url = request.getRequestURL().toString();
System.out.println(url);
System.out.println("baseFilter 拦挡了 /*");
filterChain.doFilter(req, resp);
}
}
过滤器注入
咱们这里间接通过配置类的形式将过滤器注入,这样呢,咱们这里也高深莫测,看到咱们所有的过滤器,以及过滤器规定。
上面的这些参数都是根本配置,根本都是必填,name 你就写过滤器的类名,首字母小写就好了,order 就是过滤器的执行程序,数字越小,越先执行。
这样咱们一个残缺的过滤器就配置好了。当你再拜访 /pub 接口时,是不会被 BaseFilter 拦挡到的。
这里也举荐大家当前尽量这样去配置。
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<BaseFilter> baseFilter() {FilterRegistrationBean<BaseFilter> filterBean = new FilterRegistrationBean<>();
filterBean.setFilter(new BaseFilter());
filterBean.setName("baseFilter");
filterBean.addUrlPatterns("/user/*");
filterBean.setOrder(1);
return filterBean;
}
}
我与 iOS 的一战
咱们先看报的错,再来聊聊这次的锅我是怎么甩的
RequestRejectedException: The request was rejected because the URL was not normalized.
看到没因为网址不规范,导致申请被回绝。
非说我接口有问题,原本想奋起镇压,看到对方比我身材威猛,想想还是抓到实质性证据在甩他吧。
既然说申请网址不正确,我猜想就是申请门路中是不是有什么猫腻,那咱们就抓包呗。
最初在咱们各种伎俩之下拿到了真凭实据。诸位法官请看:
他的申请门路:http://127.0.0.1:8080//user/list
他的申请门路中呈现了双斜杠,这样必定报错啊。这里须要阐明下,报错是因为引入了 Security 平安框架。
既然曾经确定问题,那我必须奋起镇压,找他甩锅,当他看到这个时候,对吧本人也无话可说,只能默默的把锅背上。
就这样我这次又顺利的甩锅胜利。
解决与反思
尽管锅甩出去了,然而问题还是要解决的。
其实按失常逻辑来说,不论咱们引入了什么货色,只有申请门路正确,及时门路中呈现再多的斜杠,咱们也应该做好解决,不能影响用户的拜访。所以咱们就通过过滤器就行一个解决。
public class UriFormatFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain)
throws ServletException, IOException {
// 门路隔离符号
String separateSymbol = "/";
String uri = req.getRequestURI();
StringBuilder newUrl = new StringBuilder();
String[] split = uri.split(separateSymbol);
for (String s : split) {if (StringUtils.isNotBlank(s)) {newUrl.append(separateSymbol).append(s);
}
}
req = new HttpServletRequestWrapper(req) {
@Override
public String getRequestURI() {return newUrl.toString();
}
};
filterChain.doFilter(req, res);
}
}
最初将过滤器注入
这里 order 为啥写 -100,如果你写 1,你认为它会是第一个执行,其实不然,在执行他之前,可能框架的一些过滤器会先执行,所以为了保险起见,咱们就设置为 -100,确保申请进来之后先走它。
@Bean
public FilterRegistrationBean<UriFormatFilter> uriFormatFilter() {FilterRegistrationBean<UriFormatFilter> filterBean = new FilterRegistrationBean<>();
filterBean.setFilter(new UriFormatFilter());
filterBean.setName("uriFormatFilter");
filterBean.addUrlPatterns("/*");
filterBean.setOrder(-100);
return filterBean;
}
留神
如果你在过滤器中留神一些 Mapper、Service 之类的话,可能会呈现问题,调用的时候被注入的对象可能是个 null,这就波及到类的加载程序,我就不在这里 bibi 了,真有人遇到了再说。反正我曾经解决了 [Doge]。
参考文章:
https://blog.csdn.net/chenmen…
https://blog.csdn.net//qq_300…
更多精彩内容请关注微信公众号: 一个程序员的成长