Spring MVC:<context:component-scan> 之间的区别和<注释驱动/>标签?
前几天开始研究这个Spring Hello World教程:http://viralpatel.net/blogs/spring-3-mvc-create-hello-world-application-spring-3-mvc/
Some days ago I began to study this Spring Hello World Tutorial: http://viralpatel.net/blogs/spring-3-mvc-create-hello-world-application-spring-3-mvc/
在本教程中,Spring DispatcherServlet 是使用 spring-servlet.xml 文件配置的,这个:
In this tutorial Spring DispatcherServlet is configured using the spring-servlet.xml file, this one:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="net.viralpatel.spring3.controller" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
在这个文件中,我使用 context:component-scan 标签来表示 Spring 必须扫描我的文件以搜索注解,例如,当控制器类发现一个方法被注解时通过 @RequestMapping("/hello") 注释知道该方法处理向以/hello"结尾的 URL 的 HTTP 请求.这很简单……
In this file I am using the context:component-scan tag to say that Spring have to scan my file searching the annotation, so for example, when the controller class finds that a method is annotated by @RequestMapping("/hello") annotation knows that this method handles the HTTP Request toward the URL ending with "/hello". This is simple...
现在我的疑问与我可以在 STSEclipse 中自动构建的 Spring MVC 模板项目有关.
Now my doubt is related to the Spring MVC template project that I could automatically build in STSEclipse.
当我在 STS 中创建一个新的 Spring MVC 项目时,我的 DispatcherServlet 是由一个名为 servlet-context.xml 的文件配置的,该文件包含一些类似于上一个示例文件.
When I create a new Spring MVC project in STS I have that my DispatcherServlet is configured by a file named servlet-context.xml that contains some configuration similar to the previous example file.
在这个文件中,我还有组件扫描标签:
In this file, I still have the component scan tag:
<context:component-scan base-package="com.mycompany.maventestwebapp" />
但我还有另一个标签(看起来有类似的任务),这个:
but I have also another tag (that look like have similar task), this one:
<annotation-driven />
这两个标签有什么区别?
另一个奇怪"的事情是前面的示例(不使用注释驱动标签)与 STS 使用 Spring MVC 模板项目创建的项目非常相似,但是如果我从其配置中删除注释驱动标签文件项目不运行并给我以下错误:HTTP Status 404 -
What is the difference between these two tags?
An other "strange" thing is that the previous example (that don't use the annotation-driven tag) is very similar to the project create by STS using the Spring MVC Template project but if I delete the annotation-driven tag from its configuration file the project don't run and give me the following error: HTTP Status 404 -
在堆栈跟踪中我有:
警告:org.springframework.web.servlet.PageNotFound - 在名为appServlet"的 DispatcherServlet 中找不到具有 URI [/maventestwebapp/] 的 HTTP 请求的映射
但是为什么呢?前面的例子在没有注释驱动标签的情况下运行良好,这个控制器类非常相似.实际上,只有一种方法可以处理对/"路径的 HTTP 请求
But why? The previous example works well without annotation-driven tag, and this controller class is very similar. In fact, there is only one method that handles HTTP request toward "/" path
这是我的控制器类的代码:
This is the code of my controller class:
package com.mycompany.maventestwebapp;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* Handles requests for the application home page.
*/
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "home";
}
有人可以帮我理解这件事吗?
Can someone help me to understand this thing?
非常感谢!
推荐答案
<mvc:annotation-driven/>
表示可以定义spring beans依赖,而不必实际指定一堆XML 中的元素或实现接口或扩展基类.例如 @Repository
告诉 spring 一个类是一个 Dao,而不必扩展 JpaDaoSupport
或 DaoSupport 的一些其他子类.类似地,@Controller
告诉 spring,指定的类包含将处理 Http 请求的方法,而无需实现 Controller 接口或扩展实现控制器的子类.
<mvc:annotation-driven />
means that you can define spring beans dependencies without actually having to specify a bunch of elements in XML or implement an interface or extend a base class. For example @Repository
to tell spring that a class is a Dao without having to extend JpaDaoSupport
or some other subclass of DaoSupport. Similarly @Controller
tells spring that the class specified contains methods that will handle Http requests without you having to implement the Controller interface or extend a subclass that implements the controller.
当 spring 启动时,它会读取其 XML 配置文件并在其中查找 <bean
元素,如果它看到类似 <bean class="com.example.Foo"/>
并且 Foo 被标记为 @Controller
它知道该类是控制器并将其视为控制器.默认情况下,Spring 假定它应该管理的所有类都明确定义在 beans.XML 文件中.
When spring starts up it reads its XML configuration file and looks for <bean
elements within it if it sees something like <bean class="com.example.Foo" />
and Foo was marked up with @Controller
it knows that the class is a controller and treats it as such. By default, Spring assumes that all the classes it should manage are explicitly defined in the beans.XML file.
使用 <context:component-scan base-package="com.mycompany.maventestwebapp"/>
进行组件扫描告诉 spring 它应该在类路径中搜索 com 下的所有类.mycompany.maventestweapp 并查看每个类以查看它是否具有 @Controller
或 @Repository
或 @Service
或 @Component
如果是,那么 Spring 将向 bean 工厂注册该类,就像您在 XML 配置文件中键入 <bean class="..."/>
.
Component scanning with <context:component-scan base-package="com.mycompany.maventestwebapp" />
is telling spring that it should search the classpath for all the classes under com.mycompany.maventestweapp and look at each class to see if it has a @Controller
, or @Repository
, or @Service
, or @Component
and if it does then Spring will register the class with the bean factory as if you had typed <bean class="..." />
in the XML configuration files.
在一个典型的 Spring MVC 应用程序中,你会发现有两个 Spring 配置文件,一个配置应用程序上下文的文件通常以 Spring 上下文侦听器启动.
In a typical spring MVC app you will find that there are two spring configuration files, a file that configures the application context usually started with the Spring context listener.
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Spring MVC 配置文件通常以 Spring 调度程序 servlet 启动.例如.
And a Spring MVC configuration file usually started with the Spring dispatcher servlet. For example.
<servlet>
<servlet-name>main</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Spring 支持分层 bean 工厂,因此在 Spring MVC 的情况下,调度程序 servlet 上下文是主应用程序上下文的子级.如果向 servlet 上下文询问名为abc"的 bean,它将首先在 servlet 上下文中查找,如果在其中找不到它,它将在父上下文中查找,即应用程序上下文.
Spring has support for hierarchical bean factories, so in the case of the Spring MVC, the dispatcher servlet context is a child of the main application context. If the servlet context was asked for a bean called "abc" it will look in the servlet context first, if it does not find it there it will look in the parent context, which is the application context.
数据源、JPA 配置、业务服务等通用 bean 是在应用程序上下文中定义的,而 MVC 特定配置不是与 servlet 关联的配置文件.
Common beans such as data sources, JPA configuration, business services are defined in the application context while MVC specific configuration goes not the configuration file associated with the servlet.
希望这会有所帮助.
相关文章