ITPub博客

首页 > 数据库 > 数据库开发技术 > 扩展RestTemplate,支持Get请求传JavaBean参数

扩展RestTemplate,支持Get请求传JavaBean参数

原创 数据库开发技术 作者:服务端技术栈 时间:2021-05-22 17:35:56 0 删除 编辑

一、问题背景

项目中使用了RestTemplate来对第三方接口进行请求。 但是使用get方式请求查询接口时,需要将参数拼接到url中,不支持使用JavaBean传参,编写代码不友好。

RestTemplate是一种客户端执行HTTP请求的工具类,封装了基础HTTP客户端库,并提供了简单的模板方法API,帮助程序员方便的发起http请求。


二、实际开发中的做法

在开发中,使用RestTemplate发起Get请求时,通常需要这么写: 

上面这种写法是可以正常传参数到服务端的,如果不使用占位符的写法,服务端将收不到参数。 下面这样写就不可以正常传参数了。

服务端接口定义如下,请求结果是参数解析失败,返回400错误码 。

这个时候就想,能不能直接传map,或者一个JavaBean来实现传参数呢?于是查看RestTemplate源码,发现RestTemplate有扩展点可以进行扩展。



三、RestTemplate扩展接口说明

扩展接口
说明
ResponseErrorHandler
用于确定特定响应是否有错误的策略接口
ClientHttpRequestInterceptor
拦截客户端HTTP请求,支持设置多个
HttpMessageConverter
策略接口,指定可以在HTTP请求和响应之间进行转换的转换器
ClientHttpRequestFactory
这个是对通信定制接口,支持okhttp,httpcompoent,netty等
UriTemplateHandler
定义用于使用变量扩展URI模板的方法。

上面5个扩展接口中,UriTemplateHandler是本文采用的,通过参数对uri进行重构,自动拼接参数到url中。


四、扩展实践 

查看RestTemplate的UriTemplateHandler扩展接口,它只有两个方法,专门处理请求url的。

public interface UriTemplateHandler {  //这个方法参数uriTemplate是我们请求的地址,map就是我们传入的参数map  URI expand(String uriTemplate, Map<String, ?> uriVariables);
  URI expand(String uriTemplate, Object... uriVariables);}


于是自定义一个UriTemplateHandler,来对请求url进行处理。

代码如下: 

public class GetUriTemplateHandler implements UriTemplateHandler {    //组合默认的uri处理器    private UriTemplateHandler uriTemplateHandler = new DefaultUriBuilderFactory();
@Override public URI expand(String uriTemplate, Map<String, ?> uriVariables) {
//利用UriComponentsBuilder将请求参数追加到url,GetParamMultiValueMap是自定义的一个map uriTemplate = UriComponentsBuilder .fromHttpUrl(uriTemplate) .queryParams(new GetParamMultiValueMap(uriVariables)).toUriString(); log.info("处理之后的url ==> {}", uriTemplate); return uriTemplateHandler.expand(uriTemplate, uriVariables); }
@Override public URI expand(String uriTemplate, Object... uriVariables) { return uriTemplateHandler.expand(uriTemplate, uriVariables); }}

GetParamMultiValueMap实现如下: 

public class GetParamMultiValueMap<K,V> implements MultiValueMap<K, V> {
private final Map<K, List<V>> map;
public GetParamMultiValueMap(Map<K, V> paramMap) { Assert.notNull(paramMap, "'map' must not be null"); //将请求参数转换成MultiValueMap this.map = new HashMap<>(); paramMap.forEach((k, v) -> { if (v instanceof List) { map.put(k, (List<V>) v); } else { map.put(k, Lists.newArrayList(v)); } }); }}  // 此处省略其他map操作方法.....


GetUriTemplateHandler实现好之后,只需要在RestTemplate实例化之后将默认的UriTemplateHandler替换就可以使用自己实现的功能了 

@Configurationpublic class RestTemplateConfig {
@ConditionalOnClass(value = RestTemplate.class) @Bean public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate(); //默认使用的jdk的http请求组件 替换成okhttp3 restTemplate.setRequestFactory(new OkHttp3ClientHttpRequestFactory()); //使用自定义的uri处理器,实现参数追加到url的功能 restTemplate.setUriTemplateHandler(new GetUriTemplateHandler()); return restTemplate; }}

下面再看测试结果: 

从测试结果看,自定义的uri处理器已经将参数拼接好了。并且收到了服务端的正确返回。 

五、再次扩展

上面已经实现将map参数拼接到url参数了,现在还是传递的map,能不能直接传一个JavaBean呢?

答案是可以的,通过对RestTemplate进行包装,借助apache-commont包将JavaBean转换成map,代码如下:

将增强的的RestTemplate注入到Spring容器中:

@Beanpublic RestTemplateWrapper restTemplateWrapper(RestTemplate restTemplate) {return new RestTemplateWrapper(restTemplate);}

测试是否可以通过bean传递参数成功。

从结果看,参数可以拼接到url,并且可以成功接收服务的响应 。

ok receive message ===> test


上面内容就是基于RestTemplate对Get请求参数扩展的处理了,如果有更多的实践方案欢迎一起探讨。



原文作者:服务端技术栈;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2019-03-08

  • 博文量
    97
  • 访问量
    41431