springmvc源码

分两个步骤解析springmvc

一,spring初始化

spring初始化的时候,把url和方法的映射,注册到urlLookup (LinkedMultiValueMap类型) 中

Web容器启动的时候,同时会启动Spring的IOC容器,RequestMappingHandlerMapping Bean也会随着IOC容器而实例化。RequestMappingHandlerMapping这个class覆盖了afterPropertiesSet方法。其超类AbstractHandlerMethodMapping的afterPropertiesSet方法代码如下:

@Override
	public void afterPropertiesSet() {
		initHandlerMethods();
	}

再看initHandlerMethods方法:

	protected void initHandlerMethods() {
		for (String beanName : getCandidateBeanNames()) {// //获取IOC容器中所有Bean的名称(我们这里只讲用注解定义的bean)
			if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
				processCandidateBean(beanName);//主要逻辑
			}
		}
		handlerMethodsInitialized(getHandlerMethods());
	}

再看processCandidateBean中代码实现:

protected void processCandidateBean(String beanName) {
		。。。
		if (beanType != null && isHandler(beanType)) {
			detectHandlerMethods(beanName);//主要逻辑
		}
	}

detectHandlerMethods是核心方法。主要功能是组装bean,并注册到handlermethod集合中

protected void detectHandlerMethods(Object handler) {
		Class<?> handlerType = (handler instanceof String ?
				obtainApplicationContext().getType((String) handler) : handler.getClass());

		if (handlerType != null) {
			Class<?> userType = ClassUtils.getUserClass(handlerType);
			Map<Method, T> methods = MethodIntrospector.selectMethods(userType,
					(MethodIntrospector.MetadataLookup<T>) method -> {
						try {
							return getMappingForMethod(method, userType);//获取并组装meathod,例如get /activitiHistory/getInstancesByUserName 
						}
						catch (Throwable ex) {
							throw new IllegalStateException("Invalid mapping on handler class [" +
									userType.getName() + "]: " + method, ex);
						}
					});
			if (logger.isTraceEnabled()) {
				logger.trace(formatMappings(userType, methods));
			}
			methods.forEach((method, mapping) -> {
				Method invocableMethod = AopUtils.selectInvocableMethod(method, userType);
				registerHandlerMethod(handler, invocableMethod, mapping);//注册到handlermethod集合中
			});
		}
	}

再看registerHandlerMethod中代码实现:

protected void registerHandlerMethod(Object handler, Method method, T mapping) {
		this.mappingRegistry.register(mapping, handler, method);
	}

调用注册方法,注册到一个LinkedMultiValueMap集合中,并设置成 类MappingRegistry的属性

	 
 public void register(T mapping, Object handler, Method method) {
	 。。。
				for (String url : directUrls) {
					this.urlLookup.add(url, mapping);//放入集合
				}
     。。。

				this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directUrls, name));//设置到MappingRegistry的属性中
		}

二,用户请求调用

用户请求调用的时候,拿着url去urlLookup中获取要调用的方法实例
1,请求首先调用dispatcherservlet的doservice

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
	。。。
		try {
			doDispatch(request, response);
		}
	。。。
	}

下面是关键方法 doDispatch(request, response);

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	。。。
		try { 
			。。。 
				mappedHandler = getHandler(processedRequest);//获取handler
				 。。。
				 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
			。。。
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}
 
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());//执行handler

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}

				applyDefaultViewName(processedRequest, mv);
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			。。。。
		}
	}

首先 getHandler(processedRequest);是获取handler,进去看下

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			for (HandlerMapping mapping : this.handlerMappings) {
				HandlerExecutionChain handler = mapping.getHandler(request);//这里
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
	}

再看 mapping.getHandler(request);

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		Object handler = getHandlerInternal(request);
	。。。
		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);//获取拦截器链
	。。。
		return executionChain;
	}

再看Object handler = getHandlerInternal(request);
	protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
		String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
		request.setAttribute(LOOKUP_PATH, lookupPath);
		this.mappingRegistry.acquireReadLock();
		try {
			HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);//这里
			return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
		}
		finally {
			this.mappingRegistry.releaseReadLock();
		}
	}

再跟进 lookupHandlerMethod(lookupPath, request);可以看到这里的mappingRegistry就是第一步初始化时候,带有urlLookup属性的类

protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
		List<Match> matches = new ArrayList<>();
		List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);   //注意在这里的mappingRegistry
	。。。
	}

接下来就一目了然了

public List<T> getMappingsByUrl(String urlPath) {
			return this.urlLookup.get(urlPath);
		}

2,接下来就是执行handler和拦截器相关的代码

上面getHandler的方法中,获取handler同时获取了拦截器链

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		Object handler = getHandlerInternal(request);
	。。。
		HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);//获取拦截器链
	。。。
		return executionChain;
	}

看getHandlerExecutionChain,该方法获取了自定义的HandlerInterceptor,添加到拦截器链中。(业务handler和自定义拦截器都在HandlerExecutionChain这个对象中)

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
		HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
				(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

		String lookupPath = this.urlPathHelper.getLookupPathForRequest(request, LOOKUP_PATH);
		for (HandlerInterceptor interceptor : this.adaptedInterceptors) { //this.adaptedInterceptors:自定义的HandlerInterceptor
			if (interceptor instanceof MappedInterceptor) {
				MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
				if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
					chain.addInterceptor(mappedInterceptor.getInterceptor());//添加到拦截器链中
				}
			}
			else {
				chain.addInterceptor(interceptor);
			}
		}
		return chain;
	}

然后回到doDispatch方法中,下面对这个方法中的流程分析:
获取到HandlerExecutionChain类型对象mappedHandler 后,
先调用已注册HandlerInterceptor的preHandle()方法
再获取处理Handler的适配器
再真正执行handler(即Controller)对应的方法
后调用已注册HandlerInterceptor的postHandle()方法

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    	。。。
		try { 
			。。。 
				mappedHandler = getHandler(processedRequest);//获取handler
				 。。。
				 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());//获取适配器
			。。。
				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
				//调用已注册HandlerInterceptor的preHandle()方法
					return;
				}
 
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());//执行handler

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}

				applyDefaultViewName(processedRequest, mv);
				mappedHandler.applyPostHandle(processedRequest, response, mv);
				 //调用已注册HandlerInterceptor的postHandle()方法
			}
			。。。。
		}
	}

我们先看 getHandlerAdapter(mappedHandler.getHandler());选出该handler的处理适配器,
这里的 this.handlerAdapters是从DispatcherServlet.properties读出来的,主要有这几种

  1. AnnotationMethodHandlerAdapter主要是适配注解类处理器,注解类处理器就是我们经常使用的@Controller的这类处理器
    2. HttpRequestHandlerAdapter主要是适配静态资源处理器,静态资源处理器就是实现了HttpRequestHandler接口的处理器,这类处理器的作用是处理通过SpringMVC来访问的静态资源的请求。
    3.SimpleControllerHandlerAdapter是Controller处理适配器,适配实现了Controller接口或Controller接口子类的处理器,比如我们经常自己写的Controller来继承MultiActionController.
    4.SimpleServletHandlerAdapter是Servlet处理适配器,适配实现了Servlet接口或Servlet的子类的处理器,我们不仅可以在web.xml里面配置Servlet,其实也可以用SpringMVC来配置Servlet,不过这个适配器很少用到,而且SpringMVC默认的适配器没有他,默认的是前面的三种。
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter adapter : this.handlerAdapters) {
				if (adapter.supports(handler)) {
					return adapter;
				}
			}
		} 
	}

再看doDispatch 的 ha.handle(processedRequest, response, mappedHandler.getHandler());
真正执行业务
跟进去

public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		return ((Controller) handler).handleRequest(request, response);
	}

跟((Controller) handler).handleRequest(request, response);

public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
	。 。。 
		if (this.synchronizeOnSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				Object mutex = WebUtils.getSessionMutex(session);
				synchronized (mutex) {
					return handleRequestInternal(request, response);//执行
				}
			}
		}
		return handleRequestInternal(request, response);
	}

跟handleRequestInternal(request, response);最后执行返回视图

protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
			throws Exception {
       。。。
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.addAllObjects(RequestContextUtils.getInputFlashMap(request));//执行业务
		if (viewName != null) {
			modelAndView.setViewName(viewName);
		}
		else {
			modelAndView.setView(getView());
		}
		return modelAndView;//返回视图
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值