[华为云在线课程][SpringMVC入门][五][文件上传与校验][学习笔记]
1.文件上传
SpringMVC中对文件上传做了封装,因此我们可以更方便实现文件上传功能。从Spring3.1开始,对于文件上传,提供了两个处理器:CommonsMultipartResolver和StandardServletMultipartResolver。
1.1.CommonsMultipartResolver
这个处理器兼容性较好,可以兼容Servlet3.0以前的版本,但依赖commons-fileupload这个第三方工具,所以如果要使用的话,一定记得添加commons-fileupload依赖。
- 在pom.xml中添加commons-fileupload依赖:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
- 在SpringMVC配置文件中配置MultipartResolver:
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver"/>
注意这个Bena一定要有id,并且id必须是multipartResolver。
- 创建jsp页面
<%--
Created by IntelliJ IDEA.
User: John
Date: 2022/7/19/0019
Time: 9:36
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>FileUpload</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="上传">
</form>
</body>
</html>
注意文件上传是用POST请求,enctype一定是multipart/form-data。
- 开发文件上传接口
package org.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
@Controller
public class FileUploadController {
@RequestMapping("/fileupload")
public String fileupload() {
return "fileUpload";
}
//声明日期格式,注意最后一个/千万不要漏掉
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("/yyyy/MM/dd/");
@RequestMapping("/upload")
@ResponseBody
public String upload(MultipartFile file, HttpServletRequest request) {
//对当前日期进行格式化
String format = simpleDateFormat.format(new Date());
//设置保存路径
String realPath = request.getServletContext().getRealPath("/img") + format;
//如果不存在则生成
File folder = new File(realPath);
if (!folder.exists()) {
folder.mkdirs();
}
//获取当前文件名作为旧名字
String oldName = file.getOriginalFilename();
//使用UUID并截取旧名字后缀进行拼接形成新名字
String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
try {
file.transferTo(new File(folder, newName));
String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/img" + format + newName;
return url;
} catch (IOException e) {
e.printStackTrace();
}
return "failed";
}
}
在这个方法中,一共做了四件事:
- 解决文件保存路径问题,将其保存在项目运行目录下的img目录下,然后利用日期继续分类。
- 处理文件名问题,使用UUID作为新的文件名字,替换旧的文件名,防止文件名冲突。
- 保存文件。
- 生成文件访问路径。
注意:SpringMVC默认是自动拦截静态资源的,意味着上传的图片无法访问。所以,还需要我们在SpringMVC的配置文件中再添加如下配置:
<mvc:resources mapping="/**" location="/"/>
完成之后就可以运行项目了。
当然,默认的配置不一定满足我们的需求,还可以自己手动配置文件上传大小等:
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
<!--默认编码-->
<property name="defaultEncoding" value="UTF-8"/>
<!--上传的总文件大小-->
<property name="maxUploadSize" value="1048576"/>
<!--上传的单文件大小-->
<property name="maxUploadSizePerFile" value="1048576"/>
<!--内存中的最大数据量,超过这个数据量,数据开始写入磁盘-->
<property name="maxInMemorySize" value="4096"/>
<!--临时目录,超过maxInMemorySize配置的大小后,数据开始写入临时目录,等全部上传完毕后,再将数据合并到正式的文件上传目录-->
<property name="uploadTempDir" value="file:///D:\\tmp"/>
</bean>
1.2.StandardServletMultipartResolver
这个处理器兼容性差一点,适用于Servlet3.0之后的版本,不依赖第三方工具,使用它可以直接做文件上传。
首先在SpringMVC配置文件中配置Bean:
<bean class="org.springframework.web.multipart.support.StandardServletMultipartResolver" id="multipartResolver"/>
这里Bean的名字依然叫multipartResolver。完成配置后需要注意的是,这个Bean无法直接配置上传文件大小等限制。要在Web.xml中进行配置(即使不需要限制文件上传大小,也需要在Web.xml中配置multipart-config):
<!--springmvc-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<multipart-config>
<!--文件保存的临时目录,这个目录系统不会主动创建-->
<location>D:\\temp</location>
<!--上传的单个文件大小-->
<max-file-size>1048576</max-file-size>
<!--上传的总文件大小-->
<max-request-size>1048566</max-request-size>
<!--内存中保存的文件最大大小-->
<file-size-threshold>4096</file-size-threshold>
</multipart-config>
</servlet>
配置完成后就可以进行文件上传了,其他部分跟上例是一样的。
1.3.多文件上传
多文件上传分为两种,一种是key相同的文件,另一种是key不同的文件。
1.3.1.key相同的文件
key相同的前端页面:
<%--
Created by IntelliJ IDEA.
User: John
Date: 2022/7/19/0019
Time: 11:59
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>key相同文件上传</title>
</head>
<body>
<form action="/upload2" method="post" enctype="multipart/form-data">
<input type="file" name="files" multiple>
<input type="submit" value="上传">
</form>
</body>
</html>
主要是input节点多了个multiple属性。后端用一个数组来接收文件即可:
package org.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
@Controller
public class FileUploadController2 {
@RequestMapping("/fileupload2")
public String fileupload() {
return "fileUpload2";
}
//声明日期格式,注意最后一个/千万不要漏掉
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("/yyyy/MM/dd/");
@RequestMapping("/upload2")
@ResponseBody
public void upload2(MultipartFile[] files, HttpServletRequest request) {
//对当前日期进行格式化
String format = simpleDateFormat.format(new Date());
//设置保存路径
String realPath = request.getServletContext().getRealPath("/img") + format;
//如果不存在则生成
File folder = new File(realPath);
if (!folder.exists()) {
folder.mkdirs();
}
try {
for (MultipartFile file : files) {
//获取当前文件名作为旧名字
String oldName = file.getOriginalFilename();
//使用UUID并截取旧名字后缀进行拼接形成新名字
String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
file.transferTo(new File(folder, newName));
String url = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/img" + format + newName;
System.out.println(url);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
1.3.2.key不同的文件
key不同的文件前端定义如下:
<%--
Created by IntelliJ IDEA.
User: John
Date: 2022/7/19/0019
Time: 13:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>fileUpload3</title>
</head>
<body>
<form action="/upload3" method="post" enctype="multipart/form-data">
<input type="file" name="file1">
<input type="file" name="file2">
<input type="submit" value="上传">
</form>
</body>
</html>
这种情况下,在后端用不同的变量来接收:
package org.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
@Controller
public class FileUploadController3 {
@RequestMapping("/fileupload3")
public String fileupload() {
return "fileUpload3";
}
//声明日期格式,注意最后一个/千万不要漏掉
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("/yyyy/MM/dd/");
@RequestMapping("/upload3")
@ResponseBody
public void upload2(MultipartFile file1, MultipartFile file2, HttpServletRequest request) {
//对当前日期进行格式化
String format = simpleDateFormat.format(new Date());
//设置保存路径
String realPath = request.getServletContext().getRealPath("/img") + format;
//如果不存在则生成
File folder = new File(realPath);
if (!folder.exists()) {
folder.mkdirs();
}
try {
//获取当前文件名作为旧名字
String oldName = file1.getOriginalFilename();
//使用UUID并截取旧名字后缀进行拼接形成新名字
String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
file1.transferTo(new File(folder, newName));
String url1 = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/img" + format + newName;
System.out.println(url1);
//获取当前文件名作为旧名字
String oldName2 = file2.getOriginalFilename();
//使用UUID并截取旧名字后缀进行拼接形成新名字
String newName2 = UUID.randomUUID().toString() + oldName2.substring(oldName2.lastIndexOf("."));
file2.transferTo(new File(folder, newName2));
String url2 = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/img" + format + newName2;
System.out.println(url2);
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.异常处理
项目中,可能会抛出多个异常,不可以直接将异常的堆栈信息展示给用户,有两个原因:
- 用户体验不好。
- 非常不安全。
所以我们要进行自定义异常处理,SpringMVC中,针对全局异常也提供了相应的解决方案,主要是通过@ControllerAdvice和@ExceptionHandler两个注解来处理的。
以一个文件上传大小超出限制为例,自定义异常只需要提供一个异常处理类即可:
package org.example.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
//一个增强版的Controller
@ControllerAdvice
public class MyException {
@ExceptionHandler(Exception.class)
public ModelAndView fileuploadException(Exception e) {
ModelAndView error = new ModelAndView("error");
error.addObject("error", e.getMessage());
return error;
}
}
- @ControllerAdvice表示这是一个增强版的Controller,用于全局数据处理。
- @ExceptionHandler表示这是一个异常处理方法,这个注解的参数,表示需要拦截的异常,参数为Exception表示拦截所有异常,这里也可以具体到某一个异常,如果具体到某一个异常,那么发生了其他异常则不会被拦截到。
- 异常方法的定义,和Controller中方法的定义一样,可以返回ModelAndView,也可以返回String或者void。
结果展示
以下代码专门拦截处理文件上传异常,和其他异常没有关系,其他异常不会进入到这个自定义异常处理的方法来。
package org.example.exception;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice
public class MyUploadException {
@ExceptionHandler(MaxUploadSizeExceededException.class)
public ModelAndView fileuploadException(MaxUploadSizeExceededException e) {
ModelAndView error = new ModelAndView("error");
error.addObject("error", e.getMessage());
return error;
}
}
3.数据校验
B/S系统中对http请求数据的校验多数在客户端进行,这也是出于简单及用户体验上考虑,但是在一些安全性要求高的系统中服务端校验是不可缺少的,实际上,几乎所有的系统,凡是涉及到数据校验,都需要在服务端进行二次校验。为什么要在服务端进行二次校验呢?这就需要我们理解客户端校验和服务端校验各自的目的。
- 客户端校验,我们主要是为了提高用户体验,例如用户输入一个邮箱地址,要校验这个邮箱地址是否合法,这样没必要发送到服务端校验,直接在前端用JavaScript继续校验即可。但前端校验无法替代后端校验,前端校验可以有效提高用户体验,但无法确保数据完整性,因为在B/S架构中,用户可以方便拿到请求地址,然后直接发送请求来传递非法参数。
- 服务端校验,虽然用户体验不好,但可以有效保证数据安全与完整性。
- 实际项目中,两个一起用比较好。
Spring支持JSR-303验证框架,JSR-303是Java EE 6中的一项子规范,叫做Bean Validation,官方参考实现是Hibernate Validator(与Hibernate ORM没有关系哈😅),JSR-303用于对Java Bean中的字段的值进行验证。
3.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。
提供一个添加学生的页面:
<%--
Created by IntelliJ IDEA.
User: John
Date: 2022/7/19/0019
Time: 15:33
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>一个添加学生的页面</title>
</head>
<body>
<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="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>
</body>
</html>
在这里需要提交的数据中,假设学生编号不能为空,学生姓名长度不能超过10且不能为空,邮箱地址要合法,年龄不能超过200。在定义实体类的时候就可以将限制条件加入。
package org.example.model;
import javax.validation.constraints.Email;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public class Student1 {
@NotNull
private Integer id;
@NotNull
@Size(min = 2,max = 10)
private String name;
@Email
private String email;
@Max(200)
private Integer age;
public Student1() {
}
public Student1(@NotNull Integer id, @NotNull @Size(min = 2, max = 10) String name, @Email String email, @Max(200) Integer age) {
this.id = id;
this.name = name;
this.email = email;
this.age = age;
}
@Override
public String toString() {
return "Student1{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", 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;
}
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;
}
}
- @NotNull:表示这个字段不能为空。
- @Size:表示字符串长度限制。
- @Email:表示字段值必须是一个邮箱地址。
- @Max:表示字段最大值。
然后在Controller中定义接口:
package org.example.controller;
import org.example.model.Student1;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
public class Student1Controller {
@RequestMapping("/addstu1")
public String addstudent() {
return "addStudent1";
}
@RequestMapping("/addstudent")
@ResponseBody
public void addStudent(@Validated Student1 student1, BindingResult result) {
if (result != null) {
//校验未通过,获取所有的异常信息并展示出来
List<ObjectError> allErrors = result.getAllErrors();
for (ObjectError allError : allErrors) {
System.out.println(allError.getObjectName() + ":" + allError.getDefaultMessage());
}
}
}
}
- @Validated:表示Student1中定义的校验规则将会生效。
- BindingResult:表示出错信息,如果这个变量不为空,表示有错误,否则校验通过。
接下来启动项目。输入数据,查看校验规则是否生效。
如果想自定义错误提示信息的话,首先先修改IDEA的编码配置,File->Settings->Editor->File Encodings,修改为UTF-8。
然后在resources目录下新建一个MyMessage.properties配置文件
student.id.notnull=id 不能为空
student.name.notnull=name 不能为空
student.name.length=name 最小长度为2,最大长度为10
student.email.error=email 地址非法
student.age.error=年龄不能超过200岁
接下来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"/>
最后在实体类的注解加上校验出错的提示信息
package org.example.model;
import javax.validation.constraints.Email;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public class Student1 {
@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 = 200,message = "{student.age.error}")
private Integer age;
public Student1() {
}
public Student1(@NotNull Integer id, @NotNull @Size(min = 2, max = 10) String name, @Email String email, @Max(200) Integer age) {
this.id = id;
this.name = name;
this.email = email;
this.age = age;
}
@Override
public String toString() {
return "Student1{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", 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;
}
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;
}
}
配置完成后,启动项目查看效果。
注意:导包时不要导错,如果导入了groupId为org.hibernate.validator的包的话,使用注解时显示包为jakarta.validation.constraints.NotNull;这样运行时就会报出javax.servlet.ServletException: Servlet[springmvc]的Servlet.init()引发异常的错误,通过观察错误信息我们会发现提示nested exception is java.lang.NoClassDefFoundError: javax/validation/ValidatorFactory。说明正确的包应该是javax.validation.constraints.NotNull;
3.2.分组校验
由于校验规则都是定义在实体类上的,但在不同的数据提交环境下,校验规则可能不一样。比如,用户id是自增长的,添加的时候不用传递用户id,但修改时必须传递用户id,这种情况下就需要使用分组校验。
首先定义校验组,其实就是空接口:
public interface ValidationGroup1 {
}
public interface ValidationGroup2 {
}
然后在实体类中,指定每一个校验规则所属的组:
package org.example.model;
import org.example.controller.ValidationGroup1;
import org.example.controller.ValidationGroup2;
import javax.validation.constraints.Email;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public class Student1 {
@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 = 200, message = "{student.age.error}", groups = {ValidationGroup1.class, ValidationGroup2.class})
private Integer age;
public Student1() {
}
public Student1(@NotNull Integer id, @NotNull @Size(min = 2, max = 10) String name, @Email String email, @Max(200) Integer age) {
this.id = id;
this.name = name;
this.email = email;
this.age = age;
}
@Override
public String toString() {
return "Student1{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", 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;
}
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;
}
}
在group中指定每一个校验规则所属的组,一个规则可以属于一个组,也可以属于多个组。
在接收参数的地方,指定校验组:
package org.example.controller;
import org.example.model.Student1;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
public class Student1Controller {
@RequestMapping("/addstu1")
public String addstudent() {
return "addStudent1";
}
@RequestMapping("/addstudent")
@ResponseBody
public void addStudent(@Validated(ValidationGroup2.class) Student1 student1, BindingResult result) {
if (result != null) {
//校验未通过,获取所有的异常信息并展示出来
List<ObjectError> allErrors = result.getAllErrors();
for (ObjectError allError : allErrors) {
System.out.println(allError.getObjectName() + ":" + allError.getDefaultMessage());
}
}
}
}
配置完成后,数据ValidationGroup2这个组的校验规则才会生效。
3.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 |
元素必须是电子邮箱地址 | |
@Length(min=,max=) | 注解的字符串大小必须在指定的范围内 |
@NotEmpty | 注解的字符串必须非空 |
@Range(min=,max=,message=) | 元素必须在合适的范围内 |
- 点赞
- 收藏
- 关注作者
评论(0)