软件测试|Spring boot 之 RestTemplate

简介: 软件测试|Spring boot 之 RestTemplate

传统情况下在java代码里访问restful服务,一般使用Apache的HttpClient。不过此种方法使用起来太过繁琐。Spring提供了一种简单便捷的模板类来进行操作,这就是RestTemplate。

内置发送get post delete等请求的方法,在SpringBoot中只要导入spring-boot-starter-web的依赖可以直接使用。

为什么说是简单便捷呢?我们来看以下两种实现方式:

/**
 * @param url
 * @param param
 * @param headers
 * @param connectTimeout  milliseconds
 * @param readTimeout  milliseconds
 * @return
 */
public static String get(String url, String param, Map<String, String> headers, int connectTimeout, int readTimeout) {
    BufferedReader in = null;
    StringBuilder builder = new StringBuilder();
    try {
        String urlNameString = url;
        if (param != null) {
            urlNameString += "?" + param;
        }
        URL realUrl = new URL(urlNameString);
        // 打开和URL之间的连接
        HttpURLConnection conn = (HttpURLConnection)realUrl.openConnection();
        // 设置通用的请求属性
        conn.setRequestProperty("accept", "*/*");
        conn.setRequestProperty("connection", "Keep-Alive");
        conn.setRequestProperty("user-agent", USER_AGENT);

        if (connectTimeout > 0) {
            conn.setConnectTimeout(connectTimeout);
        }
        if (readTimeout > 0) {
            conn.setReadTimeout(readTimeout);
        }
        if (headers != null) {
            for (Entry<String, String> entry: headers.entrySet()) {
                conn.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }
        conn.connect();
        if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                conn.getInputStream(), DEFAULT_CHARSET));
            String line;
            while ((line = in.readLine()) != null) {
                builder.append(line).append("\n");
            }
        }
    } catch (Exception e) {
        LOGGER.error("HttpUtil.get error.", e);
    }
    // 使用finally块来关闭输入流
    finally {
        try {
            if (in != null) {
                in.close();
            }
        } catch (Exception e2) {
            LOGGER.error("HttpUtil.get finally error.", e2);
        }
    }
    return builder.toString();
}
AI 代码解读
  1. 使用RestTempalte
String result = restTemplate.getForObject(url,String.class);
AI 代码解读

快速开始

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
AI 代码解读

第一步:配置RestTemplate

/**
 * RestTemplate配置
 */
@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
        return new RestTemplate(factory);
    }

    @Bean
    public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        //超时设置
        factory.setReadTimeout(6000);
        factory.setConnectTimeout(10000);
        return factory;
    }
}
AI 代码解读

第二步:使用RestTemplate的Api发送请求

/**
 * 测试get请求
 */
@Test
public void test1(){
    /**
     * getForObject
     *
     * 参数1 要请求的地址的url  必填项
     * 参数2 响应数据的类型 是String 还是 Map等 必填项
     * 参数3 请求携带参数 选填
     *
     * getForObject 方法的返回值就是 被调用接口响应的数据
     */
    String result = restTemplate.getForObject("http://apis.juhe.cn/mobile/get?phone=13429667914&key=1cca71876dc0669109ed3f9501a85e8a",String.class);
    System.out.println(result);
}
AI 代码解读

Get请求的API

getForObject API:参数1 url地址,参数2 响应数据类型 参数3 请求携带参数 返回值类型为String。

getForEntity API:参数1 url地址,参数2 响应数据类型 参数3 请求携带参数 返回值类型为ResponseEntity。

Get请求传递参数可以是以占位符的方式,或者是通过map传参。

/**
 * 测试get请求
 */
@Test
public void test2(){

    String result = restTemplate.getForObject("http://apis.juhe.cn/mobile/get?phone=13429667914&key=1cca71876dc0669109ed3f9501a85e8a", String.class);

    System.out.println("getForObject返回值:"+result);

    ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://apis.juhe.cn/mobile/get?phone=13429667914&key=1cca71876dc0669109ed3f9501a85e8a", String.class);

    System.out.println("通过ResponseEntity获取的响应状态码:"+responseEntity.getStatusCode());

    System.out.println("通过ResponseEntity获取的响应数据:"+responseEntity.getBody());

    /**
         * 通过Map传参
         */
    Map map= new HashMap();
    map.put("phone","13429667914");
    map.put("key","1cca71876dc0669109ed3f9501a85e8a");
    String resultId = restTemplate.getForObject("http://apis.juhe.cn/mobile/get?phone={phone}&key={key}",
                                                String.class,map);
    System.out.println("map传参" + resultId);

}
AI 代码解读

可以看到如下效果:

getForObject返回值:{"resultcode":"200","reason":"Return Successd!","result":{"province":"浙江","city":"杭州","areacode":"0571","zip":"310000","company":"移动","card":""},"error_code":0}
通过ResponseEntity获取的响应状态码:200 OK
通过ResponseEntity获取的响应数据:{"resultcode":"200","reason":"Return Successd!","result":{"province":"浙江","city":"杭州","areacode":"0571","zip":"310000","company":"移动","card":""},"error_code":0}
map传参{"resultcode":"200","reason":"Return Successd!","result":{"province":"浙江","city":"杭州","areacode":"0571","zip":"310000","company":"移动","card":""},"error_code":0}
AI 代码解读

Post请求的API

postForObject API:

参数1 url地址

参数2 通过LinkedMultiValueMap对象封装请求参数

参数3 响应数据类型返回值类型为String

postForLocation API:

参数1 url地址

参数2 通过LinkedMultiValueMap对象封装请求参数

响应值:获取返回的URI

postForLocation使用场景:在登录或注册完成,跳转到别的页面时,并获取要跳转的URI。

注意:postForLocation方法返回的URI实际上是指响应头的Location字段,所以,请求的接口的响应头必须要有Location字段(即请求的接口实际上是一个重定向的接口),否则返回值为null。

package com.example.restdemo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/test")
public class HelloController {
    /**
     * 测试 postForLocation
     */
    @PostMapping("/postLocation")
    public String testPostForLocation(String username,String password){
        System.out.println(username);
        return "redirect:/index.html";
    }
}
AI 代码解读

测试Post请求

/**
 * 测试Post请求
 */
@Test
public void test3(){
    LinkedMultiValueMap<String, String> request = new LinkedMultiValueMap<>();
    request.set("key","9363eb48d9bd745e7627322e2ae78099");
    request.set("date","2021-10-22");

    String result = restTemplate.postForObject("http://v.juhe.cn/laohuangli/d",request,String.class);
    System.out.println("通过LinkedMultiValueMap对象封装请求参数");
    System.out.println(result);

    Map map = new HashMap();
    map.put("key","9363eb48d9bd745e7627322e2ae78099");
    map.put("date","2021-10-22");

    String result2 = restTemplate.postForObject("http://v.juhe.cn/laohuangli/d?key={key}&date={date}",request,
            String.class,map);
    System.out.println("通过参数拼接的方式:");
    System.out.println(result2);

    LinkedMultiValueMap<String, String> req = new LinkedMultiValueMap<>();
    req.set("username","小明");
    req.set("password","decs3465523");
    URI uri = restTemplate.postForLocation("http://localhost:8085/test/postLocation", req);
    System.out.println("postForLocation请求到的地址为:"+uri);
}
AI 代码解读

执行效果如下:

通过LinkedMultiValueMap对象封装请求参数
{"reason":"successed","result":{"id":"4190","yangli":"2021-10-22","yinli":"辛丑(牛)年九月十七","wuxing":"杨柳木 收执位","chongsha":"冲牛(丁丑)煞西","baiji":"癸不词讼理弱敌强 未不服药毒气入肠","jishen":"天恩 母仓 四相 不将 玉宇","yi":"祭祀 作灶 纳财 捕捉 畋猎 馀事勿取","xiongshen":"河魁 月刑 五虚 朱雀 触水龙","ji":"动土 破土 开市 安葬"},"error_code":0}
通过参数拼接的方式:
{"reason":"successed","result":{"id":"4190","yangli":"2021-10-22","yinli":"辛丑(牛)年九月十七","wuxing":"杨柳木 收执位","chongsha":"冲牛(丁丑)煞西","baiji":"癸不词讼理弱敌强 未不服药毒气入肠","jishen":"天恩 母仓 四相 不将 玉宇","yi":"祭祀 作灶 纳财 捕捉 畋猎 馀事勿取","xiongshen":"河魁 月刑 五虚 朱雀 触水龙","ji":"动土 破土 开市 安葬"},"error_code":0}
postForLocation请求到的地址为:http://localhost:8085/index.html
AI 代码解读

总结

本文主要向大家介绍了 RestTemplate 这样一个 HTTP 请求工具类的常见用法,并没有涉及到源码,其实内部源码很多很深,包括和解析url模板,绑定参数的UriBuilderFactory UriTemplateHandler等等,建议跟踪源码跑一遍会更加理解restTemplate。这里就简单提下。

目录
打赏
0
0
0
0
142
分享
相关文章
必学!Spring Boot 单元测试、Mock 与 TestContainer 的高效使用技巧
【10月更文挑战第18天】 在现代软件开发中,单元测试是保证代码质量的重要手段。Spring Boot提供了强大的测试支持,使得编写和运行测试变得更加简单和高效。本文将深入探讨Spring Boot的单元测试、Mock技术以及TestContainer的高效使用技巧,帮助开发者提升测试效率和代码质量。
516 2
Spring Boot 两种部署到服务器的方式
本文介绍了Spring Boot项目的两种部署方式:jar包和war包。Jar包方式使用内置Tomcat,只需配置JDK 1.8及以上环境,通过`nohup java -jar`命令后台运行,并开放服务器端口即可访问。War包则需将项目打包后放入外部Tomcat的webapps目录,修改启动类继承`SpringBootServletInitializer`并调整pom.xml中的打包类型为war,最后启动Tomcat访问应用。两者各有优劣,jar包更简单便捷,而war包适合传统部署场景。需要注意的是,war包部署时,内置Tomcat的端口配置不会生效。
267 17
Spring Boot 两种部署到服务器的方式
【SpringBoot系列】初识Springboot并搭建测试环境
【SpringBoot系列】初识Springboot并搭建测试环境
110 0
基于SpringBoot+Vue实现的大学生体质测试管理系统设计与实现(系统源码+文档+数据库+部署)
面向大学生毕业选题、开题、任务书、程序设计开发、论文辅导提供一站式服务。主要服务:程序设计开发、代码修改、成品部署、支持定制、论文辅导,助力毕设!
41 2
Spring Boot 如何测试打包部署
本文介绍了 Spring Boot 项目的开发、调试、打包及投产上线的全流程。主要内容包括: 1. **单元测试**:通过添加 `spring-boot-starter-test` 包,使用 `@RunWith(SpringRunner.class)` 和 `@SpringBootTest` 注解进行测试类开发。 2. **集成测试**:支持热部署,通过添加 `spring-boot-devtools` 实现代码修改后自动重启。 3. **投产上线**:提供两种部署方案,一是打包成 jar 包直接运行,二是打包成 war 包部署到 Tomcat 服务器。
49 10
springboot之SpringBoot单元测试
本文介绍了Spring和Spring Boot项目的单元测试方法,包括使用`@RunWith(SpringJUnit4ClassRunner.class)`、`@WebAppConfiguration`等注解配置测试环境,利用`MockMvc`进行HTTP请求模拟测试,以及如何结合Spring Security进行安全相关的单元测试。Spring Boot中则推荐使用`@SpringBootTest`注解简化测试配置。
124 4
详解Swagger:Spring Boot中的API文档生成与测试工具
详解Swagger:Spring Boot中的API文档生成与测试工具
116 4
Spring运维之boot项目多环境(yaml 多文件 proerties)及分组管理与开发控制
通过以上措施,可以保证Spring Boot项目的配置管理在专业水准上,并且易于维护和管理,符合搜索引擎收录标准。
83 2
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
这篇文章是关于Apache Shiro权限管理框架的详细学习指南,涵盖了Shiro的基本概念、认证与授权流程,并通过Spring Boot测试模块演示了Shiro在单应用环境下的使用,包括与IniRealm、JdbcRealm的集成以及自定义Realm的实现。
80 3
shiro学习一:了解shiro,学习执行shiro的流程。使用springboot的测试模块学习shiro单应用(demo 6个)
|
4月前
|
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
140 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等