我用Spring Boot和百里香SpringMVC。我有返回百里香模板名称的普通控制器和用< code>@RepsonseBody注释的REST控制器。
假设我有一个< code > EntityNotFoundException ,它是由控制器调用的某个代码抛出的。如果抛出,我想分别为REST控制器返回一个404状态代码和一个错误页面或错误消息。
我当前对普通控制器的设置:
@ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
@Controller
public class FooController {
@RequestMapping("/foo") public String foo() {
try {
...
} catch (EntityNotFoundException enfe) {
throw new ResourceNotFoundException(enfe.getMessage());
}
return "foo";
}
}
对于REST控制程序,我不会捕获异常并让全局异常处理程序拾取它:
@Controller
public class BarController {
@RequestMapping("/bar")
@ResponseBody
public SomeDto bar() throws EntityNotFoundException {
...
return someDto;
}
}
@ControllerAdvice
public class ExceptionHandlerAdvice {
@ExceptionHandler(EntityNotFoundException.class)
public final ResponseEntity<Object> handleEntityNotFoundExceptionEntityNotFoundException enfe) {
return new ResponseEntity<>(enfe.getMessage, HttpStatus.NOT_FOUND);
}
}
我也不想在我的普通控制器中捕捉和重新抛出。全局处理程序应同时处理:
@ExceptionHandler(EntityNotFoundException.class)
public final Object handleEntityNotFoundException(EntityNotFoundException enfe) {
if (/* is REST controller? */) {
return new ResponseEntity<>(enfe.getMessage(), HttpStatus.NOT_FOUND);
} else {
Map<String, Object> model = ImmutableMap.of("message", enfe.getMessage());
return new ModelAndView("error", model, HttpStatus.NOT_FOUND);
}
}
有没有办法确定异常的来源,即控制器是否用@ResponseBody
矿石注释?
您可以将错误代码用作源原因/点,或为从ResourceNotFoundException扩展的不同异常源创建单独的异常。
对于错误代码,您使用一个异常并处理不同的代码,对于额外的异常,您应该创建exrta类。
public class ResourceNotFoundException extends RuntimeException {
private Long sourceErrorCode;//if you use java8 use Optional
public ResourceNotFoundException(String message) {
super(message);
}
public ResourceNotFoundException(String message , Long sourceErrorCode) {
super(message);
this.sourceErrorCode = sourceErrorCode;
}
}
扔
......
catch (EntityNotFoundException enfe) {
throw new ResourceNotFoundException(enfe.getMessage() , ERROR_SOURCE_CODE);
}
和处理程序
@ExceptionHandler(EntityNotFoundException.class)
private Set<Long> REST_CODES = ..add... {code1 , code2...}
public final Object handleSlugNotFoundException(EntityNotFoundException enfe) {
//if you use java 8 use Optional
if (REST_CODES.contains(enfe.getErrorCode())/* is REST controller? */) {
return new ResponseEntity<>(enfe.getMessage(), HttpStatus.NOT_FOUND);
} else {
Map<String, Object> model = ImmutableMap.of("message", enfe.getMessage());
return new ModelAndView("error", model, HttpStatus.NOT_FOUND);
}
}
并为错误代码创建类持有者或枚举,以避免代码重复
我会对普通控制器和REST控制器使用单独的异常,而不是用特殊的返回代码或消息来变魔术。这样,您可以编写简单的有针对性的异常处理程序。
@ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
@ResponseStatus(HttpStatus.NOT_FOUND)
public class RestResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
我找到了解决办法。您可以将当前控制器方法作为< code>HandlerMethod参数注入。
@ExceptionHandler(EntityNotFoundException.class)
public final Object handleEntityNotFoundException(EntityNotFoundException enfe, HandlerMethod handlerMethod) {
boolean isRestController = handlerMethod.hasMethodAnnotation(ResponseBody.class)
|| handlerMethod.getBeanType().isAnnotationPresent(ResponseBody.class)
|| handlerMethod.getBeanType().isAnnotationPresent(RestController.class);
if (isRestController) {
return new ResponseEntity<>(enfe.getMessage(), HttpStatus.NOT_FOUND);
} else {
Map<String, Object> model = ImmutableMap.of("message", enfe.getMessage());
return new ModelAndView("error", model, HttpStatus.NOT_FOUND);
}
}
两者的最后一个调用,即检索特定SomeDto对象的调用,可以抛出ResourceNotFoundException,该调用被配置为返回ResponseStatus NOT_Found: 但是,当调用此“未安全”时,它不会返回404 HTTP状态--它会返回401未授权: 但是,当我在RestController中显式捕获异常并将HttpServletResponse对象上的响应状态设置为 当我用一
是否有一种方法可以找出try块中的哪一行抛出异常? 问题 堆栈跟踪只在catch块中显示OtherException的行 删除try/catch块并不简单,因为有许多声明为抛出的异常,需要捕获这些异常才能编译代码。 感觉应该有一个简单的方法来做到这一点。 注意:这段代码不是我写的;-)
我有一个基于 RestEasy 的服务,我正在其中对容器响应过滤器执行一些清理工作。问题是,如果资源抛出未知的运行时异常(即我没有映射器的异常),则永远不会执行容器响应过滤器。 这是预期的行为吗?是否有解决此问题的方法?我正在查看以下问题(Jonas的回答): 我应该如何在我的RESTful JAX-RS Web服务中记录未捕获的异常? 这使得它看起来像容器响应过滤器被执行,即使控制器中抛出异常?
我有我的spring错误控制器,我需要获得实际的异常类,这样我就可以打印堆栈跟踪和其他类似的东西。这是我的错误控制器 我知道这不多,但我需要Exception对象能够做一些额外的处理。 感谢任何事先的帮助!
我知道您可以使用try-catch块对自定义消息抛出异常,例如: 但是如果我们在实用程序类中有一个方法,例如: 然后我们进入服务类,如下所示: 有没有一种方法可以自定义设置来自实用程序类方法<code>processFiles()</code>的消息及其<code>抛出的IOException</code>,而不是在该方法内部使用try-catch块?
我有一个方面类,用于记录使用泛型方法之前和之后(周围)的方法执行情况: 在方法中,我抛出了一个在logMethod中捕获的可抛出异常,并抛出了一个自定义异常,而不是类型 在我的控制器建议中,我有以下内容: 项目结构: 控制台: