User-Profile-Image
hankin
  • 5
  • Java
  • Kotlin
  • Spring
  • Web
  • SQL
  • MegaData
  • More
  • Experience
  • Enamiĝu al vi
  • 分类
    • Zuul
    • Zookeeper
    • XML
    • WebSocket
    • Web Notes
    • Web
    • Vue
    • Thymeleaf
    • SQL Server
    • SQL Notes
    • SQL
    • SpringSecurity
    • SpringMVC
    • SpringJPA
    • SpringCloud
    • SpringBoot
    • Spring Notes
    • Spring
    • Servlet
    • Ribbon
    • Redis
    • RabbitMQ
    • Python
    • PostgreSQL
    • OAuth2
    • NOSQL
    • Netty
    • MySQL
    • MyBatis
    • More
    • MinIO
    • MegaData
    • Maven
    • LoadBalancer
    • Kotlin Notes
    • Kotlin
    • Kafka
    • jQuery
    • JavaScript
    • Java Notes
    • Java
    • Hystrix
    • Git
    • Gateway
    • Freemarker
    • Feign
    • Eureka
    • ElasticSearch
    • Docker
    • Consul
    • Ajax
    • ActiveMQ
  • 页面
    • 归档
    • 摘要
    • 杂图
    • 问题随笔
  • 友链
    • Spring Cloud Alibaba
    • Spring Cloud Alibaba - 指南
    • Spring Cloud
    • Nacos
    • Docker
    • ElasticSearch
    • Kotlin中文版
    • Kotlin易百
    • KotlinWeb3
    • KotlinNhooo
    • 前端开源搜索
    • Ktorm ORM
    • Ktorm-KSP
    • Ebean ORM
    • Maven
    • 江南一点雨
    • 江南国际站
    • 设计模式
    • 熊猫大佬
    • java学习
    • kotlin函数查询
    • Istio 服务网格
    • istio
    • Ktor 异步 Web 框架
    • PostGis
    • kuangstudy
    • 源码地图
    • it教程吧
    • Arthas-JVM调优
    • Electron
    • bugstack虫洞栈
    • github大佬宝典
    • Sa-Token
    • 前端技术胖
    • bennyhuo-Kt大佬
    • Rickiyang博客
    • 李大辉大佬博客
    • KOIN
    • SQLDelight
    • Exposed-Kt-ORM
    • Javalin—Web 框架
    • http4k—HTTP包
    • 爱威尔大佬
    • 小土豆
    • 小胖哥安全框架
    • 负雪明烛刷题
    • Kotlin-FP-Arrow
    • Lua参考手册
    • 美团文章
    • Java 全栈知识体系
    • 尼恩架构师学习
    • 现代 JavaScript 教程
    • GO相关文档
    • Go学习导航
    • GoCN社区
    • GO极客兔兔-案例
    • 讯飞星火GPT
    • Hollis博客
    • PostgreSQL德哥
    • 优质博客推荐
    • 半兽人大佬
    • 系列教程
    • PostgreSQL文章
    • 云原生资料库
    • 并发博客大佬
Help?

Please contact us on our email for need any support

Support
    首页   ›   Spring   ›   SpringMVC   ›   正文
SpringMVC

SpringMVC笔记11—服务端数据校验

2020-04-05 21:31:50
723  0 1
参考目录 隐藏
1) 为什么需要服务器端校验
2) 1.普通校验
3) 2.分组校验
4) 3.校验注解

阅读完需:约 9 分钟

为什么需要服务器端校验

最早的校验,就是服务端校验。早期的网站,用户输入一个邮箱地址,校验邮箱地址需要将地址发送到服务端,服务端进行校验,校验成功后,给前端一个响应。有了JavaScript,校验工作可以放在前端去执行。那么为什么还需要服务端校验呢? 因为前端传来的数据不可信。前端很容易获取都后端的数据接口,如果有人绕过页面,就会出现非法数据,所以服务端也要数据校验。

Spring 支持 JSR-303 验证框架,JSR-303 是 JAVA EE 6 中的一项子规范,叫做 Bean Validation,官方参考实现是 Hibernate Validator(与Hibernate ORM 没有关系),JSR-303 用于对 Java Bean 中的字段的值进行验证。

1.普通校验

普通校验,是这里最基本的用法。

首先,我们需要加入校验需要的依赖:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.1.0.Final</version>
</dependency>

接下来,在 SpringMVC 的配置文件中配置校验的 Bean:

<bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" id="validatorFactoryBean">
    <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
</bean>
<mvc:annotation-driven validator="validatorFactoryBean"/>

配置时,提供一个 LocalValidatorFactoryBean 的实例,然后 Bean 的校验使用 HibernateValidator。

这样,配置就算完成了。

接下来,我们提供一个添加学生的页面:

<form action="/addstudent" method="post">
    <table>
        <tr>
            <td>学生编号:</td>
            <td><input type="text" name="id"></td>
        </tr>
        <tr>
            <td>学生姓名:</td>
            <td><input type="text" name="name"></td>
        </tr>
        <tr>
            <td>学生邮箱:</td>
            <td><input type="text" name="email"></td>
        </tr>
        <tr>
            <td>学生年龄:</td>
            <td><input type="text" name="age"></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="提交">
            </td>
        </tr>
    </table>
</form>

在这里需要提交的数据中,假设学生编号不能为空,学生姓名长度不能超过 10 且不能为空,邮箱地址要合法,年龄不能超过 150。那么在定义实体类的时候,就可以加入这个判断条件了。

public class Student {
    @NotNull
    private Integer id;
    @NotNull
    @Size(min = 2,max = 10)
    private String name;
    @Email
    private String email;
    @Max(150)
    private Integer age;

    public String getEmail() {
        return email;
    }

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

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

    public Integer getAge() {
        return age;
    }

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

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

在这里:

  • @NotNull 表示这个字段不能为空
  • @Size 中描述了这个字符串长度的限制
  • @Email 表示这个字段的值必须是一个邮箱地址
  • @Max 表示这个字段的最大值

定义完成后,接下来,在 Controller 中定义接口:

@Controller
public class StudentController {
    @RequestMapping("/addstudent")
    @ResponseBody
    public void addStudent(@Validated Student student, BindingResult result) {
        if (result != null) {
            //校验未通过,获取所有的异常信息并展示出来
            List<ObjectError> allErrors = result.getAllErrors();
            for (ObjectError allError : allErrors) {
                System.out.println(allError.getObjectName()+":"+allError.getDefaultMessage());
            }
        }
    }
}

在这里:

  • @Validated 表示 Student 中定义的校验规则将会生效
  • BindingResult 表示出错信息,如果这个变量不为空,表示有错误,否则校验通过。

接下来就可以启动项目了。访问 jsp 页面,然后添加 Student,查看校验规则是否生效。

默认情况下,打印出来的错误信息时系统默认的错误信息,这个错误信息,我们也可以自定义。自定义方式如下:

由于 properties 文件中的中文会乱码,所以需要我们先修改一下 IDEA 配置,点 File–>Settings->Editor–>File Encodings,如下:

然后定义错误提示文本,在 resources 目录下新建一个 MyMessage.properties 文件,内容如下:

student.id.notnull=id 不能为空
student.name.notnull=name 不能为空
student.name.length=name 最小长度为 2 ,最大长度为 10
student.email.error=email 地址非法
student.age.error=年龄不能超过 150

接下来,在 SpringMVC 配置中,加载这个配置文件:

<bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" id="validatorFactoryBean">
    <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
    <property name="validationMessageSource" ref="bundleMessageSource"/>
</bean>
<bean class="org.springframework.context.support.ReloadableResourceBundleMessageSource" id="bundleMessageSource">
    <property name="basenames">
        <list>
            <value>classpath:MyMessage</value>
        </list>
    </property>
    <property name="defaultEncoding" value="UTF-8"/>
    <property name="cacheSeconds" value="300"/>
</bean>
<mvc:annotation-driven validator="validatorFactoryBean"/>

最后,在实体类上的注解中,加上校验出错时的信息:

public class Student {
    @NotNull(message = "{student.id.notnull}")
    private Integer id;
    @NotNull(message = "{student.name.notnull}")
    @Size(min = 2,max = 10,message = "{student.name.length}")
    private String name;
    @Email(message = "{student.email.error}")
    private String email;
    @Max(value = 150,message = "{student.age.error}")
    private Integer age;

    public String getEmail() {
        return email;
    }

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

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

    public Integer getAge() {
        return age;
    }

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

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

配置完成后,如果校验再出错,就会展示我们自己的出错信息了。

2.分组校验

由于校验规则都是定义在实体类上面的,但是,在不同的数据提交环境下,校验规则可能不一样。例如,用户的 id 是自增长的,添加的时候,可以不用传递用户 id,但是修改的时候则必须传递用户 id,这种情况下,就需要使用分组校验。

分组校验,首先需要定义校验组,所谓的校验组,其实就是空接口:

public interface ValidationGroup1 {
}
public interface ValidationGroup2 {
}

然后,在实体类中,指定每一个校验规则所属的组:

public class Student {
    @NotNull(message = "{student.id.notnull}",groups = ValidationGroup1.class)
    private Integer id;
    @NotNull(message = "{student.name.notnull}",groups = {ValidationGroup1.class, ValidationGroup2.class})
    @Size(min = 2,max = 10,message = "{student.name.length}",groups = {ValidationGroup1.class, ValidationGroup2.class})
    private String name;
    @Email(message = "{student.email.error}",groups = {ValidationGroup1.class, ValidationGroup2.class})
    private String email;
    @Max(value = 150,message = "{student.age.error}",groups = {ValidationGroup2.class})
    private Integer age;

    public String getEmail() {
        return email;
    }

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

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

    public Integer getAge() {
        return age;
    }

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

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

在 group 中指定每一个校验规则所属的组,一个规则可以属于一个组,也可以属于多个组。

最后,在接收参数的地方,指定校验组:

@Controller
public class StudentController {
    @RequestMapping("/addstudent")
    @ResponseBody
    public void addStudent(@Validated(ValidationGroup2.class) Student student, BindingResult result) {
        if (result != null) {
            //校验未通过,获取所有的异常信息并展示出来
            List<ObjectError> allErrors = result.getAllErrors();
            for (ObjectError allError : allErrors) {
                System.out.println(allError.getObjectName()+":"+allError.getDefaultMessage());
            }
        }
    }
}

配置完成后,属于 ValidationGroup2 这个组的校验规则,才会生效。

3.校验注解

校验注解,主要有如下几种:

  • @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=) 被注解的元素必须符合指定的正则表达式
  • @NotBlank(message =) 验证字符串非 null,且长度必须大于0
  • @Email 被注解的元素必须是电子邮箱地址
  • @Length(min=,max=) 被注解的字符串的大小必须在指定的范围内
  • @NotEmpty 被注解的字符串的必须非空
  • @Range(min=,max=,message=) 被注解的元素必须在合适的范围内

如本文“对您有用”,欢迎随意打赏作者,让我们坚持创作!

1 打赏
Enamiĝu al vi
不要为明天忧虑.因为明天自有明天的忧虑.一天的难处一天当就够了。
543文章 68评论 294点赞 594444浏览

随机文章
Java面向对象(工厂代理)
5年前
SpringBoot—MockMvc单元测试
5年前
SpringBoot—Gson的使用
5年前
HttpMessageConverter—关于一个字符串到java对象的转化
5年前
SpringCloud—Hystrix(二)自定义请求命令
5年前
博客统计
  • 日志总数:543 篇
  • 评论数目:68 条
  • 建站日期:2020-03-06
  • 运行天数:1927 天
  • 标签总数:23 个
  • 最后更新:2024-12-20
Copyright © 2025 网站备案号: 浙ICP备20017730号 身体没有灵魂是死的,信心没有行为也是死的。
主页
页面
  • 归档
  • 摘要
  • 杂图
  • 问题随笔
博主
Enamiĝu al vi
Enamiĝu al vi 管理员
To be, or not to be
543 文章 68 评论 594444 浏览
测试
测试
看板娘
赞赏作者

请通过微信、支付宝 APP 扫一扫

感谢您对作者的支持!

 支付宝 微信支付