`

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对象。
分享到:
评论

相关推荐

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

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

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

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

    url-mapper:获取URL并映射到函数,解析参数

    它允许您外包处理url(映射,解析,字符串化),并专注于整理与您喜欢的框架相关的内容。 例子 import React from 'react' import ReactDOM from 'react-dom' import Mapper from 'url-mapper' import { CoreApp , ...

    详解NodeJS框架express的路径映射(路由)功能及控制

    我 们知道Express是一个基于NodeJS的非常优秀的服务端开发框架,本篇CSSer将提供express框架的route和route control章节,route实现了客户端请求的URL的路径映射功能,暂且译为路由或URL映射吧。如果你还是不太理解...

    rose框架知识介绍

    rose框架入门所需掌握的知识点,包括拦截器,错误处理等等

    基于SSM框架图书信息管理系统 | 毕业设计

    2 本项目springMVC框架采用了注解映射器,使用了RESTful风格的url对系统发起http请求,开发更灵活。 3 同时使用了了hibernate提供的校验框架,对客户端数据进行校验! 4 Mybati数据库DAO层采用的是Mapper代理开发方法...

    [其他类别]简易数据库关系映射框架EasyDBOv0.1.0测试版_easydbo010.zip

    SpringMVC负责处理请求和响应,可以实现灵活的URL映射和请求处理。MyBatis或Hibernate可以简化数据库操作,提供了方便的ORM(对象关系映射)功能,使得数据的持久化变得简单和高效。 通过以上技术选择和框架搭建,该...

    基于SSM框架(SpringMVC + Spring + Mybatis)的图书管理系统,内附,教程,数据库脚本

    2 本项目springMVC框架采用了注解映射器,使用了RESTful风格的url对系统发起http请求,开发更灵活。 3 同时使用了了hibernate提供的校验框架,对客户端数据进行校验! 4 Mybati数据库DAO层采用的是Mapper代理开发方法...

    SSM框架的图书管理系统(新增登录注册下载功能)

    2 本项目springMVC框架采用了注解映射器,使用了RESTful风格的url对系统发起http请求,开发更灵活。 3 同时使用了了hibernate提供的校验框架,对客户端数据进行校验! 4 Mybati数据库DAO层采用的是Mapper代理开发方法...

    PYTHON之Django Web框架源码下载

    Django框架是Python编程语言驱动的一个开源...4、灵活的URL映射。Django提供一个基于正则表达式的URL分发器,开发者可灵活地编写URL。 5、丰富的模板语言。 Django模板语言功能丰富,支持自定义模板标签。Django也支持

    Python框架之DjangoWeb框架讲解

    - 用于创建模型的对象关系映射; - 为最终用户设计较好的管理界面; - URL 设计; - 设计者友好的模板语言; - 缓存系统。 Django已经成为web开发者的首选框架,是一个遵循 MVC 设计模式的框架。MVC是Model、View、...

    基于SSM框架(SpringMVC + Spring + Mybatis)的图书管理系统数据库.rar

    2 本项目springMVC框架采用了注解映射器,使用了RESTful风格的url对系统发起http请求,开发更灵活。 3 同时使用了了hibernate提供的校验框架,对客户端数据进行校验! 4 Mybati数据库DAO层采用的是Mapper代理开发...

    基于SSM框架信息管理系统.zip

    2 本项目springMVC框架采用了注解映射器,使用了RESTful风格的url对系统发起http请求,开发更灵活。 3 同时使用了了hibernate提供的校验框架,对客户端数据进行校验! 4 Mybati数据库DAO层采用的是Mapper代理开发方法...

    后盾网HDPHP框架 2014.12.zip

    集成前端常用库(编辑器、文件上传、图片缩放等等)* 对象关系映射(ORM)* 与后盾网hdjs完美整合安全性:框架在系统层面提供了众多的安全特性,确保你的网站和产品安全无忧。这些特性包括:* COOKIE加密处理* 数据...

    Flask框架URL管理操作示例【基于@app.route】

    本文实例讲述了Flask框架URL...尖括号的内容是动态的,凡是匹配到的/item/前缀的URL都会被映射到这个路由上,在内部把id作为参数而获得。它使用了特殊的字段标记,默认类型是字符串。如果需要制定参数类型需要标记成这

    回答PHPCHINA上的几个问题:URL映射

    1、大家来说说URL映射吧 一般url映射有两种方式,一种是通过mod_rewrite实现,这种网上教材很多我也不多说了。另外一种是在程序中模拟,比如类似zend Framework中的那种方式/index....

    rural:基于spring的mvc框架,使用简单,URL映射零配置零注解

     Rural是一个基于spring的mvc框架,设计上类似spring mvc,相比于spring mvc,Rural使用更简便,无需配置和注解就可以实现URL到java方法的映射。 取名Rural(乡村风味的,田园的)寓意简洁。  目前Rural支持json,...

    双鱼林SSM_EasyUI框架公司员工管理系统 v1.0.rar

    2 本项目springMVC框架采用了注解映射器,使用了RESTful风格的url对系统发起http请求,开发更灵活。 3 同时使用了了hibernate提供的校验框架,对客户端数据进行校验! 4 Mybati数据库DAO层采用的是Mapper代理开发...

    springmvc-RequestMapping:根据映射的 URL 定位具有 @RequestMapping 注释的整个类或特定处理程序方法

    springmvc-RequestMapping 根据映射的 URL 定位具有 @RequestMapping 注释的整个类或特定处理程序方法目的 : 大多数时候,当我们不熟悉基于 spring 框架的 Web 应用程序时,我们只有一种选择来定位 Controller 类或...

Global site tag (gtag.js) - Google Analytics