有些时候项目需要同时监听在不同的端口上,比如同时监听http80和https 443端口,这时我们需要自定义web server。
假设我们需要项目同时使用http和https两种协议提供服务,分别使用端口80和443。
我们知道Spring Boot内置了tomcat
,jetty
,undertow
和响应式的netty
4中web server,默认使用tomcat
,所以这里使用tomcat
要演示如何让项目同时支持使用http和https协议。
WebServerFactoryCustomizer接口
很明显,WebServerFactoryCustomizer
接口是Spring Boot专门用于让开发者自定义web server的!
package org.springframework.boot.web.server;@FunctionalInterface
public interface WebServerFactoryCustomizer<T extends WebServerFactory> {void customize(T factory);
}
很简单,只有一个支持泛型的方法,其参数是WebServerFactory
接口的子类。
WebServerFactory
接口的几个重要实现:
- TomcatServletWebServerFactory:对应于tomcat
- JettyServletWebServerFactory:对应jetty
- UndertowServletWebServerFactory:对应undertow
- NettyReactiveWebServerFactory:对应netty
Spring Boot默认使用http/1.1协议。所以我们增加额外的自定义https连接器。
生成SSL证书文件
严格来说https不是一个独立协议,只是在http协议基础上增加了SSL/TLS加密层。所以我们需要先生成SSL证书,这里使用keytool生成jks。
keytool -genkey -alias test -keypass 555555 -keyalg RSA -sigalg sha256withrsa -keysize 1024 -validity 365 -keystore ./localhost.jks
这里key的密码设置为555555,对应Spring Boot配置项server.ssl.key-password
,使用RSA算法.
在执行命令时需要输入密钥库口令,对应SpringBoot配置项server.ssl.key-store-password
.
启用https
Spring Boot默认使用http:8080。所以需要覆盖默认配置:
首先需要将上一步生成的localhost.jks放到项目的resources
下:
server.port=443
server.ssl.enabled=true
server.ssl.key-store=classpath:localhost.jks
server.ssl.key-password=555555
server.ssl.key-store-password=123456
重启项目,在浏览器中访问https://localhost
即可使用https。
增加http额外的连接器
import org.apache.catalina.connector.Connector;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;/*** 自定义tomcat http 80连接器** @author cloudgyb* @since 2022/3/12 15:28*/
@Component
public class TomcatServerCustomer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {@Overridepublic void customize(TomcatServletWebServerFactory factory) {final Connector httpConn = new Connector("HTTP/1.1");httpConn.setPort(80);factory.addAdditionalTomcatConnectors(httpConn);}
}
重启项目,此时已经同时支持https:443和http:80了!