RestTemplate 发送 GET 请求
RestAPI - 通过@RequestParam接收参数的GET接口
@RequestMapping(value = "accounts/filter", method = RequestMethod.GET) public Account filter(@RequestParam String name, @RequestParam Integer age) { return new Account(new Random().nextLong(), name, age, "********"); }
RestTemplate Demo
/** * 使用 RestTemplate 发送 GET 请求 * RestTemplate 发送 GET 请求时,如果需要传入参数,需要以示例方法 url 的方式传入 * RestTemplate有两组方法发送 Get 请求 * <code> * restTemplate.getForObject(String url, Class responseType, Map uriVariables)<br/> * restTemplate.getForEntity(String url, Class responseType, Map uriVariables)<br/> * </code> * restTemplate.getForObject是对restTemplate.getForEntity的简化,<br/> * 通过restTemplate.getForEntity,我们可以获取HttpStatus的相关信息并加以使用.<br/> * 如果我们不关心 HttpStatus,那么使用 restTemplate.getForObject() 即可. */ @Test public void getMethodTest() { // http://ip:port/project-name/accounts/filter String url = "http://192.168.1.121:9001/rest-server/accounts/filter?name={name}&age={age}"; RestTemplate restTemplate = new RestTemplate(); Map<String, Object> params = new HashMap<>(); params.put("age", "26"); params.put("name", "lee"); Account account = restTemplate.getForObject(url, Account.class, params); System.out.println(account); // 上面 2 行等价于下面 5 行 /*ResponseEntity<Account> responseEntity = restTemplate.getForEntity(url, Account.class, params); if (responseEntity.getStatusCode().is2xxSuccessful()) { Account account1 = responseEntity.getBody(); System.out.println(account1); }*/ }
RestAPI - 通过@PathVariable提取url变量的GET接口
@RequestMapping(value = "accounts/{id}", method = RequestMethod.GET) public Account get(@PathVariable("id") Long id, @RequestParam String name) { return new Account(id, name, 18, "!@#$%^&*"); }
RestTemplate Demo
@Test public void getMethodTest2() { String url = "http://192.168.1.121:9001/rest-server/accounts/{id}?name={name}"; RestTemplate restTemplate = new RestTemplate(); Map<String, Object> params = new HashMap<>(); params.put("id", "100001"); params.put("name", "libai"); Account account = restTemplate.getForObject(url, Account.class, params); Assert.assertEquals(account.toString(), "Account{id=100001, age=18, name='libai', pwd='!@#$%^&*'}"); }12345678910
使用 RestTemplate 发送 POST 请求
RestAPI - 使用@RequestBody接收请求参数的POST接口
@RequestMapping(value = "accounts", method = RequestMethod.POST) public Account create(@RequestBody Account account) { return account; }
RestTemplate Demo
/** * 使用 RestTemplate 发送 POST 请求<br/> * 请求接口:{@link RestServer#create(Account)}<br/> * <br/> * 根据接口{@link RestServer#create(Account)}的要求,我们需要使用Payload提交方式来提交数据<br/> * Payload提交方式区别于Form提交方式<br/> * Form提交方式提交的数据,服务端可以通过{@link HttpServletRequest#getParameter(String)}方法获取,<br/> * 体现在SpringMVC框架中,即数据参数通过 {@link org.springframework.web.bind.annotation.RequestParam} 注解绑定获取<br/> * Payload提交方式提交的数据,服务端可以通过{@link HttpServletRequest#getInputStream()}方法获取,<br/> * 体现在SpringMVC框架中,即数据参数通过 {@link org.springframework.web.bind.annotation.RequestBody} 注解绑定获取<br/> * <br/> * RestTemplate 默认使用 Payload 方式提交数据,数据的格式是 json。<br/> * 即本示例中 <code>params</code> 会被格式化成 json 格式数据,并放在request body中发送给服务端 */ @Test public void postMethodTest() { String url = "http://192.168.1.121:9001/rest-server/accounts"; RestTemplate restTemplate = new RestTemplate(); Map<String, Object> params = new HashMap<>(); params.put("id", "100001"); params.put("name", "李白"); params.put("age", "100001"); params.put("pwd", "&*()#$%^"); Account account = restTemplate.postForObject(url, params, Account.class); System.out.println(account); }
RestAPI - 使用@RequestParam接收请求参数的POST接口
@RequestMapping(value = "accounts/create", method = RequestMethod.POST) public Account create(@RequestParam Long id, @RequestParam String name, @RequestParam Integer age, @RequestParam String pwd) { return new Account(id, name, age, pwd); }
RestTemplate Demo
/** * 使用 RestTemplate 发送 POST 请求<br/> * 请求接口:{@link RestServer#create(Long, String, Integer, String)}<br/> * <br/> * 根据接口 {@link RestServer#create(Long, String, Integer, String)}的要求,我们需要使用Form提交方式来提交数据<br/> * RestTemplate 默认使用 Payload 方式提交数据,想要使用Form方式提交,需要通过 HttpHeaders 设置<br/> * 另外,多个参数需要使用{@link LinkedMultiValueMap}来封装 */ @Test public void postMethodTest2() { String url = "http://192.168.1.121:9001/rest-server/accounts/create"; RestTemplate restTemplate = new RestTemplate(); // 此处不能换成 HashMap MultiValueMap<String, Object> params = new LinkedMultiValueMap<>(); params.add("id", "100001"); params.add("name", "杜甫"); params.add("age", "100001"); params.add("pwd", "&*()#$%^"); // 通过 HttpHeaders 设置Form方式提交 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(params, headers); Account account = restTemplate.postForObject(url, httpEntity, Account.class); System.out.println(account); }
使用 RestTemplate 发送带有 HttpHeader 信息的请求
RestAPI - 使用@RequestHeader获取请求头信息的POST接口
@RequestMapping(value = "accounts/authorization", method = RequestMethod.POST) public Account create(@RequestHeader("authorization") String authorization, @RequestHeader("token") String token, @RequestBody Account account) { if (authorization.equals("12345678") && token.equals("bce235emn97jjf00")) { return account; } return new Account(); }
RestTemplate Demo
@Test public void httpHeaderTest() { String url = "http://192.168.1.121:9001/rest-server/accounts/authorization"; HttpHeaders headers = new HttpHeaders(); headers.add("authorization", "12345678"); headers.add("token", "bce235emn97jjf00"); Map<String, Object> params = new HashMap<>(); params.put("id", "100001"); params.put("name", "李白"); params.put("age", "100001"); params.put("pwd", "&*()#$%^"); HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(params, headers); RestTemplate restTemplate = new RestTemplate(); Account account = restTemplate.postForObject(url, httpEntity, Account.class); System.out.println(account.toString()); }
使用 RestTemplate 进行文件上传
使用@RequestPart接收文件上传请求的POST接口
@RequestMapping(value = "accounts/logo", method = RequestMethod.POST) public boolean changeLogo(@RequestPart("logo") MultipartFile file, @RequestParam(value = "nickname", required = false) String nickname) throws IOException { String fileName = file.getOriginalFilename(); File f = new File(fileName); file.transferTo(f); System.out.println(f.getAbsolutePath()); return true; }
RestTemplate Demo
@Test public void uploadImgTest() { String url = "http://192.168.1.121:9001/rest-server/accounts/logo"; HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); MultiValueMap<String, Object> params = new LinkedMultiValueMap<>(); params.add("logo", new FileSystemResource("C:\\Users\\lixiangke\\Pictures\\Saved Pictures\\jdsadh.jpg")); params.add("nickname", "nick"); HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(params, headers); RestTemplate restTemplate = new RestTemplate(); String str = restTemplate.postForObject(url, httpEntity, String.class); System.out.println(str);
Account.java
package com.springboot.web.rest_template; /** * @author odllu */ public class Account { private Long id; private int age; private String name; private String pwd; public Account() { } public Account(Long id, String name, int age, String pwd) { this.id = id; this.age = age; this.name = name; this.pwd = pwd; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } @Override public String toString() { return "Account{" + "id=" + id + ", age=" + age + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}'; } }
RESTful文件上传与下载
文件上传
@Test public void whenUploadSuccess() { try { String file = mockMvc.perform(MockMvcRequestBuilders.fileUpload("/file") .file(new MockMultipartFile("file", "test.txt", "multipart/form-data", "hello upload".getBytes("UTF-8")))) .andExpect(MockMvcResultMatchers.status().isOk()) .andReturn().getResponse().getContentAsString(); log.info("file:{}",file); } catch (Exception e) { e.printStackTrace(); } } @PostMapping public FileInfo upload(MultipartFile file) { log.info(file.getName()); log.info(file.getOriginalFilename()); log.info(String.valueOf(file.getSize())); File localFile = new File(folder, new Date().getTime() + ".txt"); try { file.transferTo(localFile); return new FileInfo(localFile.getAbsolutePath()); } catch (IOException e) { e.printStackTrace(); return null; } }
文件下载
@GetMapping("/{id}") public void download(@PathVariable String id, HttpServletRequest request, HttpServletResponse response) { try (InputStream ips = new FileInputStream(new File(folder, id + ".txt")); OutputStream ops = response.getOutputStream();) { response.setContentType("application/x-download"); response.setHeader("Content-Disposition", "attachment;filename=test.txt"); IOUtils.copy(ips, ops); ops.flush(); }catch (IOException e){ e.printStackTrace(); } }
个人代码:
/** * 文件下载/预览 * * @param * @return * @throws ApiException */ @GetMapping(value = "/downloadEmailFile/{fileId}") @ApiOperation(value = "文件下载/预览", notes = "文件下载/预览") public void downloadEmailFile(@PathVariable String fileId, HttpServletResponse response) throws ApiException { byte[] body =fileInfoService.downFileByte(fileId); FileInfoVO fileInfoById = fileInfoService.getFileInfoById(fileId); InputStream inputStream=new ByteArrayInputStream(body); try ( OutputStream ops = response.getOutputStream();) { response.setContentType("application/x-download"); response.setHeader("Content-Disposition", "attachment;filename="+fileInfoById.getFileSysName()); IOUtils.copy(inputStream, ops); ops.flush(); }catch (IOException e){ e.printStackTrace(); } }
RestTemplate无法@Autowired注入解决
package com.oldlu.lcls; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; import springfox.documentation.swagger2.annotations.EnableSwagger2; import tk.mybatis.spring.annotation.MapperScan; @SpringBootApplication @EnableSwagger2 @MapperScan("com.oldlu.lcls.DAO") public class LclsApplication { //防止RestTemplate无法自动装配 @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(LclsApplication.class, args); } }
RestTemplate请求上传文件(MultipartFile不缓存文件)
- 背景
- 有两个服务,A服务有一个文件上传的接口,B服务通过restTemplate调用A服务的接口上传一个文件。
- B服务已经拿到文件内容。那么是否能够在不需要生成临时文件的情况下上传文件到A服务呢?
- 实现过程
- 定义内容
String fileStr = "文件内容";
- 字符串转换成byte[]
byte[] xmlBytes = fileStr.getBytes();
- 自定义MultipartFile实现类
public class BASE64DecodedMultipartFile implements MultipartFile { // 上传文件字节流 private final byte[] imgContent; // 上传文件的文件名 private final String originalFilename; public BASE64DecodedMultipartFile(byte[] imgContent, String originalFilename) { this.imgContent = imgContent; this.originalFilename = originalFilename; } @Override public String getName() { // TODO - implementation depends on your requirements return null; } @Override public String getOriginalFilename() { // TODO - implementation depends on your requirements return this.originalFilename; } @Override public String getContentType() { // TODO - implementation depends on your requirements return null; } @Override public boolean isEmpty() { return imgContent == null || imgContent.length == 0; } @Override public long getSize() { return imgContent.length; } @Override public byte[] getBytes() throws IOException { return imgContent; } @Override public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(imgContent); } @Override public void transferTo(File dest) throws IOException, IllegalStateException { new FileOutputStream(dest).write(imgContent); } }
- 构造上传文件对象
MultipartFile mf = new BASE64DecodedMultipartFile(xmlBytes, fileName);
- 通过restTemplate调用远程接口
HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); MultiValueMap<String, Object> requestparams = new LinkedMultiValueMap<>(); requestparams.add("file", mf.getResource()); requestparams.add("filename", mf.getOriginalFilename()); HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(requestparams, headers); RestTemplate restTemplate = new RestTemplate(); Object resultVo = restTemplate.postForObject(url, requestEntity, Object.class);
其中的文件可以传递一下资源
如果需要缓存文件直接将MultipartFile转换为本地File