Spring MVC快速入门

【内容导航】

  • 第1页:概述
  • 第2页:认识并配置DispatcherServlet
  • 第3页:初始化Web模块的WebApplicationContext
  • 第4页:初始化Spring MVC组件并集成到DispatcherServlet中
  • 第5页:装配各型组件的过程
展开全部 


概述 

    大部分Java应用都是Web应用,展现层是Web应用不可忽略的重要环节。Spring为展现层提供了一个优秀的Web框架——Spring MVC。和众多其它Web框架一样,它基于MVC设计理念,此外,由于它采用了松散耦合可插拔组件结构,具有比其它MVC框架更多的扩展性和灵活性。 

    Spring MVC框架围绕DispatcherServlet这个核心展开,DispatcherServlet的作用是截获请求并组织一系列组件共同完成请求的处理工作。 

体系结构 

    Spring MVC是基于Model 2实现的技术框架,Model 2是经典的MVC(Model,View,Control)模型的Web应用变体,这个改变主要源于HTTP协议的无状态性。Model 2的目的和MVC一样,也是利用处理器分离模型、视图和控制,达到不同技术层级间松散耦合的效果,提高系统灵活性、复用性和可维护性。在多数情况下,你可以将Model 2与MVC等同起来。

    在利用Model 2之前,我们把所有的展现逻辑和业务逻辑集中在一起,有时也称这种应用模式为Model 1,Model 1的主要缺点就是紧耦合,复用性差,维护成本高。

    由于Spring MVC就是基于Model 2实现的框架,所以它底层的机制也是MVC,我们通过图 1描述Spring MVC的宏观体系结构: 


                                                         图 1 Spring MVC具体实现 

    从接受请求到返回响应,Spring MVC框架的众多组件都伸胳膊挽袖子行动起来,各司其职,有条不紊地完成份内的工作。在整个框架中,DispatcherServlet处于核心的位置,它负责协调和组织不同组件,共同完成请求响应的工作。和大多数Web MVC框架一样,Spring MVC通过一个前端Servlet处理器接收所有的请求,并将具体工作委托给其它组件进行具体的处理,DispatcherServlet就是Spring MVC的前端Servlet处理器。下面我们对Spring MVC处理请求的整体过程做一下高空俯瞰: 

① 整个过程开始于客户端发送一个HTTP请求; 

② DispatcherServlet接收这个请求后,并将请求的处理工作委托给具体的处理器(Handler),后者负责处理请求执行相应的业务逻辑。在这之前,DispatcherServlet必须能够凭借请求信息(URL或请求参数等)按照某种机制找到请求对应的处理器,DispatcherServlet是通过垂询HandlerMapping完成这一工作的; 

③ 当DispatcherServlet从HandlerMapping中得到当前请求对应的处理器后,它就将请求分派给这个处理器。处理器根据请求的信息执行相应的业务逻辑,一个设计良好的处理器应该通过调用Service层的业务对象完成业务处理,而非自己越俎代庖。

Spring提供了丰富的处理器类型,在真正处理业务逻辑前,有些处理器会事先执行两项预处理工作: 

1)将HttpServletRequest请求参数绑定到一个POJO对象中; 
2)对绑定了请求参数的POJO对象进行数据合法性校验; 

④ 处理器完成业务逻辑的处理后将返回一个ModelAndView给DispatcherServlet,ModelAndView包含了视图逻辑名和渲染视图时需要用到的模型数据对象; 

⑤ 由于ModelAndView中包含的是视图逻辑名,DispatcherServlet必须知道这个逻辑名对应的真实视图对象,这项视图解析的工作通过调用ViewResolver来完成; 

⑥ 当得到真实的视图对象后,DispatcherServlet将请求分派给这个View对象,由其完成Model数据的渲染工作; 

⑦ 最终客户端得到返回的响应,这可能是一个普通的HTML页面,也可能是一个Excel电子表格、甚至是一个PDF文档等不一而足的视图形式,Spring的视图类型是异常丰富和灵活的。 

以上每一个步骤都包含丰富的知识点,本文将通过一个实例涵盖所有的组件,你可以从中认识到每个组件的庐山真面目,不过现在我们首先要做的第一件事是在web.xml中配置好DispatcherServlet,让这颗“启辉器”真正工作起来。

 

展开全部  认识并配置DispatcherServlet 

    DispatcherServlet是Spring MVC的心脏,它负责接收HTTP请求组织并协调Spring MVC的各种组件共同完成请求的处理工作。和任何Servlet一样,你必须在web.xml中配置好DispatcherServlet。 

DispatcherServlet的工作主要包括以下三项: 
1) 截获满足特定模式URL请求,交由Spring MVC框架处理; 

2) 初始化DispatcherServlet上下文对应的WebApplicationContext,并将其和业务层、持久层的WebApplicationContext建立关联,以便展现层的Bean可以调用业务层的Bean; 

3) 初始化Spring MVC各个组件,并将它们装配到DispatcherServlet实例中。 

下面,我们将逐一分析DispatcherServlet是如何完成以上各项任务的。 

使用DispatcherServlet截获需要Spring MVC处理的URL 

    大家知道任何Servlet都可以在web.xml中通过<servlet-mapping>的配置截获特定模式的URL请求。假设我们希望DispatcherServlet截获所有以.html结束的URL请求,并进而交由Spring MVC框架进行后续处理,那么我们可以在web.xml中按以下方式配置DispatcherServlet:

代码清单 1 配置DispatcherServlet 

<context-param>①业务层和持久层的Spring配置文件,这些配置文件被父Spring容器所使用 
<param-name>contextConfigLocation</param-name> 
<param-value>classpath:baobaotao-service.xml,classpath:baobaotao-dao.xml</param-value> 
</context-param> 
<listener> 
<listener-class> 
org.springframework.web.context.ContextLoaderListener 
</listener-class> 
</listener> 
<servlet> ②声明DispatcherServlet 
<servlet-name>baobaotao</servlet-name> 
<servlet-class> 
org.springframework.web.servlet.DispatcherServlet 
</servlet-class> 
<load-on-startup>2</load-on-startup>③Servlet自动启动的顺序号 
</servlet> 
<servlet-mapping> ④名为DispatcherServlet匹配的URL模式 
<servlet-name>baobaotao</servlet-name> 
<url-pattern>*.html</url-pattern> 
</servlet-mapping> 

越来越多的Web应用倾向于采用“.html”后缀作为框架URL映射的模式,通过这种方法可以对使用者屏蔽服务端所使用的具体实现技术(如果用.do,客户端用户马上就能猜测到服务端使用Struts框架);另外这种URL格式容易让搜索引擎“误认为”网站各个链接都是一个静态网页,这将增加动态网站信息被收录的机率。当然,从纯技术上来说,你可以使用任何后缀模式,如*.spring、*.shtml等等。

 

 初始化Web模块的WebApplicationContext 

    现在我们解决了第一个问题,但DispatcherServlet究竟如何初始化其上下文所对应的WebApplicationContext并完成和业务层、持久层WebApplicationContext的整合呢?当Web容器启动时,Spring通过ContextLoaderListener 监听器初始化业务层和持久层所对应的Spring容器(WebApplicationContext)。接着作为自动启动的DispatcherServlet开始初始化,它利用相应的Spring配置文件初始化DispatcherServlet上下文所对应的子Spring容器(WebApplicationContext),并将业务层、持久层的Spring容器作为其父容器,这种父子容器的结构带来了两个明显的好处: 

1)允许展现层和业务层、持久层更好地解耦,因为展现层的Bean定义在子容器中,而业务层和持久层的Bean定义在父容器中,子容器可以访问父容器的Bean,而父容器访问不到子容器中的Bean; 

2)允许分步骤初始化不同层次的Spring容器。通过ContextLoaderListener配合使用contextConfigLocation上下文参数初始化业务层、持久层的Spring容器,然后再通过DispatcherServlet初始化展现层的子Spring容器。 

    父Spring容器的Spring配置文件在①中定义,DispatcherServlet上下文所用到的Bean也需要一个Spring配置文件进行定义,但在②处的配置中,我们并没有看到预想中配置文件的身影。探其原因,原来是DispatcherServlet将按照默认契约机制进行工作,它自动查找WEB-INF/<servlet-name>-servlet.xml(即WEB-INF/baobaotao-servlet.xml)的配置文件,使用该配置文件初始化DispatcherServlet上下文对应的子Spring容器。 

    实际上,你可以配置多个DispatcherServlet分别处理不同URL模式的请求,每个DispatcherServlet上下文都对应一个自己的子Spring容器,它们拥有相同的父Spring容器(业务层、持久层Bean所在的容器),形成图 2所示的层次结构: 


                图 2 展现层和业务层、持久层的Bean分属于不同Spring容器中 

    DispatcherServlet规定了很多无需配置的默认契约,但都可以通过显式配置进行调整。DispatcherServlet拥有多个可配置的属性,但DispatcherServlet位于web.xml中而非在Spring配置文件中,我们如何配置DispatcherServlet的属性呢? 

    研究DispatcherServlet类的继承体系,我们可以发现它继承于FrameworkServlet,而FrameworkServlet又继承于HttpServletBean。HttpServletBean这个类的名字是否让你得到了某些启示呢?是的,HttpServletBean通过扩展HttpServlet让其具备了类似于Bean的特征 ——你可以在web.xml中通过<init-param>采用类似于在Spring配置文件中的方式配置HttpServletBean的属性,请看下面的配置片断:

代码清单 2 通过Servlet初始化参数配置DispatcherServlet属性

… 
<servlet> 
<servlet-name>baobaotao</servlet-name> 
<servlet-class> 
org.springframework.web.servlet.DispatcherServlet 
</servlet-class> 
<init-param> ①通过Servlet的初始化参数配置DispatcherServlet的属性 
<param-name>namespace</param-name> ①-1 属性名 
<param-value>bbt</param-value> ①-2 属性值 
</init-param> 
<load-on-startup>2</load-on-startup> 
</servlet> 
… 

在①处,我们通过定义了一个namespace的初始化参数,DispatcherServlet将调用自身的setNamespace()方法将“bbt”设置为nameSpace属性的值。可按照相似方式配置的属性一并介绍如下: 

 namespace:DispatcherServlet对应的命名空间,用以构造Spring配置文件的路径,如果指定该属性后,配置文件对应的路径为:WEB-INF/<namespace>.xml而非WEB-INF/< servlet-name>.xml。按照上面配置对应的配置文件为WEB-INF/bbt.xml;

 contextConfigLocation:如果DispatcherServlet上下文对应的Spring配置文件有多个,则可以使用该属性按照Spring资源路径的方式进行指定。如设置为“classpath:bbt1.xml,classpath:bbt2.xml”时,DispatcherServlet将使用类路径下的bbt1.xml和bbt2.xml这两个配置文件初始化WebApplicationContext;

 publishContext:boolean类型属性,默认值为ture。DispatcherServlet据此属性决定是否将对应的WebApplicationContext发布到ServletContext的属性中,以便任何其它的Bean可以通过ServletContext找到DispatcherServlet上下文对应的WebApplicationContext,对应的属性名为DispatcherServlet#getServletContextAttributeName()方法返回的值。 

 publishEvents:boolean类型属性。当DispatcherServlet处理完一个请求后,是否需要向容器发布一个ServletRequestHandledEvent事件,默认为ture。如果容器中没有任何事件监听器,可以将此属性设置为false,以便赚取一些程序运行性能。

 

初始化Spring MVC组件并集成到DispatcherServlet中 

    现在我们剩下最后一个问题是:DispatcherServlet究竟如何将上下文中的Spring MVC组件Bean装配到DispatcherServlet实例中呢?通过查看DispatcherServlet的initStrategies()方法体中的代码,一切的真相就大白于天下了: 

protected void initStrategies(ApplicationContext context) { 
initMultipartResolver(); ①初始化上传文件解析器(直译为多部分请求解析器) 
initLocaleResolver(); ②初始化本地化解析器 
initThemeResolver(); ③初始化主题解析器 
initHandlerMappings(); ④初始化处理器映射器 
initHandlerAdapters(); ⑤初始化处理器适配器 
initHandlerExceptionResolvers();⑥初始化处理器异常解析器 
initRequestToViewNameTranslator();⑦初始化请求到视图名翻译器 
initViewResolvers(); ⑧初始化视图解析器 


    initStrategies()方法会在DispatcherServlet对应的WebApplicationContext初始化后自动执行,此时DispatcherServlet上下文中的Bean已经初始化完毕。该方法的工作事先通过一定的发现机制查询上下文中的组件Bean,如果找不到则装配默认的组件实例。

    Spring MVC定义了一套默认的组件实现类,也就是说即使不在Spring容器中显式配置组件Bean,也会有一套可用的默认组件出现在DispatcherServlet中。Spring在spring.jar包的org/springframework/web/servlet类路径定义了一个DispatcherServlet.properties配置文件,在其中指定了组件的默认实现类: 

①本地化解析器 
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n. 
AcceptHeaderLocaleResolver 

②主题解析器 
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver 

③处理器映射器 
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet. 
handler.BeanNameUrlHandlerMapping 

④处理器适配器(共3个) 
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc. 
HttpRequestHandlerAdapter,\ 
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ 
org.springframework.web.servlet.mvc.throwaway.ThrowawayControllerHandlerAdapter 

⑤请求到视图名翻译器 
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view. 
DefaultRequestToViewNameTranslator 

⑥视图解析器 
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view. 
InternalResourceViewResolver 

    你也可以在DispatcherServlet上下文配置文件中显式配置组件Bean以覆盖DispatcherServlet.properties文件中定义的默认组件。 
    有些类型的组件仅需要配置一个(如本地化解析器),而有些类型的组件可以配置多个,它们组成一个List列表(如处理器映射器)。对于后者来说,组件类都实现了Spring的Ordered接口,你可以在配置时通过order属性指定相应的优先级。

    DispatcherServlet优先采用order值小的组件进行操作,如果它无法完成任务才交由次优先级的组件,以此类推。如果同类组件有些设定了order值,有些没有设定,则没有设定order的组件优先级最低,实际上它被设置为Integer.MAX_VALUE。

    DispatcherServlet如何在上下文中查找组件Bean并将它们组装到DispatcherServlet实例中呢?这是一个很值得研究的问题。总的来说,DispatcherServlet采用了“约定Bean名”+“匹配组件类型”的机制查找上下文中的组件Bean,如果通过这个发现机制无法找到组件Bean,则转而使用DispatcherServlet.properties文件中定义的默认实现类。对于可以配置多个组件的组件类型,DispatcherServlet允许自动探测父子容器中匹配类型的Bean,并将它们一起装配到DispatcherServlet中。 

 

我们通过表 1说明每种类型组件的装配过程,带(☆)的组件仅有一个,而带(★)的组件可以拥有多个,它们构成一个List: 

表 1 装配各型组件的过程 

组件类型发现机制
文件上传解析器 1)查找名为multipartResolver类型为MultipartResolver的Bean作为该类型组件; 2)没有默认的实现类。 所以如果你没有在上下文中显式定义这一类型的组件,DispatcherServlet中将不会拥有该类型的组件。
本地化解析器  1)查找名为localeResolver类型为LocaleResolver的Bean作为该类型·组件; 2)如果1)找不到,使用默认的实现类(AcceptHeaderLocaleResolver)创建该类型的组件。
主题解析器  1)查找名为themeResolver类型为LocaleResolver的Bean作为组件; 2)如果1)找不到,使用默认的实现类(FixedThemeResolver)。
处理器映射器 (★) 1)如果detectAllHandlerMappings属性为true(默认为true),根据类型匹配(HandlerMapping)机制查找上下文及父Spring容器中所有匹配的Bean,将它们作为该类型组件; 2)如果detectAllHandlerMappings属性为false,查找名为handlerMapping类型为HandlerMapping的Bean作为该类型组件; 3)如果通过以上方式都找不到,使用BeanNameUrlHandlerMapping实现类创建创建该类型的组件。
处理器适配器 (★) 1)如果detectAllHandlerAdapters属性为true(默认为true),根据类型匹配(HandlerAdapter)机制查找上下文及父Spring容器中所有匹配的Bean,将它们作为该类型组件; 2)如果detectAllHandlerAdapters属性为false,查找名为handlerAdapter类型为HandlerAdapter的Bean作为该类型组件; 3)如果通过以上方式都找不到,使用DispatcherServlet.properties配置文件中指定的三个实现类分别创建一个适配器,添加到适配器列表中。
处理器异常解析器 (★) 1)如果detectAllHandlerExceptionResolvers属性为true(默认为true),根据类型匹配(HandlerExceptionResolver)机制查找上下文及父Spring容器中所有匹配的Bean作为该类型组件; 2)如果detectAllHandlerExceptionResolvers属性为false,查找名为handlerExceptionResolver类型为HandlerExceptionResolver的Bean作为该类型组件; 3)如果通过以上方式都找不到,查找DispatcherServlet.properties中定义的默认实现类,不过该文件中没有对应处理器异常解析器的默认实现类(你可以更改属性文件)。
视图名翻译器  1)查找名为viewNameTranslator类型为RequestToViewNameTranslator的Bean作为该类型组件; 2)如果1)找不到,使用默认的实现类(DefaultRequestToViewNameTranslator)创建该类型的组件。  
视图解析器 (★) 1)如果detectAllViewResolvers属性为true(默认为true),根据类型匹配(ViewResolver)机制查找上下文及父Spring容器中所有匹配的Bean作为该类型组件; 2)如果detectAllViewResolvers属性为false,查找名为viewResolver类型为ViewResolver的Bean作为该类型组件; 3)如果通过以上方式都找不到,通过DispatcherServlet.properties中定义的默认实现类(InternalResourceViewResolver)创建该类型的组件。


    总体来说,当DispatcherServlet初始化完成后,就会或查找上下文的组件Bean,或根据默认配置文件实例化组件实例,装配到DispatcherServlet中了。通过上表,我们可以得出这样的结论:单一实例组件(带☆的)必须使用约定的Bean名称进行配置,而多实例组件(速 ★的)可以不指定Bean名称由DispatcherServlet自动进行探测。

一个包含以上步骤的实例 

    在学习了Spring MVC框架的结构后,我们通过一个简单的实例引出Spring MVC开发的基本过程。开发一个Spring MVC程序至少需要以下的步骤: 

1. 编写处理请求逻辑的处理器; 
2. 在DispatcherServlet上下文对应的Spring配置文件中配置处理器; 
3. 配置一个视图解析器,对处理器返回的ModelAndView进行解析; 
4. 编写一个视图对象(一般是JSP),将响应展现给客户。

 

创建处理器 
    处理器有很多类型,其中实现Controller控制器接口的处理器是最常见的方式。我们首先创建负责处理首页请求的处理器IndexController,其代码如下所示: 

代码清单 3 IndexController 
package com.baobaotao.web; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import org.springframework.web.servlet.ModelAndView; 
import org.springframework.web.servlet.mvc.Controller; 
public class IndexController implements Controller {①通过扩展Controller接口定义处理器 
private String greeting; 
public String getGreeting() { 
return greeting; 

public void setGreeting(String greeting) { 
this.greeting = greeting; 

public ModelAndView handleRequest(HttpServletRequest arg0, ②响应请求的方法 
HttpServletResponse arg1) throws Exception { 
return new ModelAndView("index","greeting",greeting); ③返回一个ModelAndView对象 



handleRequest()是Controller接口唯一的方法,仔细观察方法的结构,你会发现该方法和Servlet的service(HttpServletRequest req, HttpServletResponse resp)方法在结构上很相似。 

IndexController相当于Struts的Action,不同的是,IndexController将配置成Spring一个普通的Bean,这意味着处理器可以充分享受Spring IoC和AOP的好处。你可以将业务层的Bean注入到处理器中完成复杂的业务逻辑。 

handleRequest()在完成业务处理后,返回一个ModelAndView对象。ModelAndView包括了视图逻辑名和渲染所需模型对象。

配置处理器Bean 

    在编写好IndexController处理器后,现在可以在Spring配置文件(baobaotao-servlet.xml)中配置这个处理器,并注入greeting属性值: 

<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>①处理器映射 
<bean name="/index.html" class="com.baobaotao.web.IndexController">②处理器 
<property name="greeting" value="淘淘宝论坛欢迎您的到来!"/> 
</bean> 

    首先我们在①处定义一个将请求映射到处理器的HandlerMapping,它采用最简单的映射策略:使用和请求URL同名的处理器响应请求。通过表 1,我们知道DispatcherServlet会根据类匹配发现机制扫描Spring容器中HandlerMapping类型的Bean,并将其装配为DispatcherServlet的处理器映射组件,所以在①处定义处理器映射器时并没有必要指定id或name(这也是默认的实现类)。②处的处理器被命名为“/index.html”,这意味着使用诸如http://localhost/baobaotao/index.html以“/index.html”结尾的URL请求时,②处的IndexController将处理这个请求。由于XML id的命名规则有严格的要求,不能使用“/”字符,所以我们使用name对处理器Bean进行命名。

 

配置视图解析器 

    当IndexController#handleRequest()返回ModelAndView("index","greeting",greeting)时,视图解析器开始工作,将其解析为具体的视图对象。我们使用InternalResourceViewResolver配置一个视图解析器,它通过在视图逻辑名添加前后缀的方式得到具体的视图对象: 

代码清单 4 前后缀视图解析器 

… 
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
<property name="prefix"> ①前缀 
<value>/WEB-INF/jsp/</value> 
</property> 
<property name="suffix"> ②后缀 
<value>.jsp</value> 
</property> 
</bean> 

    通过这个视图解析器解析后,逻辑名为“index”的视图将被解析为“/WEB-INF/jsp/index.jsp”这个具体的视图对象。

创建JSP 

    最后我们需要编写index.jsp,对响应进行渲染。index.jsp是一个简单的JSP页面,其代码如下所示: 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 
<html> 
<head> 
<title>宝宝淘论坛</title> 
</head> 
<body> 
${greeting} ①引用ModelAndView中的greeting模型数据 
</body> 
</html> 

在①处,JSP文件引用处理器返回ModelAndView对象中绑定的greeting模型对象(它仅是一个简单的字符串,它可以是任何POJO),将这个JSP文件放置到WEB-INF/jsp/index.jsp位置上。 

将实例反衬到Spring MVC的体系结构中 

    至此为止,基于Spring MVC的论坛首页就开发完成了。你可以启用Tomcat,通过http://localhost/baobaotao/index.html进行访问,浏览器将返回以下的页面: 



图 3 宝宝淘论坛首页 
可见我们通过前几小节配置的各种组件已经正确地配合起来,共同完成对/index.html请求的处理工作。下面对照图 1,用处理/index.html请求的具体组件对象替换体系结构中的组件角色,得到图 4的交互结构图: 



图 4 处理/index.html的整体过程 
我们再简要地描述一下Spring MVC处理/index.html的整个过程:

1. DispatcherServlet授受到客户端的/index.html的请求; 
2. DispatcherServlet使用BeanNameUrlHandlerMapping查找负责处理该请求的处理器为“/index.html”; 
3. DispatcherServlet将请求分发给名为“/index.html”的IndexController处理器; 
4. 处理器完成业务处理后,返回ModelAndView("index","greeting",greeting)对象; 
5. DispatcherServlet调用InternalResourceViewResolver组件对返回的ModelAndView对象进行解析,得到真实的视图对象为“WEB-INF/jsp/index.jsp”; 
6. DispatcherServlet将请求转向到WEB-INF/jsp/index.jsp,使用它对greeting模型对象进行渲染; 
7. 返回响应页面给客户端。 

    通过这个小例子,我们已经了解了开发一个Spring MVC功能所需要经历的整体步骤,其它类型的实用可以轻松地在此基础上进行拓展。 

小结 

    Spring MVC框架以DispatcherServlet为核心,各种组件都能以可插拔的方式装配到DispatcherServlet上。这造就了一个高度灵活、松耦合的MVC框架,它直接建立在反向控制和可扩展的原则的基础上。 

    当一个请求到达时,处理器映射器能够根据URL信息,按照一定的映射方案返回一个处理器执行链(HandlerExecutionChain)对象,它包含用于处理请求的若干个过滤器和一个处理器。过滤器可以根据一定逻辑,判断请求是否要传递到下一个过滤器或处理器。处理器执行完请求后,一般会返回一个ModelAndView对象,它包含了视图和模型的信息。视图解析器对ModelAndView进行解析工作,并最终得到一个视图对象,该视图对象渲染模型的数据并最终返回一个页面。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值