远程调用相关知识
1. 什么是远程调用
- 远程调用: 一个项目调用另外一个项目模块(功能)
- 调用过程: 模拟浏览器过程
2.常见远程调用方式
- RPC: 自定义数据格式的远程调用方式。 更偏向于底层,通信速度快, 效率高。
常见框架: dubbo - HTTP: 采用http协议远程调用方式, 规定了数据传输的格式 ,缺点是消息封装臃肿(请求头行体,响应头行体).。在热门的Rest风格,就可以通过http协议来实现。
常见框架: HttpClient , RestTemplate
- 选择:
微服务.更加强调的是 独立,自主,灵活, 一般都会采用基于Http的Rest风格.
3.HttpClient入门
- 概述
HttpClient 是Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。 - 语法
GET请求(Delete同理)
//get请求
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
try {
// 1,创建客户端
httpClient = HttpClients.createDefault();
// 2,创建get实例
HttpGet httpGet = new HttpGet("请求路径");
// 3,发送请求
response = httpClient.execute(httpGet);
// 4,判断响应状态码
if(response.getStatusLine().getStatusCode() == 200){
// 5,获得响应结果
String str = EntityUtils.toString(response.getEntity());
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 6,释放资源
httpClient.close();
response.close();
}
//get请求, 多条件查询
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
try {
// 1,创建客户端
httpClient = HttpClients.createDefault();
// 2,获得get请求实例
//2.1设置拼接参数
StringBuilder sbf = new StringBuilder();
sbf.append("username=wang");
sbf.append("&");
sbf.append("password=1234");
HttpGet httpGet = new HttpGet("请求路径" +"?" + sbf.toString());
// 3,发送请求
response = httpClient.execute(httpGet);
// 4,判断响应状态码
if(response.getStatusLine().getStatusCode() == 200){
// 5,获得响应结果
String str = EntityUtils.toString(response.getEntity());
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 6,释放资源
response.close();
httpClient.close();
}
POST请求(PUT同理)
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
try {
httpClient = HttpClients.createDefault();
//获取post请求实例
HttpPost httpPost = new HttpPost("http://localhost:9090/user");
// 2.1 设置请求头
httpPost.setHeader("Content-Type","application/json;charset=utf-8");
// 2.2 设置请求体
// 处理json数据
User user = new User(4, "小王", "1234", 12);
String jsonstr = JSON.toJSONString(user);
httpPost.setEntity( new StringEntity(jsonstr,"UTF-8"));
response = httpClient.execute(httpPost);
if(response.getStatusLine().getStatusCode() == 200){
String str = EntityUtils.toString(response.getEntity());
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
response.close();
httpClient.close();
}
4.HttpClient高级
-
使用HttpClients.custom()可以构建自定义 CloseableHttpClient 对象
setConnectionManager 用于配置连接
setDefaultRequestConfig 用于配置请求- 通过PoolingHttpClientConnectionManager 可以为连接配置连接数和并发数
- 通过 RequestConfig.custom() 可以配置各种超时时间
(自定义httpclient 及 springboot,RestTemplate 整合 HTTPClient 完整版详见文档最后 )
5.RestTemplate
1.概述:
RestTemplate是Spring提供的用于访问Rest服务的客户端,
RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
2.语法
注意: 使用RestTemplate封装数据时,BaseResult必须提供无参构造
//1, 创建核心类
RestTemplate restTemplate = new RestTemplate();
//get请求
ResponseEntity<返回值类型> entiy =
restTemplate.getForEntity("请求路径", 返回值类型.class);
//post请求
ResponseEntity<返回值类型> entiy
= restTemplate.postForEntity("请求路径", 请求参数, 返回值类型.class);
//put请求
restTemplate.put("请求路径",请求参数);
//delete请求
restTemplate.delete("请求参数");
//返回值获取
entiy.getStatusCode() //获取状态码
entiy.getBody() //获取内容
3.配置类的使用
- 步骤一 : 编写配置类, 将需要new的对象交于spring进行管理
@Configuration //配置类, springboot会自动扫描
public class 类{
@Bean //spring将管理此方法创建的对象
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
- 步骤二 : 在任意位置, 通过 @Resource 进行注入
public class AdminClient{
@Resource //因为配置类已经构建对象, 此处自动注入
public RestTemplate restTemplate;
//..使用即可
}
6.基于http协议远程调用对比
- HttpClient 更偏向于底层,学习时原理。相当于模型浏览器。 但操作比较繁琐。
- RestTemplate 对整个请求进行简化.
- 实际开发中RestTemplate整合HttpClient
7. http配置类(完整版)
package com.czxy.config;
import lombok.Setter;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.client.LaxRedirectStrategy;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import java.nio.charset.Charset;
import java.util.List;
/**
* Created by zhaorenhui.
*/
@Configuration
@ConfigurationProperties(prefix = "http")
@Setter
public class HttpConfig {
private Integer maxTotal;
private Integer defaultMaxPerRoute;
private Integer connectTimeout;
private Integer connectionRequestTimeout;
private Integer socketTimeout;
private Integer staleConnectionCheckEnabled;
// springBoot整合httpClient
@Bean
public PoolingHttpClientConnectionManager connectionManager(){
//1 配置连接管理
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
// 1.1 设置最大连接数
connectionManager.setMaxTotal(maxTotal);
// 1.2 设置并发访问数
connectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
return connectionManager;
}
@Bean
public RequestConfig requestConfig(){
//2 请求配置
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(connectTimeout)
.setConnectionRequestTimeout(connectionRequestTimeout)
.setSocketTimeout(socketTimeout)
.build();
return requestConfig;
}
@Bean
public HttpClient httpClient(HttpClientConnectionManager connectionManager, RequestConfig requestConfig){
// 3 获得工具类
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(requestConfig)
//重定向策略
.setRedirectStrategy(new LaxRedirectStrategy())
.build();
return httpClient;
}
// RestTemplate整合HttpClient
@Bean
public ClientHttpRequestFactory requestFactory(HttpClient httpClient ){
return new HttpComponentsClientHttpRequestFactory(httpClient);
}
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory requestFactory){
RestTemplate template = new RestTemplate(requestFactory);
//乱码处理
List<HttpMessageConverter<?>> list = template.getMessageConverters();
for (HttpMessageConverter<?> mc : list) {
if (mc instanceof StringHttpMessageConverter) {
((StringHttpMessageConverter) mc).setDefaultCharset(Charset.forName("UTF-8"));
}
}
return template;
}
}