乐于分享
好东西不私藏

源码分析:Jsonrpc的标准|泛化调用执行流程

源码分析:Jsonrpc的标准|泛化调用执行流程

背景

在jsonrpc的服务化调用中,如果客户端使用多种调用姿势,比如jsonrpc的标准调用、jsonrpc的泛化调用同时存在,那么服务端必须能够同时对这两种典型的调用的方式进行兼容。不用担心,jsonrpc做到了和spring的web框架可以完美集成,比如服务端使用jsonrpc与springboot进行集成。

这里解释一下什么是jsonrpc的泛化调用?简单说,就是对jsonrpc的传输协议进行改造并进行http调用,让服务端以传统webController的方式接收请求。

那jsonrpc的标准调用又是什么?这里就不对jsonrpc的基础使用姿势进行说明,不熟悉的同学可以自己补一下相关的基础知识:https://github.com/briandilley/jsonrpc4j

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 */@Nullableprotected 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也同样没有实现这个抽象的Abstract

HandlerMethodAdapter的handle方法,使用抽象类中的handle方法。

/** * This implementation expects the handler to be an {@link HandlerMethod}. */@Override@Nullablepublic 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方法上。

到此,基于jsonrpc的标准调用和泛化调用源码执行流程就分析完毕了!

欢迎大家提出自己的想法和问题!留言区等你!

本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » 源码分析:Jsonrpc的标准|泛化调用执行流程

评论 抢沙发

9 + 9 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
×
订阅图标按钮