《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应用
- 增加Spring的支持。(JAR)
- 配置前端控制器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>
- 配置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工作。
- 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文件夹下,这样可以保护页面视图,避免直接向视图页面发送请求。
- 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>
- 测试应用。
P17基于注解的控制器
- 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方法进行处理。
- 修改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应用的开发步骤
- 在web.xml文件中定义前端控制器DispatcherServlet来拦截用户请求。
- 如果需要以POST方式提交请求,则定义包含表单数据打的JSP页面,如果仅仅只是以GET方式发送请求,则无需经过这一步。
- 定义处理用户请求的Hanler类,可以实现Controller接口或者使用@Controller注解。
- 配置Handle。
- 编写视图资源。
P23 Spring MVC执行的流程
- 用户向服务器发送请求。
- DispatcherServlet对请求URL(统一资源定位符)进行解析,得到URI(请求资源标识符)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象,包括Handler对象以及Handler对象对应的拦截器,这些对象会被封装到一个HandlerExecutionChain对象当中返回。
- DispatcherServlet根据获得的Handler,选择一个合适的HandlerAdapter。HandlerAdapter的设计符合面向对象中的单一职责原则,代码架构清晰,便于维护,最重要的是,代码可复用性高。HandlerAdapter会被用于处理多种Handler,调用Handler实际处理请求的方法,例如hello方法。
- 提取请求中的模型数据,开始执行Handler(Controller)。在填充Handler的入参过程中,根据配置,Spring将帮你做一些额外的工作。
消息转换 将请求消息(如Json,xml等数据)转换成一个对象,将对象转换为指定的响应信息 数据转换 将请求消息进行数据转换,如String转换成Integer、Double等 数据格式化 对请求消息进行数据格式化,如将字符串转换成格式化数字或格式化日期等 数据验证 验证数据的有效性(长度、格式等),验证结果存储到BIndingResult或Error中 - Handle执行完成后,向DispatcherServlet返回一个ModelAndView对象,ModelAndView对象中应该包含视图名或视图名和模型。
- 根据返回的ModelAndView对象,选择一个合适的ViewResolver(视图解析器)返回给DispatcherServlet。
- ViewResolver结合Model和View来渲染视图。
- 将视图渲染结果返回给客户端。
以上8个步骤,DispatcherServlet、HandlerMapping、HandlerAdapter和ViewResolver等对象协同工作,完成Spring MVC请求→响应的整个工作流程,这些对象所完成的工作对于开发者来说都是不可兼得,开发者并不需要关心这些对象是如何工作的,开发者只需要在Handler(Controller)当中完成对请求的业务处理。
2018.7.23
干物女(weiwei)—三无MarBlue
温柔正确的人总是难以生存,因为这世界既不温柔,也不正确。