前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RestTemplate的应用

RestTemplate的应用

作者头像
砒霜拌辣椒
发布2023-08-23 17:24:41
1760
发布2023-08-23 17:24:41
举报
文章被收录于专栏:HerculesHercules

Spring提供了一种简单便捷的模板类 RestTemplate 来调用 RESTful 接口。它提供了多种便捷访问HTTP服务的方法,能够大大提高客户端的编写效率。

RestTemplate方法

HTTP方法

getForEntity

GET

getForObject

GET

postForEntity

POST

postForObject

POST

put

PUT

patch

PATCH

delete

DELETE

exchange

any

execute

any

1、RESTful API接口

代码语言:javascript
复制
@RestController
@Slf4j
public class RestfulController {
    @GetMapping(value = "/getUser1", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public User getUser1() {
        return new User(1L, "zhaoxb");
    }

    @GetMapping(value = "/getUser2", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public User getUser2(User user) {
        log.info("getUser2:{}", JSONUtil.toJsonPrettyStr(user));
        return user;
    }

    @PostMapping(value = "/postUser", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public User postUser(User user) {
        log.info("postUser:{}", JSONUtil.toJsonPrettyStr(user));
        return user;
    }
    
    @PostMapping(value = "/postBody", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public User postBody(@RequestBody User user) {
        log.info("postBody:{}", JSONUtil.toJsonPrettyStr(user));
        return user;
    }
}
  1. GET请求,不带参。
  2. GET请求,带参。
  3. POST请求,带参。
  4. POST请求,带有请求体。

实体类,需要提供有参和无参构造

代码语言:javascript
复制
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long id;
    private String name;
}

RestTemplate配置类

代码语言:javascript
复制
@Configuration
public class RestConfig {
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
        RestTemplate restTemplate = restTemplateBuilder
                .setConnectTimeout(Duration.ofMillis(5000L))
                .setReadTimeout(Duration.ofMillis(30000L))
                .build();
        return restTemplate;
    }
}

2、发送GET请求

2.1、getForEntity方法,不带参
代码语言:javascript
复制
@ActiveProfiles("test")
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class RestfulGetTests {
    @Autowired
    private RestTemplate restTemplate;

    @Test
    public void getForEntity1() {
        ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://127.0.0.1:31000/getUser1", String.class);
        log.info("响应码:{}", responseEntity.getStatusCodeValue());
        log.info("响应体:{}", JSONUtil.toJsonPrettyStr(responseEntity.getBody()));
    }
}
代码语言:javascript
复制
响应码:200
响应体:{
    "name": "zhaoxb",
    "id": 1
}
2.2、getForEntity方法,数字占位符方式传参
代码语言:javascript
复制
@Test
public void getForEntity2() {
    ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://127.0.0.1:31000/getUser2?id={1}&name={2}", String.class, 2, "zhaoxb");
    log.info("响应体:{}", JSONUtil.toJsonPrettyStr(responseEntity.getBody()));
}

用一个数字做占位符。最后是一个可变长度的参数,用来替换前面的占位符。

代码语言:javascript
复制
响应体:{
    "name": "zhaoxb",
    "id": 2
}
2.3、getForEntity方法,map占位符方式传参
代码语言:javascript
复制
@Test
public void getForEntity3() {
    Map<String, Object> map = new HashMap<>();
    map.put("id", 3);
    map.put("name", "zhaoxb");
    ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://127.0.0.1:31000/getUser2?id={id}&name={name}", String.class, map);
    log.info("响应体:{}", JSONUtil.toJsonPrettyStr(responseEntity.getBody()));
}

使用 name={name} 这种形式。最后一个参数是map,map的key为前边占位符的名字,value为实际参数值。

代码语言:javascript
复制
响应体:{
    "name": "zhaoxb",
    "id": 3
}
2.4、getForEntity方法,返回对象
代码语言:javascript
复制
@Test
public void getForEntity4() {
    ResponseEntity<User> responseEntity = restTemplate.getForEntity("http://127.0.0.1:31000/getUser1", User.class);
    log.info("响应体:{}", JSONUtil.toJsonPrettyStr(responseEntity.getBody()));
}
代码语言:javascript
复制
响应体:{
    "name": "zhaoxb",
    "id": 1
}
2.5、getForObject方法,直接返回对象
代码语言:javascript
复制
@Test
public void getForObject() {
    User User = restTemplate.getForObject("http://127.0.0.1:31000/getUser1", User.class);
    log.info("响应体:{}", JSONUtil.toJsonPrettyStr(User));
}

getForObject是对getForEntity函数的进一步封装,只关注返回消息的实体内容。

代码语言:javascript
复制
响应体:{
    "name": "zhaoxb",
    "id": 1
}

3、发送POST请求

用post方法发送带参的请求时,Map不能被定义为 HashMapLinkedHashMap,而应被定义为 LinkedMultiValueMap,这样参数才能成功传递到后台。

3.1、postForEntity方法
代码语言:javascript
复制
@Test
public void postForEntity() {
    MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
    multiValueMap.add("id", 5);
    multiValueMap.add("name", "zhaoxb");
    ResponseEntity<User> responseEntity = restTemplate.postForEntity("http://127.0.0.1:31000/postUser", multiValueMap, User.class);
    log.info("响应码:{}", responseEntity.getStatusCodeValue());
    log.info("响应体:{}", JSONUtil.toJsonPrettyStr(responseEntity.getBody()));
}
代码语言:javascript
复制
响应体:{
    "name": "zhaoxb",
    "id": 5
}
3.2、postForObject方法
代码语言:javascript
复制
@Test
public void postForObject() {
    MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
    multiValueMap.add("id", 6);
    multiValueMap.add("name", "zhaoxb");
    User user = restTemplate.postForObject("http://127.0.0.1:31000/postUser", multiValueMap, User.class);
    log.info("响应体:{}", JSONUtil.toJsonPrettyStr(user));
}

getForObject 相对应,只关注返回的消息体。

代码语言:javascript
复制
响应体:{
    "name": "zhaoxb",
    "id": 6
}
3.3、postForObject方法,带有请求体body
代码语言:javascript
复制
@Test
public void postForObject2() {
    User reqUser = new User(10L, "zhaoxb");
    User user = restTemplate.postForObject("http://127.0.0.1:31000/postBody", reqUser, User.class);
    log.info("响应体:{}", JSONUtil.toJsonPrettyStr(user));
}

RestTemplate底层实现序列化和反序列化。

代码语言:javascript
复制
响应体:{
    "name": "zhaoxb",
    "id": 10
}
3.4、exchange方法
代码语言:javascript
复制
@Test
public void exchange() {
    MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
    multiValueMap.add("id", 7);
    multiValueMap.add("name", "zhaoxb");
    HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(multiValueMap);
//      HttpEntity<MultiValueMap<String, Object>> httpEntityWithHeaders = new HttpEntity<>(multiValueMap, new HttpHeaders());
    ResponseEntity<User> responseEntity = restTemplate.exchange("http://127.0.0.1:31000/postUser", HttpMethod.POST, httpEntity, User.class);
    log.info("响应体:{}", JSONUtil.toJsonPrettyStr(responseEntity.getBody()));
}

HttpEntity还支持带有HTTP请求头的构造方法。

代码语言:javascript
复制
响应体:{
    "name": "zhaoxb",
    "id": 7
}

RestTemplate发送PUTPATCHDELETE方法与GETPOST方法非常类似,这里不做展开。

4、自定义template

4.1、自定义HTTP源

ClientHttpRequestFactory是Spring定义的一个接口,用于生产ClientHttpRequest对象,RestTemplate只是模板类,抽象了很多调用方法,而底层真正使用何种框架发送HTTP请求是通过ClientHttpRequestFactory指定的。

RestTemplate默认使用的是SimpleClientHttpRequestFactory,其内部使用的是JDK的java.net.HttpURLConnection创建底层连接,默认是没有连接池的。可以通过 setRequestFactory 函数设置不同的HTTP源,比如 Apache HttpComponentsNettyOkHttp

设置Apache HttpComponents为HTTP客户端源

代码语言:javascript
复制
<dependencies>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
    </dependency>
</dependencies>
代码语言:javascript
复制
@Configuration
public class RestConfig {
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
        RestTemplate restTemplate = restTemplateBuilder
                .setConnectTimeout(Duration.ofMillis(5000L))
                .setReadTimeout(Duration.ofMillis(30000L))
                .requestFactory(() -> clientHttpRequestFactory())
                .build();
        return restTemplate;
    }

    @Bean
    public ClientHttpRequestFactory clientHttpRequestFactory() {
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();

        //开始设置连接池
        PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();
        poolingHttpClientConnectionManager.setMaxTotal(100);  //最大连接数
        poolingHttpClientConnectionManager.setDefaultMaxPerRoute(20);  //同路由并发数
        httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);

        HttpClient httpClient = httpClientBuilder.build();
        // httpClient连接配置
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
        // 设置超时,如果 RestTemplateBuilder 已经设置,这里就不需要设置
//        clientHttpRequestFactory.setConnectTimeout(5 * 1000); // 连接超时
//        clientHttpRequestFactory.setReadTimeout(30 * 1000); // 数据读取超时时间
        clientHttpRequestFactory.setConnectionRequestTimeout(30 * 1000); //连接不够用的等待时间
        return clientHttpRequestFactory;
    }
}
4.2、自定义messageConverter

RestTemplate默认使用 jackson 来实现序列化和反序列化,默认情况下会注册MIME类型的转换器,但可以通过 setMessageConverters 函数指定其他类型的转化器。

这里其实也可以用FastJson库的FastJsonHttpMessageConverter4类来做转换器,只是近些年FastJson屡爆漏洞,还是建议用默认的jackson来实现。

参考链接

代码地址

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-10-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、RESTful API接口
  • 2、发送GET请求
    • 2.1、getForEntity方法,不带参
      • 2.2、getForEntity方法,数字占位符方式传参
        • 2.3、getForEntity方法,map占位符方式传参
          • 2.4、getForEntity方法,返回对象
            • 2.5、getForObject方法,直接返回对象
            • 3、发送POST请求
              • 3.1、postForEntity方法
                • 3.2、postForObject方法
                  • 3.3、postForObject方法,带有请求体body
                    • 3.4、exchange方法
                    • 4、自定义template
                      • 4.1、自定义HTTP源
                        • 4.2、自定义messageConverter
                        • 参考链接
                        • 代码地址
                        相关产品与服务
                        Serverless HTTP 服务
                        Serverless HTTP 服务基于腾讯云 API 网关 和 Web Cloud Function(以下简称“Web Function”)建站云函数(云函数的一种类型)的产品能力,可以支持各种类型的 HTTP 服务开发,实现了 Serverless 与 Web 服务最优雅的结合。用户可以快速构建 Web 原生框架,把本地的 Express、Koa、Nextjs、Nuxtjs 等框架项目快速迁移到云端,同时也支持 Wordpress、Discuz Q 等现有应用模版一键快速创建。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档