springmvc source code-call

The previous blog mainly recorded some notes when the handlerMapping was initialized, this one is mainly the study notes of the calling process

transfer

When a method is called, it will be called through HttpServlet, FrameworkServlet, etc., and will eventually be called

org.springframework.web.servlet.DispatcherServlet#doDispatch

Let’s start taking notes from this method.
Before we start, there are several concepts. Let’s summarize and explain. The last blog mentioned three ways to declare a controller. These three ways are different when they are called. The handlerMapping and handlerAdapter to handle

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

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

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

This is the processing class and method corresponding to the three ways of declaring the controller

Below is part of the code of 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());

I only intercepted part of the code in the doDispatch() method

handlerMapping

You can see here: mappedHandler = getHandler(processedRequest);
This method is to find out which handlerMapping the method corresponding to the current url is stored in according to the url of the request . If it is found, it will return the current handlerMapping.

What we usually say: Finding the corresponding handlerMapping through the URL is to find the corresponding handlerMapping from the map collection according to the url. When searching, it will traverse all the handlerMappings (spring's own + provided by the programmer), in which handlerMapping is found , Return which handlerMapping.
The different handlerMappings here are stored in different map collections; after this traversal, after finding the appropriate handlerMapping, the appropriate handlerMapping will be packaged into HandlerExecutionChain;

handlerAdapter

Finding a suitable handlerAdapter according to handlerMapping means: judging which handlerAdapter the current handler (handler can be simply understood as controller) needs to be processed;
the class that implements the Controller interface needs SimpleControllerHandlerAdapter to process, and in the SimpleControllerHandlerAdapter class, determine the condition Very simple: return handler instanceof Controller;

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

For HttpRequestHandlerAdapter, determine whether the current handler is of type HttpRequestHandler

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

For RequestMappingHandlerMapping

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

Extension points provided by springmvc

So here: Spring does a better job. Spring defines the handlerAdapter interface and declares them separately

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

This provides programmers with room for expansion. If programmers want to extend the handlerAdapter by themselves, they only need to provide the implementation class of the handlerAdapter, and tell spring about the classes they implement; the code of spring itself does not need to be modified, because it is judged When using which handlerAdapter, it will traverse all

Call target method

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

It is the entrance to actually call the target method.
When calling, if the method is declared through @Controller annotation and @RequestMapping, it is called through reflection mechanism.
If it is the controller declared through the remaining two methods, it is directly through the type
Forcibly, the ha.handler() method that calls the method of the implementation class actually calls the handler() method in the handlerAdapter implementation class

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);
}

The handler methods of these two handlerAdapters are relatively simple, they are directly forced to transfer, and then call the method in the corresponding implementation class

The more troublesome thing is the handler method of RequestMappingHandlerAdapter.
This involves taking parameter assignment from the request, and then using the reflection mechanism to call the method.invoke() method to complete the call. It
also involves the processing of the return value: Is it written out through the stream? Still perform view rendering, view forwarding, etc.; if the method is annotated with @ResponseBody, the return value will be written out in a stream; if not, the default is to render and return the view according to modelAndView; in
this processing method , I’m still looking at the logic of assigning values ​​to the parameters. After learning, I’ll add

Guess you like

Origin blog.csdn.net/CPLASF_/article/details/108976743