• SpringMVC源码解读


    摘要:

    SimpleUrlHandlerMapping只是参与Handler的注册,请求映射时由AbstractUrlHandlerMapping搞定.

    初始化时,通过setMappings(Properties mappings)或者setUrlMap(Map<String, ?> urlMap)设置映射关系,然后通过WebApplicationObjectSupport的initApplicationContext调用registerHandlers进行注册.

    覆写initApplicationContext方法时,先调用父类实现,然后才调用registerHandlers进行注册.其中最终的注册registerHandler实现是由AbstractUrlHandlerMapping实现的.

    父类AbstractHandlerMapping继承了WebApplicationObjectSupport,所以SimpleUrlHandlerMapping可以通过覆写initApplicationContext注册Handler.

    注册Handler前,不忘靠AbstractHandlerMapping来初始化拦截器.

    // SimpleUrlHandlerMapping

    1     /**
    2      * Calls the {@link #registerHandlers} method in addition to the
    3      * superclass's initialization.
    4      */
    5     @Override
    6     public void initApplicationContext() throws BeansException {
    7         super.initApplicationContext();
    8         registerHandlers(this.urlMap);
    9     }

    initApplicationContext主要是进行拦截器的初始化.

      extendInterceptors是留给子类用的扩展接口,暂时没有使用

      detectMappedInterceptors是通过BeanFactoryUtils扫描应用下的全部MappedInterceptor类

      initInterceptors初始化特定的拦截器,检查MappedInterceptor,在需要时适配adaptor HandlerInterceptor

    // AbstractHandlerMapping

     1     /**
     2      * Initializes the interceptors.
     3      * @see #extendInterceptors(java.util.List)
     4      * @see #initInterceptors()
     5      */
     6     @Override
     7     protected void initApplicationContext() throws BeansException {
     8         extendInterceptors(this.interceptors);
     9         detectMappedInterceptors(this.mappedInterceptors);
    10         initInterceptors();
    11     }

    // AbstractHandlerMapping

     1     /**
     2      * Extension hook that subclasses can override to register additional interceptors,
     3      * given the configured interceptors (see {@link #setInterceptors}).
     4      * <p>Will be invoked before {@link #initInterceptors()} adapts the specified
     5      * interceptors into {@link HandlerInterceptor} instances.
     6      * <p>The default implementation is empty.
     7      * @param interceptors the configured interceptor List (never {@code null}),
     8      * allowing to add further interceptors before as well as after the existing
     9      * interceptors
    10      */
    11     protected void extendInterceptors(List<Object> interceptors) {
    12     }

    springmvc中经常使用BeanFactoryUtils扫描应用下的类来进行初始化.

    // AbstractHandlerMapping

     1     /**
     2      * Detects beans of type {@link MappedInterceptor} and adds them to the list of mapped interceptors.
     3      * This is done in addition to any {@link MappedInterceptor}s that may have been provided via
     4      * {@link #setInterceptors(Object[])}. Subclasses can override this method to change that.
     5      *
     6      * @param mappedInterceptors an empty list to add MappedInterceptor types to
     7      */
     8     protected void detectMappedInterceptors(List<MappedInterceptor> mappedInterceptors) {
     9         mappedInterceptors.addAll(
    10                 BeanFactoryUtils.beansOfTypeIncludingAncestors(
    11                         getApplicationContext(),MappedInterceptor.class, true, false).values());
    12     }

    // AbstractHandlerMapping

     1     /**
     2      * Initialize the specified interceptors, checking for {@link MappedInterceptor}s and adapting
     3      * HandlerInterceptors where necessary.
     4      * @see #setInterceptors
     5      * @see #adaptInterceptor
     6      */
     7     protected void initInterceptors() {
     8         if (!this.interceptors.isEmpty()) {
     9             for (int i = 0; i < this.interceptors.size(); i++) {
    10                 Object interceptor = this.interceptors.get(i);
    11                 if (interceptor == null) {
    12                     throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
    13                 }
    14                 if (interceptor instanceof MappedInterceptor) {
    15                     mappedInterceptors.add((MappedInterceptor) interceptor);
    16                 }
    17                 else {
    18                     adaptedInterceptors.add(adaptInterceptor(interceptor));
    19                 }
    20             }
    21         }
    22     }

    适配HandlerInterceptor和WebRequestHandlerInterceptorAdapter(什么是WebRequestHandlerInterceptorAdapter,晚点再说吧,具体看到时候拦截器部分的分析)

    // AbstractHandlerMapping

     1     /**
     2      * Adapt the given interceptor object to the HandlerInterceptor interface.
     3      * <p>Supported interceptor types are HandlerInterceptor and WebRequestInterceptor.
     4      * Each given WebRequestInterceptor will be wrapped in a WebRequestHandlerInterceptorAdapter.
     5      * Can be overridden in subclasses.
     6      * @param interceptor the specified interceptor object
     7      * @return the interceptor wrapped as HandlerInterceptor
     8      * @see org.springframework.web.servlet.HandlerInterceptor
     9      * @see org.springframework.web.context.request.WebRequestInterceptor
    10      * @see WebRequestHandlerInterceptorAdapter
    11      */
    12     protected HandlerInterceptor adaptInterceptor(Object interceptor) {
    13         if (interceptor instanceof HandlerInterceptor) {
    14             return (HandlerInterceptor) interceptor;
    15         }
    16         else if (interceptor instanceof WebRequestInterceptor) {
    17             return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor);
    18         }
    19         else {
    20             throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName());
    21         }
    22     }

    这才到SimpleUrlHandlerMapping干活的地方,迭代urlMap调用AbstractUrlHandlerMapping的registerHandler进行注册

    (保障url以"/"开头就不多说了)

    // SimpleUrlHandlerMapping

     1     /**
     2      * Register all handlers specified in the URL map for the corresponding paths.
     3      * @param urlMap Map with URL paths as keys and handler beans or bean names as values
     4      * @throws BeansException if a handler couldn't be registered
     5      * @throws IllegalStateException if there is a conflicting handler registered
     6      */
     7     protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
     8         if (urlMap.isEmpty()) {
     9             logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
    10         }
    11         else {
    12             for (Map.Entry<String, Object> entry : urlMap.entrySet()) {
    13                 String url = entry.getKey();
    14                 Object handler = entry.getValue();
    15                 // Prepend with slash if not already present.
    16                 if (!url.startsWith("/")) {
    17                     url = "/" + url;
    18                 }
    19                 // Remove whitespace from handler bean name.
    20                 if (handler instanceof String) {
    21                     handler = ((String) handler).trim();
    22                 }
    23                 registerHandler(url, handler);
    24             }
    25         }
    26     }

    // AbstractUrlHandlerMapping

     1 /**
     2      * Register the specified handler for the given URL path.
     3      * @param urlPath the URL the bean should be mapped to
     4      * @param handler the handler instance or handler bean name String
     5      * (a bean name will automatically be resolved into the corresponding handler bean)
     6      * @throws BeansException if the handler couldn't be registered
     7      * @throws IllegalStateException if there is a conflicting handler registered
     8      */
     9     protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
    10         Assert.notNull(urlPath, "URL path must not be null");
    11         Assert.notNull(handler, "Handler object must not be null");
    12         Object resolvedHandler = handler;
    13 
    14         // Eagerly resolve handler if referencing singleton via name.不是单例同时不是懒加载
    15         if (!this.lazyInitHandlers && handler instanceof String) {
    16             String handlerName = (String) handler;
    17             if (getApplicationContext().isSingleton(handlerName)) {
    18                 resolvedHandler = getApplicationContext().getBean(handlerName);
    19             }
    20         }
    21 
    22         Object mappedHandler = this.handlerMap.get(urlPath);// 获取之前已经匹配的Handler
    23         if (mappedHandler != null) {
    24             if (mappedHandler != resolvedHandler) {// 如果新匹配得到的跟之前已解析到的handler不一致,则抛异常
    25                 throw new IllegalStateException(
    26                         "Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
    27                         "]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
    28             }
    29         }
    30         else {
    31             if (urlPath.equals("/")) {// 设置rootHandler
    32                 if (logger.isInfoEnabled()) {
    33                     logger.info("Root mapping to " + getHandlerDescription(handler));
    34                 }
    35                 setRootHandler(resolvedHandler);
    36             }
    37             else if (urlPath.equals("/*")) {// 设置默认的defaultHandler
    38                 if (logger.isInfoEnabled()) {
    39                     logger.info("Default mapping to " + getHandlerDescription(handler));
    40                 }
    41                 setDefaultHandler(resolvedHandler);
    42             }
    43             else {// 最后才是普通handler的设置
    44                 this.handlerMap.put(urlPath, resolvedHandler);
    45                 if (logger.isInfoEnabled()) {
    46                     logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));
    47                 }
    48             }
    49         }
    50     }
  • 相关阅读:
    git rebase学习
    git rebase 通俗易懂!
    fatal: Refusing to fetch into current branch refs/heads/ReqMerge_26 of non-bare repository
    跨越千年的RSA算法
    CodeForces 734E-Anton and Tree(并查集缩点+树的直径)
    程序员的笑话
    智慧煤矿:新基建加速智能化布局,AI助力煤炭产业转型升级
    EasyScreenLive推流组件推RTSP流到EasyDarwin操作过程分享
    EasyCVRpython调接口报错cannot unmarshal array into Go value of type main
    使用ninja -C out/Release指令编译安卓Webrtc的SDK报错找不到android ndk处理方式
  • 原文地址:https://www.cnblogs.com/leftthen/p/5207787.html
Copyright © 2020-2023  润新知