zoukankan      html  css  js  c++  java
  • spring MVC(下)

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

    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进行访问.

    可见我们通过前几小节配置的各种组件已经正确地配合起来,共同完成对/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进行解析工作,并最终得到一个视图对象,该视图对象渲染模型的数据并最终返回一个页面。

  • 相关阅读:
    asp.net gridview中增加单击单元格事件
    asp.net在应用母版的页面下采用了ModalPopupExtender弹出窗中应用autocomplete
    网站发布后无法访问,提示“/”应用程序中的服务器错误
    asp.net将数据导出到excel
    看完让你彻底搞懂Websocket原理
    PL/SQL简单使用——导入、导出数据表
    Java 定时任务的几种实现方式
    用element-ui 时,报value.getTime is not a function错误:
    Object.assign()解释整理
    IntelliJ IDEA2017 激活方法 最新的(亲测可用)
  • 原文地址:https://www.cnblogs.com/Jiphen/p/2694537.html
Copyright © 2011-2022 走看看