`

URL到框架的映射

 
阅读更多
Spring:表现层框架
一般表现层框架面临的三大问题:
URL到框架的映射。
http请求参数绑定
http响应的生成和输出

那么Spring是如何解决这三大问题的呢?

回答:问题1
SpringMVC中的核心类及接口(以用户请求服务器到服务器响应用户请求顺序一一介绍)
rg.springframework.web.servlet包中定义的HandlerMapping接口
核心方法:HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

回到DispatcherServlet的处理流程,当DispatcherServlet接收到web请求后,由标准Servlet类处理方法doGet或者doPost,经过几次转发后,
将转发给HandlerMapping接口调用getHandler方法(HandlerMapping接口有多种实现类,此处,暂时不考虑HandlerMapping接口实现类的问题。)
getHandler方法解释如下:
1、获取web请求的HttpServletRequest对象
2、循环调用getHandler方法
3、在方法中,根据获取到HttpServletRequest对象遍历handlerMappings,直到getHandler方法获取的返回值不为null。
getHandler具体代码如下:
  protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        for (HandlerMapping hm : this.handlerMappings) {
            if (logger.isTraceEnabled()) {
                logger.trace(
                        "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
            }
            HandlerExecutionChain handler = hm.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
        return null;
    }
获取的返回对象HandlerExecutionChain就是对问题1的答案。
HandlerExecutionChain对象包含一个handler对象和拦截器数组。Handler翻译意思是处理器,那就是说,Handler就是url请求的响应对象。
SpirngMVC的第一个扩展点,就出现在这里。我们可以编写任意的HandlerMapping实现类,依据任何策略来决定一个web请求到HandlerExecutionChain对象的生成。可以说,从第一个核心接口的声明开始,SpringMVC就把自己的灵活性和野心暴露无疑:哥玩的就是”Open-Closed“。

HandlerExecutionChain对象是什么?有什么?什么作用?看下面源代码就知道了。
package org.springframework.web.servlet;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.springframework.util.CollectionUtils;

public class HandlerExecutionChain {

    private final Object handler;

    private HandlerInterceptor[] interceptors;

    private List<HandlerInterceptor> interceptorList;

    public HandlerExecutionChain(Object handler) {
        this(handler, null);
    }

    public HandlerExecutionChain(Object handler, HandlerInterceptor[] interceptors) {
        if (handler instanceof HandlerExecutionChain) {
            HandlerExecutionChain originalChain = (HandlerExecutionChain) handler;
            this.handler = originalChain.getHandler();
            this.interceptorList = new ArrayList<HandlerInterceptor>();
            CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList);
            CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);
        }
        else {
            this.handler = handler;
            this.interceptors = interceptors;
        }
    }

    public Object getHandler() {
        return this.handler;
    }

    public void addInterceptor(HandlerInterceptor interceptor) {
        initInterceptorList();
        this.interceptorList.add(interceptor);
    }

    public void addInterceptors(HandlerInterceptor[] interceptors) {
        if (interceptors != null) {
            initInterceptorList();
            this.interceptorList.addAll(Arrays.asList(interceptors));
        }
    }

    private void initInterceptorList() {
        if (this.interceptorList == null) {
            this.interceptorList = new ArrayList<HandlerInterceptor>();
        }
        if (this.interceptors != null) {
            this.interceptorList.addAll(Arrays.asList(this.interceptors));
            this.interceptors = null;
        }
    }

    public HandlerInterceptor[] getInterceptors() {
        if (this.interceptors == null && this.interceptorList != null) {
            this.interceptors = this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);
        }
        return this.interceptors;
    }

    @Override
    public String toString() {
        if (this.handler == null) {
            return "HandlerExecutionChain with no handler";
        }
        StringBuilder sb = new StringBuilder();
        sb.append("HandlerExecutionChain with handler [").append(this.handler).append("]");
        if (!CollectionUtils.isEmpty(this.interceptorList)) {
            sb.append(" and ").append(this.interceptorList.size()).append(" interceptor");
            if (this.interceptorList.size() > 1) {
                sb.append("s");
            }
        }
        return sb.toString();
    }

}

通过上述可知道URL的处理对象,但是DispatcherServlet又是如何去调用该handler,让其处理用户的请求的呢?
SpringMVC中的另外一个核心接口类HandlerAdapter:
代码如下:
package org.springframework.web.servlet;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public interface HandlerAdapter {

    boolean supports(Object handler);

    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

    long getLastModified(HttpServletRequest request, Object handler);

}

DispatcherServlet会执行下面方法:
/**
* Return the HandlerAdapter for this handler object.
* @param handler the handler object to find an adapter for
* @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.
*/
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    for (HandlerAdapter ha : this.handlerAdapters) {
        if (logger.isTraceEnabled()) {
            logger.trace("Testing handler adapter [" + ha + "]");
        }
        if (ha.supports(handler)) {
            return ha;
        }
    }
    throw new ServletException("No adapter for handler [" + handler +
            "]: Does your handler implement a supported interface like Controller?");
}

这段代码已经很明显了,HandlerExecutionChain中的handler对象会被作为参数传递进去,在DispatcherServlet类中注册的HandlerAdapter实现类列表会被遍历,然后返回第一个supports方法返回true的HandlerAdapter对象,用这个HandlerAdapter实现类中的handle方法处理handler对象,并返回ModelAndView这个包含了视图和数据的对象。HandlerAdapter就是SpringMVC提供的第三个扩展点(第二个扩展点为拦截器),你可以提供自己的实现类来处理handler对象。
分享到:
评论

相关推荐

    SpringMVC入门很简单之URL映射规则

    这个过程就涉及到URL映射。 URL映射规则在SpringMVC中主要通过`@RequestMapping`注解来实现。这个注解可以应用在类级别或方法级别,提供了多种方式来定义URL路径。 1. 类级别的`@RequestMapping`:此注解应用于...

    Spring简单URL映射例子

    在Spring MVC框架中,URL映射是连接前端请求与后端处理逻辑的关键步骤。这个"Spring简单URL映射例子"展示了如何配置并使用URL映射来处理HTTP GET请求,同时展示如何获取并处理GET方式传递的参数。让我们深入探讨这个...

    CCF资格认证题库历年真题,URL映射

    URL 映射是诸如 Django、Ruby on Rails 等网页框架 (web frameworks) 的一个重要组件。对于从浏览器发来的 HTTP 请求,URL 映射模块会解析请求中的 URL 地址,并将其分派给相应的处理代码。现在,请你来实现一个简单...

    iOS的一个urlroute框架.zip

    这样,当遇到这样的URL时,框架会自动处理并跳转到相应的页面,极大地简化了代码。 其次,URLRoute支持自定义路由规则。开发者可以为每个URL模式定义处理函数或类,比如可以定义一个处理"myapp://news/article/:id...

    使用URL映射地址导航Web页面

    - 映射方式:例如,将`/products/{category}/{id}`映射到处理程序,其中`{category}`和`{id}`可能是动态参数。 3. **Web框架中的URL映射** - 在不同的Web开发框架中,如ASP.NET、Django、Spring MVC等,都有各自...

    url静态映射及回发处理

    通过在全局.asax文件中定义路由规则,我们可以将特定的URL模式映射到处理程序或控制器动作。例如,我们可能会设置一条规则,使得所有形如"/products/{category}/{product}"的请求都由ProductsController的...

    SSM框架使用Generator生成实体类,映射文件

    总的来说,通过SSM框架中的Generator工具,我们可以快速、高效地生成项目所需的实体类、DAO接口和Mapper映射文件,极大地提高了开发效率,降低了出错的可能性。同时,这也遵循了DRY(Don't Repeat Yourself)原则,...

    Django如何将URL映射到视图

    在Django中,URL映射到视图是整个框架处理Web请求的核心部分。URLconf(URL配置)是用于将URL与视图函数关联的机制。当用户请求一个页面时,Django会通过URLconf解析这个URL,从而找到对应的视图函数来处理这个请求...

    django中url映射规则和服务端响应顺序的实现

    在Django框架中,URL映射是非常重要的一个环节,它负责将用户的请求映射到相应的视图函数上。对于Django开发者而言,掌握URL映射规则能够帮助我们更高效地构建应用。 ##### 1.1 Django搜索路径 虽然这部分内容与...

    Django框架视图层URL映射与反向解析实例分析

    本文实例讲述了Django框架视图层URL映射与反向解析。分享给大家供大家参考,具体如下: Django视图层主要工作就是衔接HTTP请求、python程序、HTML模板。 URL分发(URL dispatcher)映射配置可以被看作Django项目的...

    Android-ActivityRouter路由框架通过注解实现URL打开Activity

    3. 配置URL映射:在初始化阶段设置URL和Activity的映射关系。 4. 处理URL请求:在App的入口或合适的地方捕获URL请求并交给框架处理。 通过对`joyrun-ActivityRouter-a0bcae3`这个压缩包文件的分析,我们可以了解到...

    ASP.NET实现URL映射的方法

    `&lt;add&gt;`元素则用于定义具体的URL映射规则,其中`url`属性表示原始URL,`mappedUrl`属性表示映射到的实际URL。 例如,如果原始主页是`Homepage.aspx`,但你想将其改为`OriginalHome.aspx`,可以这样配置: ```xml ...

    magic-api HTTP接口映射框架 v2.1.1.zip

    映射框架则是将这些接口与实际业务逻辑相连接的工具,它能够帮助开发者快速地构建和配置API,将请求路由到相应的处理函数,极大地提高了开发效率。 magic-api v2.1.1作为一个开源的HTTP接口映射框架,它的主要特性...

    Spring MVC 基于URL的映射规则(注解版)

    Spring MVC 基于URL的映射规则(注解版)是指在Spring MVC框架中,通过使用注解的方式来定义URL的映射规则。这篇文章将详细介绍了Spring MVC基于URL的映射规则(注解版),并提供了多种映射方式的示例。 首先,在...

    SSH框架和FreeMarker动态网页生成静态技术

    通过配置Struts2的XML文件,可以定义Action与URL的映射,实现请求转发。 Spring框架则扮演着容器的角色,它提供了依赖注入(DI)和面向切面编程(AOP)等功能。DI允许开发者在运行时通过配置文件或注解来注入对象...

    mybatis映射生成工具

    MyBatis映射生成工具是一种高效实用的开发辅助软件,主要功能是帮助开发者自动生成MyBatis框架下的DAO层、Bean类以及对应的XML映射文件。这个工具极大地提高了开发效率,减少了手动编写这些重复性代码的工作量。接...

    archive_ magic-api HTTP接口映射框架 v2.1.1 [江西新余电信].zip.zip

    这个框架看起来是用于帮助开发者将HTTP请求映射到特定的API功能,可能是一个Java或Python等编程语言中的库。由于标签为空,我们只能依据文件名和描述来推测其内容。 HTTP接口映射框架是开发Web服务时常用的工具,它...

    完整版 Java开发实训课程系列-SpringMVC框架技术教程 第2章 处理器映射器和适配器 (共22页).pptx

    这个映射器负责处理类和方法级别的`@RequestMapping`注解,将请求映射到相应的处理方法。 4. **注解开发步骤**: - 使用注解开发SpringMVC时,通常包括以下步骤: 1) 创建带有`@Controller`注解的类,定义处理...

Global site tag (gtag.js) - Google Analytics