Spring Boot请求参数枚举类型校验及匹配值获取方案咨询
解决方案
1. 补全枚举类的Getter方法
你当前的枚举类中event字段是私有属性,没有对外访问方法,首先需要补全Getter,既方便后续获取枚举对应值,也可以供自定义转换器做匹配校验:
public enum EventTypes { ADDONE("AddOne"), DELETEONE("DeleteOne"), ADDTWO("AddTwo"), DELETETWO("DeleteTwo"); private String event; private EventTypes(String event){ this.event = event; } // 新增Getter方法 public String getEvent() { return event; } }
2. 自定义枚举转换器解决参数匹配问题
Spring默认的请求参数枚举转换器只会匹配枚举常量名(也就是ADDONE这类大写下划线格式),你需要自定义转换器支持匹配event字段的驼峰格式值,同时不匹配时直接抛出异常:
import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; @Component // 加此注解Spring Boot会自动将转换器注册到MVC转换服务中 public class EventTypesConverter implements Converter<String, EventTypes> { @Override public EventTypes convert(String source) { for (EventTypes type : EventTypes.values()) { if (type.getEvent().equals(source)) { return type; } } // 不匹配时直接抛出异常 throw new IllegalArgumentException("非法事件类型:" + source + ",可选值为AddOne/DeleteOne/AddTwo/DeleteTwo"); } }
配置完成后,你原来的控制器代码不需要修改,传参eventType=AddOne会自动转换为EventTypes.ADDONE类型。
3. 实现控制器到Service层之间的自定义逻辑
根据你的业务场景可以二选一实现:
方案A:直接在控制器中调用(逻辑仅和当前接口关联推荐使用,最简洁)
先写自定义逻辑的公共处理类:
import org.springframework.stereotype.Component; @Component public class EventPostProcessor { public void process(EventTypes eventType, MessageRequest request) { // 这里写你需要执行的自定义逻辑 System.out.println("执行自定义逻辑,当前事件类型:" + eventType.getEvent()); } }
然后在控制器中调用即可:
@Autowired private EventPostProcessor eventPostProcessor; @PostMapping(value = "/eventProcess", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public GenericResponse produceEventMessage( @Parameter(in = ParameterIn.QUERY, description = "", required = true) @RequestParam(value = "eventType", required = true) EventTypes eventType, @Valid @RequestBody MessageRequest messageEventRequest) { LOG.info("Event Type ::::" + eventType); // 调用自定义逻辑,执行完成后再调用Service层 eventPostProcessor.process(eventType, messageEventRequest); // 后续业务逻辑 ... }
方案B:AOP切面实现(通用逻辑、多个接口都需要执行推荐使用)
如果自定义逻辑是所有事件接口通用的,可以用AOP切入自动执行,不需要每个控制器手动调用:
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Aspect @Component public class EventProcessAspect { // 替换为你实际控制器方法的路径 @Pointcut("execution(* com.xxx.controller.EventController.produceEventMessage(..))") public void eventPointcut() {} @Before("eventPointcut()") public void beforeProcessEvent(JoinPoint joinPoint) { Object[] args = joinPoint.getArgs(); for (Object arg : args) { if (arg instanceof EventTypes eventType) { // 执行你的自定义逻辑 System.out.println("AOP执行自定义逻辑,当前事件类型:" + eventType.getEvent()); break; } } } }
4. 枚举不匹配的异常统一处理
可以通过全局异常捕获给客户端返回友好的错误响应:
import org.springframework.core.convert.ConversionFailedException; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(ConversionFailedException.class) public ResponseEntity<GenericResponse> handleEventTypeError(ConversionFailedException e) { if (e.getTargetType().getType() == EventTypes.class) { GenericResponse resp = new GenericResponse(); resp.setCode(400); resp.setMsg(e.getCause().getMessage()); return ResponseEntity.badRequest().body(resp); } throw e; } }
内容的提问来源于stack exchange,提问作者Tarun Pande
相关产品推荐
相关产品推荐

