Spring MVC 执行原理

在 Spring Mvc 访问过程里,每个请求都首先经过 许多的过滤器,经 DispatcherServlet 处理;

一个Spring MVC工程里,可以配置多个的 dispatcherServlet ,每个 DispatcherServlet 可以对应多个的 HandlerMapping ,每个 HandlerMapping 可以有自己的 Interceptor (拦截器)。

1. 请求首先 由 前端 DispatcherServlet 捕获;

2. DispatcherServlet 经过 HandlerMapping 获取适当的 Hanlder ,也即 Controller ,并返回给 DispatcherServlet;

3. 如果有设置 拦截器,首选执行拦截器的 preHandler 方法,并把执行结果返回 DispatcherServlet;

4. DispatcherServlet 根据捕获的请求,以及 Handler (Controller) ,获取到适当的 HandlerAdapter 处理,并把结果返回给 DispatcherServlet,结果为 (View 和 Model);

5. 如果有设置拦截器,就是执行 拦截器的 postHandler 方法,并返回 DispatcherServlet;

6. DispatcherServlet 根据获取的 view 跟 model 结合 ViewResolver,返回所指的 视图模板,并返回给 DispatcherServlet;

7. DispatcherServlet 结合 视图模型跟model ,执行 render() 渲染界面,并返回给客户端;

一个DispatcherServlet 都有自己 上下文配置文件, 这个配置继承自根的上下文配置文件;

每个 DispatcherServlet 都可配置多个不同的 HandlerMapping 映射方式;每个 HandlerMapping 都实现了 Ordered 接口,可以上下文文件配置中设置优先使用的 HandlerMapping;

用户的请求被 DispatcherServlet 捕获后,DispatcherServlet 使用优先级高的 HandlerMapping 查找可用的 Handler,如果没有找到合适的 Handler,就使优先级次之的 HandlerMapping 继续查找,直到找到为止;

比如:Spring MVC 提供主要的 HanderMapping 有 DefaultAnnotationHandlerMapping, SimpleUrlHandlerMapping, BeanNameUrlHandlerMapping

<bean id="defaultAnnoHandlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="order" value="1"/>
</bean> <bean id="simpleUrlMapping" class="org.
springframework.Web.servlet.handler.SimpleUrlHandlerMapping">
<property name="order" value="2"/>
<!-- ... -->
</bean> <bean id="beanNameUrlMapping" class="org.springframework.Web.servlet.
handler.BeanNameUrlHandlerMapping">
<!-- ... -->
</bean>

如果不为HandlerMapping明确指定order,那么默认值为Integer.MAX_VALUE,对应最低优先级。

如果 DefaultAnnotationHandlerMapping 找到相应的 Handler ,就把数据传给相应的 Controller 类下的相应的 HandlerAdapter (方法处)处理;如果没有找到,就到 SimpleUrlHandlerMapping 处理;

Spring MVC xml配置说明

1. Web.xml 配置

1>. 首先 Spring 监听器:

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

它是整个 spring 框架的入口,会自动装载 应用程序根上下文的 配置文件;因为他实现了 ServletContextListener 这个接口,项目启动时,就会执行它实现的方法。

2>. 根应用程序上下文配置:

<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>

也可叫 spring 全局配置,在这里可以配置 数据源 等一些 全局的spring 基本的配置;dispatcherServlet 可以继承自这里的配置;

3>. diapatcherServlet 配置:

<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

load-on-startup 值为 "1" 表示该 servlet (dispatcherServlet 也是一个 servlet) 随 servlet 容器同时启动。

dispatcherservlet 的 init-param 节点不是必须的,如果没有配置,该 dispatcherServlet 对应的 上下文配置文件 就会到 /WEB-INF/[servlet-name]-servlet.xml 加载;

servlet-mapping 的 url-pattern 的值 "*.do" 表示,servlet 只会拦截 .do 后缀的请求,这种配置不会影响静态资源的访问。

4>. 配置工程项目编码:

<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter> <filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

该过滤器如果没有配置,请求访问可能会遇乱码;

-------------------------------------------------------------

现在配置 diapatcherServlet 对应的 上下文配置文件: /WEB-INF/spring/appServlet/servlet-context.xml (上面配置的)

1>.  启动扫描所有的 Controller

<context:component-scan base-package="com.study.web"/>

主要作用于 @Controller,假如他的包结构是这样的:

com.study.web

|---controller

|-----|-----abcController.java

   |-----cdeController.java

那么上面的 base-package 写为 com.study.web.controller 也是正确的;

2>. <mvc:annotation-driven /> 说明:

是一种简写形式,可以让初学者快速成应用默认的配置方案,会默认注册 DefaultAnnotationHandleMapping以及AnnotionMethodHandleAdapter 这两个 Bean, 这两个 Bean ,前者对应类级别, 后者对应到方法级别;

上在面的 DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter 是 Spring 为 @Controller 分发请求所必需的。

annotation-driven 扫描指定包中类上的注解,常用的注解有:

@Controller 声明Action组件
@Service 声明Service组件 @Service("myMovieLister")
@Repository 声明Dao组件
@Component 泛指组件, 当不好归类时.
@RequestMapping("/menu") 请求映射
@Resource 用于注入,( j2ee提供的 ) 默认按名称装配,@Resource(name="beanName")
@Autowired 用于注入,(srping提供的) 默认按类型装配
@Transactional( rollbackFor={Exception.class}) 事务管理
@ResponseBody
@Scope("prototype") 设定bean的作用域

3>. 视图解析类,对模型视图名称的解析,在请求时模型视图名称添加前后缀

<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>

InternalResourceViewResolver 提供了对 JstlView 的支持: <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />

Spring Mvc 2.5 版本以前,提供了 注解 功能,实现了对 REST 的全面支持; REST 通过不带扩展名的 URL 来访问系统资源;REST 会把每个请求资源当成是静态,每个 URL 资源都是一个静态资源;

它通 @RequestMapping主@PathVariable 注释提供访问映射,由@RequestMapping 中的 value 及 method 就可以支持Rest式的访问。

通过策略接口,Spring 框架是高度可配置的,而且包含多种视图技术,例如 JavaServer Pages(JSP)技术、Velocity、Tiles、iText 和 POI。Spring MVC 框架并不知道使用的视图,所以不会强迫您只使用 JSP 技术。Spring MVC 分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。

比如 使用的是 Velocity 技术,那么只要把 suffix 的 value 值改为 ".vm" 即可;

4>.  Spring 拦截器:

全局配置:

<mvc:interceptors>

        <bean class="com.study.web.interceptor.MyInterceptor"></bean>

</mvc:interceptors>

基于路径的拦截器:

<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**/*.do"/>
<beans:bean class="com.study.interceptor.utils.StuInterceptor">
<beans:property name="startWrk">
<beans:value>1</beans:value>
</beans:property> <beans:property name="endWrk">
<beans:value>24</beans:value>
</beans:property> <beans:property name="redirectUrl">
<beans:value>http://127.0.0.1:8080/interceptor/static/timeout.htm</beans:value>
</beans:property>
</beans:bean>
</mvc:interceptor>
</mvc:interceptors>

相关的 Java 类 : StuInterceptor ( 该类的作用是拦截在指定的时间范围外,则页面请求转到/interceptor/static/timeout.htm )

package com.study.interceptor.utils;

import java.util.Calendar;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
//import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import com.study.interceptor.controller.HomeController; public class StuInterceptor implements HandlerInterceptor /*extends HandlerInterceptorAdapter*/ { private static final Logger logger = LoggerFactory.getLogger(HomeController.class); private int startWrk;
private int endWrk;
private String redirectUrl; @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.info("Interceptor", "I am in Custom Interceptor!"); Calendar cal = Calendar.getInstance(); int hour = cal.get(Calendar.HOUR_OF_DAY); if (hour > startWrk && hour < endWrk) {
return true;
} else {
response.sendRedirect(redirectUrl);
return false;
}
} public int getStartWrk() {
return this.startWrk;
} public void setStartWrk(int startWrk) {
this.startWrk = startWrk;
} public int getEndWrk() {
return this.endWrk;
} public void setEndWrk(int endWrk) {
this.endWrk = endWrk;
} public String getRedirectUrl() {
return this.redirectUrl;
} public void setRedirectUrl(String redirectUrl) {
this.redirectUrl = redirectUrl;
} @Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
System.out.println("after posthandler");
} @Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
System.out.println("after completion");
}
}

5>. 在 HandlerMapping 内配置拦截器:

<!-- Mapping -->
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/abc.do">abcController</prop>
<prop key="def.kara">defController</prop>
</props>
</property>
<!-- 注册拦截器 -->
<property name="interceptors">
<list>
<ref bean="myInterceptor"></ref>
</list>
</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<bean class="com.study.web.MyInteceptor"></bean>
</list>
</property>
</bean>

6>. 使用 placeHolder 加载应用程序属性配置文件

<context:property-placeholder location="/WEB-INF/config.properties"/>

比如 加载 mysql jdbc 配置信息:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/springdb
username=root
password=123

那么 mysql 的数据源配置的 驱动信息,用户信息,就可以配置成这样:

<context:property-placeholder location="classpath:META-INF/mybatis/mysql.properties" />

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driver}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
</bean>

spring Mvc 执行原理 及 xml注解配置说明 (六)的更多相关文章

  1. (4.1)Spring MVC执行原理和基于Java的配置过程

    一.Spring MVC执行原理和基于Java配置的配置过程 (一)Spring MVC执行过程,大致为7步. 所有的请求都会经过Spring的一个单例的DispacherServlet. Dispa ...

  2. Spring MVC执行原理和基于Java的配置过程

    一.Spring MVC执行原理和基于Java配置的配置过程 (一)Spring MVC执行过程,大致为7步. 所有的请求都会经过Spring的一个单例的DispacherServlet. Dispa ...

  3. Spring MVC执行原理

    spring的MVC执行原理 1.spring mvc将所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责对请求 进行真正的处理工作. 2.DispatcherSer ...

  4. Spring MVC 工作原理和流程、注解

    Spring MVC 是实现MVC设计模式的企业级开发框架,是Spring框架的一个子模块,无需整合,开发起来更加便捷. MVC设计模式 MVC是一种设计模式,它将应用程序分为 Controller. ...

  5. spring的MVC执行原理

    spring的MVC执行原理 1.spring mvc将所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责对请求 进行真正的处理工作. 2.DispatcherSer ...

  6. Spring MVC工作原理(好用版)

    Spring MVC工作原理 参考: SpringMVC工作原理 - 平凡希 - 博客园https://www.cnblogs.com/xiaoxi/p/6164383.html SpringMVC的 ...

  7. Spring MVC执行的流程

    1.Spring MVC应用的开发步骤 a.在web.xml文件中定义前端控制器DispatcherServlet来拦截用户请求.由于Web应用是基于请求/响应架构的应用,所以 不管哪个MVC Web ...

  8. Spring MVC简单原理

    Spring MVC原理 针对有Java Web基础.Spring基础和Spring MVC使用经验者. 前言 目前基于Java的web后端,Spring生态应该是比较常见了.虽然现在流行前后端分离, ...

  9. 一文读懂Spring MVC执行流程

    说到Spring MVC执行流程,网上有很多这方面的文章介绍,但是都不太详细,作为一个初学者去读会有许多不理解的地方,今天这篇文章记录一下我学习Spring MVC的心得体会 话不多说,先上图:   ...

随机推荐

  1. 使用Fidder从安卓模拟器获取APP内H5游戏网址

    大家都知道H5游戏其实是网页,但是有些APP或者微端不显示网址链接.这里给大家介绍介绍一种,利用Fiddler进行抓包,获取APP打开的网址的方法.有人说何必多此一举呢,直接用模拟器玩游戏就好了.的确 ...

  2. Python初学者随笔Week1

    Python从入门到放弃 本文主要是描述的是作为初学者对python学习的过程与经历分享,包括一些历程的分享与重要的时间节点记录,对于python学习的笔记与心得. 如果你也是初学者,我们可以一起学习 ...

  3. CSAPP lab2 二进制拆弹 binary bombs phase_5

    给出对应于7个阶段的7篇博客 phase_1  https://www.cnblogs.com/wkfvawl/p/10632044.htmlphase_2  https://www.cnblogs. ...

  4. 20135119_涂文斌 实验三 敏捷开发与XP实践

    北京电子科技学院(BESTI) 实  验  报  告 课程: Java        班级:1351           姓名:涂文斌          学号:20135119 成绩:         ...

  5. Leetcode题库——38.报数

    @author: ZZQ @software: PyCharm @file: countAndSay.py @time: 2018/11/9 14:07 说明:报数序列是一个整数序列,按照其中的整数的 ...

  6. “数学口袋精灵”App的第一个Sprint计划

    一.现状 我们这个团队想制作一个关于运算的游戏类型手机软件,针对我们这个学期的Android软件开发的课程,制作出一个关于数学算术游戏软件. 二.任务认领 第一阶段先把静态网页制作出来,各自的任务: ...

  7. 浅谈个人对RAID技术的理解

    RAID,字面意思为一种廉价的冗余磁盘阵列,它是通过将大量的磁盘分组,实现了数据冗余,目的是为了保护数据.RAID现已经应用于计算机各个领域.它的优点是降低了工作成本并提高了效率,并且使系统有稳定的运 ...

  8. 如何访问cxGrid控件过滤后的数据集

    var I: Integer; begin Memo1.Lines.Clear; with cxGrid1DBTableView1.DataController do for I := 0 to Fi ...

  9. 通过第三方软件打开sqlite

    1.SQLite Expert 使用之前,可以先下载SQLite Expert,方便查看.db3数据库 下载链接是http://www.sqliteexpert.com/    可以谷歌找到licen ...

  10. 移动的调试工具vConsole

    在PC端写代码调试的时候,直接console.log()即可,但是在手机端怎么调试??最近发现一个很有用的插件vConsole 首先引入插件: 然后再文件中使用即可: 这样再手机中就会出现下面的标识, ...