在以往,前端向后台传递参数时,要在业务实现中,优先对参数进行逐个校验,以实现在真正业务前对输入的参数进行“去伪”,这样会导致业务中存在大量的重复的参数校验代码,以下使用@Valid
(jakarta.validation.Valid)和@Validated
(org.springframework.validation.annotation.Validated)实现对对象参数的校验或分组校验,从此业务的业务,校验的归校验!
一、环境版本
- JDK21
- SpringBoot3.3.0
- Knife4.5.0
- Maven3.9.6
- IDEA2024.1
二、引入依赖
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version>
<relativePath/>
</parent>
<dependencies>
...
<!-- 数据校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
...
</dependencies>
二、@Valid
与@Validated
区别
区别 | @Valid | @Validated |
---|---|---|
提供者 | JSR-303规范 | Spring |
是否支持分组 | 不支持 | 支持 |
标注位置 | - METHOD - FIELD - CONSTRUCTOR - PARAMETER - TYPE_USE |
- TYPE - METHOD - PARAMETER |
嵌套校验 | 支持 | 不支持 |
三、@Valid校验
1.@Valid
主要用法
- 在实体中的属性上,添加不同的注解(如下)来完成不同的校验。
- 在接口类中的接收数据参数中添加 @Valid 注解。
2.实体注解详解
@NotEmpty
:元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@NotBlank
:验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格。
@Null
:只能为null
@NotNull
:不为null
@Email
:验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式
@AssertFalse
:必须为false
@AssertTrue
:必须为true
@DecimalMax(value)
:不大于指定值的数字
@DecimalMin(value)
:不小于指定值的数字
@Digits(integer,fraction)
:一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
@Max(value)
:不大于指定值的数字
@Min(value)
:不小于指定值的数字
@Future
:必须是一个将来的日期(不包含现在)
@FutureOrPresent
:必须是一个将来的日期(包含现在)
@Past
:必须是一个过去的日期(不包含现在)
@PastOrPresent
:必须是一个过去的日期(包含现在)
@Pattern(value)
:符合指定的正则表达式
@Size(max,min)
:限定字符长度在min到max之间
@Positive
:数值是否是正数
@PositiveOrZero
:数值是否是正数和0
@Negative
:数值是否是负数
@NegativeOrZero
:数值是否是负数和0
四、@Validated校验
该注解属于Spring框架中的注解,见于spring-context-6.1.8.jar中的org.springframework.validation.annotation
`,此注解比较强大之处在于支持分组校验,分组是在实体类验证中常用的一种技术,它允许你根据不同的场景对验证规则进行分组,从而在不同的情况下应用不同的验证规则。
定义常用的校验组后,不仅可以单独使用,还可以联合使用。
1.自定义校验组
以下为校验组空接口,作用于对象的属性参数上;名称可以自定义,以下仅列举部分,实际应用中可以根据需要进行自定义创建。
校验新增组
package cn.keyidea.common.valid;
/**
* 空间接,区分校验场景,校验添加组
*
* @author qyd
* @date 2022-10-18
*/
public interface GroupAdd {
}
校验更新组
package cn.keyidea.common.valid;
/**
* 空间接,区分校验场景,校验更新组
*
* @author qyd
* @date 2022-10-18
*/
public interface GroupUpdate {
}
校验校验自定义组(包含ID)
该校验组常和
GroupUpdate
联合使用,在涉及包括ID变更的接口中常用。
package cn.keyidea.common.valid;
/**
* 空间接,区分校验场景,校验自定义组(包含ID)
*
* @author qyd
* @date 2022-10-18
*/
public interface GroupCustomWithId {
}
校验状态组
package cn.keyidea.common.valid;
/**
* 空间接,区分校验场景,校验状态组
*
* @author qyd
* @date 2022-10-18
*/
public interface GroupStatus {
}
校验登录组
package cn.keyidea.common.valid;
/**
* 空间接,区分校验场景,校验登录组
*
* @author qyd
* @date 2022-10-18
*/
public interface GroupLogin {
}
校验修改密码组
package cn.keyidea.common.valid;
/**
* 空间接,区分校验场景,校验修改密码组
*
* @author qyd
* @date 2022-10-18
*/
public interface GroupChangePwd {
}
校验自定义分组
package cn.keyidea.common.valid;
/**
* 空间接,区分校验场景,自定义校验
*
* @author qyd
* @date 2024-05-25
*/
public interface GroupCustom {
}
在实际开发中,甚至可以按照每个控制器进行分类创建每个对象下的各自校验组,但出于抽象与简化,上述的校验组已经可以满足绝大多数场景使用。
2.使用示例
这里以数据新增和数据更新为典型场景进行示范
- 分别以数据添加和数据更新为场景,以系统配置类为示例进行
- 新增数据时,使用GroupAdd进行分组校验
- 数据更新时,使用GroupUpdate进行分组校验
- 使用分组校验时需使用
@Validated
注解;并且一般只作用于对象参数上!
系统配置控制器端配置<SysController.java
>
package cn.keyidea.sys.controller;
import cn.keyidea.common.annotation.SysLogAnnotation;
import cn.keyidea.common.bean.BaseRes;
import cn.keyidea.common.config.InitConfigProperties;
import cn.keyidea.common.constant.ConstantsExpand;
import cn.keyidea.common.valid.GroupAdd;
import cn.keyidea.common.valid.GroupUpdate;
import cn.keyidea.sys.entity.SysConfig;
import cn.keyidea.sys.service.SysConfigService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
/**
* 系统配置控制器
*
* @author qyd
* @date 2022-10-17
*/
@ApiSupport(order = 7)
@Tag(name = "7-系统配置", description = "系统配置")
@RestController
@RequestMapping("/sys/sysConfig")
public class SysConfigController
{
private final static Logger logger = LoggerFactory.getLogger(SysConfigController.class);
@Autowired
private SysConfigService sysConfigService;
@Autowired
private InitConfigProperties initConfigProperties;
......
@SysLogAnnotation(module = "配置管理", serviceDesc = "配置管理-配置新增", serviceType = ConstantsExpand.ServiceType.ADD)
@ApiOperationSupport(author = "qyd", order = 2, includeParameters = {
"sysConfig.sysConfigName",
"sysConfig.sysConfigCode",
"sysConfig.sysConfigValue",
"sysConfig.remark"
})
@Operation(summary = "配置新增", description = "")
@PostMapping("add")
public BaseRes add(@Validated(GroupAdd.class) @RequestBody SysConfig sysConfig)
{
return sysConfigService.add(sysConfig);
}
@SysLogAnnotation(module = "配置管理", serviceDesc = "配置管理-配置更新", serviceType = ConstantsExpand.ServiceType.UPDATE)
@ApiOperationSupport(author = "qyd", order = 3, includeParameters = {
"sysConfig.id",
"sysConfig.sysConfigName",
"sysConfig.sysConfigValue",
"sysConfig.remark"
})
@Operation(summary = "配置更新", description = "配置key值一旦设置便不可更改,除非删除")
@PutMapping("/update")
public BaseRes update(@Validated(GroupUpdate.class) @RequestBody SysConfig sysConfig)
{
return sysConfigService.update(sysConfig);
}
......
}
系统配置实体类<SysConfig.java
>
package cn.keyidea.sys.entity;
import cn.keyidea.common.bean.BaseModel;
import cn.keyidea.common.valid.GroupAdd;
import cn.keyidea.common.valid.GroupUpdate;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.Comment;
/**
* 系统配置表
*
* @author qyd
* @date 2022-10-17
*/
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
@Data
@EqualsAndHashCode(callSuper = true)
@Entity
@TableName("sys_config")
@Table(name = "sys_config")
@Schema(name = "SysConfig", description = "系统配置")
@Comment("系统配置表")
public class SysConfig extends BaseModel {
@NotBlank(message = "配置名称不能为空", groups = {GroupAdd.class, GroupUpdate.class})
@Schema(description = "配置名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "名称1")
@Column(name = "name", columnDefinition = "varchar(50) not null COMMENT '配置名称'")
private String name;
/**
* 参见:{@link cn.keyidea.common.constant.Constants.SYS_CONFIG_CODE}
*/
@NotBlank(message = "配置标识值为空", groups = {GroupAdd.class, GroupUpdate.class})
@Schema(description = "配置标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "code1")
@Column(name = "code", columnDefinition = "varchar(50) not null COMMENT '配置标识'")
private String code;
@NotBlank(message = "配置项值为空", groups = {GroupAdd.class, GroupUpdate.class})
@Schema(description = "配置项值", requiredMode = Schema.RequiredMode.REQUIRED, example = "value1")
@Column(name = "value", columnDefinition = "varchar(50) not null COMMENT '配置项值'")
private String value;
@Schema(description = "配置项描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "说明/描述")
@Column(name = "remark", columnDefinition = "varchar(255) COMMENT '配置项描述'")
private String remark;
}
由于系统配置实体类继承了基类,基类(<BaseModel.java
>)中也进行了校验分组
package cn.keyidea.common.bean;
import cn.keyidea.common.valid.GroupChangePwd;
import cn.keyidea.common.valid.GroupCustomWithId;
import cn.keyidea.common.valid.GroupUpdate;
import com.alibaba.fastjson.annotation.JSONField;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 实体父类
* <p>
* 特殊说明:
* 继承此基类的实体类,如果使用lombok的@Data注解时,主要同时添加@EqualsAndHashCode(callSuper = true)注解
* 1)注解@EqualsAndHashCode(callSuper = true),就是用自己的属性和从父类继承的属性来生成hashcode;
* 2)注解@EqualsAndHashCode(callSuper = false),就是只用自己的属性来生成hashcode;
* 3)@Data相当于@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode这5个注解的合集, 和@EqualsAndHashCode默认是false。
* <p>
* MappedSuperclass注解说明:
* 1.@MappedSuperclass注解仅仅能标准在类上;这个注解标识在父类上面的,用来标识父类
* 2.标注为@MappedSuperclass的类将不是一个完整的实体类,他将不会映射到数据库表,可是他的属性都将映射到其子类的数据库字段中
* 3.标注为@MappedSuperclass的类不能再标注@Entity或@Table注解
* <p>
* EntityListeners注解及相关说明:
* EntityListeners:该注解用于指定Entity或者superclass上的回调监听类
* AuditingEntityListener:这是一个JPA Entity Listener,用于捕获监听信息,当Entity发生持久化和更新操作时
*
* @author qyd
* @date 2022-10-17
*/
@SuperBuilder // @SuperBuilder支持对基类成员属性的构造;如果子类继承了BaseModel,也需要使用该注解
@AllArgsConstructor // 全参构造函数
@NoArgsConstructor // 空参构造函数
@Data
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@Schema(name = "BaseModel", description = "实体父类")
public class BaseModel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@NotNull(message = "ID不能为NUll", groups = {GroupUpdate.class, GroupChangePwd.class, GroupCustomWithId.class})
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@Id
@Column(name = "id", columnDefinition = "int(10) COMMENT '自增长ID'")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Column(name = "create_time", updatable = false, columnDefinition = "datetime not null COMMENT '创建时间'")
@TableField(value = "create_time", fill = FieldFill.INSERT)
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@Schema(description = "创建人ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
@Column(name = "create_by", updatable = false, columnDefinition = "int(10) not null COMMENT '创建人ID'")
@TableField(value = "create_by", fill = FieldFill.INSERT)
private Integer createBy;
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Column(name = "update_time", columnDefinition = "datetime COMMENT '更新时间'")
@TableField(value = "update_time", fill = FieldFill.UPDATE)
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
@Schema(description = "更新人ID", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
@Column(name = "update_by", columnDefinition = "int(10) COMMENT '更新人ID'")
@TableField(value = "update_by", fill = FieldFill.UPDATE)
private Integer updateBy;
}
五、自定义注解1:实现枚举校验
1.自定义枚举注解类<EnumValue.java
>
package cn.keyidea.common.annotation;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 枚举校验注解, 处理类参见:{@link EnumValueValidator}
*
* @author qyd
* @date 2021-11-09
*/
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {EnumValueValidator.class})
public @interface EnumValue {
// 默认错误消息
String message() default "必须为指定值";
String[] strValues() default {};
int[] intValues() default {};
// 分组
Class<?>[] groups() default {};
// 负载
Class<? extends Payload>[] payload() default {};
// 指定多个时使用
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
@Retention(RUNTIME)
@Documented
@interface List {
EnumValue[] value();
}
}
2.自定义枚举注解处理类<EnumValueValidator.java
>
支持整型枚举和字符串枚举。
package cn.keyidea.common.annotation;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
/**
* 枚举校验注解处理类, 注解类参见:{@link EnumValue}
*
* @author qyd
* @date 2021-11-09
*/
public class EnumValueValidator implements ConstraintValidator<EnumValue, Object> {
private String[] strValues;
private int[] intValues;
@Override
public void initialize(EnumValue constraintAnnotation) {
strValues = constraintAnnotation.strValues();
intValues = constraintAnnotation.intValues();
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
if (value instanceof String) {
for (String s : strValues) {
if (s.equals(value)) {
return true;
}
}
} else if (value instanceof Integer) {
for (int s : intValues) {
if (s == ((Integer) value).intValue()) {
return true;
}
}
}
return false;
}
}
3.使用示例
在属性字段进行枚举的字段上添加注解@EnumValue
,并在intValues中枚举出正常的数据,不在此列中的数据将会报错,并由全局异常捕获类处理返回。
/**
* 切片标志:
* 该标志由运营单位生成,并对空口无线资源进行标记和对用户进行标记,取值为“0、1、2、3、4、5
* 取值为“0”时表示没有切片标志,取值为“>0”时表示对应的切片标志
* <p>
* 参见{@link Resource#getSliceId()}
*/
@EnumValue(intValues = {0, 1, 2, 3, 4, 5}, groups = {GroupAdd.class, GroupUpdate.class})
@NotNull(message = "切片标志不能为NULL", groups = {GroupAdd.class, GroupUpdate.class})
@Schema(description = "切片标志:[0,5]", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@Column(name = "slice_id", columnDefinition = "int(10) not null COMMENT '切片标志:[0,5]'")
private Integer sliceId;
除了支持枚举整型外,还支持枚举字符串,在此不表;另外自定义枚举类也支持分组校验。
六、配置全局异常返回
由于使用上述校验时,报错会报MethodArgumentNotValidException异常,因此在全局异常捕获类中,对该类进行单独处理,实现数据返回的统一封装,统一返回封装类见附录A<BaseRes.java
>
AppExceptionHandler
全局异常捕获处理
package cn.keyidea.common.config;
import cn.keyidea.common.bean.BaseRes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 全局异常处理
*
* @author LiGang
* @date 2019-05-29
*/
@RestControllerAdvice
public class AppExceptionHandler {
private final static Logger logger = LoggerFactory.getLogger(AppExceptionHandler.class);
@ExceptionHandler(value = {BusinessException.class})
public BaseRes business(BusinessException ex) {
logger.error("业务异常:" + ex.getMessage());
return BaseRes.invalidParam("业务异常:" + ex.getMessage());
}
@ExceptionHandler(value = {MethodArgumentNotValidException.class})
public BaseRes methodArgumentNotValidException(MethodArgumentNotValidException ex) {
String field = ex.getBindingResult().getFieldError().getField().replace("parameter.", "");
String message = ex.getBindingResult().getFieldError().getDefaultMessage();
logger.error("验证失败:字段[" + field + "]" + message);
return BaseRes.invalidParam("验证失败:字段[" + field + "]" + message);
}
// 专门用于GET分页查询时,使用注解@ModelAttribute接收对象参数时,添加了@Valid等校验时的验证使用
@ExceptionHandler(value = {BindException.class})
public BaseRes bindException(BindException ex) {
String field = ex.getBindingResult().getFieldError().getField().replace("parameter.", "");
String message = ex.getBindingResult().getFieldError().getDefaultMessage();
logger.error("验证失败:字段[" + field + "]" + message);
return BaseRes.invalidParam("验证失败:字段[" + field + "]" + message);
}
@ExceptionHandler(value = {AuthorizationException.class})
public BaseRes authorizationException(AuthorizationException ex) {
logger.error("没有权限:" + ex.getMessage());
return BaseRes.fail("没有权限:" + ex.getMessage());
}
@ExceptionHandler(value = {Exception.class})
public BaseRes exception(Exception ex) {
logger.error("系统异常:" + ex.getMessage());
ex.printStackTrace();
return BaseRes.fail("系统异常:" + ex.getMessage());
}
}
附录A<BaseRes.java
>
package cn.keyidea.common.bean;
import cn.keyidea.common.constant.StatusCode;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
/**
* 通用响应封装,范式返回(Swagger要求)
*
* @author qyd
*/
@Data
public class BaseRes<T> implements Serializable {
/**
* 错误码
*/
@Schema(name = "code", description = "错误码,当code为1000时返回正常,其余返回异常", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
public Integer code;
/**
* 错误提示信息
*/
@Schema(name = "msg", description = "错误提示信息,当code为非1000时返回提示信息", requiredMode = Schema.RequiredMode.REQUIRED, example = "请求成功")
public String msg;
/**
* 附加返回数据
*/
@Schema(name = "data", description = "附加返回数据,当code为1000时返回数据")
public T data;
public static class DataList<T> {
/**
* 记录总数
*/
@Schema(name = "total", description = "记录总数")
public Integer total;
/**
* 数据列表
*/
@Schema(name = "list", description = "数据列表")
public T list;
public DataList(Integer total, T list) {
this.total = total;
this.list = list;
}
}
/**
* 给ObjectMapper用的,代码中不要调用
*/
public BaseRes() {
}
/**
* 自定义返回码和提示消息
*
* @param code 错误码
* @param msg 提示文字
*/
public BaseRes(int code, String msg) {
this.code = code;
this.msg = msg;
}
public BaseRes(int code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
/**
* 返回成功,但是没有附加数据
*
* @return BaseRes对象
*/
public static BaseRes success() {
return new BaseRes(StatusCode.SUCCESS.getCodeValue(), "请求成功");
}
/**
* 返回成功,带附加数据
*
* @param data 附加数据
* @return BaseRes对象
*/
public static BaseRes successData(Object data) {
BaseRes value = new BaseRes(StatusCode.SUCCESS.getCodeValue(), "请求成功");
value.data = data;
return value;
}
/**
* 返回参数无效响应
*
* @return BaseRes对象
*/
public static BaseRes invalidParam() {
return new BaseRes(StatusCode.INVALID_PARAM.getCodeValue(), "参数无效");
}
/**
* 返回参数无效响应,自定义错误提示
*
* @param msg 提示文字
* @return BaseRes对象
*/
public static BaseRes invalidParam(String msg) {
return new BaseRes(StatusCode.INVALID_PARAM.getCodeValue(), msg);
}
/**
* 返回系统忙无效响应
*
* @return BaseRes对象
*/
public static BaseRes systemBusy() {
return new BaseRes(StatusCode.SYSTEM_BUSY.getCodeValue(), "系统忙");
}
/**
* 返回master key无效响应
*
* @return BaseRes对象
*/
public static BaseRes invalidMasterkey() {
return new BaseRes(StatusCode.INVALID_MASTER_KEY.getCodeValue(), "没有接口访问权限");
}
/**
* 返回失败,附带说明
*
* @return BaseRes对象
*/
public static BaseRes fail(String msg) {
return new BaseRes(StatusCode.FAILURE.getCodeValue(), msg);
}
/**
* 返回错误信息时,仍然返回数据
*
* @param data 数据集
* @param msg 错误信息
* @return BaseRes对象
*/
public static BaseRes failData(Object data, String msg) {
return new BaseRes(StatusCode.FAILURE.getCodeValue(), msg, data);
}
/**
* 登录失效的错误
*
* @return BaseRes对象
*/
public static BaseRes invalidToken() {
return new BaseRes(StatusCode.INVALID_TOKEN.getCodeValue(), "请先登录");
}
/**
* 检查响应处理是否成功
*
* @return 成功返回true,否则false
*/
@JsonIgnore
public boolean isSuccess() {
return (this.code.equals(StatusCode.SUCCESS.getCodeValue()));
}
/**
* 返回分页列表数据
*
* @param total 记录总数
* @param list 列表数据
* @return rsp
*/
public static BaseRes list(long total, Object list) {
DataList data = new DataList((int) total, list);
return BaseRes.successData(data);
}
}