无法使用 @EnableWebMvc 配置运行 SPRING BOOT 应用程序
Posted
技术标签:
【中文标题】无法使用 @EnableWebMvc 配置运行 SPRING BOOT 应用程序【英文标题】:Can't run the SPRING BOOT application with @EnableWebMvc configuration 【发布时间】:2018-07-21 04:15:26 【问题描述】:我是 Spring Boot 新手,我对学习这项技术非常感兴趣。这是问题所在,我得到了一个带有@configuration 标签的配置文件。因此,当我尝试添加 @enablemvc 注释或在 Spring Boot 应用程序中添加带有 @enablemvc 注释的新文件时,我无法运行该应用程序。如果有人能帮我解决这个问题,我真的很感激。
日志
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'resourceHandlerMapping' defined in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'resourceHandlerMapping' threw exception; nested exception is org.springframework.beans.factory.BeanInitializationException: Failed to init ResourceHttpRequestHandler; nested exception is java.lang.IllegalStateException: WebApplicationObjectSupport instance [ResourceHttpRequestHandler [locations=[class path resource [resources/], class path resource [images/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@39e6b948]]] does not run in a WebApplicationContext but in: org.springframework.context.annotation.AnnotationConfigApplicationContext@19b44076: startup date [Sat Feb 10 09:34:19 EST 2018]; root of context hierarchy
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1173) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1067) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:693) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:360) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) ~[spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:134) [spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.boot.builder.SpringApplicationBuilder.configureAsChildIfNecessary(SpringApplicationBuilder.java:147) [spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:130) [spring-boot-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at com.boot.main.ClientMain.main(ClientMain.java:31) [bin/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_131]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_131]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_131]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-1.5.9.RELEASE.jar:1.5.9.RELEASE]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'resourceHandlerMapping' threw exception; nested exception is org.springframework.beans.factory.BeanInitializationException: Failed to init ResourceHttpRequestHandler; nested exception is java.lang.IllegalStateException: WebApplicationObjectSupport instance [ResourceHttpRequestHandler [locations=[class path resource [resources/], class path resource [images/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@39e6b948]]] does not run in a WebApplicationContext but in: org.springframework.context.annotation.AnnotationConfigApplicationContext@19b44076: startup date [Sat Feb 10 09:34:19 EST 2018]; root of context hierarchy
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
... 23 common frames omitted
Caused by: org.springframework.beans.factory.BeanInitializationException: Failed to init ResourceHttpRequestHandler; nested exception is java.lang.IllegalStateException: WebApplicationObjectSupport instance [ResourceHttpRequestHandler [locations=[class path resource [resources/], class path resource [images/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@39e6b948]]] does not run in a WebApplicationContext but in: org.springframework.context.annotation.AnnotationConfigApplicationContext@19b44076: startup date [Sat Feb 10 09:34:19 EST 2018]; root of context hierarchy
at org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry.getHandlerMapping(ResourceHandlerRegistry.java:150) ~[spring-webmvc-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.resourceHandlerMapping(WebMvcConfigurationSupport.java:446) ~[spring-webmvc-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$7c7bc0fe.CGLIB$resourceHandlerMapping$28(<generated>) ~[spring-webmvc-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$7c7bc0fe$$FastClassBySpringCGLIB$$d042f6eb.invoke(<generated>) ~[spring-webmvc-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228) ~[spring-core-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358) ~[spring-context-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$7c7bc0fe.resourceHandlerMapping(<generated>) ~[spring-webmvc-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_131]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_131]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_131]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162) ~[spring-beans-4.3.13.RELEASE.jar:4.3.13.RELEASE]
... 24 common frames omitted
Caused by: java.lang.IllegalStateException: WebApplicationObjectSupport instance [ResourceHttpRequestHandler [locations=[class path resource [resources/], class path resource [images/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@39e6b948]]] does not run in a WebApplicationContext but in: org.springframework.context.annotation.AnnotationConfigApplicationContext@19b44076: startup date [Sat Feb 10 09:34:19 EST 2018]; root of context hierarchy
at org.springframework.web.context.support.WebApplicationObjectSupport.getWebApplicationContext(WebApplicationObjectSupport.java:112) ~[spring-web-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.web.context.support.WebApplicationObjectSupport.getServletContext(WebApplicationObjectSupport.java:128) ~[spring-web-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.web.servlet.resource.ResourceHttpRequestHandler.initContentNegotiationStrategy(ResourceHttpRequestHandler.java:306) ~[spring-webmvc-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.web.servlet.resource.ResourceHttpRequestHandler.afterPropertiesSet(ResourceHttpRequestHandler.java:268) ~[spring-webmvc-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry.getHandlerMapping(ResourceHandlerRegistry.java:147) ~[spring-webmvc-4.3.12.RELEASE.jar:4.3.12.RELEASE]
... 35 common frames omitted
AutoConfiguration.java
@Configuration
//@EnableAutoConfiguration
@ConditionalOnClass(MyClass.class)
@EnableConfigurationProperties(MyProperties.class)
@ComponentScan( "com.boot", "com.jspClient" )
@SpringBootApplication
public class AutoConfiguration
private static Log log = LogFactory.getLog(AutoConfiguration.class);
@Bean
public ViewResolver getViewResolver()
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
/*@Bean
public UrlBasedViewResolver urlBasedViewResolver()
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
*/
//http://www.logicbig.com/tutorials/spring-framework/spring-web-mvc/simple-mapping-exception-resolver/
//https://github.com/paulc4/mvc-exceptions/blob/master/src/main/java/demo/config/ExceptionConfiguration.java
@Bean
public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver()
SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
Properties errorMaps = new Properties();
errorMaps.setProperty(UserNotFoundException.class.getName(), "myError");
errorMaps.setProperty("Exception", "generic_error");
resolver.setExceptionMappings(errorMaps);
resolver.setDefaultErrorView("generic_error");
resolver.setExceptionAttribute("exc");
return resolver;
@Bean
WebMvcConfigurer configurer ()
return new WebMvcConfigurerAdapter()
@Override
public void addResourceHandlers (ResourceHandlerRegistry registry)
ResourceHandlerRegistration resourceRegistration = registry
.addResourceHandler("/pages/**")
.addResourceLocations("/resources/","classpath:/images/") //Configuring Multiple Locations for a Resource
.setCachePeriod(3600); //The resources served will be cached in the browser for 3600 seconds
registry.addResourceHandler("resources/**").addResourceLocations("/resources/");
//registry.addResourceHandler("/css/**").addResourceLocations("/css/");
//registry.addResourceHandler("/img/**").addResourceLocations("/img/");
//registry.addResourceHandler("/js/**").addResourceLocations("/js/");
;
AppConfig.java
@Configuration
@ComponentScan("com.boot.controllers")
@EnableWebMvc
public class AppConfig extends WebMvcConfigurerAdapter
@Bean
public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver()
SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
Properties errorMaps = new Properties();
errorMaps.setProperty("ElectricityNotFoundException", "error");
errorMaps.setProperty("NullPointerException", "error");
resolver.setExceptionMappings(errorMaps);
resolver.setDefaultErrorView("globalerror");
resolver.setExceptionAttribute("exc");
return resolver;
WebAppInitializer.java
public class WebAppInitializer implements WebApplicationInitializer
public void onStartup(ServletContext servletContext) throws ServletException
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(AppConfig.class);
ctx.setServletContext(servletContext);
Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
dynamic.addMapping("/");
dynamic.setLoadOnStartup(1);
ClientMain.java
@ComponentScan("com.boot") // to scan controller under com.boot -> com.boot.controllers
@SpringBootApplication
public class ClientMain
private static SpringApplicationBuilder start(Class<?>... sources)
return new SpringApplicationBuilder(ClientMain.class)
.child(sources);
public static void main(String[] args) throws Exception
// using just Spring alone
/*ApplicationContext context = new AnnotationConfigApplicationContext(AutoConfiguration.class);
JspClientMain.java
@ComponentScan("com.boot")
@SpringBootApplication
public class JspClientMain
public static void main(String[] args)
SpringApplication.run(JspClientMain.class, args);
【问题讨论】:
可能相关dzone.com/articles/… documentation explains why you should or not use the annotation. 【参考方案1】:一般情况下,@EnableWebMvc
不应在 Spring Boot 应用程序中使用。我引用article by Boz Hogan:
事实证明 Spring Boot 不能与标准 Spring MVC
@EnableWebMvc
很好地混合。添加注解时会发生什么,Spring Boot 的自动配置被禁用。不好的部分(浪费了我几个小时)是在任何指南中都找不到明确说明的内容。 (...)
这是Spring Boot documentation的引述:
如果你想保留 Spring Boot MVC 特性并且你想添加额外的 MVC 配置(拦截器、格式化程序、视图控制器和其他特性),你可以添加你自己的
@Configuration
类型的WebMvcConfigurer
但是 没有@EnableWebMvc
。 (...)如果您想完全控制 Spring MVC,可以添加自己的
@Configuration
,并带有@EnableWebMvc
注释。
因此,要在 Spring Boot 应用程序中使用 @EnableWebMvc
,您需要完全控制 Spring MVC — 我认为 您需要成为 Spring 专家.
我们遇到了一个 Spring boot 1.5.9 应用程序的问题,该应用程序依赖于一个共享库,该库包含一个用 @EnableWebMvc
注释的类。删除注释解决了问题。
【讨论】:
本文虽然讨论不使用它,但并不意味着不应该使用它。更糟糕的是,这篇文章没有提供另一种方法来实现注释的功能而不使用它。 documentation explains a lot better the why you should or not use the annotation @JonathanDrapeau 请注意,答案是关于在 Spring Boot 应用程序中使用@EnableWebMvc
。甚至 Spring 文档都说您应该添加拦截器等。没有 @EnableWebMvc
。无论如何,我更新了答案以添加相关引号。感谢您的反馈。【参考方案2】:
问题似乎是由于混合了两种不同类型的初始化程序,即 WebApplicationInitializer 和 ApplicationContextInitializer。
WebApplicationInitializer 和 ApplicationContextInitializer 的用途完全不同。 WebApplicationInitializer 由 Servlet 容器在 Web 应用程序启动时使用,并提供一种以编程方式创建 Web 应用程序的方法(替换 web.xml 文件),
ApplicationContextInitializer 提供了一个钩子,用于在 Spring 应用程序上下文完全创建之前对其进行配置。 对于非 spring boot 应用程序/普通 spring mvc 应用程序,它是 web.xml 的编程配置。就像您在 WebAppInitializer.java 中的代码中所做的那样
public class WebAppInitializer implements WebApplicationInitializer
public void onStartup(ServletContext servletContext) throws
ServletException
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(AppConfig.class);
ctx.setServletContext(servletContext);
Dynamic dynamic = servletContext.addServlet("dispatcher", new
DispatcherServlet(ctx));
dynamic.addMapping("/");
dynamic.setLoadOnStartup(1);
ApplicationContextInitializer 本质上是在 Spring 应用程序上下文完全创建之前执行的代码。使用 ApplicationContextInitializer 的一个很好的用例是按照这些思路以编程方式设置 Spring 环境配置文件。
对于基于 Spring-Boot 的应用程序,可以像下面这样注册 ApplicationContextInitializer:
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class SampleWebApplication
public static void main(String[] args)
new SpringApplicationBuilder(SampleWebApplication.class)
.initializers(new DemoApplicationContextInitializer())
.run(args);
public class DemoApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>
@Override
public void initialize(ConfigurableApplicationContext ac)
ConfigurableEnvironment appEnvironment = ac.getEnvironment();
appEnvironment.addActiveProfile("demo");
【讨论】:
以上是关于无法使用 @EnableWebMvc 配置运行 SPRING BOOT 应用程序的主要内容,如果未能解决你的问题,请参考以下文章
在spring boot中使用@EnableWebMvc 一定要注意的问题!
使用 @EnableWebMvc 和 WebMvcConfigurerAdapter 进行静态资源定位的 Spring MVC 配置会导致“转发:”和“重定向:”出现问题