前言: 因为总是需要使用不同的参数传递方式,所以特地来总结一下SpringBoot中常用的参数的绑定方式,给有需要的朋友查阅。

SpringBoot参数传递

 

注意:虽然Restful风格很流行,但是大部分还是主要是GET和POST的内容,所以这里只是列举GET和POST请求为例。 而且,无论怎么样的花样传参,它都是符合上面这个报文结构的!正所谓:万变不离其宗嘛!

GET请求方式

注意:我这里是示例形式是:代码+Postman测试截图+Fiddler抓包截图。

01.单个键值对参数

/**
  * GET 方式传递参数  单个参数
  * */
 @GetMapping("/get01")
 public String get01(String comment) {
     return comment == null ? "no parameter" : comment;
 }


 

 

使用@RequestParam注解,请求必须携带参数,否则就会报错,否则就是:错误码400 Bad Request

@GetMapping("/get02")
 public String get02(@RequestParam("comment") String comment) {
     return comment;
 }

如果参数不添加 @RequestParam 注解,那么这个参数即可不传递,而使用了注解的话,默认是必须传递参数的,当然了也可以配置为false。但是,我倾向于还是显示使用注解,这样比较清晰,也可配置,更加灵活。

 

02.多个键值对参数

/**
  * GET 方式传递参数  多个参数
  * */
 @GetMapping("/get03")
 public String get03(@RequestParam("id") String id,
         @RequestParam("name") String name,
         @RequestParam("comment") String comment) {
     System.out.println(id + " " + name + " " + comment);        
     return id + " " + name + " " + comment;
 }


 

03.键值对映射对象

 

/**
  *  使用对象对参数进行封装,这样在多个参数时,优势很明显。
  *  但是这里无法使用 @RequestParam注解,否则会出错。
  * */
 @GetMapping("/get04")
 public Comment get04(Comment comment) {
     if (Objects.isNull(comment)) {
         return null;  // 需要对 null 值进行处理
     }
     System.out.println(comment);
     return comment;
 }


 

 

04.键值对映射Map

/**
   * 使用对象封装参数要求必须具有一个对象,所以可以使用 Map 来封装,这样可以减少对象的数
   * 量。 
   * * */
 @GetMapping("/get05")
 public Map<String, String> get05(@RequestParam Map<String, String> map) {
     map.forEach((k, v) -> {
         System.out.println(k + " --> " + v);
     });
     System.out.println(map.size());
     return map;
 }


 

05.路径参数

/**
  * 参数和路径结合,适用于单个参数的情况
  * */
 @GetMapping("/get06/{id}")
 public Comment getById(@PathVariable("id") String id) {
     Comment comment = new Comment();
     comment.setId(id);
     comment.setName("Alfred");
     comment.setComment("I love you yesterday and today!");
     return comment;
 }


请求直接写在路径上,成为路径的一部分

06.返回值为二进制

前面都是文本数据,现在我们尝试来获取二进制数据,注意这个方法需要下面的上传文件方法向上传文件,或者你自己在文件夹下面放入一个文件。

/**
  * 返回值为二进制
  * 其实这里可以使用 Files.readAllBytes()这个方法,这样就简单了。这里我就不改了,我习惯了使用这种
  * 循环读取的方式,不过确实有点繁琐了。
  * */
 @GetMapping("/get07/{name}")
 public void getFile(@PathVariable("name") String name, HttpServletResponse response) {
     try (OutputStream out = new BufferedOutputStream(response.getOutputStream())) {
         try (InputStream in = new BufferedInputStream(new FileInputStream(new File(baseDir, name)))) {
             int len = 0;
             byte[] data = new byte[4*1024];
             while ((len = in.read(data)) != -1) {
                 out.write(data, 0, len);
             }
         }
     } catch (IOException e) {
         e.printStackTrace();
     }
 }


 

POST请求方式

01.多个键值对参数

/**
  * POST方式传递参数
  * @return 
  * */
 @PostMapping("/post01")
 public String post01(@RequestParam("id") String id,
         @RequestParam("name") String name,
         @RequestParam("comment") String comment) {
     System.out.println(id + " " + name + " " + comment);        
     return id + " " + name + " " + comment;
 }

 

02.键值对映射Map

@PostMapping("/post02")
 public Map<String, String> post02(@RequestParam Map<String, String> map) {
     map.forEach((k, v) -> {
         System.out.println(k + " --> " + v);
     });
     return map;
 }


 

 

03.传递json数据映射对象

@PostMapping("/post03")
 public Comment post03(@RequestBody Comment comment) {
     System.out.println(comment);
     return comment;
 }


请求参数形式为json字符串,并且选择Content-Type选择 raw,不能选择其它形式的原因的,form-data和x-www-form-urlencoded都会改变请求参数

 

04.json数组映射对象数组

/**
  * 传递对象数组
  * */
 @PostMapping("/post04")
 public Comment[] post04(@RequestBody Comment[] comments) {
     return comments;
 }


 

 

05.json数组映射List

@PostMapping("/post05")
 public List<Comment> post05(@RequestBody List<Comment> commentList) {
     return commentList;
 }


 

 

06.传递二进制数据(文件)

/**
  * 传递二进制数据
  * */
 @PostMapping("/upload")
 public String uploadFile(@RequestParam("file") MultipartFile file) {    
     if (!file.isEmpty()) {
         String fileName = file.getOriginalFilename();
         try {
             file.transferTo(new File(baseDir, fileName)); // 对于 SpringBoot 中使用路径还是懵逼!
             return "success";
         } catch (IllegalStateException e) {
             e.printStackTrace();
         } catch (IOException e) {
             e.printStackTrace();
         }
     } 
     return "Fail";
 }


 

8.表单数据(文本+文件)

/**
  *  表单数据,含文本和二进制
  * */
 @PostMapping("/submitInfo01")
 public String submitInfo(@RequestParam("id") String id,
         @RequestParam("name") String name,
         @RequestParam("file") MultipartFile file) {
     
     System.out.println("id: " + id);
     System.out.println("name: " + name);
     System.out.println("fileName: " + file != null ? file.getOriginalFilename() : "null");
     
     if (!file.isEmpty()) {
         String fileName = file.getOriginalFilename();
         try {
             file.transferTo(new File(baseDir, fileName));
             return "success";
         } catch (IllegalStateException e) {
             e.printStackTrace();
         } catch (IOException e) {
             e.printStackTrace();
         }
     } 
     return "Fail";
 }


 

 

09.表单数据,进一步封装成对象

上面那样如果表单项比较多的话,映射还是比较麻烦的,可以选择创建一个对象封装所有的属性,这样处理起来就会更加方便,并且也是面向对象思想的应用。

/**
  *    表单数据,含文本和二进制 进一步封装!
  * */
 @PostMapping("/submitInfo02")
 public String submitInfo02(User user) {
     
     MultipartFile file = user.getFile();
     System.out.println("id: " + user.getId());
     System.out.println("name: " + user.getName());
     System.out.println("fileName: " + user != null ? file.getOriginalFilename() : "null");
     
     if (!file.isEmpty()) {
         String fileName = file.getOriginalFilename();
         try {
             file.transferTo(new File(baseDir, fileName));
             return "success";
         } catch (IllegalStateException e) {
             e.printStackTrace();
         } catch (IOException e) {
             e.printStackTrace();
         }
     } 
     return "Fail";
 }


 

10.ajax2.0传递二进制数据

/**
 * POST以二进制形式传递文件,通常的web表单是做不到的,但是ajax2.0以后是支持的,我们来尝试一下。
 * 注意它和 Multipart的区别,Multipart实际上不只包含文件本身的数据,还有文件的其它的信息,例如刚才获取的文件名。
 * 但是如果以二进制的形式传递,它就是完全的文件数据流,不包含任何其它信息,只有文件本身的二进制数据流。
 * 
 * 使用这种形式,只能传输单个文件,无法传输多个文件,因为它只是文件本身的二进制数据,如果是多个的话,
 * 那么谁也别想从一个连续的二进制流中把图片切分出来了。
 

* */
 @PostMapping("/binaryFile")
 public String binaryFile(@RequestBody byte[] fileData) {
     try {
         Files.write(Paths.get(baseDir, UUID.randomUUID().toString() + ".jpg"), fileData);
         return "success";
     } catch (IOException e) {
         e.printStackTrace();
         return e.getMessage();
     }
 }