office xml handler什么意思_SpringMvc中为什么有HandlerAdapter组件呢?是不是多余?

Spring MVC 使用HandlerAdapter适配器是为了适配不同的Controller处理方式,避免直接在DispatcherServlet中处理不同类型的Controller导致代码修改。通过定义统一的HandlerAdapter接口,Spring实现了对Controller的灵活扩展,遵循开闭原则。当请求到来时,DispatcherServlet根据URL从HandlerMapping获取handler,再由HandlerAdapter进行适配并执行相应函数,返回结果给客户端。
摘要由CSDN通过智能技术生成

9d7fbb32a881875f05f579c760613dca.png

在 Spring web开发中,我们开发方式基本都是使用注解,使用@Controller和@RequestMapping注解完整,但是你有没有发现,为什么SpringMVC中有HandlerAdapter适配器呢?因为你不知道还有其他方式来定义一个Controller.

  1. 使用 @Controller,@RequestMapping 注解实现
 @Controller
public class DemoController {
    @RequestMapping("/hello")
    public ModelAttribute hello(){
        ModelAndView model = new ModelAndView("hello"); 
        model.addObject("hello", "world");
        return model;
    }
}
  1. 实现Controller接口
@Controller
public class DemoController2 implements org.springframework.web.servlet.mvc.Controller {
    @Override
    public ModelAndView handleRequest( HttpServletRequest request, HttpServletResponse response ) throws Exception {
        ModelAndView model = new ModelAndView("hello");
        model.addObject("hello", "world");
        return model;
    }
}

但是这个时候就需要配置URL和Controller的关系,在spring.xml中配置

<bean name="/hello" class="com.xx.web.controller.DemoController2 "></bean>
  1. 实现Servlet接口
public class DemoController3 extends  HttpServlet {
    @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException { 
        this.doPost(req, resp); 
    }
    @Override 
    
    protected void doPost( HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.getWriter().write("Hello World."); 
    }
}

这种方式也需要在xml中配置映射;

在应用启动的 时候,Spring 加载这些Controller类,并解析出URL 对应的处理器handler, 存储到HandlerMapping 里的Map里,当请求到来的时候,DispatcherServlet 首先解析出URL,然后根据URL从HandlerMapping中获取到对应的handler,然后用HandlerAdapter去适配对应的handler,然后去执行handler对应的函数 代码,最后将执行结果返回给客户端。

但是,不同定义的Controller,其 调用的函数不一样,如果是我们自己写,怎么写呢?可以用if else 来处理,代码如下:

Handler handler = handlerMapping.get(URL);
if (handler instanceof Controller) {
  ((Controller)handler).handleRequest(...);
} else if (handler instanceof Servlet) {
  ((Servlet)handler).service(...);
} else if (hanlder 对应通过注解来定义的Controller) {
  反射调用方法...
}

上述代码的缺点是:如果再增加一个Controller类型,我们需要修改DispatcherServlet代码,在代码中增加一段上述类似的代码。这显然违背开闭原则。

那么Spring中是怎么实现的呢?

Spring 定义了统一的接口HandlerAdapter,并且每种Controller定义了对应的适配器类;

/**
* @desc: 类的描述:处理器适配器 应用到的设计模式:模版方法,适配器模式
 *HandlerAdapter
 *    ---AbstractHandlerMethodAdapter
 *      ---RequestMappingHandlerAdapter
 *    ---SimpleServletHandlerAdapter
 *    ---HttpRequestHandlerAdapter
 *    ---SimpleControllerHandlerAdapter
 *
*/
public interface HandlerAdapter {
   /**
    * 方法实现说明:判断当前的HandlerAdapter是否支持当前的handler
    */
   boolean supports(Object handler);
   /**
    * 方法实现说明:处理我们的请求 返回ModelAndView
    */
   @Nullable
   ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;


   long getLastModified(HttpServletRequest request, Object handler);
}

2020b671c38d7ecbb8a786ec94efd2da.png

我们分析其中一个HandlerAdapter (SimpleControllerHandlerAdapter)

public class SimpleControllerHandlerAdapter implements HandlerAdapter {


  // 对应实现 Controller 接口的Handler
   @Override
   public boolean supports(Object handler) {
      return (handler instanceof Controller);
   }
   @Override
   @Nullable
   public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
         throws Exception {
      return ((Controller) handler).handleRequest(request, response);
   }
   @Override
   public long getLastModified(HttpServletRequest request, Object handler) {
      if (handler instanceof LastModified) {
         return ((LastModified) handler).getLastModified(request);
      }
      return -1L;
   }
}

当我们调用的时候,DispatcherServlet 不用再区分是什么是什么样的handler,只需要获取所有的HandlerAdapter进行适配即可,源码如下:

  1. 适配器的初始化
private void initHandlerAdapters(ApplicationContext context) {
   this.handlerAdapters = null;
   if (this.detectAllHandlerAdapters) {
      /**
       * 由于我们自己配置了@EnableMvc 所有在配置类中系统会给我们配置几个HandlerApapter
       * RequestMappingHandlerAdapter
       * SimpleControllerHandlerAdapter
       * HttpRequestHandlerAdapter
       */
      Map<String, HandlerAdapter> matchingBeans =
            BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
      if (!matchingBeans.isEmpty()) {
         this.handlerAdapters = new ArrayList<>(matchingBeans.values());
         // We keep HandlerAdapters in sorted order.
         AnnotationAwareOrderComparator.sort(this.handlerAdapters);
      }
   }
   else {
      try {
         HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
         this.handlerAdapters = Collections.singletonList(ha);
      }
      catch (NoSuchBeanDefinitionException ex) {
         // Ignore, we'll add a default HandlerAdapter later.
      }
   }


   if (this.handlerAdapters == null) {
      //默认配置 是通过SpringMvc配置在DispatcherServlet.properties属性文件中
      this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
   }
}

上述代码比较简单,基本意思是 找到Spring容器中配置的HandlerAdapter实现类;

  1. handler的执行
/**
 * 根据Handler选择我们的HandlerAdpater对象
 * 默认是@RequestMappingHandlerAdapter对象
 */
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
/**
 * 方法实现说明:从我们系统默认的配置的HandlerAdapter 选择支持当前的
 * 系统配置配置的@EnableWebMvc
 *  默认配置的:
 *  RequestMappingHandlerAdapter
 *     SimpleControllerHandlerAdapter
 *     HttpRequestHandlerAdapter
 */
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
   //循环我们的系统配置配置的handlerAdapters
   if (this.handlerAdapters != null) {
      for (HandlerAdapter ha : this.handlerAdapters) {
         if (logger.isTraceEnabled()) {
            logger.trace("Testing handler adapter [" + ha + "]");
         }
         if (ha.supports(handler)) {
            return ha;
         }
      }
   }
}

总结: 所以HandlerAdapter不是多余,是为了适配不同的Controller而存在的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值