Spring Boot还能这样玩?同时监听多个端口的黑科技

关注我的公众号:【编程朝花夕拾】,可获取首发内容。

01 引言

平时开发中常见的是一个Tomcat一个端口被访问。从来没有考虑过一个接口可以通过多个端口同时访问。

直到前两天看到一个帖子说,SpringBoot同时监听多个端口。于是自己玩了一下,感觉蛮有意思的,就整理一下分享给大家。

02 场景假设

假设有一套系统运行平稳,得到合作商的青睐,想要有一套一模一样的系统。领导要求重新部署一套,但是为了节省经费,领导不提供多余的服务器,希望能够在原来的服务器的基础上技能让自己用,也能让合作商使用。

sh 复制代码
# 自己使用
curl http://localhost:8081/a/api/foo

# 合作商使用
curl http://localhost:8082/b/api/foo

这样的情况下,聪明的你想到了同一个Tomcat开放两个端口,一个给自己用,一个给合作商用。

03 问题解决

3.1 开发多接口

我们先不管端口的分配,我们先看看能不能开方多个接口。当然可以。

我们需要配置org.springframework.boot.web.servlet.server.ServletWebServerFactoryl类:

java 复制代码
@Bean
public ServletWebServerFactory servletContainer() {
    TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
    Connector aConnector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
    aConnector.setPort(8081);
    factory.addAdditionalTomcatConnectors(aConnector);

    Connector bConnector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
    bConnector.setPort(8082);
    factory.addAdditionalTomcatConnectors(bConnector);
    return factory;
}

这里开放了80818082两个接口。这两个接口不影响默认端口,加上默认端口8080总共有3个端口可以同时访问。

Java测试

java 复制代码
@Slf4j
@RestController
@RequestMapping("/api")
public class FooController {

    @GetMapping("/foo")
    public String foo() {
        return "foo";
    }
}
sh 复制代码
# 可以访问的路径
curl http://localhost:8080/api/foo
curl http://localhost:8081/api/foo
curl http://localhost:8082/api/foo

上面的三种方式都可以访问。这就实现了一个接口三个端口都可以访问的效果。

3.2 端口分配

为了实现不同接口的资源隔离。我们将代码复制了一份,为了方便演示,修改了一点提示语。

假设FooController控制层给自己用,使用8081端口,并加前缀a。而FooV2Controller给合作商用,使用8082端口,并加前缀b

我们将在不改变控制层代码的情况下,通过配置的方式完成资源的隔离。通过拦截器使用端口路由拦截。

java 复制代码
public class MultiPortIntercpetor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        int localPort = request.getLocalPort();
        String requestURI = request.getRequestURI();
        if (localPort == 8081 && requestURI.startsWith("/a")) {
            return true;
        }
        if (localPort == 8082 && requestURI.startsWith("/b")) {
            return true;
        }

        Map<String, Object>  map = new HashMap<>();
        map.put("code", 404);
        map.put("success", false);
        map.put("message", "请求错误");
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(JSON.toJSONString(map));
        return false;
    }
}

拦截器的配置:

java 复制代码
@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new MultiPortIntercpetor()).addPathPatterns("/**");
}

3.3 配置前缀

前两天刚好介绍了configurePathMatch配置方法,那我们就用起来。

java 复制代码
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
    configurer.addPathPrefix("/a", clazz -> clazz.equals(FooController.class));
    configurer.addPathPrefix("/b", clazz -> clazz.equals(FooV2Controller.class));
}

这里的配置直接使用控制层的类,也可以通过自定义的注解获取比对。

3.4 测试

04 小结

这是一个有意思的技术点。真实场景一般不会通过一个Tomcat控制两套系统。而多端口真正的使用场景,小编暂时还想不到。大家都会用在什么地方,一起唠唠!

相关推荐
自由生长20244 小时前
JNI是什么?
程序员
一 乐4 小时前
婚纱摄影网站|基于ssm + vue婚纱摄影网站系统(源码+数据库+文档)
前端·javascript·数据库·vue.js·spring boot·后端
Boilermaker19924 小时前
[Java 并发编程] Synchronized 锁升级
java·开发语言
Cherry的跨界思维4 小时前
28、AI测试环境搭建与全栈工具实战:从本地到云平台的完整指南
java·人工智能·vue3·ai测试·ai全栈·测试全栈·ai测试全栈
alonewolf_995 小时前
JDK17新特性全面解析:从语法革新到模块化革命
java·开发语言·jvm·jdk
一嘴一个橘子5 小时前
spring-aop 的 基础使用(啥是增强类、切点、切面)- 2
java
码事漫谈5 小时前
Protocol Buffers 编码原理深度解析
后端
sheji34165 小时前
【开题答辩全过程】以 中医药文化科普系统为例,包含答辩的问题和答案
java
码事漫谈5 小时前
gRPC源码剖析:高性能RPC的实现原理与工程实践
后端
恋爱绝缘体16 小时前
2020重学C++重构你的C++知识体系
java·开发语言·c++·算法·junit