上一节:SpringBoot开发笔记-(4) 属性文件读取2: @PropertySource
5.1 前情提要-场景
之前的2节都是讲怎么读取配置文件; 但是如果有下列的情况, 就需要用到@ImportResource来帮忙了:
- 有一个遗留的xml文件, 比如名叫
spring-beans.xml
里面有很多的配置bean, 都需要注册到spring容器中, 让容器来管理这些bean以备不时之需; - 传统springmvc的项目, 原来的xml配置文件不想删除, 但是又想用springboot来改造它; 就可以使用 @ImportResource来 导入外部资源
简言之: 就是还想用xml, 还想用 springboot; xml就由此注解来注册进去!
5.2. 示例
- 启动类上加注解:
@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);
}
}
- resource: spring/spring-html.xml文件:
<?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代码我们自己写的, 如下:
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容器中能够检索到, 拿出对象;
测试用例:
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));
}
}
}
输出:
org.springframework.web.client.RestTemplate@2dd8239
如果把 @ImportResource这一行注释掉: 就什么都不会输出了!!!
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);
}
}
5.3 小结@ImportResource
- 作用: 想容器中注册 xml形式的bean;
- @Import也可以将无注解的纯pojo Bean放入到spring容器中; @ImportResource是放入xml文件, 注意区别;
@Import参见: spring注解驱动开发-(5) 向Spring容器中注册组件的方法
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。