首页 > 编程笔记 > Java笔记 阅读:2

SpringBoot传递参数的5种方法(附带实例)

参数传递是 Web 开发的基础内容,前端页面和后端服务通过请求和返回的参数来判断所执行的业务逻辑,因此参数的传递和接收是 Web 开发中最基础却非常重要的功能。

Spring Boot 支持多种参数接收方式,通过提供注解来帮助限制请求的类型、接收不同格式的参数等,,接下来我们通过示例一一介绍。

@PathVariable

在 Web 应用中,最常用的参数传递方式就是 URL 传参,也就是将参数放在请求的 URL 中。

例如微博上不同用户的个人主页应该对应不同的 URL:http://weibo.com/user/1、http://weibo.com/user/2。我们不可能对每个用户都定义一个 @RequestMapping 注解的方法来映射 URL 请求。对于相同模式的 URL,可以采用同一种规则进行处理。

1) 定义URL变量

@RequestMapping 注解使用 {} 来声明 URL 变量,例如 @RequestMapping("/user/{username}")。其中,{username} 是定义的变量规则,username 是变量的名字。此 URL 路由可以匹配下列任意 URL 请求:
/user/tianmaying
/user/ricky
/user/tmy1234

在 @RequestMapping 中定义变量规则后,Spring Boot 提供的 @PathVariable 注解帮助我们获取URL中定义的变量参数,示例如下:
@RequestMapping("/user/{username}")
@ResponseBody
public String userProfile(@PathVariable String username){
    return "user:" + username;
}
在上面的示例中,Spring Boot 会自动将 URL 中定义的变量传递给 userProfile 方法的 username 参数(同名赋值),例如当 HTTP 请求为 /users/weiz 时,URL 变量 username 的值 weiz 会被赋给函数参数 username,返回的数据为 user:weiz。

需要注意的是,在默认情况下,变量参数不能包含 URL 的分隔符“/”,也就是说上面定义的 URL 路由不能匹配 /users/weiz/zhang,即使 weiz/zhang 是一个存在的用户名。

2) 定义多个URL变量

上面介绍了传递单个变量的例子,那么多个变量呢?同样,@RequestMapping 支持定义包含多个 URL 变量的路由,示例如下:
@RequestMapping("/user/{username}/blog/{blogId}")
@ResponseBody
public String getUerBlog(@PathVariable String username , @PathVariable int blogId) {
    return "user: " + username + "blog:" + blogId;
}
在上面的示例中,@RequestMapping("/user/{username}/blog/{blogId}") 传入 {username} 和 {blogId} 两个参数,然后使用 @PathVariable 映射对应的变量参数。

在多变量参数的情况下,Spring Boot 能够根据变量名自动赋值对应的函数参数值,也可以在 @PathVariable 中显式声明具体的 URL 变量名。

在默认情况下,@PathVariable 注解的参数支持自动转换一些基本的数据类型,如 int、long、date、string 等,Spring Boot 能够根据 URL 变量的具体值以及函数参数的数据类型来进行转换,例如 /user/weiz/blog/1 会将“weiz”的值赋给 username,而 1 赋给 int 类型的变量 blogId。

3) 匹配正则表达式

虽然 @RequestMapping 路由支持 URL 变量,但是很多时候需要对 URL 变量进行更加精确的定义和限制,例如用户名只包含小写字母、数字、下划线:
/user/fpc是一个合法的URL
/user/#不是一个合法的URL
这种情况下,简单定义 {username} 变量就无法满足需求了。

没关系,@RequestMapping 注解同样支持正则表达式匹配,可以通过定义正则表达式更精确地控制,定义语法是 {变量名:正则表达式},示例代码如下:
@RequestMapping("/user/{username:[a-zA-Z0-9_]+}/blog/{blogId}")
@ResponseBody
public String getUerBlog(@PathVariable String username , @PathVariable int blogId) {
    return "user: " + username + "blog:" + blogId;
}
在上面的示例中,使用 [a-zA-Z0-9_]+正则表达式来限定 username 参数值只能包含小写字母、大写字母、数字、下划线。如此设置 URL 变量规则后,不合法的 URL 不会被处理,直接返回 404Not Found。

使用Bean对象接收参数

针对参数较多的表单提交,Spring Boot 可以通过创建一个 JavaBean 对象来接收 HTTP 传入的表单参数。

需要注意的是,JavaBean 对象中必须含有默认的构造函数,同时,需要设置属性字段必须有 setter 方法。

1) 增加Bean实体类

首先,增加表单对应的实体类,具体代码如下:
public class Student {
    private  String firstName;
    private  String lastName;
    // 省略get和set
}
上面的示例定义了 Student 数据实体类。

2) 增加后台方法

在 StudentController 控制器中增加 save() 方法,接收前台传来的数据。定义 save() 方法的示例代码如下:
@RequestMapping("/save")
public String save(Student student){
    String firstName = student.getFirstName();
    String lastName = student.getLastName();
    return firstName +" "+ lastName;
}
在浏览器中提交表单数据时,Spring Boot 会自动把提交的表单数据转为 Student 对象,然后传递给 save() 方法。

@RequsetBody接收JSON数据

@RequestBody 主要是将前端传入的 JSON 数据对象映射成后端的实体对象。比如,前端传入 JSON 格式的数据后,@RequestBody 注解会自动将 JSON 数据反序列化成 Student 对象。

使用时需要注意以下两点:
下面通过示例代码演示如何使用 @RequsetBody 接收 JSON 数据:
@PostMapping(path = "/save2")
public String save2(@RequestBody Student student) {
    String firstName = student.getFirstName();
    String lastName = student.getLastName();
    return firstName +" "+ lastName;
}
@PostMapping 注解包含 consumes 参数,默认为 application/json,表示前台需要传入 JSON 格式的参数。另外,Spring Boot 会根据名称一一对应,将数据转换成相应的数据类型。例如 JSON 数据中有 int 或 date 类型,前台传过来都是字符串,Spring Boot 会自动将其转换成实体类中的数据类型。

@ModelAttribute

熟悉 MVC 的读者应该都知道,我们可以将 @ModelAttribute 注解放置在控制器(Controller)中的某个方法上。当请求这个控制器中的某个 URL 时,会首先调用这个被注解的方法并将该方法的结果作为公共模型的属性,然后调用对应 URL 的处理方法,前端页面通过模型获取返回的数据。

@ModelAttribute 标注的方法会在 Controller 类的每个映射 URL 的控制执行方法之前执行。使用方法如下面的示例代码所示:
@ModelAttribute
public void findUserById(@PathVariable("userId") Long userId, Model model) {
    model.addAttribute("user", userService.findUserById(userId));
}

@GetMapping("/user/{userId}")
public String findUser(Model model) {
    System.out.println(model.containsAttribute("user"));
    return "success !";
}
在上面的示例中,当我们请求接口 /user/1 时,会先调用 findUserById() 方法,在方法内通过 userId 查询到对应的 User 对象放置到 Model 中。

如果仅仅添加一个对象到 Model 中,上面的代码可以再精练一些:
@ModelAttribute
public User findUserById(@PathVariable("userId") Long userId) {
    return userService.findUserById(userId);
}
通过上述代码返回的 User 对象会被自动添加到Model中,相当于手动调用了 model.addAttribute(user) 方法。

Model 通过 addAttribute() 方法向页面传递参数。@ModelAttribute 修饰的方法会先于 login 调用,它把请求的参数值赋给对应的变量。可以向方法中的 Model 添加对象,前提是在方法中加入一个 Model 类型的参数。

需要注意的是,被 @ModelAttribute 注释的方法会在此控制器的每个方法执行前被执行,因此对于一个控制器映射多个 URL,要谨慎使用。

ModelAndView对象

ModelAndView 也是 Spring MVC 中常用的数据返回对象。当控制器处理完请求时,通常会将包含视图对象和数据的 ModelAndView 对象一起返回前台。它的作用类似于 request 对象的 setAttribute() 方法。

ModelAndView 对象有两个作用:
ModelAndView 使用起来也特别简单,在控制器中把前台页面需要的数据放到 ModelAndView 对象中,然后返回 mv 对象。下面通过示例演示使用 ModelAndView 对象返回数据到前台页面:
@RequestMapping(value="/detail/{id}")
public ModelAndView detail(@PathVariable Long id){
   ModelAndView mv = new ModelAndView();
   User user =userService.getUserById(id);
   // 设置user对象的username属性
   mv.addObject("user","user");
   // 地址跳转,设置返回的视图名称
   mv.setViewName("detail");
   return mv;
}
上面的示例中,先获取用户数据,然后将数据和对象一起返回到前台 detail 页面。这样 Spring MVC 将使用包含的视图对模型数据进行渲染。

相关文章