在实际开发中,很多情况下都需要调用不同项目的接口。此时可以用RestTemplate进行调用。本例以Spring Boot下使用RestTemplate为例。
RestTemplate有三个构造器,可以根据需要使用不同的构造器。
public RestTemplate() {...}
public RestTemplate(ClientHttpRequestFactory requestFactory) {
this();
this.setRequestFactory(requestFactory);
}
public RestTemplate(List<HttpMessageConverter<?>> messageConverters) {
this.messageConverters = new ArrayList();
this.errorHandler = new DefaultResponseErrorHandler();
this.headersExtractor = new RestTemplate.HeadersExtractor();
Assert.notEmpty(messageConverters, "At least one HttpMessageConverter required");
this.messageConverters.addAll(messageConverters);
this.uriTemplateHandler = initUriTemplateHandler();
}
根据需要创建Bean实例,采用SimpleClientHttpRequestFactory的方式。可以设置连接超时时间等信息
package com.study.config;
import com.study.common.interceptor.LoggingClientHttpRequestInterceptor;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Config {
@Bean
public RestTemplate restTemplate() {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(100000);
requestFactory.setReadTimeout(100000);
RestTemplate restTemplate = new RestTemplate(requestFactory);
ClientHttpRequestInterceptor ri = new LoggingClientHttpRequestInterceptor();
List<ClientHttpRequestInterceptor> ris = new ArrayList<ClientHttpRequestInterceptor>();
ris.add(ri);
restTemplate.setInterceptors(ris);
return restTemplate;
}
}
设置接口的请求地址及方法名(只测试常用的两种请求get和post)
请求地址常用有以下几种方式
GET请求:
/get_products?name=aa&code=aa123
/get_products
/get_product_details/{code}
POST请求:
/update_product
package com.study.common; public class Constants { public final static String requestUrl = "http://localhost:8080/rest"; public final static String GET_PRODUCTS = "/get_products"; public final static String GET_PRODUCT_DETAILS = "/get_product_details/{code}"; public final static String UPDATE_PRODUCTS = "/update_product"; }
创建RestUtils工具类。RestUtils.request(String url, Map<String,Object> params, HttpMethod httpMethod)方法调用。后面会说明params及url传递的方式
package com.study.utils; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.*; import org.springframework.util.MimeType; import org.springframework.util.MimeTypeUtils; import org.springframework.web.client.RestTemplate; import java.util.Map; import java.util.Set; public class RestUtils<T> { private RestTemplate restTemplate; public RestUtils() { super(); } public RestUtils(RestTemplate restTemplate) { super(); this.restTemplate = restTemplate; } public ServiceResponse<T> request(String url, Map<String, Object> params, HttpMethod httpMethod) { ServiceResponse<T> serviceResponse = new ServiceResponse<>(); try { HttpHeaders headers = new HttpHeaders(); MimeType mimeType = MimeTypeUtils.parseMimeType("application/json"); MediaType mediaType = new MediaType(mimeType.getType(), mimeType.getSubtype()); headers.setContentType(mediaType); HttpEntity<Object> entity = null; if (params == null) { entity = new HttpEntity<>(headers); } else { if (params.containsKey("data")) { entity = new HttpEntity<>(params.get("data"), headers); params.remove("data"); } else { entity = new HttpEntity<>(params, headers); } } ResponseEntity<T> responseEntity = null; if (params == null || params.isEmpty()) { responseEntity = restTemplate.exchange(url, httpMethod, entity, new ParameterizedTypeReference<T>() { }); } else { responseEntity = restTemplate.exchange(expandURL(url, params.keySet()), httpMethod, entity, new ParameterizedTypeReference<T>() { }, params); } serviceResponse.setResult(responseEntity.getBody()); } catch (Exception e) { e.printStackTrace(); serviceResponse.setCode(500); serviceResponse.setDescription(e.getMessage()); } return serviceResponse; } private String expandURL(String url, Set<?> keys) { StringBuffer sb = new StringBuffer(url); if (url.indexOf("?") > 0) { sb.append("&"); } else { sb.append("?"); } for (Object key : keys) { sb.append(key).append("=").append("{").append(key).append("}") .append("&"); } return sb.deleteCharAt(sb.length() - 1).toString(); } }
添加拦截器LoggingClientHttpRequestInterceptor,利用拦截器打印请求参数和返回状态
package com.study.common.interceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class LoggingClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
private static Logger log = LoggerFactory
.getLogger(LoggingClientHttpRequestInterceptor.class);
@Override
public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] body, ClientHttpRequestExecution execution) throws IOException {
traceRequest(httpRequest,body);
ClientHttpResponse response = execution.execute(httpRequest, body);
traceResponse(response);
return response;
}
private void traceRequest(HttpRequest request, byte[] body) {
try {
log.debug(
"Request URI:{}, Request Body:{}",
request.getURI(), new String(body, "UTF-8"));
// log.info("===========================request begin================================================");
// log.info("request URI : {}", request.getURI());
// log.info("request Method : {}", request.getMethod());
// log.info("request Headers : {}", request.getHeaders() );
// log.info("request Request body: {}", new String(body, "UTF-8"));
// log.info("==========================request end================================================");
} catch (Exception e) {
e.printStackTrace();
}
}
private void traceResponse(ClientHttpResponse response) throws IOException {
StringBuilder inputStringBuilder = new StringBuilder();
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getBody(), "UTF-8"))) {
String line = bufferedReader.readLine();
while (line != null) {
inputStringBuilder.append(line);
inputStringBuilder.append('\n');
line = bufferedReader.readLine();
}
}
log.debug("============================response begin==========================================");
log.debug("Status code : {}", response.getStatusCode());
log.debug("Status text : {}", response.getStatusText());
log.debug("Headers : {}", response.getHeaders());
log.debug("Response body: {}", inputStringBuilder.toString());//WARNING: comment out in production to improve performance
log.debug("=======================response end=================================================");
}
}
模拟请求的发送和接收响应
发送
package com.study.controller.rest; import com.study.common.Constants; import com.study.utils.JsonUtils; import com.study.utils.RestUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import java.util.HashMap; import java.util.Map; @RequestMapping("rest_request") @RestController public class RestRequestController { @Autowired private RestTemplate restTemplate; @RequestMapping("get_products") public void getProducts() { RestUtils<String> restUtils = new RestUtils<String>(restTemplate); String url = Constants.requestUrl + Constants.GET_PRODUCTS; Map<String, Object> params = new HashMap<>(); params.put("name", "test"); System.out.println(JsonUtils.toJson(restUtils.request(url, params, HttpMethod.GET))); } @RequestMapping("get_product_details") public void getProductDetails() { RestUtils<String> restUtils = new RestUtils<String>(restTemplate); String url = Constants.requestUrl + Constants.GET_PRODUCT_DETAILS; url = url.replaceAll("\\{code\\}", "123456"); System.out.println(JsonUtils.toJson(restUtils.request(url, null, HttpMethod.GET))); } @RequestMapping("update_product") public void updateProduct() { RestUtils<String> restUtils = new RestUtils<String>(restTemplate); String url = Constants.requestUrl + Constants.UPDATE_PRODUCTS; Map<String, Object> params = new HashMap<>(); Map<String, Object> data = new HashMap<>(); data.put("id", 3); data.put("code", "CC33"); params.put("data", data); System.out.println(JsonUtils.toJson(restUtils.request(url, params, HttpMethod.POST))); } }
接收
package com.study.controller.rest; import com.study.orm.Product; import com.study.utils.JsonUtils; import org.springframework.web.bind.annotation.*; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @RestController @RequestMapping("rest") public class RestResponseController { @RequestMapping(value = "get_products", method = RequestMethod.GET) public List<Product> getProducts(@RequestParam("name") String name) { System.out.println("name : " + name); List<Product> products = Arrays.asList( new Product(1L, "AA", 10.2D, "AA11"), new Product(2L, "BB", 115D, "BB22") ); return products; } @RequestMapping(value = "get_product_details/{code}", method = RequestMethod.GET) public Product getProductDetails(@PathVariable("code") String code) { System.out.println("code : " + code); return new Product(1L, "AA", 10.2D, "AA11"); } @RequestMapping(value = "update_product", method = RequestMethod.POST) public String updateProduct(@RequestBody Map<String, Object> requestMap) { System.out.println(JsonUtils.toJson(requestMap)); Map<String, Object> response = new HashMap<>(); response.put("message", "update success"); return JsonUtils.toJson(response); } }