当前位置: 首页 > 知识库问答 >
问题:

在Spring Boot中区分嵌入式Tomcat中多个连接器/端口之间的请求

西门展
2023-03-14

我在多个端口上配置了一个基于Spring Boot rest服务的应用程序,该应用程序需要区分每个请求所经过的端口。为应用程序提供多个端口的想法是由于不同的公共和私有子网(具有不同的安全访问级别)可以访问应用程序公开的服务的不同部分。

从概念上讲,这个想法是向嵌入式tomcat添加额外的连接器,然后通过向每个指定它通过的“通道”添加自定义标头来捕获所有改变它们的传入请求。

我面临的问题是,我不知道如何在连接器级别捕获这些传入请求(在它到达任何过滤器或servlet之前)。

因此,对于多端口解决方案,我有:

@Configuration
public class EmbeddedTomcatConfiguration {

    @Value("${server.additional-ports}")
    private String additionalPorts;

    @Bean
    public TomcatServletWebServerFactory servletContainer() {
        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
        Connector[] additionalConnectors = additionalConnector();
        if(additionalConnectors != null && additionalConnectors.length > 0) {
            tomcat.addAdditionalTomcatConnectors(additionalConnectors);
        }
        return tomcat;
    }

    private Connector[] additionalConnector() {
        if(StringUtils.isNotBlank(additionalPorts)) {
            return Arrays.stream(additionalPorts.split(","))
                .map(String::trim)
                .map(p -> {
                    Connector connector = new Connector(Http11NioProtocol.class.getCanonicalName());
                    connector.setScheme("http");
                    connector.setPort(Integer.valueOf(p));
                    return connector;
                })
                .toArray(Connector[]::new);
        }
        return null;
    }
}

理论上,我可以向每个连接器注册一个自定义的生命周期侦听器,但据我所知,这没有用。我也听说过一些关于阀门的事情,尽管我不知道如何在每个连接器上实现它们。

也许我走错了路。

我真的很感谢你在这件事上的任何帮助。

共有2个答案

穆远
2023-03-14

还可以使用RequestCondition根据端口路由请求,我认为端口更接近stock-spring。参见Spring Boot |如何动态添加新的tomcat连接器?

逑俊楚
2023-03-14

似乎你已经下定决心要尝试一个瓣膜,但是,经过更多的研究,我建议使用ServletFilter来完成这项工作,而不是瓣膜。

我相信您可以在Valve中完成这项工作,但Valve必须部署到tomcat/lib目录中,而不是打包在应用程序中。我强烈建议您考虑将应用程序保存在可部署工件中,而不是在创建新部署时必须记住将一个额外的jar文件部署到tomcat实例中。

从这个答案可以看出servlet中getLocalPort()和getServerPort()之间的区别,您应该能够通过在HttpServletRequest上调用getLocalPort()来访问tomcat端口。

然后根据您在问题中的想法,在请求头中添加一个特定的上下文名称。

public class PortContextFilter implements Filter {

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {

        int localPort = request.getLocalPort();

        // if else or case statements

        ServletRequest newRequest = PortContextHttpServletRequestWrapper(request, YourPortContext)

        filterChain.doFilter(newRequest, response);
    }

    public void destroy() {
        // Nothing to do
    }

    public void init(FilterConfig filterConfig) throws ServletException {
        // Nothing to do.
    }

}

在这之后,理论上,您应该能够使用@RequestMapping注释根据标头内的名称进行路由

@PreAuthorize("hasPermission(#your_object, 'YOUR_OBJECT_WRITE')")
@RequestMapping("/yourobject/{identifier}", headers="context=<context_name>", method = RequestMethod.POST)
public String postYourObject(@PathVariable(value = "identifier") YourObject yourObject) {
    // Do something here...
    ...
}
 类似资料:
  • 我有时会在pom中看到以下声明。xml。。。 如您所见,sping-boo-starter-web被声明为tomcat-embed-jasper。 是不是sping-boo-starter-web已经有一个嵌入式tomcat了?为什么一些开发人员仍然声明tomcat-embed-jasper以及boot-starter-web?还是有什么原因?

  • 我想创建一个类的实例,该类可以访问底层的嵌入式derby数据库,并使用声明性服务将该类传递给绑定到数据库包的每个包。 我在derby留档中看到,为多个线程共享一个连接有很多陷阱。所以我在考虑为我正在创建的类的每个实例创建一个连接。由于我只想要一种非常简单的方法来创建多个连接并管理它们,因此在这里使用“MiniConnectionPoolManager”似乎是一个不错的选择。derby的示例代码如下

  • 最近我正在用Spring Boot与ApachePOI合作,我面临一个问题。我想表示实体之间的数据库连接,但我在可视化多个连接时遇到了问题<所以我的基本问题是分离连接。 以下是我的出发点:1 你看不见,但这两个矩形之间有多个连接,但由于相同的起点和终端,它们相互揭示。 生成的XML代码如下: 所以我想做的是用不同的值设置曲线的圆心中点,就像在这张图中(我手动做这个例子):2 我尝试向连接器添加其他

  • 我的web应用程序(将部署在tomcat上)需要一个嵌入式数据库来存储临时用户数据,以便更快地检索。我选择Apache Embedded Derby是因为它很容易嵌入到web应用程序中,而且是一个纯Java DB。 我还实现了连接池来检索连接。我在这里面临着两个关键的问题(显示塞子)。首先,我的应用程序一次不能有两个以上的活动连接。所以,我的应用程序挂断了。 其次,我不断发现另一个应用程序已经启动

  • 我有一张按年、月、日划分的蜂巢表

  • 问题内容: 我需要在Tomcat中启动Hazelcast,而无需单独的war文件。因此,将hazelcast.jar放入lib文件夹中的hazelczast.xml某处…接下来呢?还是不可能? 问题答案: 第一步是好的,只需将Hazelcast lib和配置放在Tomcat的libs文件夹中。接下来,如果您不需要单独的WAR文件,则是构建一个小的Valve类来启动/关闭Hazelcast节点。问题