Spring MVC实现服务端数据验证 服务端数据校验 Spring Boot 服务端数据校验
一、前言
1、日常的服务端开发中,一般都是前端做数据校验,若出现”高手“绕过前端界面,直接调用服务端接口,则前言校验无效,可能会给系统造成巨大的问题,怎么解决这个问题呢?服务端增加一层验证,确保录入数据的有效性。 因服务端预言用的是Java,一般常用开发,SpringMVC作为控制层,则变成:Spring MVC实现服务端数据验证 。
二、具体代码实现如下
1、依赖 pom.xml
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.2.Final</version>
</dependency>
2、springmvc.xml 增加配置
<!--添加对JSR-303验证框架的支持 -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
<property name="validationMessageSource" ref="messageSource"/>
</bean>
<!-- 自定义消息支持 -->
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:validateMessage"/>
<property name="defaultEncoding" value="utf-8"/>
<property name="cacheSeconds" value="120"/>
</bean>
3、validateMessage.properties 配置文件
max.age.msg=不能超过最大年龄35
min.age.msg:不能超过最小年龄18
4、创建 ValidUser 类,注解方式定义验证
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import org.hibernate.validator.constraints.Length;
import com.runcode.validate.group.Edit;
/**
* description: ValidUser 服务端数据校验
* @version v1.0
* @author w
* @date 2021年6月3日上午10:51:18
**/
public class ValidUser {
@NotNull(message = "id不能为空" , groups = {Edit.class})
private String id ;
@NotNull(message = "名字不能为空")
private String name ;
@Min(value = 18 , message = "{max.age.msg}")
@Max(value = 35 , message = "{min.age.msg}")
private Integer age ;
@NotNull(message = "地址不能为空")
@Length(min=3 , message="地址长度不能低于3个字符")
private String addr ;
// ignore getter / getter
}
5、分组,针对 增、删、改 ,创建4个普通的接口类
/**
* description: 适用于 修改数据的情景
* @version v1.0
* @author w
* @date 2021年6月3日上午10:57:41
**/
public interface Edit {
}
// 其他的略
6、创建 BeanValidators 类, 封装实现数据验证
/**
* description: Map 封装返回数据
* @param validator
* @param map
* @param object
* @param groups
* @return boolean
* @version v1.0
* @author w
* @date 2021年6月3日 下午1:29:05
*/
public static boolean beanValidator(Validator validator,Map<String,Object> map , Object object, Class<?>... groups) {
try{
Set constraintViolations = validator.validate(object, groups);
BeanValidators.validateWithException(validator, object, groups);
}catch(ConstraintViolationException ex){
List<String> list = BeanValidators.extractPropertyAndMessageAsList(ex, ": ");
list.add(0, "数据验证失败:");
map.put("error", list);
return false;
}
return true;
}
public static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e, String separator) {
return extractPropertyAndMessageAsList(e.getConstraintViolations(), separator);
}
@SuppressWarnings("rawtypes")
public static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations,
String separator) {
List<String> errorMessages = new ArrayList<String>();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.add(violation.getPropertyPath() + separator + violation.getMessage());
}
return errorMessages;
}
三、如何使用
1、使用 @Validated 注解,进行验证
@RequestMapping(value = "/add")
public Map<String,Object> add(@Validated ValidUser user , BindingResult bindingResult){
Map<String ,Object> map = new HashMap<String, Object>();
if(bindingResult.hasErrors()) {
List<ObjectError> allErrors = bindingResult.getAllErrors();
for (ObjectError objectError : allErrors) {
System.out.println(objectError.getDefaultMessage());
}
map.put("errors", allErrors);
return map ;
}
map.put("success", "操作成功");
return map ;
}
2、使用 @Validated 注解,分组校验
@RequestMapping(value = "/edit")
public Map<String,Object> edit(@Validated(value = {Edit.class}) ValidUser user , BindingResult bindingResult){
Map<String ,Object> map = new HashMap<String, Object>();
if(bindingResult.hasErrors()) {
List<ObjectError> allErrors = bindingResult.getAllErrors();
for (ObjectError objectError : allErrors) {
System.out.println(objectError.getDefaultMessage());
}
map.put("errors", allErrors);
return map ;
}
map.put("success", "操作成功");
return map ;
}
3、使用 BeanValidators 工具类验证
a. 注入 Validator 类 --- javax.validation.Validator
@Autowired
private Validator validator ;
b. 工具类校验
@RequestMapping(value = "/add/bean")
public Map<String,Object> addBean(ValidUser user ){
Map<String ,Object> map = new HashMap<String, Object>();
BeanValidators.beanValidator(validator,map, user);
System.out.println(map);
map.put("success", "操作成功");
return map ;
}
四、测试
- 访问 http://localhost:8282/validate/add , 观察控制台输出情况。
- 访问 http://localhost:8282/validate/edit ,观察控制台输出情况 --- 分组校验
- 访问 http://localhost:8282/validate/add/bean?age=10 , 察控制台输出情况 --- 使用BeanValidators 工具类实现校验
五、如何在Spring Boot中使用
1、无需步骤 【二-1,二-2】中的配置,因为Spring Boot中默认集成了 hibernate-validator ;按照后续步骤,直接使用即可。
六、总结
1、SpringMVC 服务端数据验证,使用的 hibernate-validator 实现校验。
2、两种使用的方法都可以,建议用工具类的形式,然后再抽取一个公共的BaseController ,将校验方法定义好,进行使用。