如何将请求参数及限制精确提示给用户,提示支持中英文切换

2023-12-19 21:15:14

这篇博客主要是依赖前三篇博客进行展开的处理,如果没有看前三篇建议先看完三篇后再浏览这篇。这三篇博客分别是:自研究一套返回结构体异常处理返回结构体做到全局统一,系统接口未找到报404异常统一返回处理

我们都知道对请求参数的校验可以使用spring-boot-starter-validation依赖用于请求参数的校验。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-validation</artifactId>
   <version>2.3.7.RELEASE</version>
</dependency>

比如:

@Data
public class ProjectDTO {

    @NotBlank(message = "id参数为空", groups = {TestValidGroup.Update.class})
    private String id;

    @NotBlank(message = "strValue参数为空")
    private String strValue;

    @Min(value = -99, message = "intValue参数值必须大于等于-99")
    @Max(value = 100, message = "intValue参数值必须小于等于100")
    private Integer intValue;

}

在ProjectDTO类成员中使用validation校验注解都要手动写message提示信息,而且这些提示信息样式非常相似,那么如果有很多这样的请求类处理就需要在成员注解中手动写message提示信息,那么这样是相当麻烦的,首先我很懒,我是不会这样去做的,我会这样去做,让它自动帮忙处理,而且很规范。

第一步:新建一个枚举类对象

成员变量包括:

String类型枚举名称的code

String类型的中文提示模板message

String类型的英文提示模板enMessage

实现如下:

@Getter
public enum ValidatedEnum {
    
    TEMP("Temp", "", ""), //临时对象,避免模板提示信息中占位符被使用,因枚举对象属于全局对象
    NULL("Null", "%s参数值必须是空.", "The %s parameter value must be null."),
    NOT_NULL("NotNull", "%s参数为空.", "The %s parameter is empty."),
    NOT_BLANK("NotBlank", "%s参数为空.", "The %s parameter is empty."),
    NOT_EMPTY("NotEmpty", "%s参数为空.", "The %s parameter is empty."),
    MIN("Min", "%s参数必须大于等于%s.", "The %s parameter must be greater than or equal to %s."),
    MAX("Max", "%s参数必须小于等于%s.", "The %s parameter must be less than or equal to %s."),
    SIZE("Size", "%s参数字符长度必须不大于%s且不小于%s.", "The character length of the %s parameter must not be greater than %s and not less than %s."),
    ;
    /**
     * 验证枚举名称
     */
    private String code;

    /**
     * 中文提示模板
     */
    private String message;

    /**
     * 英文提示模板
     */
    private String enMessage;

    public ValidatedEnum setCode(String code) {
        this.code = code;
        return this;
    }

    public ValidatedEnum setMessage(String message) {
        this.message = message;
        return this;
    }

    public ValidatedEnum setEnMessage(String enMessage) {
        this.enMessage = enMessage;
        return this;
    }

    ValidatedEnum(String code, String message, String enMessage) {
        this.code = code;
        this.message = message;
        this.enMessage = enMessage;
    }

    /**
     * 通过验证成员变量错误信息获取对应枚举对象并合成信息
     *
     * @param fieldError
     * @return
     * @author rufeng
     * @date 2023/12/18 15:22
     */
    public static ValidatedEnum getInstanceByFieldError(FieldError fieldError) {
        ValidatedEnum[] validatedEnums = values();
        ValidatedEnum ve = TEMP;
        for (ValidatedEnum validatedEnum : validatedEnums) {
            if (validatedEnum.getCode().equals(fieldError.getCode())) {
                //获取到code注解的值,数组个数一定要与占位符数相同
                Object[] arugments = fieldError.getArguments();
                arugments[0] = fieldError.getField();
                ve.setCode(validatedEnum.getCode()).setMessage(String.format(validatedEnum.getMessage(), arugments))
                        .setEnMessage(String.format(validatedEnum.getEnMessage(), arugments));
                return ve;
            }
        }
        return null;
    }
}

通过FieldError的成员code获取该枚举类中的对应对象,然后就可以获取到枚举对象的中英文提示模板,最后对中英文提示模板赋值,得到一个完整的对象返回出去。

第二步:全局异常使用

针对validation校验注解发生的异常有个异常处理类:MethodArgumentNotValidException,通过它就可找到FieldError哪个成员属性发生了异常。

代码处理如下:

 /**
     * 自定义验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultBody handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        log.error("发生MethodArgumentNotValidException...", e);
        BindingResult bindingResult = e.getBindingResult();
        ErrorCode errorCode = ErrorCode.FAIL;
        if (bindingResult.hasErrors()) {
            FieldError fieldError = bindingResult.getFieldError();
            if (fieldError != null) {
                ValidatedEnum validatedEnum = ValidatedEnum.getInstanceByFieldError(fieldError);
                if (StringUtils.isNotNull(validatedEnum)) {
                    //存在ValidatedEnum枚举对象中,使用对应提示
                    errorCode.setMessage(validatedEnum.getMessage()).setEnMessage(validatedEnum.getEnMessage());
                } else {
                    //不存在则使用默认提示或者使用手动编写message提示
                    errorCode.setMessage(fieldError.getDefaultMessage()).setEnMessage(fieldError.getDefaultMessage());
                }
            }
        }
        return ResultBodyUtils.fail(errorCode);
    }
第三步:提示实践效果如下:

请求类:

@Data
public class LoginBody {

    /**
     * 用户名
     */
    @NotEmpty
    private String username;

    /**
     * 用户密码
     */
    @NotEmpty
    private String password;

    /**
     * 验证码
     */
    @NotEmpty
    @Size(min = 3, max = 10)
    private String code;

    /**
     * 唯一标识
     */
    @Null
    private String uuid;

    @Min(2)
    @Max(100)
    private int age;

}
  1. 使用@Null注解

失败请求参数:

{
    "username":"admin",
    "password":"admin123",
    "uuid": "123",
    "code":"213",
    "age":10
}

失败返回报文:

{
    "code": -1,
    "message": "uuid参数值必须是空.",
    "data": null
}

成功请求参数:

{
    "username":"admin",
    "password":"admin123",
    "uuid": null,
    "code":"213",
    "age":10
}

成功返回报文:

{
    "code": 200,
    "message": "成功",
    "data": {
        "token": "eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6IjhkMzg4M2EyLWQwMjEtNDFhNC04MzljLTBjOWM5NzIzNGNiMCJ9.So2e5w-8oGCZk4OnT_bsbJNqzmEgaI3Jr3nq7VYhvb0Sc_vi2MVUvndxS0_rk_fovnshYDvX3w68lItDQC99_A"
    }
}
  1. 使用@NotEmpty注解

失败请求参数:

{
    "username":"admin",
    "password":"admin123",
    "uuid": null,
    "code":"",
    "age":10
}

失败返回报文:

{
    "code": -1,
    "message": "code参数为空.",
    "data": null
}
  1. 使用@Size注解

失败请求参数:

{
    "username":"admin",
    "password":"admin123",
    "uuid": null,
    "code":"12",
    "age":10
}

失败返回报文:

{
    "code": -1,
    "message": "code参数字符长度必须不大于10且不小于3.",
    "data": null
}
  1. 使用@Min注解

失败请求参数:

{
    "username":"admin",
    "password":"admin123",
    "uuid": null,
    "code":"123",
    "age":1
}

失败返回报文:

{
    "code": -1,
    "message": "age参数必须大于等于2.",
    "data": null
}
  1. 使用@Max注解

失败请求参数:

{
    "username":"admin",
    "password":"admin123",
    "uuid": null,
    "code":"123",
    "age":101
}

失败返回报文:

{
    "code": -1,
    "message": "age参数必须小于等于100.",
    "data": null
}

综上实践:通过枚举类的模板信息处理就可省去很多工作量,而且提示信息可做到标准化,当然上述只是枚举了一些常用的验证注解,如果需要其它可手动加入并适配,不加,提示信息会直接使用默认的。切换到英文也一样。

文章来源:https://blog.csdn.net/xiarufeng/article/details/135085548
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。