Spring Boot:注入自定义上下文路径

2024-01-10

我正在运行带有嵌入式 Tomcat 的 Spring Boot 1.2.3 应用程序。

我想根据 URL 的第一部分在每个请求上注入自定义 contextPath。

例子:

  1. http://localhost:8080/foo默认情况下有contextPath=""并且应该得到contextPath="foo"

  2. http://localhost:8080/foo/bar默认情况下有contextPath=""并且应该得到contextPath="foo"

(没有路径的 URL 应保持原样)

我尝试写一个自定义的javax.servlet.Filter with @Order(Ordered.HIGHEST_PRECEDENCE),但似乎我错过了一些东西。这是代码:

@Component @Order(Ordered.HIGHEST_PRECEDENCE)
public class MultiTenancyFilter implements Filter {
    private final static Pattern pattern = Pattern.compile("^/(?<contextpath>[^/]+).*$");

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        final HttpServletRequest req = (HttpServletRequest) request;
        final String requestURI = req.getRequestURI();

        Matcher matcher = pattern.matcher(requestURI);
        if(matcher.matches()) {
            chain.doFilter(new HttpServletRequestWrapper(req) {
                @Override
                public String getContextPath() {
                    return "/"+matcher.group("contextpath");
                }
            }, response);
        }
    }

    @Override public void init(FilterConfig filterConfig) throws ServletException {}
    @Override public void destroy() {}
}

这应该简单地获取第一个之后的字符串/以及在第二个之前(如果有的话)/然后将其用作返回值getContextPath().


但是 Spring @Controller @RequestMapping 和 Spring Security 的antMatchers("/")似乎并不尊重它。两者仍然工作,好像contextPath="".


如何动态覆盖每个请求的上下文路径?


成功了!

Spring 安全文档(http://docs.spring.io/spring-security/site/docs/3.1.x/reference/security-filter-chain.html http://docs.spring.io/spring-security/site/docs/3.1.x/reference/security-filter-chain.html ) say: “Spring Security 只对保护应用程序内的路径感兴趣,因此 contextPath 被忽略。不幸的是,servlet 规范没有准确定义 servletPath 和 pathInfo 的值将包含特定请求 URI 的内容。[...] 该策略是在 AntPathRequestMatcher 类中实现的,它使用 Spring 的 AntPathMatcher 对连接的 servletPath 和 pathInfo 执行不区分大小写的模式匹配,忽略 queryString。”

所以我只是覆盖了servletPath and contextPath(即使 Spring Security 不使用它)。另外,我添加了一些小的重定向,因为通常在点击时http://localhost:8080/myContext您将被重定向到http://localhost:8080/myContext/Spring Security Antmatcher 不喜欢缺少尾部斜杠。

所以这是我的MultiTenancyFilter code:

@Component @Order(Ordered.HIGHEST_PRECEDENCE)
public class MultiTenancyFilter extends OncePerRequestFilter {
    private final static Pattern pattern = Pattern.compile("^(?<contextPath>/[^/]+)(?<servletPath>.*)$");

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        Matcher matcher = pattern.matcher(request.getServletPath());
        if(matcher.matches()) {
            final String contextPath = matcher.group("contextPath");
            final String servletPath = matcher.group("servletPath");

            if(servletPath.trim().isEmpty()) {
                response.sendRedirect(contextPath+"/");
                return;
            }

            filterChain.doFilter(new HttpServletRequestWrapper(request) {
                @Override
                public String getContextPath() {
                    return contextPath;
                }
                @Override
                public String getServletPath() {
                    return servletPath;
                }
            }, response);
        } else {
            filterChain.doFilter(request, response);
        }
    }

    @Override
    protected String getAlreadyFilteredAttributeName() {
        return "multiTenancyFilter" + OncePerRequestFilter.ALREADY_FILTERED_SUFFIX;
    }
}

它只是使用此处提到的 URL 模式提取 contextPath 和 servletPath:https://theholyjava.wordpress.com/2014/03/24/httpservletrequest-requesturirequesturlcontextpathservletpathpathinfoquerystring/ https://theholyjava.wordpress.com/2014/03/24/httpservletrequest-requesturirequesturlcontextpathservletpathpathinfoquerystring/

另外我必须提供一个自定义的getAlreadyFilteredAttributeName方法,因为否则过滤器被调用两次。 (这导致剥离contextPath twice)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring Boot:注入自定义上下文路径 的相关文章

随机推荐

  • 如何更改levatedButtonTheme中的ElevatedButton文本颜色?

    我正在尝试更改主题中levatedButtonTheme 属性中的ElevatedButton 文本颜色 但无法更改 我知道 Text 的子元素中的 TextStyle 可以更改 Text 的颜色 但我更喜欢在levedButtonThem
  • 什么是格洛姆?它与mapPartitions有何不同?

    我遇到过glom RDD 上的方法 根据文档 返回通过将每个分区内的所有元素合并到数组中创建的 RDD Does glom跨分区混洗数据还是仅将分区数据作为数组返回 在后一种情况下 我相信使用同样可以实现mapPartitions 我还想知
  • 如何在 mysql (laravel) 中使 varchar 可以为空且唯一

    我可以使 MySQL 列可以为空并且唯一吗 我有一个存储用户 Email id 的表 如果用户想提供的话 否则它将是 空 我在其他一些问题中读到我可以创建一个默认为 NULL 的唯一字段 但我在创建表时收到此错误 1067 Invalid
  • OS X cmake 找不到 PythonLibs 3.4

    python 和 python3 通过 Homebrew 安装在 OS X Yosemite 中 但 cmake 找不到 PythonLibs 3 只有 2 个 CMakeLists txt set Python ADDITIONAL VE
  • 从 Postgres JDBC 中的结果集中读取 UUID

    我正在使用 UUID 作为我的 id 列 我正在寻找一种方法来检索我的 Java 应用程序中的数据 我在 ResultSet 中找不到获取 UUID 的方法 我该如何获取 UUID 对于任何搜索的人来说 这是如何完成的 java util
  • 使用 OAuth 2.0 通过 SMACK Java 库进行 X-FACEBOOK-PLATFORM 身份验证

    第一次在这里发帖 所以请温柔 我正在使用 Smack 库构建一个 Facebook 聊天客户端 我正在使用 X FACEBOOK PLATFORM 方法 以免保存任何密码 我使用 oauth 1 0 使其正常工作 并想将其更改为 2 0 这
  • javascript for 循环内的异步过程[重复]

    这个问题在这里已经有答案了 我正在运行以下形式的事件循环 var i var j 10 for i 0 i lt j i asynchronousProcess callbackFunction alert i 我试图显示一系列显示数字 0
  • Objective-C JSON - 将 JSON 对象转换为本机对象?

    status FRE list make Toyota id 1 model camry engine Four Cylinder make Ford id 3 model focus engine Four Cylinder 我如何提取每
  • 如何在 PHP CURL 中从 POST 切换到 GET

    我尝试过从以前的 Post 请求切换到 Get 请求 它假设它是一个 Get 但最终会发布一个帖子 我在 PHP 中尝试了以下操作 curl setopt curl handle CURLOPT POSTFIELDS null curl s
  • iPhone:可以只改变UINavigationBar提示的颜色吗?

    我想知道是否可以仅更改 UINavigationBar 提示的背景颜色 例如 更改为红色 而导航栏的其余部分保持黑色 以便我可以使用 UINavigationItem 的提示属性来显示状态 错误消息作为单行 这是一个老问题 但自从引入app
  • 如何在远程机器中生成 docker 容器

    是否有可能 使用适用于 Python 的 Docker SDK https docker py readthedocs io en stable index html 在远程计算机中启动容器 import docker client doc
  • GitHub 工作流程中针对特定目录的 git Shortlog

    我想打印 GitHub 工作流程中特定目录 我的存储库的一部分 的简短日志 我使用git命令git shortlog e n s myFolder 我用checkout v3检查我的存储库 拉取请求的操作如下 uses actions ch
  • 除非设置了调试标志,否则隐藏回溯

    除非设置了详细或调试标志 否则隐藏回溯错误的惯用Python方法是什么 示例代码 their md5 c38f03d2b7160f891fc36ec776ca4685 my md5 c64e53bbb108a1c65e31eb4d1bb8e
  • 从n个列表中生成灯具

    假设我有 N 支球队 如何生成一个赛程列表 其中每支球队都与其他球队比赛 对此的最佳实践是什么 有没有一种已知的算法可以很好地做到这一点 效率并不是真正的必需品 因为它只需要每个赛季产生一次 更具体地说 我将从一些定义开始 我有 N 个团队
  • PHP 中的绝对(或相对?)路径

    抱歉问这个问题 因为之前可能已经回答过很多次了 但我的问题有点不同 我有像树一样 var www path to my app index php b php inc include php 我正在从index php访问inc inclu
  • 如何获取 Django 模型中字段的默认值?

    我有一个 Django 模型 其中一些字段指定了默认值 我希望稍后在我的代码中为我们获取这些字段之一的默认值 有没有一种简单的方法可以从模型中获取特定字段的默认值 TheModel meta get field the field get
  • 单独的红绿蓝rgba值颜色值

    I hv rgba这种格式的值RGBA 205 31 31 1 我想分离每个红色 绿色 蓝色和 alpha 值以进行进一步处理 如何使用 jQuery 实现它 所以输出看起来像 red 205 green 31 blue 31 alpha
  • Linq 查询 - 根据首字母黑白两个范围查找字符串

    我们有一个包含国家名称的列表 我们需要从黑白两个字母的列表中查找国家 地区名称 就像所有国家 地区名称以黑白 A G 开头的名称等 我们创建以下 linq 查询 但它很难看 var countryAG from elements in co
  • Airplay:从 MPMoviePlayerController 播放电影会导致仅音频流式传输到 Apple 电视

    设置 Airplay 非常简单 self moviePlayer MPMoviePlayerViewController alloc initWithContentURL url autorelease self moviePlayer s
  • Spring Boot:注入自定义上下文路径

    我正在运行带有嵌入式 Tomcat 的 Spring Boot 1 2 3 应用程序 我想根据 URL 的第一部分在每个请求上注入自定义 contextPath 例子 http localhost 8080 foo默认情况下有context