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对象。

猜你喜欢

转载自wmhbjb.iteye.com/blog/2209229