| <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Apache Dubbo – 协议规范</title><link>https://dubbo.apache.org/zh-cn/overview/reference/protocols/</link><description>Recent content in 协议规范 on Apache Dubbo</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><atom:link href="https://dubbo.apache.org/zh-cn/overview/reference/protocols/index.xml" rel="self" type="application/rss+xml"/><item><title>Overview: Triple 协议设计理念与规范</title><link>https://dubbo.apache.org/zh-cn/overview/reference/protocols/triple-spec/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/reference/protocols/triple-spec/</guid><description> |
| <h2 id="1-协议设计理念">1 协议设计理念</h2> |
| <p>Triple 协议的设计参考了 gRPC、gRPC-Web、通用 HTTP 等多种协议模式,吸取每个协议各自的特性和优点,最终设计成为一个易于浏览器访问、完全兼容 gRPC 且支持 Streaming 通信的协议,Triple 支持同时运行在 HTTP/1、HTTP/2 协议之上。</p> |
| <p>Triple 协议的设计目标如下:</p> |
| <ul> |
| <li>Triple 设计为对人类、开发调试友好的一款基于 HTTP 的协议,尤其是对 unary 类型的 RPC 请求。</li> |
| <li>完全兼容基于 HTTP/2 的 gRPC 协议,因此 Dubbo Triple 协议实现可以 100% 与 gRPC 体系互调互通。</li> |
| <li>仅依赖标准的、被广泛使用的 HTTP 特性,以便在实现层面可以直接依赖官方的标准 HTTP 网络库。</li> |
| </ul> |
| <p>当与 Protocol Buffers 一起使用时(即使用 IDL 定义服务),Triple 协议可支持 unary、client-streaming、server-streaming 和 bi-streaming RPC 通信模式,支持二进制 Protobuf、JSON 两种数据格式 payload。 Triple 实现并不绑定 Protocol Buffers,比如你可以使用 Java 接口定义服务,Triple 协议有对这种模式的扩展 Content-type 支持。</p> |
| <h2 id="2-示例">2 示例</h2> |
| <h3 id="21-unary-请求">2.1 Unary 请求</h3> |
| <p>以 HTTP/1 请求为例,目前 HTTP/1 协议仅支持 Unary RPC,支持使用 application/proto 和 application/json 编码类型,使用方式与 REST 风格请求保持一致,同时响应也包含常规的 HTTP 响应编码(如 200 OK)。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>&gt; POST /org.apache.dubbo.demo.GreetService/Greet HTTP/1.1 |
| </span></span><span style="display:flex;"><span>&gt; Host: 127.0.0.1:30551 |
| </span></span><span style="display:flex;"><span>&gt; Content-Type: application/json |
| </span></span><span style="display:flex;"><span>&gt; |
| </span></span><span style="display:flex;"><span>&gt; [&#34;Dubbo&#34;] |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>&lt; HTTP/1.1 200 OK |
| </span></span><span style="display:flex;"><span>&lt; Content-Type: application/json |
| </span></span><span style="display:flex;"><span>&lt; |
| </span></span><span style="display:flex;"><span>&lt; {&#34;greeting&#34;: &#34;Hello, Dubbo!&#34;} |
| </span></span></code></pre></div><p>一个包含指定超时时间的调用请求。</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>&gt; POST /org.apache.dubbo.demo.GreetService/Greet HTTP/1.1 |
| </span></span><span style="display:flex;"><span>&gt; Host: 127.0.0.1:30551 |
| </span></span><span style="display:flex;"><span>&gt; Content-Type: application/json |
| </span></span><span style="display:flex;"><span>&gt; Rest-service-timeout: 5000 |
| </span></span><span style="display:flex;"><span>&gt; |
| </span></span><span style="display:flex;"><span>&gt; [&#34;Dubbo&#34;] |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>&lt; HTTP/1.1 200 OK |
| </span></span><span style="display:flex;"><span>&lt; Content-Type: application/json |
| </span></span><span style="display:flex;"><span>&lt; |
| </span></span><span style="display:flex;"><span>&lt; {&#34;greeting&#34;: &#34;Hello, Buf!&#34;} |
| </span></span></code></pre></div><blockquote> |
| <p>目前仅支持 POST 请求类型,我们将考虑在未来支持 GET 请求类型,GET 请求可能适用于具有幂等属性的一些服务调用。</p> |
| </blockquote> |
| <h3 id="22-streaming-调用请求">2.2 Streaming 调用请求</h3> |
| <p>Triple 仅支持在 HTTP/2 上支持 Streaming RPC。并且为了与 gRPC 协议保持兼容,Triple 在 HTTP/2 协议实现上(包含 Streaming RPC)保持与标准 gRPC 协议完全一致。</p> |
| <p>Request</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>HEADERS (flags = END_HEADERS) |
| </span></span><span style="display:flex;"><span>:method = POST |
| </span></span><span style="display:flex;"><span>:scheme = http |
| </span></span><span style="display:flex;"><span>:path = /google.pubsub.v2.PublisherService/CreateTopic |
| </span></span><span style="display:flex;"><span>:authority = pubsub.googleapis.com |
| </span></span><span style="display:flex;"><span>grpc-timeout = 1S |
| </span></span><span style="display:flex;"><span>content-type = application/grpc+proto |
| </span></span><span style="display:flex;"><span>grpc-encoding = gzip |
| </span></span><span style="display:flex;"><span>authorization = Bearer y235.wef315yfh138vh31hv93hv8h3v |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>DATA (flags = END_STREAM) |
| </span></span><span style="display:flex;"><span>&lt;Length-Prefixed Message&gt; |
| </span></span></code></pre></div><p>Response</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>HEADERS (flags = END_HEADERS) |
| </span></span><span style="display:flex;"><span>:status = 200 |
| </span></span><span style="display:flex;"><span>grpc-encoding = gzip |
| </span></span><span style="display:flex;"><span>content-type = application/grpc+proto |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>DATA |
| </span></span><span style="display:flex;"><span>&lt;Length-Prefixed Message&gt; |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>HEADERS (flags = END_STREAM, END_HEADERS) |
| </span></span><span style="display:flex;"><span>grpc-status = 0 # OK |
| </span></span><span style="display:flex;"><span>trace-proto-bin = jher831yy13JHy3hc |
| </span></span></code></pre></div><h2 id="3-规范详情">3 规范详情</h2> |
| <p>Triple 协议支持同时运行在 HTTP/1 和 HTTP/2 协议之上,其包含以下两部分内容:</p> |
| <ol> |
| <li>一套自定义的精简 HTTP RPC 子协议,支持 HTTP/1 和 HTTP/2 作为传输层实现,仅支持 Request-Response 类型的 Unary RPC。</li> |
| <li>一套基于 gRPC 协议的扩展子协议(仍保持和 gRPC 的 100% 兼容),仅支持 HTTP/2 实现,支持 Unary RPC 和 Streaming RPC。</li> |
| </ol> |
| <h3 id="31-triple-之-http-rpc-协议">3.1 Triple 之 HTTP RPC 协议</h3> |
| <p>大部分的 RPC 调用都是 unary (request-response) 模式的,Triple HTTP RPC 协议 unary 模式能很好的满足后端服务间的数据传输需求。同时解决了gRPC协议的痛点,让浏览器、cURL 以及其他一些 HTTP 工具更容易的访问后端服务,即不需要借助代理和gRPC-web,使用标准的 HTTP 协议直接发起调用。</p> |
| <p>Triple HTTP RPC 同时支持 HTTP/1、HTTP/2 作为底层传输层协议,在实现上对应支持的 content-type 类型为 application/json、application/proto</p> |
| <h4 id="311-请求-request">3.1.1 请求 Request</h4> |
| <ul> |
| <li>Request → Request-Headers Bare-Message</li> |
| <li>Request-Headers → Call-Specification *Leading-Metadata</li> |
| <li>Call-Specification → |
| Schema Http-Method Path Http-Host Content-Type TRI-Protocol-Version TRI-Service-Timeout TRI-Service-Version TRI-Service-Group |
| Content-Encoding Accept-Encoding Accept Content-Length</li> |
| <li>Scheme → &ldquo;http&rdquo; / &ldquo;https&rdquo;</li> |
| <li>Http-Method → POST</li> |
| <li>Path → /Service-Name/Method-Name; case-sensitive</li> |
| <li>Service-Name → service interface full classname</li> |
| <li>Method-Name → service interface declared method`s name</li> |
| <li>Http-Host → Target-IP:Target-Port</li> |
| <li>Target-IP → target server ip or domain</li> |
| <li>Target-Port → target server process port</li> |
| <li>Content-Type → “Content-Type: ” “application/” Message-Codec</li> |
| <li>Message-Codec → (“json” / {custom})</li> |
| <li>TRI-Protocol-Version → &ldquo;tri-protocol-version&rdquo; &ldquo;1&rdquo;</li> |
| <li>TRI-Service-Timeout → “tri-service-timeout: ” Timeout-Milliseconds</li> |
| <li>Timeout-Milliseconds → positive integer</li> |
| <li>TRI-Service-Version → “tri-service-version: ” Version</li> |
| <li>Version → dubbo service version</li> |
| <li>TRI-Service-Group → &ldquo;tri-service-group: &quot; Group</li> |
| <li>Group → dubbo service group</li> |
| <li>Content-Encoding → “content-encoding” Content-Coding</li> |
| <li>Content-Coding → “identity” / “gzip” / “br” / “zstd” / {custom}</li> |
| <li>Accept-Encoding → “accept-encoding” Content-Coding *(&rdquo;,&quot; [&quot; “] Content-Coding) ; subset of HTTP quality value syntax</li> |
| <li>Content-Length → length of the encoded payload</li> |
| <li>Leading-Metadata → Custom-Metadata</li> |
| <li>Custom-Metadata → ASCII-Metadata / Binary-Metadata</li> |
| <li>ASCII-Metadata → Header-Name ASCII-Value</li> |
| <li>Binary-Metadata → {Header-Name &ldquo;-bin&rdquo;} {base64-encoded value}</li> |
| <li>Header-Name → 1*( %x30-39 / %x61-7A / &ldquo;_&rdquo; / &ldquo;-&rdquo; / &ldquo;.&rdquo;) ; 0-9 a-z _ - .</li> |
| <li>ASCII-Value → 1*( %x20-%x7E ) ; space &amp; printable ASCII</li> |
| <li>Bare-Message → data that encoded by json or custom and Content-Encoding</li> |
| </ul> |
| <p>Triple 协议请求的仅支持 POST 请求,请求 path 为 interfaceName/methodName,为了实现调用超时机制,需要添加 tri-service-timeout (单位 ms),</p> |
| <p>Dubbo 框架支持基于 <strong>分组(group)</strong> 和 <strong>版本(version)</strong> 的服务隔离机制,因此 Triple 协议中引入了 tri-service-group、tri-service-version 支持。</p> |
| <p><strong>Request-Headers</strong> 以标准的 HTTP header 的形式发送,如果收到的 headers 数量过多,server 可返回相应错误信息。</p> |
| <p><strong>TRI-Protocol-Version</strong> 头用来区分具有相同 Content-Type 的 triple 协议请求和其他协议请求,因为 application/json 格式的 Content-Type 非常普遍。所有的 Dubbo 原生客户端实现都应该在请求中携带 TRI-Protocol-Version,Dubbo 服务端或代理可以选择拒绝没有 TRI-Protocol-Version 的请求并返回 Http-Status 400 错误。</p> |
| <p>如果 Server 不支持 <strong>Message-Codec</strong> 指定的编码格式,则必须返回标准 HTTP 415 编码表明 Unsupported Media Type 异常。</p> |
| <p><strong>Bare-Message</strong> 即请求 payload 的编码格式取决于 Message-Codec 设置:</p> |
| <ul> |
| <li>Message-Codec: json 的场景下,payload 采用有序的数组编码形式,即将 rpc 方法的参数按顺序组装进 Array 后进行 json 序列化,方法参数的位置与数组下标保持一致,当 Triple server 接收到请求体时,根据每个参数的类型进行反序列化成对应的参数数组。对于使用 Protocol Buffer 的情形,payload 则是只有一个 json 对象的数组。</li> |
| <li>Message-Codec: proto 的场景下,Protobuf 生成的 Request 类包含了编码格式,因此将直接使用 Request 对象中的内置编码方式。</li> |
| <li>Message-Codec 支持更多自定义扩展值,请确保框架实现遵循相应的编码与解码约定。</li> |
| </ul> |
| <p>如果 Content-Encoding 指定了相应值,则 payload 是被压缩过的,应该首先进行解压缩后再解析编码数据,Bare-Message 将作为 HTTP Body 在链路上传输。</p> |
| <h5 id="request-报文示例">Request 报文示例</h5> |
| <ul> |
| <li>请求行 |
| <ul> |
| <li>POST /org.apache.dubbo.demo.GreetService/greeting HTTP/1.1</li> |
| </ul> |
| </li> |
| <li>请求头 |
| <ul> |
| <li>Host: 127.0.0.1:30551</li> |
| <li>Content-Type: application/json</li> |
| <li>Accept: application/json</li> |
| <li>Content-Length: 11</li> |
| <li>Accept-Encoding: compress, gzip</li> |
| <li>tri-protocol-version: 1.0.0</li> |
| <li>tri-service-version: 1.0.0</li> |
| <li>tri-service-group: dubbo</li> |
| <li>tri-service-timeout: 3000</li> |
| </ul> |
| </li> |
| <li>请求体 |
| <ul> |
| <li>[{&ldquo;world&rdquo;}]</li> |
| </ul> |
| </li> |
| </ul> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-latex" data-lang="latex"><span style="display:flex;"><span>POST /org.apache.dubbo.demo.GreetService/Greet HTTP/1.1 |
| </span></span><span style="display:flex;"><span>Host: 127.0.0.1:30551 |
| </span></span><span style="display:flex;"><span>Content-Type: application/json |
| </span></span><span style="display:flex;"><span>Accept: application/json |
| </span></span><span style="display:flex;"><span>Content-Length: 11 |
| </span></span><span style="display:flex;"><span>Accept-Encoding: compress, gzip |
| </span></span><span style="display:flex;"><span>tri-protocol-version: 1.0.0 |
| </span></span><span style="display:flex;"><span>tri-service-version: 1.0.0 |
| </span></span><span style="display:flex;"><span>tri-service-group: dubbo |
| </span></span><span style="display:flex;"><span>tri-service-timeout: 3000 |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>[<span style="color:#b58900">{</span>&#34;world&#34;<span style="color:#b58900">}</span>] |
| </span></span></code></pre></div><h4 id="312-响应-response">3.1.2 响应 Response</h4> |
| <ul> |
| <li>Response → Response-Headers *Bare-Message</li> |
| <li>Response-Headers → HTTP-Status Content-Type [Content-Encoding] [Accept-Encoding] *Leading-Metadata *Prefixed-Trailing-Metadata</li> |
| <li>HTTP-Status → 200 /{error code translated to HTTP}</li> |
| <li>Bare-Message → data that encoded by Content-Type and Content-Encoding</li> |
| </ul> |
| <p>对于成功 Response 响应 <strong>HTTP-Status</strong> 是 200,在这种场景下,响应体的 Content-Type 将保持和请求体的 Content-Type 保持一致。<strong>Bare-Message</strong> 就是 RPC 响应的 Payload,以 Content-Type 指定的方式进行编码并且以 Content-Encoding 来压缩(如果指定了 Content-Encoding 的话)。Bare-Message 作为 HTTP response body 发送。</p> |
| <p>异常 Response 响应的 HTTP-Status 是 non-200,并且都是标准的 HTTP status code,在这个场景下,<strong>Content-Type</strong> 必须是 &ldquo;application/json&rdquo;。<strong>Bare-Message</strong> 可以是空的,如果 Bare-Message 有值的话则是一个标准 JSON 格式数据,如果 <strong>Content-Encoding</strong> 有指定的话则是一个压缩过的数据,Bare-Message 作为标准的 HTTP response body 发送回调用方。客户端可以根据以下表格,查询 HTTP-Status 与 RPC status 之间的映射关系,以了解具体的 RPC 错误情况。</p> |
| <h5 id="response-报文格式">Response 报文格式</h5> |
| <p>** 成功响应 **</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-latex" data-lang="latex"><span style="display:flex;"><span>HTTP/1.1 200 OK |
| </span></span><span style="display:flex;"><span>Content-Type: application/json |
| </span></span><span style="display:flex;"><span>Content-Length: 11 |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>hello world |
| </span></span></code></pre></div><p>** 失败响应 **</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-latex" data-lang="latex"><span style="display:flex;"><span>HTTP/1.1 400 Bad Request |
| </span></span><span style="display:flex;"><span>Content-Type: application/json |
| </span></span><span style="display:flex;"><span>Content-Length: 46 |
| </span></span><span style="display:flex;"><span><span style="color:#b58900">{</span>&#34;status&#34;:20,&#34;message&#34;:&#34;request format error&#34;<span style="color:#b58900">}</span> |
| </span></span></code></pre></div><h4 id="313-error-codes">3.1.3 Error Codes</h4> |
| <p>Dubbo 的错误码参考</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span> status http-status message |
| </span></span><span style="display:flex;"><span> 20 200 ok |
| </span></span><span style="display:flex;"><span> 25 400 serialization error |
| </span></span><span style="display:flex;"><span> 30 408 client side timeout |
| </span></span><span style="display:flex;"><span> 31 408 server side timeout |
| </span></span><span style="display:flex;"><span> 35 500 channel inactive, directly return the unfinished requests |
| </span></span><span style="display:flex;"><span> 40 400 request format error |
| </span></span><span style="display:flex;"><span> 50 500 response format error |
| </span></span><span style="display:flex;"><span> 60 404 service not found. |
| </span></span><span style="display:flex;"><span> 70 500 service error |
| </span></span><span style="display:flex;"><span> 80 500 internal server error |
| </span></span><span style="display:flex;"><span> 90 500 internal client error |
| </span></span></code></pre></div><blockquote> |
| <p>Connect 的 HTTP to Error Code 参考</p> |
| <table> |
| <thead> |
| <tr> |
| <th>HTTP Status</th> |
| <th>Inferred Code</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>400 Bad Request</td> |
| <td>invalid_argument</td> |
| </tr> |
| <tr> |
| <td>401 Unauthorized</td> |
| <td>unauthenticated</td> |
| </tr> |
| <tr> |
| <td>403 Forbidden</td> |
| <td>permission_denied</td> |
| </tr> |
| <tr> |
| <td>404 Not Found</td> |
| <td>unimplemented</td> |
| </tr> |
| <tr> |
| <td>408 Request Timeout</td> |
| <td>deadline_exceeded</td> |
| </tr> |
| <tr> |
| <td>409 Conflict</td> |
| <td>aborted</td> |
| </tr> |
| <tr> |
| <td>412 Precondition Failed</td> |
| <td>failed_precondition</td> |
| </tr> |
| <tr> |
| <td>413 Payload Too Large</td> |
| <td>resource_exhausted</td> |
| </tr> |
| <tr> |
| <td>415 Unsupported Media Type</td> |
| <td>internal</td> |
| </tr> |
| <tr> |
| <td>429 Too Many Requests</td> |
| <td>unavailable</td> |
| </tr> |
| <tr> |
| <td>431 Request Header Fields Too Large</td> |
| <td>resource_exhausted</td> |
| </tr> |
| <tr> |
| <td>502 Bad Gateway</td> |
| <td>unavailable</td> |
| </tr> |
| <tr> |
| <td>503 Service Unavailable</td> |
| <td>unavailable</td> |
| </tr> |
| <tr> |
| <td>504 Gateway Timeout</td> |
| <td>unavailable</td> |
| </tr> |
| <tr> |
| <td><em>all others</em></td> |
| <td>unknown</td> |
| </tr> |
| </tbody> |
| </table> |
| </blockquote> |
| <h3 id="32-triple-之扩展版-grpc-协议">3.2 Triple 之扩展版 gRPC 协议</h3> |
| <p>Triple 协议的 Streaming 请求处理完全遵循 gRPC 协议规范,且仅支持 HTTP/2 作为传输层协议。并且后端服务间的 Unary 请求默认采用扩展版 gPRC 协议。</p> |
| <p>Triple 支持的 content-type 类型为标准的 gRPC 类型,包括 application/grpc、application/grpc+proto、application/grpc+json,除此之外,Triple 在实现上还扩展了 application/triple+wrapper 编码格式。</p> |
| <h4 id="321-outline">3.2.1 Outline</h4> |
| <p>The following is the general sequence of message atoms in a GRPC request &amp; response message stream</p> |
| <ul> |
| <li>Request → Request-Headers *Length-Prefixed-Message EOS</li> |
| <li>Response → (Response-Headers *Length-Prefixed-Message Trailers) / Trailers-Only</li> |
| </ul> |
| <h4 id="322-requests">3.2.2 Requests</h4> |
| <ul> |
| <li>Request → Request-Headers *Length-Prefixed-Message EOS</li> |
| </ul> |
| <p>Request-Headers are delivered as HTTP2 headers in HEADERS + CONTINUATION frames.</p> |
| <ul> |
| <li><strong>Request-Headers</strong> → Call-Definition *Custom-Metadata</li> |
| <li><strong>Call-Definition</strong> → Method Scheme Path TE [Authority] [Timeout] Content-Type [Message-Type] [Message-Encoding] [Message-Accept-Encoding] [User-Agent] Service-Version Service-Group Tracing-ID Tracing-Span-ID Cluster-Info</li> |
| <li><strong>Method</strong> → &ldquo;:method POST&rdquo;</li> |
| <li><strong>Scheme</strong> → &ldquo;:scheme &quot; (&ldquo;http&rdquo; / &ldquo;https&rdquo;)</li> |
| <li><strong>Path</strong> → &ldquo;:path&rdquo; &ldquo;/&rdquo; Service-Name &ldquo;/&rdquo; {<em>method name</em>} # But see note below.</li> |
| <li><strong>Service-Name</strong> → {<em>IDL-specific service name</em>}</li> |
| <li><strong>Authority</strong> → &ldquo;:authority&rdquo; {<em>virtual host name of authority</em>}</li> |
| <li><strong>TE</strong> → &ldquo;te&rdquo; &ldquo;trailers&rdquo; # Used to detect incompatible proxies</li> |
| <li><strong>Timeout</strong> → &ldquo;grpc-timeout&rdquo; TimeoutValue TimeoutUnit</li> |
| <li><strong>TimeoutValue</strong> → {<em>positive integer as ASCII string of at most 8 digits</em>}</li> |
| <li><strong>TimeoutUnit</strong> → Hour / Minute / Second / Millisecond / Microsecond / Nanosecond |
| <ul> |
| <li><strong>Hour</strong> → &ldquo;H&rdquo;</li> |
| <li><strong>Minute</strong> → &ldquo;M&rdquo;</li> |
| <li><strong>Second</strong> → &ldquo;S&rdquo;</li> |
| <li><strong>Millisecond</strong> → &ldquo;m&rdquo;</li> |
| <li><strong>Microsecond</strong> → &ldquo;u&rdquo;</li> |
| <li><strong>Nanosecond</strong> → &ldquo;n&rdquo;</li> |
| </ul> |
| </li> |
| <li><strong>Content-Type</strong> → &ldquo;content-type&rdquo; &ldquo;application/grpc&rdquo; [(&quot;+proto&rdquo; / &ldquo;+json&rdquo; / {<em>custom</em>})]</li> |
| <li><strong>Content-Coding</strong> → &ldquo;identity&rdquo; / &ldquo;gzip&rdquo; / &ldquo;deflate&rdquo; / &ldquo;snappy&rdquo; / {<em>custom</em>}</li> |
| <li><a name="message-encoding"></a><strong>Message-Encoding</strong> → &ldquo;grpc-encoding&rdquo; Content-Coding</li> |
| <li><strong>Message-Accept-Encoding</strong> → &ldquo;grpc-accept-encoding&rdquo; Content-Coding *(&quot;,&quot; Content-Coding)</li> |
| <li><strong>User-Agent</strong> → &ldquo;user-agent&rdquo; {<em>structured user-agent string</em>}</li> |
| <li><strong>Message-Type</strong> → &ldquo;grpc-message-type&rdquo; {<em>type name for message schema</em>}</li> |
| <li><strong>Custom-Metadata</strong> → Binary-Header / ASCII-Header</li> |
| <li><strong>Binary-Header</strong> → {Header-Name &ldquo;-bin&rdquo; } {<em>base64 encoded value</em>}</li> |
| <li><strong>ASCII-Header</strong> → Header-Name ASCII-Value</li> |
| <li><strong>Header-Name</strong> → 1*( %x30-39 / %x61-7A / &ldquo;_&rdquo; / &ldquo;-&rdquo; / &ldquo;.&rdquo;) ; 0-9 a-z _ - .</li> |
| <li><strong>ASCII-Value</strong> → 1*( %x20-%x7E ) ; space and printable ASCII</li> |
| <li>Service-Version → &ldquo;tri-service-version&rdquo; {Dubbo service version}</li> |
| <li>Service-Group → &ldquo;tri-service-group&rdquo; {Dubbo service group}</li> |
| <li>Tracing-ID → &ldquo;tri-trace-traceid&rdquo; {tracing id}</li> |
| <li>Tracing-RPC-ID → &ldquo;tri-trace-rpcid&rdquo; {_span id _}</li> |
| <li>Cluster-Info → &ldquo;tri-unit-info&rdquo; {cluster infomation}</li> |
| </ul> |
| <h4 id="323-responses">3.2.3 Responses</h4> |
| <ul> |
| <li><strong>Response</strong> → (Response-Headers *Length-Prefixed-Message Trailers) / Trailers-Only</li> |
| <li><strong>Response-Headers</strong> → HTTP-Status [Message-Encoding] [Message-Accept-Encoding] Content-Type *Custom-Metadata</li> |
| <li><strong>Trailers-Only</strong> → HTTP-Status Content-Type Trailers</li> |
| <li><strong>Trailers</strong> → Status [Status-Message] *Custom-Metadata</li> |
| <li><strong>HTTP-Status</strong> → &ldquo;:status 200&rdquo;</li> |
| <li><strong>Status</strong> → &ldquo;grpc-status&rdquo; 1*DIGIT ; 0-9</li> |
| <li><strong>Status-Message</strong> → &ldquo;grpc-message&rdquo; Percent-Encoded</li> |
| <li><strong>Percent-Encoded</strong> → 1*(Percent-Byte-Unencoded / Percent-Byte-Encoded)</li> |
| <li><strong>Percent-Byte-Unencoded</strong> → 1*( %x20-%x24 / %x26-%x7E ) ; space and VCHAR, except %</li> |
| <li><strong>Percent-Byte-Encoded</strong> → &ldquo;%&rdquo; 2HEXDIGIT ; 0-9 A-F</li> |
| </ul> |
| <p>以上即为 Triple 扩展版本的 gRPC 协议,更多详细规范说明请参照 <a href="https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md" target="_blank">gRPC 协议规范</a>。</p></description></item><item><title>Overview: Triple 协议优势与目标</title><link>https://dubbo.apache.org/zh-cn/overview/reference/protocols/triple/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/reference/protocols/triple/</guid><description> |
| <h2 id="简介">简介</h2> |
| <p>Triple 协议是 Dubbo3 设计的基于 HTTP 的 RPC 通信协议规范,它完全兼容 gRPC 协议,支持 Request-Response、Streaming 流式等通信模型,可同时运行在 HTTP/1 和 HTTP/2 之上。</p> |
| <p>Dubbo 框架提供了 Triple 协议的多种语言实现,它们可以帮助你构建浏览器、gRPC 兼容的 HTTP API 接口:你只需要定义一个标准的 Protocol Buffer 格式的服务并实现业务逻辑,Dubbo 负责帮助生成语言相关的 Server Stub、Client Stub,并将整个调用流程无缝接入如路由、服务发现等 Dubbo 体系。Go、Java 等语言的 Triple 协议实现原生支持 HTTP/1 传输层通信,相比于 gRPC 官方实现,Dubbo 框架提供的协议实现更简单、更稳定,帮助你更容易的开发和治理微服务应用。</p> |
| <p>针对某些语言版本,Dubbo 框架还提供了更贴合语言特性的编程模式,即不绑定 IDL 的服务定义与开发模式,比如在 Dubbo Java 中,你可以选择使用 Java Interface 和 Pojo 类定义 Dubbo 服务,并将其发布为基于 Triple 协议通信的微服务。</p> |
| <h2 id="协议规范specification">协议规范(Specification)</h2> |
| <p>基于 Triple 协议,你可以实现以下目标:</p> |
| <h3 id="当-dubbo-作为-client-时">当 Dubbo 作为 Client 时</h3> |
| <p>Dubbo Client 可以访问 Dubbo 服务端 (Server) 发布的 Triple 协议服务,同时还可以访问标准的 gRPC 服务端。</p> |
| <ul> |
| <li>调用标准 gRPC 服务端,发送 Content-type 为标准 gRPC 类型的请求:application/grpc, application/grpc+proto, and application/grpc+json</li> |
| <li>调用 Dubbo 服务端,发送 Content-type 为 Triple 类型的请求:application/json, application/proto, application/triple+wrapper</li> |
| </ul> |
| <h3 id="当-dubbo-作为-server-时">当 Dubbo 作为 Server 时</h3> |
| <p>Dubbo Server 默认将同时发布对 Triple、gRPC 协议的支持,并且 Triple 协议可以同时工作在 HTTP/1、HTTP/2 之上。因此,Dubbo Server 可以处理 Dubbo 客户端发过来的 Triple 协议请求,可以处理标准的 gRPC 协议请求,还能处理 cURL、浏览器发送过来的 HTTP 请求。以 Content-type 区分就是:</p> |
| <ul> |
| <li>处理 gRPC 客户端发送的 Content-type 为标准 gRPC 类型的请求:application/grpc、application/grpc+proto、application/grpc+json</li> |
| <li>处理 Dubbo 客户端发送的 Content-type 为 Triple 类型的请求:application/json、application/proto、application/grpc+wrapper</li> |
| <li>处理 cURL、浏览器等发送的 Content-type 为 Triple 类型的请求:application/json、application/proto、application/grpc+wrapper</li> |
| </ul> |
| <p>详细在此查看详细的 <a href="../triple-spec">Triple Specification</a>。</p> |
| <h2 id="与-grpc-协议的关系">与 gRPC 协议的关系</h2> |
| <p>上面提到 Triple 完全兼容 gRPC 协议,那既然 gRPC 官方已经提供了多语言的框架实现,为什么 Dubbo 还要通过 Triple 重新实现一遍那?核心目标主要有以下两点:</p> |
| <ul> |
| <li>首先,在协议设计上,Dubbo 参考 gRPC 与 gRPC-Web 两个协议设计了自定义的 Triple 协议:Triple 是一个基于 HTTP 传输层协议的 RPC 协议,它完全兼容 gRPC 的同时可运行在 HTTP/1、HTTP/2 之上。</li> |
| <li>其次,Dubbo 框架在每个语言的实现过程中遵循了符合框架自身定位的设计理念,相比于 grpc-java、grpc-go 等框架库,Dubbo 协议实现更简单、更纯粹,尝试在实现上规避 gRPC 官方库中存在的一系列问题。</li> |
| </ul> |
| <p>gRPC 本身作为 RPC 协议规范非常优秀,但我们发现原生的 gRPC 库实现在实际使用存在一系列问题,包括实现复杂、绑定 IDL、难以调试等,Dubbo 在协议设计与实现上从实践出发,很好的规避了这些问题:</p> |
| <ul> |
| <li>原生的 gRPC 实现受限于 HTTP/2 交互规范,无法为浏览器、HTTP API 提供交互方式,你需要额外的代理组件如 grpc-web、grpc-gateway 等才能实现。在 Dubbo 中,你可以直接用 curl、浏览器访问 Dubbo HTTP/2 服务.</li> |
| <li>gRPC 官方库强制绑定 Proto Buffer,唯一的开发选择就是使用 IDL 定义和管理服务,这对于一些多语言诉求不强的用户是一个非常大的使用负担。Dubbo 则在支持 IDL 的同时,为 Java、Go 等提供了语言特有的服务定义与开发方式。</li> |
| <li>在开发阶段,以 gRPC 协议发布的服务非常难以调试,你只能使用 gRPC 特定的工具来进行,很多工具都比较简陋 &amp; 不成熟。而从 Dubbo3 开始,你可以直接使用 curl | jq 或者 Chrome 开发者工具来调试你的服务,直接传入 JSON 结构体就能调用服务。</li> |
| <li>首先,gRPC 协议库有超过 10 万行代码的规模,但 Dubbo (Go、Java、Rust、Node.js 等) 关于协议实现部分仅有几千行代码,这让代码维护和问题排查变得更简单。</li> |
| <li>谷歌提供的 gRPC 实现库没有使用主流的第三方或语言官方协议库,而是选择自己维护了一套实现,让整个维护与生态扩展变得更加复杂。比如 grpc-go 自己维护了一套 HTTP/2 库而不是使用的 go 官方库。Dubbo 使用了官方库的同时,相比 gRPC 自行维护的 http 协议库维持了同一性能水准。</li> |
| <li>gRPC 库仅仅提供了 RPC 协议实现,需要你做很多额外工作为其引入服务治理能力。而 Dubbo 本身是不绑定协议的微服务开发框架,内置 HTTP/2 协议实现可以与 Dubbo 服务治理能力更好的衔接在一起。</li> |
| </ul> |
| <h3 id="实现简单">实现简单</h3> |
| <p>Dubbo 框架实现专注在 Triple 协议自身,而对于底层的网络通信、HTTP/2 协议解析等选择依赖那些经过长期检验的网络库。比如 Dubbo Java 基于 Netty 构建,而 Dubbo Go 则是直接使用的 Go 官方 HTTP 库。</p> |
| <p>Dubbo 提供的 Triple 协议实现非常简单,对应 Dubbo 中的 Protocol 组件实现,你可以仅仅花一下午时间就搞清楚 Dubbo 协议的代码实现。</p> |
| <h3 id="大规模生产环境检验">大规模生产环境检验</h3> |
| <p>自 Dubbo3 发布以来,Triple 协议已被广泛应用于阿里巴巴以及众多社区标杆企业,尤其是一些代理、网关互通场景。一方面 Triple 通过大规模生产实践被证实可靠稳定,另一方面 Triple 的简单、易于调试、不绑定 IDL 的设计也是其得到广泛应用的重要因素。</p> |
| <h3 id="原生多协议支持">原生多协议支持</h3> |
| <p>当以 Dubbo 框架为服务端对外发布服务时,可以做到在同一端口原生支持 Triple、gRPC 和 HTTP/1 协议,这意味着你可以用多种形式访问 Dubbo 服务端发布的服务,所有请求形式最终都会被转发到相同的业务逻辑实现,这给你提供了更大的灵活性。</p> |
| <p>Dubbo 完全兼容 gRPC 协议及相关特性包括 streaming、trailers、error details 等,你选择直接在 Dubbo 框架中使用 Triple 协议(另外,你也可以选择使用原生的 gRPC 协议),然后你就可以直接使用 Dubbo 客户端、curl、浏览器等访问你发布的服务。在与 gRPC 生态互操作性方面,任何标准的 gRPC 客户端,都可以正常访问 Dubbo 服务;Dubbo 客户端也可以调用任何标准的 gRPC 服务,这里有提供的 <a href="https://github.com/apache/dubbo-samples/tree/master/3-extensions/protocol/dubbo-samples-triple/src/main/java/org/apache/dubbo/sample/tri/interop">互操作性示例</a></p> |
| <p>以下是使用 cURL 客户端访问 Dubbo 服务端 Triple 协议服务的示例:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>curl <span style="color:#cb4b16">\ |
| </span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span> --header <span style="color:#2aa198">&#34;Content-Type: application/json&#34;</span> <span style="color:#cb4b16">\ |
| </span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span> --data <span style="color:#2aa198">&#39;{&#34;sentence&#34;: &#34;Hello Dubbo.&#34;}&#39;</span> <span style="color:#cb4b16">\ |
| </span></span></span><span style="display:flex;"><span><span style="color:#cb4b16"></span> https://host:port/org.apache.dubbo.sample.GreetService/sayHello |
| </span></span></code></pre></div><h3 id="一站式服务治理接入">一站式服务治理接入</h3> |
| <p>我们都知道 Dubbo 有丰富的微服务治理能力,比如服务发现、负载均衡、流量管控等,这也是我们使用 Dubbo 框架开发应用的优势所在。要想在 Dubbo 体系下使用 gRPC 协议通信,有两种方式可以实现,一种是直接在 Dubbo 框架中引入 gRPC 官方发布的二进制包,另一种是在 Dubbo 内原生提供 gRPC 协议兼容的源码实现。</p> |
| <p>相比于第一种引入二进制依赖的方式,Dubbo 框架通过内置 Triple 协议实现的方式,原生支持了 gRPC 协议,这种方式的优势在于源码完全由自己掌控,因此协议的实现与 Dubbo 框架结合更为紧密,能够更灵活的接入 Dubbo 的服务治理体系。</p> |
| <h3 id="java-语言">Java 语言</h3> |
| <p>在 Dubbo Java 库实现中,除了 IDL 方式外,你可以使用 Java Interface 方式定义服务,这对于众多熟悉 Dubbo 体系的 Java 用户来说,可以大大降低使用 gRPC 协议的成本。</p> |
| <p>另外,Java 版本的协议实现在性能上与 grpc-java 库基本持平,甚至某些场景下比 grpc-java 性能表现还要出色。而这一切还是建立在 Dubbo 版本协议的实现复杂度远小于 gRPC 版本的情况下,因为 grpc-java 维护了一套定制版本的 netty 协议实现。</p> |
| <h3 id="go-语言实现">Go 语言实现</h3> |
| <p>Dubbo Go 推荐 IDL 开发模式,通过 Dubbo 配套的 protoc 插件生成 stub 代码,你只需要提供对应的业务逻辑实现即可,你可以通过 curl、浏览器访问 Dubbo Go 发布的 gRPC 服务。</p> |
| <h2 id="后续规划">后续规划</h2> |
| <p>当前我们已经提供了 Triple 协议的 Java、Go 语言版本,接下来我们计划陆续提供 Rust、Python、Node.js 等语言的对应实现。</p></description></item><item><title>Overview: Dubbo2 协议规范</title><link>https://dubbo.apache.org/zh-cn/overview/reference/protocols/tcp/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/reference/protocols/tcp/</guid><description> |
| <p><img src="https://dubbo.apache.org/imgs/dev/dubbo_protocol_header.png" alt="/dev-guide/images/dubbo_protocol_header.jpg"></p> |
| <h2 id="协议规范-specification">协议规范 Specification</h2> |
| <ul> |
| <li> |
| <p>Magic - Magic High &amp; Magic Low (16 bits)</p> |
| <p>标识协议版本号,Dubbo 协议:0xdabb</p> |
| </li> |
| <li> |
| <p>Req/Res (1 bit)</p> |
| <p>标识是请求或响应。请求: 1; 响应: 0。</p> |
| </li> |
| <li> |
| <p>2 Way (1 bit)</p> |
| <p>仅在 Req/Res 为1(请求)时才有用,标记是否期望从服务器返回值。如果需要来自服务器的返回值,则设置为1。</p> |
| </li> |
| <li> |
| <p>Event (1 bit)</p> |
| <p>标识是否是事件消息,例如,心跳事件。如果这是一个事件,则设置为1。</p> |
| </li> |
| <li> |
| <p>Serialization ID (5 bit)</p> |
| <p>标识序列化类型:比如 fastjson 的值为6。</p> |
| </li> |
| <li> |
| <p>Status (8 bits)</p> |
| <p>仅在 Req/Res 为0(响应)时有用,用于标识响应的状态。</p> |
| <ul> |
| <li>20 - OK</li> |
| <li>30 - CLIENT_TIMEOUT</li> |
| <li>31 - SERVER_TIMEOUT</li> |
| <li>40 - BAD_REQUEST</li> |
| <li>50 - BAD_RESPONSE</li> |
| <li>60 - SERVICE_NOT_FOUND</li> |
| <li>70 - SERVICE_ERROR</li> |
| <li>80 - SERVER_ERROR</li> |
| <li>90 - CLIENT_ERROR</li> |
| <li>100 - SERVER_THREADPOOL_EXHAUSTED_ERROR</li> |
| </ul> |
| </li> |
| <li> |
| <p>Request ID (64 bits)</p> |
| <p>标识唯一请求。类型为long。</p> |
| </li> |
| <li> |
| <p>Data Length (32 bits)</p> |
| <p>序列化后的内容长度(可变部分),按字节计数。int类型。</p> |
| </li> |
| <li> |
| <p>Variable Part</p> |
| <p>被特定的序列化类型(由序列化 ID 标识)序列化后,每个部分都是一个 byte [] 或者 byte</p> |
| <ul> |
| <li>如果是请求包 ( Req/Res = 1),则每个部分依次为: |
| <ul> |
| <li>Dubbo version</li> |
| <li>Service name</li> |
| <li>Service version</li> |
| <li>Method name</li> |
| <li>Method parameter types</li> |
| <li>Method arguments</li> |
| <li>Attachments</li> |
| </ul> |
| </li> |
| <li>如果是响应包(Req/Res = 0),则每个部分依次为: |
| <ul> |
| <li>返回值类型(byte),标识从服务器端返回的值类型: |
| <ul> |
| <li>返回空值:RESPONSE_NULL_VALUE 2</li> |
| <li>正常响应值: RESPONSE_VALUE 1</li> |
| <li>异常:RESPONSE_WITH_EXCEPTION 0</li> |
| </ul> |
| </li> |
| <li>返回值:从服务端返回的响应bytes</li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| <p><strong>注意:</strong> 对于(Variable Part)变长部分,当前版本的Dubbo 框架使用json序列化时,在每部分内容间额外增加了换行符作为分隔,请在Variable Part的每个part后额外增加换行符, 如:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>Dubbo version bytes (换行符) |
| </span></span><span style="display:flex;"><span>Service name bytes (换行符) |
| </span></span><span style="display:flex;"><span>... |
| </span></span></code></pre></div><h2 id="协议特点分析">协议特点分析</h2> |
| <h3 id="优点">优点</h3> |
| <ul> |
| <li>协议设计上很紧凑,能用 1 个 bit 表示的,不会用一个 byte 来表示,比如 boolean 类型的标识。</li> |
| <li>请求、响应的 header 一致,通过序列化器对 content 组装特定的内容,代码实现起来简单。</li> |
| </ul> |
| <h3 id="可以改进的点">可以改进的点</h3> |
| <ul> |
| <li> |
| <p>对于网关代理类组件不友好。http 请求而言,通过 header 就可以确定要访问的资源,而 Dubbo 需要涉及到用特定序列化协议才可以将服务名、方法、方法签名解析出来,并且这些资源定位符是 string 类型或者 string 数组,很容易转成 bytes,因此可以组装到 header 中。类似于 http2 的 header 压缩,对于 rpc 调用的资源也可以协商出来一个int来标识,从而提升性能,如果在<code>header</code>上组装资源定位符的话,该功能则更易实现。</p> |
| </li> |
| <li> |
| <p>通过 req/res 是否是请求后,可以精细定制协议,去掉一些不需要的标识和添加一些特定的标识。比如<code>status</code>,<code>twoWay</code>标识可以严格定制,去掉冗余标识。还有超时时间是作为 Dubbo 的 <code>attachment</code> 进行传输的,理论上应该放到请求协议的header中,因为超时是网络请求中必不可少的。提到 <code>attachment</code> ,通过实现可以看到 <code>attachment</code> 中有一些是跟协议 <code>content</code>中已有的字段是重复的,比如 <code>path</code>和<code>version</code>等字段,这些会增大协议尺寸。</p> |
| </li> |
| <li> |
| <p>Dubbo 会将服务名<code>com.alibaba.middleware.hsf.guide.api.param.ModifyOrderPriceParam</code>,转换为<code>Lcom/alibaba/middleware/hsf/guide/api/param/ModifyOrderPriceParam;</code>,理论上是不必要的,最后追加一个<code>;</code>即可。</p> |
| </li> |
| <li> |
| <p>Dubbo 协议没有预留扩展字段,没法新增标识,扩展性不太好,比如新增<code>响应上下文</code>的功能,只有改协议版本号的方式,但是这样要求客户端和服务端的版本都进行升级,对于分布式场景很不友好。</p> |
| </li> |
| </ul></description></item><item><title>Overview: HTTP 协议规范</title><link>https://dubbo.apache.org/zh-cn/overview/reference/protocols/http/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://dubbo.apache.org/zh-cn/overview/reference/protocols/http/</guid><description> |
| <h2 id="什么是-dubbo-http">什么是 Dubbo Http</h2> |
| <p>基于 spring web 和 resteasy 注解编码风格,通过http协议进行服务间调用互通,dubbo protocol扩展实现的协议</p> |
| <h2 id="为什么选择dubbo-http">为什么选择Dubbo Http</h2> |
| <ul> |
| <li>dubbo http 可以实现微服务与dubbo之间的互通</li> |
| <li>多协议发布服务,可以实现服务协议的平滑迁移</li> |
| <li>http的通用性,解决跨语言互通</li> |
| <li>最新版本的http 无需添加其他组件,更轻量</li> |
| <li>resteasy以及spring web的编码风格,上手更快</li> |
| </ul> |
| <h2 id="协议规范">协议规范</h2> |
| <ul> |
| <li>Request</li> |
| </ul> |
| <p>相对于原生的http协议dubbo http 请求增加version和group两个header用于确定服务的唯一, |
| 如果provider一端没有声明group和version,http请求时就不需要传递这连个header,反之必须要传递目标 |
| 服务的group和version, 如果使用dubbo http的RestClient这两个header将会默认通过attachment传递 |
| 为区别于其他的header,attachment将会增加rest-service-前缀,因此通过其他形式的http client调用 |
| dubbo http服务需要传递 rest-service-version 和 rest-service-group 两个header</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>POST /test/path HTTP/1.1 |
| </span></span><span style="display:flex;"><span>Host: localhost:8080 |
| </span></span><span style="display:flex;"><span>Content-type: application/json |
| </span></span><span style="display:flex;"><span>Accept: text/html |
| </span></span><span style="display:flex;"><span>rest-service-version: 1.0.0 |
| </span></span><span style="display:flex;"><span>rest-service-group: dubbo |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>{&#34;name&#34;:&#34;dubbo&#34;,&#34;age&#34;:10,&#34;address&#34;:&#34;hangzhou&#34;} |
| </span></span></code></pre></div><ul> |
| <li>Response</li> |
| </ul> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>HTTP/1.1 200 |
| </span></span><span style="display:flex;"><span>Content-Type: text/html |
| </span></span><span style="display:flex;"><span>Content-Length: 4 |
| </span></span><span style="display:flex;"><span>Date: Fri, 28 Apr 2023 14:16:42 GMT |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span>&#34;success&#34; |
| </span></span></code></pre></div><ul> |
| <li>content-type支持 |
| <ul> |
| <li>application/json</li> |
| <li>application/x-www-form-urlencoded</li> |
| <li>text/plain</li> |
| <li>text/xml</li> |
| </ul> |
| </li> |
| </ul> |
| <p>目前支持以上media,后面还会对type进行扩展</p> |
| <h2 id="快速入门">快速入门</h2> |
| <p>详细的依赖以及spring配置,可以参见dubbo 项目的duubo-demo-xml模块 |
| <a href="https://github.com/apache/dubbo/tree/3.2/dubbo-demo/dubbo-demo-xml">https://github.com/apache/dubbo/tree/3.2/dubbo-demo/dubbo-demo-xml</a></p> |
| <ul> |
| <li>spring web 编码 |
| 在使用dubbo http的spring web编码时,类注解我们要求必须出现@RequestMapping或者@Controller,以此来判断用户使用的编码风格,决定使用对应的SpringMvcServiceRestMetadataResolver |
| 注解解析器进行元注解解析,Provider一侧我们允许用户使用实现类作为Dubbo Service(相比之前dubbo service export时service必须是接口的要求)</li> |
| </ul> |
| <p>API</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@RequestMapping</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;/spring/demo/service&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">interface</span> <span style="color:#268bd2">SpringRestDemoService</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@RequestMapping</span><span style="color:#719e07">(</span>method <span style="color:#719e07">=</span> RequestMethod<span style="color:#719e07">.</span>GET<span style="color:#719e07">,</span> value <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;/hello&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> Integer <span style="color:#268bd2">hello</span><span style="color:#719e07">(</span><span style="color:#268bd2">@RequestParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;a&#34;</span><span style="color:#719e07">)</span> Integer a<span style="color:#719e07">,</span> <span style="color:#268bd2">@RequestParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;b&#34;</span><span style="color:#719e07">)</span> Integer b<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@RequestMapping</span><span style="color:#719e07">(</span>method <span style="color:#719e07">=</span> RequestMethod<span style="color:#719e07">.</span>GET<span style="color:#719e07">,</span> value <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;/error&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">error</span><span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@RequestMapping</span><span style="color:#719e07">(</span>method <span style="color:#719e07">=</span> RequestMethod<span style="color:#719e07">.</span>POST<span style="color:#719e07">,</span> value <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;/say&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">sayHello</span><span style="color:#719e07">(</span><span style="color:#268bd2">@RequestBody</span> String name<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@RequestMapping</span><span style="color:#719e07">(</span>method <span style="color:#719e07">=</span> RequestMethod<span style="color:#719e07">.</span>POST<span style="color:#719e07">,</span> value <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;/testFormBody&#34;</span><span style="color:#719e07">,</span> consumes <span style="color:#719e07">=</span> MediaType<span style="color:#719e07">.</span>APPLICATION_FORM_URLENCODED_VALUE<span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> Long <span style="color:#268bd2">testFormBody</span><span style="color:#719e07">(</span><span style="color:#268bd2">@RequestBody</span> Long number<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@RequestMapping</span><span style="color:#719e07">(</span>method <span style="color:#719e07">=</span> RequestMethod<span style="color:#719e07">.</span>POST<span style="color:#719e07">,</span> value <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;/testJavaBeanBody&#34;</span><span style="color:#719e07">,</span> consumes <span style="color:#719e07">=</span> MediaType<span style="color:#719e07">.</span>APPLICATION_FORM_URLENCODED_VALUE<span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> User <span style="color:#268bd2">testJavaBeanBody</span><span style="color:#719e07">(</span><span style="color:#268bd2">@RequestBody</span> User user<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@RequestMapping</span><span style="color:#719e07">(</span>method <span style="color:#719e07">=</span> RequestMethod<span style="color:#719e07">.</span>GET<span style="color:#719e07">,</span> value <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;/primitive&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">int</span> <span style="color:#268bd2">primitiveInt</span><span style="color:#719e07">(</span><span style="color:#268bd2">@RequestParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;a&#34;</span><span style="color:#719e07">)</span> <span style="color:#dc322f">int</span> a<span style="color:#719e07">,</span> <span style="color:#268bd2">@RequestParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;b&#34;</span><span style="color:#719e07">)</span> <span style="color:#dc322f">int</span> b<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@RequestMapping</span><span style="color:#719e07">(</span>method <span style="color:#719e07">=</span> RequestMethod<span style="color:#719e07">.</span>GET<span style="color:#719e07">,</span> value <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;/primitiveLong&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">long</span> <span style="color:#268bd2">primitiveLong</span><span style="color:#719e07">(</span><span style="color:#268bd2">@RequestParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;a&#34;</span><span style="color:#719e07">)</span> <span style="color:#dc322f">long</span> a<span style="color:#719e07">,</span> <span style="color:#268bd2">@RequestParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;b&#34;</span><span style="color:#719e07">)</span> Long b<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@RequestMapping</span><span style="color:#719e07">(</span>method <span style="color:#719e07">=</span> RequestMethod<span style="color:#719e07">.</span>GET<span style="color:#719e07">,</span> value <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;/primitiveByte&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">long</span> <span style="color:#268bd2">primitiveByte</span><span style="color:#719e07">(</span><span style="color:#268bd2">@RequestParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;a&#34;</span><span style="color:#719e07">)</span> <span style="color:#dc322f">byte</span> a<span style="color:#719e07">,</span> <span style="color:#268bd2">@RequestParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;b&#34;</span><span style="color:#719e07">)</span> Long b<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@RequestMapping</span><span style="color:#719e07">(</span>method <span style="color:#719e07">=</span> RequestMethod<span style="color:#719e07">.</span>POST<span style="color:#719e07">,</span> value <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;/primitiveShort&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">long</span> <span style="color:#268bd2">primitiveShort</span><span style="color:#719e07">(</span><span style="color:#268bd2">@RequestParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;a&#34;</span><span style="color:#719e07">)</span> <span style="color:#dc322f">short</span> a<span style="color:#719e07">,</span> <span style="color:#268bd2">@RequestParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;b&#34;</span><span style="color:#719e07">)</span> Long b<span style="color:#719e07">,</span> <span style="color:#268bd2">@RequestBody</span> <span style="color:#dc322f">int</span> c<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@RequestMapping</span><span style="color:#719e07">(</span>method <span style="color:#719e07">=</span> RequestMethod<span style="color:#719e07">.</span>GET<span style="color:#719e07">,</span> value <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;/testMapParam&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">testMapParam</span><span style="color:#719e07">(</span><span style="color:#268bd2">@RequestParam</span> Map<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> String<span style="color:#719e07">&gt;</span> params<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@RequestMapping</span><span style="color:#719e07">(</span>method <span style="color:#719e07">=</span> RequestMethod<span style="color:#719e07">.</span>GET<span style="color:#719e07">,</span> value <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;/testMapHeader&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">testMapHeader</span><span style="color:#719e07">(</span><span style="color:#268bd2">@RequestHeader</span> Map<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> String<span style="color:#719e07">&gt;</span> headers<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@RequestMapping</span><span style="color:#719e07">(</span>method <span style="color:#719e07">=</span> RequestMethod<span style="color:#719e07">.</span>POST<span style="color:#719e07">,</span> value <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;/testMapForm&#34;</span><span style="color:#719e07">,</span> consumes <span style="color:#719e07">=</span> MediaType<span style="color:#719e07">.</span>APPLICATION_FORM_URLENCODED_VALUE<span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> List<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">testMapForm</span><span style="color:#719e07">(</span>MultiValueMap<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> String<span style="color:#719e07">&gt;</span> params<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@RequestMapping</span><span style="color:#719e07">(</span>method <span style="color:#719e07">=</span> RequestMethod<span style="color:#719e07">.</span>GET<span style="color:#719e07">,</span> value <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;/headerInt&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">int</span> <span style="color:#268bd2">headerInt</span><span style="color:#719e07">(</span><span style="color:#268bd2">@RequestHeader</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;header&#34;</span><span style="color:#719e07">)</span> <span style="color:#dc322f">int</span> header<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><p>Provider</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span> <span style="color:#268bd2">@DubboService</span><span style="color:#719e07">(</span>interfaceClass <span style="color:#719e07">=</span> SpringRestDemoService<span style="color:#719e07">.</span>class <span style="color:#719e07">,</span>protocol <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;rest&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">SpringRestDemoServiceImpl</span> <span style="color:#268bd2">implements</span> SpringRestDemoService <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">sayHello</span><span style="color:#719e07">(</span>String name<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;Hello, &#34;</span> <span style="color:#719e07">+</span> name<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> Long <span style="color:#268bd2">testFormBody</span><span style="color:#719e07">(</span>Long number<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> number<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> User <span style="color:#268bd2">testJavaBeanBody</span><span style="color:#719e07">(</span>User user<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> user<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">int</span> <span style="color:#268bd2">primitiveInt</span><span style="color:#719e07">(</span><span style="color:#dc322f">int</span> a<span style="color:#719e07">,</span> <span style="color:#dc322f">int</span> b<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> a <span style="color:#719e07">+</span> b<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">long</span> <span style="color:#268bd2">primitiveLong</span><span style="color:#719e07">(</span><span style="color:#dc322f">long</span> a<span style="color:#719e07">,</span> Long b<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> a <span style="color:#719e07">+</span> b<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">long</span> <span style="color:#268bd2">primitiveByte</span><span style="color:#719e07">(</span><span style="color:#dc322f">byte</span> a<span style="color:#719e07">,</span> Long b<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> a <span style="color:#719e07">+</span> b<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">long</span> <span style="color:#268bd2">primitiveShort</span><span style="color:#719e07">(</span><span style="color:#dc322f">short</span> a<span style="color:#719e07">,</span> Long b<span style="color:#719e07">,</span> <span style="color:#dc322f">int</span> c<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> a <span style="color:#719e07">+</span> b<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">testMapParam</span><span style="color:#719e07">(</span>Map<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> String<span style="color:#719e07">&gt;</span> params<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> params<span style="color:#719e07">.</span>get<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;param&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">testMapHeader</span><span style="color:#719e07">(</span>Map<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> String<span style="color:#719e07">&gt;</span> headers<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> headers<span style="color:#719e07">.</span>get<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;header&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> List<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">testMapForm</span><span style="color:#719e07">(</span>MultiValueMap<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> String<span style="color:#719e07">&gt;</span> params<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> params<span style="color:#719e07">.</span>get<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;form&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">int</span> <span style="color:#268bd2">headerInt</span><span style="color:#719e07">(</span><span style="color:#dc322f">int</span> header<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> header<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> Integer <span style="color:#268bd2">hello</span><span style="color:#719e07">(</span>Integer a<span style="color:#719e07">,</span> Integer b<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> a <span style="color:#719e07">+</span> b<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">error</span><span style="color:#719e07">()</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">throw</span> <span style="color:#719e07">new</span> RuntimeException<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;test error&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><p>Consumer</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@Component</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">SpringRestDemoServiceConsumer</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@DubboReference</span><span style="color:#719e07">(</span>interfaceClass <span style="color:#719e07">=</span> SpringRestDemoService<span style="color:#719e07">.</span>class <span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> SpringRestDemoService springRestDemoService<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">invoke</span><span style="color:#719e07">(){</span> |
| </span></span><span style="display:flex;"><span> String hello <span style="color:#719e07">=</span> springRestDemoService<span style="color:#719e07">.</span>sayHello<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;hello&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> assertEquals<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;Hello, hello&#34;</span><span style="color:#719e07">,</span> hello<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> Integer result <span style="color:#719e07">=</span> springRestDemoService<span style="color:#719e07">.</span>primitiveInt<span style="color:#719e07">(</span>1<span style="color:#719e07">,</span> 2<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> Long resultLong <span style="color:#719e07">=</span> springRestDemoService<span style="color:#719e07">.</span>primitiveLong<span style="color:#719e07">(</span>1<span style="color:#719e07">,</span> 2l<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">long</span> resultByte <span style="color:#719e07">=</span> springRestDemoService<span style="color:#719e07">.</span>primitiveByte<span style="color:#719e07">((</span><span style="color:#dc322f">byte</span><span style="color:#719e07">)</span> 1<span style="color:#719e07">,</span> 2l<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">long</span> resultShort <span style="color:#719e07">=</span> springRestDemoService<span style="color:#719e07">.</span>primitiveShort<span style="color:#719e07">((</span><span style="color:#dc322f">short</span><span style="color:#719e07">)</span> 1<span style="color:#719e07">,</span> 2l<span style="color:#719e07">,</span> 1<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> assertEquals<span style="color:#719e07">(</span>result<span style="color:#719e07">,</span> 3<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> assertEquals<span style="color:#719e07">(</span>resultShort<span style="color:#719e07">,</span> 3l<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> assertEquals<span style="color:#719e07">(</span>resultLong<span style="color:#719e07">,</span> 3l<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> assertEquals<span style="color:#719e07">(</span>resultByte<span style="color:#719e07">,</span> 3l<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> assertEquals<span style="color:#719e07">(</span>Long<span style="color:#719e07">.</span>valueOf<span style="color:#719e07">(</span>1l<span style="color:#719e07">),</span> springRestDemoService<span style="color:#719e07">.</span>testFormBody<span style="color:#719e07">(</span>1l<span style="color:#719e07">));</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> MultiValueMap<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> String<span style="color:#719e07">&gt;</span> forms <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> LinkedMultiValueMap<span style="color:#719e07">&lt;&gt;();</span> |
| </span></span><span style="display:flex;"><span> forms<span style="color:#719e07">.</span>put<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;form&#34;</span><span style="color:#719e07">,</span> Arrays<span style="color:#719e07">.</span>asList<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;F1&#34;</span><span style="color:#719e07">));</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> assertEquals<span style="color:#719e07">(</span>Arrays<span style="color:#719e07">.</span>asList<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;F1&#34;</span><span style="color:#719e07">),</span> springRestDemoService<span style="color:#719e07">.</span>testMapForm<span style="color:#719e07">(</span>forms<span style="color:#719e07">));</span> |
| </span></span><span style="display:flex;"><span> assertEquals<span style="color:#719e07">(</span>User<span style="color:#719e07">.</span>getInstance<span style="color:#719e07">(),</span> springRestDemoService<span style="color:#719e07">.</span>testJavaBeanBody<span style="color:#719e07">(</span>User<span style="color:#719e07">.</span>getInstance<span style="color:#719e07">()));</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">assertEquals</span><span style="color:#719e07">(</span>Object returnStr<span style="color:#719e07">,</span> Object exception<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">boolean</span> equal <span style="color:#719e07">=</span> returnStr <span style="color:#719e07">!=</span> <span style="color:#cb4b16">null</span> <span style="color:#719e07">&amp;&amp;</span> returnStr<span style="color:#719e07">.</span>equals<span style="color:#719e07">(</span>exception<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> <span style="color:#719e07">(</span>equal<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span><span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> <span style="color:#719e07">else</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">throw</span> <span style="color:#719e07">new</span> RuntimeException<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><ul> |
| <li>JaxRs 编码 |
| JaxRs注解使用的时候我们要求service 类上必须使用@Path注解,来确定使用JAXRSServiceRestMetadataResolver |
| 注解解析器来解析注解元信息</li> |
| </ul> |
| <p>API</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@Path</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;/jaxrs/demo/service&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">interface</span> <span style="color:#268bd2">JaxRsRestDemoService</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@GET</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Path</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;/hello&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> Integer <span style="color:#268bd2">hello</span><span style="color:#719e07">(</span><span style="color:#268bd2">@QueryParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;a&#34;</span><span style="color:#719e07">)</span> Integer a<span style="color:#719e07">,</span> <span style="color:#268bd2">@QueryParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;b&#34;</span><span style="color:#719e07">)</span> Integer b<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@GET</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Path</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;/error&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">error</span><span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@POST</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Path</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;/say&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">sayHello</span><span style="color:#719e07">(</span>String name<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@POST</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Path</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;/testFormBody&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> Long <span style="color:#268bd2">testFormBody</span><span style="color:#719e07">(</span><span style="color:#268bd2">@FormParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;number&#34;</span><span style="color:#719e07">)</span> Long number<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@POST</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Path</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;/testJavaBeanBody&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Consumes</span><span style="color:#719e07">({</span>MediaType<span style="color:#719e07">.</span>APPLICATION_JSON<span style="color:#719e07">})</span> |
| </span></span><span style="display:flex;"><span> User <span style="color:#268bd2">testJavaBeanBody</span><span style="color:#719e07">(</span>User user<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@GET</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Path</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;/primitive&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">int</span> <span style="color:#268bd2">primitiveInt</span><span style="color:#719e07">(</span><span style="color:#268bd2">@QueryParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;a&#34;</span><span style="color:#719e07">)</span> <span style="color:#dc322f">int</span> a<span style="color:#719e07">,</span> <span style="color:#268bd2">@QueryParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;b&#34;</span><span style="color:#719e07">)</span> <span style="color:#dc322f">int</span> b<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@GET</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Path</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;/primitiveLong&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">long</span> <span style="color:#268bd2">primitiveLong</span><span style="color:#719e07">(</span><span style="color:#268bd2">@QueryParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;a&#34;</span><span style="color:#719e07">)</span> <span style="color:#dc322f">long</span> a<span style="color:#719e07">,</span> <span style="color:#268bd2">@QueryParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;b&#34;</span><span style="color:#719e07">)</span> Long b<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@GET</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Path</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;/primitiveByte&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">long</span> <span style="color:#268bd2">primitiveByte</span><span style="color:#719e07">(</span><span style="color:#268bd2">@QueryParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;a&#34;</span><span style="color:#719e07">)</span> <span style="color:#dc322f">byte</span> a<span style="color:#719e07">,</span> <span style="color:#268bd2">@QueryParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;b&#34;</span><span style="color:#719e07">)</span> Long b<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@POST</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Path</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;/primitiveShort&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">long</span> <span style="color:#268bd2">primitiveShort</span><span style="color:#719e07">(</span><span style="color:#268bd2">@QueryParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;a&#34;</span><span style="color:#719e07">)</span> <span style="color:#dc322f">short</span> a<span style="color:#719e07">,</span> <span style="color:#268bd2">@QueryParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;b&#34;</span><span style="color:#719e07">)</span> Long b<span style="color:#719e07">,</span> <span style="color:#dc322f">int</span> c<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@GET</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Path</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;testMapParam&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Produces</span><span style="color:#719e07">({</span>MediaType<span style="color:#719e07">.</span>TEXT_PLAIN<span style="color:#719e07">})</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Consumes</span><span style="color:#719e07">({</span>MediaType<span style="color:#719e07">.</span>TEXT_PLAIN<span style="color:#719e07">})</span> |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">testMapParam</span><span style="color:#719e07">(</span><span style="color:#268bd2">@QueryParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;test&#34;</span><span style="color:#719e07">)</span> Map<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> String<span style="color:#719e07">&gt;</span> params<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@GET</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Path</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;testMapHeader&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Produces</span><span style="color:#719e07">({</span>MediaType<span style="color:#719e07">.</span>TEXT_PLAIN<span style="color:#719e07">})</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Consumes</span><span style="color:#719e07">({</span>MediaType<span style="color:#719e07">.</span>TEXT_PLAIN<span style="color:#719e07">})</span> |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">testMapHeader</span><span style="color:#719e07">(</span><span style="color:#268bd2">@HeaderParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;test&#34;</span><span style="color:#719e07">)</span> Map<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> String<span style="color:#719e07">&gt;</span> headers<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@POST</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Path</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;testMapForm&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Produces</span><span style="color:#719e07">({</span>MediaType<span style="color:#719e07">.</span>APPLICATION_JSON<span style="color:#719e07">})</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Consumes</span><span style="color:#719e07">({</span>MediaType<span style="color:#719e07">.</span>APPLICATION_FORM_URLENCODED<span style="color:#719e07">})</span> |
| </span></span><span style="display:flex;"><span> List<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">testMapForm</span><span style="color:#719e07">(</span>MultivaluedMap<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> String<span style="color:#719e07">&gt;</span> params<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@POST</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Path</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;/header&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Consumes</span><span style="color:#719e07">({</span>MediaType<span style="color:#719e07">.</span>TEXT_PLAIN<span style="color:#719e07">})</span> |
| </span></span><span style="display:flex;"><span> String <span style="color:#268bd2">header</span><span style="color:#719e07">(</span><span style="color:#268bd2">@HeaderParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;header&#34;</span><span style="color:#719e07">)</span> String header<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@POST</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Path</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;/headerInt&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Consumes</span><span style="color:#719e07">({</span>MediaType<span style="color:#719e07">.</span>TEXT_PLAIN<span style="color:#719e07">})</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">int</span> <span style="color:#268bd2">headerInt</span><span style="color:#719e07">(</span><span style="color:#268bd2">@HeaderParam</span><span style="color:#719e07">(</span><span style="color:#2aa198">&#34;header&#34;</span><span style="color:#719e07">)</span> <span style="color:#dc322f">int</span> header<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><p>Provider</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@DubboService</span><span style="color:#719e07">(</span>interfaceClass <span style="color:#719e07">=</span>JaxRsRestDemoService<span style="color:#719e07">.</span>class <span style="color:#719e07">,</span>protocol <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;rest&#34;</span><span style="color:#719e07">,</span>version <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;1.0.0&#34;</span><span style="color:#719e07">,</span>group <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;test&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">JaxRsRestDemoServiceImpl</span> <span style="color:#268bd2">implements</span> JaxRsRestDemoService <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">sayHello</span><span style="color:#719e07">(</span>String name<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;Hello, &#34;</span> <span style="color:#719e07">+</span> name<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> Long <span style="color:#268bd2">testFormBody</span><span style="color:#719e07">(</span>Long number<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> number<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> User <span style="color:#268bd2">testJavaBeanBody</span><span style="color:#719e07">(</span>User user<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> user<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">int</span> <span style="color:#268bd2">primitiveInt</span><span style="color:#719e07">(</span><span style="color:#dc322f">int</span> a<span style="color:#719e07">,</span> <span style="color:#dc322f">int</span> b<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> a <span style="color:#719e07">+</span> b<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">long</span> <span style="color:#268bd2">primitiveLong</span><span style="color:#719e07">(</span><span style="color:#dc322f">long</span> a<span style="color:#719e07">,</span> Long b<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> a <span style="color:#719e07">+</span> b<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">long</span> <span style="color:#268bd2">primitiveByte</span><span style="color:#719e07">(</span><span style="color:#dc322f">byte</span> a<span style="color:#719e07">,</span> Long b<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> a <span style="color:#719e07">+</span> b<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">long</span> <span style="color:#268bd2">primitiveShort</span><span style="color:#719e07">(</span><span style="color:#dc322f">short</span> a<span style="color:#719e07">,</span> Long b<span style="color:#719e07">,</span> <span style="color:#dc322f">int</span> c<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> a <span style="color:#719e07">+</span> b<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">testMapParam</span><span style="color:#719e07">(</span>Map<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> String<span style="color:#719e07">&gt;</span> params<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> params<span style="color:#719e07">.</span>get<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;param&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">testMapHeader</span><span style="color:#719e07">(</span>Map<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> String<span style="color:#719e07">&gt;</span> headers<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> headers<span style="color:#719e07">.</span>get<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;header&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> List<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;</span> <span style="color:#268bd2">testMapForm</span><span style="color:#719e07">(</span>MultivaluedMap<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> String<span style="color:#719e07">&gt;</span> params<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> params<span style="color:#719e07">.</span>get<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;form&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">header</span><span style="color:#719e07">(</span>String header<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> header<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">int</span> <span style="color:#268bd2">headerInt</span><span style="color:#719e07">(</span><span style="color:#dc322f">int</span> header<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> header<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> Integer <span style="color:#268bd2">hello</span><span style="color:#719e07">(</span>Integer a<span style="color:#719e07">,</span> Integer b<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> a <span style="color:#719e07">+</span> b<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">error</span><span style="color:#719e07">()</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">throw</span> <span style="color:#719e07">new</span> RuntimeException<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;test error&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><p>Consumer</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@Component</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">JaxRsRestDemoService</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@DubboReference</span><span style="color:#719e07">(</span>interfaceClass <span style="color:#719e07">=</span> JaxRsRestDemoService<span style="color:#719e07">.</span>class<span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> JaxRsRestDemoService jaxRsRestDemoService<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">jaxRsRestDemoServiceTest</span><span style="color:#719e07">(</span>ClassPathXmlApplicationContext context<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> JaxRsRestDemoService jaxRsRestDemoService <span style="color:#719e07">=</span> context<span style="color:#719e07">.</span>getBean<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;jaxRsRestDemoService&#34;</span><span style="color:#719e07">,</span> JaxRsRestDemoService<span style="color:#719e07">.</span>class<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> String hello <span style="color:#719e07">=</span> jaxRsRestDemoService<span style="color:#719e07">.</span>sayHello<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;hello&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> assertEquals<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;Hello, hello&#34;</span><span style="color:#719e07">,</span> hello<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> Integer result <span style="color:#719e07">=</span> jaxRsRestDemoService<span style="color:#719e07">.</span>primitiveInt<span style="color:#719e07">(</span>1<span style="color:#719e07">,</span> 2<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> Long resultLong <span style="color:#719e07">=</span> jaxRsRestDemoService<span style="color:#719e07">.</span>primitiveLong<span style="color:#719e07">(</span>1<span style="color:#719e07">,</span> 2l<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">long</span> resultByte <span style="color:#719e07">=</span> jaxRsRestDemoService<span style="color:#719e07">.</span>primitiveByte<span style="color:#719e07">((</span><span style="color:#dc322f">byte</span><span style="color:#719e07">)</span> 1<span style="color:#719e07">,</span> 2l<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#dc322f">long</span> resultShort <span style="color:#719e07">=</span> jaxRsRestDemoService<span style="color:#719e07">.</span>primitiveShort<span style="color:#719e07">((</span><span style="color:#dc322f">short</span><span style="color:#719e07">)</span> 1<span style="color:#719e07">,</span> 2l<span style="color:#719e07">,</span> 1<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> assertEquals<span style="color:#719e07">(</span>result<span style="color:#719e07">,</span> 3<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> assertEquals<span style="color:#719e07">(</span>resultShort<span style="color:#719e07">,</span> 3l<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> assertEquals<span style="color:#719e07">(</span>resultLong<span style="color:#719e07">,</span> 3l<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> assertEquals<span style="color:#719e07">(</span>resultByte<span style="color:#719e07">,</span> 3l<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> assertEquals<span style="color:#719e07">(</span>Long<span style="color:#719e07">.</span>valueOf<span style="color:#719e07">(</span>1l<span style="color:#719e07">),</span> jaxRsRestDemoService<span style="color:#719e07">.</span>testFormBody<span style="color:#719e07">(</span>1l<span style="color:#719e07">));</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> MultivaluedMapImpl<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> String<span style="color:#719e07">&gt;</span> forms <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> MultivaluedMapImpl<span style="color:#719e07">&lt;&gt;();</span> |
| </span></span><span style="display:flex;"><span> forms<span style="color:#719e07">.</span>put<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;form&#34;</span><span style="color:#719e07">,</span> Arrays<span style="color:#719e07">.</span>asList<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;F1&#34;</span><span style="color:#719e07">));</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> assertEquals<span style="color:#719e07">(</span>Arrays<span style="color:#719e07">.</span>asList<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;F1&#34;</span><span style="color:#719e07">),</span> jaxRsRestDemoService<span style="color:#719e07">.</span>testMapForm<span style="color:#719e07">(</span>forms<span style="color:#719e07">));</span> |
| </span></span><span style="display:flex;"><span> assertEquals<span style="color:#719e07">(</span>User<span style="color:#719e07">.</span>getInstance<span style="color:#719e07">(),</span> jaxRsRestDemoService<span style="color:#719e07">.</span>testJavaBeanBody<span style="color:#719e07">(</span>User<span style="color:#719e07">.</span>getInstance<span style="color:#719e07">()));</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><h2 id="使用场景">使用场景</h2> |
| <p>因为dubbo http consumer一端实现http 调用的RestClient 实现有三种形式:httpclient,okhttp,URLConnection(jdk内置) |
| 默认请情况下采用okhttp,因此在使用dubbo http 去调用其他http服务时,需要添加引入的依赖有</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>org.apache.dubbo<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>dubbo-rpc-rest<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>${dubbo-rpc-rest_version}<span style="color:#268bd2">&lt;/version&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>com.squareup.okhttp3<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>mockwebserver<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>${okhttp_version}<span style="color:#268bd2">&lt;/version&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> 或 |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;dependency&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;groupId&gt;</span>org.apache.httpcomponents<span style="color:#268bd2">&lt;/groupId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;artifactId&gt;</span>httpclient<span style="color:#268bd2">&lt;/artifactId&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;version&gt;</span>${httpclient_version}<span style="color:#268bd2">&lt;/version&gt;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">&lt;/dependency&gt;</span> |
| </span></span></code></pre></div><ul> |
| <li>微服务服务调用dubbo http</li> |
| </ul> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span><span style="color:#586e75">/** |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"> * URL rest://localhost:8888/services |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"> * rest: protocol |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"> * localhost:8888: server address |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"> * services: context path |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"> */</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">@DubboReference</span><span style="color:#719e07">(</span>interfaceClass <span style="color:#719e07">=</span> HttpService<span style="color:#719e07">.</span>class <span style="color:#719e07">,</span>url <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;rest://localhost:8888/services&#34;</span><span style="color:#719e07">,</span>version <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;1.0.0&#34;</span><span style="color:#719e07">,</span>group <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;test&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span> HttpService httpService<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">invokeHttpService</span><span style="color:#719e07">()</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> String http <span style="color:#719e07">=</span> httpService<span style="color:#719e07">.</span>http<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;Others Java Architecture Invoke Dubbo Rest&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> System<span style="color:#719e07">.</span>out<span style="color:#719e07">.</span>println<span style="color:#719e07">(</span>http<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span></code></pre></div><ul> |
| <li> |
| <p>跨语言调用</p> |
| <p>python</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>import requests |
| </span></span><span style="display:flex;"><span> url = &#39;http://localhost:8888/services/curl&#39; |
| </span></span><span style="display:flex;"><span> headers = { |
| </span></span><span style="display:flex;"><span> &#39;rest-service-group&#39;: &#39;test&#39;, |
| </span></span><span style="display:flex;"><span> &#39;rest-service-version&#39;: &#39;1.0.0&#39; |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span>response = requests.get(url, headers=headers) |
| </span></span></code></pre></div><p>go</p> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span> import ( |
| </span></span><span style="display:flex;"><span> &#34;fmt&#34; |
| </span></span><span style="display:flex;"><span> &#34;net/http&#34; |
| </span></span><span style="display:flex;"><span> ) |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> func main() { |
| </span></span><span style="display:flex;"><span> url := &#34;http://localhost:8888/services/curl&#34; |
| </span></span><span style="display:flex;"><span> req, err := http.NewRequest(&#34;GET&#34;, url, nil) |
| </span></span><span style="display:flex;"><span> if err != nil { |
| </span></span><span style="display:flex;"><span> fmt.Println(&#34;Error creating request:&#34;, err) |
| </span></span><span style="display:flex;"><span> return |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> req.Header.Set(&#34;rest-service-group&#34;, &#34;test&#34;) |
| </span></span><span style="display:flex;"><span> req.Header.Set(&#34;rest-service-version&#34;, &#34;1.0.0&#34;) |
| </span></span><span style="display:flex;"><span> client := &amp;http.Client{} |
| </span></span><span style="display:flex;"><span> resp, err := client.Do(req) |
| </span></span><span style="display:flex;"><span> if err != nil { |
| </span></span><span style="display:flex;"><span> fmt.Println(&#34;Error sending request:&#34;, err) |
| </span></span><span style="display:flex;"><span> return |
| </span></span><span style="display:flex;"><span> } |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> defer resp.Body.Close() |
| </span></span></code></pre></div></li> |
| <li> |
| <p>多协议发布</p> |
| <ul> |
| <li>dubbo 协议的代码使用http 进行数据请求测试</li> |
| <li>服务协议迁移</li> |
| </ul> |
| </li> |
| </ul> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">@DubboService</span><span style="color:#719e07">(</span>interfaceClass <span style="color:#719e07">=</span> HttpService<span style="color:#719e07">.</span>class<span style="color:#719e07">,</span> protocol <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;rest,dubbo&#34;</span><span style="color:#719e07">,</span> version <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;1.0.0&#34;</span><span style="color:#719e07">,</span> group <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;test&#34;</span><span style="color:#719e07">)</span> |
| </span></span><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">HttpServiceImpl</span> <span style="color:#268bd2">implements</span> HttpService <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">http</span><span style="color:#719e07">(</span>String invokeType<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#2aa198">&#34;Rest http request test success! by invokeType: &#34;</span> <span style="color:#719e07">+</span> invokeType<span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><ul> |
| <li>http client组件调用dubbo http(可以不引入 service api)</li> |
| </ul> |
| <div class="highlight"><pre tabindex="0" style="color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#268bd2">public</span> <span style="color:#268bd2">class</span> <span style="color:#268bd2">HttpClientInvoke</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> <span style="color:#268bd2">final</span> String versionHeader <span style="color:#719e07">=</span> RestHeaderEnum<span style="color:#719e07">.</span>VERSION<span style="color:#719e07">.</span>getHeader<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> <span style="color:#268bd2">final</span> String groupHeader <span style="color:#719e07">=</span> RestHeaderEnum<span style="color:#719e07">.</span>GROUP<span style="color:#719e07">.</span>getHeader<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#586e75">/** |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"> * contextPath services |
| </span></span></span><span style="display:flex;"><span><span style="color:#586e75"> */</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> <span style="color:#268bd2">final</span> String url <span style="color:#719e07">=</span> <span style="color:#2aa198">&#34;http://localhost:8888/services/http&#34;</span><span style="color:#719e07">;</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">void</span> <span style="color:#268bd2">httpServiceHttpClientInvoke</span><span style="color:#719e07">()</span> <span style="color:#268bd2">throws</span> IOException <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> CloseableHttpClient httpClient <span style="color:#719e07">=</span> createHttpClient<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> HttpRequestBase httpUriRequest <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> HttpGet<span style="color:#719e07">(</span>url<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> httpUriRequest<span style="color:#719e07">.</span>addHeader<span style="color:#719e07">(</span>versionHeader<span style="color:#719e07">,</span> <span style="color:#2aa198">&#34;1.0.0&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> httpUriRequest<span style="color:#719e07">.</span>addHeader<span style="color:#719e07">(</span>RestConstant<span style="color:#719e07">.</span>ACCEPT<span style="color:#719e07">,</span> <span style="color:#2aa198">&#34;text/plain&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> httpUriRequest<span style="color:#719e07">.</span>addHeader<span style="color:#719e07">(</span>groupHeader<span style="color:#719e07">,</span> <span style="color:#2aa198">&#34;test&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> httpUriRequest<span style="color:#719e07">.</span>addHeader<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;type&#34;</span><span style="color:#719e07">,</span> <span style="color:#2aa198">&#34;Http Client Invoke Dubbo Rest Service&#34;</span><span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> CloseableHttpResponse response <span style="color:#719e07">=</span> httpClient<span style="color:#719e07">.</span>execute<span style="color:#719e07">(</span>httpUriRequest<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> RestResult restResult <span style="color:#719e07">=</span> parseResponse<span style="color:#719e07">(</span>response<span style="color:#719e07">);</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> System<span style="color:#719e07">.</span>out<span style="color:#719e07">.</span>println<span style="color:#719e07">(</span><span style="color:#719e07">new</span> String<span style="color:#719e07">(</span>restResult<span style="color:#719e07">.</span>getBody<span style="color:#719e07">()));</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> RestResult <span style="color:#268bd2">parseResponse</span><span style="color:#719e07">(</span>CloseableHttpResponse response<span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#719e07">new</span> RestResult<span style="color:#719e07">()</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">getContentType</span><span style="color:#719e07">()</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> response<span style="color:#719e07">.</span>getFirstHeader<span style="color:#719e07">(</span><span style="color:#2aa198">&#34;Content-Type&#34;</span><span style="color:#719e07">).</span>getValue<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">byte</span><span style="color:#719e07">[]</span> <span style="color:#268bd2">getBody</span><span style="color:#719e07">()</span> <span style="color:#268bd2">throws</span> IOException <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">if</span> <span style="color:#719e07">(</span>response<span style="color:#719e07">.</span>getEntity<span style="color:#719e07">()</span> <span style="color:#719e07">==</span> <span style="color:#cb4b16">null</span><span style="color:#719e07">)</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> <span style="color:#719e07">new</span> <span style="color:#dc322f">byte</span><span style="color:#719e07">[</span>0<span style="color:#719e07">];</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> IOUtils<span style="color:#719e07">.</span>toByteArray<span style="color:#719e07">(</span>response<span style="color:#719e07">.</span>getEntity<span style="color:#719e07">().</span>getContent<span style="color:#719e07">());</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> Map<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">,</span> List<span style="color:#719e07">&lt;</span>String<span style="color:#719e07">&gt;&gt;</span> <span style="color:#268bd2">headers</span><span style="color:#719e07">()</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> Arrays<span style="color:#719e07">.</span>stream<span style="color:#719e07">(</span>response<span style="color:#719e07">.</span>getAllHeaders<span style="color:#719e07">()).</span>collect<span style="color:#719e07">(</span>Collectors<span style="color:#719e07">.</span>toMap<span style="color:#719e07">(</span>Header<span style="color:#719e07">::</span>getName<span style="color:#719e07">,</span> h <span style="color:#719e07">-&gt;</span> Collections<span style="color:#719e07">.</span>singletonList<span style="color:#719e07">(</span>h<span style="color:#719e07">.</span>getValue<span style="color:#719e07">())));</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">byte</span><span style="color:#719e07">[]</span> <span style="color:#268bd2">getErrorResponse</span><span style="color:#719e07">()</span> <span style="color:#268bd2">throws</span> IOException <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> getBody<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> <span style="color:#dc322f">int</span> <span style="color:#268bd2">getResponseCode</span><span style="color:#719e07">()</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> response<span style="color:#719e07">.</span>getStatusLine<span style="color:#719e07">().</span>getStatusCode<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">@Override</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">public</span> String <span style="color:#268bd2">getMessage</span><span style="color:#719e07">()</span> <span style="color:#268bd2">throws</span> IOException <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> appendErrorMessage<span style="color:#719e07">(</span>response<span style="color:#719e07">.</span>getStatusLine<span style="color:#719e07">().</span>getReasonPhrase<span style="color:#719e07">(),</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">new</span> String<span style="color:#719e07">(</span>getErrorResponse<span style="color:#719e07">()));</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">};</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> |
| </span></span><span style="display:flex;"><span> <span style="color:#268bd2">private</span> CloseableHttpClient <span style="color:#268bd2">createHttpClient</span><span style="color:#719e07">()</span> <span style="color:#719e07">{</span> |
| </span></span><span style="display:flex;"><span> PoolingHttpClientConnectionManager connectionManager <span style="color:#719e07">=</span> <span style="color:#719e07">new</span> PoolingHttpClientConnectionManager<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">return</span> HttpClients<span style="color:#719e07">.</span>custom<span style="color:#719e07">().</span>setConnectionManager<span style="color:#719e07">(</span>connectionManager<span style="color:#719e07">).</span>build<span style="color:#719e07">();</span> |
| </span></span><span style="display:flex;"><span> <span style="color:#719e07">}</span> |
| </span></span><span style="display:flex;"><span><span style="color:#719e07">}</span> |
| </span></span></code></pre></div><h2 id="32-与-30-http-实现对比">3.2 与 3.0 HTTP 实现对比</h2> |
| <p>因为 Dubbo Java 3.2 内部移除了原本 Resteasy 的实现,因此在对 Resteasy 内置的 Response,extend,ExceptionMapper 支持上将会有所变化 |
| ExceptionMapper 转换成了org.apache.dubbo.rpc.protocol.rest.exception.mapper.ExceptionHandler,Response后面也会做适配处理</p> |
| <table> |
| <thead> |
| <tr> |
| <th>版本</th> |
| <th>JaxRs</th> |
| <th>j2ee</th> |
| <th>web容器(tomcat/jetty)</th> |
| <th>spring web</th> |
| <th>http client(okhttp/httpclient/jdk URLConnnection )</th> |
| </tr> |
| </thead> |
| <tbody> |
| <tr> |
| <td>3.0</td> |
| <td>依赖与resteasy的client和server</td> |
| <td>遵循j2ee规范</td> |
| <td>依赖常见web容器</td> |
| <td>不依赖</td> |
| <td>不依赖</td> |
| </tr> |
| <tr> |
| <td>3.2</td> |
| <td>不依赖(仅需要JaxRs注解包)</td> |
| <td>不遵循</td> |
| <td>netty实现的http服务器</td> |
| <td>仅依赖spring web注解</td> |
| <td>内部实现RestClient依赖http client(默认为okhttp)</td> |
| </tr> |
| </tbody> |
| </table></description></item></channel></rss> |