5.1.1 Following the life of a request前端
Every time a user clicks a link or submits a form in their web browser, a request goes to
work. A request’s job description is that of a courier. Just like a postal carrier or a
FedEx delivery person, a request lives to carry information from one place to another.
The request is a busy creature. From the time it leaves the browser until it returns
with a response, it makes several stops, each time dropping off a bit of information
and picking up some more. Figure 5.1 shows all the stops the request makes as it travels through Spring MVCjava
每次用戶在瀏覽器上點擊一個連接或者提交一個表單時,請求就開始工做了.請求的工做內容就跟郵遞員或者聯邦快遞員同樣,他們把信息從一個地方送到另外一個地方.從離開瀏覽器開始到返回一個響應爲止,請求要停留好幾回,每次都留下一些信息而後帶走更多信息.圖5.1顯示一個請求在spring mvc框架中傳輸時所作的停留.web
The first stop in the request’s travels is at Spring’s DispatcherServlet. Like most Javabased web frameworks, Spring MVC funnels requests through a single front controller
servlet. A front controller is a common web application pattern where a single servlet
delegates responsibility for a request to other components of an application to perform actual processing. In the case of Spring MVC, DispatcherServlet is the front
controller.spring
請求的第一站是spring的DispatchServlet.和大多數基於java的Web框架同樣,spring mvc也是經過一個前端控制器分發請求.前端控制器就是一個普通的web應用模型,在這裏有一個sevlet負責把請求委派給應用中其它的組件,組件將會根據請求的信息執行相應的操做.在spring mvc框架中,DispatchServlet就是前端控制器.後端
The DispatcherServlet’s job is to send the request on to a Spring MVC controller.
A controller is a Spring component that processes the request. But a typical application
may have several controllers, and DispatcherServlet needs some help deciding
which controller to send the request to. So the DispatcherServlet consults one or
more handler mappings to figure out where the request’s next stop will be. The
handler mapping pays particular attention to the URL carried by the request when
making its decision.瀏覽器
Dispatch的工做是將請求發送給相應的spring mvc控制器.控制器是spring mvc框架中負責處理請求的組件.一般應用中都有不少控制器,dispatcher須要判斷應該把請求發送給哪一個控制器,是如何判斷的呢?dispatcherservet首先查看handler mappings(第二步),tomcat
5.1.2 Setting up Spring MVCmvc
Based on figure 5.1, it looks like there are a lot of moving parts to be configured. Fortunately, thanks to some advancements in the most recent versions of Spring, it’s easy
to get started with Spring MVC. For now, you’ll take the simplest approach to configuring Spring MVC: you’ll do just enough configuring to be able to run the controllers
you create. In chapter 7, we’ll look at some additional setup options.app
在圖5.1中,貌似須要配置好多信息.不過幸運的是,多虧了spring最近版本的改進,啓動一個spring mvc項目並不須要花費太多精力.如今,你將要用最簡單的方式配置一個spring mvc項目.只須要配置能運行控制器的必要步驟便可.等到了第7章,再詳細講解其它的配置.框架
CONFIGURING DISPATCHERSERVLET
DispatcherServlet is the centerpiece of Spring MVC. It’s where the request first hits
the framework, and it’s responsible for routing the request through all the other
components.
DispatcherServlet 是spring mvc框架的核心.是請求遇到的第一個spring mvc組件,它負責引導請求在各個組件之間的流通.
Historically, servlets like DispatcherServlet have been configured in a web.xml
file that’s carried in the web application’s WAR file. Certainly that’s one option for configuring DispatcherServlet. But thanks to recent advances in the Servlet 3 specification and in Spring 3.1, it’s not the only option. And it’s not the option we’ll go with in
this chapter.
在以往,配置dispatchservlet必須在web.xml文件裏配置一個servlet,不過在servlet 3 規範和spring 3.1版本中,還有其它的方式實現dispatchservlet.
Instead of a web.xml file, you’re going to use Java to configure DispatcherServlet
in the servlet container. The following listing shows the Java class you’ll need.
與在web.xml中配置不一樣,本章將在java文件配置DispatcherServlet.
Listing 5.1 Configuring DispatcherServlet package spittr.config; import org.springframework.web.servlet.support. AbstractAnnotationConfigDispatcherServletInitializer; public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected String[] getServletMappings() { return new String[] { "/" }; } @Override protected Class<?>[] getRootConfigClasses() { return new Class<?>[] { RootConfig.class }; } @Override protected Class<?>[] getServletConfigClasses() { return new Class<?>[] { WebConfig.class }; } }
To understand how listing 5.1 works, it’s probably sufficient to know that any class
that extends AbstractAnnotationConfigDispatcherServletInitializer will automatically be used to configure DispatcherServlet and the Spring application context in the application’s servlet context.
要理解代碼5.1的做用,你須要知道在應用的servlet容器內,任何繼承 AbstractAnnotationConfigDispatcherServletInitializer 的類將被框架自動用於配置DispatcherServlet 以及spring 應用上下文.
AbstractAnnotationConfigDispatcherServletInitializer exposed
If you insist on the more detailed explanation, here it is. In a Servlet 3.0 environment,
the container looks for any classes in the classpath that implement the javax.servlet
.ServletContainerInitializer interface; if any are found, they’re used to configure the servlet container.
Spring supplies an implementation of that interface called SpringServletContainerInitializer that, in turn, seeks out any classes that implement WebApplicationInitializer and delegates to them for configuration. Spring 3.2
introduced a convenient base implementation of WebApplicationInitializer
called AbstractAnnotationConfigDispatcherServletInitializer. Because
your SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer (and thus implements WebApplicationInitializer), it will
be automatically discovered when deployed in a Servlet 3.0 container and be used to
configure the servlet context.
在servlet3.0的環境中,容器將在類路徑下查找任何實現了javax.servlet.ServletContainerInitializer的接口,若是找到了,這些接口就將用於配置servlet容器.
spring提供了這個接口的實現,即SpringServletContainerInitializer,這樣,容器將查找任何實現了WebApplicationInitializer的類,而後使用這些類來配置servlet容器.spring 3.2引入了一個簡便的WebApplicationInitializer實現,名爲AbstractAnnotationConfigDispatcherServletInitializer,由於代碼5.1中的SpittrWebAppInitializer類繼承了AbstractAnnotationConfigDispatcherServletInitializer(固然也就繼承了WebApplicationInitializer
),因此SpittrWebAppInitializer將會在部署到servlet3.0容器後,被容器自動發現,用於配置servlet上下文.
Even though its name is extremely long, AbstractAnnotationConfigDispatcherServletInitializer is a snap to use. Looking at listing 5.1, you can see that SpittrWebAppInitializer overrides three methods.
別看AbstractAnnotationConfigDispatcherServletInitializer 名字挺長的,使用起來其實挺簡單的.從代碼5.1中咱們能夠看到SpittrWebAppInitializer重寫了三個方法.
The first method, getServletMappings(), identifies one or more paths that DispatcherServlet will be mapped to. In this case, it’s mapped to /, indicating that it will be the application’s default servlet. It will handle all requests coming into the application.
第一個方法,名爲getServletMappings(),標明瞭DispatcherServlet映射的路徑.在本例中,DispatcherServlet映射的是"/",表示它是應用的默認servlet,它將處理全部發向該應用的請求.
In order to understand the other two methods, you must first understand the relationship between DispatcherServlet and a servlet listener known as ContextLoaderListener
爲了理解其它兩個方法,你須要先理解DispatcherServlet 和 名爲ContextLoaderListener的servlet監控器之間的關係.
A TALE OF TWO APPLICATION CONTEXTS
When DispatcherServlet starts up, it creates a Spring application context and starts
loading it with beans declared in the configuration files or classes that it’s given. With
the getServletConfigClasses() method in listing 5.1, you’ve asked that DispatcherServlet load its application context with beans defined in the WebConfig configuration class (using Java configuration).
在DispatcherServlet後,它將建立一個spring應用上下文並開始加載聲明在配置文件或者給定類裏的bean.DispatcherServlet就是加載代碼5.1中的getServletConfigClasses方法返回值裏對應的bean,在本例中,這些bean是定義在java文件裏的.
But in Spring web applications, there’s often another application context. This
other application context is created by ContextLoaderListener.
可是在spring web 應用中,還有另外一種應用上下文.這種應用上下文是由ContextLoaderListener建立的.
Whereas DispatcherServlet is expected to load beans containing web components
such as controllers, view resolvers, and handler mappings, ContextLoaderListener is
expected to load the other beans in your application. These beans are typically the
middle-tier and data-tier components that drive the back end of the application.
DispatcherServlet要加載web組件相關的bean,好比說控制器/視圖/URL映射等.而ContextLoaderListener負責加載其它類型的Bean.ContextLoaderListener加載的類主要屬於中間層和數據層的組件,就是這些組件驅動着應用的後端.
Under the covers, AbstractAnnotationConfigDispatcherServletInitializer creates both a DispatcherServlet and a ContextLoaderListener. The @Configuration
classes returned from getServletConfigClasses() will define beans for DispatcherServlet’s application context. Meanwhile, the @Configuration class’s returned getRootConfigClasses() will be used to configure the application context created by
ContextLoaderListener.
AbstractAnnotationConfigDispatcherServletInitializer會建立一個DispatcherServlet和一個ContextLoaderListener.方法getServletConfigClasses返回的全部被註解@Configuration修飾的類即組成了DispatcherServlet建立的應用上下文,同時,方法getRootConfigClasses返回的全部被註解Configuration 修飾的類則組成了由ContextLoaderListener建立的的應用上下文.
In this case, your root configuration is defined in RootConfig, whereas DispatcherServlet’s configuration is declared in WebConfig. You’ll see what those two configuration classes look like in a moment.
在本例中,root配置信息定義在RootConfig類中,而DispatcherServlet的配置則聲明在WebConfig中,一會你就會看到這兩個配置類包含的內容了.
It’s important to realize that configuring DispatcherServlet via AbstractAnnotationConfigDispatcherServletInitializer is an alternative to the traditional web.xml file. Although you can include a web.xml file alongside a subclass
of AbstractAnnotationConfigDispatcherServletInitializer if you like, it’s not
necessary.
AbstractAnnotationConfigDispatcherServletInitializer 是除web.xml以外的另外一種配置應用信息的方式.雖然你能夠在應用中包含web.xml文件做爲AbstractAnnotationConfigDispatcherServletInitializer 的子集,可是這種作法真的沒有必要.
The only gotcha with configuring DispatcherServlet in this way, as opposed to in
a web.xml file, is that it will only work when deploying to a server that supports
Servlet 3.0, such as Apache Tomcat 7 or higher. The Servlet 3.0 specification has been
final since December 2009, and the odds are good that you’ll be deploying your applications to a servlet container that supports Servlet 3.0.
AbstractAnnotationConfigDispatcherServletInitializer只能配置在支持servlet3.0的環境裏,好比tomcat7及其以上版本,servlet3.0規範是在2009看12月定稿的,至此,你就能夠把應用部署在支持servlet3.0的servlet容器裏了.
If you’re not yet working with a Servlet 3.0-capable server, then configuring
DispatcherServlet in a subclass of AbstractAnnotationConfigDispatcherServletInitializer won’t work for you. You’ll have no choice but to configure DispatcherServlet in web.xml. We’ll look at web.xml and other configuration options in chapter 7. For now, though, let’s look at WebConfig and RootConfig, the two configuration classes referred to in listing 5.1, and see how to enable Spring MVC.
若是你開發的環境還不支持servlet3.0,那麼你是不能經過AbstractAnnotationConfigDispatcherServletInitializer的子類配置DispatcherServlet 的.你沒有其它的選擇,只能在web.xml中配置DispatcherServlet .咱們將在第7章中學習web.xml及其它的配置選項.如今咱們先研究下代碼5.1中的WebConfig and RootConfig,看看如何經過它們來使用spring mvc.
ENABLING SPRING MVC 使用spring mvc
Just as there are several ways of configuring DispatcherServlet, there’s more than
one way to enable Spring MVC components. Historically, Spring has been configured
using XML, and there’s an <mvc:annotation-driven> element that you can use to
enable annotation-driven Spring MVC.
We’ll talk about <mvc:annotation-driven>, among other Spring MVC configuration options, in chapter 7. But for now, you’ll keep your Spring MVC setup simple and
Java-based.
The very simplest Spring MVC configuration you can create is a class annotated
with @EnableWebMvc:
配置DispatcherServlet的方法不僅一種,配置Spring MVC的方法固然也不僅一種.在此以前,咱們用xml配置spring,使用<mvc:annotation-driven>這個元素激活spring mvc中的註解.
咱們之後再討論<mvc:annotation-driven>這個元素.如今咱們基於java配置一個簡單但功能齊全的spring mvc.
package spittr.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @Configuration @EnableWebMvc public class WebConfig { }