JavaEE之Spring webmvc 启动流程 (基于IDEA)
一、Spring webmvc 是什么
Spring webmvc是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring webmvc也是要简化我们日常Web开发的。
二、Spring webmvc所具有的优点
清晰的角色划分:控制器(controller)、验证器(validator)、命令对象(command obect)、表单对象(form object)、模型对象(model object)、Servlet分发器(DispatcherServlet)、处理器映射(handler mapping)、试图解析器(view resoler)等等。每一个角色都可以由一个专门的对象来实现。
强大而直接的配置方式:将框架类和应用程序累都能作为JavaBean配置,支持跨多个context的引用,例如,在web控制器中对业务对象和验证器validator)的引用。
可适配、非侵入:可以根据不同的应用场景,选择何事的控制器子类(simple型、command型、from型、wizard型、multi-action型或者自定义),而不是一个单一控制器(比如Action/ActionForm)继承。
可重用的业务代码:可以使用现有的业务对象作为命令或表单对象,而不需要去扩展某个特定框架的基类。
可定制的绑定(binding)和验证(validation):比如将类型不匹配作为应用级的验证错误,这可以保证错误的值。再比如本地化的日期和数字绑定等等。在其他某些框架中,你只能使用字符串表单对象,需要手动解析它并转换到业务对象。
可定制的handler mapping和view resolution:spring提供从最简单的URL映射,到复杂的、专用的定制策略。与某些web MVC框架强制开发人员使用单一特定技术相比,Spring显得更加灵活。
灵活的model转换:在Springweb框架中,使用基于Map的键/值对来达到轻易的与各种视图技术集成。
可定制的本地化和主题(theme)解析:支持在JSP中可选择地使用Spring标签库、支持JSTL、支持Velocity(不需要额外的中间层)等等。
简单而强大的JSP标签库(Spring Tag Library):支持包括诸如数据绑定和主题(theme)之类的许多功能。他提供在标记方面的最大灵活性。
JSP表单标签库:在Spring2.0中引入的表单标签库,使用在JSP编写表单更加容易。
Spring Bean的生命周期可以被限制在当前的HTTp Request或者HTTp Session。准确的说,这并非Spring MVC框架本身特性,而应归属于Spring MVC使用的WebApplicationContext容器。
三、解析Spring webmvc启动流程
1.servlet的注册
spring webmvc中使用DispatchServlet为不同请求匹配对应的处理器, 将结果传递给视图解析器最终呈现给客户端.
具体针对于DispatcherServlet 的解读参考.
在我们的spring webmvcx项目中,我们通过在web.xml里的配置能够有效地实现对于servlet的注册。
<servlet>
<servlet-name>api</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:app-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>api</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
2.IoC容器创建
何为IoC容器
spring容器是spring框架的核心,容器创建对象并且把它们连接在一起,并管理它们的生命周期。
app-context.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" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<bean id="student" class="org.example.spring.mvc.bean.Student" scope="prototype"/>
<bean id="studentHomework" class="org.example.spring.mvc.bean.StudentHomework" scope="prototype"/>
<bean id="homework" class="org.example.spring.mvc.bean.Homework" scope="prototype"/>
</beans>
并通过配置文件创建对象
public void student(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("app-context.xml");
Student student = (Student) applicationContext.getBean("student");
}
3.bean初始化
何为bean
Spring比作一个大型的工厂,而Spring容器中的Bean就是该工厂的产品.对于Spring容器能够生产哪些产品,则取决于配置文件中配置。
beans…/>元素是Spring配置文件的根元素,<bean…/>元素师<beans…/>元素的子元素,<beans…/>元素可以包含多个<bean…/>子元素,每个<bean…/>元素可以定义一个Bean实例,每一个Bean对应Spring容器里的一个Java实例定义Bean时通常需要指定两个属性。
Id:确定该Bean的唯一标识符,容器对Bean管理、访问、以及该Bean的依赖关系,都通过该属性完成。Bean的id属性在Spring容器中是唯一的。
Class:指定该Bean的具体实现类。注意这里不能使接口。通常情况下,Spring会直接使用new关键字创建该Bean的实例,因此,这里必须提供Bean实现类的类名。
(详情请参考:)
比如这里我实现了对于student,studentHomework,homework的配置
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<bean id="student" class="org.example.spring.mvc.bean.Student" scope="prototype"/>
<bean id="studentHomework" class="org.example.spring.mvc.bean.StudentHomework" scope="prototype"/>
<bean id="homework" class="org.example.spring.mvc.bean.Homework" scope="prototype"/>
</beans>
Spring容器集中管理Bean的实例化,Bean实例可以通过BeanFactory的getBean(Stringbeanid)方法得到。BeanFactory是一个工厂,程序只需要获取BeanFactory引用,即可获得Spring容器管理全部实例的引用。程序不需要与具体实例的实现过程耦合。大部分Java EE应用里,应用在启动时,会自动创建Spring容器,组件之间直接以依赖注入的方式耦合,甚至无须主动访问Spring容器本身。
这里相当于实现了:
student = new bean.Student();
studentHomework = new bean.StudentHomework();
homeworj = new.bean.Homework();
当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。
Spring支持5种作用域:
Singleton:单例模式。在整个SpringIoC容器中,使用singleton定义的Bean将只有一个实例。
Prototype:原型模式。每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例。
request:对于每次HTTP请求,使用request定义的Bean都将产生一个新的实例,即每次HTTP请求都会产生不同的Bean实例。当然只有在WEB应用中使用Spring时,该作用域才真正有效。
session:对于每次HTTPSession,使用session定义的Bean都将产生一个新的实例时,即每次HTTP Session都将产生不同的Bean实例。同HTTP一样,只有在WEB应用才会有效。
global session:每个全局的HTTPSession对应一个Bean实例。仅在portlet Context的时候才有效。
4.mvc流程
Spring Web MVC也是服务到工作者模式的实现,但进行可优化。前端控制器是DispatcherServlet;应用控制器其实拆为处理器映射器(Handler Mapping)进行处理器管理和视图解析器(View Resolver)进行视图管理;页面控制器/动作/处理器为Controller接口(仅包含ModelAndView handleRequest(request, response) 方法)的实现(也可以是任何的POJO类);支持本地化(Locale)解析、主题(Theme)解析及文件上传等;提供了非常灵活的数据验证、格式化和数据绑定机制;提供了强大的约定大于配置(惯例优先原则)的契约式编程支持。
SpringMVC在Web应用中充当控制层(Controller)的角色,对请求进行分发处理。
图源链接 深入解析spring mvc的流程:
1.客户端请求被DispatcherServlet(前端控制器)接收
2.DispatcherServlet请求HandlerMapping查询Handler
3.HandlerMapping根据请求URL查找Handler,将Handler和HandlerInterceptor以HandlerExecutionChain的形式一并返回给DispatcherServlet
4.DispatcherServlet请求HandlerAdapter执行Handler
5.HandlerAdapter调用Handler的方法做业务逻辑处理
6.HandlerAdapter处理完Handler会生成一个ModelAndView对象
7.将ModelAndView对象返回给DispatcherServlet
8.DispatcherServlet将获取的ModelAndView对象传给ViewResolver视图解析器,请求进行视图解析
9.ViewResolver将逻辑视图解析成物理视图View,返回给DispatcherServlet
10.DispatcherServlet根据View进行视图渲染(将模型数据填充到视图中)
11.DispatcherServlet将渲染后的视图响应给客户端