@@ -4402,4 +4402,249 @@ spring.kafka.producer.properties.spring.json.add.type.headers=false
44024402
44034403>  以这种方式设置的属性将覆盖 Spring Boot 明确支持的任何配置项。
44044404
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" 
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+ 
44054650** 待续……** 
0 commit comments