玩转 SpringBoot 2.x 之自定义Starter依赖

前言

SpringBoot 核心功能之一就是 starter 依赖也叫起步依赖,他默认提供了 spring-boot-starter-web、spring-boot-starter-logging、spring-boot-starter-aop 等自带的 starter 起步依赖。

那什么是起步依赖呢?SpringBoot 实战一书中介绍说:假设你要用SpringMVC 构件一个 REST API 并将JSON 作为表述,那么你使用Maven 情况下你最少需要使用 spring-core spring-webmvc hibernate-validator tomcate 等依赖。并且还要考虑版本兼容的问题,但是只需要加入 spring-boot-starter-web 一个依赖即可无需再考虑上述问题。

起步依赖就像是多个依赖的聚合,但是SpringBoot 给我们提供的不仅仅是依赖的聚合,并且为我们提供了相关功能配置,也是SprngBoot 的另一个核心功能自动配置 为一些常用的功能预先进行参数配置。其原理就是将一些 Bean 进行预先配置,在不加入任何配置的情况下使用预先默认的配置,最后在SpringBoot 启动过程中将预先配置Bean注入到Spring的容器中。

本文通过自定义HttpClient Starter 依赖实战案例带你快速了解 SpringBoot 起步依赖和自动配置到底是个什么东东。

阅读前需要你必须了解如何搭建 SpringBoot 项目,并且会简单使用 HttpClient相关操作。
接下来就开始自定义 starter 依赖实战操作!

自定义 starter 依赖实战操作

第一步:创建 Maven项目 引入 spring-boot-autoconfigure 依赖同时引入httpclient的依赖 具体配置如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0modelVersion>
  <groupId>cn.lijunkuigroupId>
  <artifactId>spring-boot-start-httpclientartifactId>
  <version>0.0.1-SNAPSHOTversion>
  <dependencies>
		<dependency>
			<groupId>org.apache.httpcomponentsgroupId>
			<artifactId>httpclientartifactId>
			<version>4.5.6version>
		dependency>
		 <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-autoconfigureartifactId>
            <version>2.1.0.RELEASEversion>
        dependency>
  dependencies>
project>

第二步:创建 HttpClient 配置参数类 HttpClientProperties

@ConfigurationProperties: 属性配置注解,可以将 SpringBoot 配置文件中配置信息注入到配置参数类中。

HttpClientProperties 类具体内容如下:

package cn.lijunkui.autoconfig;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix="spring.httpclient")
public class HttpClientProperties {
	private Integer connectTimeout = 1000;//创建连接的最长时间
	private Integer socketTimeout = 10000;//数据传输的最长时间
	private String agent = "agent";
	private Integer maxPerRoute = 10;//设置每个路由的并发数
	private Integer maxTotal = 50;//最大连接数 
	public Integer getConnectTimeout() {
		return connectTimeout;
	}
	public void setConnectTimeout(Integer connectTimeout) {
		this.connectTimeout = connectTimeout;
	}
	public Integer getSocketTimeout() {
		return socketTimeout;
	}
	public void setSocketTimeout(Integer socketTimeout) {
		this.socketTimeout = socketTimeout;
	}
	public String getAgent() {
		return agent;
	}
	public void setAgent(String agent) {
		this.agent = agent;
	}
	public Integer getMaxPerRoute() {
		return maxPerRoute;
	}
	public void setMaxPerRoute(Integer maxPerRoute) {
		this.maxPerRoute = maxPerRoute;
	}
	public Integer getMaxTotal() {
		return maxTotal;
	}
	public void setMaxTotal(Integer maxTotal) {
		this.maxTotal = maxTotal;
	}
}

第三步:创建使用自动配置的注解

自动配置的注解作用是:在SpringBoot 启动过程中将自动配置类导入到Spring容器中。具体代码如下:

package cn.lijunkui.autoconfig;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;


@Target(value = { ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Import(HttpClientAutoConfiguration.class)
public @interface EnableHttpClient {

}

也可以在resource 目录下 创建META-INF 文件夹并在该文件夹下创建名称为 spring.factories
的文件,并在文件中来指定自动配置类,具体内容如下:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=
cn.lijunkui.autoconfig.HttpClientAutoConfiguration
2中方式任选一种即可

第四步:创建 HttpClient 自动配置类 HttpClientAutoConfiguration

在创建自动配置类前我们先介绍一下自动配置类中使用的注解:

  • @Configuration :声明该类是Spring 的配置类 一般和 @Bean 结合使用
  • @Bean: 声明在方法上用于将实例对象注入Spring上下文中。
  • @EnableConfigurationProperties:会将会HttpClientProperties
    作为一个Bean引入HttpClientAutoConfiguration 中。
  • @ConditionalOnMissingBean:该注解表示,如果存在它修饰的类的 Bean,则不需要再创建这个Bean。可以给该注解传入参数例如 @ConditionOnMissingBean(name
    = “example”)
    ,这个表示如果name为“example”的bean存在,这该注解修饰的代码块不执行。通俗一点讲就是:如果不存在HttpClient配置项则走自动配置项,如果存在HttpClient配置怎不会走自动配置操作。
  • @ConditionalOnClass:该注解的参数对应的类在classpath 里必须存在,否则在启动时会报错。

自动配置类具体内容如下:

@Configuration
@ConditionalOnClass({EnableHttpClient.class})
@EnableConfigurationProperties(HttpClientProperties.class)
public class HttpClientAutoConfiguration {
	private  HttpClientProperties httpClientProperties;
	
	public HttpClientAutoConfiguration(HttpClientProperties httpClientProperties) {
		this.httpClientProperties = httpClientProperties;
	}
	@Bean
	@ConditionalOnMissingBean(HttpClient.class)
	public HttpClient httpClient() {
		RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(httpClientProperties.getConnectTimeout())
				.setSocketTimeout(httpClientProperties.getSocketTimeout()).build();
		
		HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig)
				.setUserAgent(httpClientProperties.getAgent()).setMaxConnPerRoute(httpClientProperties.getMaxPerRoute())
				.setConnectionReuseStrategy(new NoConnectionReuseStrategy()).build();
		return httpClient;
	}
}

到此自定义功能性starter依赖代码内容编写完毕,使用 Maven 的 mvn clean install 安装到本地仓库后,在 本地SpringBoot 项目中添加上该 Maven 项目的依赖,就可以使用了。

测试自定义依赖

第一步:创建SpringBoot项目并引入我们自定义的start依赖,具体pom.xml 配置如下:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0modelVersion>
	<parent>
		<groupId>org.springframework.bootgroupId>
		<artifactId>spring-boot-starter-parentartifactId>
		<version>2.1.0.RELEASEversion>
		<relativePath/> 
	parent>
	<groupId>com.examplegroupId>
	<artifactId>springbootlearnartifactId>
	<version>0.0.1-SNAPSHOTversion>
	<name>springbootlearnname>
	<description>Demo project for Spring Bootdescription>

	<properties>
		<java.version>1.8java.version>
	properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-webartifactId>
		dependency>

		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-testartifactId>
			<scope>testscope>
		dependency>
		<dependency>
			  <groupId>cn.lijunkuigroupId>
			  <artifactId>spring-boot-start-httpclientartifactId>
			  <version>0.0.1-SNAPSHOTversion>
		dependency>
	dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.bootgroupId>
				<artifactId>spring-boot-maven-pluginartifactId>
			plugin>
		plugins>
	build>

project>

第二步:在声明启动@SpringBootApplication 启动类上添加 @EnableHttpClient 注解。

@SpringBootApplication
@EnableHttpClient
public class SpringBootExamplesApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootExamplesApplication.class, args);
	}
}

第三步:编写测试类,并执行。

具体代码如下:

如下代码所示,只需将 HttpClient 注入测试类就可以使用 HttpClient 了。

package com.example.demo;

import java.io.IOException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootlearnApplicationTests {
	
	Logger log = LoggerFactory.getLogger(SpringbootlearnApplicationTests.class);
	@Autowired
	private HttpClient httpClient;
	@Test
	public void contextLoads() throws ClientProtocolException, IOException {
		HttpEntity httpEntity = httpClient.execute(new HttpGet("http://www.baidu.com")).getEntity();
		HttpGet httpGet = new HttpGet("https://www.baidu.com");
		HttpResponse httpResponse = null;
		try {
			//执行请求访问
			httpResponse = httpClient.execute(httpGet);
			//获取返回HTTP状态码
			int satausCode = httpResponse.getStatusLine().getStatusCode();
			if(satausCode == 200 ){
				String content = EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
				log.info("百度首页页面:"+content);
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

如果不想使用自定义HttpClient Starter依赖配置,我们可以在SpringBoot 项目中添加入下代码:

@Configuration
public class HttpClientConfig {
	@Bean
	public HttpClient httpClient() {
		RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(1500)
				.setSocketTimeout(15000).build();
		
		HttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig)
				.setUserAgent("agent").setMaxConnPerRoute(10)
				.setConnectionReuseStrategy(new NoConnectionReuseStrategy()).build();
		return httpClient;
	}
}

自动配置类中 connectTimeout = 1000、socketTimeout = 10000,添加HttpClientConfig 后覆盖来原先的配置,具体效果如下图所示:
玩转 SpringBoot 2.x 之自定义Starter依赖_第1张图片

也可以通过 在application.properties 添加
spring.httpclient.HttpClientProperties属性=xx来改变默认的配置。
例如:spring.httpclient.connectTimeout=2000

小结

从上述的案例中我们可用发现如果要使用HttpClient 的功能我们需要引入 httpClient 依赖,然后在进行参数配置。但是通过 HttpClient starter 依赖我们只需要一步,引入HttpClient starter 依赖即可,SpringBoot 正是通过这2个功能使得Spring 告别了原先的配置的繁琐。正如SpringBoot 实战中介绍所说:Spring 项目简化了J2EE开发,而SpringBoot 则是简化Spring应用程序开发。

代码示例

我本地环境如下:

  • SpringBoot Version: 2.1.0.RELEASE
  • Apache Maven Version: 3.6.0
  • Java Version: 1.8.0_144
  • IDEA:Spring Tools Suite (STS)

整合过程如出现问题可以在我的GitHub 仓库 springbootexamples 中模块名为 springboot-2.x-httpclient-custom-starter 和 spring-boot-start-httpclient 项目中进行对比查看

GitHub:https://github.com/zhuoqianmingyue/springbootexamples

参考文献

  • SpringBoot 实战
  • http://www.cnblogs.com/yixianyixian/p/7346894.html
  • https://www.cnblogs.com/wangxinblog/p/7818700.html

你可能感兴趣的:(【SpringBoot】)