SpringMVC第二弹。

SpringMVC-2-参数绑定与常用注解

1. 参数绑定

表单中的请求参数都是基于键值对的。SpringMVC绑定请求参数的过程是:把表单的请求参数作为控制器中方法的参数进行绑定。

SpingMVC请求参数的绑定是自动实现的,但要遵守规范。

1. 基本类型参数绑定

包含了基本数据类型和String类型

规范:参数名称必须和控制器方法参数一致,且严格区分大小写。

1
<a href="params/getUsername?username=tobing">测试普通数据类型绑定</a>
1
2
3
4
5
6
7
8
9
@Controller("paramsController")
@RequestMapping("/params")
public class ParamsController {
@RequestMapping(value = "/getUsername")
public String getUsername(String username){
System.out.println("用户名为:"+username);
return "success";
}
}

2. POJO类型参数绑定

包含了自定义实体类,以及其中关联的实体类

规范:参数名称必须和实体类属性名称一致,且控制器方法参数就是实体类。

1
2
3
4
5
6
7
8
 测试JavaBean类型绑定
<form method="post" action="params/getUser">
用户名:<input type="text" name="username"/><br>
密码:<input type="text" name="password"/><br>
账户密码:<input type="text" name="account.apwd"/><br>
账户余额:<input type="text" name="account.money"/><br>
<input type="submit" value="提交">
</form>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// JavaBean
public class User {
private String username;
private String password;
private Account account;
// setter、getter and toString
}
public class Account {
private String apwd;
private Float money;
// setter、getter and toString
}

// Controller
@Controller("paramsController")
@RequestMapping("/params")
public class ParamsController {
@RequestMapping(value = "/getUser")
public String getUser(User user){
System.out.println(user);
return "success";
}
}

3. 数组和集合类型参数绑定

包括了List结构和Map结构

规范:集合类型请求参数必须在实体类中,且请求参数名称要和实体类的属性名称一致。

List:使用下标

Map:使用键值对

1
2
3
4
5
6
7
8
9
10
参数绑定map和list
<form method="post" action="params/getUser">
用户名:<input type="text" name="username"/><br>
密码:<input type="text" name="password"/><br>
账户密码:<input type="text" name="accounts[0].apwd"/><br>
账户余额:<input type="text" name="accounts[0].money"/><br>
账户密码:<input type="text" name="accountMap['one'].apwd"/><br>
账户余额:<input type="text" name="accountMap['one'].money"/><br>
<input type="submit" value="提交">
</form>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Javabean
public class User {
private String username;
private String password;
private Map<String,Account> accountMap;
private List<Account> accounts;
// setter、getter and toString
}
public class Account {
private String apwd;
private Float money;
// setter、getter and toString
}

// Controller
@Controller("paramsController")
@RequestMapping("/params")
public class ParamsController {
@RequestMapping(value = "/getUser")
public String getUser(User user){
System.out.println(user);
return "success";
}
}

4. 自定义类型转换器

  • 当我们输入的数据格式不符合自动参数绑定的规范的时候,SpringMVC并不能帮助我们封装参数,会出错。(例如:2019/01/01可以自动封装Date,而2019-01-01会报400错误)

  • 此时除了更改数据格式,还可以使用自定义类型转换器,把数据封装。

  • 自定义类型转换器实际是我们把获取到的数据进行自定义封装。

  1. 使用步骤一:定义实现了Converter接口的实体类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    public class StringtoDateConverter implements Converter<String, Date> {
    @Override
    public Date convert(String source) {
    if(source==null){
    throw new RuntimeException("没找到数据");
    }
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    try {
    return sdf.parse(source);
    } catch (ParseException e) {
    throw new RuntimeException("日期格式异常!");
    }
    }
    }

    以上类实现了将yyyy-MM-dd格式的字符串转换为Date类型

  2. 在Spring配置文件中配置类型转换器

    spring 配置类型转换器的机制是,将自定义的转换器注册到类型转换服务中去。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <!--配置转换器-->
    <bean id="conversionServiceFactoryBean" class="org.springframework.context.support.ConversionServiceFactoryBean">
    <property name="converters">
    <set>
    <!--添加自己实现的转换器-->
    <bean class="top.tobing.utils.StringtoDateConverter"></bean>
    </set>
    </property>
    </bean>

    <!--配置spring开启mvc注解-->
    <!--引用转换器-->
    <mvc:annotation-driven conversion-service="conversionServiceFactoryBean"></mvc:annotation-driven>

5. 使用ServletAPI对象作为方法参数

  • SpringMVC 支持使用原始 ServletAPI 对象作为控制器方法的参数。

  • 支持的对象有:HttpServletRequest、HttpServletResponse 、HttpSession、 java.security.Principal 、Locale、InputStream 、OutputStream、 Reader、 Writer

  • 使用是直接将对象定义在控制器方法参数中

1
2
<a href="params/getServletAPI" >获取Servlet原生API</a>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Controller("paramsController")
@RequestMapping("/params")
public class ParamsController {
/**
* 获取Servlet原生API
* @param request
* @param response
* @return
*/
@RequestMapping("/getServletAPI")
public String getServletAPI(HttpServletRequest request, HttpServletResponse response){
System.out.println(request);
System.out.println(request.getSession());
System.out.println(response);
return "success";
}
}

2. 常用注解

1. RequestParam

  1. 作用:参数绑定时,把不符合规范的参数绑定到控制器方法指定的参数

  2. 属性:

    value:请求参数的名称

    required:请求参数中是否必须提供此参数。默认值:true。(表示必须提供,如果不提供将报错。 )

  3. 使用

    1
    2
    <a href="annos/testRequestParam?name=tobing">testRequestParam</a><br>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @Controller("annoController")
    @RequestMapping("/annos")
    @SessionAttributes(value = {"username","password"},types = {Integer.class})
    public class AnnoController {
    @RequestMapping("/testRequestParam")
    public String testRequestParam(@RequestParam("name") String usernmae){
    System.out.println("testRequestParam执行了");
    System.out.println(usernmae);
    return "success";
    }
    }

    将请求参数name绑定到控制器方法username参数上

2. RequestBody

  1. 作用:用于获取请求体内容( key=value&key=value…结构的数据),get 请求方式不适用。

  2. 属性:

    required:是否必须有请求体。默认值是:true。当取值为 true 时,get 请求方式会报错。如果取值 为 false,get 请求得到是 null。

  3. 使用:

    1
    2
    <a href="annos/testRequestBody">testRequestBody</a><br>

    1
    2
    3
    4
    5
    6
    7
    @RequestMapping("/testRequestBody")
    public String testRequestBody(@RequestBody String body){
    System.out.println("testRequestBody执行了");
    System.out.println(body);
    return "success";
    }

3. PathVaribale

  1. 作用:绑定 url 中的占位符。例如:请求 url 中 /delete/{id},这个{id}就是 url 占位符。 url 支持占位符是 spring3.0 之后加入的。是 springmvc 支持 rest 风格 URL 的一个重要标志。

  2. 属性:

    value:用于指定url中占位符名称

    required:是否必须提供占位符

  3. 使用:

    1
    2
    <a href="annos/testPathVariable/1024">testPathVariable</a><br>

    1
    2
    3
    4
    5
    6
    7
    @RequestMapping("/testPathVariable/{uid}")
    public String testPathVariable(@PathVariable("uid") String id){
    System.out.println("testPathVariable执行了");
    System.out.println(id);
    return "success";
    }

4. RequestHeader(少用)

  1. 作用:获取请求头

  2. 属性:

    value:要获取的消息头名称

    required:是否必须有次消息头

  3. 使用:

    1
    2
    <a href="annos/testRequestHeader">testRequestHeader</a><br>

    1
    2
    3
    4
    5
    6
    7
    @RequestMapping("/testRequestHeader")
    public String testRequestHeader(@RequestHeader(value = "Accept") String header){
    System.out.println("testRequestHeader执行了");
    System.out.println(header);
    return "success";
    }

    获取请求头中的Accept消息

5. CookieValue

  1. 作用:把指定cookie传到控制器方法参数中

  2. 属性:

    value:指定 cookie 的名称。

    required:是否必须有此 cookie。

  3. 使用:

    1
    2
    <a href="annos/testCookieValue">testCookieValue</a><br>

    1
    2
    3
    4
    5
    6
    7
    8
    @RequestMapping("/testCookieValue")
    public String testCookieValue(@CookieValue(value = "JSESSIONID") String cookie){
    System.out.println("testCookieValue执行了");
    System.out.println(cookie);
    return "success";
    }


6. ModeAttribute

  1. 作用:

    可以用于修饰方法和参数。

    出现在方法上,表示当前方法会在控制器的方法执行之前,先执行。它可以修饰没有返回值的方法,也可 以修饰有具体返回值的方法。

    出现在参数上,获取指定的数据给参数赋值。

  2. 属性:

    value:用于获取数据的 key。key 可以是 POJO 的属性名称,也可以是 map 结构的 key

  3. 使用场景

    当表单提交数据不是完整的实体类数据时,保证没有提交数据的字段使用数据库对象原来的数据。

    例如:我们在编辑一个用户时,用户有一个创建信息字段,该字段的值是不允许被修改的。在提交表单数 据是肯定没有此字段的内容,一旦更新会把该字段内容置为 null,此时就可以使用此注解解决问题。

  4. 使用:

    1
    2
    <a href="annos/testModelAttribute?username=tobing">testModelAttribute</a><br>

    修饰在方法上

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @RequestMapping("/testModelAttribute")
    public String testModelAttribute(User user){
    System.out.println("testModelAttribut执行了"+user.getUsername());
    return "success";
    }
    @ModelAttribute
    public void showModelAttribute(User user){
    System.out.println("showModelAttribut执行了"+user.getUsername());

    }

    showModelAttribut会先执行

    修饰在参数上:给指定参数赋值(方式一)

    1
    2
    3
    4
    5
    6
    <form method="post" action="annos/testModelAttribute">
    用户名:<input type="text" name="username"/><br>
    密码:<input type="text" name="password"/><br>
    <input type="submit" value="提交">
    </form>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @ModelAttribute
    public User showModel(String username,String password){
    User user = new User();
    user.setUsername(username);
    user.setPassword(password);
    user.setBirthday(new Date());
    System.out.println("showModel执行了"+user);
    return user;
    }

    @RequestMapping("/testModelAttribute")
    public String testModelAttribute(User user){
    System.out.println("testModelAttribut执行了"+user);
    return "success";
    }


    修饰在参数上:给指定参数赋值(方式二)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @ModelAttribute
    public void showModel(String username, Map<String,User> map){
    User user = new User();
    user.setUsername(username);
    user.setPassword("root");
    user.setBirthday(new Date());
    map.put("u",user);
    }

    @RequestMapping("/testModelAttribute")
    public String testModelAttribute(@ModelAttribute("u") User user){
    System.out.println("testModelAttribut执行了"+user);
    return "success";
    }

7. SessionAttribute

  1. 作用:用于多次执行控制器方法间的参数共享。

  2. 属性:

    value:用于指定存入的属性名称

    type:用于指定存入的数据类型。

  3. 使用:

    1
    2
    3
    4
    <a href="annos/testPut">存入SessionAttribute</a><br>
    <a href="annos/testGet">取出SessionAttribute</a><br>
    <a href="annos/complete">删除SessionAttribute</a><br>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // 存入session
    @RequestMapping("/testPut")
    public String testPut(Model model){
    model.addAttribute("username","tobing");
    model.addAttribute("password","root");
    model.addAttribute("age",21);
    return "success";
    }
    // 取出session
    @RequestMapping("/testGet")
    public String testGet(ModelMap model){
    System.out.println(""+model.get("username")+model.get("password")+model.get("age"));
    return "success";
    }

    // 删除session
    @RequestMapping("/complete")
    public String complete(SessionStatus status){
    status.setComplete();
    return "success";
    }

评论