在REST接口的设计中,利用RestTemplate进行接口测试是种常见的方法。本文主要从以下四个方面来看RestTemplate的使用:
OK,开始吧。
exchange既可以执行POST方法,还可以执行GET,设置header,所以应用最为广泛。
/**
* 发送GET请求
*
* @param uri
* @param params
* @param headers
* @return
*/
public Object doGet(String uri, Map params, HttpHeaders headers) {
HttpEntity
// 上面的代码完全一样仅需替换exchange方法
ResponseEntity response = client.postForEntity(url, requestEntity , String.class );
Map map = new HashMap<>();
map.put("name", "李四");
ResponseEntity responseEntity = restTemplate.getForEntity("http://HELLO-SERVICE/sayhello?name={name}", String.class, map);
return responseEntity.getBody();
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
headers.add("Authorization", "Bearer " + token);
HttpEntity entity = new HttpEntity<>(params, headers);
Object responseEntity = client.postForObject(uri, entity, Object.class);
在RestTemplate中,PUT请求可以通过put方法调用,put方法的参数和前面介绍的postForEntity方法的参数基本一致,只是put方法没有返回值而已。举一个简单的例子,如下
Book book = new Book();
book.setName("红楼梦");
restTemplate.put("http://HELLO-SERVICE/getbook3/{1}", book, 99);
delete请求我们可以通过delete方法调用来实现,如下例子:
restTemplate.delete("http://HELLO-SERVICE/getbook4/{1}", 100);
RestTemplate能大幅简化了提交表单数据的难度,并且附带了自动转换JSON数据的功能
JSONObject param = new JSONObject();
param.put("message", '短信内容');
JSONObject item = new JSONObject();
item.put("user_mobile", mobile);
item.put("signature", "短信签名");
param.put("sms", item);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity requestEntity = new HttpEntity(param, headers);
log.info("调用发送短信通知失败接口,requestEntity:{}", requestEntity);
ResponseEntity responseEntity = restTemplate.exchange("http://notification.test.com", HttpMethod.POST, requestEntity, JSONObject.class);
JSONObject retJson = responseEntity.getBody();
log.info("调用发送短信通知接口,返回:{}", retJson);
Integer code = (Integer) retJson.get("code");
String msg = (String) retJson.get("message");
if (code > 0) {
throw new BaseException("调用发送短信通知失败,原因:", msg);
}
在RestTemplate的使用中,HttpEntity用于传递具体的参数值,而uriVariables则用于格式化Http地址,而不是地址参数,正确的用法如下:
// 在地址中加入格式化参数path
String url = "http://localhost/mirana-ee/app/{path}";
// 准备格式化参数
Map varParams = new HashMap();
varParams.put("path", "login");
// 其他代码略
// 格式化提交地址
ResponseEntity response = client.postForEntity(url, requestEntity , String.class, varParams);
在网上的很多例子中,我发现很多人为了处理Payload提交,都添加了自定义的HttpMessageConverter,如下
// 完全没有必要
client.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
client.getMessageConverters().add(new StringHttpMessageConverter());
然后,经过我查看源码与调试发现,RestTemplate内置了7种HttpMessageConverter,如下:
当POST请求的请求头里设置Content-Type: application/x-www-form-urlencoded(默认), 参数在请求体以标准的Form Data的形式提交,以&符号拼接,参数格式为key=value&key=value&key=value….
如果使用AJAX原生POST请求,请求头里设置Content-Type:application/json,请求的参数会显示在Request Payload中,参数格式为JSON格式:{“key”:”value”,”key”:”value”…},这种方式可读性会更好。对于Payload方式,提交的内容一定要是String,且Header要设置为“application/json”,示例如下:
// 请求地址
String url = "http://localhost/mirana-ee/app/login";
RestTemplate client = new RestTemplate();
// 一定要设置header
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
// 将提交的数据转换为String
// 最好通过bean注入的方式获取ObjectMapper
ObjectMapper mapper = new ObjectMapper();
Map params= new HashMap();
params.put("username", "国米");
params.put("password", "123456");
String value = mapper.writeValueAsString(params);
HttpEntity requestEntity = new HttpEntity(value, headers);
// 执行HTTP请求
ResponseEntity response = client.postForEntity(url, requestEntity , String.class );
System.out.println(response.getBody());
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(30 * 1000);
requestFactory.setReadTimeout(30 * 1000);
restTemplate.setRequestFactory(requestFactory);
package net.demo.my.common.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
public class HttpUtil {
public static final String APPLICATION_JSON = "application/json";
public static final String APPLICATION_JSON_UTF8 = "application/json;charset=UTF-8";
/**
* Send a get request
*
* @param url
* @return response
* @throws IOException
*/
static public String get(String url) throws IOException {
return get(url, null);
}
/**
* Send a get request
*
* @param url Url as string
* @param headers Optional map with headers
* @return response Response as string
* @throws IOException
*/
static public String get(String url,
Map headers) throws IOException {
return fetch("GET", url, null, headers);
}
/**
* Send a post request
*
* @param url Url as string
* @param body Request body as string
* @param headers Optional map with headers
* @return response Response as string
* @throws IOException
*/
static public String post(String url, String body,
Map headers) throws IOException {
return fetch("POST", url, body, headers);
}
/**
* Send a post request
*
* @param url Url as string
* @param body Request body as string
* @return response Response as string
* @throws IOException
*/
static public String post(String url, String body) throws IOException {
return post(url, body, null);
}
/**
* Post a form with parameters
*
* @param url Url as string
* @param params map with parameters/values
* @return response Response as string
* @throws IOException
*/
static public String postForm(String url, Map params)
throws IOException {
return postForm(url, params, null);
}
/**
* Post a form with parameters
*
* @param url Url as string
* @param params Map with parameters/values
* @param headers Optional map with headers
* @return response Response as string
* @throws IOException
*/
static public String postForm(String url, Map params,
Map headers) throws IOException {
// set content type
if (headers == null) {
headers = new HashMap();
}
headers.put("Content-Type", "application/x-www-form-urlencoded");
// parse paramet ers
String body = "";
if (params != null) {
boolean first = true;
for (String param : params.keySet()) {
if (first) {
first = false;
} else {
body += "&";
}
String value = params.get(param);
body += URLEncoder.encode(param, "UTF-8") + "=";
body += URLEncoder.encode(value, "UTF-8");
}
}
return post(url, body, headers);
}
/**
* Send a put request
*
* @param url Url as string
* @param body Request body as string
* @param headers Optional map with headers
* @return response Response as string
* @throws IOException
*/
static public String put(String url, String body,
Map headers) throws IOException {
return fetch("PUT", url, body, headers);
}
/**
* Send a put request
*
* @param url Url as string
* @return response Response as string
* @throws IOException
*/
static public String put(String url, String body) throws IOException {
return put(url, body, null);
}
/**
* Send a delete request
*
* @param url Url as string
* @param headers Optional map with headers
* @return response Response as string
* @throws IOException
*/
static public String delete(String url,
Map headers) throws IOException {
return fetch("DELETE", url, null, headers);
}
/**
* Send a delete request
*
* @param url Url as string
* @return response Response as string
* @throws IOException
*/
static public String delete(String url) throws IOException {
return delete(url, null);
}
/**
* Append query parameters to given url
*
* @param url Url as string
* @param params Map with query parameters
* @return url Url with query parameters appended
* @throws IOException
*/
static public String appendQueryParams(String url,
Map params) throws IOException {
String fullUrl = url;
if (params != null) {
boolean first = (fullUrl.indexOf('?') == -1);
for (String param : params.keySet()) {
if (first) {
fullUrl += '?';
first = false;
} else {
fullUrl += '&';
}
String value = params.get(param);
fullUrl += URLEncoder.encode(param, "UTF-8") + '=';
fullUrl += URLEncoder.encode(value, "UTF-8");
}
}
return fullUrl;
}
/**
* Retrieve the query parameters from given url
*
* @param url Url containing query parameters
* @return params Map with query parameters
* @throws IOException
*/
static public Map getQueryParams(String url)
throws IOException {
Map params = new HashMap();
int start = url.indexOf('?');
while (start != -1) {
// read parameter name
int equals = url.indexOf('=', start);
String param = "";
if (equals != -1) {
param = url.substring(start + 1, equals);
} else {
param = url.substring(start + 1);
}
// read parameter value
String value = "";
if (equals != -1) {
start = url.indexOf('&', equals);
if (start != -1) {
value = url.substring(equals + 1, start);
} else {
value = url.substring(equals + 1);
}
}
params.put(URLDecoder.decode(param, "UTF-8"),
URLDecoder.decode(value, "UTF-8"));
}
return params;
}
/**
* Returns the url without query parameters
*
* @param url Url containing query parameters
* @return url Url without query parameters
* @throws IOException
*/
static public String removeQueryParams(String url)
throws IOException {
int q = url.indexOf('?');
if (q != -1) {
return url.substring(0, q);
} else {
return url;
}
}
/**
* Send a request
*
* @param method HTTP method, for example "GET" or "POST"
* @param url Url as string
* @param body Request body as string
* @param headers Optional map with headers
* @return response Response as string
* @throws IOException
*/
static public String fetch(String method, String url, String body,
Map headers) throws IOException {
// connection
URL u = new URL(url);
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setConnectTimeout(10000);
conn.setReadTimeout(10000);
// method
if (method != null) {
conn.setRequestMethod(method);
}
// headers
if (headers != null) {
for (String key : headers.keySet()) {
conn.addRequestProperty(key, headers.get(key));
}
}
// body
if (body != null) {
conn.setDoOutput(true);
OutputStream os = conn.getOutputStream();
os.write(body.getBytes());
os.flush();
os.close();
}
// response
InputStream is = conn.getInputStream();
String response = streamToString(is);
is.close();
// handle redirects
if (conn.getResponseCode() == 301) {
String location = conn.getHeaderField("Location");
return fetch(method, location, body, headers);
}
return response;
}
/**
* Read an input stream into a string
*
* @param in
* @return
* @throws IOException
*/
static public String streamToString(InputStream in) throws IOException {
StringBuffer out = new StringBuffer();
byte[] b = new byte[4096];
for (int n; (n = in.read(b)) != -1; ) {
out.append(new String(b, 0, n));
}
return out.toString();
}
}
调用例子:
String url = "https://tcc.taobao.com/cc/json/mobile_tel_segment.htm";
Map param = new HashMap<>();
param.put("tel", mobileNum);
String fullUrl = HttpUtil.appendQueryParams(url, param);
String res = HttpUtil.get(fullUrl);
Map headers = new HashMap<>();
headers.put("content-type", HttpUtil.APPLICATION_JSON_UTF8);
Map param = new HashMap<>();
param.put("dataId", called);
String body = JSON.toJSONString(param);
String retJson = HttpUtil.post(url, body, headers);
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Map;
@Component
@Slf4j
public class HttpClientService {
public static final String AUTHORIZATION = "Authorization";
@Autowired
private RestTemplate customRestTemplate;
public T doPost(final String uri, final Map params, Class cls, String token) {
if (log.isInfoEnabled()) {
log.info("请求 URL:" + uri);
log.info("请求参数:" + JSON.toJSONString(params));
}
final HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE);
headers.add("keepalive_timeout", "30s");
final HttpEntity