@@ -4402,4 +4402,249 @@ spring.kafka.producer.properties.spring.json.add.type.headers=false
4402
4402
4403
4403
> 以这种方式设置的属性将覆盖 Spring Boot 明确支持的任何配置项。
4404
4404
4405
+ <a id =" boot-features-resttemplate " ></a >
4406
+
4407
+ ## 34、使用 ` RestTemplate ` 调用 REST 服务
4408
+
4409
+ 如果您的应用程序需要调用远程 REST 服务,这可以使用 Spring Framework 的 [ ` RestTemplate ` ] ( https://docs.spring.io/spring/docs/5.1.3.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html ) 类。由于 ` RestTemplate ` 实例在使用之前通常需要进行自定义,因此 Spring Boot 不提供任何自动配置的 ` RestTemplate ` bean。但是,它会自动配置 ` RestTemplateBuilder ` ,可在需要时创建 ` RestTemplate ` 实例。自动配置的 ` RestTemplateBuilder ` 确保将合适的 ` HttpMessageConverters ` 应用于 ` RestTemplate ` 实例。
4410
+
4411
+ 以下代码展示了一个典型示例:
4412
+
4413
+ ``` java
4414
+ @Service
4415
+ public class MyService {
4416
+
4417
+ private final RestTemplate restTemplate;
4418
+
4419
+ public MyService (RestTemplateBuilder restTemplateBuilder ) {
4420
+ this . restTemplate = restTemplateBuilder. build();
4421
+ }
4422
+
4423
+ public Details someRestCall (String name ) {
4424
+ return this . restTemplate. getForObject(" /{name}/details" , Details . class, name);
4425
+ }
4426
+
4427
+ }
4428
+ ```
4429
+
4430
+ ** 提示**
4431
+
4432
+ > ` RestTemplateBuilder ` 包含许多可用于快速配置 ·RestTemplate· 的方法。例如,要添加 BASIC auth 支持,可以使用 ` builder.basicAuthentication("user", "password").build() ` 。
4433
+
4434
+ <a id =" boot-features-resttemplate-customization " ></a >
4435
+
4436
+ ### 34.1、自定义 RestTemplate
4437
+
4438
+ ` RestTemplate ` 自定义有三种主要方法,具体取决于您希望自定义的程度。
4439
+
4440
+ 要想自定义的范围尽可能地窄,请注入自动配置的 ` RestTemplateBuilder ` ,然后根据需要调用其方法。每个方法调用都返回一个新的 ` RestTemplateBuilder ` 实例,因此自定义只会影响当前构建器。
4441
+
4442
+ 要在应用程序范围内添加自定义配置,请使用 ` RestTemplateCustomizer ` bean。所有这些 bean 都会自动注册到自动配置的 ` RestTemplateBuilder ` ,并应用于使用它构建的所有模板。
4443
+
4444
+ 以下示例展示了一个 customizer,它为除 ` 192.168.0.5 ` 之外的所有主机配置代理:
4445
+
4446
+ ``` java
4447
+ static class ProxyCustomizer implements RestTemplateCustomizer {
4448
+
4449
+ @Override
4450
+ public void customize (RestTemplate restTemplate ) {
4451
+ HttpHost proxy = new HttpHost (" proxy.example.com" );
4452
+ HttpClient httpClient = HttpClientBuilder . create()
4453
+ .setRoutePlanner(new DefaultProxyRoutePlanner (proxy) {
4454
+
4455
+ @Override
4456
+ public HttpHost determineProxy (HttpHost target ,
4457
+ HttpRequest request , HttpContext context )
4458
+ throws HttpException {
4459
+ if (target. getHostName(). equals(" 192.168.0.5" )) {
4460
+ return null ;
4461
+ }
4462
+ return super . determineProxy(target, request, context);
4463
+ }
4464
+
4465
+ }). build();
4466
+ restTemplate. setRequestFactory(
4467
+ new HttpComponentsClientHttpRequestFactory (httpClient));
4468
+ }
4469
+
4470
+ }
4471
+ ```
4472
+
4473
+ 最后,最极端(也很少使用)的选择是创建自己的 ` RestTemplateBuilder ` bean。这样做会关闭 ` RestTemplateBuilder ` 的自动配置,并阻止使用任何 ` RestTemplateCustomizer ` bean。
4474
+
4475
+ <a id =" boot-features-webclient " ></a >
4476
+
4477
+ ## 35、使用 ` WebClient ` 调用 REST 服务
4478
+
4479
+ 如果在 classpath 上存在 Spring WebFlux,则还可以选择使用 ` WebClient ` 来调用远程 REST 服务。与 ` RestTemplate ` 相比,该客户端更具函数式风格并且完全响应式。您可以在 [ Spring Framework 文档的相关部分] ( https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/web-reactive.html#webflux-client ) 中了解有关 ` WebClient ` 的更多信息。
4480
+
4481
+ Spring Boot 为您创建并预配置了一个 ` WebClient.Builder ` 。强烈建议将其注入您的组件中并使用它来创建 ` WebClient ` 实例。Spring Boot 配置该构建器以共享 HTTP 资源,以与服务器相同的方式反射编解码器设置(请参阅 [ WebFlux HTTP 编解码器自动配置] ( #boot-features-webflux-httpcodecs ) )等。
4482
+
4483
+ 以下代码是一个典型示例:
4484
+
4485
+ ``` java
4486
+ @Service
4487
+ public class MyService {
4488
+
4489
+ private final WebClient webClient;
4490
+
4491
+ public MyService (WebClient .Builder webClientBuilder ) {
4492
+ this . webClient = webClientBuilder. baseUrl(" http://example.org" ). build();
4493
+ }
4494
+
4495
+ public Mono<Details > someRestCall (String name ) {
4496
+ return this . webClient. get(). uri(" /{name}/details" , name)
4497
+ .retrieve(). bodyToMono(Details . class);
4498
+ }
4499
+
4500
+ }
4501
+ ```
4502
+
4503
+ <a id =" boot-features-webclient-runtime " ></a >
4504
+
4505
+ ### 35.1、WebClient 运行时
4506
+
4507
+ Spring Boot 将自动检测用于驱动 ` WebClient ` 的 ` ClientHttpConnector ` ,具体取决于应用程序 classpath 上可用的类库。目前支持 Reactor Netty 和 Jetty RS 客户端。
4508
+
4509
+ 默认情况下 ` spring-boot-starter-webflux ` starter 依赖于 ` io.projectreactor.netty:reactor-netty ` ,它包含了服务器和客户端的实现。如果您选择将 ` Jetty ` 用作响应式服务器,则应添加 Jetty Reactive HTTP 客户端库依赖项 ` org.eclipse.jetty:jetty-reactive-httpclient ` 。服务器和客户端使用相同的技术具有一定优势,因为它会自动在客户端和服务器之间共享 HTTP 资源。
4510
+
4511
+ 开发人员可以通过提供自定义的 ` ReactorResourceFactory ` 或 ` JettyResourceFactory ` bean 来覆盖 Jetty 和 Reactor Netty 的资源配置 —— 这将同时应用于客户端和服务器。
4512
+
4513
+ 如果您只希望覆盖客户端选项,则可以定义自己的 ` ClientHttpConnector ` bean 并完全控制客户端配置。
4514
+
4515
+ 您可以在 [ Spring Framework 参考文档中了解有关 ` WebClient ` 配置选项的更多信息] ( https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/web-reactive.html#webflux-client-builder ) 。
4516
+
4517
+ <a id =" boot-features-webclient-customization " ></a >
4518
+
4519
+ ### 35.2、自定义 WebClient
4520
+
4521
+ ` WebClient ` 自定义有三种主要方法,具体取决于您希望自定义的程度。
4522
+
4523
+ 要想自定义的范围尽可能地窄,请注入自动配置的 ` WebClient.Builder ` ,然后根据需要调用其方法。` WebClient.Builder ` 实例是有状态的:构建器上的任何更改都会影响到之后所有使用它创建的客户端。如果要使用相同的构建器创建多个客户端,可以考虑使用 ` WebClient.Builder other = builder.clone(); ` 的方式克隆构建器。
4524
+
4525
+ 要在应用程序范围内对所有 ` WebClient.Builder ` 实例添加自定义,可以声明 ` WebClientCustomizer ` bean 并在注入点局部更改 ` WebClient.Builder ` 。
4526
+
4527
+ 最后,您可以回退到原始 API 并使用 ` WebClient.create() ` 。在这种情况下,不会应用自动配置或 ` WebClientCustomizer ` 。
4528
+
4529
+ <a id =" boot-features-validation " ></a >
4530
+
4531
+ ## 36、验证
4532
+
4533
+ 只要 classpath 上存在 JSR-303 实现(例如 Hibernate 验证器),就会自动启用 Bean Validation 1.1 支持的方法验证功能。这允许 bean 方法在其参数和/或返回值上使用 ` javax.validation ` 约束进行注解。带有此类注解方法的目标类需要在类级别上使用 ` @Validated ` 进行注解,以便搜索其内联约束注解的方法。
4534
+
4535
+ 例如,以下服务触发第一个参数的验证,确保其大小在 8 到 10 之间:
4536
+
4537
+ ``` java
4538
+ @Service
4539
+ @Validated
4540
+ public class MyBean {
4541
+
4542
+ public Archive findByCodeAndAuthor (@Size (min = 8 , max = 10 ) String code ,
4543
+ Author author ) {
4544
+ ...
4545
+ }
4546
+
4547
+ }
4548
+ ```
4549
+
4550
+ <a id =" boot-features-email " ></a >
4551
+
4552
+ ## 37、发送邮件
4553
+
4554
+ Spring Framework 提供了一个使用 ` JavaMailSender ` 接口发送电子邮件的简单抽象,Spring Boot 为其提供了自动配置以及一个 starter 模块。
4555
+
4556
+ ** 提示**
4557
+
4558
+ > 有关如何使用 ` JavaMailSender ` 的详细说明,请参阅[ 参考文档] ( https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/integration.html#mail ) 。
4559
+
4560
+ 如果 ` spring.mail.host ` 和相关库(由 ` spring-boot-starter-mail ` 定义)可用,则创建默认的 ` JavaMailSender ` (如果不存在)。可以通过 ` spring.mail ` 命名空间中的配置项进一步自定义发件人。有关更多详细信息,请参阅 [ ` MailProperties ` ] ( https://github.com/spring-projects/spring-boot/tree/v2.1.1.RELEASE/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailProperties.java ) 。
4561
+
4562
+ 特别是,某些默认超时时间的值是无限的,您可能想更改它以避免线程被无响应的邮件服务器阻塞,如下示例所示:
4563
+
4564
+ ``` ini
4565
+ spring.mail.properties.mail.smtp.connectiontimeout =5000
4566
+ spring.mail.properties.mail.smtp.timeout =3000
4567
+ spring.mail.properties.mail.smtp.writetimeout =5000
4568
+ ```
4569
+
4570
+ 也可以使用 JNDI 中的现有 ` Session ` 配置一个 ` JavaMailSender ` :
4571
+
4572
+ ``` ini
4573
+ spring.mail.jndi-name =mail/Session
4574
+ ```
4575
+
4576
+ 设置 ` jndi-name ` 时,它优先于所有其他与 ` Session ` 相关的设置。
4577
+
4578
+ <a id =" boot-features-jta " ></a >
4579
+
4580
+ ## 38、JTA 分布式事务
4581
+
4582
+ Spring Boot 通过使用 [ Atomikos] ( http://www.atomikos.com/ ) 或 [ Bitronix] ( https://github.com/bitronix/btm ) 嵌入式事务管理器来支持跨多个 XA 资源的分布式 JTA 事务。部署在某些 Java EE 应用服务器(Application Server)上也支持 JTA 事务。
4583
+
4584
+ 当检测到 JTA 环境时,Spring 的 ` JtaTransactionManager ` 将用于管理事务。自动配置的 JMS、DataSource 和 JPA bean 已升级为支持 XA 事务。您可以使用标准的 Spring 方式(例如 ` @Transactional ` )来使用分布式事务。如果您处于 JTA 环境中并且仍想使用本地事务,则可以将 ` spring.jta.enabled ` 属性设置为 ` false ` 以禁用 JTA 自动配置。
4585
+
4586
+ <a id =" boot-features-jta-atomikos " ></a >
4587
+
4588
+ ### 38.1、使用 Atomikos 事务管理器
4589
+
4590
+ [ Atomikos] ( https://www.atomikos.com/ ) 是一个流行的开源事务管理器,可以嵌入到 Spring Boot 应用程序中。您可以使用 ` spring-boot-starter-jta-atomikos ` starter 来获取相应的 Atomikos 库。Spring Boot 自动配置 Atomikos 并确保将合适的依赖设置应用于 Spring bean,以确保启动和关闭顺序正确。
4591
+
4592
+ 默认情况下,Atomikos 事务日志将写入应用程序主目录(应用程序 jar 文件所在的目录)中的 ` transaction-logs ` 目录。您可以通过在 ` application.properties ` 文件中设置 ` spring.jta.log-dir ` 属性来自定义此目录的位置。也可用 ` spring.jta.atomikos.properties ` 开头的属性来自定义 Atomikos ` UserTransactionServiceImp ` 。有关完整的详细信息,请参阅 [ AtomikosProperties Javadoc] ( https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/api/org/springframework/boot/jta/atomikos/AtomikosProperties.html ) 。
4593
+
4594
+ ** 注意**
4595
+
4596
+ > 为确保多个事务管理器可以安全地协调相同的资源管理器,必须为每个 Atomikos 实例配置唯一 ID。默认情况下,此 ID 是运行 Atomikos 的计算机的 IP 地址。在生产环境中要确保唯一性,应为应用程序的每个实例配置 ` spring.jta.transaction-manager-id ` 属性,并使用不同的值。
4597
+
4598
+ <a id =" boot-features-jta-bitronix " ></a >
4599
+
4600
+ ### 38.2、使用 Bitronix 事务管理器
4601
+
4602
+ [ Bitronix] ( https://github.com/bitronix/btm ) 是一个流行的开源 JTA 事务管理器实现。您可以使用 ` spring-boot-starter-jta-bitronix ` starter 为您的项目添加合适的 Bitronix 依赖。与 Atomikos 一样,Spring Boot 会自动配置 Bitronix 并对 bean 进行后处理(post-processes),以确保启动和关闭顺序正确。
4603
+
4604
+ 默认情况下,Bitronix 事务日志文件(` part1.btm ` 和 ` part2.btm ` )将写入应用程序主目录中的 ` transaction-logs ` 目录。您可以通过设置 ` spring.jta.log-dir ` 属性来自定义此目录的位置。以 ` spring.jta.bitronix.properties ` 开头的属性绑定到了 ` bitronix.tm.Configuration ` bean,允许完全自定义。有关详细信息,请参阅 [ Bitronix 文档] ( https://github.com/bitronix/btm/wiki/Transaction-manager-configuration ) 。
4605
+
4606
+ ** 注意**
4607
+
4608
+ > 为确保多个事务管理器能够安全地协调相同的资源管理器,必须为每个 Bitronix 实例配置唯一的 ID。默认情况下,此 ID 是运行 Bitronix 的计算机的 IP 地址。生产环境要确保唯一性,应为应用程序的每个实例配置 ` spring.jta.transaction-manager-id ` 属性,并使用不同的值。
4609
+
4610
+ <a id =" boot-features-jta-javaee " ></a >
4611
+
4612
+ ### 38.3、使用 Java EE 管理的事务管理器
4613
+
4614
+ 如果将 Spring Boot 应用程序打包为 ` war ` 或 ` ear ` 文件并将其部署到 Java EE 应用程序服务器,则可以使用应用程序服务器的内置事务管理器。Spring Boot 尝试通过查找常见的 JNDI 位置(` java:comp/UserTransaction ` 、` java:comp/TransactionManager ` 等)来自动配置事务管理器。如果使用应用程序服务器提供的事务服务,通常还需要确保所有资源都由服务器管理并通过 JNDI 暴露。Spring Boot 尝试通过在 JNDI 路径(` java:/JmsXA ` 或 ` java:/JmsXA ` )中查找 ` ConnectionFactory ` 来自动配置 JMS,并且可以使用 [ ` spring.datasource.jndi-name ` 属性] ( #boot-features-connecting-to-a-jndi-datasource ) 来配置 ` DataSource ` 。
4615
+
4616
+ <a id =" boot-features-jta-mixed-jms " ></a >
4617
+
4618
+ ### 38.4、混合使用 XA 与非 XA JMS 连接
4619
+
4620
+ 使用 JTA 时,主 JMS ` ConnectionFactory ` bean 可识别 XA 并参与分布式事务。在某些情况下,您可能希望使用非 XA ` ConnectionFactory ` 处理某些 JMS 消息。例如,您的 JMS 处理逻辑可能需要比 XA 超时时间更长的时间。
4621
+
4622
+ 如果要使用非 XA ` ConnectionFactory ` ,可以注入 ` nonXaJmsConnectionFactory ` bean 而不是 ` @Primary ` ` jmsConnectionFactory ` bean。为了保持一致性,提供的 ` jmsConnectionFactory ` bean 还需要使用 ` xaJmsConnectionFactory ` 别名。
4623
+
4624
+ 以下示例展示了如何注入 ` ConnectionFactory ` 实例:
4625
+
4626
+ ``` java
4627
+ // Inject the primary (XA aware) ConnectionFactory
4628
+ @Autowired
4629
+ private ConnectionFactory defaultConnectionFactory;
4630
+
4631
+ // Inject the XA aware ConnectionFactory (uses the alias and injects the same as above)
4632
+ @Autowired
4633
+ @Qualifier (" xaJmsConnectionFactory" )
4634
+ private ConnectionFactory xaConnectionFactory;
4635
+
4636
+ // Inject the non-XA aware ConnectionFactory
4637
+ @Autowired
4638
+ @Qualifier (" nonXaJmsConnectionFactory" )
4639
+ private ConnectionFactory nonXaConnectionFactory;
4640
+ ```
4641
+
4642
+ <a id =" boot-features-jta-supporting-alternative-embedded " ></a >
4643
+
4644
+ ## 38.5、支持嵌入式事务管理器
4645
+
4646
+ [ ` XAConnectionFactoryWrapper ` ] ( https://github.com/spring-projects/spring-boot/tree/v2.1.1.RELEASE/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jms/XAConnectionFactoryWrapper.java ) 和 [ ` XADataSourceWrapper ` ] ( https://github.com/spring-projects/spring-boot/tree/v2.1.1.RELEASE/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/XADataSourceWrapper.java ) 接口可用于支持其他嵌入式事务管理器。接口负责包装 ` XAConnectionFactory ` 和 ` XADataSource ` bean,并将它们公开为普通的 ` ConnectionFactory ` 和 ` DataSource ` bean,它们透明地加入分布式事务。` DataSource ` 和 JMS 自动配置使用 JTA 变体,前提是您需要有一个 ` JtaTransactionManager ` bean 和在 ` ApplicationContext ` 中注册有的相应 XA 包装器(wrapper) bean。
4647
+
4648
+ [ BitronixXAConnectionFactoryWrapper] ( https://github.com/spring-projects/spring-boot/tree/v2.1.1.RELEASE/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/bitronix/BitronixXAConnectionFactoryWrapper.java ) 和 [ BitronixXADataSourceWrapper] ( https://github.com/spring-projects/spring-boot/tree/v2.1.1.RELEASE/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/bitronix/BitronixXADataSourceWrapper.java ) 为如何编写 XA 包装器提供了很好示例。
4649
+
4405
4650
** 待续……**
0 commit comments