远程调用
1概述
-
一个项目想要调用另一个项目的功能
-
“用户管理系统”调用“商品管理系统”这个现象,
我们称为“远程调用”此时“用户管理系统”相当于模拟“浏览器”。
2调用方式
- RPC : 自定义数据格式的远程调用方式,更偏向于底层
- 常见框架 : dubbo
- Http : 采用了http远程调用协议,规定了数据传输的方式,缺点是消息封装臃肿
- 现在热门的Rest风格,就可以通过http协议来实现
- 常见框架 : HttpClient,RestTemplate
区别 | HTTP | RPC |
---|---|---|
速度 | 较慢 | 快 |
难度 | 简单 | 复杂 |
灵活性 | 灵活,跨平台、跨语言 |
3HttpClient入门
- 确定maven环境
<!--确定spring boot的版本-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<dependencies>
<!--web起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--httpclient-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
<!--支持lombok-->
<dependency>
<groupId>lombok</groupId>
<artifactId>lombok</artifactId>
<version>1.0</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.49</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
- 使用HttpClient发送Get请求
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
try {
//1 创建Httpclient对象(默认连接),相当于打开了浏览器
CloseableHttpClient httpClient = HttpClients.createDefault();
//2 确定请求方式和请求路径,相当于在浏览器输入地址
HttpGet httpGet = new HttpGet("http://localhost:9090/user");
//3 执行请求并获取响应,相当于敲完地址后按下回车。
CloseableHttpResponse response = httpClient.execute(httpGet);
//4 判断状态码
if(response.getStatusLine().getStatusCode() == 200){
//5.1 获得响应数据的类型
System.out.println(response.getEntity().getContentType());
//5.2 获得响应体内容并使用EntityUtils工具进行处理
String str = EntityUtils.toString(response.getEntity(),"UTF-8");
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
//6 释放资源
response.close();
httpClient.close();
}
-
使用HttpClient发送Post请求
CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; try { httpClient = HttpClients.createDefault(); HttpPost httpPost = new HttpPost("http://localhost:9090/user"); // 设置请求头 httpPost.setHeader("content-type","application/json;charset=utf-8"); // 设置并处理请求体 String str = "{\"username\":\"jack\",\"password\":\"1111\"}"; httpPost.setEntity(new StringEntity(str,"utf-8")); response = httpClient.execute(httpPost); if (response.getStatusLine().getStatusCode() == 200){ System.out.println(EntityUtils.toString(response.getEntity())); } } catch (IOException e) { e.printStackTrace(); }finally { response.close(); httpClient.close(); }
-
使用HttpClient发送Put请求
CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; try { httpClient = HttpClients.createDefault(); HttpPut httpPut = new HttpPut("http://localhost:9090/user"); httpPut.setHeader("content-type","application/json;charset=utf-8"); String jsonStr = JSON.toJSONString(new User(1, "jack", "1111", 18)); httpPut.setEntity(new StringEntity(jsonStr,"utf-8")); response = httpClient.execute(httpPut); if (response.getStatusLine().getStatusCode() == 200){ System.out.println(EntityUtils.toString(response.getEntity())); } } catch (IOException e) { e.printStackTrace(); } finally { response.close(); httpClient.close(); }
-
使用HttpClient发送Delete请求
CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; try { //1, 创建客户端 httpClient = HttpClients.createDefault(); //2, 创建DELETE实例 HttpDelete httpDelete = new HttpDelete("http://localhost:9090/user/1"); //3, 发送请求 response = httpClient.execute(httpDelete); //4, 判断状态码 if (response.getStatusLine().getStatusCode() == 200){ //5, 实用工具处理响应数据 System.out.println(EntityUtils.toString(response.getEntity())); } } catch (IOException e) { e.printStackTrace(); } finally { //6, 释放资源 response.close(); httpClient.close(); }
4RestTemplate
-
RestTemplate是Spring提供的用于访问Rest服务的客户端,
RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率
-
Get请求
[@Test](https://my.oschina.net/azibug) public void testGet(){ RestTemplate restTemplate = new RestTemplate(); // 设置url,返回值类型 ResponseEntity<BaseResult> entity = restTemplate.getForEntity("http://localhost:9090/user", BaseResult.class); // 返回状态码 System.out.println(entity.getStatusCode()); // 返回响应体 System.out.println(entity.getBody().getData()); }
-
Post请求
[@Test](https://my.oschina.net/azibug) public void testLogin(){ RestTemplate restTemplate = new RestTemplate(); // 设置url,请求体(自动处理),返回值类型 ResponseEntity<User> entity = restTemplate.postForEntity("http://localhost:9090/user/login", new User(1,"jack","1234",18), User.class); System.out.println(entity.getStatusCodeValue()); System.out.println(entity.getBody()); }
-
Put请求
[@Test](https://my.oschina.net/azibug) public void testPut(){ RestTemplate restTemplate = new RestTemplate(); // 设置url restTemplate.put("http://localhost:9090/user",new User(1,"jack","1234",18)); System.out.println("修改成功"); }
-
Delete请求
[@Test](https://my.oschina.net/azibug) public void testDelete(){ RestTemplate restTemplate = new RestTemplate(); // 设置url restTemplate.delete("http://localhost:9090/user/1"); System.out.println(" 删除成功"); }
1.5SpringBoot 整合 HttpClient及RestTemplate自定义连接池
package com.czxy.config;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
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 澈 on 2019/12/3.
*/
@Configuration
public class HttpClientConfig {
//1. 自定义连接 httpClient
@Bean
public CloseableHttpClient httpClient(PoolingHttpClientConnectionManager connectionManager,
RequestConfig requestConfig){
return HttpClients.custom()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(requestConfig)
.build();
}
//2. 配置PoolingHttpClientConnectionManager
@Bean
public PoolingHttpClientConnectionManager connectionManager(){
//1. HttpClient连接管理器
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
//1.1. 最大连接数
connectionManager.setMaxTotal(1000);
//1.2. 设置并发访问数
connectionManager.setDefaultMaxPerRoute(20);
return connectionManager;
}
//3. 配置RequestConfig
@Bean
public RequestConfig requestConfig(){
//1.3. 请求配置RequestConfig
return RequestConfig.custom()
.setConnectTimeout(1000)
.setConnectionRequestTimeout(500)
.setSocketTimeout(10 * 1000)
.build();
}
//4. 创建一个工厂
@Bean
public ClientHttpRequestFactory requestFactory(HttpClient httpClient){
return new HttpComponentsClientHttpRequestFactory(httpClient);
}
//5. 配置restTemplate
@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;
}
}
6整合SpringBoot测试类
- 在测试代码中可以进行Spring容器的注册
package com.czxy;
import com.alibaba.fastjson.JSON;
import com.czxy.domain.User;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.io.IOException;
/**
* Created by 澈 on 2019/12/4.
*/
@RunWith(SpringRunner.class) //spring 整合junit
@SpringBootTest(classes = HttpClientApplication.class) //spring整合启动类
public class Test04 {
@Resource
private CloseableHttpClient httpClient;
@Resource
private RestTemplate restTemplate;
@Resource
private PoolingHttpClientConnectionManager connectionManager;
@Resource
private RequestConfig requestConfig;
@Test
public void testDemo02(){
System.out.println(httpClient);
System.out.println(restTemplate);
System.out.println(connectionManager);
System.out.println(requestConfig);
}
}