IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 过滤器实现URL拦截,跳转URL -> 正文阅读

[Java知识库]过滤器实现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<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));
    }
}

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

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-05-07 11:02:36  更:2022-05-07 11:04:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:59:07-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码