Controller层方法经常会接收前端返回的数据,并进行参数校验。
可以采取注解式的参数校验方法,这样就不需要在每个controller方法里都手写参数校验代码。
思路
- 使用 Hibernate validator 参数校验
- 对实体类进行注解,将校验代码配置成注解
- 不同的Controller方法可能有不同的校验需求,可采用分组校验的方法解决
- 特殊的校验需求,可以使用自定义校验注解的方式处理
实现
-
建立校验分组
校验分组可实现对不同校验需求进行不同适配。只需要建立接口即可。
package com.zp.haveplace.validator.group.admin;
/**
* 校验分组
* 管理员登录时的Controller校验
* @author zp
* @date 2018/4/20
*/
public interface LoginValidatorGroup {
}
package com.zp.haveplace.validator.group.admin;
/**
* 校验分组
* 修改管理员信息时的Controller校验
* @author zp
* @date 2018/4/20
*/
public interface UpdateAdminValidatorGroup {
}
- 实体类中对需要校验的字段进行注解
package com.zp.haveplace.entity;
import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.FieldFill;
import com.baomidou.mybatisplus.enums.FieldStrategy;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.zp.haveplace.util.TimeUtils;
import com.zp.haveplace.validator.group.admin.AddAdminValidatorGroup;
import com.zp.haveplace.validator.group.admin.LoginValidatorGroup;
import com.zp.haveplace.validator.group.admin.UpdateAdminValidatorGroup;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.Min;
import java.util.Date;
/**
* 后台管理员信息
* "password",isDeleted","gmtCreate","gmtModified"字段不输出
*/
@JsonIgnoreProperties({"password","isDeleted","gmtCreate","gmtModified"})
@TableName("_admin")
public class Admin {
@NotEmpty(message = "被修改管理员id不能为空",groups = {UpdateAdminValidatorGroup.class})
@Min(value = 1,message = "id必须大于0",groups = {UpdateAdminValidatorGroup.class})
private Integer adminId;
// 登录校验,添加校验
@NotEmpty(message = "账号不能为空",groups = {LoginValidatorGroup.class,AddAdminValidatorGroup.class})
private String account;
// 登录校验,添加校验
@NotEmpty(message = "密码不能为空",groups = {LoginValidatorGroup.class,AddAdminValidatorGroup.class})
private String password;
private Integer role;
private String phone;
private String comment;
private Integer isDeleted;
private Date gmtCreate;
private Date gmtModified;
//......get/set方法
}
其中,@JsonIgnoreProperties注解是用于实体类包装返回为JSON时需要忽略的字段;message意思是校验不通过时返回的信息,信息除了硬编码以外,还可以通过配置文件获取,我采取了硬编码;groups是校验分组。
- Controller使用校验
package com.zp.haveplace.web;
import com.zp.haveplace.annotation.LoginRequired;
import com.zp.haveplace.annotation.RoleRequired;
import com.zp.haveplace.bean.PageBean;
import com.zp.haveplace.bean.ResponseBean;
import com.zp.haveplace.common.RoleConst;
import com.zp.haveplace.common.SessionConstant;
import com.zp.haveplace.entity.Admin;
import com.zp.haveplace.service.AdminService;
import com.zp.haveplace.bean.LoggerBean;
import com.zp.haveplace.util.TimeUtils;
import com.zp.haveplace.validator.group.admin.LoginValidatorGroup;
import com.zp.haveplace.validator.group.admin.UpdateAdminValidatorGroup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.security.acl.Group;
import java.util.EnumSet;
import java.util.List;
import org.springframework.validation.BindingResult;
/**
* 管理员控制器
*
* @author zp
* @date 2018/4/21
*/
@Controller
@RequestMapping("/admin")
public class AdminController{
// 用户登录方法
@RequestMapping(value = "/login",method = RequestMethod.POST)
@ResponseBody
public ResponseBean login(@Validated(value = {LoginValidatorGroup.class}) Admin loginAdmin,
BindingResult bindingResult,
HttpServletRequest request)throws Exception{
//需要校验的参数必须使用@Validated注解,并在此注解后增加BindingResult参数
//@Validated需配置校验分组
//BindingResult类用于存储校验结果
//检查校验结果
if(bindingResult.hasErrors()){
String errorInfo = "";
List<FieldError> errors = bindingResult.getFieldErrors();//获取字段参数不合法的错误集合
for(FieldError error : errors){
errorInfo = errorInfo + "[" + error.getField() + " " + error.getDefaultMessage() + "]";
}
return new ResponseBean().setExceptionResponse(errorInfo);//返回校验错误
}
//.....业务逻辑代码
return new ResponseBean().setSuccessMessage("登录成功");
}
}
对校验结果的检查,可以采用AOP方式实现,彻底抛弃controller硬编码。具体实现请参考:
[Spring] Web层使用AOP方式进行参数校验
-
自定义校验
百度有很多
参考
部分源码及思路来自:
优雅的SSM(Spring+SpringMVC+Mybatis)框架
Hibernate Validator注解大全
[SpringMVC] Web层返回值包装JSON