RestTemple
是Spring提供的用于访问Http请求的客户端HttpClient
HttpURLConnection
【1】RestTemplate是Spring提供的进行远程调用客户端的工具
【2】调用RestTemplate的默认构造函数时,底层通过使用java.net包下实现创建HTTP请求访问
【3】RestTemplate创建需要ClientHttpRequestFactory
,主要是如下三种(底层执行引擎)
SimpleClientHttpRequestFactory
默认实现,使用J2SE提供的方式创建底层的Http请求连接
RestTemplate restTemplate = new RestTemplate();HttpComponentsClientHttpRequestFactory
底层使用HttpClient请求http服务
RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory());OkHttp3ClientHttpRequestFactory
底层使用OkHttp访问远程的Http服务
RestTemplate默认使用HttpMessageConverter进行住消息转换;
调用restful接口数据传递格式为json,返回数据格式也是json字符串,然而restTemplate.postForObject方法的请求参数和返回参数都是java类,是由于RestTemplate通过HttpMessageConverter自动进行转换
在创建RestTemplate的时候会默认添加一组HttpMessageConveter的实现。
【HttpMessageConveter源码】
public interface HttpMessageConverter<T> {
//指示此转换器是否可以读取给定的类。
boolean canRead(Class<?> clazz, @Nullable MediaType mediaType);
//指示此转换器是否可以写给定的类。
boolean canWrite(Class<?> clazz, @Nullable MediaType mediaType);
//返回List
List<MediaType> getSupportedMediaTypes();
//读取一个inputMessage
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
//往output message写一个Object
void write(T t, @Nullable MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException;
}
StringHttpMessageConverter
来处理text/plain;MappingJackson2HttpMessageConverter
来处理application/json;MappingJackson2XmlHttpMessageConverter
来处理application/xml RestTemplate restTemplate = new RestTemplate();
//获取RestTemplate默认配置好的所有转换器
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
//默认的MappingJackson2HttpMessageConverter在第7个 先把它移除掉
messageConverters.remove(6);
//添加上GSON的转换器,下标从0开始
messageConverters.add(6, new GsonHttpMessageConverter());
@RestController
public class TestController
{
@RequestMapping(value = "testPost", method = RequestMethod.POST)
public ResponseBean testPost(@RequestBody RequestBean requestBean)
{
ResponseBean responseBean = new ResponseBean();
responseBean.setRetCode("0000");
responseBean.setRetMsg("succ");
return responseBean;
}
}
使用RestTemplate访问该服务
//请求地址
String url = "http://localhost:8080/testPost";
//入参
RequestBean requestBean = new RequestBean();
requestBean.setTest1("1");
requestBean.setTest2("2");
requestBean.setTest3("3");
RestTemplate restTemplate = new RestTemplate();
ResponseBean responseBean = restTemplate.postForObject(url, requestBean, ResponseBean.class);
RestTemplate有两个核心方法执行Get请求
1)RestTemplate.getForObject()
可以获取对象
2)RestTemplate.getForEntity()
可以获取对象,获取http状态码、请求头等
@Configuration
public class RestConfig {
@Bean
public RestTemplate restTemplate(){
// 默认底层执行HttpurlConnection
return new RestTemplate();
}
}
【RestTemplate.getForObject()样例程序】
@Autowired
private RestTemplate restTemplate;
@GetMapping("/getForObject")
public Object getForObject(){
String url = "http://localhost:8080/addUser/100/mimimi";
Map<String, Integer> map = new HashMap<>();
UserDTO result = restTemplate.getForObject(url, UserDTO.class,map);
return result; //{"id":100,"name":"mimimi"}
}
Post请求包括两个核心方法:
1)RestTemplate.postForObject()
2)RestTemplate.postForEntity()
Post方法方法传参Map必须是MutiValueMap
;MutiValueMap支持基本类型分开传参,也支持实体传参
// post请求:基本类型/实体传参
@GetMapping("/postForObject")
public UserDTO postForObject(){
String url= "http://localhost:8080/addUser1";
MultiValueMap<String,Object> map = new LinkedMultiValueMap<>();
map.add("id",12);
map.add("name","小黑");
// 返回UserDTO对象
UserDTO userDTO = restTemplate.postForObject(url,map, UserDTO.class);
return userDTO; //{"id":12,"name":"小黑"}
}
// post请求:postForEntity
@GetMapping("/postForEntity1")
public UserDTO postForEntity1(){
String url="http://localhost:8080/addUser1";
// 提交参数:使用 map 装载参数
MultiValueMap<String,Object> map = new LinkedMultiValueMap<>();
map.add("id",1000);
map.add("name","hello restTemplate");
//发送post请求
ResponseEntity<UserDTO> userDTOResponseEntity= restTemplate.postForEntity(url,map, UserDTO.class);
// postForEntity可以获取响应码、响应对象、响应头等
HttpStatus status = userDTOResponseEntity.getStatusCode();
int code = userDTOResponseEntity.getStatusCodeValue();
HttpHeaders headers = userDTOResponseEntity.getHeaders();
log.info("http响应码:{},响应状态码:{},headers信息:{}",status,code,headers);
return userDTOResponseEntity.getBody();//{"id":1000,"name":"hello restTemplate"}
}
postForEntity()和getForObject()唯一的区别是:返回的时候使用ResponseEntity<>
2.1 restTemplate.exchange()方法:
参数说明:url: 请求地址
method:请求类型( POST 、GET等)
requestEntity: 请求实体,封装请求头,请求内容
responseType: 请求响应对象的类型
uriVariables: url中的@PathVariable参数,可变长度参数列表
// exchange
@GetMapping("/exchange")
public UserDTO exchange(){
String url = "";
// 传参使用MultiValueMap
MultiValueMap<String,Object> map = new LinkedMultiValueMap<>();
map.add("id",10);
map.add("name","xixixi");
// 请求使用HttpEntity,包装map
HttpEntity<MultiValueMap> requestEntity = new HttpEntity<>(map);
// 返回使用ResponseEntity
ResponseEntity<UserDTO> response = restTemplate.exchange(url, HttpMethod.POST,requestEntity, UserDTO.class);
return response.getBody();
}
对于一个请求来说,超期时间,请求连接时间等都是必不可少的参数,为了更好的适应业务需求,所以可以自己修改restTemplate的配置
restTemplate简书
//生成一个设置了连接超时时间、请求超时时间、异常最大重试次数的httpClient
RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(10000).setConnectTimeout(10000).setSocketTimeout(30000).build();
HttpClientBuilder builder = HttpClientBuilder.create().setDefaultRequestConfig(config).setRetryHandler(new DefaultHttpRequestRetryHandler(5, false));
HttpClient httpClient = builder.build();
//使用httpClient创建一个ClientHttpRequestFactory的实现
ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
//ClientHttpRequestFactory作为参数构造一个使用作为底层的RestTemplate
RestTemplate restTemplate = new RestTemplate(requestFactory);