将 HTTP 请求数据转换为枚举时捕获异常

Posted

技术标签:

【中文标题】将 HTTP 请求数据转换为枚举时捕获异常【英文标题】:Catching exception while converting HTTP request data into enum 【发布时间】:2018-11-17 01:10:44 【问题描述】:

我在使用自定义 com.fasterxml.jackson.databind.JsonDeserializer 反序列化器实现将 HTTP 请求值反序列化为枚举时遇到问题:

public class EnvelopeColorJsonDeserializer extends JsonDeserializer<EnvelopeColor> 

    @Override
    public EnvelopeColor deserialize(JsonParser p, DeserializationContext ctxt) throws IOException 
        String val = p.getValueAsString();
        return EnvelopeColor.fromCode(val);
    

这就是我将值转换为枚举的方式:

public static EnvelopeColor fromCode(String code) 
    Assert.notNull(code, "code");
    for (EnvelopeColor type : values()) 
        if (code.equals(type.code)) 
            return type;
        
    
    throw new RuntimeException("Not supported color: " + code);

端点:

@PostMapping("/")
    public @ResponseBody
    ResponseEntity add(@RequestBody EnvelopeDto envelope) 
// some stuff goes here...

问题

有什么方法可以 a) 检查 HTTP 请求值是否是有效的枚举常量值 去反序列化过程或 b) 如何在@ControllerAdvice 异常处理程序中捕获异常? (我想避免在fromCode() 方法中抛出自定义异常)。

【问题讨论】:

您的请求是如何定义的? (您的端点) @VeselinDavidov 添加了 视情况而定。在您的应用程序的正常过程中,您会期待未知的颜色吗?如果是这样,您最好为此定义一个枚举常量。如果不是,则在 fromCode 方法中抛出异常是正确的,因为这是意外行为。 分享信封到详情 【参考方案1】:

对于@ControllerAdvice 异常处理程序中的捕获异常,试试这个:

@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ApplicationExceptionHandler 

    private static Logger logger = LoggerFactory.getLogger(ApplicationExceptionHandler.class);

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(RuntimeException.class)
    public @ResponseBody Response<Error> handleIllegalArgumentException(Exception e) 
        logger.error("BadRequestException :: ", e);
        return new Response<Error>(new Error("BadRequestException", e.getMessage()));
    


【讨论】:

【参考方案2】:

您可以为类HttpMessageNotReadableException 添加异常处理程序。 当 Spring 无法将有效负载反序列化到 DTO 时,将引发此异常。

@ExceptionHandler(org.springframework.http.converter.HttpMessageNotReadableException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
protected @ResponseBody handleIncorrectData(HttpMessageNotReadableException ex,
            HttpServletRequest request, HttpServletResponse response)

....


此外,您可以定义一个自定义 EnumConverter,它将向用户提供正确的枚举值的确切详细信息。

public class CustomEnumConverter extends EnumConverter 

    @Override
    public Object unmarshal(HierarchicalStreamReader reader,
            UnmarshallingContext context) 
        try 
            return super.unmarshal(reader, context);
         catch (IllegalArgumentException e) 
            String inputValue = reader.getValue();
            Class contextType = context.getRequiredType();
            StringBuilder sb = new StringBuilder();
            Object[] enumConstants = contextType.getEnumConstants();
            for (Object o : enumConstants) 
                sb.append(o + ",");
            
            if (sb.length() > 0)
                sb.deleteCharAt(sb.length() - 1);
            throw new InvalidArgumentException(ErrorCode.INVALID_ARGUMENT, inputValue,
                    reader.getNodeName(), sb.toString());
        
    


【讨论】:

以上是关于将 HTTP 请求数据转换为枚举时捕获异常的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 异常:未捕获的类型错误:将循环结构转换为 JSON

未捕获的 SoapFault 异常:HTTP 请求实体太大

JQuery $.ajax 捕获异常信息

致命错误:带有消息的未捕获异常“com_exception”。在将ppt转换为jpg时

从 Node.JS 中的未捕获异常中恢复

从 Node.JS 中的未捕获异常中恢复