web-dev-qa-db-ja.com

Spring MVC:<context:component-scan>と<annotation-driven />タグの違いは?

数日前、私はこのSpring Hello Worldチュートリアルの研究を始めました: http://viralpatel.net/blogs/spring-3-mvc-create-hello-world-application-spring-3-mvc/

このチュートリアルでは、Spring DispatcherServletはspring-servlet.xmlファイルを使用して設定されます。

<?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")アノテーションが付けられていることを検出します。アノテーションは、このメソッドが、 /こんにちは"。これは簡単です...

私の疑問は、STS\Eclipseで自動的にビルドできるSpring MVCテンプレートプロジェクトに関連しています。

STSで新しいSpring MVCプロジェクトを作成するとき、DispatcherServletservlet-context.xmlこれには、前のサンプルファイルに似た構成が含まれています。

このファイルには、まだコンポーネントスキャンタグがあります。

<context:component-scan base-package="com.mycompany.maventestwebapp" />

しかし、私は別のタグ(同様のタスクを持っているように見える)、これも持っています:

<annotation-driven />

これら2つのタグの違いは何ですか?
もう1つの「奇妙な」ことは、前の例(アノテーション駆動型タグを使用しない)は、Spring MVCテンプレートプロジェクトを使用してSTSによって作成されたプロジェクトに非常に似ていますが、アノテーションを削除すると構成ファイルからタグを駆動すると、プロジェクトが実行されず、次のエラーが表示されます:HTTP Status 404-

そして、私はスタックトレースに:

WARN:org.springframework.web.servlet.PageNotFound-「appServlet」という名前のDispatcherServletでURI [/ maventestwebapp /]のHTTPリクエストのマッピングが見つかりませんでした

しかし、なぜ?前の例は、アノテーション駆動型のタグがなくてもうまく機能し、このコントローラークラスは非常に似ています。実際、「/」パスへのHTTPリクエストを処理するメソッドは1つだけです

これは私のコントローラークラスのコードです。

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";
}

誰かがこのことを理解するのを手伝ってくれますか?

どうもありがとうございました!

64
AndreaNobili

<mvc:annotation-driven />は、XMLで多数の要素を指定したり、インターフェースを実装したり、基本クラスを拡張したりする必要なく、Spring Beanの依存関係を定義できることを意味します。たとえば@Repositoryは、JpaDaoSupportまたはDaoSupportの他のサブクラスを拡張することなく、クラスがDaoであることをSpringに通知します。同様に、@Controllerは、指定したクラスに、コントローラーインターフェイスを実装したり、コントローラーを実装するサブクラスを拡張したりせずに、Http要求を処理するメソッドが含まれていることをspringに伝えます。

Springが起動すると、XML設定ファイルを読み取り、<beanのようなものが表示され、Fooが<bean class="com.example.Foo" />でマークアップされている場合、その中の@Controller要素を探します。そしてそれをそのように扱います。デフォルトでは、Springは、管理する必要があるすべてのクラスがbeans.XMLファイルで明示的に定義されていると想定します。

<context:component-scan base-package="com.mycompany.maventestwebapp" />を使用したコンポーネントスキャンは、com.mycompany.maventestweappの下のすべてのクラスのクラスパスを検索し、各クラスを見て@Controllerまたは@Repositoryがあるかどうかを確認することをばねに伝えています。 、または@Service、または@Componentの場合、SpringはXML構成ファイルに<bean class="..." />を入力したかのようにBeanファクトリにクラスを登録します。

典型的なSpring MVCアプリには、2つのSpring設定ファイルがあり、それらは通常Springコンテキストリスナーで起動されるアプリケーションコンテキストを設定するファイルです。

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

また、Spring MVC構成ファイルは通常、Springディスパッチャサーブレットで開始されました。例えば。

<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の場合、ディスパッチャサーブレットコンテキストはメインアプリケーションコンテキストの子です。サーブレットコンテキストが「abc」というBeanを要求された場合、最初にサーブレットコンテキストを検索し、そこで見つからない場合は、アプリケーションコンテキストである親コンテキストを検索します。

データソース、JPA構成、ビジネスサービスなどの一般的なBeanはアプリケーションコンテキストで定義されますが、MVC固有の構成はサーブレットに関連付けられた構成ファイルではありません。

お役に立てれば。

83
ams
<context:component-scan base-package="" /> 

springにこれらのパッケージの注釈をスキャンするよう指示します。

<mvc:annotation-driven> 

requestMappingHanderMapping、RequestMappingHandlerAdapter、およびExceptionHandlerExceptionResolverを登録して、MVCに付属する@ RequestMapping、@ ExceptionHandlerなどの注釈付きコントローラーメソッドをサポートします。

これにより、出力の注釈駆動型の書式設定と入力の注釈駆動型の検証をサポートするConversionServiceも有効になります。また、JSONデータを返すために使用できる@ResponseBodyのサポートも有効にします。

@Configurationクラスで@ComponentScan(basePackages = {"..."、 "..."}および@EnableWebMvcを使用して、Javaベースの構成を使用して同じことを実現できます。

詳細については、3.1のドキュメントをご覧ください。

http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-config

26
Dennis S

注釈駆動型は、注釈付きBeanをスキャンする必要があり、XML Bean構成だけに依存しないことをSpringに示します。コンポーネントスキャンは、それらのBeanを探す場所を示します。

ここにいくつかのドキュメントがあります: http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-config-enable

12
atrain