适配器模式(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. Django学习笔记之Web框架由浅入深和第一个Django实例

    Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端. 这样我们就可以自己实现Web框架了. 半成品自定义web框架 impor ...

  2. Nginx配置location跳转后偶尔出现404

    tv.xxx.com/voice请求时需跳转至:tv.xxx.com/zongyi/zt2015/haoshengyin/index.shtml 目录结构: nginx服务器配置: location ...

  3. AVL模板

    感谢此博客 #include <bits/stdc++.h> #define pb push_back #define mp make_pair #define de(x) cout &l ...

  4. 商品详情页,banner滚动点击加载效果,js,jquary

    <script language="javascript">       $(document).ready(function () {   //purchase   ...

  5. Codeforces Round #361 (Div. 2) E. Mike and Geometry Problem 离散化+逆元

    E. Mike and Geometry Problem time limit per test 3 seconds memory limit per test 256 megabytes input ...

  6. jsplumb 的初次使用

    最近的项目要能创建流程, 流程配置什么的就找了 jsplumb 来做流程的显示配置.经过两天的研究成果已经很明显了 参考了以下一些大神们的博客: jsplumb 中文教程 连线绘图工具库介绍 附简单在 ...

  7. PHP会话控制之如何正确设置session_name

    定义: string session_name([string $name]) 说明: 在php.ini中配置为:session.name = PHPSESSID 在请求开始的时候,会话名称会被重置并 ...

  8. 安装fcitx

    设置好软件源后,终端执行: sudo apt-get install fcitx  fcitx-ui-* fcitx-sunpinyin fcitx-googlepinyin fcitx-pinyin ...

  9. 搞懂分布式技术21:浅谈分布式消息技术 Kafka

    搞懂分布式技术21:浅谈分布式消息技术 Kafka 浅谈分布式消息技术 Kafka 本文主要介绍了这几部分内容: 1基本介绍和架构概览 2kafka事务传输的特点 3kafka的消息存储格式:topi ...

  10. 二十五 Python分布式爬虫打造搜索引擎Scrapy精讲—Requests请求和Response响应介绍

    Requests请求 Requests请求就是我们在爬虫文件写的Requests()方法,也就是提交一个请求地址,Requests请求是我们自定义的 Requests()方法提交一个请求 参数: ur ...