SpringBoot WebSocket场景无@Valid注解校验及内置反序列化使用问题问询
解决方案
1. 编程式实现javax.validation校验
Spring Boot已经自动装配了javax.validation.Validator接口的实例,你只需要注入该对象,手动调用校验API即可完成基于注解的校验,校验不通过时可自行构造MethodArgumentNotValidException抛出,和REST接口@Valid注解触发的异常保持一致。
2. 替换FastJson为Spring内置反序列化器
Spring Boot默认内置Jackson作为JSON处理工具,自动装配了com.fasterxml.jackson.databind.ObjectMapper实例,直接注入即可完成JSON反序列化,和Spring MVC的JSON序列化/反序列化配置保持全局统一,避免多JSON工具的配置冲突问题。
修改后完整代码
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; import lombok.NonNull; import org.springframework.stereotype.Component; import org.springframework.validation.BeanPropertyBindingResult; import org.springframework.validation.Validator; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.WebSocketSession; import org.springframework.web.socket.handler.AbstractWebSocketHandler; import javax.validation.constraints.NotBlank; import lombok.Data; @Data class CustomMessage { @NotBlank private String text; } @Component @Slf4j public class MyCustomWebSocketHandler extends AbstractWebSocketHandler { // 注入Spring内置校验器 private final Validator validator; // 注入Spring内置Jackson序列化器 private final ObjectMapper objectMapper; // 构造函数注入(Spring 4.3+ 单实例Bean无需加@Autowired) public MyCustomWebSocketHandler(Validator validator, ObjectMapper objectMapper) { this.validator = validator; this.objectMapper = objectMapper; } @Override protected void handleTextMessage(@NonNull WebSocketSession session, @NonNull TextMessage message) throws Exception { // 1. 用Jackson完成反序列化 CustomMessage customMessage; try { customMessage = objectMapper.readValue(message.getPayload(), CustomMessage.class); } catch (JsonProcessingException e) { log.error("消息JSON格式错误:{}", message.getPayload(), e); throw e; } // 2. 手动执行校验 BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(customMessage, "customMessage"); validator.validate(customMessage, bindingResult); if (bindingResult.hasErrors()) { // 校验不通过抛出和@Valid一致的异常 throw new MethodArgumentNotValidException(null, bindingResult); } log.debug("Received valid message {}", customMessage); } }
如果需要自定义异常返回,你可以直接从bindingResult中获取所有FieldError字段错误信息,组装后主动推送给WebSocket客户端即可。
内容的提问来源于stack exchange,提问作者Green 绿色
相关产品推荐
相关产品推荐

