Group分组校验
1:创建校验通用接口类
//用户分组校验的接口
public interface Notnull{
}
2:创建实体类添加@NotBlank注解
public class User {
private String id;
@NotBlank(message = "用户名字不能为空",group = {NotNull.class})
private String userName;
@NotBlank(message = "用户代码不能为空",group = {NotNull.class})
private String userCode;
}
3:控制层
@PostMapping(value = "/save")
public ApiResult save(@RequestBody User user) {
StringBuilder stringBuilder = groupValidator(user);
if (StringUtils.isNotEmpty(stringBuilder)){
return ApiResult.fail(stringBuilder.toString());
}
return userService.save(user);
}
4::通用校验方法
//source 控制层入参的实体类
public <T> StringBuilder groupValidator(T source){
StringBuilder msg = new StringBuilder();
List<String> list = new ArrayList<>();
//可以在数据库配置类路径 将查询的结果添加到集合
list.add("用户分组校验的接口类的相对路径(NotNull类的路径)");
try{
List<Class<?>> classList = new ArrayList<>()
for (String s : list){
//循环集合拿到类的路径 通过反射获得类名
classList.add(Class.forName(s));
}
msg = ValidatorUtil.validateToMsg(source,classList.toArray(new Class<?>[0]));
msg.equals(ValidatorUtil.validateToMsg(source).toString());
return msg;
}catch(Exception exception){
throw new BusinessException("自定义异常信息")
}
}
5:校验工具类
import cn.hutool.core.util.StrUtil;
import org.hibernate.validator.HibernateValidator;
import org.springframework.util.CollectionUtils;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.groups.Default;
import java.util.*;
/**
* @class: ValidatorUtil
* @description: 校验工具
*/
public class ValidatorUtil {
/**
* 也可以使用spring注入的方式
*/
private static ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
.configure()
.failFast( false )
.buildValidatorFactory();
private static Validator validator = validatorFactory.getValidator();
/**
* 使用指定分组
*
* @param object 被校验的bean
* @param groups 分组
* @return
*/
public static <T> List<MsgVo> validate(T object, Class<?>... groups) {
List<MsgVo> msgVos = new ArrayList<>();
if (groups == null) {
groups = new Class[]{Default.class};
}
Set<ConstraintViolation<T>> set = validator.validate(object, groups);
if (CollectionUtils.isEmpty(set)) {
return msgVos;
}
for (ConstraintViolation<T> c : set) {
// 这里循环获取错误信息,可以自定义格式
String finalProperty = c.getPropertyPath().toString();
Optional<MsgVo> vo = msgVos.stream().filter(t -> finalProperty.equals(t.getProperty())).findFirst();
if (vo.isPresent()) {
vo.get().getMessage().append(StrUtil.COMMA).append(c.getMessage());
} else {
StringBuilder sb = new StringBuilder();
sb.append(c.getMessage());
msgVos.add(MsgVo.builder().property(finalProperty).message(sb).build());
}
}
return msgVos;
}
/**
* 使用指定分组
*
* @param object 被校验的bean
* @param groups 分组
* @return
*/
public static <T> StringBuilder validateToMsg(T object, Class<?>... groups) {
StringBuilder msg = new StringBuilder();
if (groups == null) {
groups = new Class[]{Default.class};
}
Set<ConstraintViolation<T>> set = validator.validate(object, groups);
if (CollectionUtils.isEmpty(set)) {
return msg;
}
set.stream().sorted(Comparator.comparing(ConstraintViolation::getMessage));
for (ConstraintViolation<T> c : set) {
msg.append("<br>").append(c.getMessage());
}
if(msg.length()>0)
{
return msg.delete(0,4);
}
return msg;
}
/**
* 不指定默认分组
*
* @param <T>
* @param object
*/
public static <T> List<MsgVo> validate(T object) {
return validate(object, Default.class);
}
/**
* 不指定默认分组
*
* @param <T>
* @param object
*/
public static <T> StringBuilder validateToMsg(T object) {
return validateToMsg(object, Default.class);
}
}
5: 实体类
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MsgVo {
/**
* 字段属性
*/
private String property;
/**
* 错误信息
*/
private StringBuilder message;
}
6:统一返回结果处理
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.StringUtils;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Data
@Accessors(chain = true)
@Builder
@AllArgsConstructor
public class ApiResult<T> implements Serializable {
@ApiModelProperty(value = "状态码,200为操作成功,其他为错误状态码", example = "状态码,200为操作成功,其他为错误状态码")
private int code;
@ApiModelProperty(value = "返回数据,当状态码为200时,返回的接口数据", example = "返回数据,当状态码为200时,返回的接口数据")
private T data;
@ApiModelProperty(value = "错误说明", example = "错误说明")
private String msg;
@ApiModelProperty(value = "操作时间,格式为:yyyy-MM-dd HH:mm:ss", example = "操作时间,格式为:yyyy-MM-dd HH:mm:ss")
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date time;
public ApiResult() {
}
public static ApiResult result(boolean flag) {
if (flag) {
return ok();
}
return fail("");
}
public static ApiResult result(ApiCode apiCode) {
return result(apiCode, null);
}
public static ApiResult result(ApiCode apiCode, Object data) {
return result(apiCode, null, data);
}
public static ApiResult result(ApiCode apiCode, String msg, Object data) {
String message = apiCode.getMsg();
if (StringUtils.isNotBlank(msg)) {
message = msg;
}
return ApiResult.builder()
.code(apiCode.getCode())
.msg(message)
.data(data)
.time(new Date())
.build();
}
public static ApiResult result(Integer code, String msg, Object data) {
return ApiResult.builder()
.code(code)
.msg(msg)
.data(data)
.time(new Date())
.build();
}
public static ApiResult ok() {
return ok(null);
}
public static ApiResult ok(Object data) {
return result(ApiCode.SUCCESS, data);
}
public static ApiResult ok(String key, Object value) {
Map<String, Object> map = new HashMap<>();
map.put(key, value);
return ok(map);
}
public static ApiResult fail(ApiCode apiCode) {
return result(apiCode, null);
}
public static ApiResult fail(String msg) {
return result(ApiCode.FAIL, msg, null);
}
public static ApiResult fail(ApiCode apiCode, Object data) {
if (ApiCode.SUCCESS == apiCode) {
throw new RuntimeException("失败结果状态码不能为" + ApiCode.SUCCESS.getCode());
}
return result(apiCode, data);
}
public static ApiResult fail(String key, Object value) {
Map<String, Object> map = new HashMap<>();
map.put(key, value);
return result(ApiCode.FAIL, map);
}
public Boolean compare(ApiCode apiCode) {
if (apiCode.getCode()==code) {
return true;
}
return false;
}
/**
* 执行完成
* @return
*/
@JsonIgnore
public Boolean isSuccess() {
if (ApiCode.SUCCESS.getCode() == code)
{
return true;
}
return false;
}
/**
* 执行失败
* @return
*/
@JsonIgnore
public Boolean isFail() {
if (ApiCode.SUCCESS.getCode() != code)
{
return true;
}
return false;
}
}
枚举类
public enum ApiCode {
SUCCESS(200, "操作成功"),
UNAUTHORIZED(401, "非法访问"),
NOT_PERMISSION(403, "没有权限"),
NOT_FOUND(404, "你请求的路径不存在"),
FAIL(500, "操作失败"),
SYSTEM_EXCEPTION(5000, "系统异常!"),
PARAMETER_EXCEPTION(5001, "请求参数校验异常"),
PARAMETER_PARSE_EXCEPTION(5002, "请求参数解析异常"),
HTTP_MEDIA_TYPE_EXCEPTION(5003, "HTTP Media 类型异常"),
TOKEN_EXCEPTION(30000, "Token失效请重新登录"),
TICKET_EXCEPTION(30001, "验签失败,请重新登录"),
HY_USER_NO_FOUND_EXCEPTION(900001, "用户不存在!"),
HY_USER_ACCESS_DENIED_EXCEPTION(900002, "用户没有权限!"),
HY_USER_INVALID(900008, "用户无效"),
CHECK_FAIL(301, "校验不通过"),
SYSTEM_LOGIN_EXCEPTION(5005, "系统登录异常");
private final int code;
private final String msg;
ApiCode(final int code, final String msg) {
this.code = code;
this.msg = msg;
}
public static ApiCode getApiCode(int code) {
ApiCode[] ecs = ApiCode.values();
for (ApiCode ec : ecs) {
if (ec.getCode() == code) {
return ec;
}
}
return SUCCESS;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
}