Spring靴子| 如何动态添加新的tomcat连接器?

Spring靴子| 如何动态添加新的tomcat连接器?,第1张

Spring靴子| 如何动态添加新的tomcat连接器?

嗨,这是我的示例项目:示例项目

1-主要应用程序(DemoApplication.java):

    @SpringBootApplicationpublic class DemoApplication {    public static void main(String[] args) {    SpringApplication.run(DemoApplication.class, args);    }}

2-配置文件(AppConfig.java):

@Configurationpublic class AppConfig {@Autowiredprivate ServletWebServerApplicationContext server;private static FilterConfig filterConfig = new FilterConfig();@PostConstructvoid init() {    //setting default port config    filterConfig.addNewPortConfig(8080, "/admin");}@Bean@Scope(value = WebApplicationContext.SCOPE_APPLICATION, proxyMode = ScopedProxyMode.TARGET_CLASS)public FilterConfig createFilterConfig() {    return filterConfig;}public void addPort(String schema, String domain, int port, boolean secure) {    TomcatWebServer ts = (TomcatWebServer) server.getWebServer();    synchronized (this) {        ts.getTomcat().setConnector(createConnector(schema, domain, port, secure));    }}public void addContextAllowed(FilterConfig filterConfig, int port, String context) {    filterConfig.addNewPortConfig(port, context);} public void removePort(int port) {    TomcatWebServer ts = (TomcatWebServer) server.getWebServer();    Service service = ts.getTomcat().getService();    synchronized (this) {        Connector[] findConnectors = service.findConnectors();        for (Connector connector : findConnectors) { if (connector.getPort() == port) {     try {         connector.stop();         connector.destroy();         filterConfig.removePortConfig(port);     } catch (LifecycleException e) {         e.printStackTrace();     } }        }    }}private Connector createConnector(String schema, String domain, int port, boolean secure) {    Connector conn = new Connector("org.apache.coyote.http11.Http11NioProtocol");    conn.setScheme(schema);    conn.setPort(port);    conn.setSecure(true);    conn.setDomain(domain);    if (secure) {        // config secure port...    }    return conn;}}

3-过滤器(NewPortFilter.java):

public class NewPortFilter {@Bean(name = "restrictFilter")public FilterRegistrationBean<Filter> retstrictFilter(FilterConfig filterConfig) {    Filter filter = new oncePerRequestFilter() {        @Override        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,     FilterChain filterChain) throws ServletException, IOException { // get allowed url contexts Set<String> config = filterConfig.getConfig().get(request.getLocalPort()); if (config == null || config.isEmpty()) {     response.sendError(403); } boolean accepted = false; for (String value : config) {     if (request.getPathInfo().startsWith(value)) {         accepted = true;         break;     } } if (accepted) {     filterChain.doFilter(request, response); } else {     response.sendError(403); }        }    };    FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<Filter>();    filterRegistrationBean.setFilter(filter);    filterRegistrationBean.setOrder(-100);    filterRegistrationBean.setName("restrictFilter");    return filterRegistrationBean;}}

4-过滤器配置(FilterConfig.java):

public class FilterConfig {    private Map<Integer, Set<String>> acceptedContextsByPort = new ConcurrentHashMap<>();    public void addNewPortConfig(int port, String allowedContextUrl) {        if(port > 0 && allowedContextUrl != null) { Set<String> set = acceptedContextsByPort.get(port); if (set == null) {     set = new HashSet<>(); } set = new HashSet<>(set); set.add(allowedContextUrl); acceptedContextsByPort.put(port, set);        }    }    public void removePortConfig(int port) {        if(port > 0) { acceptedContextsByPort.remove(port);        }    }    public Map<Integer, Set<String>> getConfig(){        return acceptedContextsByPort;    }}

5-控制器(TestController.java):

@RestControllerpublic class TestController {@AutowiredAppConfig config;@AutowiredFilterConfig filterConfig;@GetMapping("/admin/hello")String test() {    return "hello test";}@GetMapping("/alternative/hello")String test2() {    return "hello test 2";}@GetMapping("/admin/addNewPort")ResponseEntity<String> createNewPort(@RequestParam Integer port, @RequestParam String context) {    if (port == null || port < 1) {        return new ResponseEntity<>("Invalid Port" + port, HttpStatus.BAD_REQUEST);    }    config.addPort("http", "localhost", port, false);    if (context != null && context.length() > 0) {        config.addContextAllowed(filterConfig, port, context);    }    return new ResponseEntity<>("Added port:" + port, HttpStatus.OK);}@GetMapping("/admin/removePort")ResponseEntity<String> removePort(@RequestParam Integer port) {    if (port == null || port < 1) {        return new ResponseEntity<>("Invalid Port" + port, HttpStatus.BAD_REQUEST);    }    config.removePort(port);    return new ResponseEntity<>("Removed port:" + port, HttpStatus.OK); }}

如何测试呢?

在浏览器中:

1-尝试

http:// localhost:8080 / admin / hello

预期响应 :你好测试

2-尝试:

http:// localhost:8080 / admin / addNewPort?port = 9090&context =
alternative

预期响应 :已添加端口:9090

3-尝试:

http:// localhost:9090 / alternative /
hello

预期响应 :你好测试2

4-尝试预期的错误:

http:// localhost:9090 / alternative / addNewPort?port = 8181&context =
alternative

预期响应(允许使用上下文[替代],但端点未为此控制器在控制器中注册) :Whitelabel错误页面…

http:// localhost:9090 / any / hello

预期的响应(不允许上下文[任何]) :Whitelabel错误页面…

http:// localhost:8888 / any / hello

预期的响应(无效的端口号) :ERR_CONNECTION_REFUSED

http:// localhost:8080 /你好

预期的响应(不允许上下文[/ hello]) :Whitelabel错误页面…

5-尝试删除端口:

http:// localhost:8080 / admin / removePort?port =
9090

6-检查已移除的端口:

http:// localhost:9090 / alternative /
hello

预期响应(端口关闭) :ERR_CONNECTION_REFUSED

希望对您有所帮助。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5122919.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-17
下一篇 2022-11-17

发表评论

登录后才能评论

评论列表(0条)

保存