gpt4 book ai didi

java - Spring Boot - 处理用 BindException 包装的异常

转载 作者:行者123 更新时间:2023-11-30 10:19:12 25 4
gpt4 key购买 nike

我正在寻找一种方法来处理在将请求参数绑定(bind)到 DTO 字段期间抛出的自定义异常。

我在 Spring Boot 应用程序中有一个 cantroller,如下所示

@GetMapping("/some/url")
public OutputDTO filterEntities(InputDTO inputDTO) {
return service.getOutput(inputDTO);
}

输入的DTO字段很少,其中一个是枚举类型

public class InputDTO {

private EnumClass enumField;
private String otherField;

/**
* more fields
*/
}

用户将以这种方式点击 URL

localhost:8081/some/url?enumField=wrongValue&otherField=anyValue

现在,如果用户为 enumField 发送了错误的值,我想抛出包含特定消息的 CustomException。枚举实例创建和抛出异常的过程在binder中实现

@InitBinder
public void initEnumClassBinder(final WebDataBinder webdataBinder) {
webdataBinder.registerCustomEditor(
EnumClass.class,
new PropertyEditorSupport() {
@Override
public void setAsText(final String text) throws IllegalArgumentException {
try {
setValue(EnumClass.valueOf(text.toUpperCase()));
} catch (Exception exception) {
throw new CustomException("Exception while deserializing EnumClass from " + text, exception);
}
}
}
);
}

问题是当抛出异常时无法用

@ExceptionHandler(CustomException.class)
public String handleException(CustomException exception) {
// log exception
return exception.getMessage();
}

Spring 使用 BindException 包装初始异常。该实例包含我的初始错误消息,但与其他对我来说多余的文本连接在一起。我不认为对该消息进行解析和子字符串化是件好事...

我错过了什么吗?从初始获取消息的正确方法是什么这里是 CustomException?

最佳答案

您将无法使用带注释的方法处理在进入 Controller 方法之前抛出的异常。 Spring 通过注册 DefaultHandlerExceptionResolver extends AbstractHandlerExceptionResolver 处理程序在进入 Controller 之前处理这些异常。这是 BindingException 的情况,当 Spring 无法绑定(bind)请求参数以匹配您的 InputDTO 对象时抛出。你可以做的是注册你自己的处理程序(创建一个 Component 实现 HandlerExceptionResolverOrdered 接口(interface)),在处理错误时赋予它最高的优先级并根据需要玩异常。您还必须注意 BindException,因为它包装了您的自定义异常 CustomException.class

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger; import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;


import yourpackage.CustomException;

@Component()
public class BindingExceptionResolver implements HandlerExceptionResolver, Ordered {
private static final Logger logger = LoggerFactory.getLogger(BindingExceptionResolver.class);

public BindingExceptionResolver() {
}

private ModelAndView handleException(ObjectError objectError, HttpServletResponse response){
if (objectError == null) return null;
try {
if(objectError.contains(CustomException.class)) {
CustomException ex = objectError.unwrap(CustomException.class);
logger.error(ex.getMessage(), ex);
return handleCustomException(ex, response);
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return null;
}

protected ModelAndView handleCustomException(CustomException ex, HttpServletResponse response) throws IOException {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, ex.getMessage());
return new ModelAndView();
}

@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
try {
if (ex instanceof org.springframework.validation.BindException) {
BindException be = (BindException) ex;
logger.debug("Binding exception in {} :: ({}) :: ({})=({})", be.getObjectName(), be.getBindingResult().getTarget().getClass(), be.getFieldError().getField(), be.getFieldError().getRejectedValue());
return be.getAllErrors().stream()
.filter(o->o.contains(Exception.class))
.map(o ->handleException(o, response))
.filter(mv ->mv !=null)
.findFirst().orElse(null);
}
} catch (Exception handlerException) {
logger.error("Could not handle exception", handlerException);
}
return null;
}


@Override
public int getOrder() {
return Integer.MIN_VALUE;
}

}

希望对你有帮助

关于java - Spring Boot - 处理用 BindException 包装的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48786173/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com