refactor: 使用 SpEL Validator 优化部分校验场景

This commit is contained in:
2025-07-06 15:10:08 +08:00
parent acfdfce2cc
commit 0d3c1bb2b1
4 changed files with 21 additions and 24 deletions

View File

@@ -21,6 +21,7 @@ import cn.hutool.core.text.CharSequenceUtil;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
@@ -32,13 +33,13 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.NoHandlerFoundException;
import top.continew.starter.core.constant.StringConstants;
import top.continew.starter.core.exception.BadRequestException;
import top.continew.starter.core.exception.BaseException;
import top.continew.starter.core.exception.BusinessException;
import top.continew.starter.core.util.ExceptionUtils;
import top.continew.starter.web.model.R;
import java.util.Objects;
import org.springframework.validation.BindException;
/**
* 全局异常处理器
@@ -96,16 +97,19 @@ public class GlobalExceptionHandler {
}
/**
* 方法参数无效异常
* 参数校验不通过异常
* <p>
* {@code @NotBlank}、{@code @NotNull} 等参数验证不通过
* </p>
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) {
@ExceptionHandler({BindException.class, MethodArgumentNotValidException.class})
public R handleBindException(BindException e, HttpServletRequest request) {
log.error("[{}] {}", request.getMethod(), request.getRequestURI(), e);
String errorMsg = ExceptionUtils.exToNull(() -> Objects.requireNonNull(e.getBindingResult().getFieldError())
.getDefaultMessage());
String errorMsg = e.getFieldErrors()
.stream()
.findFirst()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.orElse(StringConstants.EMPTY);
return R.fail(String.valueOf(HttpStatus.BAD_REQUEST.value()), errorMsg);
}

View File

@@ -21,7 +21,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.RestController;
import top.continew.admin.common.base.controller.BaseController;
import top.continew.admin.system.enums.NoticeMethodEnum;
import top.continew.admin.system.enums.NoticeScopeEnum;
import top.continew.admin.system.model.query.NoticeQuery;
import top.continew.admin.system.model.req.NoticeReq;
import top.continew.admin.system.model.resp.notice.NoticeDetailResp;
@@ -55,10 +54,6 @@ public class NoticeController extends BaseController<NoticeService, NoticeResp,
return;
}
NoticeReq req = (NoticeReq)args[0];
// 校验通知范围
if (NoticeScopeEnum.USER.equals(req.getNoticeScope())) {
ValidationUtils.throwIfEmpty(req.getNoticeUsers(), "通知用户不能为空");
}
// 校验通知方式
List<Integer> noticeMethods = req.getNoticeMethods();
if (CollUtil.isNotEmpty(noticeMethods)) {

View File

@@ -16,7 +16,11 @@
package top.continew.admin.system.model.req;
import cn.sticki.spel.validator.constrain.SpelNotEmpty;
import cn.sticki.spel.validator.constrain.SpelNotNull;
import cn.sticki.spel.validator.jakarta.SpelValid;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Future;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@@ -36,6 +40,7 @@ import java.util.List;
* @since 2023/8/20 10:55
*/
@Data
@SpelValid
@Schema(description = "公告创建或修改请求参数")
public class NoticeReq implements Serializable {
@@ -76,6 +81,7 @@ public class NoticeReq implements Serializable {
* 通知用户
*/
@Schema(description = "通知用户", example = "[1,2,3]")
@SpelNotEmpty(condition = "#this.noticeScope == T(top.continew.admin.system.enums.NoticeScopeEnum).USER", message = "通知用户不能为空")
private List<String> noticeUsers;
/**
@@ -87,13 +93,16 @@ public class NoticeReq implements Serializable {
/**
* 是否定时
*/
@Schema(description = "是否定时", example = "false")
@Schema(description = "是否定时", example = "true")
@NotNull(message = "是否定时不能为空")
private Boolean isTiming;
/**
* 发布时间
*/
@Schema(description = "发布时间", example = "2023-08-08 00:00:00", type = "string")
@SpelNotNull(condition = "#this.isTiming == true", message = "定时发布时间不能为空")
@Future(message = "定时发布时间不能早于当前时间")
private LocalDateTime publishTime;
/**

View File

@@ -36,7 +36,6 @@ import top.continew.admin.system.service.MessageService;
import top.continew.admin.system.service.NoticeLogService;
import top.continew.admin.system.service.NoticeService;
import top.continew.starter.core.util.validation.CheckUtils;
import top.continew.starter.core.util.validation.ValidationUtils;
import top.continew.starter.extension.crud.model.query.PageQuery;
import top.continew.starter.extension.crud.model.resp.PageResp;
@@ -67,11 +66,6 @@ public class NoticeServiceImpl extends BaseServiceImpl<NoticeMapper, NoticeDO, N
@Override
public void beforeCreate(NoticeReq req) {
// 校验定时发布
if (Boolean.TRUE.equals(req.getIsTiming())) {
ValidationUtils.throwIf(req.getPublishTime() == null, "定时发布时间不能为空");
ValidationUtils.throwIf(req.getPublishTime().isBefore(LocalDateTime.now()), "定时发布时间不能早于当前时间");
}
if (!NoticeStatusEnum.DRAFT.equals(req.getStatus())) {
if (Boolean.TRUE.equals(req.getIsTiming())) {
// 待发布
@@ -113,11 +107,6 @@ public class NoticeServiceImpl extends BaseServiceImpl<NoticeMapper, NoticeDO, N
req.setPublishTime(oldNotice.getPublishTime());
}
case DRAFT, PENDING -> {
// 校验定时发布
if (Boolean.TRUE.equals(req.getIsTiming())) {
ValidationUtils.throwIf(req.getPublishTime() == null, "定时发布时间不能为空");
ValidationUtils.throwIf(req.getPublishTime().isBefore(LocalDateTime.now()), "定时发布时间不能早于当前时间");
}
// 已发布
if (NoticeStatusEnum.PUBLISHED.equals(req.getStatus())) {
if (Boolean.TRUE.equals(req.getIsTiming())) {