将 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