Spring 表单验证

1 概述
验证可以避免用户输入不规范的数据,在数据过滤的一道门。这道门有前端验证和后台验证,前端验证使用JavaScript脚本,后台验证使用Java EE验证规范JSR 303。
在这里插入图片描述

2 工程结构
在这里插入图片描述

为避免反复手动启动程序,我们引入热启动。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>


4.0.0

org.springframework.boot
spring-boot-starter-parent
2.1.6.RELEASE


com.wangshenghua
spring-thymeleaf-form
0.0.1-SNAPSHOT
spring-thymeleaf-form
Demo project for Spring Boot

<properties>
    <java.version>1.8</java.version>
    <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
     
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>    
     
     
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
spring-boot-devtools模块可以让工程是源码和配置变更后自动重启嵌入式tomcat。

3 模型层
JSR 303验证规则放置于数据模型层,以注释的形式加入。

User.java

package com.wangshenghua.model;

import javax.validation.constraints.Email;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class User {

@NotNull
private long id;

@NotNull
@Size(min = 2, max = 30,message="姓名在2~30个字符之间")
private String name;

@NotNull
@Min(message="年龄至少15岁",value=15)
private Integer age;

@NotEmpty
@Email(message="邮箱格式不对")
private String email;

public User() {
}

public User(@NotNull long id, @NotNull @Size(min = 2, max = 30) String name, @NotNull @Min(15) Integer age,
        String email) {
    this.id = id;
    this.name = name;
    this.age = age;
    this.email = email;
}

public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getEmail() {
    return email;
}

public void setEmail(String email) {
    this.email = email;
}

public Integer getAge() {
    return age;
}

public void setAge(Integer age) {
    this.age = age;
}

}
常见的验证注释有:

验证规则 说明
@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(value) 被注释的元素必须符合指定的正则表达式
@Email 被注释的元素必须是电子邮箱地址
@Length 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range 被注释的元素必须在合适的范围内
4 数据访问层
数据访问层采用List模拟数据库。

UserDao.java

package com.wangshenghua.dao;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Repository;

import com.wangshenghua.model.User;

@Repository
public class UserDao {

private static List<User> users = new ArrayList<User>();
// 使用List当容器保存数据,来代替数据库

static {
    users.add(new User(1, "黄志燕", 17, "ssss@qq.com"));
    users.add(new User(2, "侯慧聪", 19, "hhhh@qq.com"));
    users.add(new User(3, "王广宏", 15, "gggg@qq.com"));
}

public long getMaxId() {
    long id = 0;
    for (User user : users) {
        if (user.getId() > id)
            id = user.getId();
    }

    return id + 1;
}

public User getUser(long id) {
    User user = null;
    for (User u : users) {
        if (u.getId() == id) {
            user = u;
            break;
        }
    }

    return user;
}

public void update(User user, long id) {
    for (User u : users) {
        if (u.getId() == id) {
            u.setName(user.getName());
            u.setEmail(user.getEmail());
            u.setAge(user.getAge());
            break;
        }
    }
}

public void delete(long id) {
    for (User u : users) {
        if (u.getId() == id) {
            users.remove(u);
            break;
        }
    }
}

public List<User> getUsers() {
    return users;
}

}
@Repository注释表示此类是一个数据访问对象dao。Spring对各MVC各层注释有着规范的要求:

控制器层 @Controller
服务层 @Service
数据访问层 @Repository
在类前加入这些注释后,Spring工程一启动,扫描这些有注释的类,并实例化到内存里。

5 控制器
UserController.java

package com.wangshenghua.controller;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;

import com.wangshenghua.dao.UserDao;
import com.wangshenghua.model.User;

@Controller
public class UserController {

@Autowired
private UserDao userDao;


/** 控制器的方法 **/

@GetMapping("/")
public String index() {
    return "redirect:/allUser";
}

@GetMapping("/allUser")
public String allUser(Model model) {
    model.addAttribute("users", userDao.getUsers());
    return "list-user";
}

@GetMapping("/adduser")
public String showAddUserForm(Model model) {
    User user = new User();
    user.setId(userDao.getMaxId());
    model.addAttribute("user", user);
    return "add-user";
}

@PostMapping("/adduser")
public String addUser(@Valid User user, BindingResult bindingResult) {

    if (bindingResult.hasErrors()) {
        return "add-user";
    }

    userDao.getUsers().add(user);

    return "redirect:/allUser";
}

@GetMapping("/edit/{id}") // {id}是占位符
public String showUpdateForm(@PathVariable("id") long id, Model model) { // @PathVariable 路径变量
    User user = userDao.getUser(id);
    model.addAttribute("user", user);
    return "update-user";
}

@PostMapping("/update/{id}")
public String updateUser(@PathVariable("id") long id, @Valid User user, BindingResult bindingResult) {
    if (bindingResult.hasErrors()) {
        return "update-user";
    }
    userDao.update(user, id);
    return "redirect:/allUser";
}

@GetMapping("/delete/{id}")
public String deleteUser(@PathVariable("id") long id, Model model) {
    userDao.delete(id);
    return "redirect:/allUser";
}

}
@Autowired注释将内存里已经实例好的对象引入进来,并赋值给变量。

private UserDao userDao; 如变量userDao指向一个引用,引用内存中的UserDao实例。

这就是Spring中著名的控制反转和依赖注入。之前是由驱动类UserController负责实例化UserDao;现在Spring不是这样玩了,由Spring容器在启动时扫描类上的注释,并实例化到内存,控制权不在驱动类手里,在Spring手里;驱动类要依赖某一个类,只需写注释@Autowired声明一个变量就OK。

在方法addUser里有一个参数User user前,有一个注释@Valid,用于启动数据模型User.java类中JSR 303验证规则,它将对视图层传递过来的User对象进行验证。

验证结果又放置到BindingResult对象里,BindingResult的hasErrors()方法发现有错误,则返回到视图层。

6 视图层
add-user.html

添加用户
    <p th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></p>
     
     
    <label for="age">年龄</label>
    <input type="text" th:field="*{age}" id="age" placeholder="age">
     
    <p th:if="${#fields.hasErrors('age')}" th:errors="*{age}"></p>
     
     
    <label for="email">邮箱</label>
    <input type="text" th:field="*{email}" id="email" placeholder="Email">
    <p th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></p>
     
     
    <input type="submit" value="保存">  
</form>
视图层采用thymeleaf技术,它先判断th:if="${#fields.hasErrors('name')}" 如果有错误,则显示错误消息th:errors="*{name}"

7 总结
本节课程使用Spring Boot和thymeleaf技术实现表单验证功能 world程序。

演示了如何在数据模型层User.java中添加JSR 303验证规则,及在控制器如何启用验证,及视图层如何展示验证的消息提示。

同时简要介绍了Spring的控制反转和依赖注释的使用。

学员位重点掌握表单验证和控制反转和依赖注释的使用。

本节课程源码已经上传到github,可以前往下载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值