Spring Boot 全局控制器建议未在 Spring 上下文中加载
Posted
技术标签:
【中文标题】Spring Boot 全局控制器建议未在 Spring 上下文中加载【英文标题】:Spring Boot global controller advice is not loaded in Spring Context 【发布时间】:2019-01-15 07:05:04 【问题描述】:我有一个控制器来接收 POST 请求并返回 JSON 输出。在控制器类中实现的异常处理程序运行良好。
我尝试使用@ControllerAdvice
注释添加全局异常处理,但这在我的解决方案中不起作用。我认为没有加载全局异常处理程序类。
下面是我的控制器类:
package hello;
@Controller
@RequestMapping("/v1")
public class MyController
@RequestMapping(value = "/saveEmployee", method = RequestMethod.POST, produces = "application/json")
@ResponseBody
public String saveEmployee(@Valid @RequestBody Employee employee)
return " \"name\":\"" + employee.getEmail() + "\"";
下面是全局异常处理类:
package util;
@ControllerAdvice
public class MyControllerAdvice
@ExceptionHandler(MethodArgumentNotValidException.class)
// @ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public String processValidationError(MethodArgumentNotValidException ex)
BindingResult result = ex.getBindingResult();
FieldError fieldError = result.getFieldError();
String code = fieldError.getCode();
String field = fieldError.getField();
String message = fieldError.getDefaultMessage();
message = " \"Code\":\"" + code + "\",\"field\":\"" + field + "\",\"Message\":\"" + message + "\"";
return message;
以下是我的配置:
package hello;
@SpringBootApplication
public class Application
@Bean
public MessageSource messageSource()
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
@Bean
public LocalValidatorFactoryBean validator()
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(messageSource());
return bean;
public static void main(String[] args)
SpringApplication.run(Application.class, args);
Spring boot 版本:2.0.3.RELEASE
【问题讨论】:
这是我在传递给控制器的无效参数中收到的内容“[nio-8080-exec-2] .wsmsDefaultHandlerExceptionResolver:已解决由处理程序执行引起的异常:org.springframework.web.bind.MethodArgumentNotValidException :方法中索引 0 处的参数验证失败:“@Piotr Rogowski 您能发布您对上述控制器的 Spring 配置吗?我看到控制器位于名为hello
的包中,而异常处理程序位于名为util
的包中。我的第一个问题是您没有将异常处理程序带入上下文。
【参考方案1】:
我认为您在这里遇到的问题正是您发现的问题。 MyControllerAdvice
类未加载。根据您发布的代码,我推断您的项目结构类似于:
src
main
java
hello
Application.java
MyController.java
util
MyControllerAdvice.java
因为您的 SpringBootApplication
类上有 SpringBootApplication
注释,所以 Spring Boot 使用它作为创建 bean 的起点,它会查找带有 @Controller
和 @ControllerAdvice
等注释的类(以及其他)添加到它的上下文中。
有许多不同的配置方法,但如果您刚开始或正在处理一个相对较小的项目,最简单的方法是对其进行重组以适应 Spring 在此处的建议:
https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-structuring-your-code.html
该页面很短,值得一读以了解背景,但本质是您希望您的@SpringBootApplication
注释类与您希望Spring管理的所有类在同一个包或父包中,上面的页面举个例子:
com
+- example
+- myapplication
+- Application.java
|
+- customer
| +- Customer.java
| +- CustomerController.java
| +- CustomerService.java
| +- CustomerRepository.java
|
+- order
+- Order.java
+- OrderController.java
+- OrderService.java
+- OrderRepository.java
因此,在您的情况下,这意味着将 util
包移动到 hello
下,例如:
src
main
java
hello
Application.java
MyController.java
util
MyControllerAdvice.java
或者为hello
和util
创建一个父包并将Application
移动到该包,例如:
src
main
java
example
Application.java
hello
MyController.java
util
MyControllerAdvice.java
【讨论】:
是的。这行得通。我已经重新构建了整个项目。现在 Spring 引导已将 @ControllerAdvice 添加到上下文中。谢谢【参考方案2】:试试这个:@ControllerAdvice("hello")
根据ControllerAdvice
的文档:
将包含属于这些基础包或其子包的控制器,例如:@ControllerAdvice(basePackages="org.my.pkg") 或 @ControllerAdvice(basePackages="org.my.pkg", " org.my.other.pkg")。 value 是该属性的别名,只是允许更简洁地使用注释。 还可以考虑使用 basePackageClasses() 作为基于字符串的包名称的类型安全替代方案。
【讨论】:
我已经试过了。但没有区别。我观察到的是“DefaultHandlerExceptionResolver:由处理程序执行引起的已解决异常:org.springframework.web.bind.MethodArgumentNotValidException:”@Hank 试试把MyControllerAdvice
放到MyController
的同一个包里。我可以重现您的问题并通过我的解决方案解决它。
是的。我只是尝试了与您提到的相同的方法,并且有效。谢谢。但是你有什么理由不把 MyControllerAdvice 放在不同的包中工作吗? @汉克
@DaveyDaveDave 的回答解释了我的观点。 Spring 使用 @SpringBootApplication
类的包作为默认根包,并扫描该根包下的 Beans/Configurations。这就是为什么你的@ControllerAdvice
一开始没有被Spring 找到:)。但也请注意,仅将@SpringBootApplication
拉到上层是不够的,@ControllerAdvice
默认只影响@Controller
的相同包(和子包),除非你正确配置basePackages
。
是的。这是一个很好的建议。我正确配置了基础包并对问题进行了排序。@Hank【参考方案3】:
你确定它会抛出 MethodArgumentNotValidException 吗?像这样制作默认处理程序
@ExceptionHandler(value = Exception.class)
public ResponseEntity<Object> exception(Exception exception)
return new ResponseEntity<>(exception, HttpStatus.BAD_REQUEST)
【讨论】:
没有。这行不通。是的,我确定它会触发 MethodArgumentNotValidException @GerNik 如果它没有被其他处理程序捕获,这有助于我获得洞察力。以上是关于Spring Boot 全局控制器建议未在 Spring 上下文中加载的主要内容,如果未能解决你的问题,请参考以下文章
JSP 文件未在 Spring Boot Web 应用程序中呈现
使用邮递员返回错误请求,但未在单元测试 Spring Boot 中返回
多部分表单数据输入 Java 模型属性未在请求类中注入元素 - Spring Boot
Spring boot 配置文件详解 (properties 和yml )