报错如下(备注:我是springmvc xml零配置项目通过嵌入式tomcat启动):
原因:tomcat上下文context在addServlet时,传入了空参构造的DispatcherServlet的。
官网对于DispatcherServlet
是这么说的:
DispatcherServlet
expects a WebApplicationContext
(an extension of a plain ApplicationContext
) for its own configuration. WebApplicationContext
has a link to the ServletContext
and the Servlet
with which it is associated. It is also bound to the ServletContext
such that applications can use static methods on RequestContextUtils
to look up the WebApplicationContext
if they need access to it.
也就是说DispatcherServlet需要有一个IOC容器上下文进行自身的配置
如果我们回顾springmvc xml配置文件就会发现DispatcherServlet的确在xml文件中会通过
init-param标签中的contextConfigLocation属性进行初始化配置
然后我们看看官网的DispatcherServlet层级结构图:
DispatcherServlet的底层运作的确是需要IOC容器上下文的:
根容器:提供bean服务(service/dao等),供子容器使用
子容器:前端路由控制器,视图解析器等,依赖于父容器提供的bean服务
总而言之: DispatcherServlet必须跟IOC容器上下文WebApplicationContext绑定
顺附上国外的一篇DispatcherServlet用法的讲解:
The org.springframework.web.servlet.DispatcherServlet needs an org.springframework.web.context.WebApplicationContext to configure itself with the needed components. You can either let the servlet construct one itself or use the constructor to pass an application context. In an XML-based configuration
file, the first option is used (because there is no way to construct an application context). In a Java-based configuration, the second option is used
大概意思是:DispatcherServlet需要有WebApplicationContext上下文对自身进行配置。
使用xml文件时,可以通过空参构造进行配置,因为xml文件中没法通过构造方法传入IOC容器上下文WebApplicationContext;
但是如果是java编程模式就必须通过有参构造传入IOC容器上下文WebApplicationContext
因为:我这里是xml零配置,所以采用方法2
但是我这里又扩展了一种方法,所以即便是xml零配置,我也有两种方法:
解决办法1: 给DispatcherServlet传入构造参数:WebApplicationContext
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(AppStarter.class); // 将注解类的配置注册到IOC容器,这样注解中包含的bean都会被注入到IOC容器
context.refresh();
// addServlet方法不能接收空构造的DispatcherServlet,否则会报错:Could not open ServletContext resource [/WEB-INF/xxxServlet-servlet.xml]
Dynamic registration1 = servletContext.addServlet("appServlet", new DispatcherServlet(context));
解决办法2:空参DispatcherServlet的通过SetWebApplicationContext方法绑定IOC容器上下文
(这种情况多半是DispatcherServlet通过bean注入的,但是没法跟IOC容器直接绑定
)
特别注意: 创建IOC容器时返回类型一定要特别注意:返回类型必须是AnnotationConfigWebApplicationContext类型,不能为AnnotationConfigApplicationContext,否则传入DispatcherServlet时就会报错!