SpringMVC source code analysis------HandlerAdapter adapter

The project address
SpringMVC_04
thinks the blogger can also give a Star

Adapter mode
converts the interface of a class into another interface that the customer wants. The Adapter mode allows those classes that cannot work together because of incompatible interfaces to work together.

HandlerAdapter analysis
We have learned the definition of the adapter pattern, now let's take a look at HandlerAdapter. HandlerAdapter has been used in the doDispatch() method of our DispatcherServlet, so why use this adapter? When we wrote the SpringMVC logic process by hand, we did not use the adapter, but we still achieved our goal. After we understand the adapter mode, we can find that he finally put the originally incompatible interfaces together for use. This is why it is used in this way. Let's look at the source code first.
Debug walked up. When you get to this position, it is in the doDispatch() method to get the adapter.
Insert picture description hereWe will see that there are three adapters, these three adapters are the initial injection. Let's take a look at these adapters originally injected by the implementation class of HandlerAdapter, among which RequestMappingHandlerAdapter is because it inherits AbstractHandlerMethodAdapter, so we have to look at AbstractHandlerMethodAdapter

HttpRequestHandlerAdapter
Insert picture description hereAbstractHandlerMethodAdapter
Insert picture description hereamong which RequestMappingHandlerAdapter does not need to be shown, because it is an inherited
AbstractHandlerMethodAdapter and does not override the supports() and handler() methods.

We see the above four pictures, we can find that each picture has rewritten the supports() and handler() methods, and the supports() method of each class determines the type of the parameter handler. The handler() method of each class executes its target method.

So how do we judge the circumstances under which these four adapters are used?

Not much nonsense. Create the project first. And write the following code.
MyConfig.java

package com.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author 龙小虬
 * @date 2021/3/18 14:43
 */
@Configuration
@ComponentScan("com.controller")
public class MyConfig {
    
    
}

WebInitializer.java

package com.config;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

/**
 * @author 龙小虬
 * @date 2021/3/18 14:41
 */
public class WebInitializer implements WebApplicationInitializer {
    
    
    @Override
    public void onStartup(ServletContext servletContext) {
    
    
        // 1.   创建SpringMVC容器
        AnnotationConfigWebApplicationContext app = new AnnotationConfigWebApplicationContext();
        // 2. 注册我们的配置文件
        app.register(MyConfig.class);
        // 注册我们的
        DispatcherServlet dispatcherServlet = new DispatcherServlet(app);
        ServletRegistration.Dynamic dynamic = servletContext.addServlet("dispatcherServlet", dispatcherServlet);
        dynamic.addMapping("/");
        dynamic.setLoadOnStartup(1);// 最优先启动
        dynamic.setAsyncSupported(true);
    }
}

The configuration of the above two classes is described in SpringMVC source code analysis-basic knowledge (2) . The following is what we use to judge the usage scenarios of each adapter.
MemberController.java

package com.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.HttpRequestHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 龙小虬
 * @date 2021/3/18 15:13
 */
@Controller("/memberController")
public class MemberController implements HttpRequestHandler {
    
    
    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        response.getWriter().print("HttpRequestHandlerAdapter");
    }
}

MemberController.java

package com.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.HttpRequestHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author 龙小虬
 * @date 2021/3/18 15:13
 */
@Controller("/memberController")
public class MemberController implements HttpRequestHandler {
    
    
    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        response.getWriter().print("HttpRequestHandlerAdapter");
    }
}

PayController.java

package com.controller;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author 龙小虬
 * @date 2021/3/18 15:09
 */
@org.springframework.stereotype.Controller("/payController")
public class PayController implements Controller {
    
    
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
    
    
        response.getWriter().print("SimpleControllerHandlerAdapter");
        return new ModelAndView("");
    }
}

For testing, we will find:

  1. SimpleControllerHandlerAdapter is used only when it implements the interface org.springframework.web.servlet.mvc.Controller
  2. AbstractHandlerMethodAdapter (RequestMappingHandlerAdapter) is used only after using @RequestMapping annotation
  3. HttpRequestHandlerAdapter is only used when the interface HttpRequestHandler is implemented

In fact, why we need to use the adapter to wrap the handler once has also been solved. In our code, we can find that the method called is a different method name. Once we want to use them together, we need to use the adapter. Of course, some people may wonder, why not use if directly? ? ? If you use if, how can developers expand? Using the adapter mode, other developers can expand very well.

Guess you like

Origin blog.csdn.net/weixin_43911969/article/details/114981687