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. opencv core组件进阶

    1.图像在内存中存储方式,图像矩阵的大小取决于颜色模型,取决于所有的通道数:还有重要的颜色空间缩减的概念:因为如果是RGB的话,使用uchar的话,就有256^3的结合方法.所以要用到颜色缩减的方法, ...

  2. Unity之日志管理

    1. 目录结构 1. Plugins --> 存放Log4Net动态库文件 2. Scripts --> 存放写日志的脚本 3. StreamingAssets -->存放Log4N ...

  3. LintCode——旋转字符串

    描述:给定一个字符串和一个偏移量,根据偏移量旋转字符串(从左向右旋转) 样例:对于字符串 "abcdefg"     offset=0 => "abcdefg&qu ...

  4. 当activity改变时,我们如何处理它

    用户和系统触发­的事件,可能造成一个activity状体的改变.这个文档描述了一些常见的情况,和如何去处理这些改变. 原网站:https://developer.android.google.cn/g ...

  5. 在Ubuntu虚拟机上安装DVWA

    学习资料来源:https://www.neddos.tech/?p=107 最后更新时间: 190122·17:41 1> 什么是DVWA(Damn Vulnerable Web Applica ...

  6. C语言函数参数传递

    1.值传递 void swap(int x,int y) { int temp = x; x = y; y = temp; } void main() { , b = ; swap(a, b); } ...

  7. CentOS下 NFS的简单使用以及windows 关在linux的NFS存储方法

    1. 全部安装的情况下NFS已经安装到服务器上面了,如果没有安装的话 需要使用如下命令进行安装 yum -y install nfs-utils rpcbind 2. 创建需要使用的NFS目录 mkd ...

  8. C语言变长数组data[0]

    1.前言 在刷题时遇到一个结构中包含char data[0],第一次见到时感觉很奇怪,数组的长度怎么可以为零呢?于是上网搜索一下这样的用法的目的,发现在linux内核中,结构体中经常用到data[0] ...

  9. Spring之c3p0连接池xml配置和使用举例

    1.导入jar包 c3p0-0.9.5.2.jar mchange-commons-java-0.2.11.jar 2.源码: beans.xml <beans xmlns="http ...

  10. ES6学习笔记(三):与迭代相关的新东东

    Symbol 概念 Symbol:一种新的原始数据类型,表示独一无二的值. 注意:Symbol函数的参数只是表示对当前Symbol值的描述,因此相同参数的Symbol函数的返回值是不相等的. // 没 ...