实战!16条SpringBoot Web服务配置指南及优化技巧

开发 前端
对于反应堆栈应用程序,spring-boot-starter-webflux 通过加入 spring-boot-starter-reactor-netty 包含了 Reactor Netty,但你也可以使用 spring-boot-starter-tomcat、spring-boot-starter-jetty 或 spring-boot-starter-undertow 代替。

环境:SpringBoot3.2.5

1. 切换其它Web Server

对于 servlet 栈应用程序,spring-boot-starter-web 通过包含 spring-boot-starter-tomcat 将 Tomcat 包括在内,但也可以使用 spring-boot-starter-jetty 或 spring-boot-starter-undertow 代替。

对于反应堆栈应用程序,spring-boot-starter-webflux 通过加入 spring-boot-starter-reactor-netty 包含了 Reactor Netty,但你也可以使用 spring-boot-starter-tomcat、spring-boot-starter-jetty 或 spring-boot-starter-undertow 代替。

当切换到不同的 HTTP 服务器时,需要将默认依赖项替换为你需要的依赖项。为了帮助完成这一过程,Spring Boot 为每个受支持的 HTTP 服务器都提供了一个单独的启动器。

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
  <exclusions>
    <!-- 排除 Tomcat dependency -->
    <exclusion>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<!-- 使用 Jetty 替换-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-jetty</artifactId>
</dependency>

注:替换web server后在application.yml中的配置要进行相应的调整

2. 禁用Web Server

如果在类路径包含启动 Web 服务器所需的组件,Spring Boot 会自动启动它。要禁用此行为,请在 application.yml 中配置 WebApplicationType,如下示例:

spring:
  main:
    web-application-type: "none"

这样配置后,在实例化ApplicationContext容器对象时将不会实例化WebServer相关的容器对象。

3. 修改端口

默认为 8080,但可以使用 server.port 进行设置(例如,在 application.properties 中或作为系统属性)。由于放宽了环境值的绑定,你还可以使用 SERVER_PORT(例如,作为操作系统环境变量)。

若要完全关闭 HTTP 端点,但仍要创建 WebApplicationContext,请使用 server.port=-1(这样做有助于测试)。

4. 随机分配端口

要扫描空闲端口(使用操作系统本地端口以防止冲突),请使用 server.port=0。

你还可以指定范围内随机生成端口

server:
  port: ${random.int[5000,10000]}

这里指定端口在5000~10000范围内。

5. 运行时获取 HTTP 端口

要想在运行时获取端口号,你可以添加一下@Bean获取

@Component
public class PackWebServerListener implements ApplicationListener<WebServerInitializedEvent> {
  @Override
  public void onApplicationEvent(WebServerInitializedEvent event) {
    System.out.printf("服务运行端口: %d%n", event.getWebServer().getPort()) ;
  }
}

使用 @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) 的测试也可以通过 @LocalServerPort 注解将实际端口注入字段,如下示例:

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class MyWebIntegrationTests {


  @LocalServerPort
  int port ;
}

@LocalServerPort 是 @Value("${local.server.port}")的元注解。 不要尝试在常规应用程序中注入端口。只能在测试环境下使用

6. 启用HTTP响应压缩

Jetty、Tomcat、Reactor Netty 和 Undertow 支持 HTTP 响应压缩。可在 application.properties 中启用,如下所示:

server:
  compression:
    enabled: true

默认情况下,响应长度必须至少达到 2048 字节才能执行压缩。可以通过配置进行修改大小,如下所示:

server:
  compression:
    min-response-size: 1024

默认情况下,只有当响应的内容类型为以下类型之一时,才会对其进行压缩:

  • text/html
  • text/xml
  • text/plain
  • text/css
  • text/javascript
  • application/javascript
  • application/json
  • application/xml

可通过如下属性进行配置

server:
  compression:
    mime-types:
    - xxx

这里是数组类型。

7. 配置SSL

SSL 可通过设置各种 server.ssl.* 属性进行声明式配置,通常在 application.properties 或 application.yaml 中设置。下面的示例展示了使用 Java KeyStore 文件设置 SSL 属性:

server:
  port: 8443
  ssl:
    key-store: "classpath:pack.keystore"
    key-store-password: "xxxooo"
    key-password: "xxxooo"

密钥库可通过如下方式生成

keytool -genkey -alias pack -keyalg RSA -keystore f:/pack.keystore

使用上例这样的配置意味着应用程序不再支持 8080 端口的纯 HTTP 连接器。Spring Boot 不支持通过 application.properties 同时配置 HTTP 连接器和 HTTPS 连接器。

8. 配置HTTP/2

可以使用 server.http2.enabled 配置属性在 Spring Boot 应用程序中启用 HTTP/2 支持。h2(HTTP/2 over TLS)和 h2c(HTTP/2 over TCP)均受支持。要使用 h2,还必须启用 SSL。未启用 SSL 时,将使用 h2c。例如,当应用程序在执行 TLS 终止的代理服务器后面运行时,就可能需要使用 h2c。

使用 Tomcat 的 HTTP/2

Spring Boot 默认随附 Tomcat 10.1.x,它支持开箱即用的 h2c 和 h2。另外,如果主机操作系统安装了 libtcnative 库及其依赖项,也可以使用 libtcnative 来支持 h2。

如果 JVM 库路径中还没有库目录,则必须提供该库目录。可以使用 JVM 参数(如 -Djava.library.path=/usr/local/opt/tomcat-native/lib)来这样做。 

9. 配置Web Server

一般来说,你应该首先考虑使用许多可用配置的key(即在配置文件中进行的配置)。server.* 命名空间在此非常有用,它包括 server.tomcat.*、server.jetty.* 等命名空间,用于实现特定于服务器的功能。当,相应server.*下没有你需要的配置,那么你可以通过如下编程方式进行自定义配置

@Component
public class PackTomcatWebServerCustomizer implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {


  @Override
  public void customize(TomcatServletWebServerFactory factory) {
    // TODO
  }
}

通过该种方式进行针对性的配置。

10. 添加Servlet,Filter或Listener

在基于 Servlet 栈应用程序中,有两种方法可以在应用程序中添加 Servlet、Filter、ServletContextListener 和 Servlet API 支持的其他监听器:

  • 定义Servlet, Filter, Listener类型的Bean对象

对于Filter和Servlet,你可以分别注册FilterRegistrationBean 和 ServletRegistrationBean 来进行更多的配置选项。

@Bean
public FilterRegistrationBean<CustomFilter> registration(CustomFilter filter) {
    FilterRegistrationBean<CustomFilter> registration = new FilterRegistrationBean<>(filter) ;
    registration.setUrlPatterns(Arrays.asList("/**")) ;
    // ...
    return registration;
}
  • 通过扫描的机制自动注册

分别使用@WebServlet, @WebFilter, and @WebListener注解标注对应的类,然后在配置类上添加@ServletComponentScan注解。

11. 日志配置

访问日志可通过 Tomcat、Undertow 和 Jetty 各自的命名空间进行配置。

Tomcat

server:
  tomcat:
    basedir: "my-tomcat"
    accesslog:
      enabled: true
      pattern: "%t %a %r %s (%D microseconds)"

Undertow

server:
  undertow:
    accesslog:
      enabled: true
      pattern: "%t %a %r %s (%D milliseconds)"
    options:
      server:
        record-request-start-time: true

请注意,除了启用访问日志和配置其模式外,还启用了记录请求开始时间。在访问日志模式中包含响应时间 (%D) 时需要这样做。日志存储在相对于应用程序工作目录的日志目录中。可以通过设置 server.undertow.accesslog.dir 属性来自定义该位置。

Jetty

server:
  jetty:
    accesslog:
      enabled: true
      filename: "/var/log/jetty-access.log"

默认情况下,日志会重定向到 System.err。 

12. 自定义Tomcat代理配置

如果你使用Tomcat,还可以进一步配置用于携带“转发”信息的头名称,如下所示:

server:
  tomcat:
    remoteip:
      remote-ip-header: "x-your-remote-ip-header"
      protocol-header: "x-your-protocol-header"

Tomcat 还配置了一个正则表达式,用于匹配需要信任的内部代理。有关其默认值,请查看server.tomcat.remoteip.internal-proxies 。你可以通过在 application.properties 中添加一个条目来自定义阀门的配置,如下所示:

server:
  tomcat:
    remoteip:
      internal-proxies: "192\\.168\\.\\d{1,3}\\.\\d{1,3}"

13. Tomcat注册多个Connector

@Configuration(proxyBeanMethods = false)
public class MyTomcatConfiguration {


  @Bean
  public WebServerFactoryCustomizer<TomcatServletWebServerFactory> connectorCustomizer() {
    return (tomcat) -> tomcat.addAdditionalTomcatConnectors(createConnector());
  }
  private Connector createConnector() {
    Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
    connector.setPort(8081) ;
    return connector ;
  }
}

这里又开启了一个8081端口。

14. 开启Tomcat MBean

嵌入式 Tomcat 的 MBean 注册表默认是禁用的。这最大限度地减少了 Tomcat 的内存占用。你可以通过如下配置开启

server:
  tomcat:
    mbeanregistry:
      enabled: true

15. Undertow开启多个Listener

向 UndertowServletWebServerFactory 添加一个 UndertowBuilderCustomizer,并向 Builder 添加一个监听器,如下所示:

@Configuration(proxyBeanMethods = false)
public class MyUndertowConfiguration {


  @Bean
  public WebServerFactoryCustomizer<UndertowServletWebServerFactory> undertowListenerCustomizer() {
    return (factory) -> factory.addBuilderCustomizers(this::addHttpListener);
  }
  private Builder addHttpListener(Builder builder) {
    return builder.addHttpListener(8080, "0.0.0.0") ;
  }
}

16. 使用@ServerEndpoint创建WebSocket端点

如果要在嵌入式容器的 Spring Boot 应用程序中使用 @ServerEndpoint,则必须声明一个 ServerEndpointExporter @Bean,如下所示:

@Configuration(proxyBeanMethods = false)
public class MyWebSocketConfiguration {


  @Bean
  public ServerEndpointExporter serverEndpointExporter() {
    return new ServerEndpointExporter();
  }
}

上例中显示的 Bean 会向底层 WebSocket 容器注册任何带有 @ServerEndpoint 注释的 Bean。当部署到独立的 servlet 容器时,这一角色由 servlet 容器初始化器执行,而不需要 ServerEndpointExporter Bean。

责任编辑:武晓燕 来源: Spring全家桶实战案例源码
相关推荐

2022-01-07 06:09:23

Web性能优化

2023-01-26 01:33:09

web性能优化

2022-05-11 12:15:50

scriptweb性能

2019-08-14 15:40:05

Web图片优化前端

2022-04-06 11:18:46

SpringBoot代码实践

2020-10-26 15:01:02

Spring Boot源码参数

2009-02-18 11:24:24

优化加速PHP

2011-08-29 09:33:48

2018-01-01 20:56:43

AndroidUIAPI

2024-08-27 09:09:49

Web系统JSP

2009-09-18 14:02:09

Nis服务器

2021-01-28 10:04:40

JavaScript开发技术

2009-12-24 16:15:17

2010-06-07 09:08:38

Cacti配置

2022-04-27 10:53:34

web优化性能

2020-01-16 18:30:07

技术SQL优化

2017-02-05 17:33:59

前端优化Web性能

2011-04-01 10:49:42

vSphereWeb Access管

2020-05-26 15:05:30

Spark安装环境

2010-05-31 15:57:36

Cacti使用手册
点赞
收藏

51CTO技术栈公众号