RestTemplate使用

本文详细介绍了Spring框架中的RestTemplate组件,包括其初始化配置、使用方法及如何处理中文乱码等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概述

RestTemplate是spring内置的http请求封装,它提供一套接口,实际用Java常用http连接库来实现这套接口,java常用的实现http请求实现库有以下三种:

  • JDK 自带的 HttpURLConnection
  • Apache 的 HttpClient
  • OKHttp3

在使用spring的情况下,http请求直接使用RestTemplate是不错的选择。

Rest服务端

使用RestTemplate发起http请求的时候,Rest服务提供者没有什么特殊要求,直接按照传统的SpringMVC的Controller层实现方式实现即可。

举例:

@RestController
@RequestMapping("/user")
public class UserController {

  private Logger logger = LoggerFactory.getLogger(UserController.class);

   @PostMapping("/add")
    public UserBean add(UserBean userBean) {
        logger.info("request param:{}", JSON.toJSON(userBean));
        return userBean;
    }

    @GetMapping("/{id}")
    public UserBean getUser(@PathVariable("id") Long userId, @RequestHeader("token") String token) {
        logger.info("get user id={},token={}", userId, token);
        UserBean userBean = new UserBean();
        userBean.setAge(33);
        userBean.setId(userId);
        userBean.setName("张山");
        return userBean;
    }
}

Rest客户端

使用RestTemplate前先得做一些初始化处理,比如指定http客户端工厂类、设置超时时间、响应参数转换器等。

初始化RestTemplate
@Configuration
@ConditionalOnClass(value = {RestTemplate.class, HttpClient.class})
public class RestTemplateConfiguration {

  @Value("${remote.maxTotalConnect:0}")
  private int maxTotalConnect; //连接池的最大连接数默认为0
  @Value("${remote.maxConnectPerRoute:200}")
  private int maxConnectPerRoute; //单个主机的最大连接数
  @Value("${remote.connectTimeout:2000}")
  private int connectTimeout; //连接超时默认2s
  @Value("${remote.readTimeout:30000}")
  private int readTimeout; //读取超时默认30s

  //创建HTTP客户端工厂
  private ClientHttpRequestFactory createFactory() {
    if (this.maxTotalConnect <= 0) {
      SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
      factory.setConnectTimeout(this.connectTimeout);
      factory.setReadTimeout(this.readTimeout);
      return factory;
    }
    HttpClient httpClient = HttpClientBuilder.create().setMaxConnTotal(this.maxTotalConnect)
        .setMaxConnPerRoute(this.maxConnectPerRoute).build();
    HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(
        httpClient);
    factory.setConnectTimeout(this.connectTimeout);
    factory.setReadTimeout(this.readTimeout);
    return factory;
  }

  //初始化RestTemplate,并加入spring的Bean工厂,由spring统一管理
  @Bean
  @ConditionalOnMissingBean(RestTemplate.class)
  public RestTemplate getRestTemplate() {
    RestTemplate restTemplate = new RestTemplate(this.createFactory());
    List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();

    //重新设置StringHttpMessageConverter字符集为UTF-8,解决中文乱码问题
    HttpMessageConverter<?> converterTarget = null;
    for (HttpMessageConverter<?> item : converterList) {
      if (StringHttpMessageConverter.class == item.getClass()) {
        converterTarget = item;
        break;
      }
    }
    if (null != converterTarget) {
      converterList.remove(converterTarget);
    }
    converterList.add(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));

    //加入FastJson转换器
    converterList.add(new FastJsonHttpMessageConverter4());
    return restTemplate;
  }

}

StringHttpMessageConverter默认使用的字符集是ISO-8859-1,在遇到中文的时候会有乱码,所以需要移除RestTemplate默认的StringHttpMessageConverter修改字符字符集后重新设置。

spring的json转换器默认使用的是Jackson,json字符串和对应的Entity如果有字段对不上就会报错,这个有点不符合国情,而FastJson则不会报错,所以很多时候都会用FastJSON替换默认的Jackson。

FastJSON替换Jackson配置
@Configuration
public class FastjsonConfiguration {


  @Bean
  public HttpMessageConverters fastjsonConverter() {
    FastJsonConfig fastJsonConfig = new FastJsonConfig();
    //自定义格式化输出
    fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat,
        SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.WriteNullNumberAsZero);

    FastJsonHttpMessageConverter4 fastjson = new FastJsonHttpMessageConverter4();
    fastjson.setFastJsonConfig(fastJsonConfig);
    return new HttpMessageConverters(fastjson);
  }

}

RestTemplate使用举例

POST请求
  • MultiValueMap传参
  @Test
  public void multiValueMapParam() {
    MultiValueMap<String, String> requestParam = new LinkedMultiValueMap<>();
    requestParam.set("name", "张三");
    UserBean result = restTemplate
        .postForObject("http://127.0.0.1:8280/user/add", requestParam, UserBean.class);
    logger.info("result:{}", JSON.toJSON(result));
  }
  • Entity传参
  @Test
  public void restClient() {
    UserBean userBean = new UserBean();
    userBean.setName("王五");
    String result = restTemplate
        .postForObject("http://127.0.0.1:8280/user/add", userBean, String.class);
    logger.info("result:{}", result);
  }

以Entity传参,接收端Controller以Entity接收参数的时候需加上@RequestBody注解,否则接收不到参数。

@PostMapping("/add")
public UserBean add(@RequestBody UserBean userBean) {
    logger.info("request param:{}", JSON.toJSON(userBean));
    return userBean;
}
GET请求
 /**
  * 普通 GET请求,请求参数在路径中
  */
 @Test
 public void getUser() {
     long userId = 32L;
     UserBean result = restTemplate.getForObject(
             "http://127.0.0.1:8280/user/{id}",
             UserBean.class,
             userId);
     logger.info("result={}", JSON.toJSONString(result));
 }
带header的GET请求

实际项目中远程接口调用很多时候是需要授权访问的,授权信息通常设置在http请求头里面,RestTemplate封装的get请求方法里面没有设置header的地方,那么我们是否对这种需要有header的get请求就不能使用RestTemplate了呢,当然不是。

那几个get请求封装方法重载程度较高,要往请求里面加请求头不容易,那我们就用里面的exchange方法,这个方法的封装程度是不高的,里面直接设置请求方式,并可以设置请求头。

    /**
     * 带header的GET请求
     */
    @Test
    public void getHasHeader() {
        long userId = 32L;
        HttpHeaders headers = new HttpHeaders();
        headers.add("token", "123");
        ResponseEntity<UserBean> response = restTemplate.exchange(
                "http://127.0.0.1:8280/user/{id}",
                HttpMethod.GET,
                new HttpEntity<String>(headers),
                UserBean.class,
                userId);
        logger.info("response={}", JSON.toJSONString(response.getBody()));
    }

打印远程访问日志

添加依赖

<dependency>
    <groupId>org.hobsoft.spring</groupId>
    <artifactId>spring-rest-template-logger</artifactId>
    <version>2.0.0</version>
</dependency>

配置

RestTemplate restTemplate = new RestTemplateBuilder()
    .customizers(new LoggingCustomizer())
    .build()

设置日志级别=debug

logging.level.org.hobsoft.spring.resttemplatelogger.LoggingCustomizer=debug

原文地址:http://www.itclj.com/blog/5925894681c06e672f942ad6

demo地址:https://github.com/clj198606061111/spring-boot-rest-template-demo

打印远程访问日志:https://stackoverflow.com/questions/7952154/spring-resttemplate-how-to-enable-full-debugging-logging-of-requests-responses

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值