继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

SpringMVC源码学习

holdtom
关注TA
已关注
手记 1703
粉丝 240
获赞 991


1. SpringMVC重要组件

1. DispatcherServlet

SpringMVC的中央Servlet,所有请求的入口,重写了doService()方法。核心方法:doService()、doDispatch()。

2. HandlerMapping

处理器映射,负责根据HttpServletRequest找到对应的Handler,这里返回Handler的辅助类HandlerExecutionChain。

public interface HandlerMapping {

    @Nullable

    HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

}

3. HandlerExecutionChain

Handler execution chain, consisting of handler object and any handler interceptors.

处理器执行链,Handler辅助类,由Handler对象和一些HandlerInterceptor组成,主要功能为执行拦截器,核心属性和方法:

    private final Object handler;

    private HandlerInterceptor[] interceptors;

    // 一般情况下返回的是一个HandlerMethod对象

    Object getHandler()

    boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response)

    void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv)

4. HandlerMethod

Encapsulates information about a handler method consisting of a method and a bean. Provides convenient access to method parameters, the method return value, method annotations, etc.

保存了Controller Bean对象和对应的Method对象。

    // 对应的Controller实例

    private final Object bean;

    // 处理请求的方法

    private final Method method;

    // 方法的参数

    private final MethodParameter[] parameters;

5. HandlerInterceptor

拦截器,自定义拦截器实现此接口。preHandle()和postHandle()方法分别在实际的请求处理之前和之后执行。

public interface HandlerInterceptor {

    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)

            throws Exception {

        return true;

    }

    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,

            @Nullable ModelAndView modelAndView) throws Exception {

    }

    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,

            @Nullable Exception ex) throws Exception {

    }

}

6. HandlerAdapter

处理器适配器。handle()方法负责执行实际的请求处理并返回一个ModelAndView对象。

public interface HandlerAdapter {

    boolean supports(Object handler);

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

    long getLastModified(HttpServletRequest request, Object handler);

}

2. SpringMVC请求处理流程

DispatcherServlet作为入口且重写了doService()方法,所以请求会首先到doService()方法。下面步骤1、2、3在doService()方法完成,接着doService()方法调用doDispatch()方法,doDispatch()方法完成剩下的所有步骤。

WebApplicationContext对象绑定到Request,key为DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE。

locale resolver绑定到Request。

theme resolver绑定到Request。

如果是multipart request,包装成MultipartHttpServletRequest。

调用HandlerMapping的getHandler()方法获取对应的Handler,这里是HandlerExecutionChain对象。

调用HandlerExecutionChain的getHandler()方法,这里返回HandlerMethod对象,根据Handler获取HandlerAdapter。

如果是GET或者HEAD方法执行HandlerAdapter的getLastModified()方法。

调用HandlerExecutionChain的applyPreHandle()方法执行HandlerInterceptor的preHandle()方法。

调用HandlerAdapter的handle()方法执行实际的请求处理,实际执行HandlerMethod的对应方法,返回ModelAndView对象,

根据ModelAndView视图解析器找到对应的View。

渲染视图返回用户。

3. HandlerMethod收集

请求处理流程中的第5步中提到了HandlerMapping,这个核心第实现是RequestMappingHandlerMapping类,当使用SpringMVC时此类就会被注入到spring容器中,此类实现了InitializingBean接口,所以在实例化过程中会执行afterPropertiesSet()方法,此方法调用initHandlerMethods(),这个方法负责收集HandlerMethod,其相关源码如下:

    /**

     * Detects handler methods at initialization.

     * @see #initHandlerMethods

     */

    @Override

    public void afterPropertiesSet() {

        initHandlerMethods();

    }

    /**

     * Scan beans in the ApplicationContext, detect and register handler methods.

     * @see #getCandidateBeanNames()

     * @see #processCandidateBean

     * @see #handlerMethodsInitialized

     */

    protected void initHandlerMethods() {

        // 1. 遍历所有beanName

        for (String beanName : getCandidateBeanNames()) {

            if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {

                processCandidateBean(beanName);

            }

        }

        handlerMethodsInitialized(getHandlerMethods());

    }

    /**

     *  2. 判断beanName对应的Class是否为Controller

     */

    protected void processCandidateBean(String beanName) {

        Class<?> beanType = null;

        try {

            beanType = obtainApplicationContext().getType(beanName);

        }

        catch (Throwable ex) {

            // An unresolvable bean type, probably from a lazy bean - let's ignore it.

            if (logger.isTraceEnabled()) {

                logger.trace("Could not resolve type for bean '" + beanName + "'", ex);

            }

        }

        // 3. 判断逻辑为是否有@Controller或@RequestMapping注解

        if (beanType != null && isHandler(beanType)) {

            // 检测Controller类中的HandlerMethod

            detectHandlerMethods(beanName);

        }

    }

    @Override

    protected boolean isHandler(Class<?> beanType) {

        // 判断逻辑为是否有@Controller或@RequestMapping注解

        return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||

                AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));

    }

    protected void detectHandlerMethods(Object handler) {

        Class<?> handlerType = (handler instanceof String ?

                obtainApplicationContext().getType((String) handler) : handler.getClass());

        if (handlerType != null) {

            Class<?> userType = ClassUtils.getUserClass(handlerType);

            // 4. 检测到所有Method

            Map<Method, T> methods = MethodIntrospector.selectMethods(userType,

                    (MethodIntrospector.MetadataLookup<T>) method -> {

                        try {

                            return getMappingForMethod(method, userType);

                        }

                        catch (Throwable ex) {

                            throw new IllegalStateException("Invalid mapping on handler class [" +

                                    userType.getName() + "]: " + method, ex);

                        }

                    });

            if (logger.isTraceEnabled()) {

                logger.trace("Mapped " + methods.size() + " handler method(s) for " + userType + ": " + methods);

            }

            // 5. 对检测到到Method进行注册缓存。

            methods.forEach((method, mapping) -> {

                Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);

                // 这里把解析出到HanderMethod对象进行组册

                registerHandlerMethod(handler, invocableMethod, mapping);

            });

        }

    }

    protected void registerHandlerMethod(Object handler, Method method, T mapping) {

        // 6. 这里组册到MappingRegistry的对应的集合中缓存起来

        this.mappingRegistry.register(mapping, handler, method);

    }

相关类图: 

image

©著作权归作者所有:来自51CTO博客作者zhuwensheng的原创作品,如需转载,请注明出处,否则将追究法律责任


打开App,阅读手记
1人推荐
发表评论
随时随地看视频慕课网APP