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. ats 安全

    Controlling Access ats可以配置为仅允许某些客户端使用代理缓存. 1. 为ip_allow.config添加一行,以获取允许访问ats的每个IP地址或IP地址范围; 2. traf ...

  2. sqli-labs 下载、安装

    sqli-labs 下载.安装 下载地址:https://github.com/Audi-1/sqli-labs phpstudy:http://down.php.cn/PhpStudy2018021 ...

  3. SQL执行结果操作

    1. 返回执行结果中的一行 mysql_fetch_row() 返回执行结果的当前行的数值数组,执行这个函数后,结果指向下一行. e.g. $row = mysql_fetch_row($result ...

  4. “北航Clubs” Beta版本开发目标

    Beta版本开发目标 总体设想:修复Alpha版本中的若干bug,并在Alpha版本成果之上进行进一步开发,实现社员管理.评论.站内信等功能. 1.对Alpha版本功能的更新与加强 后端实现从SQLi ...

  5. java实验项目报告

            JAVA课程项目报告   题目:利用java实现一个时钟的小程序 姓名:王国梁 班级:计科13-2 学号:201303011200         利用JAVA实现一个时钟的小程序 1 ...

  6. git learn

    $ git config --global user.name "Your Name" $ git config --global user.email "email@e ...

  7. [专贴]Xshell 以及 shell 的快捷键

    Ctrl + a 切换到命令行开始Ctrl + e 切换到命令行末尾Ctrl + l 清除屏幕内容Ctrl + u 清除光标之前的内容Ctrl + k 清除光标之后的内容Ctrl + h 类似于退格键 ...

  8. SpringBoot 7.SpringBoot 结合 Thymeleaf

    一.引入 Thymeleaf 依赖 <!-- Spring boot - thymeleaf --> <dependency> <groupId>org.sprin ...

  9. Spring注入的不同方式

    1.直接创建一个Bean <bean id="dboperate" class="study.spring2.Test"></bean> ...

  10. 【大数据】SparkStreaming学习笔记

    第1章 Spark Streaming概述 1.1 Spark Streaming是什么 Spark Streaming用于流式数据的处理.Spark Streaming支持的数据输入源很多,例如:K ...