SpringMVC源码分析------HandlerAdapter适配器

项目地址
SpringMVC_04
觉得博主还可以给个Star

适配器模式
将一个类的接口转换成客户希望的另一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作。

HandlerAdapter分析
我们了解到了适配器模式的定义,那现在来看看HandlerAdapter吧。在我们DispatcherServlet中doDispatch()方法中HandlerAdapter被使用过,那为什么要使用这个适配器呢?在我们前面纯手写SpringMVC逻辑处理过程的时候,我们并没有使用适配器,可还是达到了目的。我们了解了适配器模式之后,就可以发现,他是把原本不兼容的接口最终放在一起使用。这就是为什么要这样使用了。我们先看源代码。
debug走起。在走到这个位置的时候,也就是doDispatch()获取适配器的方法中。
在这里插入图片描述我们会看到这里面有三个适配器,这三个适配器是最开始初始化注入的。我们来看看HandlerAdapter的实现类最初注入的这几个适配器,其中RequestMappingHandlerAdapter是因为继承了AbstractHandlerMethodAdapter,所以我们得看AbstractHandlerMethodAdapter

HttpRequestHandlerAdapter
在这里插入图片描述AbstractHandlerMethodAdapter
在这里插入图片描述其中RequestMappingHandlerAdapter就没必要展示了,因为他是继承的
AbstractHandlerMethodAdapter,并没有重写supports()和handler()方法。

我们看到上面四张图,可以发现每张图片都重写了supports()和handler()方法,而每个类的supports()方法里面都判断了参数handler属于的类型。每个类的handler()方法都去执行其目标方法了。

那么我们怎么去判断这四个适配器分别是在什么情况下使用的呢?

废话不多说。先创建项目。并写下如下代码。
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);
    }
}

上面的两个类的配置在SpringMVC源码分析------基础知识(二)中描述过了。下面就是我们用来判断各个适配器的使用场景。
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("");
    }
}

进行测试,我们会发现:

  1. SimpleControllerHandlerAdapter是实现了接口org.springframework.web.servlet.mvc.Controller才使用
  2. AbstractHandlerMethodAdapter(RequestMappingHandlerAdapter)是使用了@RequestMapping注解才进行使用
  3. HttpRequestHandlerAdapter是实现了接口HttpRequestHandler才使用

其实为什么要使用适配器包装一次handler也已经解开了,在我们的代码中,可以发现,调用的方法是不同的方法名,一旦我们要把它们集中在一块使用就需要使用适配器。当然,有人会疑问,为什么不直接用if???假如使用if的话,那开发者怎么去扩展?使用适配器模式,其他的开发者就可以很好的扩展。

猜你喜欢

转载自blog.csdn.net/weixin_43911969/article/details/114981687