第二章 Spring MVC简介

《Spring+MyBatis企业应用实战》笔记

P10 MVC思想及其优势

  • MVC思想将一个应用分成三个基本部分:Model(模型)、View(视图)和Controller(控制器),这三个部分以最少的耦合协同工作,从而提高应用的可扩展性和可维护性。
  • 观察者模式:观察者模式(有时又被称为模型-视图(View)模式、源-收听者(Listener)模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实现事件处理系统。
  • Web应用是一种请求/响应模式下应用,对应请求/响应应用,如果用户不对应用发出请求,视图将无法主动更新自己。

P11 Spring的下载和安装

  • Spring框架文件夹
docs 该文件夹下存放Spring的相关文档,包含开发指南、API参考文档。
libs 该文件夹下的JARS分为三类:①Spring框架class文件的JAR包;②Spring框架源文件的压缩包,文件名以-source结尾;③Spring框架API文档的压缩包,文件名以-javadoc结尾。
schemas 该文件夹下包含了Spring各种配置文件的XML Schemas文档。
readme.txt、notice.txt、license.txt等说明性文档。
  • Spring的核心容器必须依赖于common-logging的JAR包。

P12 Spring MVC的DispatcherServlet

web.xml配置

    <!-- 定义Spring MVC的前端控制器 -->
    <servlet>
        <!--Servlet的名称-->
        <servlet-name>springmvc</servlet-name>
        <!--Servlet对应的Java类-->
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--当前Servlet的参数信息-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/springmvc-config.xml</param-value>
        </init-param>
        <!--再Web应用启动时立即加载Servlet-->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- 让Spring MVC的前端控制器拦截所有请求 -->
    <!--Servlet的映射声明-->
    <servlet-mapping>
        <!--请求对应的Servlet的名称-->
        <servlet-name>springmvc</servlet-name>
        <!--监听当前域的所有请求-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

2018.7.22

P13 基于Controller接口的控制器

DispatcherServlet在Spring当中充当一个前端控制器的角色,它的核心功能是分发请求。请求会被分发给对应处理的Java类,Spring MVC中称为Handle。在Spring2.5版本以前,开发一个Handle的唯一方法是实现org.springframework.web.servlet.mvc.Controller接口,Controller接口必须实现一个方法,该方法的签名如下:

ModelAndView handleRequest(HttpServletRequest request,HttpServletResponse response) throws Exception

Controller接口的实现类可以通过handleRequest方法传递的参数访问对应请求的HttpServletRequest和HttpServletResponse对象,处理完业务请求之后,必须返回一个包含模型对象和视图路径的ModelAndView对象。

Controller接口的实现类只能处理一个单一请求动作,而Spring2.5之后新增的基于注解的控制器可以支持同时处理多个请求动作,并且无须实现任何接口,更加灵活。

P13 第一个Spring MVC应用

  1. 增加Spring的支持。(JAR)
  2. 配置前端控制器DispatcherServlet。(web.xml)
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
        <!--<context-param>-->
            <!--<param-name>contextConfigLocation</param-name>-->
            <!--<param-value>/WEB-INF/applicationContext.xml</param-value>-->
        <!--</context-param>-->
        <!--<listener>-->
            <!--<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>-->
        <!--</listener>-->
    
        <!-- 定义Spring MVC的前端控制器 -->
        <servlet>
            <!--Servlet的名称-->
            <servlet-name>springmvc</servlet-name>
            <!--Servlet对应的Java类-->
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!--当前Servlet的参数信息-->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>/WEB-INF/springmvc-config.xml</param-value>
            </init-param>
            <!--再Web应用启动时立即加载Servlet-->
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <!-- 让Spring MVC的前端控制器拦截所有请求 -->
        <!--Servlet的映射声明-->
        <servlet-mapping>
            <!--请求对应的Servlet的名称-->
            <servlet-name>springmvc</servlet-name>
            <!--监听当前域的所有请求-->
            <url-pattern>/</url-pattern>
        </servlet-mapping>
        <welcome-file-list>
            <welcome-file>welcome.jsp</welcome-file>
        </welcome-file-list>
    </web-app>
  3. 配置Spring MVC的Controller。(springmvc-config.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        <!-- 配置Handle,映射“/hello”请求 -->
        <bean name="/hello" class="org.fkit.controller.HelloController"/>
        <!-- 处理映射器将bean的name作为url进行查找,需要在配置Handle时制定name(即url) -->
        <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
        <!-- SimpleControllerHandlerAdapter是一个处理器适配器,所有处理适配器都要实现HandlerAdapter接口 -->
        <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
        <!-- 视图解析器 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
    </beans>

    springmvc-config.xml文件声明了HelloController业务控制器类,并将其映射到/Hello请求。此处还配置了一个处理映射器BeanNameUrlHandlerMapping,这样可以Bean的名称为url进行查找老同事配置了处理器适配器SimpleControllerHandlerAdapter,来完成对HelloController类的handleRequest方法的调用;最后配置了视图解析器InternalResourceViewResolver来解析视图,将View呈现给用户。需要注意的是,在Spring4.0之后,如果不配置处理映射器、处理器适配器和视图解析器,也会使用默认的完成Spring内部MVC工作。

  4. Controller的实现。(Java)
    package org.fkit.controller;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.Controller;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class HelloController implements Controller {
        private static final Log logger=LogFactory.getLog(HelloController.class);
    
        @Override
        public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
            logger.info("handleRequest 被调用。");
            ModelAndView modelAndView =new ModelAndView();
            modelAndView.addObject("message","Hello World!");
            modelAndView.setViewName("welcome.jsp");
            return modelAndView;
        }
    
    }
    

    Spring MVC建议把所有的视图页面存放在WEB-INF文件夹下,这样可以保护页面视图,避免直接向视图页面发送请求。

  5. View页面。(JSP)
    <%--
      Created by IntelliJ IDEA.
      User: Jeanne d'Arc
      Date: 2018/7/10
      Time: 21:59
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
      <head>
        <title>$Title$</title>
      </head>
      <body>
      ${requestScope.message}
      </body>
    </html>
    
  6. 测试应用。

P17基于注解的控制器

  1. Controller的实现
    package org.fkit.controller;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;
    
    /**
     * HelloController是一个基于注解的控制器,
     * 可以同时处理多个请求动作,并且无需实现任何接口。
     * org.springframewok.stereotype.Controller注解用于指示该类是一个控制器
     */
    @Controller
    public class HelloController {
        private static final Log logger = LogFactory.getLog(HelloController.class);
        /**
         * org.springframework.web.bind.annotation.RequestMapping注解
         * 用来映射请求的URL和请求的方法等。本例用来映射"/hello"
         * hello只是一个普通方法。
         * 该方法返回一个包含视图名或视图名和模型的ModelAndView对象。
         **/
        @RequestMapping(value = "/hello")
        public ModelAndView hello() {
            logger.info("hello方法被调用。");
            //创建准备返回的ModelAndView对象,该对象通常包含了返回视图名、模型的名称以及模型对象
            ModelAndView modelAndView = new ModelAndView();
            //添加模型数据,视图解析器会根据改名字解析到具体的视图页面
            modelAndView.setViewName("/WEB-INF/welcome.jsp");
            //返回ModelAndView对象
            return modelAndView;
        }
    }
    

    value="hello" 表示请求由hello方法进行处理。

  2. 修改Spring MVC的配置文件
    <?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:mvc="http://www.springframework.org/schema/mvc"
           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/mvc
           http://www.springframework.org/schema/mvc/spring-mvc.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd">
        <!--spring可以自动去扫描bean-package下面的包或者子包下面的java文件-->
        <context:component-scan base-package="org.fkit.controller"/>
        <!--配置annotation类型的处理映射器-->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
        <!--配置annotation类型的处理器映射器-->
        <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
        <!--视图解析器-->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"/>
    </beans>

     

附录 Spring Schema 约束

<?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:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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
          http://www.springframework.org/schema/aop
          http://www.springframework.org/schema/aop/spring-aop.xsd
          http://www.springframework.org/schema/tx
          http://www.springframework.org/schema/tx/spring-tx.xsd">
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    //上面两个是基础IOC的约束,必备
    xmlns:context="http://www.springframework.org/schema/context"
    //上面一个是开启注解管理Bean对象的约束
    xmlns:aop="http://www.springframework.org/schema/aop"
    //aop的注解约束
    xmlns:tx="http://www.springframework.org/schema/tx"
    //事务的约束
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    //上面两个是基础IOC的约束,必备
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd
    //上面一个是开启注解管理Bean对象的约束
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    //aop的注解约束
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">
    //事务的约束
</beans>

P19 详解DispatcherServlet

框架源代码:org.springframework.web.servlet.DispatcherServlet.java

protected void initStrategies(ApplicationContext context) {
		initMultipartResolver(context);//初始化上传文件解析器
		initLocaleResolver(context);//初始化本地化解析器
		initThemeResolver(context);//初始化主题解析器
		initHandlerMappings(context);//初始化处理器解析器,将请求映射到处理器
		initHandlerAdapters(context);//初始化处理器适配器
		initHandlerExceptionResolvers(context);
        //初始化处理器异常解析器,如果执行过程中遇到一场将交给HandlerExceptionResolver来解析
		initRequestToViewNameTranslator(context);//初始化请求到视图名称解析器
		initViewResolvers(context);
        //初始化视图解析器,通过ViewResolver解析逻辑视图名到具体视图实现
		initFlashMapManager(context);//初始化flash映射管理器
	}

initStrategies方法将在WebApplicationContext初始化后自动执行,自动扫描上下文的Bean,根据名称或类型匹配的机制查找自定义的组件,如果没有找到则会装配一套Spring的默认组件。在org.springframework.web.servlet路径下有一个DispatcherServlet.properties配置文件,该文件制定了DispatcherServlet所使用的默认组件。

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

//处理器解析器(共2个)
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping

//处理器适配器(共3个)
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter

//异常处理器(共3个)
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
	org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
	org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

//视图名称解析器
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

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

//FlashMap映射解析器
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

同一类型的组件如果存在多个,优先级顺序:因为这些组件都实现了org.springframework.core.Ordered接口,所以可以通过Order属性确定优先级的顺序,值越小的优先级越高。

P22 Spring MVC应用的开发步骤

  1. 在web.xml文件中定义前端控制器DispatcherServlet来拦截用户请求。
  2. 如果需要以POST方式提交请求,则定义包含表单数据打的JSP页面,如果仅仅只是以GET方式发送请求,则无需经过这一步。
  3. 定义处理用户请求的Hanler类,可以实现Controller接口或者使用@Controller注解。
  4. 配置Handle。
  5. 编写视图资源。

P23 Spring MVC执行的流程

  1. 用户向服务器发送请求。
  2. DispatcherServlet对请求URL(统一资源定位符)进行解析,得到URI(请求资源标识符)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象,包括Handler对象以及Handler对象对应的拦截器,这些对象会被封装到一个HandlerExecutionChain对象当中返回。
  3. DispatcherServlet根据获得的Handler,选择一个合适的HandlerAdapter。HandlerAdapter的设计符合面向对象中的单一职责原则,代码架构清晰,便于维护,最重要的是,代码可复用性高。HandlerAdapter会被用于处理多种Handler,调用Handler实际处理请求的方法,例如hello方法。
  4. 提取请求中的模型数据,开始执行Handler(Controller)。在填充Handler的入参过程中,根据配置,Spring将帮你做一些额外的工作。   
    消息转换 将请求消息(如Json,xml等数据)转换成一个对象,将对象转换为指定的响应信息
    数据转换 将请求消息进行数据转换,如String转换成Integer、Double等
    数据格式化 对请求消息进行数据格式化,如将字符串转换成格式化数字或格式化日期等
    数据验证 验证数据的有效性(长度、格式等),验证结果存储到BIndingResult或Error中
  5. Handle执行完成后,向DispatcherServlet返回一个ModelAndView对象,ModelAndView对象中应该包含视图名或视图名和模型。
  6. 根据返回的ModelAndView对象,选择一个合适的ViewResolver(视图解析器)返回给DispatcherServlet。
  7. ViewResolver结合Model和View来渲染视图。
  8. 将视图渲染结果返回给客户端。

以上8个步骤,DispatcherServlet、HandlerMapping、HandlerAdapter和ViewResolver等对象协同工作,完成Spring MVC请求→响应的整个工作流程,这些对象所完成的工作对于开发者来说都是不可兼得,开发者并不需要关心这些对象是如何工作的,开发者只需要在Handler(Controller)当中完成对请求的业务处理。

2018.7.23

干物女(weiwei)—三无MarBlue

温柔正确的人总是难以生存,因为这世界既不温柔,也不正确。

猜你喜欢

转载自blog.csdn.net/Altr1aPendrag0n/article/details/81154913