`
rensanning
  • 浏览: 3537550 次
  • 性别: Icon_minigender_1
  • 来自: 大连
博客专栏
Efef1dba-f7dd-3931-8a61-8e1c76c3e39f
使用Titanium Mo...
浏览量:37938
Bbab2146-6e1d-3c50-acd6-c8bae29e307d
Cordova 3.x入门...
浏览量:606378
C08766e7-8a33-3f9b-9155-654af05c3484
常用Java开源Libra...
浏览量:680993
77063fb3-0ee7-3bfa-9c72-2a0234ebf83e
搭建 CentOS 6 服...
浏览量:88631
E40e5e76-1f3b-398e-b6a6-dc9cfbb38156
Spring Boot 入...
浏览量:401173
Abe39461-b089-344f-99fa-cdfbddea0e18
基于Spring Secu...
浏览量:69529
66a41a70-fdf0-3dc9-aa31-19b7e8b24672
MQTT入门
浏览量:91384
社区版块
存档分类
最新评论

Spring Boot 入门 - 基础篇(12)- 数据校验

 
阅读更多
除过在客户端做JavaScript数据校验外,服务器端做数据校验是很有必要的。Spring提供数据校验,SpringBoot工程里使用没有多大变化。

数据校验分为两种:
  • 单字段校验(比如:非空、长度、大小等),Java的标准Bean Validation(内部实现是Hibernate Validator)
  • 关系多字段校验(比如:时间期间、密码的两次输入等),Spring 的 org.springframework.validation.Validator

(1)单字段校验

Form字段上添加注解
src/main/java/com/rensanning/springboot/web/form/ValidSampleForm.java
public class ValidSampleForm {

    @NotBlank
    @Size(max=5)
    private String name;

}


Contrller注入参数前添加@Validated
src/main/java/com/rensanning/springboot/web/ValidSampleContrller.java
@Controller
public class ValidSampleContrller {

    @RequestMapping(value="/validSample", method = RequestMethod.POST)
    public String postValidSample(@ModelAttribute("form") @Validated ValidSampleForm form, BindingResult result, Model model) {
 
        if (result.hasErrors()) {
            for(FieldError err: result.getFieldErrors()) {
                log.debug("error code = [" + err.getCode() + "]");
            }
        }

        return "validSample";
    }

}


页面中显示错误信息
src/main/resources/templates/validSample.html
<form th:action="@{/validSample}" th:object="${form}" method="post">
<table>
<tr>
  <td>姓名:</td>
  <td>
    <input type="text" th:field="*{name}" th:errorclass="fieldError" />
  </td>
  <td th:if="${#fields.hasErrors('name')}" th:errors="*{name}" style="color: red"></td>
</tr>
</table>
</form>


一览显示错误信息
<ul>
  <li th:each="e : ${#fields.detailedErrors()}"
    th:class="${e.global}? globalerrMsg : fielderrMsg" th:text="${e.message}" />
</ul>


(2)自定义错误信息

Spring默认错误信息
引用
hibernate-validator-5.3.4.Final.jar\org\hibernate\validator\ValidationMessages.properties


自定义错误信息
Java中自定义
@NotNull(message="不能为空!")

外部自定义
@NotNull(message="{sample.bean_validation.notNull}")

引用
sample.bean_validation.notNull=不能为空!


SpringBoot自动读取classpath中的ValidationMessages.properties里的错误信息
src/main/resources/ValidationMessages.properties
引用
javax.validation.constraints.Pattern.message=
javax.validation.constraints.Size.message=
javax.validation.constraints.Min.message=
org.hibernate.validator.constraints.NotBlank.message=


统一到国际化信息文件messages.properties
@Bean
public LocalValidatorFactoryBean validator() {
    LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
    localValidatorFactoryBean.setValidationMessageSource(messageSource);
    return localValidatorFactoryBean;
}

@Override
public org.springframework.validation.Validator getValidator() {
    return validator();
}


(3)嵌套校验 @Valid
public class OrderForm {

    @NotNull
    @Valid
    private AddressForm receiverAddress;

    @NotNull
    @Valid
    private AddressForm senderAddress;

}

public class AddressForm {

    @NotNull
    @Size(min = 1, max = 100)
    private String address;

}


集合Bean校验也和上边一致:
public class OrderForm {

    @NotNull
    @Size(min = 1, max = 3)
    @Valid
    private List<AddressForm> addresses;

}


(4)组校验

定义Group
public class ValidSampleForm {
 
    public static interface Group1 {};
    public static interface Group2 {};
 
    @NotBlank(groups=Group1.class)
    @Size(max=5, groups=Group1.class)
    private String name;
 
    @Min(value=0, groups={Group1.class, Group2.class})
    private Integer age;
 
    @NotBlank(groups=Group2.class)
    private Date birthday;

}


只校验Group1的字段
@RequestMapping(value="/validSample", method = RequestMethod.POST)
public String postValidSample(@ModelAttribute("form") @Validated(Group1.class) ValidSampleForm form, BindingResult result, Model model) {
 
    if (result.hasErrors()) {
        for(FieldError err: result.getFieldErrors()) {
            log.debug("error code = [" + err.getCode() + "]");
        }
    }
    return "validSample";
}


顺序执行校验

假如以下定义,如果name为空,两个错误提示都会显示到页面上。
@NotEmpty(message = "请输入姓名!")
@Length(min = 1, max = 10, message = "1到10位字符")
private String name;


只有@NotEmpty不出错的情况下才执行@Length:
public interface First { }
public interface Second { }

@GroupSequence({First.class, Second.class})
public interface All {

}


@NotEmpty(message = "请输入姓名!", groups = First.class)
@Length(min = 1, max = 10, message = "1到10位字符", groups = Second.class)
private String name;

@RequestMapping(method = RequestMethod.POST)
public String indexPost(@ModelAttribute("form") @Validated(All.class) Person p, BindingResult r) {
    return "index";
}


(5)多字段校验

实现Spring的Validator
@Component
public class ValidSampleValidator implements Validator {

	public boolean supports(Class<?> c) {
		return ValidSampleForm.class.isAssignableFrom(c);
	}

	@Override
	public void validate(Object paramObject, Errors paramErrors) {
            if (paramErrors.hasFieldErrors("from") || paramErrors.hasFieldErrors("to")) {
                return;
            }
 
            ValidSampleForm form = (ValidSampleForm)paramObject;
            Date from = form.getFrom();
            Date to = form.getTo();
            if (from != null && to != null && from.compareTo(to) > 0) {
                paramErrors.rejectValue("from", "validator.Period");
            }
	}
}


通过@InitBinder添加自定义校验
@Controller
public class ValidSampleController {

	@Autowired
	private ValidSampleValidator validSampleValidator;

	@InitBinder
	public void initBinder(WebDataBinder binder) {
	    binder.addValidators(validSampleValidator);
	}

	@RequestMapping(value="/validSample", method = RequestMethod.POST)
	public String postValidSample(@ModelAttribute("form") ValidSampleForm form, BindingResult result, Model model) {
 
 	   if (result.hasErrors()) {
 	       for(FieldError err: result.getFieldErrors()) {
  	          log.debug("error code = [" + err.getCode() + "]");
  	      }
 	   }

 	   return "validSample";
	}

}


src/main/resources/messages.properties
引用
validator.Period=


一个Controller需要校验多个Form的话:
@Controller
public class XxxController {

    @ModelAttribute("AaaForm")
    public AaaForm() {
        return new AaaForm();
    }

    @ModelAttribute("BbbForm")
    public BbbForm() {
        return new BbbForm();
    }

    @InitBinder("AaaForm")
    public void initBinderForAaa(WebDataBinder binder) {
        binder.addValidators(aaaValidator);
    }

    @InitBinder("BbbForm")
    public void initBinderForBbb(WebDataBinder binder) {
        binder.addValidators(bbbValidator);
    }

}


(6)自定义校验

a - 已有注解基础上自定义
@NotBlank
@Size(min=1, max=5)
public @interface Name {
    String message() default "{com.rensanning.springboot.validator.constraints.Name.message}";
    // ...
}

引用
com.rensanning.springboot.validator.constraints.Name.message=xxx

@Name
private String name;


b - 单字段校验
public class AgeValidator implements ConstraintValidator<Age, Integer> {
    int min;
    int max;
 
    @Override
    public void initialize(Age annotation) {
        min = annotation.min();
        max = annotation.max();
    }
 
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext paramConstraintValidatorContext) {
        if (value == null) {
            return true;
        }
        if (value < min || value > max) {
            return false;
        }
        return true;
    }
 
}

@Constraint(validatedBy={AgeValidator.class})
public @interface Age {
      String message() default "{com.rensanning.springboot.validator.constraints.Age.message}";

      int min() default 0;
      int max() default 100;

}

引用
com.rensanning.springboot.validator.constraints.Age.message=

@Age(min=18)
private Integer age;


c - 多字段关联校验
@Constraint(validatedBy={PeriodValidator.class})
public @interface Period {
      String message() default "{com.rensanning.springboot.validator.constraints.Period.message}";

      String fieldFrom() default "from";
      String fieldTo() default "to";

}

引用
com.rensanning.springboot.validator.constraints.Period.message=

public class PeriodValidator implements ConstraintValidator<Period, Object> {
    private String fieldFrom;
    private String fieldTo;
    private String message;
 
    @Override
    public void initialize(Period annotation) {
        this.fieldFrom = annotation.fieldFrom();
        this.fieldTo = annotation.fieldTo();
        this.message = annotation.message();
    }
 
    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
 
        BeanWrapper beanWrapper = new BeanWrapperImpl(value);
 
        Date from = (Date)beanWrapper.getPropertyValue(fieldFrom);
        Date to = (Date)beanWrapper.getPropertyValue(fieldTo);
 
        if (from != null && to != null && from.compareTo(to) > 0) {
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate(message)
                   .addNode(fieldFrom)
                   .addConstraintViolation();
            return false;
        }
        return true;
    }
 
}

@Period(fieldFrom="from", fieldTo="to")
public class ValidSampleForm {
  
    private Date from;
    private Date to;

}


(7)同时支持Hibernate Validator 和 Spring Validator
@Controller
public class UserController {

	@Autowired
	private UserFormValidator userFormValidator;

	@RequestMapping(value = "/save", method = RequestMethod.POST)
	public String save(@ModelAttribute("userForm") @Valid User user,
		BindingResult result, Model model) {

		// 手动执行Spring Validator
		userFormValidator.validate(user, result);

		if (result.hasErrors()) {
			//...
		} else {
			//...
		}

	}

}
分享到:
评论

相关推荐

    Spring-mvc Srping-boot spring-jdbc

    此外,Spring MVC支持多种视图技术,如JSP、Thymeleaf和FreeMarker,提供了强大的数据绑定和校验功能。 **Spring Boot** Spring Boot是为了简化Spring应用程序的初始搭建和配置而诞生的。它内置了Tomcat或Jetty...

    Spring Boot中使用LDAP来统一管理用户信息的示例

    本篇文章主要介绍了 Spring Boot 中使用 LDAP 来统一管理用户信息的示例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。下面我们将详细介绍 LDAP 的基础概念和在 Spring Boot 中如何使用 LDAP 来统一管理用户...

    spring-analysis-源码.rar

    Spring MVC是Spring为构建Web应用程序提供的模块,它负责处理请求、转发响应,提供模型绑定、数据校验、本地化等功能,使开发人员能更专注于业务逻辑。 7. **Spring Boot** Spring Boot简化了Spring应用的初始...

    spring-cloud搭建.pdf

    Spring Cloud是基于Spring Boot实现的,它利用Spring Boot的开发便利性简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Cloud的开发方式快速...

    springcloud整合oauth2和jwt

    - 配置MyBatis:在Spring Boot应用中添加MyBatis依赖,创建MyBatis配置类,配置数据源、SqlSessionFactory和Mapper扫描路径。 - 编写Mapper接口和XML映射文件,实现业务逻辑。 6. **安全注意事项**: - 保护敏感...

    spring-cloud分布式实战视频教程.txt

    Spring Cloud是一系列框架的有序集合,它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等。通过Spring Cloud可以快速高效地...

    springboot-shiro.zip

    本篇文章将深入探讨如何将Spring Boot与Shiro进行整合,实现一个安全的个人博客系统。 **一、Spring Boot简介** Spring Boot是基于Spring框架的快速开发工具,它简化了Spring应用的初始搭建以及开发过程。通过自动...

    Springboot 自定义校验代码实例

    本篇将详细介绍如何在Spring Boot中实现自定义校验,以`StartWithValidation`为例。 首先,自定义校验注解`StartWithValidation`是整个过程的核心。这个注解使用了`@Constraint`,表明它是一个约束注解,并且通过`...

    详细步骤截图。微信,淘宝客api域名检验,centos nginx springboot jar下的验证文件xxx.txt放置于您所配置域名

    这篇描述主要涉及了如何在CentOS操作系统上,通过Nginx服务器进行多域名配置,并结合SpringBoot应用来完成微信、淘宝客API的域名验证过程。下面我们将详细讲解这个过程。 首先,验证域名通常涉及到提供一个特定的...

    157-停车场管理系统源码.zip

    从这个结构来看,系统很可能使用了Spring Boot作为基础框架,它集成了Spring MVC和Spring Data等组件,便于快速开发。此外,数据库可能采用MySQL或其他SQL数据库,通过JDBC或ORM框架如Hibernate进行操作。系统可能还...

    Java生成验证码(包含gif动画验证码)

    本篇文章将详细探讨如何在Java中实现这两种类型的验证码。 首先,让我们从静态图片验证码开始。生成静态图片验证码的基本步骤通常包括以下几个部分: 1. **随机生成字符**:随机选择一定数量的字符,这些字符可以...

    Springboot-Interest-Calculator

    2.4 验证与异常处理:可以使用JSR-303/JSR-349提供的数据校验功能,以及Spring的`@ExceptionHandler`进行异常处理,提高API的健壮性。 三、部署与测试 3.1 内嵌Web服务器:SpringBoot默认内嵌Tomcat或Jetty服务器...

    乐优商城19天完整

    根据给定的信息,“乐优商城19天完整版带笔记”这一资料主要涉及的是一个基于Spring ...通过本篇内容的介绍,希望能够帮助读者建立起对Spring Cloud及其在电商项目中应用的整体认识,并为后续深入学习打下坚实的基础。

    springboot-08-shiro.rar

    由于Shiro并不直接支持SpringBoot,我们通常需要借助Spring Boot Starter Web和Spring Boot Starter Actuator来构建基础环境。 2. 配置Shiro 首先,我们需要创建一个Shiro的配置类,这个类会定义Shiro的主要组件,...

    web实验报告5.01

    本篇实验报告将围绕“Web实验报告5.01”展开,主要探讨在Web开发技术基础课程设计中的核心功能实现,包括用户注册、登录、登出、游客模式、微博评论、点赞、微博发布与存储、微博显示、分页、排序、发博时图片的处理...

    SpringBoot权限管理系统

    二、Spring Security基础 在SpringBoot权限管理系统中,核心组件Spring Security扮演了关键角色。Spring Security是一个强大且高度可定制的身份验证和访问控制框架,用于保护基于Java的Web应用。它提供了一套完整的...

    基于Android的防走失系统的设计与实现.pdf

    系统服务器基于Java语言,使用Spring Boot框架构建,系统数据库采用MongoDB进行数据存储。系统提供可用的百度地图API接口。客户端与服务器之间的Socket通信是主要的交互机制,而HTTP通信作为辅助,具有传输时间短、...

    hrm 管理系统 后端使用springboot 前端使用vue 内含sql脚本,亲测可用

    4. SpringBoot后端接收到请求,执行相应的业务逻辑,如查询数据库、校验数据等。 5. 数据库MySQL根据后端的SQL指令进行数据操作,返回结果。 6. SpringBoot将数据库返回的结果转换为JSON格式,发送回前端。 7. Vue....

    java web 系统权限设计 源码

    - Spring Security:这是一个强大的安全框架,提供了完善的权限控制功能,支持RBAC和其他访问控制模型,能与Spring Boot无缝集成。 - Shiro:另一个常用的Java安全框架,提供了一套简洁的API,易于理解和使用,...

Global site tag (gtag.js) - Google Analytics