栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

过滤器实现URL拦截,跳转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);

    }

}

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

@Order
@Component
public class MyUrlMappingContainer {

    static final List 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));
    }
}

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方法。也就是说这个方法就是关键。
后续的就不写了。哈哈哈哈哈

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/860040.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号