springmvc源码-调用

上篇博客主要记录了handlerMapping初始化时的一些笔记,这篇主要是调用过程的学习笔记

调用

在调用一个方法的时候,会通过HttpServlet、FrameworkServlet等进行调用,最终会调用到

org.springframework.web.servlet.DispatcherServlet#doDispatch

我们就从这个方法开始记录笔记
在开始之前,有几个概念,先总结说明一下,上篇博客有说到过,声明一个controller的三种方式,这三种方式在调用的时候,是由不同的handlerMapping和handlerAdapter来处理的

实现Controller接口
      通过BeanNameUrlHandlerMapping来处理
      通过SimpleControllerHandlerAdapter来处理
      通过SimpleControllerHandlerAdapter类中的方法来调用实现接口的目标类的方法

实现HttpRequestHandler接口
      通过BeanNameurlHandlerMapping来处理
      通过HttpRequestHandlerAdapter来处理
      通过HttpRequestHandlerAdapter调用实现接口类的目标方法

通过@Componenet注解
      通过RequestMappingHandlerMapping来处理
      通过RequestMappingHandlerAdappter来处理
      通过反射的方式来调用目标方法(org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#handleInternal)

这是三种声明controller的方式对应的处理类和方式

下面是doDispatch()的部分代码

// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null) {
    
    
	noHandlerFound(processedRequest, response);
	return;
}

// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = "GET".equals(method);
if (isGet || "HEAD".equals(method)) {
    
    
	long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
	if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
    
    
		return;
	}
}

if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    
    
	return;
}
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

我只截取了doDispatch()方法中的部分代码

handlerMapping

这里可以看到:mappedHandler = getHandler(processedRequest);
这个方法是根据request的url找到当前url对应的method是在哪个handlerMapping中存储的,找到了,就返回当前handlerMapping

我们通常所说的:通过url找到对应的handlerMapping就是根据url从map集合中找对应的handlerMapping,在查找的时候,会遍历所有的handlerMapping(spring自己的+程序员提供的),在哪个handlerMapping找到了,就返回哪个handlerMapping
这里不同的handlerMapping,是放在不同的map集合中存储的;在这个遍历之后,找到合适的handlerMapping之后,会将合适的handlerMapping包装成HandlerExecutionChain;

handlerAdapter

根据handlerMapping找合适的handlerAdapter,是指:判断当前的handler(handler我觉得可以简单理解为controller)需要用哪个handlerAdapter来处理;
实现Controller接口的类,需要SimpleControllerHandlerAdapter来处理,在SimpleControllerHandlerAdapter该类中,判断条件很简单:return handler instanceof Controller;

org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter#supports
@Override
public boolean supports(Object handler) {
	return (handler instanceof HttpRequestHandler);
}

对于HttpRequestHandlerAdapter来说,判断当前handler是否是HttpRequestHandler类型的

@Override
public boolean supports(Object handler) {
    
    
	return (handler instanceof HttpRequestHandler);
}

对于RequestMappingHandlerMapping来说

// 只有这里的handler是handlerMethod的实例,就可以了,后面的supportsInternal默认是返回true的
@Override
public final boolean supports(Object handler) {
    
    
	return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}

springmvc提供的扩展点

所以这里:spring做的比较好,spring定义了handlerAdapter接口,分别声明了

// 这个方法是判断当前handlerAdapter是否支持handler的处理
boolean supports(Object handler); 
//具体处理handler的方法
ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;  

这样就给程序员提供了扩展的空间,程序员如果要自己扩展handlerAdapter,那只需要提供handlerAdapter的实现类即可,并且将自己实现的类告诉spring;spring本身的代码无需做改造,因为在判断使用哪个handlerAdapter的时候,会遍历所有的

调用目标方法

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

是真正来调用目标方法的入口
在调用的时候,如果是通过@Controller注解和@RequestMapping来声明的方法,是通过反射机制来调用的
如果是通过剩下两种方式声明的controller,是直接通过类型强转,调用实现类的方法的
ha.handler()方法其实调用的,就是handlerAdapter实现类中的handler()方法

org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter#handle

@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
		throws Exception {
    
    

	((HttpRequestHandler) handler).handleRequest(request, response);
	return null;
}
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter#handle

@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
		throws Exception {
    
    

	return ((Controller) handler).handleRequest(request, response);
}

这两个handlerAdapter的handler方法比较简单,都是直接进行了强转,然后调用相应的实现类中的方法

比较麻烦的是RequestMappingHandlerAdapter的handler方法
这里涉及到从request中取参数赋值,然后通过反射机制,调用method.invoke()方法完成调用
并且还会涉及到对返回值的处理:是通过流写出去?还是进行视图渲染、视图转发等;如果方法加了@ResponseBody注解,就会把返回值通过流的方式写出去;如果没有,那默认是按照modelAndView来进行视图的渲染和返回;
这种处理方式中,给参数赋值的这块逻辑我还在看,待学习之后,补充

猜你喜欢

转载自blog.csdn.net/CPLASF_/article/details/108976743