基于Spring代码的配置 - IllegalArgumentException:需要ServletContext [英] Spring code-based configuration - IllegalArgumentException: A ServletContext is required

查看:2402
本文介绍了基于Spring代码的配置 - IllegalArgumentException:需要ServletContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里找到了一个基于100%代码的弹簧配置的例子:

I have found an example of 100% code-based spring configuration here:

http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/web/WebApplicationInitializer.html

内容:

public class MyWebAppInitializer implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext container) {
  // Create the 'root' Spring application context
  AnnotationConfigWebApplicationContext rootContext =
    new AnnotationConfigWebApplicationContext();
  rootContext.register(AppConfig.class);

  // Manage the lifecycle of the root application context
  container.addListener(new ContextLoaderListener(rootContext));

  // Create the dispatcher servlet's Spring application context
  AnnotationConfigWebApplicationContext dispatcherContext =
    new AnnotationConfigWebApplicationContext();
  dispatcherContext.register(DispatcherConfig.class);

  // Register and map the dispatcher servlet
  ServletRegistration.Dynamic dispatcher =
    container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
  dispatcher.setLoadOnStartup(1);
  dispatcher.addMapping("/");
}

}

refresh()注册配置类后。
但是API说 - 必须调用refresh()才能使上下文完全处理新类。
所以我添加refresh()每个寄存器语句

In the example above they never called refresh() after registering a configuration class. But API says - that refresh() must be called in order for the context to fully process the new class. So I added refresh() afrer each register statement

rootContext.register(AppConfig.class);
rootContext.refresh();

dispatcherContext.register(DispatcherConfig.class);
dispatcherContext.refresh();

结果:

SEVERE: ContainerBase.addChild: start: 
org.apache.catalina.LifecycleException: Failed to start component    [StandardEngine[Catalina].StandardHost[localhost].StandardContext[]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:726)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:702)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:699)
at org.apache.catalina.startup.HostConfig.manageApp(HostConfig.java:1647)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:465)
at org.apache.catalina.mbeans.MBeanFactory.createStandardContext(MBeanFactory.java:415)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1487)
at javax.management.remote.rmi.RMIConnectionImpl.access$300(RMIConnectionImpl.java:97)
at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1328)
at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1420)
at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:848)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:322)
at sun.rmi.transport.Transport$1.run(Transport.java:177)
at sun.rmi.transport.Transport$1.run(Transport.java:174)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:556)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:811)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:670)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultServletHandlerMapping' defined in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.web.servlet.HandlerMapping org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.defaultServletHandlerMapping()] threw exception; nested exception is java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:592)


推荐答案

在这种情况下,这只对于 ApplicationContext 传递给 DispatcherServlet DispatcherServlet 构造函数状态

In your case, this is only important for the ApplicationContext passed to the DispatcherServlet. That DispatcherServlet constructor states


给定的Web应用程序上下文可能尚未刷新。如果
尚未刷新(建议的方法),那么将会出现

The given web application context may or may not yet be refreshed. If it has not already been refreshed (the recommended approach), then the following will occur:


  • 如果给定的上下文没有父级,则根应用上下文将被设置为父级。

  • 如果给定的上下文尚未分配ID,则会为其分配一个

  • ServletContext ServletConfig 对象将被委派给应用程序上下文

  • postProcessWebApplicationContext 将被调用

  • 任何 ApplicationContextInitializers 通过
    指定contextInitializerClasses param或通过
    的setContextInitializers属性将被应用。如果上下文实现 ConfigurableApplicationContext
  • ,将调用
  • refresh li>
  • If the given context does not already have a parent, the root application context will be set as the parent.
  • If the given context has not already been assigned an id, one will be assigned to it
  • ServletContext and ServletConfig objects will be delegated to the application context
  • postProcessWebApplicationContext will be called
  • Any ApplicationContextInitializers specified through the "contextInitializerClasses" init-param or through the setContextInitializers property will be applied.
  • refresh() will be called if the context implements ConfigurableApplicationContext

如果上下文已经刷新,上面将不会出现
,假设用户有

因此,对于 DispatcherServlet ,您必须执行以下操作:

So for the DispatcherServlet, you have to do the following

AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.register(DispatcherConfig.class);

// will take care of calling refresh() on the ApplicationContext
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));

这是 DispatcherServlet 配置所必需的,因为由于 @EnableWebMvc (或等效的< mvc:annotation-driven> )生成的一些bean需要 ServletContext 和/或 ServletConfig 由Servlet容器提供的对象。

This is necessary for the DispatcherServlet configuration because some of the beans generated because of @EnableWebMvc (or the equivalent <mvc:annotation-driven>) require the ServletContext and/or ServletConfig objects which are provided by the Servlet container.

根上下文不应该有这样的依赖,所以它是安全的做

The root context should not have such dependencies so it is safe to do

AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(AppConfig.class);
rootContext.refresh();



<通过将 @Configuration 类作为参数传递给它的构造函数。

Note that you could just create the AnnotationConfigWebApplicationContext object by passing the @Configuration classes as arguments to its constructor.

这篇关于基于Spring代码的配置 - IllegalArgumentException:需要ServletContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆