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

适用场景:

1、已经存在的类的接口不符合我们的需求;

2、创建一个可以复用的类,使得该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作;

3、在不对每一个都进行子类化以匹配它们的接口的情况下,使用一些已经存在的子类。

找到DispatcherServlet类中的doDispatch体,我们可以看到,它的作用是相当于在Servlet的 doService调用的。 也就是用来传递request给我们编写的Controller并执行相应的方法、返回ModeView对象。

执行的代码片段:

  1. ...
  2. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
  3. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
  4. ...

mappedHandler.getHandler()得到的是Controller对象 
而此处并非采用直接 调用.handlerRequest或者MultiActionController中编写的自定义方法,而采用了一个HandlerAdapter 的接口。

此处采用了适配器模式, 由于Controller的类型不同,有多重实现方式,那么调用方式就不是确定的,如果需要直接调用Controller方法,需要在代码中写成如下形式:

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

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

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

废话不多说还是上代码吧,为了看得清楚,就自己实现一套代码来模拟springMVC, 直接贴Spring源码容易降低关注点。

    1. //定义一个Adapter接口
    2. public interface HandlerAdapter {
    3. public boolean supports(Object handler);
    4. public void handle(Object handler);
    5. }
    6. //以下是三种Controller实现
    7. public interface Controller {
    8. }
    9. public class HttpController implements Controller{
    10. public void doHttpHandler(){
    11. System.out.println("http...");
    12. }
    13. }
    14. public class SimpleController implements Controller{
    15. public void doSimplerHandler(){
    16. System.out.println("simple...");
    17. }
    18. }
    19. public class AnnotationController implements Controller{
    20. public void doAnnotationHandler(){
    21. System.out.println("annotation...");
    22. }
    23. }
    24. //下面编写适配器类
    25. public class SimpleHandlerAdapter implements HandlerAdapter {
    26. public void handle(Object handler) {
    27. ((SimpleController)handler).doSimplerHandler();
    28. }
    29. public boolean supports(Object handler) {
    30. return (handler instanceof SimpleController);
    31. }
    32. }
    33. public class HttpHandlerAdapter implements HandlerAdapter {
    34. public void handle(Object handler) {
    35. ((HttpController)handler).doHttpHandler();
    36. }
    37. public boolean supports(Object handler) {
    38. return (handler instanceof HttpController);
    39. }
    40. }
    41. public class AnnotationHandlerAdapter implements HandlerAdapter {
    42. public void handle(Object handler) {
    43. ((AnnotationController)handler).doAnnotationHandler();
    44. }
    45. public boolean supports(Object handler) {
    46. return (handler instanceof AnnotationController);
    47. }
    48. }
    49. //模拟一个DispatcherServlet
    50. import java.util.ArrayList;
    51. import java.util.List;
    52. public class DispatchServlet {
    53. public static List<HandlerAdapter> handlerAdapters = new ArrayList<HandlerAdapter>();
    54. public DispatchServlet(){
    55. handlerAdapters.add(new AnnotationHandlerAdapter());
    56. handlerAdapters.add(new HttpHandlerAdapter());
    57. handlerAdapters.add(new SimpleHandlerAdapter());
    58. }
    59. public void doDispatch(){
    60. //此处模拟SpringMVC从request取handler的对象,仅仅new出,可以出,
    61. //不论实现何种Controller,适配器总能经过适配以后得到想要的结果
    62. //      HttpController controller = new HttpController();
    63. //      AnnotationController controller = new AnnotationController();
    64. SimpleController controller = new SimpleController();
    65. //得到对应适配器
    66. HandlerAdapter adapter = getHandler(controller);
    67. //通过适配器执行对应的controller对应方法
    68. adapter.handle(controller);
    69. }
    70. public HandlerAdapter getHandler(Controller controller){
    71. for(HandlerAdapter adapter: this.handlerAdapters){
    72. if(adapter.supports(controller)){
    73. return adapter;
    74. }
    75. }
    76. return null;
    77. }
    78. public static void main(String[] args){
    79. new DispatchServlet().doDispatch();
    80. }
    81. }

SpringMVC中的适配器的更多相关文章

  1. SpringMVC中的适配器(适配者模式)

    此处采用了适配器模式, 由于Controller的类型不同,有多重实现方式,那么调用方式就不是确定的,如果需要直接调用Controller方法,需要在代码中写成如下形式: if(mappedHandl ...

  2. SpringMVC中注解和非注解方式下的映射器和适配器总结

    1. 非注解方式 1.1 处理器适配器 上一节中使用的处理器适配器是:org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapte ...

  3. 【SpringMVC学习03】SpringMVC中注解和非注解方式下的映射器和适配器总结

    从上一篇的springmvc入门中已经看到,springmvc.xml中的配置了映射器和适配器,是使用非注解的方式来配置的,这是非注解方式的一种,这里再复习一下: 1. 非注解方式 1.1 处理器适配 ...

  4. springmvc中RequestMapping的解析

    在研究源码的时候,我们应该从最高层来看,所以我们先看这个接口的定义: package org.springframework.web.servlet; import javax.servlet.htt ...

  5. springMVC中ajax的使用

    springMVC中使用ajax有两种方法,第一种是根据servletAPI来使用ajax,第二种是根据springMVC给我们提供的API来使用. 一.根据servletAPI: springMVC ...

  6. JavaEE开发之SpringMVC中的自定义拦截器及异常处理

    上篇博客我们聊了<JavaEE开发之SpringMVC中的路由配置及参数传递详解>,本篇博客我们就聊一下自定义拦截器的实现.以及使用ModelAndView对象将Controller的值加 ...

  7. 将SpringMVC中的HttpMessageConverter替换为Gson

    读者们看到这个标题也许会感到奇怪,SpringMVC中默认的HttpMessageConverter不是Jackson吗,但是我在使用的过程中发现Jackson并不好用,如果有一些复杂的嵌套类型,当然 ...

  8. 关于springMVC中component-scan的问题以及springmvc.xml整理

    关于springMVC中component-scan的问题以及springmvc.xml整理 一.component-scan问题和解决办法         最近在学习使用springMVC+myba ...

  9. 【SpringMVC学习06】SpringMVC中的数据校验

    这一篇博文主要总结一下springmvc中对数据的校验.在实际中,通常使用较多是前端的校验,比如页面中js校验,对于安全要求较高的建议在服务端也要进行校验.服务端校验可以是在控制层conroller, ...

随机推荐

  1. 在MySQL中使用explain查询SQL的执行计划

    1.什么是MySQL执行计划 要对执行计划有个比较好的理解,需要先对MySQL的基础结构及查询基本原理有简单的了解. MySQL本身的功能架构分为三个部分,分别是 应用层.逻辑层.物理层,不只是MyS ...

  2. 20145329 《Java程序设计》第五周学习总结

    20145329 <Java程序设计>第五周学习总结 教材学习内容总结 第八章 Java异常处理是要处理Exception类及其子类(Checked Exception),RuntimeE ...

  3. 20135320赵瀚青LINUX内核分析第三周学习笔记

    赵瀚青原创作品转载请注明出处<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 概述 本周是学习的主要是构造 ...

  4. CentOS 64位系统 yum安装32位软件包的方法

    //假如你要安装libjpeg的32位版本 1.查询具体的32位版本,然后安装 yum search libjpeg.i686 yum -y install libjpeg.i386 2.一劳永逸的方 ...

  5. Spring笔记2——Spring中Bean的装配

    1.引言 Spring中,对象无需自己负责查找或创建与其关联的其他对象,而是由容器负责把需要相互协作的对象引用赋予各个对象.创建应用对象之间的协作关系的行为通常称为装配(Wiring),这也是依赖注入 ...

  6. [ARC061E]すぬけ君の地下鉄旅行 / Snuke's Subway Trip

    题目大意:Snuke的城镇有地铁行驶,地铁线路图包括$N$个站点和$M$个地铁线.站点被从$1$到$N$的整数所标记,每条线路被一个公司所拥有,并且每个公司用彼此不同的整数来表示. 第$i$条线路($ ...

  7. Can't connect to any repository: xxxxxx Error writing request body to server

    今天在git提交代码时一直报如下错误: Can't connect to any repository: https://gitee.com/xxxxxx(https://gitee.com/xxxx ...

  8. 【分类】AlexNet论文总结

    目录 0. 论文链接 1. 概述 2. 对数据集的处理 3. 网络模型 3.1 ReLU Nonlinearity 3.2 Training on multiple GPUs 3.3 Local Re ...

  9. 使用xunit对asp.net core webapi进行集成测试

    新项目我们采用前后端分离,后端采用asp.net core webapi, 如何对后端代码进行自动化测试呢,有以下几种方案: 1. 单元测试,目前这个方案对我们来说难度很大,抛开时间的问题,单元测试对 ...

  10. jQuery实际案例④——360导航图片效果

    如图:①首先使用弹性盒子布局display:flex; flex-wrap:wrap; ②鼠标移上去出现“百度一下,你就知道了”,这句话之前带上各个网站的logo:③logo使用的是sprite,需要 ...