本文介绍了Spring MVC 为什么这个 Hello World 在没有注解驱动标签的情况下运行良好(与任何其他项目 Spring 不同)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经开始学习 Spring MVC 阅读本教程:http://viralpatel.net/blogs/spring-3-mvc-create-hello-world-application-spring-3-mvc/

I have begin to study Spring MVC reading this tutorial: http://viralpatel.net/blogs/spring-3-mvc-create-hello-world-application-spring-3-mvc/

好的,这对我来说很清楚.

Ok, this is very clear for me.

在本例中,我使用 web.xml 文件来配置我的 Web 应用程序:

In this example I have the web.xml file to configure my web application:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee    /web-app_2_5.xsd"
id="WebApp_ID" version="2.5">

<display-name>Spring3MVC</display-name>
<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
</welcome-file-list>

<servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>*.html</url-pattern>
</servlet-mapping>

以及用于配置 mu DispatcherServlet 的 spring-servlet.xml 文件:

And the spring-servlet.xml file used to configure mu DispatcherServlet:

<?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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.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>

而且,正如您在上一个链接中看到的,我只有一个控制器类来处理对/hello"URL 的 HTTP 请求......好吧......这对我来说很清楚......

And, as you can see in the previus link I have only a controller class that handle the HTTP Request toward "/hello" URL...ok...this is clear for me...

在此示例旁边,我通过 STS\Eclipse 中的相关模板项目创建了一个新的 Spring MVC 项目.

Next to this example I have create a new Spring MVC Project by the related template project in STS\Eclipse.

这个例子与之前的例子非常相似:我总是有 web.xml 文件来配置我的 web 应用程序,一个文件来配置 DispatcherServlet 和一个处理 HTTP 请求的控制器类.

This example is very very similar to te previus one: I always have the web.xml file to confiure my web app, a file to configure the DispatcherServlet and a controller class that handle the HTTP Request.

但是有一些我无法理解的区别.

But there is some difference that I can not understand.

这是我的 web.xml 配置文件:

This is my web.xml configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>


<!-- Creates the Spring Container shared by all Servlets and Filters -->

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Processes application requests -->
<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>appServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

这是 servlet-context.xml 文件(配置我的 DispatcherServlet 的配置文件):

And this is the servlet-context.xml file (the configuration file that configure my DispatcherServlet):

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
    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">

<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<context:component-scan base-package="com.mycompany.maventestwebapp" />
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />

<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />

<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <beans:property name="prefix" value="/WEB-INF/views/" />
    <beans:property name="suffix" value=".jsp" />
</beans:bean>

好的,你可以看到两个例子的配置文件有一些区别:

Ok, as you can see there is some difference in the configuration files of the two example:

在由 STS\Eclipse 创建的项目中,在 servlet-context.xml 文件中,我有我发布的第一个示例中没有的这些配置:

In the project created by STS\Eclipse, within the servlet-context.xml file I have these configuration that are not present in the first example that I posted:

<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />

好的...我已经阅读了很多关于这个配置标签的文档:意味着你可以定义 spring bean 依赖项,而实际上不必在 xml 中指定一堆元素或实现一个接口或扩展一个基类.当 spring 启动时,它读取它的 xml 配置文件并查找 Foo 用 @Controller 标记,它知道该类是一个控制器并将其视为控制器.默认情况下,spring 假定它应该管理的所有类都在 beans.xml 文件中明确定义.然后是组件扫描标记告诉Spring它应该搜索com.mycompany.maventestweapp下所有类的类路径并查看每个类以查看它是否有@Controller,或者@Repository,或@Service,或@Component,如果是,那么Spring 会将类注册到bean 工厂,就像您在xml 配置文件中键入一样.BLABLABLA ETCETCETC BLABLA

Ok...I have read a lot of documentation about this configuration tag: 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. When spring starts up it reads its xml configuration file and looks for 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. Then there is the component scanning tag that tell to Spring that it should search the class path 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 in the xml configuration files. BLABLABLA ETCETCETC BLABLA

好的,这对我来说绝对清楚!!!我想我没有问题可以理解为什么我在第二个示例的 DispatcherServler 配置文件中有 annotation-driven 标记,这很清楚.

Ok, this is absolutly clear for me !!! I think that I have NO PROBLEM to understand why I have the annotation-driven tag inside the DispatcherServler configuration file of my second example, this is clear.

问题是要理解为什么我的第一个示例的 DispatcherServlet 配置文件中没有这个标签以及为什么它运行良好如果我尝试从 servlet-context.xml 文件中删除这个标签(在我的第二个示例中)这不会运行并进入错误说我:HTTP 状态 404 - 并且在堆栈跟踪中我有:警告:org.springframework.web.servlet.PageNotFound - 在名为appServlet"的 DispatcherServlet 中找不到具有 URI [/maventestwebapp/] 的 HTTP 请求的映射

The problem is to understand WHY I HAVE NOT THIS TAG in the DispatcherServlet configuration file of my first example and why it work well If I try to delete this tag form the servlet-context.xml file (in my second example) this don't run and go into error sayng me: HTTP Status 404 - and in the stack trace I have: WARN : org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/maventestwebapp/] in DispatcherServlet with name 'appServlet'

我认为这是合理的行为,因为 Spring 没有启用注解支持,所以没有注册我的控制器类(使用注解驱动并用 @Controller 注释我的控制器类,如果我在一个bean.xml 文件),所以不能使用这个 bean 的方法来处理 HTTP 请求......好吧......这听起来不错......

I think that it is rational behavior because Spring has not enabled the annotation support, so have not register my controller class (using annotation-driven and annotating my controller class with @Controller is how if I have this class explicitly defined in a bean.xml file), so can't use the methods of this bean to handle HTTP Request...ok...this sound good...

但是为什么在第一个示例中没有注释驱动的标签就可以工作?我没有注释驱动的标签(所以我没有启用注释来声明哪个类是 Spring bean,例如控制器)并且我没有在 beans.xml 文件中明确声明这个类......所以不应该当我删除注释驱动的标签时,第二个示例不起作用……但它起作用了:-/

But then why in the first example works without having annotation-driven tag ?I have no annotation-driven tag (so I am not enabling the use of annotation to declare what class is a Spring bean such as a controller) and I have not explicitly declared this class in a beans.xml file...so should not work as the second example does not work when I remove the annotation-driven tag...but it work :-/

我要疯了才明白为什么...

I am going crazy to understand why...

拜托,你能帮我吗?

非常感谢

安德里亚

推荐答案

是一个提供额外服务的辅助标签:

<mvc:annotation-driven> is a helper tag that provides additional services:

  • 注册默认处理程序映射
  • 消息转换(例如将控制器中返回的对象转换为JSON)
  • JSR 303 验证(@Valid 注释)
  • 转换服务(如果指定了转换器,则控制器将能够将实体作为参数,即来自请求的文本 ID 将通过 MVC 层转换为实际的业务对象.其他对象(如日期)也是如此、枚举等)
  • 也许在 Spring 的新版本中会添加更多功能.

它是通过 AnnotationDrivenBeanDefinitionParser 在 org.springframework.web.servlet.config 包中

it is implemented with AnnotationDrivenBeanDefinitionParser in org.springframework.web.servlet.config package

如果您有适当的映射(如果需要,您可以显式添加所需的 bean).但是,如果您想做一些或多或少的高级操作,例如 JSR 303 验证、使用 JSON 实现 REST 服务、为 MVC 注册转换服务,那么这个标签会很有用,因为它将这些服务的配置保存在一个地方.

It's not required for your simple controller to work, if you have appropriate mappings (you can add the required beans explicitly if you want).But if you want to do some more or less advanced stuff for example JSR 303 validation, implementing a REST service with JSON, registering a conversion service for MVC, this tag turns out to be useful because it keeps the configuration of these services in one place.

这就是为什么它包含在 Spring 模板项目中的原因(模板项目是开发 Spring 应用程序的起点(因此您只需 去把@Responsebody放在控制器方法返回的值上或添加一个转换器到 MVC)而不仅仅是 Spring 学习者的一个例子).

That is why it's included into the Spring template project(template project is rather a starting point for developing a Spring application(so you can just go and put @Responsebody on the values returned by the controller methods or add a converter to MVC) than just an example for the Spring learners).

另外请注意Spring 3.1 中更改的处理程序映射配置:

在 Spring 3.1 之前,类型和方法级别的请求映射是在两个不同的阶段进行检查——首先选择一个控制器DefaultAnnotationHandlerMapping 和要调用的实际方法第二个被 AnnotationMethodHandlerAdapter 缩小.

这篇关于Spring MVC 为什么这个 Hello World 在没有注解驱动标签的情况下运行良好(与任何其他项目 Spring 不同)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 12:43