10、RestTemplate方式实现远程调用Client
一、JSONObject类详解:
JSONobject是FastJson提供的对象,在API中是用一个私有的常量map进行封装的,实际就是一个map,只不过 FastJson对其进行了封装,添加了很多方便快捷的属性方法。
添加相关依赖:
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.79</version> </dependency>
1、将Java对象转化成String:
2、将String类型转json对象,取JSON中KEY对应的VALUE:
3、将String对象转化为List类型:
public class JSONObjectDemo { public static void main(String[] args) { //创建对象 List<JsonObjectVO> list = new ArrayList<>(); //对象1 JsonObjectVO vo1 = new JsonObjectVO(); vo1.setUuid(UUID.randomUUID().toString()); vo1.setName("1"); //对象2 JsonObjectVO vo2 = new JsonObjectVO(); vo2.setUuid(UUID.randomUUID().toString()); vo2.setName("2"); list.add(vo1); list.add(vo2); ResponseVO responseVO = ResponseVO.builder() .uuid(UUID.randomUUID().toString()) .list(list) .build(); /** * 1、java对象转化成String * toPrint:{"list":[{"name":"1","uuid":"b73bb9e8-f7a3-4dcf-8d8d-51313c7f5fd7"},{"name":"2","uuid":"ef109d35-cd07-45cd-9b45-791b205c878f"}],"uuid":"dbc3b9c6-2360-4b83-9d15-b88fe7980f27"} * */ String str = JSONObject.toJSONString(responseVO); /** * 2、String类型转json对象,取JSON中的KEY * toPrint:[{"name":"1","uuid":"b73bb9e8-f7a3-4dcf-8d8d-51313c7f5fd7"},{"name":"2","uuid":"ef109d35-cd07-45cd-9b45-791b205c878f"}] * */ Object data = JSONObject.parseObject(str).get("list"); /** * 3、将String对象转化为List类型 * toPrint:[JsonObjectVO(uuid=aebd390d-f543-4410-9c3a-98f2cb057757, name=1), JsonObjectVO(uuid=d170bb12-7570-47dd-8f2d-9ec2df5573c5, name=2)] * */ List<JsonObjectVO> aList = JSONObject.parseArray(JSONObject.toJSONString(data),JsonObjectVO.class); System.out.println(str); System.out.println(data); System.out.println(aList); } }
二、RestTemplate详解:
RestTemplate是由Spring框架提供的一个可调用REST服务的类,它简化了与HTTP服务的通信方式,统一了RESTFUL的标准,封装了HTTP连接。相较于之前常用的HttpClient,RestTemplate是一种更为优雅的调用RESTFul服务的方式。
1、添加依赖:
<!--JSONObject插件--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.79</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.1</version> </dependency>
2、声明RestTemplate配置类:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate(){ return new RestTemplate(); } }
3、RestTemplate配置超时连接:
@Configuration public class RestTemplateConfig { @Bean public RestTemplate restTemplate(){ //配置HTTP超时时间 HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); // 从连接池中获取连接的超时时间 httpRequestFactory.setConnectionRequestTimeout(10000); // 客户端和服务器建立连接的超时时间 httpRequestFactory.setConnectTimeout(10000); // 户端从服务器读取数据的超时时间 httpRequestFactory.setReadTimeout(60000); return new RestTemplate(httpRequestFactory); } }
4、RestTemplate采用HttpClient连接池配置高并发下超时连接:
添加依赖:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency>
相关配置:
import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; 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.SSLConnectionSocketFactory; import org.apache.http.impl.client.HttpClientBuilder; 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.web.client.RestTemplate; @Configuration public class RestTemplateConfig { /** * 高并发采用HttpClient连接池 */ @Bean public RestTemplate restTemplate() { return new RestTemplate(httpRequestFactory()); } @Bean public ClientHttpRequestFactory httpRequestFactory() { return new HttpComponentsClientHttpRequestFactory(httpClient()); } @Bean public HttpClient httpClient() { Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create() .register("http", PlainConnectionSocketFactory.getSocketFactory()) .register("https", SSLConnectionSocketFactory.getSocketFactory()) .build(); PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry); //设置整个连接池最大连接数 connectionManager.setMaxTotal(400); //路由是对maxTotal的细分 connectionManager.setDefaultMaxPerRoute(100); RequestConfig requestConfig = RequestConfig.custom() .setSocketTimeout(30000) //返回数据的超时时间 .setConnectTimeout(20000) //连接上服务器的超时时间 .setConnectionRequestTimeout(1000) //从连接池中获取连接的超时时间 .build(); return HttpClientBuilder.create() .setDefaultRequestConfig(requestConfig) .setConnectionManager(connectionManager) .build(); } }
5、自定义远程调用Client通用工具类(重):
import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import java.util.HashSet; import java.util.Map; import java.util.Optional; @Slf4j @Component public class HttpClientUtil { @Autowired private RestTemplate restTemplate; /** * @Param basisUrl:根地址(不带请求参数) * @Param param:请求参数 * @Param method:请求方式(HttpMethod.GET、HttpMethod.POST......) * @Param authToken:请求令牌 */ public String getUrlResponse(String basisUrl, Map<Object, Object> param, HttpMethod method, String authToken) { MultiValueMap heards = new LinkedMultiValueMap(); if (StringUtils.isNotBlank(authToken)) { heards.add("Authorization", authToken); } //合成请求地址 String url = buildUrl(basisUrl, param); log.info("请求地址为:" + url); HttpEntity<Object> httpEntity = new HttpEntity<>(heards); ResponseEntity<Object> response = restTemplate.exchange(url, method, httpEntity, Object.class, param); String jsonString = JSONObject.toJSONString(response.getBody()); return jsonString; } /** * 拼接url地址: * 例:http://127.0.0.1:xxx/xx/xxx?xx=xx&xx=xx */ private String buildUrl(String basisUrl, Map<Object, Object> param) { StringBuilder params = new StringBuilder(basisUrl); params.append("?"); Optional.ofNullable(param.entrySet()).orElse(new HashSet<>()).stream().forEach((Map.Entry entry) -> { params.append(entry.getKey()).append("=").append(entry.getValue()).append("&"); }); return params.toString().substring(0, params.toString().length() - 1); } }
三、远程调用的实现:
1、test-demo工程:
声明控制类:
@RestController @RequestMapping("/v1") public class DemoController { @Autowired private DemoService demoService; /** * get方式 * 查询全量信息 * * http://localhost:8081/v1/get-detail?pageNum=1&pageSize=8 * */ @GetMapping("/get-detail") public Response<List<ResponseVO>> list1( @RequestParam(value = "pageNum", required = false , defaultValue = "1") Integer pageNum, @RequestParam(value = "pageSize", required = false , defaultValue = "8") Integer pageSize) { return Response.success(demoService.selectDetail(pageNum , pageSize)); } /** * post方式 * 查询全量信息 * * http://localhost:8081/v1/post-detail * */ @PostMapping("/post-detail") public Response<List<ResponseVO>> list2() { return Response.success(demoService.selectList()); } }
2、client-demo工程:
(1)、获取test-demo工程接口返回:
@Component @Slf4j public class HttpClient { @Autowired private HttpClientUtil httpClientUtil; @Value("${url.v1.clent:http://localhost:8081/v1}") private String url; public String getGetMethodURL() { return url + "/get-detail"; } public String list() { //获取根地址 String url = getGetMethodURL(); //放置请求参数 Map<Object, Object> param = new HashMap<>(); param.put("pageNum", 1); param.put("pageSize", 100); String jsonString = httpClientUtil.getUrlResponse(url, param, HttpMethod.GET, null); Object data = JSONObject.parseObject(jsonString).get("entity"); if (ObjectUtils.isEmpty(data)) { return "数据为空"; } String dataList = JSONObject.toJSONString(data); return dataList; } }
(2)、业务类:
@Service public class DemoServiceImpl implements DemoService { @Autowired private HttpClient httpClient; @Override public String selectList() { return httpClient.list(); } }