概述
RestTemplate一款好用且强大的Http请求工具
上一篇,我介绍了使用CMD窗口的CURL命令之后,我就觉得CURL虽然好用,但是许多功能不能完全满足我们日常的接口测试工作
,比如他的中文处理不是很好,就单单这一点就让我很是头痛。
所以,我这次就来了解一下Http请求工具。
文章目录
- RestTemplate一款好用且强大的Http请求工具
- 前言
- RestTemplate
- 1.1 如何使用
- 1.1.1 配置restTemplate的配置类
- 1.2 常用方法
- 1.2.1 GET请求模板方法
- ① getForObject方法
- ② getForEntity方法
- 1.2.2 POST请求模板方法
- ① postForObject方法:fire:
- RestTemplate的传参
- @RequestBody传参
- ② postForEntity方法:fire:
- 1.2.3 Exchange方法
- restTemplate Exchange
前言
首先,我们在这之前,先了解下我们常见的Http请求状态码有哪些,也算是回顾了。
下面是常见的 HTTP 状态码:
- 200 - 请求成功
- 301 - 资源(网页等)被永久转移到其它URL
- 404 - 请求的资源(网页等)不存在
- 500 - 内部服务器错误
那么,有没有小伙伴会产生一个疑问呢?这些状态码是否有规律呢,答案:是的,可以总结出一些规律也方便我们记忆和总结。那么我们可以将Http状态码可以分为
分类 | 分类描述 |
---|---|
1** | 信息,服务器收到请求,需要请求者继续执行操作 |
2** | 成功,操作被成功接收并处理 |
3** | 重定向,需要进一步的操作以完成请求 |
4** | 客户端错误,请求包含语法错误或无法完成请求 |
5** | 服务器错误,服务器在处理请求的过程中发生了错误 |
回顾完毕之后,我们就需要正式的认识一下什么是Http请求工具了
RestTemplate
常见的Http客户端请求工具有哪些?
- JDK httpURI Connection
Apache httpClient 使用率也很高
OkHttp 市面使用率十分高
RestTemplate是一个同步的Web HTTP客户端请求模板,是Spring对HTTP URI Connection的封装
官方文档参考地址:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html
RestTemplate默认使用的是HttpUrlConnection ,可以通过构造方法替换默认的HttpClient,常见的执行引擎包含:
- Apache HttpComponenets(httpClient)
- Netty
- OkHttp
RestTempalte template = new RestTemplate();// 默认是HttpUrlConnection
// 想要切换为别的 比如说是Apache的请求库
RestTemplate template = new RestTempalte(new HttpcComponentsClientHttpRequestFactory());
1.1 如何使用
1.1.1 配置restTemplate的配置类
/**
* Bean注入配置声明RestTemplate模板
* @author wangruoxian
*
*/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
在项目中如果要使用RestTemplate的话,我们只需要写一个RestTemplate的配置类,然后在需要使用的类上通过@AutoWired注解注入即可使用。
所以,我们需要在使用上述的方法之前,一定要先写这个配置类
1.2 常用方法
1.2.1 GET请求模板方法
Modifier and Type | Method and Description | 描述 |
---|---|---|
ResponseEntity | getForEntity(String url, Class responseType, Map<String,?> uriVariables) | 通过Get方式发送一个请求 |
ResponseEntity | getForEntity(String url, Class responseType, Object… uriVariables) | 通过Get方式发送一个请求 |
ResponseEntity | getForEntity(URI url, Class responseType) | 通过Get方式发送一个请求 |
T | getForObject(String url, Class responseType, Map<String,?> uriVariables) | 通过Get方式发送一个请求 |
T | getForObject(String url, Class responseType, Object… uriVariables) | 通过Get方式发送一个请求 |
参数说明:
- URI: 为测试的API的URL映射访问路径
- Class responseType: 为API方法的返回值的类型
- Map|uriVariables: map和可变性惨都可以作为参数传递的容器。
① getForObject方法
【示例代码】
@Autowired
private StudentService studentService;
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/queryCondition/{name}/{email}")
public Student queryCondition(@PathVariable("name") String name, @PathVariable("email") String email) {
Map<String, Object> paraMap = new HashMap<>();
paraMap.put("name", name);
paraMap.put("email", email);
Student queryCondition = studentService.queryCondition(paraMap);
return queryCondition;
}
@GetMapping("/getForObject")
public Student getForObject() {
String url = "http://localhost:8099/student/queryCondition/test/123";
// Map<String, Object> paramMap= new HashMap<>();
Student student = restTemplate.getForObject(url, Student.class);
return student;
}
这里我所演示的方法是带有两个参数 的getForObject方法,为了方便测试使用了Rest风格,我们也可以写一个不用Rest风格的API去进行测试,使用ApiFox测试工具进行测试
② getForEntity方法
@RequestMapping("/queryByName")
public Student queryByName(@RequestParam("name") String name) {
Student student = studentService.queryByName(name);
return student;
}
@GetMapping("/getForEntity")
public Student getForEntity() {
String url = "http://localhost:8099/student/queryByName?name={name}";
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("name", "孙权");
ResponseEntity<Student> entity = restTemplate.getForEntity(url, Student.class, paramMap);
System.out.println("entity响应体"+entity);
HttpStatus statusCode = entity.getStatusCode();
System.out.println("状态码:"+statusCode);
int statusCodeValue = entity.getStatusCodeValue();
System.out.println("状态码所表现的值:"+statusCodeValue);
HttpHeaders headers = entity.getHeaders();
System.out.println("响应头信息:"+headers.toString());
return entity.getBody();
}
????????????注意:
我们在使用三个参数方法的时候,在传递参数的时候需要在URL里面使用{}来包裹参数的占位变量,这个变量需要与Map的键的名称一致
总结:
- getForObject方法只能返回方法请求返回的对象值;
- getForEntity方法不仅可以返回一个对象值,还可以返回状态码,请求头信息等。
1.2.2 POST请求模板方法
Modifier and Type | Method and Description | 描述 |
---|---|---|
<T> ResponseEntity<T> | postForEntity(String url, Object request, Class responseType, Map<String,?> uriVariables) | 通过将给定对象发布到URI模板来创建新资源,并将响应作为HttpEntity返回。 |
<T> ResponseEntity<T> | postForEntity(String url, Object request, Class responseType, Object… uriVariables) | 通过将给定对象发布到URI模板来创建新资源,并将响应作为ResponseEntity返回。 |
<T> ResponseEntity<T> | postForEntity(URI url, Object request, Class responseType) | 通过将给定对象发布到URI模板来创建新资源,并将响应作为ResponseEntity返回 |
URI | postForLocation(String url, Object request, Map<String,?> uriVariables) | 通过将给定对象发布到URI模板来创建新资源,并返回位置标头的值。 |
<T> T | postForObject(String url, Object request, Class responseType, Map<String,?> uriVariables) | 通过将给定对象发布到URI模板来创建新资源,并返回在响应中找到的表示形式。 |
ResponseEntity | getForObject(URI url, Class responseType) | 通过Get方式发送一个请求 |
① postForObject方法????
RestTemplate的传参
RestTemplate的Post方法与Get方法的区别就在于Post方法传参Map必须是MultiValueMap
Post方法的MultiValueMap即支持基本的类型分开传参,也支持实体传参,类似于下面的形式。
【参数说明】:
- url: 请求地址;
- request: 请求实体,封装请求头,请求内容,请求参数等信息,
对应着map参数集合
- responseType: 响应类型,根据服务接口的返回类型决定
一定要和测试的方法的返回值类型对应,否则就会报错
- uriVariables: url中参数变量值
/**
* post方式 实体传参
*/
@RequestMapping("/addStudent")
public String addStu(Student student) {
if (studentService.addStu(student)) {
return "添加一名学生";
}
return "添加学生失败...";
}
@RequestMapping("/postForOject")
public Student postForObject(Student student) {
String url = "http://localhost:8099/student/addStudent";
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("name", student.getName());
map.add("email", student.getEmail());
map.add("age", student.getAge());
map.add("id",student.getId());
Student student = restTemplate.postForObject(url, map, String.class);
return student;
}
使用ApiFox测试访问测试
控制台输出结果,发现已经插入成功
注意:
这里的PostForObject的ResponseType必须要和测试方法的返回值类型匹配
【小结】
参数和get请求的相比,就多了第二个参数(Object request),如果使用最后一个参数传参时,和get请求类似,request设置为null就可以,如果使用第二个参数传参时,就需要考虑request的类型,request参数类型必须是实体对象、MultiValueMap、HttpEntity对象的的一种,其他不可以!!!
❓
那么为什么使用PostForObject的时候,传递参数必须要使用MultiValueMap这个map呢???
这里看到一篇博客后,这里总结以下:
我们如果使用hashMap来进行参数的传递的话,Spring的RestTemplate模板会将我们传进去的参数以Json的形式进行解析存储在Body里面,所以我们请求URL的时候,就会爆出没有参数的异常信息。
这时候就有一个核心的类AbstractJackson2HttpMessageConverter
理解为json的Http消息转化器,里面的一个writeInternal
方法
设用Josn的原因在于,RestTemplate会先根据请求实体HttpEntity的Body内容,遍历当前所支持的所有的消息解析器,并判断是否适配。
AbstractJackson2HttpMessageConverter
这个类里面有个canWrite的方法,在我们使用HashMap传递参数的时候也是可以别解析到的,只不过是被解析到了Body里面,URL是不会获取到的
那么问题又来了,如何使得URL可以放拿到我们传递的参数呢,此时,我们就需要去 FormHttpMessageConverter
里面的canWrite方法找答案
【小结】
我们在使用PostForObject模拟发送Post请求的时候,就必须要搭配MultiValueMap来进行传参。
【参考博客:】https://blog.csdn.net/qq_33589510/article/details/121527830?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165586313916780357263110%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=165586313916780357263110&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogfirst_rank_ecpm_v1~rank_v31_ecpm-1-121527830-null-null.nonecase&utm_term=resttemplate&spm=1018.2226.3001.4450
@RequestBody传参
需要使用HttpEntity的方式传参
/**
* @RequestBody传参
* @return
*/
@RequestMapping("/addStudent3")
public Student addStu3(@RequestBody Student student) {
Student student2 =new Student();
student2.setName(student.getName()+"from RequestBody");
return student2;
}
@RequestMapping("/postForEntity")
public Student postForEntity() {
// 申请一个请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// 远程访问的URL
String url = "http://localhost:8099/student/addStudent3";
Student student = new Student();
student.setName("嗨嗨嗨,老爹又回来了");
// 使用HttpEntity封装传参
HttpEntity<Student> entity = new HttpEntity<Student>(student,headers);
Student student2 = restTemplate.postForObject(url, entity, Student.class);
return student2;
}
注意:使用@ResponseBody传递参数的时候,需要使用HttpEntity进行封装参数和响应头信息,
而且不能使用MultiVlaueMap,如果使用,则会报错
② postForEntity方法????
@RequestMapping("/addStudent")
public String addStu(Student student) {
if (studentService.addStu(student)) {
return "添加一名学生";
}
return "添加学生失败...";
}
@RequestMapping("/addStudent4")
public Student addStu4(
@RequestParam("name") String name,
@RequestParam("email") String email,
@RequestParam("age") Integer age,
@RequestParam("id") Integer id) {
Student student = new Student();
student.setName(name);
student.setAge(age);
student.setEmail(email);
student.setId(id);
return student;
}
/**
* postForEntity
*/
@RequestMapping("/postForEntity2")
public Student postForEntity2() {
String url = "http://localhost:8099/student/addStudent4";
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("name", "张三");
map.add("email", "1687567@qq.com");
map.add("age", 34);
map.add("id",1456);
ResponseEntity<Student> entity = restTemplate.postForEntity(url, map, Student.class);
HttpStatus statusCode = entity.getStatusCode();
System.out.println(statusCode);
int statusCodeValue = entity.getStatusCodeValue();
System.out.println(statusCodeValue);
HttpHeaders headers = entity.getHeaders();
System.out.println(headers);
return entity.getBody();
}
1.2.3 Exchange方法
- Exchange方法即可以发送get请求,也可以发送Post请求
- Exchange方法可以做getForEntity,也可以做postForEntity等等。
restTemplate Exchange
????????exchange 使用时,返回响应数据时用ResponseEntity封装,请求时用HttpEntity封装参数。
方法名称 | exchange(String url, HttpMethod method,@Nullable HttpEntity<?> requestEntity, Class responseType, Map uriVariables) |
---|
【参数说明】:
- url: 请求地址;
- method: 请求类型(如:POST,PUT,DELETE,GET);
- requestEntity: 请求实体,封装请求头,请求内容,请求参数等信息
- responseType: 响应类型,根据服务接口的返回类型决定
- uriVariables: url中参数变量值
@RequestMapping("/addStudent5")
public Student addStu5(@RequestParam("name") String name,@RequestParam("email") String email,@RequestParam("age") Integer age) {
Student student = new Student();
student.setName(name);
student.setAge(age);
student.setEmail(email);
student.setId(1001);
return student;
}
/**
* exchange方法
*/
@RequestMapping("/exchange")
public Student echanges() {
String url ="http://localhost:8099/student/addStudent5";
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("name", "李思思");
map.add("email", "lisis@qq.com");
map.add("age", 34);
// 封装请求参数
HttpEntity<MultiValueMap> requestEntity = new HttpEntity<>(map);
// 封装响应 参数1为url,参数二为请求方式,参数三为封装的请求HttpEntity,参数四为返回值的
ResponseEntity<Student> exchange = restTemplate.exchange(url, HttpMethod.POST,requestEntity,Student.class);
return exchange.getBody();
}
最后
以上就是诚心保温杯为你收集整理的Http客户端请求工具-RestTemplateRestTemplate一款好用且强大的Http请求工具前言RestTemplate的全部内容,希望文章能够帮你解决Http客户端请求工具-RestTemplateRestTemplate一款好用且强大的Http请求工具前言RestTemplate所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复