上一節:SpringBoot開發筆記-(4) 屬性文件讀取2: @PropertySourcehtml
以前的2節都是講怎麼讀取配置文件; 可是若是有下列的狀況, 就須要用到@ImportResource來幫忙了:java
spring-beans.xml
裏面有不少的配置bean, 都須要註冊到spring容器中, 讓容器來管理這些bean以備不時之需;簡言之: 就是還想用xml, 還想用 springboot; xml就由此註解來註冊進去!web
@ImportResource("classpath:/spring/spring-*.xml")
package com.niewj.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ImportResource; @SpringBootApplication @ImportResource("classpath:/spring/spring-*.xml") public class HelloApplication { public static void main(String[] args) { SpringApplication.run(HelloApplication.class, args); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= --> <!-- RestTemplate --> <bean id="httpClient" class="com.niewj.springboot.utils.MyHttpClientUtils" factory-method="buildHttpClient"/> <bean id="clientHttpRequestFactory" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory"> <property name="connectTimeout" value="20000"/><!-- 鏈接超時 --> <property name="readTimeout" value="30000"/><!-- 數據讀取超時時間 --> <property name="connectionRequestTimeout" value="20000"/> <!-- 鏈接不夠用的等待時間 --> <constructor-arg ref="httpClient"/> </bean> <bean id="restTemplate" class=" org.springframework.web.client.RestTemplate"> <constructor-arg ref="clientHttpRequestFactory"/> </bean> </beans>
這個xml中但願獲得一個 RestTemplate的bean, 須要依賴一個httpClient, httpClient代碼咱們本身寫的, 以下:spring
package com.niewj.springboot.utils; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.ssl.SSLContextBuilder; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; /** * Created by niewj on 2019/04/10. */ public class MyHttpClientUtils { public static CloseableHttpClient buildHttpClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); // setup a Trust Strategy that allows all certificates. // SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { @Override public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { return true; } }).build(); httpClientBuilder.setSSLContext(sslContext); HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE; // 這是特殊的部分: // -- need to create an SSL Socket Factory, to use our weakened "trust strategy"; // -- and create a Registry, to register it. // SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, hostnameVerifier); // 註冊http和https請求 Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", sslSocketFactory).build(); // 開始設置鏈接池-- allows multi-threaded use PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager(socketFactoryRegistry); // 最大鏈接數200 connMgr.setMaxTotal(200); // 同路由併發數100 connMgr.setDefaultMaxPerRoute(100); httpClientBuilder.setConnectionManager(connMgr); // 重試次數 httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)); CloseableHttpClient client = httpClientBuilder.build(); return client; } }
在此例中, 這個類自己並不重要, 重要的是 xml中配置的bean id, 要最終在spring容器中可以檢索到, 拿出對象;shell
測試用例:apache
package com.niewj.springboot; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.ApplicationContext; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.web.client.RestTemplate; import java.util.Arrays; import java.util.Optional; @RunWith(SpringRunner.class) @SpringBootTest public class SpringbootTest { @Autowired private ApplicationContext ctx; @Test public void testImportResurce() { // 從spring容器中拿到容器管理的全部bean定義, 而後過濾 bean的id, 看有沒有叫 restTemplate的: Optional<String> restTemplate = Arrays.stream(ctx.getBeanDefinitionNames()).filter(s -> s.equalsIgnoreCase("restTemplate")).findAny(); String template = restTemplate.orElse(null); // 若是有, 打印出對象 if(null != template){ System.out.println(ctx.getBean(RestTemplate.class)); } } }
輸出:segmentfault
org.springframework.web.client.RestTemplate@2dd8239
若是把 @ImportResource這一行註釋掉: 就什麼都不會輸出了!!!springboot
package com.niewj.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ImportResource; @SpringBootApplication //@ImportResource("classpath:/spring/spring-*.xml") public class HelloApplication { public static void main(String[] args) { SpringApplication.run(HelloApplication.class, args); } }
@Import參見: spring註解驅動開發-(5) 向Spring容器中註冊組件的方法併發