4、POST 请求
4.1、post 请求常见的 3 种类型
http 请求头中的 Content-Type 用来指定请求的类型,常见的有 3 种
Content-Type | 说明 |
application/x-www-form-urlencoded | 页面中普通的 form 表单提交时就是这种类型,表单中的元素会按照名称和值拼接好,然后之间用&连接,格式如:p1=v1&p2=v2&p3=v3然后通过 urlencoded 编码之后丢在 body 中发送 |
multipart/form-data | 页面中表单上传文件的时候,用到的就是这种格式 |
application/json | 将发送的数据转换为 json 格式,丢在 http 请求的 body 中发送,后端接口通常用@RequestBody 配合对象来接收。 |
下面看则种方式的案例。
4.2、普通表单请求
普通表单默认为 application/x-www-form-urlencoded 类型的请求。
接口代码
@PostMapping("/test/form1") @ResponseBody public BookDto form1(BookDto bookDto) { return bookDto; }
使用 RestTemplate 调用接口
@Test public void test10() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/chat16/test/form1"; //①:表单信息,需要放在MultiValueMap中,MultiValueMap相当于Map<String,List<String>> MultiValueMap<String, String> body = new LinkedMultiValueMap<>(); //调用add方法填充表单数据(表单名称:值) body.add("id","1"); body.add("name","SpringMVC系列"); //②:发送请求(url,请求体,返回值需要转换的类型) BookDto result = restTemplate.postForObject(url, body, BookDto.class); System.out.println(result); }
如果想携带头信息,代码如下
@Test public void test11() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/chat16/test/form1"; //①:表单信息,需要放在MultiValueMap中,MultiValueMap相当于Map<String,List<String>> MultiValueMap<String, String> body = new LinkedMultiValueMap<>(); //调用add方法放入表单元素(表单名称:值) body.add("id","1"); body.add("name","SpringMVC系列"); //②:请求头 HttpHeaders headers = new HttpHeaders(); //调用set方法放入请求头 headers.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE); //③:请求实体:包含了请求体和请求头 HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(body, headers); //④:发送请求(url,请求实体,返回值需要转换的类型) BookDto result = restTemplate.postForObject(url, httpEntity, BookDto.class); System.out.println(result); }
4.3、上传本地文件
上传文件 Content-Type 为 multipart/form-data 类型。
接口如下,上传上传单个文件,返回值为一个 Map 类型,是泛型类型
@PostMapping(value = "/test/form2") @ResponseBody public Map<String, String> form2(@RequestParam("file1") MultipartFile file1) { Map<String, String> fileMetadata = new LinkedHashMap<>(); fileMetadata.put("文件名", file1.getOriginalFilename()); fileMetadata.put("文件类型", file1.getContentType()); fileMetadata.put("文件大小(byte)", String.valueOf(file1.getSize())); return fileMetadata; }
使用 RestTemplate 调用接口,主要下面代码②
上传的文件需要包装为org.springframework.core.io.Resource
,常用的有 3 中[FileSystemResource、InputStreamResource、ByteArrayResource],这里案例中我们用到的是 FileSystemResource 来上传本地文件,另外 2 种(InputStreamResource、ByteArrayResource)用法就比较特殊了,见下个案例。
@Test public void test12() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/chat16/test/form2"; //①:表单信息,需要放在MultiValueMap中,MultiValueMap相当于Map<String,List<String>> MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); //调用add方法放入表单元素(表单名称:值) //②:文件对应的类型,需要是org.springframework.core.io.Resource类型的,常见的有[FileSystemResource、InputStreamResource、ByteArrayResource] body.add("file1", new FileSystemResource(".\\src\\main\\java\\com\\javacode2018\\springmvc\\chat16\\dto\\UserDto.java")); //③:头 HttpHeaders headers = new HttpHeaders(); headers.add("header1", "v1"); headers.add("header2", "v2"); //④:请求实体 RequestEntity<MultiValueMap<String, Object>> requestEntity = new RequestEntity<>(body, headers, HttpMethod.POST, URI.create(url)); //⑤:发送请求(请求实体,返回值需要转换的类型) ResponseEntity<Map<String, String>> responseEntity = restTemplate.exchange( requestEntity, new ParameterizedTypeReference<Map<String, String>>() { }); Map<String, String> result = responseEntity.getBody(); System.out.println(result); }
4.4、通过流或字节数组的方式上传文件
有时候,上传的文件是通过流的方式或者字节数组的方式,那么就需要用到 InputStreamResource、ByteArrayResource 这俩了。 **注意:**使用这俩的时候,需要重写 2 个方法,否则会上传失败
- getFilename:文件名称
- contentLength:长度
@Test public void test13() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/chat16/test/form2"; //①:表单信息,需要放在MultiValueMap中,MultiValueMap相当于Map<String,List<String>> MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); /** * ②:通过流的方式上传文件,流的方式需要用到InputStreamResource类,需要重写2个方法 * getFilename:文件名称 * contentLength:长度 */ InputStream inputStream = RestTemplateTest.class.getResourceAsStream("/1.txt"); InputStreamResource inputStreamResource = new InputStreamResource(inputStream) { @Override public String getFilename() { return "1.txt"; } @Override public long contentLength() throws IOException { return inputStream.available(); } }; body.add("file1", inputStreamResource); //③:头 HttpHeaders headers = new HttpHeaders(); headers.add("header1", "v1"); headers.add("header2", "v2"); //④:请求实体 RequestEntity<MultiValueMap<String, Object>> requestEntity = new RequestEntity<>(body, headers, HttpMethod.POST, URI.create(url)); //⑤:发送请求(请求实体,返回值需要转换的类型) ResponseEntity<Map<String, String>> responseEntity = restTemplate.exchange( requestEntity, new ParameterizedTypeReference<Map<String, String>>() { }); Map<String, String> result = responseEntity.getBody(); System.out.println(result); }
4.5、复杂表单:多个普通元素+多文件上传
接口
/** * 复杂的表单:包含了普通元素、多文件 * * @param userDto * @return */ @PostMapping("/test/form3") @ResponseBody public Map<String, String> form3(UserDto userDto) { Map<String, String> result = new LinkedHashMap<>(); result.put("name", userDto.getName()); result.put("headImg", userDto.getHeadImg().getOriginalFilename()); result.put("idImgList", Arrays.toString(userDto.getIdImgList().stream(). map(MultipartFile::getOriginalFilename).toArray())); return result; }
UserDto:包含了多个元素(姓名、头像、多张证件照),这种可以模拟复杂的表单
public class UserDto { //姓名 private String name; //头像 private MultipartFile headImg; //多张证件照 private List<MultipartFile> idImgList; //get set 省略了... }
用 RestTemplate 调用这个接口,代码如下
@Test public void test14() { RestTemplate restTemplate = new RestTemplate(); String url = "http://localhost:8080/chat16/test/form3"; //①:表单信息,需要放在MultiValueMap中,MultiValueMap相当于Map<String,List<String>> MultiValueMap<String, Object> body = new LinkedMultiValueMap<>(); body.add("name", "路人"); body.add("headImg", new FileSystemResource(".\\src\\main\\resources\\1.jpg")); //来2张证件照,元素名称一样 body.add("idImgList", new FileSystemResource(".\\src\\main\\resources\\2.jpg")); body.add("idImgList", new FileSystemResource(".\\src\\main\\resources\\3.jpg")); //③:头 HttpHeaders headers = new HttpHeaders(); headers.add("header1", "v1"); headers.add("header2", "v2"); //④:请求实体 RequestEntity<MultiValueMap<String, Object>> requestEntity = new RequestEntity<>(body, headers, HttpMethod.POST, URI.create(url)); //⑤:发送请求(请求实体,返回值需要转换的类型) ResponseEntity<Map<String, String>> responseEntity = restTemplate.exchange( requestEntity, new ParameterizedTypeReference<Map<String, String>>() { }); Map<String, String> result = responseEntity.getBody(); System.out.println(result); }
输出
{name=路人, headImg=1.jpg, idImgList=[2.jpg, 3.jpg]}