component-scan位置不当404
http://blog.tmaize.net/posts/2017/06/24/spring-mvc常见问题.html
一开始Spring和SpringMVC的配置都是一个文件,一点问题没有
后来把一个文件拆分成两个文件,分别是applicationContext.xml和spring-mvc.xml,为的是结构清晰,结果导致所有的controller 404, web.xml配置如下
<!-- 配置Spring容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置SpringMVC -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:config/spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
原因就是Spring是父容器,Spring MVC是子容器,子容器可以访问父容器的bean,父容器不能访问子容器的bean,而MVC容器默认查找当前容器的Controller,所以界面出现404。
有两种解决方式
1.还是使用以前的单文件配置,所有的spring配置在一个文件里,web.xml只需要如下配置即可
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- 里面有spring和springMVC的配置 -->
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
</servlet>
2.分开扫描,springmvc只负责扫描controller
applicationContext.xml文件
<!-- 扫包,不用net.tmaize.crm.* -->
<context:component-scan base-package="net.tmaize.crm">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
spring-mvc.xml文件
<!-- 自动扫包 ,Controller -->
<context:component-scan base-package="net.tmaize.crm.controller" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
@Controller注解为什么要配置<mvc:annotation-driven />
http://mxdxm.iteye.com/blog/2099748
mvc:annotation-driven/相当于注册了DefaultAnnotationHandlerMapping和 AnnotationMethodHandlerAdapter两个bean,配置一些messageconverter。即解决了 @Controller注解的使用前提配置。
context:annotation-config/是对包进行扫描,实现注释驱动Bean定义,同时将bean自动注入容器中使用。即解决了@Controller标识的类的bean的注入和使用。
一开始我在写配置的时候,只写了context:component-scan/,并没有使用mvc:annotation-driven/,servlet拦截*.do,.do请求可以被正确捕捉和处理。代码如下
是什么原因造成这种区别的呢?为什么一开始没用mvc:annotation-driven/的时候可以,添加了默认servlet之后就不行了呢?
最后的配置如果没有mvc:annotation-driven/,那么所有的Controller可能就没有解析, 所有当有请求时候都没有匹配的处理请求类,就都去mvc:default-servlet-handler/即default servlet处理了。添加上mvc:annotation-driven/后,相应的do请求被Controller处理,而静态资源 因为没有相应的Controller就会被default servlet处理。总之没有相应的Controller就会被default servlet处理就ok了。
This tag registers the DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter beans that are required for Spring MVC to dispatch requests to Controllers.
这个标签注册了Spring MVC分发请求到控制器所必须的DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter实例
The tag configures those two beans with sensible defaults based on what is present in your classpath.
标签配置的这2个实例可以根据classpath中的内容默认提供以下功能: