• 第五节:适配器在 SpringMVC 中的应用


    一、适配器模式在 SpringMVC 框架应用的源码分析

      1、SpringMVC 中的 HandlerAdapter,就使用了适配器模式;

      2、SpringMVC 处理请求的流程回顾:

                         

      3、使用 HandlerAdapter 的原因分析:

        在容器中会有多个处理器(Controller),且它们类型不同,有多重实现方式,那么调用方式就不是确定的。如果需要直接调用 Controller 方法,需要调用的时候就得不断是使用 if else 来进行判断是哪一种子类然后执行。如果后面要扩展 Controller,就得修改原来的代码,违背了 OCP 原则。

        不适用设计模式情况下:

    1 if(mappedHandler.getHandler() instanceof MultiActionController){  
    2    ((MultiActionController)mappedHandler.getHandler()).xxx  
    3 }else if(mappedHandler.getHandler() instanceof XXX){  
    4     ...  
    5 }else if(...){  
    6    ...  
    7 }

      这样假设如果我们增加一个HardController,就要在代码中加入一行 if(mappedHandler.getHandler() instanceof  HardController) 这种形式就使得程序难以维护,也违反了设计模式中的开闭原则 --  对扩展开放,对修改关闭。     

      因此Spring定义了一个适配接口,使得每一种Controller有一种对应的适配器实现类,让适配器代替controller执行相应的方法。这样在扩展Controller 时,只需要增加一个适配器类就完成了SpringMVC的扩展了,真的是很精巧的做法! 

    二、适配器模式在 SpringMVC 框架应用的源码剖析

      1、流程图

        

      2、源码分析

        (1)DispatcherServlet 中 doDispatch 方法

     1 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
     2         HttpServletRequest processedRequest = request;
     3         HandlerExecutionChain mappedHandler = null;
     4         boolean multipartRequestParsed = false;
     5         WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
     6 
     7         try {
     8             try {
     9                 ModelAndView mv = null;
    10                 Object dispatchException = null;
    11 
    12                 try {
    13                     processedRequest = this.checkMultipart(request);
    14                     multipartRequestParsed = processedRequest != request;
    15                     mappedHandler = this.getHandler(processedRequest); //根据请求获取对应的处理器(controller)
    16                     if (mappedHandler == null) {
    17                         this.noHandlerFound(processedRequest, response);
    18                         return;
    19                     }
    20 
    21                     HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());//根据controller获取对应adapter
    22                     String method = request.getMethod();
    23                     boolean isGet = "GET".equals(method);
    24                     if (isGet || "HEAD".equals(method)) {
    25                         long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
    26                         if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
    27                             return;
    28                         }
    29                     }
    30 
    31                     if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    32                         return;
    33                     }
    34 
    35                     mv = ha.handle(processedRequest, response, mappedHandler.getHandler());//根据Adapter执行对应controller里面的方法,返回ModelAndView
    36                     if (asyncManager.isConcurrentHandlingStarted()) {
    37                         return;
    38                     }
    39 
    40                     this.applyDefaultViewName(processedRequest, mv);
    41                     mappedHandler.applyPostHandle(processedRequest, response, mv);
    42                 } catch (Exception var20) {
    43                     dispatchException = var20;
    44                 } catch (Throwable var21) {
    45                     dispatchException = new NestedServletException("Handler dispatch failed", var21);
    46                 }
    47 
    48                 this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
    49             } catch (Exception var22) {
    50                 this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
    51             } catch (Throwable var23) {
    52                 this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
    53             }
    54 
    55         } finally {
    56             if (asyncManager.isConcurrentHandlingStarted()) {
    57                 if (mappedHandler != null) {
    58                     mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
    59                 }
    60             } else if (multipartRequestParsed) {
    61                 this.cleanupMultipart(processedRequest);
    62             }
    63 
    64         }
    65     }

      

      (2)getHandler 方法

     1  @Nullable
     2     protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
     3         if (this.handlerMappings != null) {
     4             Iterator var2 = this.handlerMappings.iterator();
     5 
     6             while(var2.hasNext()) {
     7                 HandlerMapping mapping = (HandlerMapping)var2.next();
     8                 HandlerExecutionChain handler = mapping.getHandler(request);
     9                 if (handler != null) {
    10                     return handler;
    11                 }
    12             }
    13         }
    14 
    15         return null;
    16     }

      (3)getHandlerAdapter 方法:遍历所有的Adapter,根据 controller获取对应 Adapter

     1 protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
     2         if (this.handlerAdapters != null) {
     3             Iterator var2 = this.handlerAdapters.iterator();
     4 
     5             while(var2.hasNext()) {
     6                 HandlerAdapter adapter = (HandlerAdapter)var2.next();
     7                 if (adapter.supports(handler)) {
     8                     return adapter;
     9                 }
    10             }
    11         }
    12 
    13         throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
    14     }

      (4)以 HttpRequestHandlerAdapter 为例:

     1 public class HttpRequestHandlerAdapter implements HandlerAdapter {
     2     public HttpRequestHandlerAdapter() {
     3     }
     4 
     5     public boolean supports(Object handler) {
     6         return handler instanceof HttpRequestHandler;
     7     }
     8 
     9     @Nullable
    10     public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    11         ((HttpRequestHandler)handler).handleRequest(request, response);
    12         return null;
    13     }
    14 
    15     public long getLastModified(HttpServletRequest request, Object handler) {
    16         return handler instanceof LastModified ? ((LastModified)handler).getLastModified(request) : -1L;
    17     }
    18 }

     

    三、手动代码实现

      实现一套代码来模拟springMVC

      Controller 类:

     1 /**
     2  * 多种Controller实现 
     3  */ 
     4 public interface Controller {
     5 
     6 }
     7 
     8 class HttpController implements Controller {
     9     public void doHttpHandler() {
    10         System.out.println("http...");
    11     }
    12 }
    13 
    14 class SimpleController implements Controller {
    15     public void doSimplerHandler() {
    16         System.out.println("simple...");
    17     }
    18 }
    19 
    20 class AnnotationController implements Controller {
    21     public void doAnnotationHandler() {
    22         System.out.println("annotation...");
    23     }
    24 }

      

      Adapter 接口及实现:

     1 /**
     2  * 定义一个Adapter接口
     3  */
     4 public interface HandlerAdapter {
     5     public boolean supports(Object handler);
     6 
     7     public void handle(Object handler);
     8 }
     9 
    10 /**
    11  * 多种适配器类
    12  */
    13 class SimpleHandlerAdapter implements HandlerAdapter {
    14 
    15     @Override
    16     public void handle(Object handler) {
    17         ((SimpleController) handler).doSimplerHandler();
    18     }
    19 
    20     @Override
    21     public boolean supports(Object handler) {
    22         return (handler instanceof SimpleController);
    23     }
    24 
    25 }
    26 
    27 class HttpHandlerAdapter implements HandlerAdapter {
    28 
    29     @Override
    30     public void handle(Object handler) {
    31         ((HttpController) handler).doHttpHandler();
    32     }
    33 
    34     @Override
    35     public boolean supports(Object handler) {
    36         return (handler instanceof HttpController);
    37     }
    38 
    39 }
    40 
    41 class AnnotationHandlerAdapter implements HandlerAdapter {
    42 
    43     @Override
    44     public void handle(Object handler) {
    45         ((AnnotationController) handler).doAnnotationHandler();
    46     }
    47 
    48     @Override
    49     public boolean supports(Object handler) {
    50 
    51         return (handler instanceof AnnotationController);
    52     }
    53 
    54 }

      测试类:模拟 DispatcherServlet

     1 public class DispatchServlet {
     2 
     3     public static List<HandlerAdapter> handlerAdapters = new ArrayList<>();
     4 
     5     public DispatchServlet() {
     6         handlerAdapters.add(new AnnotationHandlerAdapter());
     7         handlerAdapters.add(new HttpHandlerAdapter());
     8         handlerAdapters.add(new SimpleHandlerAdapter());
     9     }
    10 
    11     public void doDispatch() {
    12 
    13         // 此处模拟SpringMVC从request取handler的对象,
    14         // 适配器可以获取到希望的Controller
    15          HttpController controller = new HttpController();
    16         // AnnotationController controller = new AnnotationController();
    17         //SimpleController controller = new SimpleController();
    18         // 得到对应适配器
    19         HandlerAdapter adapter = getHandler(controller);
    20         // 通过适配器执行对应的controller对应方法
    21         adapter.handle(controller);
    22 
    23     }
    24 
    25     public HandlerAdapter getHandler(Controller controller) {
    26         //遍历:根据得到的controller(handler), 返回对应适配器
    27         for (HandlerAdapter adapter : handlerAdapters) {
    28             if (adapter.supports(controller)) {
    29                 return adapter;
    30             }
    31         }
    32         return null;
    33     }
    34 
    35     public static void main(String[] args) {
    36         new DispatchServlet().doDispatch();
    37     }
    38 
    39 }

       说明:

        1)Spring 定义了一个适配接口,使得每一种 conroller 有一种对应的适配器实现类;

        2)适配器代替 controller 执行相应的方法;

        3)扩展 controller 时,只需要增加一个适配器类就完成了 SpringMVC 的扩展;

      

  • 相关阅读:
    关于oralce字符集问题(复制别人的,纯属自己学习)
    Linux下oracle11gR2系统安装到数据库建立配置及最后oracle的dmp文件导入一站式操作记录
    Linux下部署ASP.NET服务连接oracle遇到的问题记录
    前端金钱分转元,元转分精度问题解决
    vue-element的form表单显示图片
    vue页面刷新技巧--(v-if指令)以及vue动态设置css属性
    vue后端获取的数据无法进行双向数据绑定
    Vue实现勾选框全选和局部选择功能
    VUE/jQuery生成二维码扫描跳转地址
    uni-app之数据状态改动后页面不刷新踩坑
  • 原文地址:https://www.cnblogs.com/niujifei/p/14289759.html
Copyright © 2020-2023  润新知