关于java:为了一个HTTP请求问题差点和iOS干起来

48次阅读

共计 3893 个字符,预计需要花费 10 分钟才能阅读完成。

本次斗殴事件起因全副归 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…

更多精彩内容请关注微信公众号: 一个程序员的成长

正文完
 0