Java Spring启动-用BindException包装句柄异常
我正在寻找一种方法来处理将请求参数绑定到DTO字段期间引发的自定义异常 我在Spring Boot应用程序中有一个cantroller,如下所示Java Spring启动-用BindException包装句柄异常,java,spring-boot,exception-handling,Java,Spring Boot,Exception Handling,我正在寻找一种方法来处理将请求参数绑定到DTO字段期间引发的自定义异常 我在Spring Boot应用程序中有一个cantroller,如下所示 @GetMapping("/some/url") public OutputDTO filterEntities(InputDTO inputDTO) { return service.getOutput(inputDTO); } 输入DTO有几个字段,其中一个是枚举类型 public class InputDTO { privat
@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 here?在使用
@ExceptionHandler
注释方法进入控制器方法之前,您将无法处理抛出的异常。Spring通过注册DefaultHandlerExceptionResolver扩展AbstractHandlerExceptionResolver
handler,在进入控制器之前处理这些异常。
这是BindingException的情况,当Spring无法将请求参数绑定到与InputDTO对象匹配时抛出。
您可以注册自己的处理程序(创建一个实现HandlerExceptionResolver
和Ordered
接口的组件
),为它提供处理错误的最高优先级,并根据需要处理异常。
您还必须注意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;
}
}
希望能有所帮助我首先检查了一下。BindException实例的getClause()方法返回null。您看到了吗?非常感谢@bogdotro。你的解释很有帮助。