栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springmvc源码笔记-RequestMappingHandlerMapping

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springmvc源码笔记-RequestMappingHandlerMapping

下图是springmvc的执行流程

图片来源:https://www.jianshu.com/p/8a20c547e245


DispatcherServlet根据url定位到Controller和方法,依赖的是HandlerMapping接口的各个实现类,其中,RequestMappingHandlerMapping是专门用来处理注解方式的Controller的

下面,我们分RequestMappingHandlerMapping的加载以及RequestMappingHandlerMapping如何根据url定位Controller两部分来讲

RequestMappingHandlerMapping加载过程
  1. RMHP在系统启动时会被注册成bean,见《springmvc源码笔记-HandlerMapping注入》

  2. 因为RMHP实现了InitializingBean接口,在bean加载完成后会自动调用afterPropertiesSet方法,在此方法中调用了AbstractHandlerMethodMapping#initHandlerMethods()来实现初始化

    protected void initHandlerMethods() {
    	// 遍历所有的bean
    	for (String beanName : getCandidateBeanNames()) {
    		if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
    			processCandidateBean(beanName);
    		}
    	}
    	handlerMethodsInitialized(getHandlerMethods());
    }
    
    protected void processCandidateBean(String beanName) {
    	Class beanType = null;
    	try {
    		beanType = obtainApplicationContext().getType(beanName);
    	}
    	......
    	// isHandler判断类是否有Controller或者RequestMapping注解
    	if (beanType != null && isHandler(beanType)) {
    		detectHandlerMethods(beanName);
    	}
    }
    
    protected void detectHandlerMethods(Object handler) {
    	......
    	if (handlerType != null) {
    		Class userType = ClassUtils.getUserClass(handlerType);
    		// 遍历类的所有方法
    		Map methods = MethodIntrospector.selectMethods(userType,
    				(MethodIntrospector.MetadataLookup) method -> {
    					try {
    						// 获取方法上的映射(会读取方法上的RequestMapping注解获取url)
    						return getMappingForMethod(method, userType);
    					}
    					catch (Throwable ex) {
    						throw new IllegalStateException("Invalid mapping on handler class [" +
    								userType.getName() + "]: " + method, ex);
    					}
    				});
    		......
    		methods.forEach((method, mapping) -> {
    			Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
    			// 将映射关系放入AbstractHandlerMethodMapping.mappingRegistry中
    			registerHandlerMethod(handler, invocableMethod, mapping);
    		});
    	}
    }
    
RequestMappingHandlerMapping解析过程
  1. DispatcherServlet继承HttpServlet,所以执行链是FrameworkServlet#doGet→DispatcherServlet#doService→DispatcherServlet#doDispatch→DispatcherServlet#getHandler

    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    	if (this.handlerMappings != null) {
    		// handlerMappings已在onRefresh方法中初始化
    		for (HandlerMapping mapping : this.handlerMappings) {
    			// 第一个mapping就是RequestMappingHandlerMapping
    			// 获取处理程序,也就是url对应的controller和method
    			HandlerExecutionChain handler = mapping.getHandler(request);
    			if (handler != null) {
    				return handler;
    			}
    		}
    	}
    	return null;
    }
    
    // AbstractHandlerMapping#getHandler->RequestMappingHandlerMapping#getHandlerInternal->AbstractHandlerMapping#lookupHandlerMethod
    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
    	// lookupPath就是请求路径
    	List matches = new ArrayList<>();
    	// 获取url路径匹配项
    	List directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
    	if (directPathMatches != null) {
    		// 添加映射匹配集合
    		addMatchingMappings(directPathMatches, matches, request);
    	}
    	if (matches.isEmpty()) {
    		addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);
    	}
    	if (!matches.isEmpty()) {
    		......
    		// 至此,根据url获取到controller和method
    		return bestMatch.getHandlerMethod();
    	} else {
    		return handleNoMatch(this.mappingRegistry.getRegistrations().keySet(), lookupPath, request);
    	}
    }
    
    private void addMatchingMappings(Collection mappings, List matches, HttpServletRequest request) {
    	for (T mapping : mappings) {
    		T match = getMatchingMapping(mapping, request);
    		if (match != null) {
    			// this.mappingRegistry.getRegistrations().get(mapping)就是获取HandlerMethodMapping
    			// HandlerMethodMapping保存controller和method信息的类
    			matches.add(new Match(match, this.mappingRegistry.getRegistrations().get(mapping)));
    		}
    	}
    }
    
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/889298.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号