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();
    }
}

 

 

 

 

 

 

 

 

 

 

posted on 2022-08-17 15:23  爱文(Iven)  阅读(264)  评论(0编辑  收藏  举报

导航