当前位置:   article > 正文

过滤器实现URL拦截,跳转URL_filter怎么拦截特定的url

filter怎么拦截特定的url

过滤器实现URL拦截,跳转URL

一,背景

业务存在pc和pad两个客户端,pc已经上线。并且pc和pad大部分的接口都可以复用,为了避免重复的代码写2份(即相同的controller),所以目标是pc和pad共用controller,至于pad新的接口,则pad专属。

二,实现

为了实现pc和pad接口公用,pad会在url上传入特定的前缀,比如/pad。

使用过滤器,在DispatcherServlet#doDispatch方法执行前,将url进行替换。
AbstractHandlerMethodMapping的属性mappingRegistry,是保存了URL相关信息,以及handlerMethod的相关信息的,并且在Spring初始化的时候,在对象RequestMappingHandlerMapping里会被赋值。
于是替换思路就有了:
1.在过滤器中拦截url
2.如果URL不包含目标前缀,则FilterChain#doFilter正常放过
3.否则在Spring容器中取出, 并且通过该对象的getHandlerMethods(),拿到保存的URL相关的handlerMethodsMap
4.通过该map能找到信息的,就意味着是pad端独有的接口,通过FilterChain#doFilter正常放过
5.找不到信息的,就将URL中目标前缀替换为空后执行FilterChain#doFilter进行放过。

三,实现代码

拦截器

@Slf4j
@Component
public class MyOncePerRequestFilter extends OncePerRequestFilter {


    private static final String PREFIX = "/pad";

    // 从spring里面拿  RequestMappingHandlerMapping

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {


        String originalRequestURI = request.getRequestURI();
        if (StrUtil.isNotEmpty(originalRequestURI)) {
            // http://localhost:8002/v1/te/turn/get/query?item=95270244541
            // 输出的结果:===== 获取的 requestURI:/v1/te/turn/get/query
            System.out.println("===== 获取的 requestURI:" + originalRequestURI);

            if (originalRequestURI.contains(PREFIX)) {

                // {GET /v1/te/turn/get/query}
                String httpMethodType = request.getMethod();
                String queryURI = "{" + httpMethodType + " " + originalRequestURI + "}";

                // 在DispatcherServlet存放urls里面找,找不到则去掉prefix
                if (!MyUrlMappingContainer.urlMappingContainer.contains(queryURI)) {

                    String targetURI = originalRequestURI.replace(PREFIX, "");
                    StringBuffer requestURL = request.getRequestURL();
                    String tempURLStr = requestURL.toString();
                    StringBuffer stringBuilder = new StringBuffer(tempURLStr.replace(PREFIX, ""));

                    // 内部类的写法
                    final HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(request) {

                        @Override
                        public StringBuffer getRequestURL() {
                            return stringBuilder;
                        }

                        @Override
                        public String getRequestURI() {
                            return targetURI;
                        }

                        @Override
                        public String getServletPath() {
                            return targetURI;
                        }
                    };

                    filterChain.doFilter(requestWrapper, response);
                    return;
                }
            }
        }

        filterChain.doFilter(request, response);

    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

封装的获取Spring初始的URL信息

@Order
@Component
public class MyUrlMappingContainer {

    static final List<String> urlMappingContainer = new ArrayList<>();

    @Autowired
    public void initContainer(ApplicationHelper applicationHelper) {

        RequestMappingHandlerMapping mapping = applicationHelper.getBeanByClass(RequestMappingHandlerMapping.class);
        // Key 是个对象 requestMappingInfo
        // RequestMappingInfo requestMappingInfo = new RequestMappingInfo();
        Map handlerMethodsMap = mapping.getHandlerMethods();

        for (Object obj : handlerMethodsMap.keySet()) {

            urlMappingContainer.add(obj.toString());
        }

        System.out.println(JSON.toJSONString(urlMappingContainer));
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

ps:
如何找到RequestMappingHandlerMapping 类的
通过断点调试

在controller打上断点,比如:
在这里插入图片描述
然后找调用堆栈
就能找到DispatcherServlet这个分发器,以及在这个DispatcherServlet之前执行的filter(这个顺序就印证了过滤器是在请求分发前执行的)

找到这个方法,断点进入 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#invokeHandlerMethod
在这里插入图片描述

往上找
找到这个方法
org.springframework.web.servlet.DispatcherServlet#getHandler


可以看出 mappedHandler = getHandler(processedRequest);这个方法,通过请求,返回了匹配的controller方法。也就是说这个方法就是关键。
后续的就不写了。哈哈哈哈哈

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/编程谜题解决者/article/detail/61344
推荐阅读
相关标签
  

闽ICP备14008679号