为了一个HTTP请求问题,差点跟iOS干起来
本次斗殴事件起因全部归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/chenmengyijiu/article/details/84561302 https://blog.csdn.net//qq_30062181/article/details///84964691
日拱一卒,功不唐捐
本文分享自微信公众号 - 一个程序员的成长(xiaozaibuluo)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
mysql数据库优化
PS:随着业务的发展,数据量越来越大了。不能再像之前一样随意查询了,数据库优化势在必行。所以这里总结一下mysql数据库有哪些优化的方法 一、数据库优化的大致分类 1、数据库层面的优化 2、硬件层面的优化 数据库层面的优化: (1)、影响数据库查询速度的几大因素一是表结构的设计是否合理, 特别是表中的列是否设置了合适的数据类型,是否设置了合适的数据长度以及是否适配了实际的工作场景,例如需要经常更新的表往往有着较少的列,而需要经常分析大量数据的表则有着更多的列。所以一切还是以实际情况为主。 (2)、建立的索引是否生效 (3)、是否使用了合适的存储引擎,mysql数据库有多个存储引擎,不同的存储引擎有着不同的特点,以主键索引为例,在InnoDB引擎中主键索引时将数据存储在叶子节点中,而在myism引擎中则是将数据存储在辅助表,并且所有的数据都是存储在一个.MYD的文件中。所以在适当的时候选择适当的存储引擎对于数据的查询等也是非常有效的。 (4)、数据库表是否使用了固定的行格式,如是否使用了压缩,MySQL表压缩是一个十分实用的功能,mysql中的数据在未指定表压缩时默认使用的存储方式是一页...
- 下一篇
浅谈数据仓库质量管理规范
大家好,我是一哥,今天和大家聊一下如何管理数据仓库质量如何管理。 一、 背景 现在数据仓库层面的工作越来越多,开发人员也越来越多,如何保障数据准确性是一项非常重要的工作,,数据仓库的很多应用数据直接呈现给用户或者支撑企业分析决策的,容不得数据出现错误。随着开展的业务越来越多,数据模型越来也多,我们管控的越晚就越容易出问题。尽管有数据仓库建设规范,同样在数据模型命名,数据逻辑开发,每个人都可能不一样,而这些也容易导致数据模型准确性的问题。我们迫切需要制定一套数据的准确性验证流程,让大家都按规范流程来做,保障数据的准确性。 二、 数据指标管理 首先我们看下数据仓库的数据流转,要确认计算出的指标正确,就要保证数据源的准确和逻辑的准确。 所以开发前需要确认需求理解的准确性。根据“需求模板”完善所开发的需求,遇到提出的模糊定义,需要和业务人员确认指标口径的准确性。 需求模板主要包含业务分类、指标名称、是否新增、统计周期、指标维度、业务口径、技术口径、数据源表、需求提出人、需求提出日期、优先级等: 开发数据指标过程分为四部分:看、查、管、控。 1. 看 首先我们要对开发出的指标结果数据进行查看,是...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS关闭SELinux安全模块
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Docker安装Oracle12C,快速搭建Oracle学习环境
- SpringBoot2全家桶,快速入门学习开发网站教程
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- CentOS6,CentOS7官方镜像安装Oracle11G