Spring RestTemplate配置及讲解 - Go语言中文社区

Spring RestTemplate配置及讲解


HttpClient 与 RestTemplate 都是Java代码发送http请求的工具。


HttpClient

  • HttpClient 是apache的开源,需要引入两个包:httpclient-4.2.4.jar 和 httpcore-4.2.2.jar

RestTemplate

  • RestTemplate 是Spring的封装,需要spring的包 spring-web-3.0.7.RELEASE.jar

  • 目前我们使用Spring boot框架作为开发主框架,以下对RestTemplate,以及我们代码中封装的发送http请求的方法做一些讲解。

同步RestTemplate配置

RestConfig.java


package com.shanyuan.platform.ms.base.rest.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

/**
* restTemplate配置
* @author yangjian 2017/09/28
*
*/
@Component
@Configuration
public class RestConfig {

@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory){
return new RestTemplate(factory);
}

@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(5000);//ms
factory.setConnectTimeout(15000);//ms
return factory;
}

}


异步RestTemplate配置

  • AsyncRestConfig.java
package com.shanyuan.platform.ms.base.rest.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.AsyncClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.AsyncRestTemplate;

@Component
@Configuration
public class AsyncRestConfig {

@Bean
public AsyncRestTemplate asyncRestTemplate(){
return new AsyncRestTemplate();
}

public AsyncClientHttpRequestFactory clientHttpRequestFactory(){
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(5000);
factory.setReadTimeout(5000);
return factory;

}
}


我们项目中如果要使用Resttemplate注解的话需要对Bean进行配置。配置完成之后就可以直接注入 RestTemplate 和 AsyncRestTemplate 进行get或者post或者其他方式进行访问了,目前最常用的请求方式为get与post,所以代码中只对这两种请求进行了封装,并且针对同一类型请求,基于参数以及其他需求做了不同封装。


  • RestService.java

package com.shanyuan.platform.ms.base.rest.service;

import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpHeaders;
import org.springframework.util.LinkedMultiValueMap;

import com.alibaba.fastjson.JSONObject;
import com.shanyuan.platform.ms.base.common.ServiceResult;

/**
* restService接口
* @author yangjian 2017/09/28
*
*/
public interface RestService {

/**
* get请求
* @param map
* @param url
* @return
*/
public ServiceResult parseGetResult(Map<String, Object> map, String url);

/**
* get请求
* @param map
* @param url
* @return
*/
public ServiceResult parseGetResult(HashMap<String, Object> map, String url);

/**
* 无参或已拼接参数get请求
* @param url
* @return
*/
public ServiceResult parseGetResult(String url);

/**
* post请求
* @param map
* @param url
* @return
*/
public ServiceResult parsePostResult(LinkedMultiValueMap<String, Object> map, String url);

/**
* 带有请求头的post请求
* @param httpHeader
* @param params
* @param url
* @return
*/
public ServiceResult parsePostResultWithHeader(HttpHeaders httpHeader, JSONObject params, String url);

}


  • AsyncService.java

package com.shanyuan.platform.ms.base.rest.service;

import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpHeaders;
import org.springframework.util.LinkedMultiValueMap;

import com.alibaba.fastjson.JSONObject;
import com.shanyuan.platform.ms.base.common.ServiceResult;

/**
* 异步rest请求接口
* @author win10
*
*/
public interface AsyncRestService {

/**
* get请求
* @param map
* @param url
* @return
*/
public ServiceResult parseGetResult(Map<String, Object> map, String url);

/**
* get请求
* @param url
* @return
*/
public ServiceResult parseGetResult(String url);

/**
* get请求
* @param map
* @param url
* @return
*/
public ServiceResult parseGetResult(HashMap<String, Object> map, String url);

/**
* post请求
* @param map
* @param url
* @return
*/
public ServiceResult parsePostResult(LinkedMultiValueMap<String, Object> map, String url);

/**
* 带header的http请求
* @param headers
* @param params
* @param url
* @return
*/
public ServiceResult parsePostResultWithHeader(HttpHeaders headers, JSONObject params, String url);

}


  • 抽象接口,对不同请求方式及同一请求方式的不同实现进行封装

  • RestServiceImpl.java

package com.shanyuan.platform.ms.base.rest.service.impl;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.client.RestTemplate;

import com.alibaba.fastjson.JSONObject;
import com.shanyuan.platform.ms.base.common.BaseService;
import com.shanyuan.platform.ms.base.common.ServiceResult;
import com.shanyuan.platform.ms.base.exception.CoreServiceExcepType;
import com.shanyuan.platform.ms.base.exception.CoreServiceException;
import com.shanyuan.platform.ms.base.rest.service.RestService;

@Service
public class RestServiceImpl extends BaseService implements RestService{

protected Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
private RestTemplate restTemplate;

/**
* 发送get请求
* @param map 参数map
* @param url 请求地址,参数拼接在链接中,用通配符代表
* 示例 :
* Map<String, Object> map = new HashMap<String, Object>;
* map.put("channel", 1);
* map.put("goodsId", 2);
* String url = "http://localhost:8083/goods/goodsIndex?channel={channel}&goods_id={goodsId}";
* 根据实际情况自己添加参数
* @return
*/
@Override
public ServiceResult parseGetResult(Map<String, Object> map, String url){
ServiceResult result = new ServiceResult();
try {
String sResult = restTemplate.getForObject(url, String.class, map);
JSONObject jResult = JSONObject.parseObject(sResult);
result = buildSuccessResult(jResult);
} catch (CoreServiceException e) {
result = buildErrorResult("url:"+ url +"请求失败");
logger.info("url:{}, map:{},请求失败", url, map);
e = new CoreServiceException(CoreServiceExcepType.REQUEST_CODE, "请求失败");
e.printStackTrace();
}

return result;
}

/**
* 发送get请求
* @param map 参数map
* @param url 请求地址,地址中不需要拼接参数,在方法中处理
* 示例 :
* HashMap<String, Object> map = new HashMap<String, Object>;
* map.put("channel", 1);
* map.put("goodsId", 2);
* String url = "http://localhost:8083/goods/goodsIndex";
* 根据实际情况自己添加参数
* @return
*/
@Override
public ServiceResult parseGetResult(HashMap<String, Object> map, String url) {
StringBuilder sb = new StringBuilder();
sb.append(url);
if(!CollectionUtils.isEmpty(map)){
Set keys = map.keySet();
sb.append("?");
for (String string : keys) {
sb.append(string);
sb.append("=");
sb.append(map.get(string).toString());
sb.append("&");
}
}
String finalUrl = sb.toString();
if(finalUrl.endsWith("&")){
finalUrl = finalUrl.substring(0, finalUrl.length() - 1);
}
ServiceResult result = this.parseGetResult(finalUrl);
return result;
}

/**
* 发送get请求
* @param url 请求地址
* 请求为纯字符串,可以是无参数的get请求,也可以是将参数的K V都拼接好传入
* 示例
* 1、http://localhost:8083/goods/goodsIndex
* 2、http://localhost:8083/goods/goodsIndex?channel=1&goods_id=2
* 以上两种方式都支持
* @return
*
*/
@Override
public ServiceResult parseGetResult(String url) {
ServiceResult result = new ServiceResult();
try {
String sResult = restTemplate.getForObject(url, String.class);
JSONObject jResult = JSONObject.parseObject(sResult);
result = buildSuccessResult(jResult);
} catch (CoreServiceException e) {
result = buildErrorResult("url:"+ url +"请求失败");
logger.info("url:{}, map:{},请求失败", url);
e = new CoreServiceException(CoreServiceExcepType.REQUEST_CODE, "请求失败");
e.printStackTrace();
}

return result;
}

/**
* 发送post请求
* @param map 请求参数集合
* @param 请求地址
* 示例:
* MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
* map.add("channel", 1);
* map.add("goods_id", 2);
* String url = "http://localhost:8083/goods/goodsIndex";
* 根据实际情况自己添加参数
* @return
*/
@Override
public ServiceResult parsePostResult(LinkedMultiValueMap<String, Object> map, String url) {
ServiceResult result = new ServiceResult();
try{
String sResult = restTemplate.postForObject(url, map, String.class);
JSONObject jResult = JSONObject.parseObject(sResult);
result = buildSuccessResult(jResult);
}catch (CoreServiceException e) {
result = buildErrorResult("url:"+ url +"请求失败");
logger.info("url:{}, map:{},请求失败", url, map);
e = new CoreServiceException(CoreServiceExcepType.REQUEST_CODE, "请求失败");
e.printStackTrace();
}
return result;
}

/**
* 带header的http post请求
* header中的值可以自己设置
*/
@Override
public ServiceResult parsePostResultWithHeader(HttpHeaders httpHeader, JSONObject params, String url) {
ServiceResult result = new ServiceResult();
try{
HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<Map<String,Object>>(params, httpHeader);
ResponseEntity exchange = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
JSONObject jResult = JSONObject.parseObject(exchange.getBody());
result = buildSuccessResult(jResult);
}catch (Exception e) {
logger.info("url:{}, map:{},请求失败", url, params);
result = buildErrorResult("url:" + url + "请求失败");
}
return result;
}

}


  • AsyncServiceImpl.java

package com.shanyuan.platform.ms.base.rest.service.impl;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.web.client.AsyncRestTemplate;

import com.alibaba.fastjson.JSONObject;
import com.shanyuan.platform.ms.base.common.BaseService;
import com.shanyuan.platform.ms.base.common.ServiceResult;
import com.shanyuan.platform.ms.base.exception.CoreServiceExcepType;
import com.shanyuan.platform.ms.base.exception.CoreServiceException;
import com.shanyuan.platform.ms.base.rest.service.AsyncRestService;

/**
*
* @author yangjian 2017/09/28
*
*/
@Service
public class AsyncRestServiceImpl extends BaseService implements AsyncRestService {

protected Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
private AsyncRestTemplate restTemplate;

/**
* 发送get请求
* @param map 参数map
* @param url 请求地址,参数拼接在链接中,用通配符代表
* 示例 :
* Map<String, Object> map = new HashMap<String, Object>;
* map.put("channel", 1);
* map.put("goodsId", 2);
* String url = "http://localhost:8083/goods/goodsIndex?channel={channel}&goods_id={goodsId}";
* 根据实际情况自己添加参数
* @return
*/
@Override
public ServiceResult parseGetResult(Map<String, Object> map, String url) {

ServiceResult result = new ServiceResult();
ListenableFuture<ResponseEntity> forEntity = restTemplate.getForEntity(url, String.class, map);
forEntity.addCallback(new ListenableFutureCallback<ResponseEntity>() {
public void onSuccess(ResponseEntity resp) {
String sResult = resp.getBody();
if(!StringUtils.isEmpty(sResult)){
JSONObject jResult = JSONObject.parseObject(sResult);
result.setContent(jResult);
result.setCode(CODE_SUCCESS);
result.setMessage("success");
logger.info("url:{}, map:{} 请求成功", url, map);
}else{
this.onFailure(new Throwable(new CoreServiceException(CoreServiceExcepType.REQUEST_CODE, "请求结果为空")));
}
}
public void onFailure(Throwable t) {
result.setMessage(t.getMessage());
result.setCode(CODE_ERROR);
t.printStackTrace();
logger.info("url:{}, map:{} 请求失败", url, map);
}
});

return result;
}

/**
* 发送get请求
* @param url 请求地址
* 请求为纯字符串,可以是无参数的get请求,也可以是将参数的K V都拼接好传入
* 示例
* 1、http://localhost:8083/goods/goodsIndex
* 2、http://localhost:8083/goods/goodsIndex?channel=1&goods_id=2
* 以上两种方式都支持
* @return
*
*/
@Override
public ServiceResult parseGetResult(String url) {
ServiceResult result = new ServiceResult();
ListenableFuture<ResponseEntity> forEntity = restTemplate.getForEntity(url, String.class);
forEntity.addCallback(new ListenableFutureCallback<ResponseEntity>() {
public void onSuccess(ResponseEntity resp) {
String sResult = resp.getBody();
if(!StringUtils.isEmpty(sResult)){
JSONObject jResult = JSONObject.parseObject(sResult);
result.setContent(jResult);
result.setCode(CODE_SUCCESS);
result.setMessage("success");
logger.info("url:{} 请求成功", url);
}else{
this.onFailure(new Throwable(new CoreServiceException(CoreServiceExcepType.REQUEST_CODE, "请求结果为空")));
}
}
public void onFailure(Throwable t) {
result.setMessage(t.getMessage());
result.setCode(CODE_ERROR);
t.printStackTrace();
logger.info("url:{} 请求失败", url);
}
});

return result;
}

/**
* 发送get请求
* @param map 参数map
* @param url 请求地址,地址中不需要拼接参数,在方法中处理
* 示例 :
* HashMap<String, Object> map = new HashMap<String, Object>;
* map.put("channel", 1);
* map.put("goodsId", 2);
* String url = "http://localhost:8083/goods/goodsIndex";
* 根据实际情况自己添加参数
* @return
*/
@Override
public ServiceResult parseGetResult(HashMap<String, Object> map, String url) {
StringBuilder sb = new StringBuilder();
sb.append(url);
if(!CollectionUtils.isEmpty(map)){
Set keys = map.keySet();
sb.append("?");
for (String string : keys) {
sb.append(string);
sb.append("=");
sb.append(map.get(string).toString());
sb.append("&");
}
}
String finalUrl = sb.toString();
if(finalUrl.endsWith("&")){
finalUrl = finalUrl.substring(0, finalUrl.length() - 1);
}
ServiceResult result = this.parseGetResult(finalUrl);
return result;
}

/**
* 发送post请求
* @param map 请求参数集合
* @param 请求地址
* 示例:
* MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
* map.add("channel", 1);
* map.add("goods_id", 2);
* String url = "http://localhost:8083/goods/goodsIndex";
* 根据实际情况自己添加参数
* @return
*/
@Override
public ServiceResult parsePostResult(LinkedMultiValueMap<String, Object> map, String url) {
ServiceResult result = new ServiceResult();
String header = "";
HttpEntity httpEntity = new HttpEntity(header);
ListenableFuture<ResponseEntity> forEntity = restTemplate.postForEntity(url, httpEntity, String.class, map);
forEntity.addCallback(new ListenableFutureCallback<ResponseEntity>() {
public void onSuccess(ResponseEntity resp) {
String sResult = resp.getBody();
if(!StringUtils.isEmpty(sResult)){
JSONObject jResult = JSONObject.parseObject(sResult);
result.setContent(jResult);
result.setCode(CODE_SUCCESS);
result.setMessage("success");
logger.info("url:{}, map:{} 请求成功", url, map);
}else{
this.onFailure(new Throwable(new CoreServiceException(CoreServiceExcepType.REQUEST_CODE, "请求结果为空")));
}
}
public void onFailure(Throwable t) {
result.setMessage(t.getMessage());
result.setCode(CODE_ERROR);
t.printStackTrace();
logger.info("url:{}, map:{} 请求失败", url, map);
}
});
return result;
}

@Override
public ServiceResult parsePostResultWithHeader(HttpHeaders headers, JSONObject params, String url) {
ServiceResult result = new ServiceResult();
HttpEntity httpEntity = new HttpEntity(headers);
ListenableFuture<ResponseEntity> forEntity = restTemplate.postForEntity(url, httpEntity, String.class, params);
forEntity.addCallback(new ListenableFutureCallback<ResponseEntity>() {
public void onSuccess(ResponseEntity resp) {
String sResult = resp.getBody();
if(!StringUtils.isEmpty(sResult)){
JSONObject jResult = JSONObject.parseObject(sResult);
result.setContent(jResult);
result.setCode(CODE_SUCCESS);
result.setMessage("success");
logger.info("url:{}, map:{} 请求成功", url, params);
}else{
this.onFailure(new Throwable(new CoreServiceException(CoreServiceExcepType.REQUEST_CODE, "请求结果为空")));
}
}
public void onFailure(Throwable t) {
result.setMessage(t.getMessage());
result.setCode(CODE_ERROR);
t.printStackTrace();
logger.info("url:{}, map:{} 请求失败", url, params);
}
});
return result;
}

}


以上是对上边接口的实现,具体参数说明都已经写到注释里边,有不清楚的问题可以一起讨论。

补充:目前已经我们项目中已经不使用这种方式去调用接口了,直接用SpringBoot中Feign组件了。

转载于:https://my.oschina.net/u/2617082/blog/1592528

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_34413802/article/details/92337949
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-01 22:50:19
  • 阅读 ( 1066 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢