spring HandlerMapping、HandlerExecutionChain 、HandlerAdapter的作用

转自:https://blog.csdn.net/wangjun5159/article/details/98849661

HandlerMapping
HandlerMapping是request与handler object之间的映射,它能根据request找到对应的handler。handler object总会被包装成HandlerExecutionChain ,HandlerExecutionChain 里含有handler object、interceptor等。
HandlerMapping接口仅有一个方法getHandler,从方法注释中得知,handler object可以是任意类型,甚至都不需要实现标签接口,这样的好处是允许使用其他框架的handler object。
注意,在getHandler时,会进行content-type、参数、url、method等要素匹配,如果找不到对应的handler object(通常是@controller、@requestmapping注解的方法,也就是HandlerMethod),则会出抛出异常,返回404、405之类的状态码。

/**
     * Return a handler and any interceptors for this request. The choice may be made
     * on request URL, session state, or any factor the implementing class chooses.
     * <p>The returned HandlerExecutionChain contains a handler Object, rather than
     * even a tag interface, so that handlers are not constrained in any way.
     * For example, a HandlerAdapter could be written to allow another framework's
     * handler objects to be used.
     * <p>Returns {@code null} if no match was found. This is not an error.
     * The DispatcherServlet will query all registered HandlerMapping beans to find
     * a match, and only decide there is an error if none can find a handler.
     * @param request current HTTP request
     * @return a HandlerExecutionChain instance containing handler object and
     * any interceptors, or {@code null} if no mapping found
     * @throws Exception if there is an internal error
     */
    HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
看一个HandlerMapping实例,<mvc:annotation-driven>标签注册RequestMappingHandlerMapping,它实现了HandlerMapping接口,此类中的lookupHandlerMethod方法负责寻找request对应的HandlerMethod。

/**
     * Look up the best-matching handler method for the current request.
     * If multiple matches are found, the best match is selected.
     * @param lookupPath mapping lookup path within the current servlet mapping
     * @param request the current request
     * @return the best-matching handler method, or {@code null} if no match
     * @see #handleMatch(Object, String, HttpServletRequest)
     * @see #handleNoMatch(Set, String, HttpServletRequest)
     */
    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
        List<Match> matches = new ArrayList<Match>();
        List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
        if (directPathMatches != null) {
            addMatchingMappings(directPathMatches, matches, request);
        }
        if (matches.isEmpty()) {
            // No choice but to go through all mappings...
            addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
        }

        if (!matches.isEmpty()) {
            // 省略
        }
        else {
            return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
        }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
HandlerExecutionChain
HandlerExecutionChain 是Handler执行链,包含handler Object、interceptor。所以HandlerExecutionChain 提供了getHandler、getInterceptors方法,配置文件中配置的interceptor都会加入到HandlerExecutionChain


实例
接下来看一下HandlerMapping、HandlerExecutionChain的实际应用,DispatcherServlet的doDispatch方法

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        
                HandlerExecutionChain mappedHandler = null;
                mappedHandler = getHandler(processedRequest);
                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    noHandlerFound(processedRequest, response);
                    return;
                }

                // Determine handler adapter for the current request.
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

                // Process last-modified header, if supported by the handler.
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (logger.isDebugEnabled()) {
                        logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                    }
                
                }

                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }

                // Actually invoke the handler.
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
大体流程是,根据request获取到HandlerExecutionChain ,根据HandlerExecutionChain 获取到handler,根据handler获取HandlerAdapter ,HandlerAdapter 判断文件是否被修改过,如果没修改过,直接返回。否则,HandlerExecutionChain 执行拦截器的prehandle方法,然后HandlerAdapter 执行实际处理。

HandlerAdapter
HandlerAdapter 是Handler适配器,负责具体的request处理,比如参数解析、返回值处理。

/**
     * Use the given handler to handle this request.
     * The workflow that is required may vary widely.
     * @param request current HTTP request
     * @param response current HTTP response
     * @param handler handler to use. This object must have previously been passed
     * to the {@code supports} method of this interface, which must have
     * returned {@code true}.
     * @throws Exception in case of errors
     * @return ModelAndView object with the name of the view and the required
     * model data, or {@code null} if the request has been handled directly
     */
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
1
2
3
4
5
6
7
8
9
10
11
12
13
总结
个人感觉,HandlerMapping、HandlerExecutionChain 、HandlerAdapter是spring mvc最重要的三个组件了

HandlerMapping
是request与handler object的映射,负责url、参数、content-type、method等匹配
HandlerExecutionChain
是handler执行链,它包装了handler obejct、interceptor,很典型的包装对象
HandlerAdapter
顾名思义,是handler的适配器,它能处理参数转换为handler能接受的数据类型,解析参数、处理返回值等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值