欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

RestTemplate详解

程序员文章站 2022-04-28 17:29:33
...

概述

当我们在开发项目的过程中,一个系统中要请求另外一个服务中的接口,那么通常是用过http请求,需要有个httpClient类:类似代码如下:

import com.alibaba.fastjson.JSONObject;
/**
 * HttpClient4.3工具类
 * @author tech
 * @date 2016-03-29
 *
 */
public class HttpClientUtils {
    private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);    //日志记录
 
    /**
     * httpPost
     * @param url  路径
     * @param jsonParam 参数
     * @return
     */
    public static JSONObject httpPost(String url,JSONObject jsonParam){
        return httpPost(url, jsonParam, false);
    }
 
    /**
     * post请求
     * @param url         url地址
     * @param jsonParam     参数
     * @param noNeedResponse    不需要返回结果
     * @return
     */
    public static JSONObject httpPost(String url,JSONObject jsonParam, boolean noNeedResponse){
        //post请求返回结果
        CloseableHttpClient httpClient = HttpClients.createDefault();  
        JSONObject jsonResult = null;
        HttpPost httpPost = new HttpPost(url);
        //设置请求和传输超时时间
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();
        httpPost.setConfig(requestConfig); 
        try {
            if (null != jsonParam) {
                //解决中文乱码问题
                StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
                entity.setContentEncoding("UTF-8");
                entity.setContentType("application/json");
                httpPost.setEntity(entity);
            }
            CloseableHttpResponse result = httpClient.execute(httpPost);
            /**请求发送成功,并得到响应**/
            if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                String str = "";
                try {
                    /**读取服务器返回过来的json字符串数据**/
                    str = EntityUtils.toString(result.getEntity(), "utf-8");
                    if (noNeedResponse) {
                        return null;
                    }
                    /**把json字符串转换成json对象**/
                    jsonResult = JSONObject.parseObject(str);
                } catch (Exception e) {
                    logger.error("post请求提交失败:" + url, e);
                }
            }
        } catch (IOException e) {
            logger.error("post请求提交失败:" + url, e);
        } finally{
        	httpPost.releaseConnection();
        }
        return jsonResult;
    }
 
 
    /**
     * 发送get请求
     * @param url    路径
     * @return
     */
    public static JSONObject httpGet(String url){
        //get请求返回结果
        JSONObject jsonResult = null;
        CloseableHttpClient client = HttpClients.createDefault();  
        //发送get请求
        HttpGet request = new HttpGet(url);
        //设置请求和传输超时时间
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();
        request.setConfig(requestConfig); 
        try {
            CloseableHttpResponse response = client.execute(request);     
 
            /**请求发送成功,并得到响应**/
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                /**读取服务器返回过来的json字符串数据**/
            	HttpEntity entity = response.getEntity();
                String strResult = EntityUtils.toString(entity, "utf-8");
                /**把json字符串转换成json对象**/
                jsonResult = JSONObject.parseObject(strResult);
            } else {
                logger.error("get请求提交失败:" + url);
            }
        } catch (IOException e) {
            logger.error("get请求提交失败:" + url, e);
        } finally{
        	request.releaseConnection();
        }
        return jsonResult;
    }
}

今天讲一下spring中另外一种请求方式,通过RestTemplate 这个模板类:

RestTemplate与httpClient类似,都是java中可以模拟http请求的封装。但是RestTemplate比httpClient更优雅,它是spring中的一个封装功能。

RestTemplate也是java中的模板类。采用的设计模式中的模板模式。

源码解析

RestTemplate继承InterceptingHttpAccessor抽象类,实现RestOperation接口。

public class RestTemplate extends InterceptingHttpAccessor implements RestOperations

在RestOperations定义了基本的Rest操作集合。RestTemplate实现了这个接口。

public interface RestOperations {
 
	// GET
 
	<T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException;
 
	<T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
 
	<T> T getForObject(URI url, Class<T> responseType) throws RestClientException;
 
	<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) throws RestClientException;
 
	<T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
 
	<T> ResponseEntity<T> getForEntity(URI url, Class<T> responseType) throws RestClientException;
 
 
	// HEAD
 
	HttpHeaders headForHeaders(String url, Object... uriVariables) throws RestClientException;
 
	HttpHeaders headForHeaders(String url, Map<String, ?> uriVariables) throws RestClientException;
 
	HttpHeaders headForHeaders(URI url) throws RestClientException;
 
 
	// POST
 
	URI postForLocation(String url, Object request, Object... uriVariables) throws RestClientException;
 
	URI postForLocation(String url, Object request, Map<String, ?> uriVariables) throws RestClientException;
 
	URI postForLocation(URI url, Object request) throws RestClientException;
 
	<T> T postForObject(String url, Object request, Class<T> responseType, Object... uriVariables)
			throws RestClientException;
 
	<T> T postForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
			throws RestClientException;
 
	<T> T postForObject(URI url, Object request, Class<T> responseType) throws RestClientException;
 
	<T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
			throws RestClientException;
 
	<T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
			throws RestClientException;
 
	<T> ResponseEntity<T> postForEntity(URI url, Object request, Class<T> responseType) throws RestClientException;
 
 
	// PUT
 
	void put(String url, Object request, Object... uriVariables) throws RestClientException;
 
	void put(String url, Object request, Map<String, ?> uriVariables) throws RestClientException;
 
	void put(URI url, Object request) throws RestClientException;
 
 
	// PATCH
 
	<T> T patchForObject(String url, Object request, Class<T> responseType, Object... uriVariables)
			throws RestClientException;
 
	<T> T patchForObject(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables)
			throws RestClientException;
 
	<T> T patchForObject(URI url, Object request, Class<T> responseType) throws RestClientException;
 
 
 
	// DELETE
 
	void delete(String url, Object... uriVariables) throws RestClientException;
 
	void delete(String url, Map<String, ?> uriVariables) throws RestClientException;
 
	void delete(URI url) throws RestClientException;
 
 
	// OPTIONS
 
	Set<HttpMethod> optionsForAllow(String url, Object... uriVariables) throws RestClientException;
 
	Set<HttpMethod> optionsForAllow(String url, Map<String, ?> uriVariables) throws RestClientException;
 
	Set<HttpMethod> optionsForAllow(URI url) throws RestClientException;
 
 
	// exchange
 
	<T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity,
			Class<T> responseType, Object... uriVariables) throws RestClientException;
 
	<T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity,
			Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
 
	<T> ResponseEntity<T> exchange(URI url, HttpMethod method, HttpEntity<?> requestEntity,
			Class<T> responseType) throws RestClientException;
 
	<T> ResponseEntity<T> exchange(String url,HttpMethod method, HttpEntity<?> requestEntity,
			ParameterizedTypeReference<T> responseType, Object... uriVariables) throws RestClientException;
 
	<T> ResponseEntity<T> exchange(String url, HttpMethod method, HttpEntity<?> requestEntity,
			ParameterizedTypeReference<T> responseType, Map<String, ?> uriVariables) throws RestClientException;
 
	<T> ResponseEntity<T> exchange(URI url, HttpMethod method, HttpEntity<?> requestEntity,
			ParameterizedTypeReference<T> responseType) throws RestClientException;
 
	<T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, Class<T> responseType) throws RestClientException;
 
	<T> ResponseEntity<T> exchange(RequestEntity<?> requestEntity, ParameterizedTypeReference<T> responseType)
			throws RestClientException;
 
 
	// general execution
 
	<T> T execute(String url, HttpMethod method, RequestCallback requestCallback,
			ResponseExtractor<T> responseExtractor, Object... uriVariables) throws RestClientException;
 
	<T> T execute(String url, HttpMethod method, RequestCallback requestCallback,
			ResponseExtractor<T> responseExtractor, Map<String, ?> uriVariables) throws RestClientException;
 
	<T> T execute(URI url, HttpMethod method, RequestCallback requestCallback,
			ResponseExtractor<T> responseExtractor) throws RestClientException;
 
}

PostForObject与PostForEntity的区别在于前者请求返回就是响应体,后者返回的是响应行,响应头,响应体。

这里也有一个基础的http访问类HttpAccessor,里面主要是一个工厂方法,用来构造HttpRequestFactory。

public abstract class HttpAccessor {
 
	protected final Log logger = LogFactory.getLog(getClass());
 
	private ClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
 
	public void setRequestFactory(ClientHttpRequestFactory requestFactory) {
		Assert.notNull(requestFactory, "ClientHttpRequestFactory must not be null");
		this.requestFactory = requestFactory;
	}
 
	public ClientHttpRequestFactory getRequestFactory() {
		return this.requestFactory;
	}
 
	protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException {
		ClientHttpRequest request = getRequestFactory().createRequest(url, method);
		if (logger.isDebugEnabled()) {
			logger.debug("Created " + method.name() + " request for \"" + url + "\"");
		}
		return request;
	}
 
}

springboot对RestTemplate的集成

1.首先添加配置

@Configuration
public class RestTemplateConfig {
	
	@Bean
	public RestTemplate restTemplate(){
		RestTemplate restTemplate = new RestTemplate();
		restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
		return restTemplate;
	}
 
}

不然在service中的autowired会注入不进去

2.再设置请求头

		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);

3.请求行,请求头,请求体分装成 一个Entity

HttpEntity<String> entity = new HttpEntity<>(JSONObject.toJSONString(dto),headers );

4.接下来就调用
ResponseEntity r = restTemplate.exchange(ADD_URL, HttpMethod.POST, entity, String.class);

那就可以请求到结果了。