Springcloud学习笔记42--利用HttpClient实现服务A向服务B发送Http请求
1.服务A发送Http请求
1.1 在yml文件中配置Http的相关参数
http:
maxTotal: 100
defaultMaxPerRoute: 20
connectTimeout: 1000
connectionRequestTimeout: 500
socketTimeout: 10000
staleConnectionCheckEnable: true
1.2 编写HttpClient的相关配置类
1.2.1 @Configuration
@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。
- @Configuration配置spring并启动spring容器
- @Configuration启动容器+@Bean注册Bean
- @Configuration启动容器+@Component注册Bean
使用 AnnotationConfigApplicationContext 注册 AppContext 类的两种方法
配置Web应用程序(web.xml中配置AnnotationConfigApplicationContext)
注意:@Configuration注解的类在springboot启动时就会加载;
2022-03-25 15:15:51.116 | INFO | main | org.springframework.web.context.ContextLoader:283 | [] - Root WebApplicationContext: initialization completed in 1270 ms
//此时,进入断点
2022-03-25 15:41:08.945 | INFO | main | com.ttbank.flep.core.FileFlepApplication:59 | [] - Started FileFlepApplication in 238.843 seconds (JVM running for 240.545)
在Root WebApplicationContext: initialization completed启动完成之后,会进入debug状态;
1.3.2 @Component和@Bean注解
@Component注解表明一个类会作为组件类,并告知Spring要为这个类创建bean。
@Bean注解告诉Spring这个方法将会返回一个对象,这个对象要注册为Spring应用上下文中的bean。通常方法体中包含了最终产生bean实例的逻辑。
两者的目的是一样的,都是注册bean到Spring容器中。
package com.ttbank.flep.core.config; import org.apache.http.client.config.RequestConfig; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.concurrent.TimeUnit; @Configuration public class HttpClientConfig { @Value("${http.maxTotal}") private Integer maxTotal; @Value("${http.defaultMaxPerRoute}") private Integer defaultMaxPerRoute; @Value("${http.connectTimeout}") private Integer connectTimeout; @Value("${http.connectionRequestTimeout}") private Integer connectionRequestTimeout; @Value("${http.socketTimeout}") private Integer socketTimeout; @Value("${http.staleConnectionCheckEnable}") private boolean staleConnectionCheckEnable; /** * 首先实例化一个连接管理器,设置最大连接数,并发数 */ @Bean(name="httpClientConnectionManager") public PoolingHttpClientConnectionManager getHttpClientConnectionManager(){ PoolingHttpClientConnectionManager httpClientConnectionManager=new PoolingHttpClientConnectionManager(); //最大连接数 httpClientConnectionManager.setMaxTotal(maxTotal); //并发数 httpClientConnectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute); return httpClientConnectionManager; } /** * 实例化连接池 */ @Bean(name="httpClientBuilder") public HttpClientBuilder getHttpClientBuilder(@Qualifier("httpClientConnectionManager")PoolingHttpClientConnectionManager httpClientConnectionManager){ HttpClientBuilder httpClientBuilder=HttpClientBuilder.create(); httpClientBuilder.setConnectionManager(httpClientConnectionManager); //以下可不设置,如果指定了要清理的过期连接,才会启动清理线程,默认不启动。会有一个单独的线程来扫描连接池中的连接,发现离最近一次使用超时设置后,就会清理。 //设置是否清理过期连接 httpClientBuilder.evictExpiredConnections(); //连接存活时间 httpClientBuilder.setConnectionTimeToLive(10000, TimeUnit.SECONDS); //设置清理空闲连接的时间 httpClientBuilder.evictIdleConnections(60000, TimeUnit.MILLISECONDS); return httpClientBuilder; } /** * 注入连接池,用于获取httpclient */ @Bean public CloseableHttpClient getCloseableHttpClient(@Qualifier("httpClientBuilder")HttpClientBuilder httpClientBuilder){ return httpClientBuilder.build(); } /** * Builder是RequestConfig的一个内部类,利用custom方法可获取一个Builder对象 * 设置builder的连接信息 */ @Bean(name="builder") public RequestConfig.Builder getBuilder(){ RequestConfig.Builder builder = RequestConfig.custom(); return builder.setConnectTimeout(connectTimeout) .setConnectionRequestTimeout(connectionRequestTimeout) .setSocketTimeout(socketTimeout); } /** * 使用builder构建一个RequestConfig对象 */ @Bean public RequestConfig getRequestConfig(@Qualifier("builder") RequestConfig.Builder builder){ return builder.build(); } }
1.3 HttpClientUtil
采用@Component注解将这个类交给spring容器管理;因此,HttpClientUtil类中的两个成员变量httpClient,requestConfig可以由spring完成对象的注入;
注意:使用HttpClientUtil类,必须采用@autowired注解进行注入,不能采用new 对象的方式;
package com.ttbank.flep.core.util; import com.ttbank.flep.core.dto.Result; import org.apache.http.Consts; import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.utils.URIBuilder; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * @Author lucky * @Date 2022/3/25 9:23 */ @Component public class HttpClientUtil { @Autowired private CloseableHttpClient httpClient; @Autowired private RequestConfig requestConfig; public Result doPost(String url) throws Exception{ return this.doPost(url,null); } /** * 带参数的post方法 * @param url * @param map */ public Result doPost(String url, Mapmap) throws Exception{ HttpPost httpPost=new HttpPost(url); httpPost.setConfig(requestConfig); if(map!=null){ List list=new ArrayList<>(); for (Map.Entry entry : map.entrySet()) { list.add(new BasicNameValuePair(entry.getKey(),entry.getValue().toString() )); } //构造form表单对象 UrlEncodedFormEntity urlEncodedFormEntity=new UrlEncodedFormEntity(list,"UTF-8"); //把表单放到post里 httpPost.setEntity(urlEncodedFormEntity); } //发起请求 CloseableHttpResponse response = this.httpClient.execute(httpPost); return new Result(String.valueOf(response.getStatusLine().getStatusCode()),"",EntityUtils.toString(response.getEntity(),"UTF-8")); } public Result doPostJson(String url,String json) throws Exception{ HttpPost httpPost=new HttpPost(url); httpPost.setConfig(requestConfig); StringEntity entity=new StringEntity(json); httpPost.setEntity(entity); httpPost.setHeader("Accept","application/json"); httpPost.setHeader("Content-type","application/json"); CloseableHttpResponse response=this.httpClient.execute(httpPost); return new Result(String.valueOf(response.getStatusLine().getStatusCode()),"",EntityUtils.toString(response.getEntity(),"UTF-8")); } public Result doPostFile(String url, String key,String params, InputStream fileInputStream) throws IOException { HttpPost httpPost=new HttpPost(url); httpPost.setConfig(requestConfig); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.addBinaryBody("file",fileInputStream, ContentType.create("multipart/form-data"),"test" ); StringBody body=new StringBody(params,ContentType.create("text/plain", Consts.UTF_8 )); builder.addPart(key,body); HttpEntity entity=builder.build(); httpPost.setEntity(entity); //发起请求 CloseableHttpResponse response = this.httpClient.execute(httpPost); return new Result(String.valueOf(response.getStatusLine().getStatusCode()),"",EntityUtils.toString(response.getEntity(),"UTF-8")); } /** * 不带参数的get请求 * @param url */ public Result doGet(String url) throws IOException { HttpGet httpGet=new HttpGet(url); //加载配置信息 httpGet.setConfig(requestConfig); //发起请求 CloseableHttpResponse response = this.httpClient.execute(httpGet); return new Result(String.valueOf(response.getStatusLine().getStatusCode()),"",EntityUtils.toString(response.getEntity(),"UTF-8")); } public Result doGet(String url,Map map) throws Exception{ URIBuilder uriBuilder=new URIBuilder(url); if(map!=null){ for (Map.Entry entry : map.entrySet()) { uriBuilder.setParameter(entry.getKey(),entry.getValue().toString() ); } } return this.doGet(uriBuilder.build().toString()); } }
1.4 使用测试案例
package com.ttbank.flep.core.controller; import com.sun.media.jfxmedia.logging.Logger; import com.ttbank.flep.core.util.HttpClientUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Map; /** * @Author lucky * @Date 2022/3/25 11:41 */ @RestController @RequestMapping("/httpclient") @Slf4j public class HttpClientController { @Autowired HttpClientUtil httpClientUtil; @PostMapping("/sayHello") public void sayHello(){ String url="http://127.0.0.1:7011/task/getAttr"; MapparamMap=new HashMap<>(); paramMap.put("name","lucky" ); paramMap.put("address","tiantai" ); try { httpClientUtil.doPost(url,paramMap); log.info("send OK"); } catch (Exception e) { e.printStackTrace(); } } @GetMapping("/sayBye") public void sayBye(){ String url="http://127.0.0.1:7011/task/getInfo"; Map paramMap=new HashMap<>(); paramMap.put("name","linda" ); paramMap.put("address","hangzhou" ); try { httpClientUtil.doGet(url,paramMap); log.info("send success"); } catch (Exception e) { e.printStackTrace(); } } }
1.5 postman调用
http://127.0.0.1:7010/httpclient/sayBye
2.服务B接收Http请求
package com.ttbank.flep.task.controller; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; /** * @Author lucky * @Date 2022/3/25 14:31 */ @RestController @RequestMapping("/task") @Slf4j public class TaskController { @PostMapping("/getAttr") public void getAttr(@RequestParam String name,@RequestParam String address){ log.info(name+":"+address); } @GetMapping("/getInfo") public void getInfo(@RequestParam String name,@RequestParam String address){ log.info(name+":"+address); } }
此时,控制台输出日志:
2022-03-25 17:25:04.985 | INFO | http-nio-7011-exec-8 | com.ttbank.flep.task.controller.TaskController:19 | [] - lucky:tiantai
2022-03-25 17:50:42.897 | INFO | http-nio-7011-exec-5 | com.ttbank.flep.task.controller.TaskController:21 | [] - linda:hangzhou