AbstractControllerUrlHandlerMapping类详解 - HandlerMapping系列四

AbstractControllerUrlHandlerMapping是将实现了Controller接口或者注释了@Controller的bean作为Handler,并且可以通过设置excludedClasses和excludedPackages将不包含的bean或者不包含的包下的所有bean排除在外。

determineUrlsForHandler() 获取bean并完成beanName和beanClass的对应关系

@Override  
protected String[] determineUrlsForHandler(String beanName) {  
    Class beanClass = getApplicationContext().getType(beanName);  
    //判断是不是支持的类型  
    if (isEligibleForMapping(beanName, beanClass)) {  
        //模板方法,在子类实现  
        return buildUrlsForHandler(beanName, beanClass);  
    }  
    else {  
        return null;  
    }  
}

setIncludeAnnotatedControllers()  配置操作

public void setIncludeAnnotatedControllers(boolean includeAnnotatedControllers) {  
	this.predicate = (includeAnnotatedControllers ?  new AnnotationControllerTypePredicate() : new ControllerTypePredicate());  
}  
  
public void setExcludedPackages(String... excludedPackages) {  
	this.excludedPackages = (excludedPackages != null) ?  new HashSet(Arrays.asList(excludedPackages)) : new HashSet();  
}  

public void setExcludedClasses(Class... excludedClasses) {  
	this.excludedClasses = (excludedClasses != null) ?  new HashSet>(Arrays.asList(excludedClasses)) : new HashSet>();  
}

AbstractControllerUrlHandlerMapping提供了一些配置,用于排除掉一些包或者一些类,可以在配置中进行配置。

AbstractControllerUrlHandlerMapping源码

public abstract class AbstractControllerUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping  {  
    // 通过控制器接口类型或者控制器注解类型查找简单控制器和注解控制器的实用类  
    private ControllerTypePredicate predicate = new AnnotationControllerTypePredicate();  
  
    // 声明的包中的控制器不会作为处理器进行注册  
    private SetexcludedPackages = Collections.singleton("org.springframework.web.servlet.mvc");  
  
    // 声明的类不会作为处理器进行注册  
    private SetexcludedClasses = Collections.emptySet();  
  
    // 实现根据Bean映射出URL的逻辑  
    @Override  
    protected String[] determineUrlsForHandler(String beanName) {  
        // 取得Bean的类型  
        Class beanClass = getApplicationContext().getType(beanName);  
          
        // 判断是否Bean可以作为控制器处理器  
        if (isEligibleForMapping(beanName, beanClass)) {  
            // 根据Bean名字或者类型名映射出URL的逻辑  
            return buildUrlsForHandler(beanName, beanClass);  
        }  
        else {  
            return null;  
        }  
    }  
    //判断beanName和beanClass是否已经配置排除对应关系
    protected boolean isEligibleForMapping(String beanName, Class beanClass) {  
        // 如果Bean类型是空,则不映射此Bean  
        if (beanClass == null) {  
            if (logger.isDebugEnabled()) {  
                logger.debug("Excluding controller bean '" + beanName + "' from class name mapping " +  
                        "because its bean type could not be determined");  
            }  
            return false;  
        }  
          
        // 如果Bean的包配置为排除包,则不映射此Bean  
        if (this.excludedClasses.contains(beanClass)) {  
            if (logger.isDebugEnabled()) {  
                logger.debug("Excluding controller bean '" + beanName + "' from class name mapping " +  
                        "because its bean class is explicitly excluded: " + beanClass.getName());  
            }  
            return false;  
        }  
          
        // 如果Bean的包配置为排除类,则不映射此Bean  
        String beanClassName = beanClass.getName();  
        for (String packageName : this.excludedPackages) {  
            if (beanClassName.startsWith(packageName)) {  
                if (logger.isDebugEnabled()) {  
                    logger.debug("Excluding controller bean '" + beanName + "' from class name mapping " +  
                            "because its bean class is defined in an excluded package: " + beanClass.getName());  
                }  
                return false;  
            }  
        }  
          
        // 必须是控制器类型,才映射作为控制器处理器  
        return isControllerType(beanClass);  
    }  
    protected boolean isControllerType(Class beanClass) {  
        return this.predicate.isControllerType(beanClass);  
    }  
    protected boolean isMultiActionControllerType(Class beanClass) {  
        return this.predicate.isMultiActionControllerType(beanClass);  
    }  
    // 子类可以选择根据Bean名字还是根据Bean类来映射URL Pattern  
    protected abstract String[] buildUrlsForHandler(String beanName, Class beanClass);  
  
} 

总结

1. AbstractControllerUrlHandlerMapping是抽象探测URL处理器映射的另外一个实现,这个实现也是一个抽象的实现,它是通过在Bean环境中找到合适的控制器类型,根据一定的规则将控制器类型映射到一个或者多个URL Pattern来实现的。

2. AbstractControllerUrlHandlerMapping的实现机制就是根据beanName从容器中获取实现类beanClass,同时beanName和beanClass的对应关系的操作是在其子类中完成实现的,同时AbstractControllerUrlHandlerMapping提供了一些配置用于排除一些类的关系。

版权声明:本文为JAVASCHOOL原创文章,未经本站允许不得转载。