blob: 946f983dd813a6cc3504e7013c24ce3a4c279644 [file] [log] [blame]
<!doctype html><html lang=zh-cn class=no-js><head><meta name=ROBOTS content="INDEX, FOLLOW"><link rel=canonical href=https://dubbo.apache.org/zh-cn/docsv2.7/user/references/protocol/rest/><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name=generator content="Hugo 0.120.4"><link rel="shortcut icon" type=image/png href=/imgs/favicon.png><link rel=apple-touch-icon href=/favicons/apple-touch-icon-180x180.png sizes=180x180><link rel=manifest href=/manifest.webmanifest><title>rest 协议 | Apache Dubbo</title><meta property="og:title" content="rest 协议">
<meta property="og:description" content="rest:// 协议参考手册"><meta property="og:type" content="article"><meta property="og:url" content="https://dubbo.apache.org/zh-cn/docsv2.7/user/references/protocol/rest/"><meta property="article:section" content="docsv2.7"><meta property="article:modified_time" content="2023-03-01T09:48:32+08:00"><meta itemprop=name content="rest 协议"><meta itemprop=description content="rest:// 协议参考手册"><meta itemprop=dateModified content="2023-03-01T09:48:32+08:00"><meta itemprop=wordCount content="930"><meta itemprop=keywords content><meta name=twitter:card content="summary"><meta name=twitter:title content="rest 协议"><meta name=twitter:description content="rest:// 协议参考手册"><script async src="https://www.googletagmanager.com/gtag/js?id=G-1TFHM5YBH0"></script><script>var doNotTrack=!1;if(!doNotTrack){window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments)}gtag("js",new Date),gtag("config","G-1TFHM5YBH0",{anonymize_ip:!1})}</script><link rel=preload href=/scss/main.min.fe7176cbe3102a33d3e8c0c9cec61eb52508abd24a2cc1ae23ccf535a481ffde.css as=style><link href=/scss/main.min.fe7176cbe3102a33d3e8c0c9cec61eb52508abd24a2cc1ae23ccf535a481ffde.css rel=stylesheet integrity><script src=/js/jquery-3.5.1.min.js integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin=anonymous></script><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/@docsearch/css@3><meta name=theme-color content="#326ce5"><link rel=stylesheet href=/css/feature-states.css><meta name=description content="rest:// 协议参考手册"><meta property="og:description" content="rest:// 协议参考手册"><meta name=twitter:description content="rest:// 协议参考手册"><meta property="og:url" content="https://dubbo.apache.org/zh-cn/docsv2.7/user/references/protocol/rest/"><meta property="og:title" content="rest 协议"><meta name=twitter:title content="rest 协议"><meta name=twitter:image:alt content="Apache Dubbo"><meta property="og:type" content="article"><meta name=viewport content="width=device-width"><script async defer src=/js/github-buttons.js></script><link href=/css/community.css rel=stylesheet><link href=/css/contactus.css rel=stylesheet><link href=/css/language.css rel=stylesheet><script src=/js/script.js></script></head><body class="td-page td-documentation"><header><nav class="js-navbar-scroll navbar navbar-expand navbar-dark flex-column flex-md-row td-navbar" data-auto-burger=primary><a class=navbar-brand href=/zh-cn/><span class=navbar-logo></span><span class="text-uppercase font-weight-bold">Apache Dubbo</span></a><div class="td-navbar-nav-scroll ml-md-auto" id=main_navbar><ul class="navbar-nav mt-2 mt-lg-0"><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=/zh-cn/overview/home/><span>文档</span></a></li><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=/zh-cn/blog/><span>博客</span></a></li><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=/zh-cn/download/><span>版本发布</span></a></li><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=/zh-cn/contact/><span>联系社区</span></a></li><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=https://start.dubbo.apache.org/bootstrap.html target=_blank><span>Initializer</span><i class='fas fa-external-link-alt'></i></a></li><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=/zh-cn/github/><span>Github</span><i class='fa-brands fa-github'></i></a></li><li class="nav-item dropdown d-lg-block"><a class="nav-link dropdown-toggle" href=# id=navbarDropdownMenuLink role=button data-toggle=dropdown aria-haspopup=true aria-expanded=false>中文</a><div class="dropdown-menu dropdown-menu-right" aria-labelledby=navbarDropdownMenuLink><a class=dropdown-item href=/en/>English</a></div></li><li class="nav-item dropdown d-lg-block"><div class="nav-item d-none d-lg-block"><div id=docsearch></div></div></li></ul></div></nav><section class="header-hero text-white pb-0 light-text"></section></header><div class="container-fluid td-outer"><div class=td-main><div class="row flex-md-nowrap"><div class="col-12 col-md-3 col-xl-2 td-sidebar d-print-none"><script>$(function(){$("#td-section-nav a").removeClass("active"),$("#td-section-nav #m-zh-cndocsv27userreferencesprotocolrest").addClass("active"),$("#td-section-nav #m-zh-cndocsv27userreferencesprotocolrest-li span").addClass("td-sidebar-nav-active-item"),$("#td-section-nav #m-zh-cndocsv27userreferencesprotocolrest").parents("li").addClass("active-path"),$("#td-section-nav li.active-path").addClass("show"),$("#td-section-nav li.active-path").children("input").prop("checked",!0),$("#td-section-nav #m-zh-cndocsv27userreferencesprotocolrest-li").siblings("li").addClass("show"),$("#td-section-nav #m-zh-cndocsv27userreferencesprotocolrest-li").children("ul").children("li").addClass("show"),$("#td-sidebar-menu").toggleClass("d-none")})</script><div id=td-sidebar-menu class="td-sidebar__inner d-none"><div id=content-mobile><form class="td-sidebar__search d-flex align-items-center"><div id=docsearch></div><button class="btn btn-link td-sidebar__toggle d-md-none p-0 ml-3 fas fa-bars" type=button data-toggle=collapse data-target=#td-section-nav aria-controls=td-docs-nav aria-expanded=false aria-label="Toggle section navigation"></button></form></div><div id=content-desktop></div><nav class="collapse td-sidebar-nav foldable-nav" id=td-section-nav><ul class="td-sidebar-nav__section pr-md-3 ul-0"><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27-li><ul class=ul-1><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27user-li><input type=checkbox id=m-zh-cndocsv27user-check>
<label for=m-zh-cndocsv27user-check><a href=/zh-cn/docsv2.7/user/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27user><span>用户文档</span></a></label><ul class="ul-2 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27userpreface-li><input type=checkbox id=m-zh-cndocsv27userpreface-check>
<label for=m-zh-cndocsv27userpreface-check><a href=/zh-cn/docsv2.7/user/preface/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27userpreface><span>入门介绍</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userprefacebackground-li><input type=checkbox id=m-zh-cndocsv27userprefacebackground-check>
<label for=m-zh-cndocsv27userprefacebackground-check><a href=/zh-cn/docsv2.7/user/preface/background/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userprefacebackground><span>背景</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userprefacerequirements-li><input type=checkbox id=m-zh-cndocsv27userprefacerequirements-check>
<label for=m-zh-cndocsv27userprefacerequirements-check><a href=/zh-cn/docsv2.7/user/preface/requirements/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userprefacerequirements><span>需求</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userprefacearchitecture-li><input type=checkbox id=m-zh-cndocsv27userprefacearchitecture-check>
<label for=m-zh-cndocsv27userprefacearchitecture-check><a href=/zh-cn/docsv2.7/user/preface/architecture/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userprefacearchitecture><span>架构</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userprefaceusage-li><input type=checkbox id=m-zh-cndocsv27userprefaceusage-check>
<label for=m-zh-cndocsv27userprefaceusage-check><a href=/zh-cn/docsv2.7/user/preface/usage/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userprefaceusage><span>用法</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userquick-start-li><input type=checkbox id=m-zh-cndocsv27userquick-start-check>
<label for=m-zh-cndocsv27userquick-start-check><a href=/zh-cn/docsv2.7/user/quick-start/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userquick-start><span>快速开始</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userdependencies-li><input type=checkbox id=m-zh-cndocsv27userdependencies-check>
<label for=m-zh-cndocsv27userdependencies-check><a href=/zh-cn/docsv2.7/user/dependencies/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userdependencies><span>基本依赖</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27usermaturity-li><input type=checkbox id=m-zh-cndocsv27usermaturity-check>
<label for=m-zh-cndocsv27usermaturity-check><a href=/zh-cn/docsv2.7/user/maturity/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27usermaturity><span>成熟度</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27userconfiguration-li><input type=checkbox id=m-zh-cndocsv27userconfiguration-check>
<label for=m-zh-cndocsv27userconfiguration-check><a href=/zh-cn/docsv2.7/user/configuration/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27userconfiguration><span>配置手册</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userconfigurationxml-li><input type=checkbox id=m-zh-cndocsv27userconfigurationxml-check>
<label for=m-zh-cndocsv27userconfigurationxml-check><a href=/zh-cn/docsv2.7/user/configuration/xml/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userconfigurationxml><span>XML 配置</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userconfigurationconfig-center-li><input type=checkbox id=m-zh-cndocsv27userconfigurationconfig-center-check>
<label for=m-zh-cndocsv27userconfigurationconfig-center-check><a href=/zh-cn/docsv2.7/user/configuration/config-center/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userconfigurationconfig-center><span>动态配置中心</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userconfigurationproperties-li><input type=checkbox id=m-zh-cndocsv27userconfigurationproperties-check>
<label for=m-zh-cndocsv27userconfigurationproperties-check><a href=/zh-cn/docsv2.7/user/configuration/properties/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userconfigurationproperties><span>属性配置</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userconfigurationenvironment-variables-li><input type=checkbox id=m-zh-cndocsv27userconfigurationenvironment-variables-check>
<label for=m-zh-cndocsv27userconfigurationenvironment-variables-check><a href=/zh-cn/docsv2.7/user/configuration/environment-variables/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userconfigurationenvironment-variables><span>自动加载环境变量</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userconfigurationapi-li><input type=checkbox id=m-zh-cndocsv27userconfigurationapi-check>
<label for=m-zh-cndocsv27userconfigurationapi-check><a href=/zh-cn/docsv2.7/user/configuration/api/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userconfigurationapi><span>API 配置</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userconfigurationannotation-li><input type=checkbox id=m-zh-cndocsv27userconfigurationannotation-check>
<label for=m-zh-cndocsv27userconfigurationannotation-check><a href=/zh-cn/docsv2.7/user/configuration/annotation/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userconfigurationannotation><span>注解配置</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userconfigurationconfiguration-load-process-li><input type=checkbox id=m-zh-cndocsv27userconfigurationconfiguration-load-process-check>
<label for=m-zh-cndocsv27userconfigurationconfiguration-load-process-check><a href=/zh-cn/docsv2.7/user/configuration/configuration-load-process/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userconfigurationconfiguration-load-process><span>配置加载流程</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27userexamples-li><input type=checkbox id=m-zh-cndocsv27userexamples-check>
<label for=m-zh-cndocsv27userexamples-check><a href=/zh-cn/docsv2.7/user/examples/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27userexamples><span>用法示例</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplese9878de8af95e6aca1e695b0e9858de7bdae-li><input type=checkbox id=m-zh-cndocsv27userexamplese9878de8af95e6aca1e695b0e9858de7bdae-check>
<label for=m-zh-cndocsv27userexamplese9878de8af95e6aca1e695b0e9858de7bdae-check><a href=/zh-cn/docsv2.7/user/examples/%E9%87%8D%E8%AF%95%E6%AC%A1%E6%95%B0%E9%85%8D%E7%BD%AE/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplese9878de8af95e6aca1e695b0e9858de7bdae><span>服务重试</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplespreflight-check-li><input type=checkbox id=m-zh-cndocsv27userexamplespreflight-check-check>
<label for=m-zh-cndocsv27userexamplespreflight-check-check><a href=/zh-cn/docsv2.7/user/examples/preflight-check/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplespreflight-check><span>启动时检查</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesfault-tolerent-strategy-li><input type=checkbox id=m-zh-cndocsv27userexamplesfault-tolerent-strategy-check>
<label for=m-zh-cndocsv27userexamplesfault-tolerent-strategy-check><a href=/zh-cn/docsv2.7/user/examples/fault-tolerent-strategy/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesfault-tolerent-strategy><span>集群容错</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesloadbalance-li><input type=checkbox id=m-zh-cndocsv27userexamplesloadbalance-check>
<label for=m-zh-cndocsv27userexamplesloadbalance-check><a href=/zh-cn/docsv2.7/user/examples/loadbalance/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesloadbalance><span>负载均衡</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesthread-model-li><input type=checkbox id=m-zh-cndocsv27userexamplesthread-model-check>
<label for=m-zh-cndocsv27userexamplesthread-model-check><a href=/zh-cn/docsv2.7/user/examples/thread-model/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesthread-model><span>线程模型</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesexplicit-target-li><input type=checkbox id=m-zh-cndocsv27userexamplesexplicit-target-check>
<label for=m-zh-cndocsv27userexamplesexplicit-target-check><a href=/zh-cn/docsv2.7/user/examples/explicit-target/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesexplicit-target><span>直连提供者</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplessubscribe-only-li><input type=checkbox id=m-zh-cndocsv27userexamplessubscribe-only-check>
<label for=m-zh-cndocsv27userexamplessubscribe-only-check><a href=/zh-cn/docsv2.7/user/examples/subscribe-only/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplessubscribe-only><span>只订阅</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesmulti-protocols-li><input type=checkbox id=m-zh-cndocsv27userexamplesmulti-protocols-check>
<label for=m-zh-cndocsv27userexamplesmulti-protocols-check><a href=/zh-cn/docsv2.7/user/examples/multi-protocols/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesmulti-protocols><span>多协议</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesmulti-registry-li><input type=checkbox id=m-zh-cndocsv27userexamplesmulti-registry-check>
<label for=m-zh-cndocsv27userexamplesmulti-registry-check><a href=/zh-cn/docsv2.7/user/examples/multi-registry/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesmulti-registry><span>多注册中心</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesservice-group-li><input type=checkbox id=m-zh-cndocsv27userexamplesservice-group-check>
<label for=m-zh-cndocsv27userexamplesservice-group-check><a href=/zh-cn/docsv2.7/user/examples/service-group/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesservice-group><span>服务分组</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesstatic-service-li><input type=checkbox id=m-zh-cndocsv27userexamplesstatic-service-check>
<label for=m-zh-cndocsv27userexamplesstatic-service-check><a href=/zh-cn/docsv2.7/user/examples/static-service/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesstatic-service><span>静态服务</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesmulti-versions-li><input type=checkbox id=m-zh-cndocsv27userexamplesmulti-versions-check>
<label for=m-zh-cndocsv27userexamplesmulti-versions-check><a href=/zh-cn/docsv2.7/user/examples/multi-versions/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesmulti-versions><span>多版本</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesgroup-merger-li><input type=checkbox id=m-zh-cndocsv27userexamplesgroup-merger-check>
<label for=m-zh-cndocsv27userexamplesgroup-merger-check><a href=/zh-cn/docsv2.7/user/examples/group-merger/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesgroup-merger><span>分组聚合</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesparameter-validation-li><input type=checkbox id=m-zh-cndocsv27userexamplesparameter-validation-check>
<label for=m-zh-cndocsv27userexamplesparameter-validation-check><a href=/zh-cn/docsv2.7/user/examples/parameter-validation/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesparameter-validation><span>参数验证</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesgeneric-invoke-with-json-li><input type=checkbox id=m-zh-cndocsv27userexamplesgeneric-invoke-with-json-check>
<label for=m-zh-cndocsv27userexamplesgeneric-invoke-with-json-check><a href=/zh-cn/docsv2.7/user/examples/generic-invoke-with-json/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesgeneric-invoke-with-json><span>JSON泛化调用</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesmsgpack-serialization-li><input type=checkbox id=m-zh-cndocsv27userexamplesmsgpack-serialization-check>
<label for=m-zh-cndocsv27userexamplesmsgpack-serialization-check><a href=/zh-cn/docsv2.7/user/examples/msgpack-serialization/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesmsgpack-serialization><span>msgpack序列化</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesprovider-timeout-release-li><input type=checkbox id=m-zh-cndocsv27userexamplesprovider-timeout-release-check>
<label for=m-zh-cndocsv27userexamplesprovider-timeout-release-check><a href=/zh-cn/docsv2.7/user/examples/provider-timeout-release/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesprovider-timeout-release><span>provider超时打断</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesresult-cache-li><input type=checkbox id=m-zh-cndocsv27userexamplesresult-cache-check>
<label for=m-zh-cndocsv27userexamplesresult-cache-check><a href=/zh-cn/docsv2.7/user/examples/result-cache/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesresult-cache><span>结果缓存</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesbroadcast-resp-collect-li><input type=checkbox id=m-zh-cndocsv27userexamplesbroadcast-resp-collect-check>
<label for=m-zh-cndocsv27userexamplesbroadcast-resp-collect-check><a href=/zh-cn/docsv2.7/user/examples/broadcast-resp-collect/ title=收集Dubbo广播响应 class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesbroadcast-resp-collect><span>收集广播响应</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesinvoke-with-specified-ip-li><input type=checkbox id=m-zh-cndocsv27userexamplesinvoke-with-specified-ip-check>
<label for=m-zh-cndocsv27userexamplesinvoke-with-specified-ip-check><a href=/zh-cn/docsv2.7/user/examples/invoke-with-specified-ip/ title="指定Ip Port调用Provider" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesinvoke-with-specified-ip><span>指定IP</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesgeneric-reference-li><input type=checkbox id=m-zh-cndocsv27userexamplesgeneric-reference-check>
<label for=m-zh-cndocsv27userexamplesgeneric-reference-check><a href=/zh-cn/docsv2.7/user/examples/generic-reference/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesgeneric-reference><span>使用泛化调用</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesprotobuf-idl-li><input type=checkbox id=m-zh-cndocsv27userexamplesprotobuf-idl-check>
<label for=m-zh-cndocsv27userexamplesprotobuf-idl-check><a href=/zh-cn/docsv2.7/user/examples/protobuf-idl/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesprotobuf-idl><span>Protobuf</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplespb-generic-reference-li><input type=checkbox id=m-zh-cndocsv27userexamplespb-generic-reference-check>
<label for=m-zh-cndocsv27userexamplespb-generic-reference-check><a href=/zh-cn/docsv2.7/user/examples/pb-generic-reference/ title="GoogleProtobuf 对象泛化调用" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplespb-generic-reference><span>Protobuf 泛化调用</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesgeneric-service-li><input type=checkbox id=m-zh-cndocsv27userexamplesgeneric-service-check>
<label for=m-zh-cndocsv27userexamplesgeneric-service-check><a href=/zh-cn/docsv2.7/user/examples/generic-service/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesgeneric-service><span>实现泛化调用</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesecho-service-li><input type=checkbox id=m-zh-cndocsv27userexamplesecho-service-check>
<label for=m-zh-cndocsv27userexamplesecho-service-check><a href=/zh-cn/docsv2.7/user/examples/echo-service/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesecho-service><span>回声测试</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplescontext-li><input type=checkbox id=m-zh-cndocsv27userexamplescontext-check>
<label for=m-zh-cndocsv27userexamplescontext-check><a href=/zh-cn/docsv2.7/user/examples/context/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplescontext><span>上下文信息</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesattachment-li><input type=checkbox id=m-zh-cndocsv27userexamplesattachment-check>
<label for=m-zh-cndocsv27userexamplesattachment-check><a href=/zh-cn/docsv2.7/user/examples/attachment/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesattachment><span>隐式参数</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesasync-call-li><input type=checkbox id=m-zh-cndocsv27userexamplesasync-call-check>
<label for=m-zh-cndocsv27userexamplesasync-call-check><a href=/zh-cn/docsv2.7/user/examples/async-call/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesasync-call><span>异步调用</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesasync-execute-on-provider-li><input type=checkbox id=m-zh-cndocsv27userexamplesasync-execute-on-provider-check>
<label for=m-zh-cndocsv27userexamplesasync-execute-on-provider-check><a href=/zh-cn/docsv2.7/user/examples/async-execute-on-provider/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesasync-execute-on-provider><span>异步执行</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexampleslocal-call-li><input type=checkbox id=m-zh-cndocsv27userexampleslocal-call-check>
<label for=m-zh-cndocsv27userexampleslocal-call-check><a href=/zh-cn/docsv2.7/user/examples/local-call/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexampleslocal-call><span>本地调用</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplescallback-parameter-li><input type=checkbox id=m-zh-cndocsv27userexamplescallback-parameter-check>
<label for=m-zh-cndocsv27userexamplescallback-parameter-check><a href=/zh-cn/docsv2.7/user/examples/callback-parameter/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplescallback-parameter><span>参数回调</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesevents-notify-li><input type=checkbox id=m-zh-cndocsv27userexamplesevents-notify-check>
<label for=m-zh-cndocsv27userexamplesevents-notify-check><a href=/zh-cn/docsv2.7/user/examples/events-notify/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesevents-notify><span>事件通知</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexampleslocal-stub-li><input type=checkbox id=m-zh-cndocsv27userexampleslocal-stub-check>
<label for=m-zh-cndocsv27userexampleslocal-stub-check><a href=/zh-cn/docsv2.7/user/examples/local-stub/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexampleslocal-stub><span>本地存根</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexampleslocal-mock-li><input type=checkbox id=m-zh-cndocsv27userexampleslocal-mock-check>
<label for=m-zh-cndocsv27userexampleslocal-mock-check><a href=/zh-cn/docsv2.7/user/examples/local-mock/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexampleslocal-mock><span>本地伪装</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesdelay-publish-li><input type=checkbox id=m-zh-cndocsv27userexamplesdelay-publish-check>
<label for=m-zh-cndocsv27userexamplesdelay-publish-check><a href=/zh-cn/docsv2.7/user/examples/delay-publish/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesdelay-publish><span>延迟暴露</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesconcurrency-control-li><input type=checkbox id=m-zh-cndocsv27userexamplesconcurrency-control-check>
<label for=m-zh-cndocsv27userexamplesconcurrency-control-check><a href=/zh-cn/docsv2.7/user/examples/concurrency-control/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesconcurrency-control><span>并发控制</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesconfig-connections-li><input type=checkbox id=m-zh-cndocsv27userexamplesconfig-connections-check>
<label for=m-zh-cndocsv27userexamplesconfig-connections-check><a href=/zh-cn/docsv2.7/user/examples/config-connections/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesconfig-connections><span>连接控制</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexampleslazy-connect-li><input type=checkbox id=m-zh-cndocsv27userexampleslazy-connect-check>
<label for=m-zh-cndocsv27userexampleslazy-connect-check><a href=/zh-cn/docsv2.7/user/examples/lazy-connect/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexampleslazy-connect><span>延迟连接</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesstickiness-li><input type=checkbox id=m-zh-cndocsv27userexamplesstickiness-check>
<label for=m-zh-cndocsv27userexamplesstickiness-check><a href=/zh-cn/docsv2.7/user/examples/stickiness/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesstickiness><span>粘滞连接</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplestls-li><input type=checkbox id=m-zh-cndocsv27userexamplestls-check>
<label for=m-zh-cndocsv27userexamplestls-check><a href=/zh-cn/docsv2.7/user/examples/tls/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplestls><span>TLS</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplestoken-authorization-li><input type=checkbox id=m-zh-cndocsv27userexamplestoken-authorization-check>
<label for=m-zh-cndocsv27userexamplestoken-authorization-check><a href=/zh-cn/docsv2.7/user/examples/token-authorization/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplestoken-authorization><span>令牌验证</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesrouting-rule-li><input type=checkbox id=m-zh-cndocsv27userexamplesrouting-rule-check>
<label for=m-zh-cndocsv27userexamplesrouting-rule-check><a href=/zh-cn/docsv2.7/user/examples/routing-rule/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesrouting-rule><span>路由规则</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesrouting-rule-deprecated-li><input type=checkbox id=m-zh-cndocsv27userexamplesrouting-rule-deprecated-check>
<label for=m-zh-cndocsv27userexamplesrouting-rule-deprecated-check><a href=/zh-cn/docsv2.7/user/examples/routing-rule-deprecated/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesrouting-rule-deprecated><span>旧路由规则</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesconfig-rule-li><input type=checkbox id=m-zh-cndocsv27userexamplesconfig-rule-check>
<label for=m-zh-cndocsv27userexamplesconfig-rule-check><a href=/zh-cn/docsv2.7/user/examples/config-rule/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesconfig-rule><span>配置规则</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesservice-downgrade-li><input type=checkbox id=m-zh-cndocsv27userexamplesservice-downgrade-check>
<label for=m-zh-cndocsv27userexamplesservice-downgrade-check><a href=/zh-cn/docsv2.7/user/examples/service-downgrade/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesservice-downgrade><span>服务降级</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesconfig-rule-deprecated-li><input type=checkbox id=m-zh-cndocsv27userexamplesconfig-rule-deprecated-check>
<label for=m-zh-cndocsv27userexamplesconfig-rule-deprecated-check><a href=/zh-cn/docsv2.7/user/examples/config-rule-deprecated/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesconfig-rule-deprecated><span>旧配置规则</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesconsumer-threadpool-li><input type=checkbox id=m-zh-cndocsv27userexamplesconsumer-threadpool-check>
<label for=m-zh-cndocsv27userexamplesconsumer-threadpool-check><a href=/zh-cn/docsv2.7/user/examples/consumer-threadpool/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesconsumer-threadpool><span>消费端线程池模型</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesgraceful-shutdown-li><input type=checkbox id=m-zh-cndocsv27userexamplesgraceful-shutdown-check>
<label for=m-zh-cndocsv27userexamplesgraceful-shutdown-check><a href=/zh-cn/docsv2.7/user/examples/graceful-shutdown/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesgraceful-shutdown><span>优雅停机</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexampleshostname-binding-li><input type=checkbox id=m-zh-cndocsv27userexampleshostname-binding-check>
<label for=m-zh-cndocsv27userexampleshostname-binding-check><a href=/zh-cn/docsv2.7/user/examples/hostname-binding/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexampleshostname-binding><span>主机绑定</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userexamplesset-host-li><input type=checkbox id=m-zh-cndocsv27userexamplesset-host-check>
<label for=m-zh-cndocsv27userexamplesset-host-check><a href=/zh-cn/docsv2.7/user/examples/set-host/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userexamplesset-host><span>主机配置</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27userreferences-li><input type=checkbox id=m-zh-cndocsv27userreferences-check>
<label for=m-zh-cndocsv27userreferences-check><a href=/zh-cn/docsv2.7/user/references/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27userreferences><span>参考手册</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27userreferencesxml-li><input type=checkbox id=m-zh-cndocsv27userreferencesxml-check>
<label for=m-zh-cndocsv27userreferencesxml-check><a href=/zh-cn/docsv2.7/user/references/xml/ title="Schema 配置参考手册" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27userreferencesxml><span>XML 配置</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesxmldubbo-application-li><input type=checkbox id=m-zh-cndocsv27userreferencesxmldubbo-application-check>
<label for=m-zh-cndocsv27userreferencesxmldubbo-application-check><a href=/zh-cn/docsv2.7/user/references/xml/dubbo-application/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesxmldubbo-application><span>dubbo:application</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesxmldubbo-argument-li><input type=checkbox id=m-zh-cndocsv27userreferencesxmldubbo-argument-check>
<label for=m-zh-cndocsv27userreferencesxmldubbo-argument-check><a href=/zh-cn/docsv2.7/user/references/xml/dubbo-argument/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesxmldubbo-argument><span>dubbo:argument</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesxmldubbo-config-center-li><input type=checkbox id=m-zh-cndocsv27userreferencesxmldubbo-config-center-check>
<label for=m-zh-cndocsv27userreferencesxmldubbo-config-center-check><a href=/zh-cn/docsv2.7/user/references/xml/dubbo-config-center/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesxmldubbo-config-center><span>dubbo:config-center</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesxmldubbo-consumer-li><input type=checkbox id=m-zh-cndocsv27userreferencesxmldubbo-consumer-check>
<label for=m-zh-cndocsv27userreferencesxmldubbo-consumer-check><a href=/zh-cn/docsv2.7/user/references/xml/dubbo-consumer/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesxmldubbo-consumer><span>dubbo:consumer</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesxmldubbo-method-li><input type=checkbox id=m-zh-cndocsv27userreferencesxmldubbo-method-check>
<label for=m-zh-cndocsv27userreferencesxmldubbo-method-check><a href=/zh-cn/docsv2.7/user/references/xml/dubbo-method/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesxmldubbo-method><span>dubbo:method</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesxmldubbo-module-li><input type=checkbox id=m-zh-cndocsv27userreferencesxmldubbo-module-check>
<label for=m-zh-cndocsv27userreferencesxmldubbo-module-check><a href=/zh-cn/docsv2.7/user/references/xml/dubbo-module/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesxmldubbo-module><span>dubbo:module</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesxmldubbo-monitor-li><input type=checkbox id=m-zh-cndocsv27userreferencesxmldubbo-monitor-check>
<label for=m-zh-cndocsv27userreferencesxmldubbo-monitor-check><a href=/zh-cn/docsv2.7/user/references/xml/dubbo-monitor/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesxmldubbo-monitor><span>dubbo:monitor</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesxmldubbo-parameter-li><input type=checkbox id=m-zh-cndocsv27userreferencesxmldubbo-parameter-check>
<label for=m-zh-cndocsv27userreferencesxmldubbo-parameter-check><a href=/zh-cn/docsv2.7/user/references/xml/dubbo-parameter/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesxmldubbo-parameter><span>dubbo:parameter</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesxmldubbo-protocol-li><input type=checkbox id=m-zh-cndocsv27userreferencesxmldubbo-protocol-check>
<label for=m-zh-cndocsv27userreferencesxmldubbo-protocol-check><a href=/zh-cn/docsv2.7/user/references/xml/dubbo-protocol/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesxmldubbo-protocol><span>dubbo:protocol</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesxmldubbo-provider-li><input type=checkbox id=m-zh-cndocsv27userreferencesxmldubbo-provider-check>
<label for=m-zh-cndocsv27userreferencesxmldubbo-provider-check><a href=/zh-cn/docsv2.7/user/references/xml/dubbo-provider/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesxmldubbo-provider><span>dubbo:provider</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesxmldubbo-reference-li><input type=checkbox id=m-zh-cndocsv27userreferencesxmldubbo-reference-check>
<label for=m-zh-cndocsv27userreferencesxmldubbo-reference-check><a href=/zh-cn/docsv2.7/user/references/xml/dubbo-reference/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesxmldubbo-reference><span>dubbo:reference</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesxmldubbo-registry-li><input type=checkbox id=m-zh-cndocsv27userreferencesxmldubbo-registry-check>
<label for=m-zh-cndocsv27userreferencesxmldubbo-registry-check><a href=/zh-cn/docsv2.7/user/references/xml/dubbo-registry/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesxmldubbo-registry><span>dubbo:registry</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesxmldubbo-service-li><input type=checkbox id=m-zh-cndocsv27userreferencesxmldubbo-service-check>
<label for=m-zh-cndocsv27userreferencesxmldubbo-service-check><a href=/zh-cn/docsv2.7/user/references/xml/dubbo-service/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesxmldubbo-service><span>dubbo:service</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27userreferencesprotocol-li><input type=checkbox id=m-zh-cndocsv27userreferencesprotocol-check>
<label for=m-zh-cndocsv27userreferencesprotocol-check><a href=/zh-cn/docsv2.7/user/references/protocol/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27userreferencesprotocol><span>协议参考手册</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesprotocoldubbo-li><input type=checkbox id=m-zh-cndocsv27userreferencesprotocoldubbo-check>
<label for=m-zh-cndocsv27userreferencesprotocoldubbo-check><a href=/zh-cn/docsv2.7/user/references/protocol/dubbo/ title="dubbo 协议" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesprotocoldubbo><span>dubbo://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesprotocolrest-li><input type=checkbox id=m-zh-cndocsv27userreferencesprotocolrest-check>
<label for=m-zh-cndocsv27userreferencesprotocolrest-check><a href=/zh-cn/docsv2.7/user/references/protocol/rest/ title="rest 协议" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesprotocolrest><span>rest://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesprotocolhttp-li><input type=checkbox id=m-zh-cndocsv27userreferencesprotocolhttp-check>
<label for=m-zh-cndocsv27userreferencesprotocolhttp-check><a href=/zh-cn/docsv2.7/user/references/protocol/http/ title="http 协议" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesprotocolhttp><span>http://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesprotocolhessian-li><input type=checkbox id=m-zh-cndocsv27userreferencesprotocolhessian-check>
<label for=m-zh-cndocsv27userreferencesprotocolhessian-check><a href=/zh-cn/docsv2.7/user/references/protocol/hessian/ title="hessian 协议" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesprotocolhessian><span>hessian://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesprotocolredis-li><input type=checkbox id=m-zh-cndocsv27userreferencesprotocolredis-check>
<label for=m-zh-cndocsv27userreferencesprotocolredis-check><a href=/zh-cn/docsv2.7/user/references/protocol/redis/ title="redis 协议" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesprotocolredis><span>redis://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesprotocolthrift-li><input type=checkbox id=m-zh-cndocsv27userreferencesprotocolthrift-check>
<label for=m-zh-cndocsv27userreferencesprotocolthrift-check><a href=/zh-cn/docsv2.7/user/references/protocol/thrift/ title="thrift 协议" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesprotocolthrift><span>thrift://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesprotocolgrpc-li><input type=checkbox id=m-zh-cndocsv27userreferencesprotocolgrpc-check>
<label for=m-zh-cndocsv27userreferencesprotocolgrpc-check><a href=/zh-cn/docsv2.7/user/references/protocol/grpc/ title="gRPC 协议" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesprotocolgrpc><span>grpc://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesprotocolmemcached-li><input type=checkbox id=m-zh-cndocsv27userreferencesprotocolmemcached-check>
<label for=m-zh-cndocsv27userreferencesprotocolmemcached-check><a href=/zh-cn/docsv2.7/user/references/protocol/memcached/ title="memcached 协议" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesprotocolmemcached><span>memcached://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesprotocolrmi-li><input type=checkbox id=m-zh-cndocsv27userreferencesprotocolrmi-check>
<label for=m-zh-cndocsv27userreferencesprotocolrmi-check><a href=/zh-cn/docsv2.7/user/references/protocol/rmi/ title="rmi 协议" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesprotocolrmi><span>rmi://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesprotocolwebservice-li><input type=checkbox id=m-zh-cndocsv27userreferencesprotocolwebservice-check>
<label for=m-zh-cndocsv27userreferencesprotocolwebservice-check><a href=/zh-cn/docsv2.7/user/references/protocol/webservice/ title="webservice 协议" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesprotocolwebservice><span>webservice://</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27userreferencesregistry-li><input type=checkbox id=m-zh-cndocsv27userreferencesregistry-check>
<label for=m-zh-cndocsv27userreferencesregistry-check><a href=/zh-cn/docsv2.7/user/references/registry/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27userreferencesregistry><span>注册中心参考手册</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesregistrynacos-li><input type=checkbox id=m-zh-cndocsv27userreferencesregistrynacos-check>
<label for=m-zh-cndocsv27userreferencesregistrynacos-check><a href=/zh-cn/docsv2.7/user/references/registry/nacos/ title="Nacos 注册中心" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesregistrynacos><span>Nacos</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesregistryzookeeper-li><input type=checkbox id=m-zh-cndocsv27userreferencesregistryzookeeper-check>
<label for=m-zh-cndocsv27userreferencesregistryzookeeper-check><a href=/zh-cn/docsv2.7/user/references/registry/zookeeper/ title="Zookeeper 注册中心" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesregistryzookeeper><span>Zookeeper</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesregistrymulticast-li><input type=checkbox id=m-zh-cndocsv27userreferencesregistrymulticast-check>
<label for=m-zh-cndocsv27userreferencesregistrymulticast-check><a href=/zh-cn/docsv2.7/user/references/registry/multicast/ title="Multicast 注册中心" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesregistrymulticast><span>Multicast</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesregistryredis-li><input type=checkbox id=m-zh-cndocsv27userreferencesregistryredis-check>
<label for=m-zh-cndocsv27userreferencesregistryredis-check><a href=/zh-cn/docsv2.7/user/references/registry/redis/ title="Redis 注册中心" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesregistryredis><span>Redis</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesregistrysimple-li><input type=checkbox id=m-zh-cndocsv27userreferencesregistrysimple-check>
<label for=m-zh-cndocsv27userreferencesregistrysimple-check><a href=/zh-cn/docsv2.7/user/references/registry/simple/ title="Simple 注册中心" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesregistrysimple><span>Simple</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesmetadata-li><input type=checkbox id=m-zh-cndocsv27userreferencesmetadata-check>
<label for=m-zh-cndocsv27userreferencesmetadata-check><a href=/zh-cn/docsv2.7/user/references/metadata/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesmetadata><span>元数据参考手册</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesapi-li><input type=checkbox id=m-zh-cndocsv27userreferencesapi-check>
<label for=m-zh-cndocsv27userreferencesapi-check><a href=/zh-cn/docsv2.7/user/references/api/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesapi><span>API 参考手册</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesqos-li><input type=checkbox id=m-zh-cndocsv27userreferencesqos-check>
<label for=m-zh-cndocsv27userreferencesqos-check><a href=/zh-cn/docsv2.7/user/references/qos/ title=在线运维命令参考手册 class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesqos><span>QOS 手册</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencestelnet-li><input type=checkbox id=m-zh-cndocsv27userreferencestelnet-check>
<label for=m-zh-cndocsv27userreferencestelnet-check><a href=/zh-cn/docsv2.7/user/references/telnet/ title="Telnet 命令参考手册" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencestelnet><span>Telnet 手册</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userreferencesmaven-li><input type=checkbox id=m-zh-cndocsv27userreferencesmaven-check>
<label for=m-zh-cndocsv27userreferencesmaven-check><a href=/zh-cn/docsv2.7/user/references/maven/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userreferencesmaven><span>Maven 插件参考手册</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27userversions-li><input type=checkbox id=m-zh-cndocsv27userversions-check>
<label for=m-zh-cndocsv27userversions-check><a href=/zh-cn/docsv2.7/user/versions/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27userversions><span>版本升级</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userversionsversion-270-li><input type=checkbox id=m-zh-cndocsv27userversionsversion-270-check>
<label for=m-zh-cndocsv27userversionsversion-270-check><a href=/zh-cn/docsv2.7/user/versions/version-270/ title=升级与可能的兼容性问题总结 class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userversionsversion-270><span>2.7.0</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userbest-practice-li><input type=checkbox id=m-zh-cndocsv27userbest-practice-check>
<label for=m-zh-cndocsv27userbest-practice-check><a href=/zh-cn/docsv2.7/user/best-practice/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userbest-practice><span>服务化最佳实践</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userrecommend-li><input type=checkbox id=m-zh-cndocsv27userrecommend-check>
<label for=m-zh-cndocsv27userrecommend-check><a href=/zh-cn/docsv2.7/user/recommend/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userrecommend><span>推荐用法</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27usercapacity-plan-li><input type=checkbox id=m-zh-cndocsv27usercapacity-plan-check>
<label for=m-zh-cndocsv27usercapacity-plan-check><a href=/zh-cn/docsv2.7/user/capacity-plan/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27usercapacity-plan><span>容量规划</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userperf-test-li><input type=checkbox id=m-zh-cndocsv27userperf-test-check>
<label for=m-zh-cndocsv27userperf-test-check><a href=/zh-cn/docsv2.7/user/perf-test/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userperf-test><span>性能测试报告</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27usercoveragence-li><input type=checkbox id=m-zh-cndocsv27usercoveragence-check>
<label for=m-zh-cndocsv27usercoveragence-check><a href=/zh-cn/docsv2.7/user/coveragence/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27usercoveragence><span>测试覆盖率报告</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userbenchmark-tool-li><input type=checkbox id=m-zh-cndocsv27userbenchmark-tool-check>
<label for=m-zh-cndocsv27userbenchmark-tool-check><a href=/zh-cn/docsv2.7/user/benchmark-tool/ title=基准测试工具包 class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userbenchmark-tool><span>基准测试</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userrest-li><input type=checkbox id=m-zh-cndocsv27userrest-check>
<label for=m-zh-cndocsv27userrest-check><a href=/zh-cn/docsv2.7/user/rest/ title="开发 REST 应用" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userrest><span>REST 支持</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27usersimple-monitor-li><input type=checkbox id=m-zh-cndocsv27usersimple-monitor-check>
<label for=m-zh-cndocsv27usersimple-monitor-check><a href=/zh-cn/docsv2.7/user/simple-monitor/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27usersimple-monitor><span>简单监控</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userserialization-li><input type=checkbox id=m-zh-cndocsv27userserialization-check>
<label for=m-zh-cndocsv27userserialization-check><a href=/zh-cn/docsv2.7/user/serialization/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userserialization><span>Kryo 和 FST 序列化</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27userlanguages-li><input type=checkbox id=m-zh-cndocsv27userlanguages-check>
<label for=m-zh-cndocsv27userlanguages-check><a href=/zh-cn/docsv2.7/user/languages/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27userlanguages><span>其他语言支持</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27userlanguageserlang-li><input type=checkbox id=m-zh-cndocsv27userlanguageserlang-check>
<label for=m-zh-cndocsv27userlanguageserlang-check><a href=/zh-cn/docsv2.7/user/languages/erlang/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27userlanguageserlang><span>Erlang</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userlanguageserlangquick-start-li><input type=checkbox id=m-zh-cndocsv27userlanguageserlangquick-start-check>
<label for=m-zh-cndocsv27userlanguageserlangquick-start-check><a href=/zh-cn/docsv2.7/user/languages/erlang/quick-start/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userlanguageserlangquick-start><span>快速开始</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userlanguageserlangreference-li><input type=checkbox id=m-zh-cndocsv27userlanguageserlangreference-check>
<label for=m-zh-cndocsv27userlanguageserlangreference-check><a href=/zh-cn/docsv2.7/user/languages/erlang/reference/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userlanguageserlangreference><span>消费者配置</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userlanguageserlangservice-li><input type=checkbox id=m-zh-cndocsv27userlanguageserlangservice-check>
<label for=m-zh-cndocsv27userlanguageserlangservice-check><a href=/zh-cn/docsv2.7/user/languages/erlang/service/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userlanguageserlangservice><span>提供者配置</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27userlanguageserlangserialization-li><input type=checkbox id=m-zh-cndocsv27userlanguageserlangserialization-check>
<label for=m-zh-cndocsv27userlanguageserlangserialization-check><a href=/zh-cn/docsv2.7/user/languages/erlang/serialization/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27userlanguageserlangserialization><span>序列化配置项</span></a></label></li></ul></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27usernew-features-in-a-glance-li><input type=checkbox id=m-zh-cndocsv27usernew-features-in-a-glance-check>
<label for=m-zh-cndocsv27usernew-features-in-a-glance-check><a href=/zh-cn/docsv2.7/user/new-features-in-a-glance/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27usernew-features-in-a-glance><span></span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27dev-li><input type=checkbox id=m-zh-cndocsv27dev-check>
<label for=m-zh-cndocsv27dev-check><a href=/zh-cn/docsv2.7/dev/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27dev><span>开发指南</span></a></label><ul class="ul-2 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devbuild-li><input type=checkbox id=m-zh-cndocsv27devbuild-check>
<label for=m-zh-cndocsv27devbuild-check><a href=/zh-cn/docsv2.7/dev/build/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devbuild><span>源码构建</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devdesign-li><input type=checkbox id=m-zh-cndocsv27devdesign-check>
<label for=m-zh-cndocsv27devdesign-check><a href=/zh-cn/docsv2.7/dev/design/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devdesign><span>框架设计</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devspi-li><input type=checkbox id=m-zh-cndocsv27devspi-check>
<label for=m-zh-cndocsv27devspi-check><a href=/zh-cn/docsv2.7/dev/spi/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devspi><span>扩展点加载</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplementation-li><input type=checkbox id=m-zh-cndocsv27devimplementation-check>
<label for=m-zh-cndocsv27devimplementation-check><a href=/zh-cn/docsv2.7/dev/implementation/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplementation><span>实现细节</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27devimpls-li><input type=checkbox id=m-zh-cndocsv27devimpls-check>
<label for=m-zh-cndocsv27devimpls-check><a href=/zh-cn/docsv2.7/dev/impls/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27devimpls><span>SPI 扩展实现</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsprotocol-li><input type=checkbox id=m-zh-cndocsv27devimplsprotocol-check>
<label for=m-zh-cndocsv27devimplsprotocol-check><a href=/zh-cn/docsv2.7/dev/impls/protocol/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsprotocol><span>协议扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsfilter-li><input type=checkbox id=m-zh-cndocsv27devimplsfilter-check>
<label for=m-zh-cndocsv27devimplsfilter-check><a href=/zh-cn/docsv2.7/dev/impls/filter/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsfilter><span>调用拦截扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsinvoker-listener-li><input type=checkbox id=m-zh-cndocsv27devimplsinvoker-listener-check>
<label for=m-zh-cndocsv27devimplsinvoker-listener-check><a href=/zh-cn/docsv2.7/dev/impls/invoker-listener/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsinvoker-listener><span>引用监听扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsexporter-listener-li><input type=checkbox id=m-zh-cndocsv27devimplsexporter-listener-check>
<label for=m-zh-cndocsv27devimplsexporter-listener-check><a href=/zh-cn/docsv2.7/dev/impls/exporter-listener/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsexporter-listener><span>暴露监听扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplscluster-li><input type=checkbox id=m-zh-cndocsv27devimplscluster-check>
<label for=m-zh-cndocsv27devimplscluster-check><a href=/zh-cn/docsv2.7/dev/impls/cluster/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplscluster><span>集群扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsrouter-li><input type=checkbox id=m-zh-cndocsv27devimplsrouter-check>
<label for=m-zh-cndocsv27devimplsrouter-check><a href=/zh-cn/docsv2.7/dev/impls/router/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsrouter><span>路由扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsload-balance-li><input type=checkbox id=m-zh-cndocsv27devimplsload-balance-check>
<label for=m-zh-cndocsv27devimplsload-balance-check><a href=/zh-cn/docsv2.7/dev/impls/load-balance/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsload-balance><span>负载均衡扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsmerger-li><input type=checkbox id=m-zh-cndocsv27devimplsmerger-check>
<label for=m-zh-cndocsv27devimplsmerger-check><a href=/zh-cn/docsv2.7/dev/impls/merger/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsmerger><span>合并结果扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsregistry-li><input type=checkbox id=m-zh-cndocsv27devimplsregistry-check>
<label for=m-zh-cndocsv27devimplsregistry-check><a href=/zh-cn/docsv2.7/dev/impls/registry/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsregistry><span>注册中心扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsmonitor-li><input type=checkbox id=m-zh-cndocsv27devimplsmonitor-check>
<label for=m-zh-cndocsv27devimplsmonitor-check><a href=/zh-cn/docsv2.7/dev/impls/monitor/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsmonitor><span>监控中心扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsextension-factory-li><input type=checkbox id=m-zh-cndocsv27devimplsextension-factory-check>
<label for=m-zh-cndocsv27devimplsextension-factory-check><a href=/zh-cn/docsv2.7/dev/impls/extension-factory/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsextension-factory><span>扩展点加载扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsproxy-factory-li><input type=checkbox id=m-zh-cndocsv27devimplsproxy-factory-check>
<label for=m-zh-cndocsv27devimplsproxy-factory-check><a href=/zh-cn/docsv2.7/dev/impls/proxy-factory/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsproxy-factory><span>动态代理扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplscompiler-li><input type=checkbox id=m-zh-cndocsv27devimplscompiler-check>
<label for=m-zh-cndocsv27devimplscompiler-check><a href=/zh-cn/docsv2.7/dev/impls/compiler/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplscompiler><span>编译器扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsconfig-center-li><input type=checkbox id=m-zh-cndocsv27devimplsconfig-center-check>
<label for=m-zh-cndocsv27devimplsconfig-center-check><a href=/zh-cn/docsv2.7/dev/impls/config-center/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsconfig-center><span>配置中心扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsdispatcher-li><input type=checkbox id=m-zh-cndocsv27devimplsdispatcher-check>
<label for=m-zh-cndocsv27devimplsdispatcher-check><a href=/zh-cn/docsv2.7/dev/impls/dispatcher/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsdispatcher><span>消息派发扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsthreadpool-li><input type=checkbox id=m-zh-cndocsv27devimplsthreadpool-check>
<label for=m-zh-cndocsv27devimplsthreadpool-check><a href=/zh-cn/docsv2.7/dev/impls/threadpool/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsthreadpool><span>线程池扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsserialize-li><input type=checkbox id=m-zh-cndocsv27devimplsserialize-check>
<label for=m-zh-cndocsv27devimplsserialize-check><a href=/zh-cn/docsv2.7/dev/impls/serialize/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsserialize><span>序列化扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsremoting-li><input type=checkbox id=m-zh-cndocsv27devimplsremoting-check>
<label for=m-zh-cndocsv27devimplsremoting-check><a href=/zh-cn/docsv2.7/dev/impls/remoting/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsremoting><span>网络传输扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsexchanger-li><input type=checkbox id=m-zh-cndocsv27devimplsexchanger-check>
<label for=m-zh-cndocsv27devimplsexchanger-check><a href=/zh-cn/docsv2.7/dev/impls/exchanger/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsexchanger><span>信息交换扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsnetworker-li><input type=checkbox id=m-zh-cndocsv27devimplsnetworker-check>
<label for=m-zh-cndocsv27devimplsnetworker-check><a href=/zh-cn/docsv2.7/dev/impls/networker/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsnetworker><span>组网扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplstelnet-handler-li><input type=checkbox id=m-zh-cndocsv27devimplstelnet-handler-check>
<label for=m-zh-cndocsv27devimplstelnet-handler-check><a href=/zh-cn/docsv2.7/dev/impls/telnet-handler/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplstelnet-handler><span>Telnet 命令扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsstatus-checker-li><input type=checkbox id=m-zh-cndocsv27devimplsstatus-checker-check>
<label for=m-zh-cndocsv27devimplsstatus-checker-check><a href=/zh-cn/docsv2.7/dev/impls/status-checker/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsstatus-checker><span>状态检查扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplscontainer-li><input type=checkbox id=m-zh-cndocsv27devimplscontainer-check>
<label for=m-zh-cndocsv27devimplscontainer-check><a href=/zh-cn/docsv2.7/dev/impls/container/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplscontainer><span>容器扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplscache-li><input type=checkbox id=m-zh-cndocsv27devimplscache-check>
<label for=m-zh-cndocsv27devimplscache-check><a href=/zh-cn/docsv2.7/dev/impls/cache/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplscache><span>缓存扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplsvalidation-li><input type=checkbox id=m-zh-cndocsv27devimplsvalidation-check>
<label for=m-zh-cndocsv27devimplsvalidation-check><a href=/zh-cn/docsv2.7/dev/impls/validation/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplsvalidation><span>验证扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplslogger-adapter-li><input type=checkbox id=m-zh-cndocsv27devimplslogger-adapter-check>
<label for=m-zh-cndocsv27devimplslogger-adapter-check><a href=/zh-cn/docsv2.7/dev/impls/logger-adapter/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplslogger-adapter><span>日志适配扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devimplspage-li><input type=checkbox id=m-zh-cndocsv27devimplspage-check>
<label for=m-zh-cndocsv27devimplspage-check><a href=/zh-cn/docsv2.7/dev/impls/page/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devimplspage><span></span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27devprincipals-li><input type=checkbox id=m-zh-cndocsv27devprincipals-check>
<label for=m-zh-cndocsv27devprincipals-check><a href=/zh-cn/docsv2.7/dev/principals/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27devprincipals><span>设计原则</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devprincipalscode-detail-li><input type=checkbox id=m-zh-cndocsv27devprincipalscode-detail-check>
<label for=m-zh-cndocsv27devprincipalscode-detail-check><a href=/zh-cn/docsv2.7/dev/principals/code-detail/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devprincipalscode-detail><span>魔鬼在细节</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devprincipalsconfiguration-li><input type=checkbox id=m-zh-cndocsv27devprincipalsconfiguration-check>
<label for=m-zh-cndocsv27devprincipalsconfiguration-check><a href=/zh-cn/docsv2.7/dev/principals/configuration/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devprincipalsconfiguration><span>配置设计</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devprincipalsdummy-li><input type=checkbox id=m-zh-cndocsv27devprincipalsdummy-check>
<label for=m-zh-cndocsv27devprincipalsdummy-check><a href=/zh-cn/docsv2.7/dev/principals/dummy/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devprincipalsdummy><span>防痴呆设计</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devprincipalsexpansibility-li><input type=checkbox id=m-zh-cndocsv27devprincipalsexpansibility-check>
<label for=m-zh-cndocsv27devprincipalsexpansibility-check><a href=/zh-cn/docsv2.7/dev/principals/expansibility/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devprincipalsexpansibility><span>谈谈扩充式扩展与增量式扩展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devprincipalsextension-li><input type=checkbox id=m-zh-cndocsv27devprincipalsextension-check>
<label for=m-zh-cndocsv27devprincipalsextension-check><a href=/zh-cn/docsv2.7/dev/principals/extension/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devprincipalsextension><span>扩展点重构</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devprincipalsgeneral-knowledge-li><input type=checkbox id=m-zh-cndocsv27devprincipalsgeneral-knowledge-check>
<label for=m-zh-cndocsv27devprincipalsgeneral-knowledge-check><a href=/zh-cn/docsv2.7/dev/principals/general-knowledge/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devprincipalsgeneral-knowledge><span>一些设计上的基本常识</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devprincipalsrobustness-li><input type=checkbox id=m-zh-cndocsv27devprincipalsrobustness-check>
<label for=m-zh-cndocsv27devprincipalsrobustness-check><a href=/zh-cn/docsv2.7/dev/principals/robustness/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devprincipalsrobustness><span>设计实现的健壮性</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devprincipalsintroduction-li><input type=checkbox id=m-zh-cndocsv27devprincipalsintroduction-check>
<label for=m-zh-cndocsv27devprincipalsintroduction-check><a href=/zh-cn/docsv2.7/dev/principals/introduction/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devprincipalsintroduction><span></span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devcontract-li><input type=checkbox id=m-zh-cndocsv27devcontract-check>
<label for=m-zh-cndocsv27devcontract-check><a href=/zh-cn/docsv2.7/dev/contract/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devcontract><span>公共契约</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27devsource-li><input type=checkbox id=m-zh-cndocsv27devsource-check>
<label for=m-zh-cndocsv27devsource-check><a href=/zh-cn/docsv2.7/dev/source/ title="Dubbo 源代码分析" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27devsource><span>源代码</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devsourcedubbo-spi-li><input type=checkbox id=m-zh-cndocsv27devsourcedubbo-spi-check>
<label for=m-zh-cndocsv27devsourcedubbo-spi-check><a href=/zh-cn/docsv2.7/dev/source/dubbo-spi/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devsourcedubbo-spi><span>Dubbo SPI</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devsourcerouter-li><input type=checkbox id=m-zh-cndocsv27devsourcerouter-check>
<label for=m-zh-cndocsv27devsourcerouter-check><a href=/zh-cn/docsv2.7/dev/source/router/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devsourcerouter><span>服务路由</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devsourceadaptive-extension-li><input type=checkbox id=m-zh-cndocsv27devsourceadaptive-extension-check>
<label for=m-zh-cndocsv27devsourceadaptive-extension-check><a href=/zh-cn/docsv2.7/dev/source/adaptive-extension/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devsourceadaptive-extension><span>SPI 自适应拓展</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devsourceexport-service-li><input type=checkbox id=m-zh-cndocsv27devsourceexport-service-check>
<label for=m-zh-cndocsv27devsourceexport-service-check><a href=/zh-cn/docsv2.7/dev/source/export-service/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devsourceexport-service><span>服务导出</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devsourcerefer-service-li><input type=checkbox id=m-zh-cndocsv27devsourcerefer-service-check>
<label for=m-zh-cndocsv27devsourcerefer-service-check><a href=/zh-cn/docsv2.7/dev/source/refer-service/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devsourcerefer-service><span>服务引用</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devsourceservice-invoking-process-li><input type=checkbox id=m-zh-cndocsv27devsourceservice-invoking-process-check>
<label for=m-zh-cndocsv27devsourceservice-invoking-process-check><a href=/zh-cn/docsv2.7/dev/source/service-invoking-process/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devsourceservice-invoking-process><span>服务调用过程</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devsourcedirectory-li><input type=checkbox id=m-zh-cndocsv27devsourcedirectory-check>
<label for=m-zh-cndocsv27devsourcedirectory-check><a href=/zh-cn/docsv2.7/dev/source/directory/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devsourcedirectory><span>服务目录</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devsourcecluster-li><input type=checkbox id=m-zh-cndocsv27devsourcecluster-check>
<label for=m-zh-cndocsv27devsourcecluster-check><a href=/zh-cn/docsv2.7/dev/source/cluster/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devsourcecluster><span>集群</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devsourceloadbalance-li><input type=checkbox id=m-zh-cndocsv27devsourceloadbalance-check>
<label for=m-zh-cndocsv27devsourceloadbalance-check><a href=/zh-cn/docsv2.7/dev/source/loadbalance/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devsourceloadbalance><span>负载均衡</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devrelease-li><input type=checkbox id=m-zh-cndocsv27devrelease-check>
<label for=m-zh-cndocsv27devrelease-check><a href=/zh-cn/docsv2.7/dev/release/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devrelease><span>版本管理</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devchecklist-li><input type=checkbox id=m-zh-cndocsv27devchecklist-check>
<label for=m-zh-cndocsv27devchecklist-check><a href=/zh-cn/docsv2.7/dev/checklist/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devchecklist><span>检查列表</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devcoding-li><input type=checkbox id=m-zh-cndocsv27devcoding-check>
<label for=m-zh-cndocsv27devcoding-check><a href=/zh-cn/docsv2.7/dev/coding/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devcoding><span>编码约定</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devcode-smell-li><input type=checkbox id=m-zh-cndocsv27devcode-smell-check>
<label for=m-zh-cndocsv27devcode-smell-check><a href=/zh-cn/docsv2.7/dev/code-smell/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devcode-smell><span>坏味道</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27devtck-li><input type=checkbox id=m-zh-cndocsv27devtck-check>
<label for=m-zh-cndocsv27devtck-check><a href=/zh-cn/docsv2.7/dev/tck/ title=技术兼容性测试 class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27devtck><span>TCK</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27admin-li><input type=checkbox id=m-zh-cndocsv27admin-check>
<label for=m-zh-cndocsv27admin-check><a href=/zh-cn/docsv2.7/admin/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27admin><span>运维指南</span></a></label><ul class="ul-2 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27adminops-li><input type=checkbox id=m-zh-cndocsv27adminops-check>
<label for=m-zh-cndocsv27adminops-check><a href=/zh-cn/docsv2.7/admin/ops/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27adminops><span>Dubbo Admin 运维指南</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27adminopsfunctions-li><input type=checkbox id=m-zh-cndocsv27adminopsfunctions-check>
<label for=m-zh-cndocsv27adminopsfunctions-check><a href=/zh-cn/docsv2.7/admin/ops/functions/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27adminopsfunctions><span>管理控制台运维</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27adminopsintroduction-li><input type=checkbox id=m-zh-cndocsv27adminopsintroduction-check>
<label for=m-zh-cndocsv27adminopsintroduction-check><a href=/zh-cn/docsv2.7/admin/ops/introduction/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27adminopsintroduction><span>Dubbo 管理控制台介绍</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27adminopstest-li><input type=checkbox id=m-zh-cndocsv27adminopstest-check>
<label for=m-zh-cndocsv27adminopstest-check><a href=/zh-cn/docsv2.7/admin/ops/test/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27adminopstest><span>服务测试</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27adminopssearch-li><input type=checkbox id=m-zh-cndocsv27adminopssearch-check>
<label for=m-zh-cndocsv27adminopssearch-check><a href=/zh-cn/docsv2.7/admin/ops/search/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27adminopssearch><span>服务查询和详情展示</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27adminopsapidocs-li><input type=checkbox id=m-zh-cndocsv27adminopsapidocs-check>
<label for=m-zh-cndocsv27adminopsapidocs-check><a href=/zh-cn/docsv2.7/admin/ops/apidocs/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27adminopsapidocs><span>API文档&测试</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27adminopsgovernance-li><input type=checkbox id=m-zh-cndocsv27adminopsgovernance-check>
<label for=m-zh-cndocsv27adminopsgovernance-check><a href=/zh-cn/docsv2.7/admin/ops/governance/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27adminopsgovernance><span>服务治理和配置管理</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27adminopsskywalking-li><input type=checkbox id=m-zh-cndocsv27adminopsskywalking-check>
<label for=m-zh-cndocsv27adminopsskywalking-check><a href=/zh-cn/docsv2.7/admin/ops/skywalking/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27adminopsskywalking><span>使用 Apache Skywalking 做分布式跟踪</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27adminopspinpoint-li><input type=checkbox id=m-zh-cndocsv27adminopspinpoint-check>
<label for=m-zh-cndocsv27adminopspinpoint-check><a href=/zh-cn/docsv2.7/admin/ops/pinpoint/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27adminopspinpoint><span>使用 Pinpoint 做分布式跟踪</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-zh-cndocsv27admininstall-li><input type=checkbox id=m-zh-cndocsv27admininstall-check>
<label for=m-zh-cndocsv27admininstall-check><a href=/zh-cn/docsv2.7/admin/install/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-zh-cndocsv27admininstall><span>安装手册</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27admininstalladmin-console-li><input type=checkbox id=m-zh-cndocsv27admininstalladmin-console-check>
<label for=m-zh-cndocsv27admininstalladmin-console-check><a href=/zh-cn/docsv2.7/admin/install/admin-console/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27admininstalladmin-console><span>管理控制台安装</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27admininstallprovider-demo-li><input type=checkbox id=m-zh-cndocsv27admininstallprovider-demo-check>
<label for=m-zh-cndocsv27admininstallprovider-demo-check><a href=/zh-cn/docsv2.7/admin/install/provider-demo/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27admininstallprovider-demo><span>示例提供者安装</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27admininstallconsumer-demo-li><input type=checkbox id=m-zh-cndocsv27admininstallconsumer-demo-check>
<label for=m-zh-cndocsv27admininstallconsumer-demo-check><a href=/zh-cn/docsv2.7/admin/install/consumer-demo/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27admininstallconsumer-demo><span>示例消费者安装</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27admininstallredis-li><input type=checkbox id=m-zh-cndocsv27admininstallredis-check>
<label for=m-zh-cndocsv27admininstallredis-check><a href=/zh-cn/docsv2.7/admin/install/redis/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27admininstallredis><span>Redis 注册中心安装</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27admininstallzookeeper-li><input type=checkbox id=m-zh-cndocsv27admininstallzookeeper-check>
<label for=m-zh-cndocsv27admininstallzookeeper-check><a href=/zh-cn/docsv2.7/admin/install/zookeeper/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27admininstallzookeeper><span>Zookeeper 注册中心安装</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-zh-cndocsv27admininstallmonitor-center-li><input type=checkbox id=m-zh-cndocsv27admininstallmonitor-center-check>
<label for=m-zh-cndocsv27admininstallmonitor-center-check><a href=/zh-cn/docsv2.7/admin/install/monitor-center/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-zh-cndocsv27admininstallmonitor-center><span>Simple 监控中心安装</span></a></label></li></ul></li></ul></li></ul></li></ul></nav></div></div><main class="col-12 col-md-9 col-xl-8 pl-md-5" role=main><nav aria-label=breadcrumb class=td-breadcrumbs><ol class=breadcrumb><li class=breadcrumb-item><a href=https://dubbo.apache.org/zh-cn/docsv2.7/>文档 2.x</a></li><li class=breadcrumb-item><a href=https://dubbo.apache.org/zh-cn/docsv2.7/user/>用户文档</a></li><li class=breadcrumb-item><a href=https://dubbo.apache.org/zh-cn/docsv2.7/user/references/>参考手册</a></li><li class=breadcrumb-item><a href=https://dubbo.apache.org/zh-cn/docsv2.7/user/references/protocol/>协议参考手册</a></li><li class="breadcrumb-item active" aria-current=page><a href=https://dubbo.apache.org/zh-cn/docsv2.7/user/references/protocol/rest/ aria-disabled=true class="btn-link disabled">rest://</a></li></ol></nav><div class=td-content><h1>rest 协议</h1><div class=lead>rest:// 协议参考手册</div><header class=article-meta></header><p>基于标准的Java REST API——JAX-RS 2.0(Java API for RESTful Web Services的简写)实现的REST调用支持</p><h2 id=快速入门>快速入门</h2><p>在dubbo中开发一个REST风格的服务会比较简单,下面以一个注册用户的简单服务为例说明。</p><p>这个服务要实现的功能是提供如下URL(注:这个URL不是完全符合REST的风格,但是更简单实用):</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>http://localhost:8080/users/register
</span></span></code></pre></div><p>而任何客户端都可以将包含用户信息的JSON字符串POST到以上URL来完成用户注册。</p><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-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>interface</span> <span style=color:#268bd2>UserService</span> {
</span></span><span style=display:flex><span> <span style=color:#dc322f>void</span> <span style=color:#268bd2>registerUser</span>(User user);
</span></span><span style=display:flex><span>}
</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-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>@Path</span>(<span style=color:#2aa198>&#34;/users&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>UserServiceImpl</span> <span style=color:#268bd2>implements</span> UserService {
</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:#2aa198>&#34;/register&#34;</span>)
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Consumes</span>({MediaType.APPLICATION_JSON})
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> <span style=color:#dc322f>void</span> <span style=color:#268bd2>registerUser</span>(User user) {
</span></span><span style=display:flex><span> <span style=color:#586e75>// save the user...</span>
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>上面的实现非常简单,但是由于该 REST 服务是要发布到指定 URL 上,供任意语言的客户端甚至浏览器来访问,所以这里额外添加了几个 JAX-RS 的标准 annotation 来做相关的配置。</p><p>@Path("/users"):指定访问UserService的URL相对路径是/users,即http://localhost:8080/users</p><p>@Path("/register"):指定访问registerUser()方法的URL相对路径是/register,再结合上一个@Path为UserService指定的路径,则调用UserService.register()的完整路径为http://localhost:8080/users/register</p><p>@POST:指定访问registerUser()用HTTP POST方法</p><p>@Consumes({MediaType.APPLICATION_JSON}):指定registerUser()接收JSON格式的数据。REST框架会自动将JSON数据反序列化为User对象</p><p>最后,在spring配置文件中添加此服务,即完成所有服务开发工作:</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:#586e75>&lt;!-- 用rest协议在8080端口暴露服务 --&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> port=<span style=color:#2aa198>&#34;8080&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#586e75>&lt;!-- 声明需要暴露的服务接口 --&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;dubbo:service</span> interface=<span style=color:#2aa198>&#34;xxx.UserService&#34;</span> ref=<span style=color:#2aa198>&#34;userService&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#586e75>&lt;!-- 和本地bean一样实现服务 --&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;bean</span> id=<span style=color:#2aa198>&#34;userService&#34;</span> class=<span style=color:#2aa198>&#34;xxx.UserServiceImpl&#34;</span> <span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><h2 id=rest服务提供端详解>REST服务提供端详解</h2><p>下面我们扩充“快速入门”中的UserService,进一步展示在dubbo中REST服务提供端的开发要点。</p><h3 id=http-postget的实现>HTTP POST/GET的实现</h3><p>REST服务中虽然建议使用HTTP协议中四种标准方法POST、DELETE、PUT、GET来分别实现常见的“增删改查”,但实际中,我们一般情况直接用POST来实现“增改”,GET来实现“删查”即可(DELETE和PUT甚至会被一些防火墙阻挡)。</p><p>前面已经简单演示了POST的实现,在此,我们为UserService添加一个获取注册用户资料的功能,来演示GET的实现。</p><p>这个功能就是要实现客户端通过访问如下不同URL来获取不同ID的用户资料:</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>http://localhost:8080/users/1001
</span></span><span style=display:flex><span>http://localhost:8080/users/1002
</span></span><span style=display:flex><span>http://localhost:8080/users/1003
</span></span></code></pre></div><p>当然,也可以通过其他形式的URL来访问不同ID的用户资料,例如:</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-gdscript3 data-lang=gdscript3><span style=display:flex><span>http:<span style=color:#719e07>//</span>localhost:<span style=color:#2aa198>8080</span><span style=color:#719e07>/</span>users<span style=color:#719e07>/</span><span style=color:#b58900>load</span>?id<span style=color:#719e07>=</span><span style=color:#2aa198>1001</span>
</span></span></code></pre></div><p>JAX-RS本身可以支持所有这些形式。但是上面那种在URL路径中包含查询参数的形式(http://localhost:8080/users/1001) 更符合REST的一般习惯,所以更推荐大家来使用。下面我们就为UserService添加一个getUser()方法来实现这种形式的URL访问:</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>@GET</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>@Path</span>(<span style=color:#2aa198>&#34;/{id : \\d+}&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>@Produces</span>({MediaType.APPLICATION_JSON})
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id) {
</span></span><span style=display:flex><span> <span style=color:#586e75>// ...</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>@GET:指定用HTTP GET方法访问</p><p>@Path("/{id : \d+}"):根据上面的功能需求,访问getUser()的URL应当是“http://localhost:8080/users/ + 任意数字",并且这个数字要被做为参数传入getUser()方法。 这里的annotation配置中,@Path中间的{id: xxx}指定URL相对路径中包含了名为id参数,而它的值也将被自动传递给下面用@PathParam(&ldquo;id&rdquo;)修饰的方法参数id。{id:后面紧跟的\d+是一个正则表达式,指定了id参数必须是数字。</p><p>@Produces({MediaType.APPLICATION_JSON}):指定getUser()输出JSON格式的数据。框架会自动将User对象序列化为JSON数据。</p><h3 id=annotation放在接口类还是实现类>Annotation放在接口类还是实现类</h3><p>在Dubbo中开发REST服务主要都是通过JAX-RS的annotation来完成配置的,在上面的示例中,我们都是将annotation放在服务的实现类中。但其实,我们完全也可以将annotation放到服务的接口上,这两种方式是完全等价的,例如:</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:#2aa198>&#34;/users&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>interface</span> <span style=color:#268bd2>UserService</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:#2aa198>&#34;/{id : \\d+}&#34;</span>)
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Produces</span>({MediaType.APPLICATION_JSON})
</span></span><span style=display:flex><span> User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>在一般应用中,我们建议将annotation放到服务实现类,这样annotation和java实现代码位置更接近,更便于开发和维护。另外更重要的是,我们一般倾向于避免对接口的污染,保持接口的纯净性和广泛适用性。</p><p>但是,如后文所述,如果我们要用dubbo直接开发的消费端来访问此服务,则annotation必须放到接口上。</p><p>如果接口和实现类都同时添加了annotation,则实现类的annotation配置会生效,接口上的annotation被直接忽略。</p><h3 id=jsonxml等多数据格式的支持>JSON、XML等多数据格式的支持</h3><p>在dubbo中开发的REST服务可以同时支持传输多种格式的数据,以给客户端提供最大的灵活性。其中我们目前对最常用的JSON和XML格式特别添加了额外的功能。</p><p>比如,我们要让上例中的getUser()方法支持分别返回JSON和XML格式的数据,只需要在annotation中同时包含两种格式即可:</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>@Produces</span>({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
</span></span><span style=display:flex><span>User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id);
</span></span></code></pre></div><p>或者也可以直接用字符串(还支持通配符)表示MediaType:</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>@Produces</span>({<span style=color:#2aa198>&#34;application/json&#34;</span>, <span style=color:#2aa198>&#34;text/xml&#34;</span>})
</span></span><span style=display:flex><span>User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id);
</span></span></code></pre></div><p>如果所有方法都支持同样类型的输入输出数据格式,则我们无需在每个方法上做配置,只需要在服务类上添加annotation即可:</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:#2aa198>&#34;/users&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>@Consumes</span>({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
</span></span><span style=display:flex><span><span style=color:#268bd2>@Produces</span>({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>UserServiceImpl</span> <span style=color:#268bd2>implements</span> UserService {
</span></span><span style=display:flex><span> <span style=color:#586e75>// ...</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>在一个REST服务同时对多种数据格式支持的情况下,根据JAX-RS标准,一般是通过HTTP中的MIME header(content-type和accept)来指定当前想用的是哪种格式的数据。</p><p>但是在dubbo中,我们还自动支持目前业界普遍使用的方式,即用一个URL后缀(.json和.xml)来指定想用的数据格式。例如,在添加上述annotation后,直接访问http://localhost:8888/users/1001.json则表示用json格式,直接访问http://localhost:8888/users/1002.xml则表示用xml格式,比用HTTP Header更简单直观。Twitter、微博等的REST API都是采用这种方式。</p><p>如果你既不加HTTP header,也不加后缀,则dubbo的REST会优先启用在以上annotation定义中排位最靠前的那种数据格式。</p><blockquote><p>注意:这里要支持XML格式数据,在annotation中既可以用MediaType.TEXT_XML,也可以用MediaType.APPLICATION_XML,但是TEXT_XML是更常用的,并且如果要利用上述的URL后缀方式来指定数据格式,只能配置为TEXT_XML才能生效。</p></blockquote><h3 id=中文字符支持>中文字符支持</h3><p>为了在dubbo REST中正常输出中文字符,和通常的Java web应用一样,我们需要将HTTP响应的contentType设置为UTF-8编码。</p><p>基于JAX-RS的标准用法,我们只需要做如下annotation配置即可:</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>@Produces</span>({<span style=color:#2aa198>&#34;application/json; charset=UTF-8&#34;</span>, <span style=color:#2aa198>&#34;text/xml; charset=UTF-8&#34;</span>})
</span></span><span style=display:flex><span>User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id);
</span></span></code></pre></div><p>为了方便用户,我们在dubbo REST中直接添加了一个支持类,来定义以上的常量,可以直接使用,减少出错的可能性。</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>@Produces</span>({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8})
</span></span><span style=display:flex><span>User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id);
</span></span></code></pre></div><h3 id=xml数据格式的额外要求>XML数据格式的额外要求</h3><p>由于JAX-RS的实现一般都用标准的JAXB(Java API for XML Binding)来序列化和反序列化XML格式数据,所以我们需要为每一个要用XML传输的对象添加一个类级别的JAXB annotation,否则序列化将报错。例如为getUser()中返回的User添加如下:</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>@XmlRootElement</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>User</span> <span style=color:#268bd2>implements</span> Serializable {
</span></span><span style=display:flex><span> <span style=color:#586e75>// ...</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>此外,如果service方法中的返回值是Java的 primitive类型(如int,long,float,double等),最好为它们添加一层wrapper对象,因为JAXB不能直接序列化primitive类型。</p><p>例如,我们想让前述的registerUser()方法返回服务器端为用户生成的ID号:</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:#dc322f>long</span> <span style=color:#268bd2>registerUser</span>(User user);
</span></span></code></pre></div><p>由于primitive类型不被JAXB序列化支持,所以添加一个wrapper对象:</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>@XmlRootElement</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>RegistrationResult</span> <span style=color:#268bd2>implements</span> Serializable {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>private</span> Long id;
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> <span style=color:#268bd2>RegistrationResult</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:#268bd2>RegistrationResult</span>(Long id) {
</span></span><span style=display:flex><span> <span style=color:#719e07>this</span>.id <span style=color:#719e07>=</span> id;
</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> Long <span style=color:#268bd2>getId</span>() {
</span></span><span style=display:flex><span> <span style=color:#719e07>return</span> id;
</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>setId</span>(Long id) {
</span></span><span style=display:flex><span> <span style=color:#719e07>this</span>.id <span style=color:#719e07>=</span> id;
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>并修改service方法:</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>RegistrationResult <span style=color:#268bd2>registerUser</span>(User user);
</span></span></code></pre></div><p>这样不但能够解决XML序列化的问题,而且使得返回的数据都符合XML和JSON的规范。例如,在JSON中,返回的将是如下形式:</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-javascript data-lang=javascript><span style=display:flex><span>{<span style=color:#2aa198>&#34;id&#34;</span><span style=color:#719e07>:</span> <span style=color:#2aa198>1001</span>}
</span></span></code></pre></div><p>如果不加wrapper,JSON返回值将直接是</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>1001
</span></span></code></pre></div><p>而在XML中,加wrapper后返回值将是:</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;registrationResult&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;id&gt;</span>1002<span style=color:#268bd2>&lt;/id&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/registrationResult&gt;</span>
</span></span></code></pre></div><p>这种wrapper对象其实利用所谓Data Transfer Object(DTO)模式,采用DTO还能对传输数据做更多有用的定制。</p><h3 id=定制序列化>定制序列化</h3><p>如上所述,REST的底层实现会在service的对象和JSON/XML数据格式之间自动做序列化/反序列化。但有些场景下,如果觉得这种自动转换不满足要求,可以对其做定制。</p><p>Dubbo中的REST实现是用JAXB做XML序列化,用Jackson做JSON序列化,所以在对象上添加JAXB或Jackson的annotation即可以定制映射。</p><p>例如,定制对象属性映射到XML元素的名字:</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>@XmlRootElement</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>@XmlAccessorType</span>(XmlAccessType.FIELD)
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>User</span> <span style=color:#268bd2>implements</span> Serializable {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@XmlElement</span>(name<span style=color:#719e07>=</span><span style=color:#2aa198>&#34;username&#34;</span>)
</span></span><span style=display:flex><span> <span style=color:#268bd2>private</span> String name;
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>定制对象属性映射到JSON字段的名字:</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>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>User</span> <span style=color:#268bd2>implements</span> Serializable {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@JsonProperty</span>(<span style=color:#2aa198>&#34;username&#34;</span>)
</span></span><span style=display:flex><span> <span style=color:#268bd2>private</span> String name;
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>更多资料请参考JAXB和Jackson的官方文档,或自行google。</p><h3 id=配置rest-server的实现>配置REST Server的实现</h3><p>目前在dubbo中,我们支持5种嵌入式rest server的实现,并同时支持采用外部应用服务器来做rest server的实现。rest server可以通过如下配置实现:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> server=<span style=color:#2aa198>&#34;jetty&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>以上配置选用了嵌入式的jetty来做rest server,同时,如果不配置server属性,rest协议默认也是选用jetty。jetty是非常成熟的java servlet容器,并和dubbo已经有较好的集成(目前5种嵌入式server中只有jetty和后面所述的tomcat、tjws,与dubbo监控系统等完成了无缝的集成),所以,如果你的dubbo系统是单独启动的进程,你可以直接默认采用jetty即可。</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> server=<span style=color:#2aa198>&#34;tomcat&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>以上配置选用了嵌入式的tomcat来做rest server。在嵌入式tomcat上,REST的性能比jetty上要好得多(参见后面的基准测试),建议在需要高性能的场景下采用tomcat。</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> server=<span style=color:#2aa198>&#34;netty&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>以上配置选用嵌入式的netty来做rest server。(TODO more contents to add)</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> server=<span style=color:#2aa198>&#34;tjws&#34;</span><span style=color:#268bd2>/&gt;</span> (tjws is now deprecated)
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> server=<span style=color:#2aa198>&#34;sunhttp&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>以上配置选用嵌入式的tjws或Sun HTTP server来做rest server。这两个server实现非常轻量级,非常方便在集成测试中快速启动使用,当然也可以在负荷不高的生产环境中使用。 注:tjws目前已经被deprecated掉了,因为它不能很好的和servlet 3.1 API工作。</p><p>如果你的dubbo系统不是单独启动的进程,而是部署到了Java应用服务器中,则建议你采用以下配置:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> server=<span style=color:#2aa198>&#34;servlet&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>通过将server设置为servlet,dubbo将采用外部应用服务器的servlet容器来做rest server。同时,还要在dubbo系统的web.xml中添加如下配置:</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;web-app&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;context-param&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;param-name&gt;</span>contextConfigLocation<span style=color:#268bd2>&lt;/param-name&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;param-value&gt;</span>/WEB-INF/classes/META-INF/spring/dubbo-demo-provider.xml<span style=color:#268bd2>&lt;/param-value&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;/context-param&gt;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;listener&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;listener-class&gt;</span>org.apache.dubbo.remoting.http.servlet.BootstrapListener<span style=color:#268bd2>&lt;/listener-class&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;/listener&gt;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;listener&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;listener-class&gt;</span>org.springframework.web.context.ContextLoaderListener<span style=color:#268bd2>&lt;/listener-class&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;/listener&gt;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;servlet&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;servlet-name&gt;</span>dispatcher<span style=color:#268bd2>&lt;/servlet-name&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;servlet-class&gt;</span>org.apache.dubbo.remoting.http.servlet.DispatcherServlet<span style=color:#268bd2>&lt;/servlet-class&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;load-on-startup&gt;</span>1<span style=color:#268bd2>&lt;/load-on-startup&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;/servlet&gt;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;servlet-mapping&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;servlet-name&gt;</span>dispatcher<span style=color:#268bd2>&lt;/servlet-name&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;url-pattern&gt;</span>/*<span style=color:#268bd2>&lt;/url-pattern&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;/servlet-mapping&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/web-app&gt;</span>
</span></span></code></pre></div><p>即必须将dubbo的BootstrapListener和DispatherServlet添加到web.xml,以完成dubbo的REST功能与外部servlet容器的集成。</p><blockquote><p>注意:如果你是用spring的ContextLoaderListener来加载spring,则必须保证BootstrapListener配置在ContextLoaderListener之前,否则dubbo初始化会出错。</p></blockquote><p>其实,这种场景下你依然可以坚持用嵌入式server,但外部应用服务器的servlet容器往往比嵌入式server更加强大(特别是如果你是部署到更健壮更可伸缩的WebLogic,WebSphere等),另外有时也便于在应用服务器做统一管理、监控等等。</p><h3 id=获取上下文context信息>获取上下文(Context)信息</h3><p>在远程调用中,值得获取的上下文信息可能有很多种,这里特别以获取客户端IP为例。</p><p>在dubbo的REST中,我们有两种方式获取客户端IP。</p><p>第一种方式,用JAX-RS标准的@Context annotation:</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>public</span> User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id, <span style=color:#268bd2>@Context</span> HttpServletRequest request) {
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;Client address is &#34;</span> <span style=color:#719e07>+</span> request.getRemoteAddr());
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>用Context修饰getUser()的一个方法参数后,就可以将当前的HttpServletRequest注入进来,然后直接调用servlet api获取IP。</p><blockquote><p>注意:这种方式只能在将server设置为 tjws、tomcat、jetty 或者 servlet 的时候才能工作,因为只有这几种 server 的实现才提供了 servlet 容器。另外,标准的JAX-RS还支持用@Context修饰service类的一个实例字段来获取HttpServletRequest,但在dubbo中我们没有对此作出支持。</p></blockquote><p>第二种方式,用dubbo中常用的RpcContext:</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>public</span> User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id) {
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;Client address is &#34;</span> <span style=color:#719e07>+</span> RpcContext.getContext().getRemoteAddressString());
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><blockquote><p>注意:这种方式只能在设置server=&ldquo;jetty"或者server=&ldquo;tomcat"或者server=&ldquo;servlet"或者server=&ldquo;tjws"的时候才能工作。另外,目前dubbo的RpcContext是一种比较有侵入性的用法,未来我们很可能会做出重构。</p></blockquote><p>如果你想保持你的项目对JAX-RS的兼容性,未来脱离dubbo也可以运行,请选择第一种方式。如果你想要更优雅的服务接口定义,请选用第二种方式。</p><p>此外,在最新的dubbo rest中,还支持通过RpcContext来获取HttpServletRequest和HttpServletResponse,以提供更大的灵活性来方便用户实现某些复杂功能,比如在dubbo标准的filter中访问HTTP 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-java data-lang=java><span style=display:flex><span><span style=color:#719e07>if</span> (RpcContext.getContext().getRequest() <span style=color:#719e07>!=</span> <span style=color:#cb4b16>null</span> <span style=color:#719e07>&amp;&amp;</span> RpcContext.getContext().getRequest() <span style=color:#719e07>instanceof</span> HttpServletRequest) {
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;Client address is &#34;</span> <span style=color:#719e07>+</span> ((HttpServletRequest) RpcContext.getContext().getRequest()).getRemoteAddr());
</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>if</span> (RpcContext.getContext().getResponse() <span style=color:#719e07>!=</span> <span style=color:#cb4b16>null</span> <span style=color:#719e07>&amp;&amp;</span> RpcContext.getContext().getResponse() <span style=color:#719e07>instanceof</span> HttpServletResponse) {
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;Response object from RpcContext: &#34;</span> <span style=color:#719e07>+</span> RpcContext.getContext().getResponse());
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><blockquote><p>注意:为了保持协议的中立性,RpcContext.getRequest()和RpcContext.getResponse()返回的仅仅是一个Object类,而且可能为null。所以,你必须自己做null和类型的检查。</p></blockquote><blockquote><p>注意:只有在设置server=&ldquo;jetty"或者server=&ldquo;tomcat"或者server=&ldquo;servlet"的时候,你才能通过以上方法正确的得到HttpServletRequest和HttpServletResponse,因为只有这几种server实现了servlet容器。</p></blockquote><p>为了简化编程,在此你也可以用泛型的方式来直接获取特定类型的request/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-java data-lang=java><span style=display:flex><span><span style=color:#719e07>if</span> (RpcContext.getContext().getRequest(HttpServletRequest.class) <span style=color:#719e07>!=</span> <span style=color:#cb4b16>null</span>) {
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;Client address is &#34;</span> <span style=color:#719e07>+</span> RpcContext.getContext().getRequest(HttpServletRequest.class).getRemoteAddr());
</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>if</span> (RpcContext.getContext().getResponse(HttpServletResponse.class) <span style=color:#719e07>!=</span> <span style=color:#cb4b16>null</span>) {
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;Response object from RpcContext: &#34;</span> <span style=color:#719e07>+</span> RpcContext.getContext().getResponse(HttpServletResponse.class));
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>如果request/response不符合指定的类型,这里也会返回null。</p><h3 id=配置端口号和context-path>配置端口号和Context Path</h3><p>dubbo中的rest协议默认将采用80端口,如果想修改端口,直接配置:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> port=<span style=color:#2aa198>&#34;8888&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>另外,如前所述,我们可以用@Path来配置单个rest服务的URL相对路径。但其实,我们还可以设置一个所有rest服务都适用的基础相对路径,即java web应用中常说的context path。</p><p>只需要添加如下contextpath属性即可:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> port=<span style=color:#2aa198>&#34;8888&#34;</span> contextpath=<span style=color:#2aa198>&#34;services&#34;</span><span style=color:#268bd2>/&gt;</span>
</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-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>@Path</span>(<span style=color:#2aa198>&#34;/users&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>UserServiceImpl</span> <span style=color:#268bd2>implements</span> UserService {
</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:#2aa198>&#34;/register&#34;</span>)
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Consumes</span>({MediaType.APPLICATION_JSON})
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> <span style=color:#dc322f>void</span> <span style=color:#268bd2>registerUser</span>(User user) {
</span></span><span style=display:flex><span> <span style=color:#586e75>// save the user...</span>
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>现在registerUser()的完整访问路径为:</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>http://localhost:8888/services/users/register
</span></span></code></pre></div><p>注意:如果你是选用外部应用服务器做rest server,即配置:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> port=<span style=color:#2aa198>&#34;8888&#34;</span> contextpath=<span style=color:#2aa198>&#34;services&#34;</span> server=<span style=color:#2aa198>&#34;servlet&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>则必须保证这里设置的port、contextpath,与外部应用服务器的端口、DispatcherServlet的上下文路径(即webapp path加上servlet url pattern)保持一致。例如,对于部署为tomcat ROOT路径的应用,这里的contextpath必须与web.xml中DispacherServlet的<code>&lt;url-pattern/></code>完全一致:</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;servlet-mapping&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;servlet-name&gt;</span>dispatcher<span style=color:#268bd2>&lt;/servlet-name&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;url-pattern&gt;</span>/services/*<span style=color:#268bd2>&lt;/url-pattern&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/servlet-mapping&gt;</span>
</span></span></code></pre></div><h3 id=配置线程数和io线程数>配置线程数和IO线程数</h3><p>可以为rest服务配置线程池大小:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> threads=<span style=color:#2aa198>&#34;500&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><blockquote><p>注意:目前线程池的设置只有当server=&ldquo;netty"或者server=&ldquo;jetty"或者server=&ldquo;tomcat"的时候才能生效。另外,如果server=&ldquo;servlet&rdquo;,由于这时候启用的是外部应用服务器做rest server,不受dubbo控制,所以这里的线程池设置也无效。</p></blockquote><p>如果是选用netty server,还可以配置Netty的IO worker线程数:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> iothreads=<span style=color:#2aa198>&#34;5&#34;</span> threads=<span style=color:#2aa198>&#34;100&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><h3 id=配置长连接>配置长连接</h3><p>Dubbo中的rest服务默认都是采用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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> keepalive=<span style=color:#2aa198>&#34;false&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><blockquote><p>注意:这个配置目前只对server=&ldquo;netty"和server=&ldquo;tomcat"才能生效。</p></blockquote><h3 id=配置最大的http连接数>配置最大的HTTP连接数</h3><p>可以配置服务器提供端所能同时接收的最大HTTP连接数,防止REST server被过多连接撑爆,以作为一种最基本的自我保护机制:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> accepts=<span style=color:#2aa198>&#34;500&#34;</span> server=<span style=color:#2aa198>&#34;tomcat/</span><span style=color:#268bd2>&gt;</span>
</span></span></code></pre></div><blockquote><p>注意:这个配置目前只对server=&ldquo;tomcat"才能生效。</p></blockquote><h3 id=配置每个消费端的超时时间和http连接数>配置每个消费端的超时时间和HTTP连接数</h3><p>如果rest服务的消费端也是dubbo系统,可以像其他dubbo RPC机制一样,配置消费端调用此rest服务的最大超时时间以及每个消费端所能启动的最大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;dubbo:service</span> interface=<span style=color:#2aa198>&#34;xxx&#34;</span> ref=<span style=color:#2aa198>&#34;xxx&#34;</span> protocol=<span style=color:#2aa198>&#34;rest&#34;</span> timeout=<span style=color:#2aa198>&#34;2000&#34;</span> connections=<span style=color:#2aa198>&#34;10&#34;</span><span style=color:#268bd2>/&gt;</span>
</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-xml data-lang=xml><span style=display:flex><span><span style=color:#268bd2>&lt;dubbo:reference</span> id=<span style=color:#2aa198>&#34;xxx&#34;</span> interface=<span style=color:#2aa198>&#34;xxx&#34;</span> timeout=<span style=color:#2aa198>&#34;2000&#34;</span> connections=<span style=color:#2aa198>&#34;10&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>但是,通常我们建议配置在服务提供端提供此类配置。按照dubbo官方文档的说法:“Provider上尽量多配置Consumer端的属性,让Provider实现者一开始就思考Provider服务特点、服务质量的问题。”</p><blockquote><p>注意:如果dubbo的REST服务是发布给非dubbo的客户端使用,则这里<code>&lt;dubbo:service/></code>上的配置完全无效,因为这种客户端不受dubbo控制。</p></blockquote><h3 id=用annotation取代部分spring-xml配置>用Annotation取代部分Spring XML配置</h3><p>以上所有的讨论都是基于dubbo在spring中的xml配置。但是,dubbo/spring本身也支持用annotation来作配置,所以我们也可以按dubbo官方文档中的步骤,把相关annotation加到REST服务的实现中,取代一些xml配置,例如:</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>@Service</span>(protocol <span style=color:#719e07>=</span> <span style=color:#2aa198>&#34;rest&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>@Path</span>(<span style=color:#2aa198>&#34;/users&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>UserServiceImpl</span> <span style=color:#268bd2>implements</span> UserService {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Autowired</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>private</span> UserRepository userRepository;
</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:#2aa198>&#34;/register&#34;</span>)
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Consumes</span>({MediaType.APPLICATION_JSON})
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> <span style=color:#dc322f>void</span> <span style=color:#268bd2>registerUser</span>(User user) {
</span></span><span style=display:flex><span> <span style=color:#586e75>// save the user</span>
</span></span><span style=display:flex><span> userRepository.save(user);
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>annotation的配置更简单更精确,通常也更便于维护(当然现代IDE都可以在xml中支持比如类名重构,所以就这里的特定用例而言,xml的维护性也很好)。而xml对代码的侵入性更小一些,尤其有利于动态修改配置,特别是比如你要针对单个服务配置连接超时时间、每客户端最大连接数、集群策略、权重等等。另外,特别对复杂应用或者模块来说,xml提供了一个中心点来涵盖的所有组件和配置,更一目了然,一般更便于项目长时期的维护。</p><p>当然,选择哪种配置方式没有绝对的优劣,和个人的偏好也不无关系。</p><h3 id=添加自定义的filterinterceptor等>添加自定义的Filter、Interceptor等</h3><p>Dubbo的REST也支持JAX-RS标准的Filter和Interceptor,以方便对REST的请求与响应过程做定制化的拦截处理。</p><p>其中,Filter主要用于访问和设置HTTP请求和响应的参数、URI等等。例如,设置HTTP响应的cache 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-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>CacheControlFilter</span> <span style=color:#268bd2>implements</span> ContainerResponseFilter {
</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>filter</span>(ContainerRequestContext req, ContainerResponseContext res) {
</span></span><span style=display:flex><span> <span style=color:#719e07>if</span> (req.getMethod().equals(<span style=color:#2aa198>&#34;GET&#34;</span>)) {
</span></span><span style=display:flex><span> res.getHeaders().add(<span style=color:#2aa198>&#34;Cache-Control&#34;</span>, <span style=color:#2aa198>&#34;someValue&#34;</span>);
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Interceptor主要用于访问和修改输入与输出字节流,例如,手动添加GZIP压缩:</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>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>GZIPWriterInterceptor</span> <span style=color:#268bd2>implements</span> WriterInterceptor {
</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>void</span> <span style=color:#268bd2>aroundWriteTo</span>(WriterInterceptorContext context)
</span></span><span style=display:flex><span> <span style=color:#268bd2>throws</span> IOException, WebApplicationException {
</span></span><span style=display:flex><span> OutputStream outputStream <span style=color:#719e07>=</span> context.getOutputStream();
</span></span><span style=display:flex><span> context.setOutputStream(<span style=color:#719e07>new</span> GZIPOutputStream(outputStream));
</span></span><span style=display:flex><span> context.proceed();
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>在标准JAX-RS应用中,我们一般是为Filter和Interceptor添加@Provider annotation,然后JAX-RS runtime会自动发现并启用它们。而在dubbo中,我们是通过添加XML配置的方式来注册Filter和Interceptor:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> port=<span style=color:#2aa198>&#34;8888&#34;</span> extension=<span style=color:#2aa198>&#34;xxx.TraceInterceptor, xxx.TraceFilter&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>在此,我们可以将Filter、Interceptor和DynamicFeature这三种类型的对象都添加到<code>extension</code>属性上,多个之间用逗号分隔。(DynamicFeature是另一个接口,可以方便我们更动态的启用Filter和Interceptor,感兴趣请自行google。)</p><p>当然,dubbo自身也支持Filter的概念,但我们这里讨论的Filter和Interceptor更加接近协议实现的底层,相比dubbo的filter,可以做更底层的定制化。</p><blockquote><p>注:这里的XML属性叫extension,而不是叫interceptor或者filter,是因为除了Interceptor和Filter,未来我们还会添加更多的扩展类型。</p></blockquote><p>如果REST的消费端也是dubbo系统(参见下文的讨论),则也可以用类似方式为消费端配置Interceptor和Filter。但注意,JAX-RS中消费端的Filter和提供端的Filter是两种不同的接口。例如前面例子中服务端是ContainerResponseFilter接口,而消费端对应的是ClientResponseFilter:</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>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>LoggingFilter</span> <span style=color:#268bd2>implements</span> ClientResponseFilter {
</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>filter</span>(ClientRequestContext reqCtx, ClientResponseContext resCtx) <span style=color:#268bd2>throws</span> IOException {
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;status: &#34;</span> <span style=color:#719e07>+</span> resCtx.getStatus());
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;date: &#34;</span> <span style=color:#719e07>+</span> resCtx.getDate());
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;last-modified: &#34;</span> <span style=color:#719e07>+</span> resCtx.getLastModified());
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;location: &#34;</span> <span style=color:#719e07>+</span> resCtx.getLocation());
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;headers:&#34;</span>);
</span></span><span style=display:flex><span> <span style=color:#719e07>for</span> (Entry<span style=color:#719e07>&lt;</span>String, List<span style=color:#719e07>&lt;</span>String<span style=color:#719e07>&gt;&gt;</span> header : resCtx.getHeaders().entrySet()) {
</span></span><span style=display:flex><span> System.out.print(<span style=color:#2aa198>&#34;\t&#34;</span> <span style=color:#719e07>+</span> header.getKey() <span style=color:#719e07>+</span> <span style=color:#2aa198>&#34; :&#34;</span>);
</span></span><span style=display:flex><span> <span style=color:#719e07>for</span> (String value : header.getValue()) {
</span></span><span style=display:flex><span> System.out.print(value <span style=color:#719e07>+</span> <span style=color:#2aa198>&#34;, &#34;</span>);
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> System.out.print(<span style=color:#2aa198>&#34;\n&#34;</span>);
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;media-type: &#34;</span> <span style=color:#719e07>+</span> resCtx.getMediaType().getType());
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><h3 id=添加自定义的exception处理>添加自定义的Exception处理</h3><p>Dubbo的REST也支持JAX-RS标准的ExceptionMapper,可以用来定制特定exception发生后应该返回的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-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>CustomExceptionMapper</span> <span style=color:#268bd2>implements</span> ExceptionMapper<span style=color:#719e07>&lt;</span>NotFoundException<span style=color:#719e07>&gt;</span> {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> Response <span style=color:#268bd2>toResponse</span>(NotFoundException e) {
</span></span><span style=display:flex><span> <span style=color:#719e07>return</span> Response.status(Response.Status.NOT_FOUND).entity(<span style=color:#2aa198>&#34;Oops! the requested resource is not found!&#34;</span>).type(<span style=color:#2aa198>&#34;text/plain&#34;</span>).build();
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>和Interceptor、Filter类似,将其添加到XML配置文件中即可启用:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> port=<span style=color:#2aa198>&#34;8888&#34;</span> extension=<span style=color:#2aa198>&#34;xxx.CustomExceptionMapper&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><h3 id=配置http日志输出>配置HTTP日志输出</h3><p>Dubbo rest支持输出所有HTTP请求/响应中的header字段和body消息体。</p><p>在XML配置中添加如下自带的REST filter:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> port=<span style=color:#2aa198>&#34;8888&#34;</span> extension=<span style=color:#2aa198>&#34;org.apache.dubbo.rpc.protocol.rest.support.LoggingFilter&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>然后配置在logging配置中至少为org.apache.dubbo.rpc.protocol.rest.support打开INFO级别日志输出,例如,在log4j.xml中配置:</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;logger</span> name=<span style=color:#2aa198>&#34;org.apache.dubbo.rpc.protocol.rest.support&#34;</span><span style=color:#268bd2>&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;level</span> value=<span style=color:#2aa198>&#34;INFO&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;appender-ref</span> ref=<span style=color:#2aa198>&#34;CONSOLE&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/logger&gt;</span>
</span></span></code></pre></div><p>当然,你也可以直接在ROOT logger打开INFO级别日志输出:</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;root&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;level</span> value=<span style=color:#2aa198>&#34;INFO&#34;</span> <span style=color:#268bd2>/&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;appender-ref</span> ref=<span style=color:#2aa198>&#34;CONSOLE&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/root&gt;</span>
</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-fallback data-lang=fallback><span style=display:flex><span>The HTTP headers are:
</span></span><span style=display:flex><span>accept: application/json;charset=UTF-8
</span></span><span style=display:flex><span>accept-encoding: gzip, deflate
</span></span><span style=display:flex><span>connection: Keep-Alive
</span></span><span style=display:flex><span>content-length: 22
</span></span><span style=display:flex><span>content-type: application/json
</span></span><span style=display:flex><span>host: 192.168.1.100:8888
</span></span><span style=display:flex><span>user-agent: Apache-HttpClient/4.2.1 (java 1.5)
</span></span></code></pre></div><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>The contents of request body is:
</span></span><span style=display:flex><span>{&#34;id&#34;:1,&#34;name&#34;:&#34;dang&#34;}
</span></span></code></pre></div><p>打开HTTP日志输出后,除了正常日志输出的性能开销外,也会在比如HTTP请求解析时产生额外的开销,因为需要建立额外的内存缓冲区来为日志的输出做数据准备。</p><h3 id=输入参数的校验>输入参数的校验</h3><p>dubbo的rest支持采用Java标准的bean validation annotation(JSR 303)来做输入校验http://beanvalidation.org/</p><p>为了和其他dubbo远程调用协议保持一致,在rest中作校验的annotation必须放在服务的接口上,例如:</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>public</span> <span style=color:#268bd2>interface</span> <span style=color:#268bd2>UserService</span> {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@Min</span>(value<span style=color:#719e07>=</span>1L, message<span style=color:#719e07>=</span><span style=color:#2aa198>&#34;User ID must be greater than 1&#34;</span>) Long id);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>当然,在很多其他的bean validation的应用场景都是将annotation放到实现类而不是接口上。把annotation放在接口上至少有一个好处是,dubbo的客户端可以共享这个接口的信息,dubbo甚至不需要做远程调用,在本地就可以完成输入校验。</p><p>然后按照dubbo的标准方式在XML配置中打开验证:</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;dubbo:service</span> interface=<span style=color:#2aa198>xxx.UserService&#34;</span> ref=<span style=color:#2aa198>&#34;userService&#34;</span> protocol=<span style=color:#2aa198>&#34;rest&#34;</span> validation=<span style=color:#2aa198>&#34;true&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>在dubbo的其他很多远程调用协议中,如果输入验证出错,是直接将<code>RpcException</code>抛向客户端,而在rest中由于客户端经常是非dubbo,甚至非java的系统,所以不便直接抛出Java异常。因此,目前我们将校验错误以XML的格式返回:</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;violationReport&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;constraintViolations&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;path&gt;</span>getUserArgument0<span style=color:#268bd2>&lt;/path&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;message&gt;</span>User ID must be greater than 1<span style=color:#268bd2>&lt;/message&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;value&gt;</span>0<span style=color:#268bd2>&lt;/value&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;/constraintViolations&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/violationReport&gt;</span>
</span></span></code></pre></div><p>稍后也会支持其他数据格式的返回值。至于如何对验证错误消息作国际化处理,直接参考bean validation的相关文档即可。</p><p>如果你认为默认的校验错误返回格式不符合你的要求,可以如上面章节所述,添加自定义的ExceptionMapper来自由的定制错误返回格式。需要注意的是,这个ExceptionMapper必须用泛型声明来捕获dubbo的RpcException,才能成功覆盖dubbo rest默认的异常处理策略。为了简化操作,其实这里最简单的方式是直接继承dubbo rest的RpcExceptionMapper,并覆盖其中处理校验异常的方法即可:</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>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>MyValidationExceptionMapper</span> <span style=color:#268bd2>extends</span> RpcExceptionMapper {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>protected</span> Response <span style=color:#268bd2>handleConstraintViolationException</span>(ConstraintViolationException cve) {
</span></span><span style=display:flex><span> ViolationReport report <span style=color:#719e07>=</span> <span style=color:#719e07>new</span> ViolationReport();
</span></span><span style=display:flex><span> <span style=color:#719e07>for</span> (ConstraintViolation cv : cve.getConstraintViolations()) {
</span></span><span style=display:flex><span> report.addConstraintViolation(<span style=color:#719e07>new</span> RestConstraintViolation(
</span></span><span style=display:flex><span> cv.getPropertyPath().toString(),
</span></span><span style=display:flex><span> cv.getMessage(),
</span></span><span style=display:flex><span> cv.getInvalidValue() <span style=color:#719e07>==</span> <span style=color:#cb4b16>null</span> <span style=color:#719e07>?</span> <span style=color:#2aa198>&#34;null&#34;</span> : cv.getInvalidValue().toString()));
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> <span style=color:#586e75>// 采用json输出代替xml输出</span>
</span></span><span style=display:flex><span> <span style=color:#719e07>return</span> Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(report).type(ContentType.APPLICATION_JSON_UTF_8).build();
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>然后将这个ExceptionMapper添加到XML配置中即可:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> port=<span style=color:#2aa198>&#34;8888&#34;</span> extension=<span style=color:#2aa198>&#34;xxx.MyValidationExceptionMapper&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><div id=pre-footer><h2>反馈</h2><p class=feedback--prompt>此页是否对您有帮助?</p><button class="btn btn-primary mb-4 feedback--yes"></button>
<button class="btn btn-primary mb-4 feedback--no"></button></div><script>const yes=document.querySelector(".feedback--yes"),no=document.querySelector(".feedback--no");document.querySelectorAll(".feedback--link").forEach(e=>{e.href=e.href+window.location.pathname});const sendFeedback=e=>{gtag||console.log("!gtag"),gtag("event","click",{event_category:"Helpful",event_label:window.location.pathname,value:e})},disableButtons=()=>{yes.disabled=!0,yes.classList.add("feedback--button__disabled"),no.disabled=!0,no.classList.add("feedback--button__disabled")};yes.addEventListener("click",()=>{sendFeedback(1),disableButtons(),document.querySelector(".feedback--response").classList.remove("feedback--response__hidden")}),no.addEventListener("click",()=>{sendFeedback(0),disableButtons(),document.querySelector(".feedback--response").classList.remove("feedback--response__hidden")})</script><br><div class="text-muted mt-5 pt-3 border-top">最后修改 March 1, 2023: <a href=https://github.com/apache/dubbo-website/commit/f2070b3fdd1b7b200db0f8f2a50fb09d7c398a64>Add /zh/ docs aliases (#2336) (f2070b3fdd)</a></div></div></main><div class="d-none d-xl-block col-xl-2 td-toc d-print-none"><div class="td-page-meta ml-2 pb-1 pt-2 mb-0"><a href=https://github.com/apache/dubbo-website/edit/master/content/zh-cn/docsv2.7/user/references/protocol/rest.md target=_blank><i class="fa fa-edit fa-fw"></i> 编辑此页</a>
<a href="https://github.com/apache/dubbo-website/new/master/content/zh-cn/docsv2.7/user/references/protocol/rest.md?filename=change-me.md&amp;value=---%0Atitle%3A+%22Long+Page+Title%22%0AlinkTitle%3A+%22Short+Nav+Title%22%0Aweight%3A+100%0Adescription%3A+%3E-%0A+++++Page+description+for+heading+and+indexes.%0A---%0A%0A%23%23+Heading%0A%0AEdit+this+template+to+create+your+new+page.%0A%0A%2A+Give+it+a+good+name%2C+ending+in+%60.md%60+-+e.g.+%60getting-started.md%60%0A%2A+Edit+the+%22front+matter%22+section+at+the+top+of+the+page+%28weight+controls+how+its+ordered+amongst+other+pages+in+the+same+directory%3B+lowest+number+first%29.%0A%2A+Add+a+good+commit+message+at+the+bottom+of+the+page+%28%3C80+characters%3B+use+the+extended+description+field+for+more+detail%29.%0A%2A+Create+a+new+branch+so+you+can+preview+your+new+file+and+request+a+review+via+Pull+Request.%0A" target=_blank><i class="fa fa-edit fa-fw"></i> 创建子页面</a>
<a href="https://github.com/apache/dubbo-website/issues/new?title=rest%20%e5%8d%8f%e8%ae%ae" target=_blank><i class="fab fa-github fa-fw"></i> 登记问题</a>
<a href=https://github.com/apache/dubbo/issues/new target=_blank><i class="fas fa-tasks fa-fw"></i> 提交项目问题</a></div><nav id=TableOfContents><ul><li><a href=#快速入门>快速入门</a></li><li><a href=#rest服务提供端详解>REST服务提供端详解</a><ul><li><a href=#http-postget的实现>HTTP POST/GET的实现</a></li><li><a href=#annotation放在接口类还是实现类>Annotation放在接口类还是实现类</a></li><li><a href=#jsonxml等多数据格式的支持>JSON、XML等多数据格式的支持</a></li><li><a href=#中文字符支持>中文字符支持</a></li><li><a href=#xml数据格式的额外要求>XML数据格式的额外要求</a></li><li><a href=#定制序列化>定制序列化</a></li><li><a href=#配置rest-server的实现>配置REST Server的实现</a></li><li><a href=#获取上下文context信息>获取上下文(Context)信息</a></li><li><a href=#配置端口号和context-path>配置端口号和Context Path</a></li><li><a href=#配置线程数和io线程数>配置线程数和IO线程数</a></li><li><a href=#配置长连接>配置长连接</a></li><li><a href=#配置最大的http连接数>配置最大的HTTP连接数</a></li><li><a href=#配置每个消费端的超时时间和http连接数>配置每个消费端的超时时间和HTTP连接数</a></li><li><a href=#用annotation取代部分spring-xml配置>用Annotation取代部分Spring XML配置</a></li><li><a href=#添加自定义的filterinterceptor等>添加自定义的Filter、Interceptor等</a></li><li><a href=#添加自定义的exception处理>添加自定义的Exception处理</a></li><li><a href=#配置http日志输出>配置HTTP日志输出</a></li><li><a href=#输入参数的校验>输入参数的校验</a></li></ul></li></ul></nav></div></div></div></div><footer class="bg-dark py-5 row d-print-none footer-margin-0"><div class="container-fluid mx-sm-5"><div class=row><div class="col-6 col-sm-4 text-xs-center order-sm-2"><ul class="list-inline mb-0"><li class="list-inline-item mx-2 h3" data-toggle=tooltip data-placement=top title="Dubbo mailing list archive" aria-label="Dubbo mailing list archive"><a class=text-white target=_blank rel="noopener noreferrer" href=https://lists.apache.org/list.html?dev@dubbo.apache.org><i class="fa fa-envelope"></i></a></li></ul></div><div class="col-6 col-sm-4 text-right text-xs-center order-sm-3"><ul class="list-inline mb-0"><li class="list-inline-item mx-2 h3" data-toggle=tooltip data-placement=top title=GitHub aria-label=GitHub><a class=text-white target=_blank rel="noopener noreferrer" href=https://github.com/apache/dubbo><i class="fab fa-github"></i></a></li><li class="list-inline-item mx-2 h3" data-toggle=tooltip data-placement=top title="Subscribe to mailing list" aria-label="Subscribe to mailing list"><a class=text-white target=_blank rel="noopener noreferrer" href=mailto:dev-subscribe@dubbo.apache.org><i class="fa fa-envelope"></i></a></li></ul></div><div class="col-12 col-sm-4 text-center py-2 order-sm-2"><small class=text-white>&copy; 2023 The Apache Software Foundation. Apache and the Apache feather logo are trademarks of The Apache Software Foundation. 保留所有权利</small></div></div></div></footer><div class="row pt-2 pb-2 footer-margin-0"><div class="container-fluid mx-sm-5"><div class=text-center id=my-footer><img style=float:left alt=apache_logo src=/imgs/apache_logo.png><ul><li><a href=https://www.apache.org>Foundation</a></li><li><a href=https://www.apache.org/licenses/>License</a></li><li><a href=https://dubbo.apache.org/en/docs/notices/security/>Security</a></li><li><a href=https://www.apache.org/events/current-event>Events</a></li><li><a href=https://www.apache.org/foundation/sponsorship.html>Sponsorship</a></li><li><a href=https://privacy.apache.org/policies/privacy-policy-public.html>Privacy</a></li><li><a href=https://www.apache.org/foundation/thanks.html>Thanks</a></li></ul></div></div></div><script src=/js/popper.min.js integrity=sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49 crossorigin=anonymous></script><script src=/js/bootstrap.min.js integrity=sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy crossorigin=anonymous></script><script src=/js/main.min.a4534a01940be8c082c4c0e6777b61df9884f202b61c9519352adb6d1039d5aa.js integrity="sha256-pFNKAZQL6MCCxMDmd3th35iE8gK2HJUZNSrbbRA51ao=" crossorigin=anonymous></script><script src=https://cdn.jsdelivr.net/npm/@docsearch/js@3></script><script>docsearch({appId:"L5F4T9F0I1",apiKey:"364ae307e1da9d02b2335675e9db1eb1",indexName:"apache_dubbo",container:"#docsearch",debug:!1}),docsearch({appId:"L5F4T9F0I1",apiKey:"364ae307e1da9d02b2335675e9db1eb1",indexName:"apache_dubbo",container:"#docsearch_zh_home",debug:!1})</script></body></html>