RestTemplate 配置,拦截器配置的一些参数,和测试

12 篇文章 0 订阅

提出问题:怎样配置 RestTemplate的参数比较好呢?RestTemplate 有哪些冷门的用法与知识呢? 怎么不启动项目,直接在测试类中 测试 RestTemplate 呢?

解决效果:

0) 2个参数 ClientHttpRequestFactory 和 拦截器 可以配置

1) 支持多次调用  response body的流信息。( 默认 response 只能调用1次getBody() )

2) 记录请求日志,使用 拦截器 ClientHttpRequestInterceptor 

3) 更改 request 和response的 header 等信息,也可在拦截器内统一实现 

4) 支持异步操作(暂无)

5) 设置超时时间,否则可能会因为网络不稳定而失败而没有明显的通知信息。设置了超时后,会自动 抛出异常,并且被代码拦截后就可以很快知道了。

/**
 * @author storm
 * @date 2020-11-19  14:31
 */
@Slf4j
@Configuration
public class RestClientConfig {

    // 多个 拦截器,注册为Bean,方便后期 调用该方法 返回同一个单例Bean
    @Bean
    public List<ClientHttpRequestInterceptor> restInterceptor() {
        List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();

        // 作用:更改 request的 header 和uri 等信息,更改response的header等信息
        ClientHttpRequestInterceptor header = new ClientHttpRequestInterceptor() {
            @Override
            public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
                ClientHttpResponse response = execution.execute(request, body);
                response.getHeaders().add("Foo", "bar");
                return response;
            }
        };

        // log日志,记录请求时耗时和参数信息
        ClientHttpRequestInterceptor timer = new ClientHttpRequestInterceptor() {
            @Override
            public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
                StopWatch watch = new StopWatch();
                watch.start();

                ClientHttpResponse response = execution.execute(request, body);
                watch.stop();

                String time = String.valueOf(watch.getTime(TimeUnit.MILLISECONDS));
                response.getHeaders().add("cost-milliseconds", time);

                log.info("发送rest请求耗时 :{} ms,{} {} headers:{}", time, request.getMethod(), request.getURI(), request.getHeaders());
                return response;
            }
        };

        interceptors.add(timer);
        interceptors.add(header);

        return interceptors;
    }

    /**
     * 支持多次使用 response.getBody() 读取流, 参考 https://www.baeldung.com/spring-rest-template-interceptor
     */
    @Bean
    public RestTemplate restTemplate() {
        HttpComponentsClientHttpRequestFactory rqstFactory = new HttpComponentsClientHttpRequestFactory();
        rqstFactory.setConnectionRequestTimeout(1*1000); // 从pool池中获取可用连接的时间,1 s
        rqstFactory.setConnectTimeout(10*1000); // 与远程服务器建立一个新连接所需要的时间, 10 s
        rqstFactory.setReadTimeout(30*1000); // 数据包开始传输之前的等待时间, 30 s

        RestTemplate template = new RestTemplate(
                // 多次使用 getBody() response body
                new BufferingClientHttpRequestFactory(rqstFactory));

        List<ClientHttpRequestInterceptor> interceptors = template.getInterceptors();
        if (CollectionUtils.isEmpty(template.getInterceptors())) {
            interceptors = restInterceptor();
        } else {
            interceptors.addAll(restInterceptor());  // 无论调用几次该方法,总是获取的是容器中的相同的一个 单例Bean。这也是为什么 restInterceptor() 必须使用 @Bean 注解 
        }

        template.setInterceptors(interceptors);
        return template;
    }

}

测试

不启动项目,直接测试 ,方式有3: 1) main 方法 内各种 new 对象之后 调用 ;2)  @RunWith  + @Autowired 注入Bean对象调用;3)  不使用 @RunWith  + @Autowired 也能调用

1) 掠过

2) @RunWith  + @Autowired 注入Bean对象调用 

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.http.*;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.client.RestTemplate;

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

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

@RunWith(SpringJUnit4ClassRunner.class)  // 在该类中运行测试,提供一些 spring 的某些特性支持
@ContextConfiguration(classes = RestClientConfig.class) // 利用SpringJUnit4ClassRunner 特性注入 Bean
public class RestTemplateConfigTest {
 
    @Autowired  //利用SpringJUnit4ClassRunner特性,直接使用 @Autowired 注入 
    RestTemplate restTemplate;
 
    @Test
    public void test01() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);  // 指定传输参数的格式为 json
        HttpEntity<Object> request = new HttpEntity<Object>(null, headers);

        ResponseEntity<String> responseEntity = restTemplate.postForEntity("http://httpbin.org/post", request, String.class);
        assertThat(responseEntity.getHeaders()
                .get("Foo")
                .get(0), is(equalTo("bar")));

        System.out.println("大多时候,成功的解决了提出问题的人,就以为万事大吉。典型的 国产思维。这可不好呀,都是自己人。");
    }
}
 

3) 不使用 @RunWith  + @Autowired

public class RestTemplateConfigTest {
 
    @Test
    public void test02() {
        ApplicationContext context = new AnnotationConfigApplicationContext(RestClientConfig.class);
        RestTemplate restTemplate = context.getBean(RestTemplate.class);
        String object = restTemplate.getForObject("https://不要解决提出问题的人.ok?param=yes", String.class);
    }
}

 

补充几句:

RestTemplate 更多案例 

@Runwith 的 作用 如下所示,更多 使用例子参考 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值