一、自定义校验(@State 注解)
1. 自定义注解 @State
用于校验文章状态是否为 已发布 或 草稿:
java
运行
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = StateValidation.class)
public @interface State {
// 校验失败的提示信息
String message() default "文章状态只能是:已发布或者草稿";
// 分组校验支持
Class[] groups() default {};
// 负载信息
Class<? extends Payload>[] payload() default {};
}
2. 校验逻辑实现类 StateValidation
实现 ConstraintValidator 接口,编写具体校验规则:
java
运行
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
public class StateValidation implements ConstraintValidator<State, String> {
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
// 状态不能为空
if (value == null) {
return false;
}
// 校验是否为允许的状态值
return value.equals("已发布") || value.equals("草稿");
}
}
3. 在实体类中使用 @State 注解
java
运行
@Data
public class Article {
private Integer id; // 主键ID
@NotEmpty(message = "文章标题不能为空")
private String title; // 文章标题
@NotEmpty(message = "文章内容不能为空")
private String content; // 文章内容
private String coverImg; // 封面图像
@State(message = "文章状态只能是:已发布或者草稿")
private String state; // 发布状态:已发布/草稿
@NotNull(message = "文章分类ID不能为空")
private Integer categoryId; // 文章分类ID
private Integer createUser; // 创建人ID
private LocalDateTime createTime; // 创建时间
private LocalDateTime updateTime; // 更新时间
}
二、新增文章接口实现
1. Controller 层
java
运行
@RestController
@RequestMapping("/article")
public class ArticleController {
@Autowired
private ArticleService articleService;
@PostMapping
public Result add(@RequestBody @Validated Article article) {
articleService.add(article);
return Result.success();
}
}
2. Service 层
java
运行
@Service
public class ArticleServiceImpl implements ArticleService {
@Autowired
private ArticleMapper articleMapper;
@Override
public void add(Article article) {
// 从 ThreadLocal 获取当前登录用户ID
Map<String, Object> claims = ThreadLocalUtil.get();
Integer userId = (Integer) claims.get("id");
// 自动填充字段
article.setCreateUser(userId);
LocalDateTime now = LocalDateTime.now();
article.setCreateTime(now);
article.setUpdateTime(now);
articleMapper.add(article);
}
}
3. Mapper 层(SQL)
java
运行
@Mapper
public interface ArticleMapper {
@Insert("insert into article(title, content, cover_img, state, category_id, create_user, create_time, update_time) " +
"values(#{title}, #{content}, #{coverImg}, #{state}, #{categoryId}, #{createUser}, #{createTime}, #{updateTime})")
void add(Article article);
}
三、关键注意事项
-
自定义校验生效条件
- 自定义注解上添加
@Constraint(validatedBy = StateValidation.class),关联校验实现类 - 实体类字段上添加
@State注解 - Controller 接口参数前添加
@Validated注解,开启校验
- 自定义注解上添加
-
新增文章接口字段校验
title:非空校验(@NotEmpty)content:非空校验(@NotEmpty)categoryId:非空校验(@NotNull)state:自定义校验(@State),必须为已发布或草稿
-
用户 ID 安全获取
- 不要由前端传入
createUser,统一从ThreadLocal中获取,避免越权发布文章
- 不要由前端传入
-
时间字段自动填充
- 新增时
createTime和updateTime都设置为当前时间,保证数据一致性
- 新增时