Jsonrpc标准+泛化调用,服务端DispatcherServlet源码思路分析

背景

在rpc的服务化调用中,如果客户端使用多种调用姿势,比如jsonrpc的标准调用、jsonrpc的泛化调用同时存在,那么服务端必须能够同时对这两种典型的调用的方式进行兼容。好在jsonrpc和spring的web框架可以完美集成。比如服务端使用jsonrpc+springboot进行集成。
这里解释一下什么是jsonrpc的泛化调用?一句话,就是对jsonrpc的传输协议进行改造并进行http调用,让服务端以传统webController的方式接收请求。
jsonrpc的标准调用是什么?可以参看下文档:https://github.com/briandilley/jsonrpc4j
这里不对jsonrpc的基础使用姿势进行说明,可以自己补一下。jsonrpc的基本协议格式是:
在这里插入图片描述

具体可以看下官方文档相关协议说明:https://www.jsonrpc.org/specification

思路分析

那么,jsonrpc泛化请求如:/demo2/genericService/genericCall在服务端是怎么处理的?
通过抓包可以看到请求报文如下:
在这里插入图片描述跟普通的http的web请求没啥两样。
前边说过,服务端我们是springboot+jsonrpc的框架,所以会由DispatcherServlet的doDispatch方法为入口。

  • 关键代码:
mappedHandler = getHandler(processedRequest);

首先,DispatcherServlet里getHandler方法就可以通过request对象从以下handlerMappings中找到合适的handler。
代码如下:

/**
 * Return the HandlerExecutionChain for this request.
 * <p>Tries all handler mappings in order.
 * @param request current HTTP request
 * @return the HandlerExecutionChain, or {@code null} if no handler could be found
 */
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
   if (this.handlerMappings != null) {
      for (HandlerMapping mapping : this.handlerMappings) {
         HandlerExecutionChain handler = mapping.getHandler(request);
         if (handler != null) {
            return handler;
         }
      }
   }
   return null;
}

在这里插入图片描述
比如这里找到的就是具体Controller的目标调用method,同时这里匹配到的是RequestMappingHandlerMapping:
在这里插入图片描述但是对于jsonrpc的标准调用,这里有了变化。这里匹配到的是BeanNameHandlerMapping,得到的handler是JsonServiceExporter。
在这里插入图片描述
JsonServiceExporter是jsonrpc的类,继承了AbstractJsonServiceExporter,实现了org.springframework.web.HttpRequestHandler。JsonServiceExporter是被spring容器实例化的时候调用AbstractJsonServiceExporter的afterProperties方法来完成jsonrpcServer的创建。
代码如下:

  • JsonServiceExporter
public class JsonServiceExporter extends AbstractJsonServiceExporter implements HttpRequestHandler {

   private JsonRpcServer jsonRpcServer;

   /**
    * {@inheritDoc}
    */
   @Override
   protected void exportService() {
      jsonRpcServer = getJsonRpcServer();
   }

   /**
    * {@inheritDoc}
    */
   public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      jsonRpcServer.handle(request, response);
      response.getOutputStream().flush();
   }

}
  • AbstractJsonServiceExporter:
abstract class AbstractJsonServiceExporter extends RemoteExporter implements InitializingBean, ApplicationContextAware {

    public void afterPropertiesSet() throws Exception {
        ...
        jsonRpcServer = new JsonRpcServer(objectMapper,
      null == getServiceInterface() ? getService() : getProxyForService(),
      getServiceInterface());
        .....
    }
     .....
}

然后,根据handler查找HandlerAdapter,关键代码如下:

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

具体如下:

/**
 * Return the HandlerAdapter for this handler object.
 * @param handler the handler object to find an adapter for
 * @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.
 */
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
   if (this.handlerAdapters != null) {
      for (HandlerAdapter adapter : this.handlerAdapters) {
         if (adapter.supports(handler)) {
            return adapter;
         }
      }
   }
   throw new ServletException("No adapter for handler [" + handler +
         "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}

这里的handlerAdapters是:
在这里插入图片描述
这里handler最终找到的是RequestMappingHandlerAdapter。
但同样如果是jsonrpc的标准调用,这里就不一样了。由于JsonServiceExporter实现了HttpRequestHandler接口,所以这里支持的适配器就是HttpRequestHandlerAdapter。

public class JsonServiceExporter extends AbstractJsonServiceExporter implements HttpRequestHandler{......}

在这里插入图片描述
然后,就是执行具体的方法返回modeAndView视图了。关键代码:

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

但RequestMappingHandlerAdapter也没有实现AbstractHandlerMethodAdapter的handle方法。所以使用抽象类中的方法。

/**
 * This implementation expects the handler to be an {@link HandlerMethod}.
 */
@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {

   return handleInternal(request, response, (HandlerMethod) handler);
}

最终执行到业务Controller中的方法。
不过jsonrpc的标准调用返回的适配器是HttpRequestHandlerAdapter,自然也就是执行其hanle方法了。

package org.springframework.web.servlet.mvc;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.lang.Nullable;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.ModelAndView;

/**
 * Adapter to use the plain {@link org.springframework.web.HttpRequestHandler}
 * interface with the generic {@link org.springframework.web.servlet.DispatcherServlet}.
 * Supports handlers that implement the {@link LastModified} interface.
 *
 * <p>This is an SPI class, not used directly by application code.
 *
 * @author Juergen Hoeller
 * @since 2.0
 * @see org.springframework.web.servlet.DispatcherServlet
 * @see org.springframework.web.HttpRequestHandler
 * @see LastModified
 * @see SimpleControllerHandlerAdapter
 */
public class HttpRequestHandlerAdapter implements HandlerAdapter {

   @Override
   public boolean supports(Object handler) {
      return (handler instanceof HttpRequestHandler);
   }

   @Override
   @Nullable
   public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
         throws Exception {

      ((HttpRequestHandler) handler).handleRequest(request, response);
      return null;
   }

   @Override
   public long getLastModified(HttpServletRequest request, Object handler) {
      if (handler instanceof LastModified) {
         return ((LastModified) handler).getLastModified(request);
      }
      return -1L;
   }

}

这里hanle传进来的handler也就是JsonServiceExporter,也就是说最终会执行其hanleRequest方法。
在这里插入图片描述
在这里插入图片描述
后在jsonRpcServer中进行一系列的反射调用,执行到最后的标注有@AutoJsonRpcServiceImpl的Service方法上。

Jeff.Star CSDN认证博客专家 Java
[努力支撑经历,经历支撑能力.]
[思路决定出路,细节决定成败.]
[聚焦,分享,转化,参与.]
[数据在流动,技术在流动,我们也要流动.]
微信:TiensC
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 博客之星2020 设计师:CY__0809 返回首页