SpringMVC(中)

时间:2019-10-21
本文章向大家介绍SpringMVC(中),主要包括SpringMVC(中)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、传值方式

(1)Map

Controller

@Controller
public class MyController {
    @RequestMapping("first")
    public String show(Map map){
        // 把数据写到 request 域
        map.put("name","大白");
        map.put("age",20);
        return "/result.jsp";
    }
}

结果页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>结果页</h3>
    ${requestScope.name}
    ${requestScope.age}
</body>
</html>

(2)ModelMap

ModelMap 对象主要用于传递控制方法处理数据到结果页面,也就是说我们把结果页面上需要的数据放到ModelMap 对象中即可。

把数据写到 request 域。request对象的setAttribute方法的作用: 用来在一个请求过程中传递处理的数据。

使用方法与model一样。

(3)Model

Model 和 ModelMap 的实例都是 spirng mvc 框架来自动创建并作为控制器方法参数传入,用户无需自己创建

可以简单地将model的实现类理解成一个Map,Request级别的模型数据。

Model 是一个接口, 其实现类为 ExtendedModelMap,继承了ModelMap类。

方法介绍

① asMap
Map<String, Object> asMap();

将当前的 model 转换成 Map

发送请求页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>Title</title>
  </head>
  <body>
  <a href="${pageContext.request.contextPath}/first">发送请求</a>
  </body>
</html>

结果页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>结果页</h3>
    ${requestScope.name}
</body>
</html>

Controller

@Controller
public class MyController {
    @RequestMapping("first")
    public String show(Model model){
        // 把数据写到 request 域
        model.addAttribute("name","Hello World");
        System.out.println(model.asMap());
        return "/result.jsp";
    }
}
② addAttribute
// 添加键值属性对
Model addAttribute(String attributeName, Object attributeValue);
// 以属性的类型为键添加属性
Model addAttribute(Object attributeValue);

注意:

① addAttribute(Object attributeValue) 默认的key是属性的类型首字母小写

② 如果model存在相同key,会被覆盖

请求页和 ① asMap 一样

结果页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>结果页</h3>
    ${requestScope.dog}
</body>
</html>

Controller

@Controller
public class MyController {
    @RequestMapping("first")
    public String show(Model model){
        // 把数据写到 request 域
        Dog mydog = new Dog();
        mydog.setName("WC");
        mydog.setColor("白色");
        model.addAttribute("dogs",mydog);
        // model.addAttribute(mydog); 相当于 model.addAttribute("dog",mydog);
        model.addAttribute(mydog);
        System.out.println(model.asMap());
        return "/result.jsp";
    }
}
③ addAllAttributes
// 将attributes中的内容复制到当前的model中,如果当前model存在相同内容,会被覆盖
Model addAllAttributes(Map<String, ?> attributes);
// 以集合中数据的类型首字母小写做为key,将所提供的Collection中的所有属性复制到这个Map中,如果有同类型会存在覆盖现象
Model addAllAttributes(Collection<?> attributeValues);

Controller

@Controller
public class MyController {
    @RequestMapping("first")
    public String show(Model model){
        // 把数据写到 request 域
        model.addAttribute("name","旺财");

        HashMap<String, Object> map = new HashMap<>();
        map.put("name","大白");
        map.put("age",20);
        model.addAllAttributes(map);
        System.out.println(model.asMap());
        // output:{name=大白, age=20}

        ArrayList<Object> list = new ArrayList<>();
        list.add("小白");
        list.add(20);
        model.addAllAttributes(list);
        System.out.println(model.asMap());
        // output:{name=大白, age=20, string=小白, integer=20}
        return "/result.jsp";
    }
}
④ mergeAttributes
// 将attributes中的内容复制到当前的model中,如果当前model存在相同内容,不会被覆盖
Model mergeAttributes(Map<String, ?> attributes);

Controller

@Controller
public class MyController {
    @RequestMapping("first")
    public String show(Model model){
        // 把数据写到 request 域
        model.addAttribute("name","旺财");

        HashMap<String, Object> map = new HashMap<>();
        map.put("name","大白");
        map.put("age",20);
        model.mergeAttributes(map);
        System.out.println(model.asMap());
        // output:{name=旺财, age=20}
        
        return "/result.jsp";
    }
}
⑤ containsAttribute
// 判断是否包含键为attributeName的值
boolean containsAttribute(String attributeName);

(4)ModelAndView

需要自己创建,既包含模型也包含视图

Controller

@Controller
public class MyController {
    @RequestMapping("first")
    public ModelAndView show(){
        ModelAndView modelAndView = new ModelAndView();
        // 把数据写到 request 域
        modelAndView.addObject("name","大白");
        modelAndView.addObject("age",20);
        System.out.println(modelAndView.getModel());
        modelAndView.setViewName("/result.jsp");
        return modelAndView;
    }
}

结果页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>结果页</h3>
    ${requestScope.name}
    ${requestScope.age}
</body>
</html>

(5)@SessionAttributes注解

将模型中的某个属性暂存到 HttpSession 中,以便多个请求之间可以共享这个属性,@SessionAttributes是标注在类上的。

value :通过指定key将model数据放到session域当中

type :把指定类型的模型数据放到session域当中

@Controller
@SessionAttributes(value = {"name","age"},types = String.class)
public class MyController {
    @RequestMapping("first")
    public String show(Model model){
        // 把数据写到 request 域
        model.addAttribute("name","大白");
        model.addAttribute("age",20);
        return "/result.jsp";
    }
}

结果页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>结果页</h3>
    ${requestScope.name}
    ${requestScope.age}
    ${sessionScope.name}
    ${sessionScope.age}
</body>
</html>

(6)@SessionAttribute注解

使用 @SessionAttribute 来访问预先存在的全局会话属性

请求发送页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>Title</title>
  </head>
  <body>
  <a href="${pageContext.request.contextPath}/first">发送请求</a>

  <a href="${pageContext.request.contextPath}/second">获取Session</a>
  </body>
</html>

Controller

@Controller
@SessionAttributes(value = {"name","age"},types = String.class)
public class MyController {
    @RequestMapping("first")
    public String show(Model model){
        model.addAttribute("name","大白");
        model.addAttribute("age",20);
        return "/result.jsp";
    }

    @RequestMapping("second")
    public String get(@SessionAttribute("name") String name, @SessionAttribute("age") Integer age){
        // 把数据写到 request 域
        System.out.println(name);
        System.out.println(age);
        return "/result.jsp";
    }
}

(7)@ModelAttribute

① @ModelAttribute 修饰方法参数:修改处理方法的参数时,自动把该参数放到model当中

@Controller
public class MyController {
    @RequestMapping("first")
    // 使用JavaBean接收参数,如果方法参数中有 Model model,会自动的把JavaBean添加到 model中去
    // 默认键名为JavaBean类型首字母小写,键名可以用@ModelAttribute设置
    public String show(@ModelAttribute("mydog") Dog mydog, Model model){
        // 把数据写到 request 域
        System.out.println(model.asMap());
        return "/result.jsp";
    }
}

② @ModelAttribute 修饰方法

@ModelAttribute 修饰的方法,在对应的 @RequestMapping 映射方法执行之前,会自动调用,并且会自动的把model传入这个方法,允许提前传入一些model信息。

请求发送页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>Title</title>
  </head>
  <body>
  <a href="${pageContext.request.contextPath}/first">发送请求</a>
  <form action="${pageContext.request.contextPath}/first" method="post">
    <p>name : <input type="text" name="name" value="小白"></p>
    <p>color : <input type="text" name="color" value="白色"></p>
    <p><input type="submit" value="提交"></p>
  </form>
  </body>
</html>

Controller

@ModelAttribute 修饰的方法,在对应的 @RequestMapping 映射方法执行之前,允许提前传入一些model信息

@Controller
public class MyController {
    
    @ModelAttribute
    public void init(Model model){
        System.out.println("@ModelAttribute 自动调用");
        model.addAttribute("age",5);
    }

    @RequestMapping("first")
    public String show(@ModelAttribute("mydog") Dog mydog, Model model){
        System.out.println(model.asMap());
        return "/result.jsp";
    }
}

注意:

@ModelAttribute 修饰的方法中设置的 key 和 @RequestMapping 修饰的方法参数中的 key值相同时 @ModelAttribute中的会被“属性”覆盖。即 同名的属性名覆盖。

请求发送页不变,Controller如下

@Controller
public class MyController {

    @ModelAttribute
    public void init(Model model){
        System.out.println("@ModelAttribute 自动调用");
        Dog dog = new Dog();
        dog.setName("initName");
        dog.setColor("initColor");
        dog.setAge(20);
        model.addAttribute("mydog",dog);
    }

    @RequestMapping("first")
    public String show(@ModelAttribute("mydog") Dog mydog, Model model){
        System.out.println(model.asMap());
        // outPut:{mydog=Dog{name='小白', color='白色', age=20}, ……}
        return "/result.jsp";
    }
}

注意:

@ModelAttribute 修饰的方法中,model 传进来之前,会把session域里的数据放到model中。

在 @ModelAttribute 里写的内容会覆盖session里的同名内容(“对象”覆盖)

请求发送

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>Title</title>
  </head>
  <body>
  <a href="${pageContext.request.contextPath}/session">发送请求</a>
  <form action="${pageContext.request.contextPath}/first" method="post">
    <p>name : <input type="text" name="name" value="小白"></p>
    <p>color : <input type="text" name="color" value="白色"></p>
    <p><input type="submit" value="提交"></p>
  </form>
  </body>
</html>

Controller

@Controller
@SessionAttributes(value = "")
public class MyController {

    @RequestMapping("session")
    public String session(Model model){
        Dog dog = new Dog();
        dog.setName("sessionName");
        dog.setColor("sessionColor");
        dog.setAge(10);
        model.addAttribute("dogs",dog);
        return "/result.jsp";
    }

    // model 传进来之前,会把session域里的数据放到model中。
    // 在 @ModelAttribute 里写的内容会覆盖session里的同名内容(“对象”覆盖)
    @ModelAttribute
    public void init(Model model){
        System.out.println("@ModelAttribute 自动调用");
        Dog dog = new Dog();
        dog.setName("initName");
        dog.setColor("initColor");
        model.addAttribute("dogs",dog);
    }

    @RequestMapping("first")
    public String show(@ModelAttribute("mydog") Dog mydog, Model model){
        System.out.println(model.asMap());
        // outPut:{dogs=Dog{name='initName', color='initColor', age=null}, mydog=Dog{name='小白', color='白色', age=null},……}
        return "/result.jsp";
    }
}

二、mvc:view-controller

当我们发送一个请求时,如果没有找到对应的mapping,则会对配置文件当中匹配 mvc:view-controller

请求发送页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>Title</title>
  </head>
  <body>
  <a href="${pageContext.request.contextPath}/session">发送请求</a>
  </body>
</html>

Controller

@Controller
public class MyController {

}

springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--注解扫描-->
    <context:component-scan base-package="com.ssm"/>

    <mvc:view-controller path="session" view-name="/result.jsp"/>
</beans>

注意点

使用时要添加:

<mvc:annotation-driven/>

如果没有添加,@Controller 中的 @RequestMapping 将不能使用。

请求发送页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>Title</title>
  </head>
  <body>
  <a href="${pageContext.request.contextPath}/session">发送请求</a>
  <a href="${pageContext.request.contextPath}/first">发送请求</a>
  </body>
</html>

Controller

@Controller
public class MyController {
    @RequestMapping("first")
    public String view(){
        return "/result.jsp";
    }
}

springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--注解扫描-->
    <context:component-scan base-package="com.ssm"/>

    <mvc:view-controller path="session" view-name="/result.jsp"/>
</beans>

点击第二个发送请求时,会报404错误

(1)默认情况下(不写 mvc:view-controller),DispatcherServlet (前端控制器)会自动注册以下三个类

0 = {HttpRequestHandlerAdapter@8252}
1 = {SimpleControllerHandlerAdapter@8253}
2 = {RequestMappingHandlerAdapter@8254}

RequestMappingHandlerAdapter 就是处理 @RequestMapping 的。

(2)写了 mvc:view-controller 后,DispatcherServlet (前端控制器)只会自动注册以下两个类

0 = {HttpRequestHandlerAdapter@8255}
1 = {SimpleControllerHandlerAdapter@8256}

缺少了 RequestMappingHandlerAdapter ,所以发送 @RequestMapping 的请求会报 404 未找到错误。

(3)添加了 <mvc:annotation-driven/> 后会自动注册那三个类。

三、mvc:annotation-driven

<mvc:annotation-driven /> 是一种简写形式

会自动注册三个Bean

  • RequestMappingHandlerMapping
  • RequestMappingHandlerAdapter
  • ExceptionHandlerExceptionResolver

并提供了:

  • 数据绑定支持,
  • @NumberFormatannotation支持,
  • @DateTimeFormat支持,
  • @Valid支持,读写XML的支持(JAXB),
  • 读写JSON的支持(Jackson)。

所以,一般我们都加上 <mvc:annotation-driven /> 。

四、SpringMVC 中的 form标签

简介

在使用SpringMVC的时候我们可以使用Spring封装的一系列表单标签,这些标签都可以访问到 ModelMap 中的内容。

作用

第一是它会自动的绑定来自Model中的一个属性值到当前form对应的实体对象;第二是它支持我们在提交表单的时候使用除GET和POST之外的其他方法进行提交,包括DELETE和PUT等

使用场景

当编辑时, 跳转到form表单页,传统模式要在跳转前先到数据库查询数据,然后进行表单数据回显。

使用form之前一定要保证有对应的bean,没有对应的bean时, 会自动以command为key到 request域中查询,当找不到的时候, 会报异常。

使用方式

User

package com.ssm.domain;

import lombok.Getter;
import lombok.Setter;

import java.util.Arrays;

@Setter @Getter
public class User {
    private Integer id;
    private String username;
    private String password;
    private String gender;
    private Integer age;
    private String[] hobby;
    private Pet pet;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", gender='" + gender + '\'' +
                ", age=" + age +
                ", hobby=" + Arrays.toString(hobby) +
                ", pet=" + pet +
                '}';
    }
}

Pet

package com.ssm.domain;

import lombok.Getter;
import lombok.Setter;

@Setter @Getter
public class Pet {
    private Integer id;
    private String name;

    public Pet() {
    }

    public Pet(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Pet{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

发送请求

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>Title</title>
  </head>
  <body>
  <a href="${pageContext.request.contextPath}/edit/2">发送更新请求</a>
  </body>
</html>

处理请求

@RequestMapping("edit/{id}")
public String view(@PathVariable Integer id, Model model){
    System.out.println(id);
    /* 模拟数据库查询,准备数据 */
    ArrayList<String> hobbyList = new ArrayList<>();
    hobbyList.add("篮球");
    hobbyList.add("足球");
    hobbyList.add("排球");
    hobbyList.add("乒乓球");
    model.addAttribute("hobbys", hobbyList);

    ArrayList<Pet> petList = new ArrayList<>();
    petList.add(new Pet(1,"狗"));
    petList.add(new Pet(2,"猫"));
    petList.add(new Pet(3,"鸟"));
    petList.add(new Pet(4,"猪"));
    model.addAttribute("pets",petList);


    User user = new User();
    // 文本框
    user.setId(id);
    user.setUsername("user1");
    user.setPassword("145263");
    user.setAge(20);
    // 单选框
    user.setGender("男");
    // 复选框
    String[] hobby = new String[]{"篮球","足球","排球"};
    user.setHobby(hobby);
    // 下拉框
    user.setPet(new Pet(2,"猫"));

    model.addAttribute("user",user);
    return "/update.jsp";
}

创建表单页,引入标签库

引入标签库

<%@ taglib uri="http://www.springframework.org/tags/form" prefix="fm" %>

update.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="fm" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>更新界面</h1>
    <fm:form modelAttribute="user" action="${pageContext.request.contextPath}/update">
        <p>用户Id : <fm:input path="id"/></p>
        <p>用户名 : <fm:input path="username"/></p>
        <p>密码 : <fm:input path="password"/></p>
        <p>年龄 : <fm:input path="age"/></p>
        <p>性别 : <fm:radiobutton path="gender" value="男" label="男"/>
            <fm:radiobutton path="gender" value="女" label="女"/></p>
        <p>爱好 : <fm:checkboxes path="hobby" items="${hobbys}"/></p>
        <p>宠物 : <fm:select path="pet.id" items="${pets}" itemValue="id" itemLabel="name"/></p>
        <p><input type="submit" value="更新"></p>
    </fm:form>
</body>
</html>

处理请求

@RequestMapping("update")
public String update(User user){
    System.out.println(user);
    return "result.jsp";
}

result.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>结果页</h3>
    ${requestScope.user}
</body>
</html>

五、服务器表单校验

为什么后端要做表单的校验,如果只使用前端校验的话,当浏览器把JS给禁用掉,就校验不了啦

JSR

JSR 303 是 Java 为 Bean 数据合法性校验提供的标准框架,它已经包含在 JavaEE 6.0 中 ,JSR 303 通过在 Bean 属性上标注类似于 @NotNull、@Max 等标准的注解,指定校验规则,并通过标准的验证接口对 Bean 进行验证。

Hibernate Validator

Hibernate Validator 是 JSR 303 的一个参考实现,除支持所有标准的校验注解外,它还支持其它的扩展注解。

使用时需要导入jar包

+ Hibernate-Validator
    - classmate.jar
    - hibernate-validator-5.jar
    - hibernate-validator-annotation-processor-5.jar
    - jboss-logging-3.1.1.jar
    - validation-api-1.1.0.jar

常用校验规则

Bean Validation 中内置的约束

约束注解 说明
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max=, min=) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(regex=,flag=) 被注释的元素必须符合指定的正则表达式

Hibernate Validator 附加的约束

约束注解 说明
@NotBlank(message =) 验证字符串非null,且长度必须大于0
@Email 被注释的元素必须是电子邮箱地址
@Length(min=,max=) 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range(min=,max=,message=) 被注释的元素必须在合适的范围内

使用

① 导入jar包,在配置文件当中写上

<mvc:annotation-driven/>

② 在模型当中添加对应的校验规则

package com.ssm.domain;

import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.NotBlank;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.util.Arrays;

@Setter @Getter
public class User {
    @NotNull(message = "ID不能为空")
    private Integer id;
    @NotBlank(message = "用户名不能为空")
    private String username;
    @NotBlank(message = "密码不能为空")
    private String password;
    private String gender;
    @Max(value = 200, message = "年龄不正确")
    @Min(value = 0, message = "年龄不正确")
    private Integer age;
    private String[] hobby;
    private Pet pet;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", gender='" + gender + '\'' +
                ", age=" + age +
                ", hobby=" + Arrays.toString(hobby) +
                ", pet=" + pet +
                '}';
    }
}

③ 在处理器方法的参数标记@valid注解即可

@RequestMapping("update")
public String update(@Valid User user, BindingResult result) {
    System.out.println(user);
    List<FieldError> fieldErrors = result.getFieldErrors();
    for (FieldError fieldError : fieldErrors) {
        System.out.println(fieldError.getField() + " : " + fieldError.getDefaultMessage());
    }
    return "result.jsp";
}

④ 错误信息页面回显

(1)使用form标签
<fm:errors path=""/>

请求发送页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>Title</title>
  </head>
  <body>
  <a href="${pageContext.request.contextPath}/edit/2">发送更新请求</a>
  </body>
</html>

user

package com.ssm.domain;

import lombok.Getter;
import lombok.Setter;
import org.hibernate.validator.constraints.NotBlank;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.util.Arrays;

@Setter @Getter
public class User {
    @NotNull(message = "ID不能为空")
    private Integer id;
    @NotBlank(message = "用户名不能为空")
    private String username;
    @NotBlank(message = "密码不能为空")
    private String password;
    private String gender;
    @Max(value = 200, message = "年龄不正确")
    @Min(value = 0, message = "年龄不正确")
    private Integer age;
    private String[] hobby;
    private Pet pet;

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", gender='" + gender + '\'' +
                ", age=" + age +
                ", hobby=" + Arrays.toString(hobby) +
                ", pet=" + pet +
                '}';
    }
}

Controller

package com.ssm.web.controller;

import com.ssm.domain.Pet;
import com.ssm.domain.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;

@Controller
public class MyController {
    ArrayList<String> hobbyList;
    ArrayList<Pet> petList;

    @RequestMapping("edit/{id}")
    public String view(@PathVariable Integer id, Model model) {
        System.out.println(id);
        /* 模拟数据库查询,准备数据 */
        hobbyList = new ArrayList<>();
        hobbyList.add("篮球");
        hobbyList.add("足球");
        hobbyList.add("排球");
        hobbyList.add("乒乓球");
        model.addAttribute("hobbys", hobbyList);

        petList = new ArrayList<>();
        petList.add(new Pet(1, "狗"));
        petList.add(new Pet(2, "猫"));
        petList.add(new Pet(3, "鸟"));
        petList.add(new Pet(4, "猪"));
        model.addAttribute("pets", petList);


        User user = new User();
        // 文本框
        user.setId(id);
        user.setUsername("user1");
        user.setPassword("145263");
        user.setAge(20);
        // 单选框
        user.setGender("男");
        // 复选框
        String[] hobby = new String[]{"篮球", "足球", "排球"};
        user.setHobby(hobby);
        // 下拉框
        user.setPet(new Pet(2, "猫"));

        model.addAttribute("user", user);
        return "/update.jsp";
    }

    @RequestMapping("update")
    public String update(@Valid User user, BindingResult result, Model model) {
        System.out.println(user);
        if (result.getErrorCount() != 0){
            List<FieldError> fieldErrors = result.getFieldErrors();
            for (FieldError fieldError : fieldErrors) {
                System.out.println(fieldError.getField() + " : " + fieldError.getDefaultMessage());
            }
            model.addAttribute("hobbys", hobbyList);
            model.addAttribute("pets", petList);

            return "/update.jsp";
        }

        return "/result.jsp";
    }
}

update.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="fm" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>更新界面</h1>
    <fm:form modelAttribute="user" action="${pageContext.request.contextPath}/update">
        <p>用户Id : <fm:input path="id"/> <fm:errors path="id" cssStyle="color: red"/></p>
        <p>用户名 : <fm:input path="username"/> <fm:errors path="username" cssStyle="color: red"/> </p>
        <p>密码 : <fm:input path="password"/> <fm:errors path="password" cssStyle="color: red"/></p>
        <p>年龄 : <fm:input path="age"/> <fm:errors path="age" cssStyle="color: red"/></p>
        <p>性别 : <fm:radiobutton path="gender" value="男" label="男"/>
            <fm:radiobutton path="gender" value="女" label="女"/></p>
        <p>爱好 : <fm:checkboxes path="hobby" items="${hobbys}"/></p>
        <p>宠物 : <fm:select path="pet.id" items="${pets}" itemValue="id" itemLabel="name"/></p>
        <p><input type="submit" value="更新"></p>
    </fm:form>
</body>
</html>

结果页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h3>结果页</h3>
    ${requestScope.user}
</body>
</html>
(2)使用原始表单错误信息写到Model中

原文地址:https://www.cnblogs.com/xzh0717/p/11713484.html