spring Mvc 执行原理 及 xml注解配置说明 (六)

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注解配置说明 (六),布布扣,bubuko.com

时间: 2024-10-11 08:00:14

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

【转】spring Mvc 执行原理 及 xml注解配置说明

Spring MVC 执行原理 在 Spring Mvc 访问过程里,每个请求都首先经过 许多的过滤器,经 DispatcherServlet 处理; 一个Spring MVC工程里,可以配置多个的 dispatcherServlet ,每个 DispatcherServlet 可以对应多个的 HandlerMapping ,每个 HandlerMapping 可以有自己的 Interceptor (拦截器). 1. 请求首先 由 前端 DispatcherServlet 捕获: 2. Disp

Spring MVC执行的流程

1.Spring MVC应用的开发步骤 a.在web.xml文件中定义前端控制器DispatcherServlet来拦截用户请求.由于Web应用是基于请求/响应架构的应用,所以 不管哪个MVC Web框架,都需要在web.xml中配置该框架的核心Servlet或Filter,这样才可以让该框架介入到Web应用中. <servlet> <!-- Serlvet的名称 --> <servlet-name>springmvc</servlet-name> <

Spring MVC简单原理

Spring MVC简单原理 针对有Java Web基础.Spring基础和Spring MVC使用经验者,文章比较简单,权当自己的一个总结和备忘吧. 前言 目前基于Java的web后端,Spring生态应该是比较常见了.虽然现在流行前后端分离,MVC和后端模板渲染越来越少,后端专注向前端提供数据接口.但由于笔者维护着一个老项目,既有JSP技术也有只返回JSON的接口,两者都是基于Spring MVC这一套技术实现的,所以暂且觉得了解一下Spring MVC原理还是有所裨益的. Spring M

Spring MVC 4常用的那些注解

Spring从2.5版本开始在编程中引入注解,用户可以使用@RequestMapping, @RequestParam, @ModelAttribute等等这样类似的注解.到目前为止,Spring的版本虽然发生了很大的变化,但注解的特性却是一直延续下来,并不断扩展,让广大的开发人员的双手变的更轻松起来,这都离不开Annotation的强大作用,今天我们就一起来看看Spring MVC 4中常用的那些注解吧. 1. @Controller Controller控制器是通过服务接口定义的提供访问应用

详解Spring MVC 4常用的那些注解

Spring从2.5版本开始在编程中引入注解,用户可以使用@RequestMapping, @RequestParam, @ModelAttribute等等这样类似的注解.到目前为止,Spring的版本虽然发生了很大的变化,但注解的特性却是一直延续下来,并不断扩展,让广大的开发人员的双手变的更轻松起来,这都离不开Annotation的强大作用,今天我们就一起来看看Spring MVC 4中常用的那些注解吧. 1. @Controller Controller控制器是通过服务接口定义的提供访问应用

[转]Spring MVC 4常用的那些注解

Spring从2.5版本开始在编程中引入注解,用户可以使用@RequestMapping, @RequestParam, @ModelAttribute等等这样类似的注解.到目前为止,Spring的版本虽然 Controller控制器是通过服务接口定义的提供访问应用程序的一种行为,它解释用户的输入,将其转换成一个模型然后将试图呈献给用户. 1 2 3 4 5 6 7 8 9 10 11 12 13 <?xml version="1.0" encoding="UTF-8&

Spring MVC:原理与使用

本人上一篇博文提到了Spring的注入功能,这样在存在对象依赖(具体意思可见上一篇博文)的时候就不用自己生成一个对象了,特别是对于较多的无状态对象的时候,这个特别方便,加上Spring提供的用xml配置文件和代码注解两种方式,使得使用更加灵活.然而spring的功能远不止如此,Spring的强大功能其实还在于做Java后台框架,即Spring MVC,把后台的逻辑和和视图解耦分离,方便使用与扩展,特别是在大型项目中很有用. PS:卖个自己的广告,上一篇博文<Spring注入:配置与注解> (如

Spring MVC工作原理

Spring MVC工作流程图 图一 图二  Spring工作流程描述 1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获: 2. DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI).然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回: 3.

Spring MVC(一)Spring MVC的原理

1.Spring MVC的目的 构建向Spring框架那样灵活和松耦合的Web应用程序. 2.Spring MVC中如何处理Request? 每当用户在Web浏览器中点击链接或者提交表单时,Request就开始工作了. 从离开浏览器开始到获取响应返回,Request会在经历过的每一站留下一些信息,也会获取一些信息. DipatcherServlet--前端控制器Servlet,负责将Request发送给Spring MVC的Controller: Handler Mapping--处理器映射,应