blob: 95ca47e5ef4355f5fdfcd38131c9874167b7b616 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<title>Examples-zh - Dubbo - Alibaba Open Sesame</title>
<meta http-equiv="X-UA-Compatible" content="IE=8">
<meta charset="UTF-8">
<!-- Deprecated since 3.4. To be removed in a future version of Confluence; use AJS.Confluence.getContextPath() -->
<meta id="confluence-context-path" name="confluence-context-path" content="/wiki">
<meta name="ajs-context-path" content="/wiki">
<meta name="ajs-version-number" content="3.5.9">
<meta name="ajs-build-number" content="2166">
<meta id="atlassian-token" name="atlassian-token" content="c116db80711201b36e2067aa83f3b044c2d5a30e">
<meta id="confluence-space-key" name="confluence-space-key" content="dubbo">
<meta name="ajs-remote-user" content="">
<meta name="ajs-static-resource-url-prefix" content="/wiki/s/en/2166/34/_">
<script type="text/javascript">
// Deprecated global variables. To be removed in a future version of Confluence.
var contextPath = '/wiki';
</script>
<!-- include system css resources -->
<link type="text/css" rel="stylesheet" href="batch.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/26/_/download/superbatch/css/batch.css" media="all">
<!--[if IE]>
<link type="text/css" rel="stylesheet" href="batch.css-ieonly=true.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/26/_/download/superbatch/css/batch.css?ieonly=true" media="all">
<![endif]-->
<link type="text/css" rel="stylesheet" href="batch.css-media=print.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/26/_/download/superbatch/css/batch.css?media=print" media="print">
<link type="text/css" rel="stylesheet" href="com.atlassian.confluence.ext.newcode-macro-plugin-syntaxhighlighter.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.9.10/_/download/batch/com.atlassian.confluence.ext.newcode-macro-plugin:syntaxhighlighter/com.atlassian.confluence.ext.newcode-macro-plugin:syntaxhighlighter.css" media="all">
<link type="text/css" rel="stylesheet" href="com.atlassian.confluence.ext.newcode-macro-plugin-sh-theme-confluence.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.9.10/_/download/batch/com.atlassian.confluence.ext.newcode-macro-plugin:sh-theme-confluence/com.atlassian.confluence.ext.newcode-macro-plugin:sh-theme-confluence.css" media="all">
<link type="text/css" rel="stylesheet" href="confluence-forms.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.0/_/download/resources/confluence.web.resources:aui-forms/confluence-forms.css" media="all">
<!--[if IE]>
<link type="text/css" rel="stylesheet" href="confluence.web.resources-aui-forms.css-ieonly=true.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.0/_/download/batch/confluence.web.resources:aui-forms/confluence.web.resources:aui-forms.css?ieonly=true" media="all">
<![endif]-->
<link type="text/css" rel="stylesheet" href="com.atlassian.confluence.plugins.share-page-mail-page-resources.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.8/_/download/batch/com.atlassian.confluence.plugins.share-page:mail-page-resources/com.atlassian.confluence.plugins.share-page:mail-page-resources.css" media="all">
<link type="text/css" rel="stylesheet" href="confluence.web.resources-view-comment.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.0/_/download/batch/confluence.web.resources:view-comment/confluence.web.resources:view-comment.css" media="all">
<!--[if IE]>
<link type="text/css" rel="stylesheet" href="confluence.web.resources-view-comment.css-ieonly=true.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.0/_/download/batch/confluence.web.resources:view-comment/confluence.web.resources:view-comment.css?ieonly=true" media="all">
<![endif]-->
<link type="text/css" rel="stylesheet" href="confluence.macros.advanced-fancy-box.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.16/_/download/batch/confluence.macros.advanced:fancy-box/confluence.macros.advanced:fancy-box.css" media="all">
<link type="text/css" rel="stylesheet" href="com.atlassian.confluence.plugins.drag-and-drop-support.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.0.16/_/download/batch/com.atlassian.confluence.plugins.drag-and-drop:support/com.atlassian.confluence.plugins.drag-and-drop:support.css" media="all">
<link type="text/css" rel="stylesheet" href="com.atlassian.plugins.shortcuts.atlassian-shortcuts-module-shortcuts.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/0.8/_/download/batch/com.atlassian.plugins.shortcuts.atlassian-shortcuts-module:shortcuts/com.atlassian.plugins.shortcuts.atlassian-shortcuts-module:shortcuts.css" media="all">
<link type="text/css" rel="stylesheet" href="com.atlassian.confluence.keyboardshortcuts-confluence-keyboard-shortcuts.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/3.5.9/_/download/batch/com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts/com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts.css" media="all">
<!-- end system css resources -->
<link rel="stylesheet" href="combined.css-spaceKey=dubbo.css" tppabs="http://10.20.160.198/wiki/s/en/2166/34/3/_/styles/combined.css?spaceKey=dubbo" type="text/css">
<meta name="confluence-request-time" content="1392025400271">
<meta name="loggedInUsername" content="">
<meta name="ajs-keyboardshortcut-hash" content="bf02a79603372a43d395a0a429bdf66">
<!-- Deprecated since 3.4. To be removed in a future version of Confluence; use atl.header -->
<script type="text/x-template" title="share-content-popup">
<form action="#" method="post" class="aui share-content-popup">
<fieldset>
<label for="users">User name or email</label>
<div class="autocomplete-user-target">
<input class="text autocomplete-sharepage" id="users" data-max="10" data-dropdown-target=".autocomplete-user-target" data-none-message="No matching user or email found"/>
</div>
<ol class="recipients">
</ol>
<div><label for="note">Note</label></div>
<textarea class="textarea" id="note" placeholder="Add an optional note"/>
</fieldset>
<div class="button-panel">
<div class="progress-messages-icon"></div>
<div class="progress-messages">
</div>
<input class="button submit" type="submit" value="Share" disabled/>
<a class="close-dialog" href="#">Cancel</a>
</div>
</form>
</script>
<script type="text/x-template" title="share-content-popup-recipient-username">
<li data-username="{username}" style="display: none">
<span>
<img src="{thumbnailLink.href}" title="{title}">
<span>{title}</span>
<span class="remove-recipient"/>
</span>
</li>
</script>
<script type="text/x-template" title="share-content-popup-recipient-email">
<li data-email="{email}" style="display: none">
<span>
<img src="{icon}" title="{email}">
<span>{email}</span>
<span class="remove-recipient"/>
</span>
</li>
</script>
<meta name="ajs-use-keyboard-shortcuts" content="true">
<link rel="shortcut icon" href="/wiki/favicon.ico">
<link rel="icon" type="image/png" href="/wiki/s/en/2166/34/_/images/logo/confluence_16.png">
<link rel="search" type="application/opensearchdescription+xml" href="/wiki/opensearch/osd.action" title="Alibaba Open Sesame"/>
<!-- include system javascript resources -->
<script type="text/javascript" src="batch.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/26/_/download/superbatch/js/batch.js" ></script>
<script type="text/javascript" src="com.atlassian.confluence.ext.newcode-macro-plugin-syntaxhighlighter.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.9.10/_/download/batch/com.atlassian.confluence.ext.newcode-macro-plugin:syntaxhighlighter/com.atlassian.confluence.ext.newcode-macro-plugin:syntaxhighlighter.js" ></script>
<script type="text/javascript" src="com.atlassian.confluence.ext.newcode-macro-plugin-syntaxhighlighter-brushes.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.9.10/_/download/batch/com.atlassian.confluence.ext.newcode-macro-plugin:syntaxhighlighter-brushes/com.atlassian.confluence.ext.newcode-macro-plugin:syntaxhighlighter-brushes.js" ></script>
<script type="text/javascript" src="com.atlassian.confluence.plugins.share-page-mail-page-resources.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.8/_/download/batch/com.atlassian.confluence.plugins.share-page:mail-page-resources/com.atlassian.confluence.plugins.share-page:mail-page-resources.js" ></script>
<script type="text/javascript" src="confluence.macros.advanced-fancy-box.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.16/_/download/batch/confluence.macros.advanced:fancy-box/confluence.macros.advanced:fancy-box.js" ></script>
<script type="text/javascript" src="confluence.macros.advanced-thumbnail-images.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.16/_/download/batch/confluence.macros.advanced:thumbnail-images/confluence.macros.advanced:thumbnail-images.js" ></script>
<script type="text/javascript" src="com.atlassian.confluence.plugins.drag-and-drop-support.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.0.16/_/download/batch/com.atlassian.confluence.plugins.drag-and-drop:support/com.atlassian.confluence.plugins.drag-and-drop:support.js" ></script>
<script type="text/javascript" src="com.atlassian.confluence.plugins.drag-and-drop-drag-and-drop-for-view-content.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.0.16/_/download/batch/com.atlassian.confluence.plugins.drag-and-drop:drag-and-drop-for-view-content/com.atlassian.confluence.plugins.drag-and-drop:drag-and-drop-for-view-content.js" ></script>
<script type="text/javascript" src="com.atlassian.confluence.plugins.doctheme-splitter.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.9/_/download/batch/com.atlassian.confluence.plugins.doctheme:splitter/com.atlassian.confluence.plugins.doctheme:splitter.js" ></script>
<script type="text/javascript" src="com.atlassian.plugins.shortcuts.atlassian-shortcuts-module-shortcuts.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/0.8/_/download/batch/com.atlassian.plugins.shortcuts.atlassian-shortcuts-module:shortcuts/com.atlassian.plugins.shortcuts.atlassian-shortcuts-module:shortcuts.js" ></script>
<script type="text/javascript" src="com.atlassian.confluence.keyboardshortcuts-confluence-keyboard-shortcuts.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/3.5.9/_/download/batch/com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts/com.atlassian.confluence.keyboardshortcuts:confluence-keyboard-shortcuts.js" ></script>
<script type="text/javascript" src="legacy.confluence.web.resources-prototype.js" tppabs="http://10.20.160.198/wiki/s/en/2166/34/1.0/_/download/batch/legacy.confluence.web.resources:prototype/legacy.confluence.web.resources:prototype.js" ></script>
<!-- end system javascript resources -->
<link rel="canonical" href="http://code.alibabatech.com/wiki/display/dubbo/Examples-zh">
<link rel="shortlink" href="http://code.alibabatech.com/wiki/x/9ANq">
<meta name="wikilink" content="[dubbo:Examples-zh]">
<meta name="page-version" content="86">
</head>
<body onload="placeFocus()"
id="com-atlassian-confluence" class="theme-default ">
<ul id="assistive-skip-links" class="assistive">
<li><a href="#title-heading">Skip to content</a></li>
<li><a href="#breadcrumbs">Skip to breadcrumbs</a></li>
<li><a href="#header-menu-bar">Skip to header menu</a></li>
<li><a href="#navigation">Skip to action menu</a></li>
<li><a href="#quick-search-query">Skip to quick search</a></li>
</ul>
<div id="page">
<div id="full-height-container">
<fieldset class="hidden parameters">
<input type="hidden" id="shortcutDialogTip" value="Shortcut tip: Pressing <b>{shortcut}</b> also opens this dialog box">
<input type="hidden" title="i18n.close.name" value="Close">
<input type="hidden" title="i18n.cancel.name" value="Cancel">
</fieldset><fieldset class="hidden parameters">
<input type="hidden" id="statusDialogHeading" value="What are you working on?">
<input type="hidden" id="statusDialogAccessibilityLabel" value="Enter your status (140 character limit)">
<input type="hidden" id="statusDialogLatestLabel" value="Last update:">
<input type="hidden" id="statusDialogUpdateButtonLabel" value="Update">
<input type="hidden" id="statusDialogCancelButtonLabel" value="Cancel">
</fieldset>
<fieldset class="hidden parameters">
<input type="hidden" id="globalSettingsAttachmentMaxSize" value="10485760">
<input type="hidden" id="userLocale" value="en_GB">
<input type="hidden" id="staticResourceUrlPrefix" value="/wiki/s/en/2166/34/_">
<input type="hidden" id="contextPath" value="/wiki">
</fieldset>
<div id="header" class="" style="display: none">
<form id="quick-search" class="quick-search" method="get" action="http://10.20.160.198/wiki/dosearchsite.action">
<fieldset>
<label class="assistive" for="quick-search-query">Quick Search</label>
<input class="quick-search-query" id="quick-search-query" type="text" accessKey="q" autocomplete="off" name="queryString" size="25" title="Quick Search" />
<input class="quick-search-submit" id="quick-search-submit" type="submit" value="Search" />
<div class="aui-dd-parent quick-nav-drop-down"><!-- Quick nav appears here --></div>
</fieldset>
<fieldset class="hidden parameters">
<input type="hidden" id="quickNavEnabled" value="true" />
</fieldset>
</form>
<ul id="header-menu-bar" class="ajs-menu-bar">
<li class="normal ajs-menu-item">
<a id="browse-menu-link" class="browse trigger ajs-menu-title" href="#"><span><span>Browse</span></span></a> <div class="assistive ajs-drop-down">
<ul id="browse-menu-link-leading" class="section-leading first">
<li>
<a id="space-pages-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/listpages.action?key=dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/listpages.action?key=dubbo%27" tppabs="http://10.20.160.198/wiki/pages/listpages.action?key=dubbo" class="" title="Browse pages in the Dubbo space">
<span>Pages</span></a> </li>
<li>
<a id="space-blogposts-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/viewrecentblogposts.action?key=dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/viewrecentblogposts.action?key=dubbo%27" tppabs="http://10.20.160.198/wiki/pages/viewrecentblogposts.action?key=dubbo" class="" title="Browse blogs in the Dubbo space">
<span>Blog</span></a> </li>
<li>
<a id="space-labels-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/labels/listlabels-heatmap.action?key=dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/labels/listlabels-heatmap.action?key=dubbo%27" tppabs="http://10.20.160.198/wiki/labels/listlabels-heatmap.action?key=dubbo" class="" title="Browse labels in the Dubbo space">
<span>Labels</span></a> </li>
<li>
<a id="space-attachments-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/spaces/listattachmentsforspace.action?key=dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/spaces/listattachmentsforspace.action?key=dubbo%27" tppabs="http://10.20.160.198/wiki/spaces/listattachmentsforspace.action?key=dubbo" class="" title="Browse attachments in the Dubbo space">
<span>Attachments</span></a> </li>
<li>
<a id="space-mail-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/spaces/viewmailarchive.action?key=dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/spaces/viewmailarchive.action?key=dubbo%27" tppabs="http://10.20.160.198/wiki/spaces/viewmailarchive.action?key=dubbo" class="" title="Browse mail in the Dubbo space">
<span>Mail</span></a> </li>
<li>
<a id="space-advanced-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/spaces/viewspacesummary.action?key=dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/spaces/viewspacesummary.action?key=dubbo%27" tppabs="http://10.20.160.198/wiki/spaces/viewspacesummary.action?key=dubbo" class="" title="Browse additional space functions in the Dubbo space">
<span>Advanced</span></a> </li>
<li>
<a href="javascript:if(confirm(%27http://10.20.160.198/wiki/spaces/usage/report.action?key=dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/spaces/usage/report.action?key=dubbo%27" tppabs="http://10.20.160.198/wiki/spaces/usage/report.action?key=dubbo" class="" title="">
<span>Activity</span></a> </li>
</ul>
<ul id="browse-menu-link-global" class="section-global">
<li>
<a id="whats-new-menu-link" href="javascript:if(confirm(%27http://docs.atlassian.com/confluence/docs-35/whatsnew/iframe \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://docs.atlassian.com/confluence/docs-35/whatsnew/iframe%27" tppabs="http://docs.atlassian.com/confluence/docs-35/whatsnew/iframe" class="" title="">
<span>What’s New</span></a> </li>
<li>
<a id="people-directory-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/peopledirectory.action \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/peopledirectory.action%27" tppabs="http://10.20.160.198/wiki/peopledirectory.action" class="" title="Browse the Confluence people directory">
<span>People Directory</span></a> </li>
<li>
<a id="space-directory-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/spacedirectory/view.action \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/spacedirectory/view.action%27" tppabs="http://10.20.160.198/wiki/spacedirectory/view.action" class="" title="Browse the Confluence space directory">
<span>Space Directory</span></a> </li>
<li>
<a id="keyboard-shortcuts-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki%27" tppabs="http://10.20.160.198/wiki" class="" title="View available keyboard shortcuts">
<span>Keyboard Shortcuts</span></a> </li>
<li>
<a id="gadget-directory-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki%27" tppabs="http://10.20.160.198/wiki" class="user-item administration-link" title="Browse gadgets provided by Confluence">
<span>Confluence Gadgets</span></a> </li>
</ul>
</div>
</li>
<li class="ajs-menu-item normal">
<a id="login-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/login.action?os_destination=%2Fdisplay%2Fdubbo%2FExamples-zh \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/login.action?os_destination=%2Fdisplay%2Fdubbo%2FExamples-zh%27" tppabs="http://10.20.160.198/wiki/login.action?os_destination=%2Fdisplay%2Fdubbo%2FExamples-zh" class="user-item login-link" title="">
<span>Log In</span></a> </li>
</ul>
<ol id="breadcrumbs">
<li class="first" >
<span><a href="javascript:if(confirm(%27http://10.20.160.198/wiki/dashboard.action \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/dashboard.action%27" tppabs="http://10.20.160.198/wiki/dashboard.action" title="Go to Dashboard">Dashboard</a></span>
</li>
<li>
<span><a href="javascript:if(confirm(%27http://10.20.160.198/wiki/display/dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/display/dubbo%27" tppabs="http://10.20.160.198/wiki/display/dubbo">Dubbo</a></span>
</li>
<li id="ellipsis" title="Show all breadcrumbs"><span><strong>&#8230;</strong></span></li>
<li class="hidden-crumb" >
<span><a href="Home-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Home-zh">Home-zh</a></span>
</li>
<li>
<span><a href="User+Guide-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/User+Guide-zh">User Guide-zh</a></span>
</li>
<li>
<span>Examples-zh</span>
</li>
</ol>
</div><!-- \#header -->
<div id="main" >
<div id="navigation" class="content-navigation view" style="display: none">
<fieldset class="hidden parameters">
<input type="hidden" id="pageId" value="6947828">
</fieldset>
<ul class="ajs-menu-bar">
<li class="normal ajs-menu-item">
<a id="add-menu-link" class="add trigger ajs-menu-title" href="#"><span><span>Add</span></span></a> <div class="assistive ajs-drop-down">
<ul id="add-menu-link-page" class="section-page first">
<li>
<a id="add-comment-menu-link" href="Examples-zh-showComments=true&showCommentArea=true.htm#addcomment" tppabs="http://10.20.160.198/wiki/display/dubbo/Examples-zh?showComments=true&showCommentArea=true#addcomment" class="add-comment" title="Add a Comment">
<span>Comment</span></a> </li>
</ul>
</div>
</li>
<li class="normal ajs-menu-item">
<a id="action-menu-link" class="action trigger ajs-menu-title" href="#"><span><span>Tools</span></span></a> <div class="assistive ajs-drop-down">
<ul id="action-menu-link-primary" class="section-primary first">
<li>
<a id="view-attachments-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/viewpageattachments.action?pageId=6947828 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/viewpageattachments.action?pageId=6947828%27" tppabs="http://10.20.160.198/wiki/pages/viewpageattachments.action?pageId=6947828" class="action-view-attachments" accessKey="a" title="View Attachments">
<span><u>A</u>ttachments (0)</span></a> </li>
<li>
<a id="action-view-history-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/viewpreviousversions.action?pageId=6947828 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/viewpreviousversions.action?pageId=6947828%27" tppabs="http://10.20.160.198/wiki/pages/viewpreviousversions.action?pageId=6947828" class="action-view-history" title="">
<span>Page History</span></a> </li>
<li>
<a id="action-page-permissions-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6947828 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6947828%27" tppabs="http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6947828" class="action-page-permissions" title="Edit restrictions">
<span>Restrictions</span></a> </li>
</ul>
<ul id="action-menu-link-secondary" class="section-secondary">
<li>
<a id="view-page-info-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6947828 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6947828%27" tppabs="http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6947828" class="action-view-info" title="">
<span>Info</span></a> </li>
<li>
<a id="link-to-page-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6947828 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6947828%27" tppabs="http://10.20.160.198/wiki/pages/viewinfo.action?pageId=6947828" class="" title="Link to this Page">
<span>Link to this Page&hellip;</span></a> </li>
<li>
<a id="view-in-hierarchy-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/listpages-dirview.action?key=dubbo&openId=6947828 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/listpages-dirview.action?key=dubbo&openId=6947828#selectedPageInHierarchy%27" tppabs="http://10.20.160.198/wiki/pages/listpages-dirview.action?key=dubbo&openId=6947828#selectedPageInHierarchy" class="" title="">
<span>View in Hierarchy</span></a> </li>
<li>
<a id="action-view-source-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/viewpagesrc.action?pageId=6947828 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/viewpagesrc.action?pageId=6947828%27" tppabs="http://10.20.160.198/wiki/pages/viewpagesrc.action?pageId=6947828" class="action-view-source popup-link" title="">
<span>View Wiki Markup</span></a> </li>
</ul>
</div>
</li>
</ul>
</div>
<h1 id="title-heading" class="pagetitle" style="display: none">
<a href="javascript:if(confirm(%27http://10.20.160.198/wiki/display/dubbo \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/display/dubbo%27" tppabs="http://10.20.160.198/wiki/display/dubbo"><img class="logo space custom" src="dubbo-version=5&modificationDate=1320723683000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/6324241/dubbo?version=5&modificationDate=1320723683000" alt=""></a>
</h1>
<div id="content" class="page view">
<div id="link-to-page-fields" class="hidden parameters">
<input type="hidden" id="linkToThisPageHeading" value="Link to this Page">
<input type="hidden" id="linkToThisPageLink" value="Link">
<input type="hidden" id="linkToThisPageTinyLink" value="Tiny Link">
<input type="hidden" id="linkToThisPageWikiMarkup" value="Wiki Markup">
<input type="hidden" id="linkToThisPageClose" value="Close">
</div>
<fieldset class="hidden parameters">
<input type="hidden" title="movePageDialogViewPageTitle" value="Move Page &ndash; &#8216;Examples-zh&#8217;">
<input type="hidden" title="movePageDialogEditPageTitle" value="Set Page Location">
<input type="hidden" title="movePageDialogMoveButton" value="Move">
<input type="hidden" title="movePageDialogCancelButton" value="Cancel">
<input type="hidden" title="movePageDialogBrowsePanelTip" value="Click to select the new parent page for this page and its children.">
<input type="hidden" title="movePageDialogSearchPanel" value="Search">
<input type="hidden" title="movePageDialogHistoryPanel" value="Recently Viewed">
<input type="hidden" title="movePageDialogHistoryNoResults" value="There were no recently viewed pages found.">
<input type="hidden" title="movePageDialogLocationPanel" value="Known Location">
<input type="hidden" title="movePageDialogLocationNotFound" value="The specified page was not found.">
<input type="hidden" title="movePageDialogBrowsePanel" value="Browse">
<input type="hidden" title="movePageDialogPanelLoadErrorMsg" value="Error reading the panel content from the server.">
<input type="hidden" title="movePageDialogPanelLoadErrorTip" value="You could try reloading the page and launching the dialog again.">
<input type="hidden" title="movePageDialogPanelLoadErrorStatus" value="HTTP Status">
<input type="hidden" title="movePageDialogNoSelectionErrorMsg" value="You must make a selection in the tree before you can move the page.">
<input type="hidden" title="movePageDialogSearchError" value="Failed to retrieve search results from the server.">
<input type="hidden" title="movePageDialogSearchNoResults" value="There were no pages found containing <b>{0}</b>.">
<input type="hidden" title="movePageDialogSearchResultCount" value="Showing <b>{0}</b>-<b>{1}</b> of <b>{2}</b> pages containing <b>{3}</b>.">
<input type="hidden" title="movePageDialogMoveFailed" value="Move failed. There was a problem contacting the server.">
<input type="hidden" title="movePageDialogCannotChangeSpace" value="You cannot move this page to another space because you do not have permission to remove it from this space.">
<input type="hidden" title="pageTitle" value="Examples-zh"/>
<input type="hidden" title="parentPageTitle" value="User Guide-zh"/>
<input type="hidden" title="fromPageTitle" value=""/>
<input type="hidden" title="spaceKey" value="dubbo"/>
<input type="hidden" title="spaceName" value="Dubbo"/>
<input type="hidden" title="movePageDialogInvalidLocation" value="You cannot move a page to be underneath itself or its children."/>
<input type="hidden" title="movePageDialogOrderingTitle" value="Page Ordering"/>
<input type="hidden" title="movePageDialogBackButton" value="Back"/>
<input type="hidden" title="movePageDialogMoveAndOrderButton" value="Reorder"/>
<input type="hidden" title="movePageDialogNextButton" value="Move"/>
</fieldset>
<script type="text/x-template" title="movePageDialog">
<div class="row information">
<div class="inner">
<div class="element">
Specify the new parent page for this page and its children by space and title.
</div>
</div>
</div>
<div class="form">
<fieldset>
<legend class="assistive"><span>Change the Parent Page to a Known Page</span></legend>
<div class="row">
<label for="new-space">New space:</label>
<div class="value new-space-value">
<input id="new-space-key" name="new-space-key" type="hidden" value="dubbo">
<span class="space-input">
<input id="new-space" name="new-space" value="Dubbo" disabled="disabled">
</span>
<span class="description warning">You cannot move this page to another space because you do not have permission to remove it from this space.</span>
<div class="new-space-dropdown aui-dd-parent autocomplete"></div>
</div>
</div>
<div class="row">
<label for="new-parent-page">New parent page:</label>
<div class="value new-parent-page-value">
<span class="page-input">
<input id="new-parent-page" name="new-parent-page" value="User Guide-zh">
</span>
<span class="description">Start typing a page title to see a list of suggestions.</span>
<div class="new-parent-page-dropdown aui-dd-parent autocomplete"></div>
</div>
</div>
</fieldset>
</div>
<div class="location-info">
<div class="row">
<label>Current location:</label>
<div class="value breadcrumbs-container">
<div class="breadcrumbs-line">
<ul id="current-parent-breadcrumbs" class="breadcrumbs">
</ul>
</div>
</div>
</div>
<div class="row">
<label>New location:</label>
<div class="value breadcrumbs-container">
<div class="breadcrumbs-line">
<ul id="new-parent-breadcrumbs" class="breadcrumbs">
</ul>
</div>
</div>
</div>
</div>
</script>
<script type="text/x-template" title="movePageErrors">
<div id="move-errors" class="hidden warning"></div>
</script>
<script type="text/x-template" title="movePageBreadcrumb">
<li><a class="{2}" title="{3}" tabindex="-1"><span>{0}</span></a></li>
</script>
<script type="text/x-template" title="movePageBreadcrumbLoading">
<li class="loading"><span>Loading breadcrumbs&hellip;</span></li>
</script>
<script type="text/x-template" title="movePageBreadcrumbError">
<li class="warning last"><span>Error retrieving breadcrumbs.</span></li>
</script>
<script type="text/x-template" title="movePageNoMatchingPages">
<ol><li><span class="warning">No matching pages found.</span></li></ol>
</script>
<script type="text/x-template" title="movePageNoMatchingSpaces">
<ol><li><span class="warning">No matching spaces found.</span></li></ol>
</script>
<script type="text/x-template" title="movePageSearchPanel">
<div class="row information">
<div class="inner">
<div class="element">
Search for and select the new parent page for this page and its children.
</div>
</div>
</div>
<div id="move-page-search-container" class="row">
<div class="search-form">
<fieldset>
<legend class="assistive"><span>Search for a New Parent Page</span></legend>
<label for="move-page-search-query" class="assistive">Search keywords</label>
<input class="search-query" id="move-page-search-query">
<label for="move-page-search-space" class="assistive">Search in space</label>
<select id="move-page-search-space" class="search-space" disabled="disabled">
<option value="dubbo" selected="selected">Dubbo</option>
</select>
<input type="button" value="Search">
<div class="description warning">You cannot move this page to another space because you do not have permission to remove it from this space.</div>
</fieldset>
</div>
<div class="search-results">
</div>
</div>
</script>
<script type="text/x-template" title="movePageSearchResultsLoading">
<div class="searching">Searching…</div>
</script>
<script type="text/x-template" title="movePageHistoryPanel">
<div class="row information">
<div class="inner">
<div class="element">
Select the new parent page for this page and its children from your history.
</div>
</div>
</div>
<div id="move-page-search-container" class="row">
<div class="search-results">
</div>
</div>
</script>
<script type="text/x-template" title="movePageHistoryLoading">
<div class="searching">Loading…</div>
</script>
<script type="text/x-template" title="movePageBrowsePanel">
<div class="row information">
<div class="inner">
<div class="element">
Click to select the new parent page for this page and its children.
</div>
</div>
</div>
<div class="tree"></div>
</script>
<script type="text/x-template" title="movePagePanelLoading">
<span>Loading…</span>
</script>
<script type="text/x-template" title="movePageBrowsePanelSpace">
<ul><li id='tree-root-node-item' class='root-node-list-item'><a class='root-node' href='#'>{0}</a></li></ul>
</script>
<script type="text/x-template" title="orderingPagePanel">
<div id="orderingPlaceHolder"></div>
</script>
<script type="text/x-template" title="reorderCheckbox">
<span id="reorderRequirement"><input id="reorderCheck" type="checkbox" name="reorderFlag" title="Choose the position of this page within the list of child pages."/><label for="reorderCheck" title="Choose the position of this page within the list of child pages.">Reorder</label></span>
</script>
<script type="text/x-template" title="move-help-link">
<div class="dialog-help-link">
<a href="http://docs.atlassian.com/confluence/docs-35/Moving+a+Page" target="_blank">Help</a>
</div>
</script>
<script type="text/x-template" title="searchResultsGrid">
<table>
<thead>
<tr class="header">
<th class="search-result-title">Page Title</th>
<th class="search-result-space">Space</th>
<th class="search-result-date">Updated</th>
</tr>
</thead>
</table>
</script>
<script type="text/x-template" title="searchResultsGridCount">
<p class="search-result-count">{0}</p>
</script>
<script type="text/x-template" title="searchResultsGridRow">
<tr class="search-result">
<th class="search-result-title"><a href="{1}" class="content-type-{2}"><span>{0}</span></a></th>
<td class="search-result-space"><a class="space" href="http://10.20.160.198/wiki/display/{4}/" title="{3}">{3}</a></td>
<td class="search-result-date"><span class="date" title="{6}">{5}</span></td>
</tr>
</script>
<!-- Start restrictions section -->
<script type="text/x-template" title="page-permissions-div">
<div id="page-permissions-div">
<div id="page-permissions-editor-form">
<div id="page-permissions-error-div" class="hidden">
<a href="#" id="permissions-error-div-close">Ok</a>
<div></div>
</div>
<div id="page-permissions-type-radios" class="page-permissions-label-rows">
<div>
<input id="restrictViewRadio" type="radio" checked="checked" name="pagePermissionTypeRadio" value="view"/>
<label for="restrictViewRadio">Restrict viewing of this page</label>
<input id="restrictEditRadio" type="radio" name="pagePermissionTypeRadio" value="edit"/>
<label for="restrictEditRadio">Restrict editing of this page</label>
</div>
</div>
<div id="page-permissions-input" class="page-permissions-label-rows">
<div class="page-permissions-label">To:</div>
<div id="page-permissions-chooser-box">
<span id="page-permissions-choose-user" class="ajs-button">
<a href="#" id='userpicker-popup-link-image' onClick="var picker = window.open('http://10.20.160.198/wiki/spaces/openuserpicker.action?key=dubbo&startIndex=0&onPopupSubmit=AJS.PagePermissions.addUserPermissions', 'EntitiesPicker', 'status=yes,resizable=yes,top=100,left=200,width=700,height=680,scrollbars=yes'); picker.focus(); return false;"><img src="user_16.gif"/*tpa=http://10.20.160.198/wiki/s/en/2166/34/_/images/icons/user_16.gif*/ height=16 width=16 border=0 align="absmiddle" title="Choose users" /></a>
<a href="#" id='userpicker-popup-link-text' onClick="var picker = window.open('http://10.20.160.198/wiki/spaces/openuserpicker.action?key=dubbo&startIndex=0&onPopupSubmit=AJS.PagePermissions.addUserPermissions', 'EntitiesPicker', 'status=yes,resizable=yes,top=100,left=200,width=700,height=680,scrollbars=yes'); picker.focus(); return false;">Person...</a>
</span>
<span id="page-permissions-choose-group" class="ajs-button">
<a href="#" id='grouppicker-popup-link-image' onClick="var picker = window.open('http://10.20.160.198/wiki/spaces/opengrouppicker.action?key=dubbo&startIndex=0&actionName=dosearchgroups.action&onPopupSubmit=AJS.PagePermissions.addGroupPermissions', 'EntitiesPicker', 'status=yes,resizable=yes,top=100,left=200,width=580,height=550,scrollbars=yes'); picker.focus(); return false;"><img src="group_16.gif"/*tpa=http://10.20.160.198/wiki/s/en/2166/34/_/images/icons/group_16.gif*/ height=16 width=16 border=0 align="absmiddle" title="Choose groups" /></a>
<a href="#" id='grouppicker-popup-link-text' onClick="var picker = window.open('http://10.20.160.198/wiki/spaces/opengrouppicker.action?key=dubbo&startIndex=0&actionName=dosearchgroups.action&onPopupSubmit=AJS.PagePermissions.addGroupPermissions', 'EntitiesPicker', 'status=yes,resizable=yes,top=100,left=200,width=580,height=550,scrollbars=yes'); picker.focus(); return false;">Group...</a>
</span>
</div>
<div id="page-permissions-input-box">
<span>
<input type="text" id="page-permissions-names-input" class="input-placeholder" value="Enter user or group name" name="permissionNames" size="30" autocomplete="off"/>
</span>
<input
type="hidden"
id="page-permissions-names-hidden" /> <img height="16px" width="1px" src="spacer.gif"/*tpa=http://10.20.160.198/wiki/s/en/2166/34/_/images/border/spacer.gif*//>
<input type="button" id="add-typed-names" value="Restrict">
</div>
</div>
</div>
<div id="page-permissions-tables">
<div id="page-permissions-table-div">
<table id="page-permissions-table" class="page-permissions-table">
<tr id="page-permissions-no-views" class="marker-row">
<td colspan="3" class="page-permissions-marker-cell"><span>No view restrictions are defined for this page</span></td>
</tr>
<tr id="page-permissions-no-edits" class="marker-row">
<td colspan="3" class="page-permissions-marker-cell"><span>No edit restrictions are defined for this page</span></td>
</tr>
</table>
</div>
<div id="page-inherited-permissions-table-div" class="hidden">
<span id="page-inherited-permissions-table-desc">
<a class="icon twisty-closed">Show/Hide</a>
<a id="toggle-inherited-permissions" title="Click to see inherited restrictions">This page has restricted parent pages. It can only be seen by users who can see those parent pages.</a>
</span>
<div id="page-inherited-permissions-tables" class="hidden page-inheritance-togglable"></div>
</div>
</div>
</div>
</script>
<script type="text/x-template" title="permissions-row-template">
<tr class="permission-row">
<td class="page-permissions-marker-cell" width="20%">
<span>Viewing restricted to:</span>
</td>
<td class="permission-entity" nowrap="true" width="40%">
<span class="entity-container">
<img class="permission-entity-picture"/>
<span class="permission-entity-display-name"></span>
<span class="permission-entity-name-wrap">&nbsp;(<span class="permission-entity-name"></span>)</span>
</span>
</td>
<td class="permission-detail-column">
<div class="permission-remove-div">
<a href="#" class="remove-permission-link">Remove restriction</a>
</div>
</td>
</tr>
</script>
<script type="text/x-template" title="permissions-username-no-suggestion-template">
<ol>
<li><a href="#" class="message"><span>No matches</span></a></li>
</ol>
</script>
<script type="text/x-template" title="page-inherited-permissions-table-div-template">
<div class="page-inherited-permissions-owner-div">
<div class="page-inherited-permissions-table-desc">Viewing restrictions apply to “<a></a>”. In order to see “<span></span>”, a user must be in the following list of users and groups:</div>
<table class="page-permissions-table"></table>
</div>
</script>
<script type="text/x-template" title="page-restrictions-help-link">
<div class="dialog-help-link">
<a href="http://docs.atlassian.com/confluence/docs-35/Page+Restrictions" target="_blank">Help</a>
</div>
</script>
<!-- End restrictions section -->
<fieldset class="hidden parameters">
<input type="hidden" title="spaceKeyEncoded" value="dubbo">
<input type="hidden" title="spaceKeyDecoded" value="dubbo">
</fieldset>
<a href="#page-metadata-end" class="assistive">Skip to end of metadata</a>
<div id="page-metadata-start" class="assistive"></div>
<div class="page-metadata">
<ul>
<li class="page-metadata-item noprint">
<a id="content-metadata-page-restrictions" href="#" class="page-metadata-icon page-restrictions hidden" title="Page restrictions apply. Click the lock icon to view or edit the restriction.">
<span>Page restrictions apply</span></a> </li>
<li class="page-metadata-modification-info" style="display: none">
Added by <a href="javascript:if(confirm(%27http://10.20.160.198/wiki/display/~william.liangf \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/display/~william.liangf%27" tppabs="http://10.20.160.198/wiki/display/~william.liangf"
class="url fn confluence-userlink" data-username="william.liangf"
>梁 飞</a>, last edited by <a href="javascript:if(confirm(%27http://10.20.160.198/wiki/display/~ding.lid \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/display/~ding.lid%27" tppabs="http://10.20.160.198/wiki/display/~ding.lid"
class="url fn confluence-userlink" data-username="ding.lid"
>李 鼎</a> on 十一月 27, 2012
<span class="noprint">&nbsp;(<a id="view-change-link" href="javascript:if(confirm(%27http://10.20.160.198/wiki/pages/diffpages.action?pageId=6947828&originalId=8355854 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://10.20.160.198/wiki/pages/diffpages.action?pageId=6947828&originalId=8355854%27" tppabs="http://10.20.160.198/wiki/pages/diffpages.action?pageId=6947828&originalId=8355854">view change</a>)</span>
</li>
</ul>
<div id="version-comment" class="noteMacro" style="display: none;">
<strong>Comment:</strong>
<br />
</div>
</div>
<a href="#page-metadata-start" class="assistive">Go to start of metadata</a>
<div id="page-metadata-end" class="assistive"></div>
<fieldset class="hidden parameters">
<input type="hidden" title="browsePageTreeMode" value="view">
<input type="hidden" title="parentPageId" value="6948813">
</fieldset>
<div class="wiki-content">
<!-- wiki content -->
<h2><a name="Examples-zh-%E7%A4%BA%E4%BE%8B"></a>示例</h2>
<p>(<a href="Examples-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Examples-zh" title="Examples-zh">+</a>) (<a href="#Examples-zh-%E7%A4%BA%E4%BE%8B">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>想完整的运行起来,请参见:<a href="#Examples-zh-%E5%BF%AB%E9%80%9F%E5%90%AF%E5%8A%A8">快速启动</a> (<a href="Quick+Start-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Quick+Start-zh" title="Quick Start-zh">+</a>),这里只列出各种场景的配置方式</td></tr></table></div>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>以下示例全部使用基于Spring的<a href="#Examples-zh-Xml%E9%85%8D%E7%BD%AE">Xml配置</a> (<a href="Xml+Config-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Xml+Config-zh" title="Xml Config-zh">+</a>)作为参考,如果不想使用Spring,而希望通过API的方式进行调用,请参见:<a href="#Examples-zh-API%E9%85%8D%E7%BD%AE">API配置</a> (<a href="API+Config-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/API+Config-zh" title="API Config-zh">+</a>)</td></tr></table></div>
<h3><a name="Examples-zh-%E5%90%AF%E5%8A%A8%E6%97%B6%E6%A3%80%E6%9F%A5"></a>启动时检查</h3>
<p>(<a href="Check+On+Startup-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Check+On+Startup-zh" title="Check On Startup-zh">+</a>) (<a href="#Examples-zh-%E5%90%AF%E5%8A%A8%E6%97%B6%E6%A3%80%E6%9F%A5">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>Dubbo缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止Spring初始化完成,以便上线时,能及早发现问题,默认check=true。</td></tr></table></div>
<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="warning-3.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>如果你的Spring容器是懒加载的,或者通过API编程延迟引用服务,请关闭check,否则服务临时不可用时,会抛出异常,拿到null引用,如果check=false,总是会返回引用,当服务恢复时,能自动连上。</td></tr></table></div>
<p>可以通过check="false"关闭检查,比如,测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动。</p>
<p>关闭某个服务的启动时检查:(没有提供者时报错)</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference interface="com.foo.BarService" check="false" /&gt;]]></script>
</div></div>
<p>关闭所有服务的启动时检查:(没有提供者时报错)</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:consumer check="false" /&gt;]]></script>
</div></div>
<p>关闭注册中心启动时检查:(注册订阅失败时报错)</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:registry check="false" /&gt;]]></script>
</div></div>
<p>也可以用dubbo.properties配置:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>dubbo.properties</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: text; gutter: false"><![CDATA[dubbo.reference.com.foo.BarService.check=false
dubbo.reference.check=false
dubbo.consumer.check=false
dubbo.registry.check=false]]></script>
</div></div>
<p>也可以用-D参数:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: text; gutter: false"><![CDATA[java -Ddubbo.reference.com.foo.BarService.check=false
java -Ddubbo.reference.check=false
java -Ddubbo.consumer.check=false
java -Ddubbo.registry.check=false]]></script>
</div></div>
<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="warning-3.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>注意区别</b><br /><ul>
<li>dubbo.reference.check=false,强制改变所有reference的check值,就算配置中有声明,也会被覆盖。</li>
<li>dubbo.consumer.check=false,是设置check的缺省值,如果配置中有显式的声明,如:&lt;dubbo:reference check="true"/&gt;,不会受影响。</li>
<li>dubbo.registry.check=false,前面两个都是指订阅成功,但提供者列表是否为空是否报错,如果注册订阅失败时,也允许启动,需使用此选项,将在后台定时重试。</li>
</ul>
</td></tr></table></div>
<p>引用缺省是延迟初始化的,只有引用被注入到其它Bean,或被getBean()获取,才会初始化。<br/>
如果需要饥饿加载,即没有人引用也立即生成动态代理,可以配置:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference interface="com.foo.BarService" init="true" /&gt;]]></script>
</div></div>
<h3><a name="Examples-zh-%E9%9B%86%E7%BE%A4%E5%AE%B9%E9%94%99"></a>集群容错</h3>
<p>(<a href="Fault+Tolerance-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Fault+Tolerance-zh" title="Fault Tolerance-zh">+</a>) (<a href="#Examples-zh-%E9%9B%86%E7%BE%A4%E5%AE%B9%E9%94%99">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>在集群调用失败时,Dubbo提供了多种容错方案,缺省为failover重试。</td></tr></table></div>
<p><span class="image-wrap" style=""><img src="cluster.jpg-version=1&modificationDate=1321028038000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/6949932/cluster.jpg?version=1&modificationDate=1321028038000" style="border: 0px solid black" /></span></p>
<p>各节点关系:</p>
<ul>
<li>这里的Invoker是Provider的一个可调用Service的抽象,Invoker封装了Provider地址及Service接口信息。</li>
<li>Directory代表多个Invoker,可以把它看成List&lt;Invoker&gt;,但与List不同的是,它的值可能是动态变化的,比如注册中心推送变更。</li>
<li>Cluster将Directory中的多个Invoker伪装成一个Invoker,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个。</li>
<li>Router负责从多个Invoker中按路由规则选出子集,比如读写分离,应用隔离等。</li>
<li>LoadBalance负责从多个Invoker中选出具体的一个用于本次调用,选的过程包含了负载均衡算法,调用失败后,需要重选。</li>
</ul>
<h5><a name="Examples-zh-%E9%9B%86%E7%BE%A4%E5%AE%B9%E9%94%99%E6%A8%A1%E5%BC%8F%EF%BC%9A"></a>集群容错模式:</h5>
<p>可以自行扩展集群容错策略,参见:<a href="Developer+Guide-zh.htm#DeveloperGuide-zh-%E9%9B%86%E7%BE%A4%E6%89%A9%E5%B1%95" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh#DeveloperGuide-zh-%E9%9B%86%E7%BE%A4%E6%89%A9%E5%B1%95">集群扩展</a></p>
<h6><a name="Examples-zh-FailoverCluster"></a>Failover Cluster</h6>
<ul>
<li>失败自动切换,当出现失败,重试其它服务器。(缺省)</li>
<li>通常用于读操作,但重试会带来更长延迟。</li>
<li>可通过retries="2"来设置重试次数(不含第一次)。</li>
</ul>
<h6><a name="Examples-zh-FailfastCluster"></a>Failfast Cluster</h6>
<ul>
<li>快速失败,只发起一次调用,失败立即报错。</li>
<li>通常用于非幂等性的写操作,比如新增记录。</li>
</ul>
<h6><a name="Examples-zh-FailsafeCluster"></a>Failsafe Cluster</h6>
<ul>
<li>失败安全,出现异常时,直接忽略。</li>
<li>通常用于写入审计日志等操作。</li>
</ul>
<h6><a name="Examples-zh-FailbackCluster"></a>Failback Cluster</h6>
<ul>
<li>失败自动恢复,后台记录失败请求,定时重发。</li>
<li>通常用于消息通知操作。</li>
</ul>
<h6><a name="Examples-zh-ForkingCluster"></a>Forking Cluster</h6>
<ul>
<li>并行调用多个服务器,只要一个成功即返回。</li>
<li>通常用于实时性要求较高的读操作,但需要浪费更多服务资源。</li>
<li>可通过forks="2"来设置最大并行数。</li>
</ul>
<h6><a name="Examples-zh-BroadcastCluster"></a>Broadcast Cluster</h6>
<ul>
<li>广播调用所有提供者,逐个调用,任意一台报错则报错。(2.1.0开始支持)</li>
<li>通常用于通知所有提供者更新缓存或日志等本地资源信息。</li>
</ul>
<p>重试次数配置如:(failover集群模式生效)</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:service retries="2" /&gt;]]></script>
</div></div>
<p>或:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference retries="2" /&gt;]]></script>
</div></div>
<p>或:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference&gt;
&lt;dubbo:method name="findFoo" retries="2" /&gt;
&lt;/dubbo:reference&gt;]]></script>
</div></div>
<p>集群模式配置如:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:service cluster="failsafe" /&gt;]]></script>
</div></div>
<p>或:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference cluster="failsafe" /&gt;]]></script>
</div></div>
<h3><a name="Examples-zh-%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1"></a>负载均衡</h3>
<p>(<a href="Load+Balance-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Load+Balance-zh" title="Load Balance-zh">+</a>) (<a href="#Examples-zh-%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>在集群负载均衡时,Dubbo提供了多种均衡策略,缺省为random随机调用。</td></tr></table></div>
<p>可以自行扩展负载均衡策略,参见:<a href="Developer+Guide-zh.htm#DeveloperGuide-zh-%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E6%89%A9%E5%B1%95" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh#DeveloperGuide-zh-%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E6%89%A9%E5%B1%95">负载均衡扩展</a></p>
<h6><a name="Examples-zh-RandomLoadBalance"></a>Random LoadBalance</h6>
<ul>
<li>随机,按权重设置随机概率。</li>
<li>在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。</li>
</ul>
<h6><a name="Examples-zh-RoundRobinLoadBalance"></a>RoundRobin LoadBalance</h6>
<ul>
<li>轮循,按公约后的权重设置轮循比率。</li>
<li>存在慢的提供者累积请求问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。</li>
</ul>
<h6><a name="Examples-zh-LeastActiveLoadBalance"></a>LeastActive LoadBalance</h6>
<ul>
<li>最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。</li>
<li>使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。</li>
</ul>
<h6><a name="Examples-zh-ConsistentHashLoadBalance"></a>ConsistentHash LoadBalance</h6>
<ul>
<li>一致性Hash,相同参数的请求总是发到同一提供者。</li>
<li>当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。</li>
<li>算法参见:<a href="javascript:if(confirm(%27http://en.wikipedia.org/wiki/Consistent_hashing \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://en.wikipedia.org/wiki/Consistent_hashing%27" tppabs="http://en.wikipedia.org/wiki/Consistent_hashing" class="external-link" rel="nofollow">http://en.wikipedia.org/wiki/Consistent_hashing</a></li>
<li>缺省只对第一个参数Hash,如果要修改,请配置&lt;dubbo:parameter key="hash.arguments" value="0,1" /&gt;</li>
<li>缺省用160份虚拟节点,如果要修改,请配置&lt;dubbo:parameter key="hash.nodes" value="320" /&gt;</li>
</ul>
<p>配置如:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:service interface="..." loadbalance="roundrobin" /&gt;]]></script>
</div></div>
<p>或:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference interface="..." loadbalance="roundrobin" /&gt;]]></script>
</div></div>
<p>或:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:service interface="..."&gt;
&lt;dubbo:method name="..." loadbalance="roundrobin"/&gt;
&lt;/dubbo:service&gt;]]></script>
</div></div>
<p>或:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference interface="..."&gt;
&lt;dubbo:method name="..." loadbalance="roundrobin"/&gt;
&lt;/dubbo:reference&gt;]]></script>
</div></div>
<h3><a name="Examples-zh-%E7%BA%BF%E7%A8%8B%E6%A8%A1%E5%9E%8B"></a>线程模型</h3>
<p>(<a href="Thread+Model-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Thread+Model-zh" title="Thread Model-zh">+</a>) (<a href="#Examples-zh-%E7%BA%BF%E7%A8%8B%E6%A8%A1%E5%9E%8B">#</a>)</p>
<p><span class="image-wrap" style=""><img src="dubbo-protocol.jpg-version=1&modificationDate=1331068241000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/6949458/dubbo-protocol.jpg?version=1&modificationDate=1331068241000" style="border: 0px solid black" /></span></p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>事件处理线程说明</b><br /><ul>
<li>如果事件处理的逻辑能迅速完成,并且不会发起新的IO请求,比如只是在内存中记个标识,则直接在IO线程上处理更快,因为减少了线程池调度。</li>
<li>但如果事件处理逻辑较慢,或者需要发起新的IO请求,比如需要查询数据库,则必须派发到线程池,否则IO线程阻塞,将导致不能接收其它请求。</li>
<li>如果用IO线程处理事件,又在事件处理过程中发起新的IO请求,比如在连接事件中发起登录请求,会报“可能引发死锁”异常,但不会真死锁。</li>
</ul>
</td></tr></table></div>
<ul>
<li>Dispatcher
<ul>
<li>all 所有消息都派发到线程池,包括请求,响应,连接事件,断开事件,心跳等。</li>
<li>direct 所有消息都不派发到线程池,全部在IO线程上直接执行。</li>
<li>message 只有请求响应消息派发到线程池,其它连接断开事件,心跳等消息,直接在IO线程上执行。</li>
<li>execution 只请求消息派发到线程池,不含响应,响应和其它连接断开事件,心跳等消息,直接在IO线程上执行。</li>
<li>connection 在IO线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池。</li>
</ul>
</li>
</ul>
<ul>
<li>ThreadPool
<ul>
<li>fixed 固定大小线程池,启动时建立线程,不关闭,一直持有。(缺省)</li>
<li>cached 缓存线程池,空闲一分钟自动删除,需要时重建。</li>
<li>limited 可伸缩线程池,但池中的线程数只会增长不会收缩。(为避免收缩时突然来了大流量引起的性能问题)。</li>
</ul>
</li>
</ul>
<p>配置如:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:protocol name="dubbo" dispatcher="all" threadpool="fixed" threads="100" /&gt;]]></script>
</div></div>
<h3><a name="Examples-zh-%E7%9B%B4%E8%BF%9E%E6%8F%90%E4%BE%9B%E8%80%85"></a>直连提供者</h3>
<p>(<a href="Directly+Provider-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Directly+Provider-zh" title="Directly Provider-zh">+</a>) (<a href="#Examples-zh-%E7%9B%B4%E8%BF%9E%E6%8F%90%E4%BE%9B%E8%80%85">&#35;</a>)</p>
<p>在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,<br/>
点对点直联方式,将以服务接口为单位,忽略注册中心的提供者列表,<br/>
A接口配置点对点,不影响B接口从注册中心获取列表。</p>
<p><span class="image-wrap" style=""><img src="dubbo-directly.jpg-version=1&modificationDate=1326853485000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/6949440/dubbo-directly.jpg?version=1&modificationDate=1326853485000" style="border: 0px solid black" /></span></p>
<p>(1) 如果是线上需求需要点对点,可在&lt;dubbo:reference&gt;中配置url指向提供者,将绕过注册中心,<b>多个地址用分号隔开</b>,配置如下:(1.0.6及以上版本支持)</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[&lt;dubbo:reference id="xxxService" interface="com.alibaba.xxx.XxxService" url="dubbo://localhost:20890" /&gt;]]></script>
</div></div>
<p>(2) 在JVM启动参数中加入-D参数映射服务地址,如:<br/>
(key为服务名,value为服务提供者url,此配置优先级最高,1.0.15及以上版本支持)</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[java -Dcom.alibaba.xxx.XxxService=dubbo://localhost:20890]]></script>
</div></div>
<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="information.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/information.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>注意</b><br />为了避免复杂化线上环境,不要在线上使用这个功能,只应在测试阶段使用。</td></tr></table></div>
<p>(3) 如果服务比较多,也可以用文件映射,如:<br/>
(用-Ddubbo.resolve.file指定映射文件路径,此配置优先级高于&lt;dubbo:reference&gt;中的配置,1.0.15及以上版本支持)<br/>
(2.0以上版本自动加载${user.home}/dubbo-resolve.properties文件,不需要配置)</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[java -Ddubbo.resolve.file=xxx.properties]]></script>
</div></div>
<p>然后在映射文件xxx.properties中加入:<br/>
(key为服务名,value为服务提供者url)</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[com.alibaba.xxx.XxxService=dubbo://localhost:20890]]></script>
</div></div>
<div class='panelMacro'><table class='infoMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="information.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/information.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>注意</b><br />为了避免复杂化线上环境,不要在线上使用这个功能,只应在测试阶段使用。</td></tr></table></div>
<h3><a name="Examples-zh-%E5%8F%AA%E8%AE%A2%E9%98%85"></a>只订阅</h3>
<p>(<a href="Subscribe+Only-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Subscribe+Only-zh" title="Subscribe Only-zh">+</a>) (<a href="#Examples-zh-%E5%8F%AA%E8%AE%A2%E9%98%85">#</a>)</p>
<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="warning-3.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>问题</b><br />为方便开发测试,经常会在线下共用一个所有服务可用的注册中心,这时,如果一个正在开发中的服务提供者注册,可能会影响消费者不能正常运行。</td></tr></table></div>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>解决方案</b><br />可以让服务提供者开发方,只订阅服务(开发的服务可能依赖其它服务),而不注册正在开发的服务,通过直连测试正在开发的服务。</td></tr></table></div>
<p><span class="image-wrap" style=""><img src="subscribe-only.jpg-version=1&modificationDate=1326468174000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/6949667/subscribe-only.jpg?version=1&modificationDate=1326468174000" style="border: 0px solid black" /></span></p>
<p>禁用注册配置:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:registry address="10.20.153.10:9090" register="false" /&gt;]]></script>
</div></div>
<p>或者:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:registry address="10.20.153.10:9090?register=false" /&gt;]]></script>
</div></div>
<h3><a name="Examples-zh-%E5%8F%AA%E6%B3%A8%E5%86%8C"></a>只注册</h3>
<p>(<a href="Register+Only-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Register+Only-zh" title="Register Only-zh">+</a>) (<a href="#Examples-zh-%E5%8F%AA%E6%B3%A8%E5%86%8C">#</a>)</p>
<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="warning-3.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>问题</b><br />如果有两个镜像环境,两个注册中心,有一个服务只在其中一个注册中心有部署,另一个注册中心还没来得及部署,而两个注册中心的其它应用都需要依赖此服务,所以需要将服务同时注册到两个注册中心,但却不能让此服务同时依赖两个注册中心的其它服务。</td></tr></table></div>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>解决方案</b><br />可以让服务提供者方,只注册服务到另一注册中心,而不从另一注册中心订阅服务。</td></tr></table></div>
<p>禁用订阅配置:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:registry id="hzRegistry" address="10.20.153.10:9090" /&gt;
&lt;dubbo:registry id="qdRegistry" address="10.20.141.150:9090" subscribe="false" /&gt;]]></script>
</div></div>
<p>或者:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:registry id="hzRegistry" address="10.20.153.10:9090" /&gt;
&lt;dubbo:registry id="qdRegistry" address="10.20.141.150:9090?subscribe=false" /&gt;]]></script>
</div></div>
<h3><a name="Examples-zh-%E9%9D%99%E6%80%81%E6%9C%8D%E5%8A%A1"></a>静态服务</h3>
<p>(<a href="Static+Provider-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Static+Provider-zh" title="Static Provider-zh">+</a>) (<a href="#Examples-zh-%E9%9D%99%E6%80%81%E6%9C%8D%E5%8A%A1">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>有时候希望人工管理服务提供者的上线和下线,此时需将注册中心标识为非动态管理模式。</td></tr></table></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:registry address="10.20.141.150:9090" dynamic="false" /&gt;]]></script>
</div></div>
<p>或者:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:registry address="10.20.141.150:9090?dynamic=false" /&gt;]]></script>
</div></div>
<p>服务提供者初次注册时为禁用状态,需人工启用,断线时,将不会被自动删除,需人工禁用。</p>
<p>如果是一个第三方独立提供者,比如memcached等,可以直接向注册中心写入提供者地址信息,消费者正常使用:<br/>
(通常由脚本监控中心页面等调用)</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
registry.register(URL.valueOf("memcached://10.20.153.11/com.foo.BarService?category=providers&amp;dynamic=false&amp;application=foo"));]]></script>
</div></div>
<h3><a name="Examples-zh-%E5%A4%9A%E5%8D%8F%E8%AE%AE"></a>多协议</h3>
<p>(<a href="Multi+Protocol-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Multi+Protocol-zh" title="Multi Protocol-zh">+</a>) (<a href="#Examples-zh-%E5%A4%9A%E5%8D%8F%E8%AE%AE">#</a>)</p>
<p>可以自行扩展协议,参见:<a href="Developer+Guide-zh.htm#DeveloperGuide-zh-%E5%8D%8F%E8%AE%AE%E6%89%A9%E5%B1%95" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh#DeveloperGuide-zh-%E5%8D%8F%E8%AE%AE%E6%89%A9%E5%B1%95">协议扩展</a></p>
<h4><a name="Examples-zh-%281%29%E4%B8%8D%E5%90%8C%E6%9C%8D%E5%8A%A1%E4%B8%8D%E5%90%8C%E5%8D%8F%E8%AE%AE"></a>(1) 不同服务不同协议</h4>
<p>比如:不同服务在性能上适用不同协议进行传输,比如大数据用短连接协议,小数据大并发用长连接协议。</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>consumer.xml</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd"&gt;
&lt;dubbo:application name="world" /&gt;
&lt;dubbo:registry id="registry" address="10.20.141.150:9090" username="admin" password="hello1234" /&gt;
&lt;!-- 多协议配置 --&gt;
&lt;dubbo:protocol name="dubbo" port="20880" /&gt;
&lt;dubbo:protocol name="rmi" port="1099" /&gt;
&lt;!-- 使用dubbo协议暴露服务 --&gt;
&lt;dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" protocol="dubbo" /&gt;
&lt;!-- 使用rmi协议暴露服务 --&gt;
&lt;dubbo:service interface="com.alibaba.hello.api.DemoService" version="1.0.0" ref="demoService" protocol="rmi" /&gt;
&lt;/beans&gt;]]></script>
</div></div>
<h4><a name="Examples-zh-%282%29%E5%A4%9A%E5%8D%8F%E8%AE%AE%E6%9A%B4%E9%9C%B2%E6%9C%8D%E5%8A%A1"></a>(2) 多协议暴露服务</h4>
<p>比如:需要与http客户端互操作</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>consumer.xml</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd"&gt;
&lt;dubbo:application name="world" /&gt;
&lt;dubbo:registry id="registry" address="10.20.141.150:9090" username="admin" password="hello1234" /&gt;
&lt;!-- 多协议配置 --&gt;
&lt;dubbo:protocol name="dubbo" port="20880" /&gt;
&lt;dubbo:protocol name="hessian" port="8080" /&gt;
&lt;!-- 使用多个协议暴露服务 --&gt;
&lt;dubbo:service id="helloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" protocol="dubbo,hessian" /&gt;
&lt;/beans&gt;]]></script>
</div></div>
<h3><a name="Examples-zh-%E5%A4%9A%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83"></a>多注册中心</h3>
<p>(<a href="Multi+Registry-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Multi+Registry-zh" title="Multi Registry-zh">+</a>) (<a href="#Examples-zh-%E5%A4%9A%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83">#</a>)</p>
<p>可以自行扩展注册中心,参见:<a href="Developer+Guide-zh.htm#DeveloperGuide-zh-%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E6%89%A9%E5%B1%95" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh#DeveloperGuide-zh-%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E6%89%A9%E5%B1%95">注册中心扩展</a></p>
<h4><a name="Examples-zh-%281%29%E5%A4%9A%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E6%B3%A8%E5%86%8C"></a>(1) 多注册中心注册</h4>
<p>比如:中文站有些服务来不及在青岛部署,只在杭州部署,而青岛的其它应用需要引用此服务,就可以将服务同时注册到两个注册中心。</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>consumer.xml</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd"&gt;
&lt;dubbo:application name="world" /&gt;
&lt;!-- 多注册中心配置 --&gt;
&lt;dubbo:registry id="hangzhouRegistry" address="10.20.141.150:9090" /&gt;
&lt;dubbo:registry id="qingdaoRegistry" address="10.20.141.151:9010" default="false" /&gt;
&lt;!-- 向多个注册中心注册 --&gt;
&lt;dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" registry="hangzhouRegistry,qingdaoRegistry" /&gt;
&lt;/beans&gt;]]></script>
</div></div>
<h4><a name="Examples-zh-%282%29%E4%B8%8D%E5%90%8C%E6%9C%8D%E5%8A%A1%E4%BD%BF%E7%94%A8%E4%B8%8D%E5%90%8C%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83"></a>(2) 不同服务使用不同注册中心</h4>
<p>比如:CRM有些服务是专门为国际站设计的,有些服务是专门为中文站设计的。</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>consumer.xml</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd"&gt;
&lt;dubbo:application name="world" /&gt;
&lt;!-- 多注册中心配置 --&gt;
&lt;dubbo:registry id="chinaRegistry" address="10.20.141.150:9090" /&gt;
&lt;dubbo:registry id="intlRegistry" address="10.20.154.177:9010" default="false" /&gt;
&lt;!-- 向中文站注册中心注册 --&gt;
&lt;dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" registry="chinaRegistry" /&gt;
&lt;!-- 向国际站注册中心注册 --&gt;
&lt;dubbo:service interface="com.alibaba.hello.api.DemoService" version="1.0.0" ref="demoService" registry="intlRegistry" /&gt;
&lt;/beans&gt;]]></script>
</div></div>
<h4><a name="Examples-zh-%283%29%E5%A4%9A%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E5%BC%95%E7%94%A8"></a>(3) 多注册中心引用</h4>
<p>比如:CRM需同时调用中文站和国际站的PC2服务,PC2在中文站和国际站均有部署,接口及版本号都一样,但连的数据库不一样。</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>consumer.xml</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd"&gt;
&lt;dubbo:application name="world" /&gt;
&lt;!-- 多注册中心配置 --&gt;
&lt;dubbo:registry id="chinaRegistry" address="10.20.141.150:9090" /&gt;
&lt;dubbo:registry id="intlRegistry" address="10.20.154.177:9010" default="false" /&gt;
&lt;!-- 引用中文站服务 --&gt;
&lt;dubbo:reference id="chinaHelloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" registry="chinaRegistry" /&gt;
&lt;!-- 引用国际站站服务 --&gt;
&lt;dubbo:reference id="intlHelloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" registry="intlRegistry" /&gt;
&lt;/beans&gt;]]></script>
</div></div>
<p>如果只是测试环境临时需要连接两个不同注册中心,使用竖号分隔多个不同注册中心地址:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>consumer.xml</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://code.alibabatech.com/schema/dubbohttp://code.alibabatech.com/schema/dubbo/dubbo.xsd"&gt;
&lt;dubbo:application name="world" /&gt;
&lt;!-- 多注册中心配置,竖号分隔表示同时连接多个不同注册中心,同一注册中心的多个集群地址用逗号分隔 --&gt;
&lt;dubbo:registry address="10.20.141.150:9090|10.20.154.177:9010" /&gt;
&lt;!-- 引用服务 --&gt;
&lt;dubbo:reference id="helloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" /&gt;
&lt;/beans&gt;]]></script>
</div></div>
<h3><a name="Examples-zh-%E6%9C%8D%E5%8A%A1%E5%88%86%E7%BB%84"></a>服务分组</h3>
<p>(<a href="Multi+Group-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Multi+Group-zh" title="Multi Group-zh">+</a>) (<a href="#Examples-zh-%E6%9C%8D%E5%8A%A1%E5%88%86%E7%BB%84">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>当一个接口有多种实现时,可以用group区分。</td></tr></table></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:service group="feedback" interface="com.xxx.IndexService" /&gt;
&lt;dubbo:service group="member" interface="com.xxx.IndexService" /&gt;]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference id="feedbackIndexService" group="feedback" interface="com.xxx.IndexService" /&gt;
&lt;dubbo:reference id="memberIndexService" group="member" interface="com.xxx.IndexService" /&gt;]]></script>
</div></div>
<p>任意组:(2.2.0以上版本支持,总是只调一个可用组的实现)</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference id="barService" interface="com.foo.BarService" group="*" /&gt;]]></script>
</div></div>
<h3><a name="Examples-zh-%E5%A4%9A%E7%89%88%E6%9C%AC"></a>多版本</h3>
<p>(<a href="Multi+Version-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Multi+Version-zh" title="Multi Version-zh">+</a>) (<a href="#Examples-zh-%E5%A4%9A%E7%89%88%E6%9C%AC">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。</td></tr></table></div>
<ul>
<li>在低压力时间段,先升级一半提供者为新版本</li>
<li>再将所有消费者升级为新版本</li>
<li>然后将剩下的一半提供者升级为新版本</li>
</ul>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:service interface="com.foo.BarService" version="1.0.0" /&gt;]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:service interface="com.foo.BarService" version="2.0.0" /&gt;]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference id="barService" interface="com.foo.BarService" version="1.0.0" /&gt;]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference id="barService" interface="com.foo.BarService" version="2.0.0" /&gt;]]></script>
</div></div>
<p>不区分版本:(2.2.0以上版本支持)</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference id="barService" interface="com.foo.BarService" version="*" /&gt;]]></script>
</div></div>
<h3><a name="Examples-zh-%E5%88%86%E7%BB%84%E8%81%9A%E5%90%88"></a>分组聚合</h3>
<p>(<a href="Merge+By+Group-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Merge+By+Group-zh" title="Merge By Group-zh">+</a>) (<a href="#Examples-zh-%E5%88%86%E7%BB%84%E8%81%9A%E5%90%88">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>按组合并返回结果,比如菜单服务,接口一样,但有多种实现,用group区分,现在消费方需从每种group中调用一次返回结果,合并结果返回,这样就可以实现聚合菜单项。</td></tr></table></div>
<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="warning-3.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>从2.1.0版本开始支持</td></tr></table></div>
<p><span class="image-wrap" style=""><img src="dubbo-merger.jpg-version=1&modificationDate=1329310196000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/6952105/dubbo-merger.jpg?version=1&modificationDate=1329310196000" style="border: 0px solid black" /></span></p>
<p>代码参见:<a href="javascript:if(confirm(%27https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/merge \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/merge%27" tppabs="https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/merge" class="external-link" rel="nofollow">https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/merge</a></p>
<p>配置如:(搜索所有分组)</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference interface="com.xxx.MenuService" group="*" merger="true" /&gt;]]></script>
</div></div>
<p>或:(合并指定分组)</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference interface="com.xxx.MenuService" group="aaa,bbb" merger="true" /&gt;]]></script>
</div></div>
<p>或:(指定方法合并结果,其它未指定的方法,将只调用一个Group)</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference interface="com.xxx.MenuService" group="*"&gt;
&lt;dubbo:method name="getMenuItems" merger="true" /&gt;
&lt;/dubbo:service&gt;]]></script>
</div></div>
<p>或:(某个方法不合并结果,其它都合并结果)</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference interface="com.xxx.MenuService" group="*" merger="true"&gt;
&lt;dubbo:method name="getMenuItems" merger="false" /&gt;
&lt;/dubbo:service&gt;]]></script>
</div></div>
<p>或:(指定合并策略,缺省根据返回值类型自动匹配,如果同一类型有两个合并器时,需指定合并器的名称)<br/>
参见:<span class="error">&#91;合并结果扩展&#93;</span></p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference interface="com.xxx.MenuService" group="*"&gt;
&lt;dubbo:method name="getMenuItems" merger="mymerge" /&gt;
&lt;/dubbo:service&gt;]]></script>
</div></div>
<p>或:(指定合并方法,将调用返回结果的指定方法进行合并,合并方法的参数类型必须是返回结果类型本身)</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference interface="com.xxx.MenuService" group="*"&gt;
&lt;dubbo:method name="getMenuItems" merger=".addAll" /&gt;
&lt;/dubbo:service&gt;]]></script>
</div></div>
<h3><a name="Examples-zh-%E5%8F%82%E6%95%B0%E9%AA%8C%E8%AF%81"></a>参数验证</h3>
<p>(<a href="Parameter+Validation-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Parameter+Validation-zh" title="Parameter Validation-zh">+</a>) (<a href="#Examples-zh-%E5%8F%82%E6%95%B0%E9%AA%8C%E8%AF%81">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>参数验证功能是基于<a href="javascript:if(confirm(%27http://jcp.org/en/jsr/detail?id=303 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://jcp.org/en/jsr/detail?id=303%27" tppabs="http://jcp.org/en/jsr/detail?id=303" class="external-link" rel="nofollow">JSR303</a>实现的,用户只需标识JSR303标准的验证Annotation,并通过声明filter来实现验证。</td></tr></table></div>
<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="warning-3.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>2.1.0以上版本支持</td></tr></table></div>
<p>完整示例代码参见:<a href="javascript:if(confirm(%27https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/validation \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/validation%27" tppabs="https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/validation" class="external-link" rel="nofollow">https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/validation</a></p>
<p>验证方式可扩展,参见:<a href="Developer+Guide-zh.htm#DeveloperGuide-zh-Validation" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh#DeveloperGuide-zh-Validation">Validation扩展点</a></p>
<p>参数标注示例:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[import java.io.Serializable;
import java.util.Date;
import javax.validation.constraints.Future;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
public class ValidationParameter implements Serializable {
private static final long serialVersionUID = 7158911668568000392L;
@NotNull // 不允许为空
@Size(min = 1, max = 20) // 长度或大小范围
private String name;
@NotNull(groups = ValidationService.Save.class) // 保存时不允许为空,更新时允许为空 ,表示不更新该字段
@Pattern(regexp = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$")
private String email;
@Min(18) // 最小值
@Max(100) // 最大值
private int age;
@Past // 必须为一个过去的时间
private Date loginDate;
@Future // 必须为一个未来的时间
private Date expiryDate;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getLoginDate() {
return loginDate;
}
public void setLoginDate(Date loginDate) {
this.loginDate = loginDate;
}
public Date getExpiryDate() {
return expiryDate;
}
public void setExpiryDate(Date expiryDate) {
this.expiryDate = expiryDate;
}
}]]></script>
</div></div>
<p>分组验证示例:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[public interface ValidationService { // 缺省可按服务接口区分验证场景,如:@NotNull(groups = ValidationService.class)
@interface Save{} // 与方法同名接口,首字母大写,用于区分验证场景,如:@NotNull(groups = ValidationService.Save.class),可选
void save(ValidationParameter parameter);
void update(ValidationParameter parameter);
}]]></script>
</div></div>
<p>关联验证示例:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[import javax.validation.GroupSequence;
public interface ValidationService {
@GroupSequence(Update.class) // 同时验证Update组规则
@interface Save{}
void save(ValidationParameter parameter);
@interface Update{}
void update(ValidationParameter parameter);
}]]></script>
</div></div>
<p>参数验证示例:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
public interface ValidationService {
void save(@NotNull ValidationParameter parameter); // 验证参数不为空
void delete(@Min(1) int id); // 直接对基本类型参数验证
}]]></script>
</div></div>
<p>在客户端验证参数:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference id="validationService" interface="com.alibaba.dubbo.examples.validation.api.ValidationService" validation="true" /&gt;]]></script>
</div></div>
<p>在服务器端验证参数:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:service interface="com.alibaba.dubbo.examples.validation.api.ValidationService" ref="validationService" validation="true" /&gt;]]></script>
</div></div>
<p>验证异常信息:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[import javax.validation.ConstraintViolationException;
import javax.validation.ConstraintViolationException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.alibaba.dubbo.examples.validation.api.ValidationParameter;
import com.alibaba.dubbo.examples.validation.api.ValidationService;
import com.alibaba.dubbo.rpc.RpcException;
public class ValidationConsumer {
public static void main(String[] args) throws Exception {
String config = ValidationConsumer.class.getPackage().getName().replace('.', '/') + "/validation-consumer.xml";
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(config);
context.start();
ValidationService validationService = (ValidationService)context.getBean("validationService");
// Error
try {
parameter = new ValidationParameter();
validationService.save(parameter);
System.out.println("Validation ERROR");
} catch (RpcException e) { // 抛出的是RpcException
ConstraintViolationException ve = (ConstraintViolationException) e.getCause(); // 里面嵌了一个ConstraintViolationException
Set&lt;ConstraintViolation&lt;?&gt;&gt; violations = ve.getConstraintViolations(); // 可以拿到一个验证错误详细信息的集合
System.out.println(violations);
}
}
}]]></script>
</div></div>
<p>需要加入依赖:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dependency&gt;
&lt;groupId&gt;javax.validation&lt;/groupId&gt;
&lt;artifactId&gt;validation-api&lt;/artifactId&gt;
&lt;version&gt;1.0.0.GA&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.hibernate&lt;/groupId&gt;
&lt;artifactId&gt;hibernate-validator&lt;/artifactId&gt;
&lt;version&gt;4.2.0.Final&lt;/version&gt;
&lt;/dependency&gt;]]></script>
</div></div>
<h3><a name="Examples-zh-%E7%BB%93%E6%9E%9C%E7%BC%93%E5%AD%98"></a>结果缓存</h3>
<p>(<a href="Result+Cache-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Result+Cache-zh" title="Result Cache-zh">+</a>) (<a href="#Examples-zh-%E7%BB%93%E6%9E%9C%E7%BC%93%E5%AD%98">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>结果缓存,用于加速热门数据的访问速度,Dubbo提供声明式缓存,以减少用户加缓存的工作量。</td></tr></table></div>
<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="warning-3.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>2.1.0以上版本支持</td></tr></table></div>
<p>示例代码:<a href="javascript:if(confirm(%27https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/cache \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/cache%27" tppabs="https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/cache" class="external-link" rel="nofollow">https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/cache</a></p>
<ul>
<li>lru 基于最近最少使用原则删除多余缓存,保持最热的数据被缓存。</li>
<li>threadlocal 当前线程缓存,比如一个页面渲染,用到很多portal,每个portal都要去查用户信息,通过线程缓存,可以减少这种多余访问。</li>
<li>jcache 与<a href="javascript:if(confirm(%27http://jcp.org/en/jsr/detail?id=107 \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27http://jcp.org/en/jsr/detail?id=107%27" tppabs="http://jcp.org/en/jsr/detail?id=107" class="external-link" rel="nofollow">JSR107</a>集成,可以桥接各种缓存实现。</li>
</ul>
<p>缓存类型可扩展,参见:<a href="Developer+Guide-zh.htm#DeveloperGuide-zh-CacheFactory" tppabs="http://10.20.160.198/wiki/display/dubbo/Developer+Guide-zh#DeveloperGuide-zh-CacheFactory">CacheFactory扩展点</a></p>
<p>配置如:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference interface="com.foo.BarService" cache="lru" /&gt;]]></script>
</div></div>
<p>或:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference interface="com.foo.BarService"&gt;
&lt;dubbo:method name="findBar" cache="lru" /&gt;
&lt;/dubbo:reference&gt;]]></script>
</div></div>
<h3><a name="Examples-zh-%E6%B3%9B%E5%8C%96%E5%BC%95%E7%94%A8"></a>泛化引用</h3>
<p>(<a href="Generic+Reference-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Generic+Reference-zh" title="Generic Reference-zh">+</a>) (<a href="#Examples-zh-%E6%B3%9B%E5%8C%96%E5%BC%95%E7%94%A8">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>泛接口调用方式主要用于客户端没有API接口及模型类元的情况,参数及返回值中的所有POJO均用Map表示,通常用于框架集成,比如:实现一个通用的服务测试框架,可通过GenericService调用所有服务实现。</td></tr></table></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference id="barService" interface="com.foo.BarService" generic="true" /&gt;]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[GenericService barService = (GenericService) applicationContext.getBean("barService");
Object result = barService.$invoke("sayHello", new String[] { "java.lang.String" }, new Object[] { "World" });]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[import com.alibaba.dubbo.rpc.service.GenericService;
...
// 引用远程服务
ReferenceConfig&lt;GenericService&gt; reference = new ReferenceConfig&lt;GenericService&gt;(); // 该实例很重量,里面封装了所有与注册中心及服务提供方连接,请缓存
reference.setInterface("com.xxx.XxxService"); // 弱类型接口名
reference.setVersion("1.0.0");
reference.setGeneric(true); // 声明为泛化接口
GenericService genericService = reference.get(); // 用com.alibaba.dubbo.rpc.service.GenericService可以替代所有接口引用
// 基本类型以及Date,List,Map等不需要转换,直接调用
Object result = genericService.$invoke("sayHello", new String[] {"java.lang.String"}, new Object[] {"world"});
// 用Map表示POJO参数,如果返回值为POJO也将自动转成Map
Map&lt;String, Object&gt; person = new HashMap&lt;String, Object&gt;();
person.put("name", "xxx");
person.put("password", "yyy");
Object result = genericService.$invoke("findPerson", new String[]{"com.xxx.Person"}, new Object[]{person}); // 如果返回POJO将自动转成Map
...]]></script>
</div></div>
<p>假设存在POJO如: </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.xxx;
public class PersonImpl implements Person {
private String name;
private String password;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password= password;
}
}]]></script>
</div></div>
<p>则POJO数据: </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[Person person = new PersonImpl();
person.setName("xxx");
person.setPassword("yyy");]]></script>
</div></div>
<p>可用下面Map表示: </p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[Map&lt;String, Object&gt; map = new HashMap&lt;String, Object&gt;();
map.put("class", "com.xxx.PersonImpl"); // 注意:如果参数类型是接口,或者List等丢失泛型,可通过class属性指定类型。
map.put("name", "xxx");
map.put("password", "yyy");]]></script>
</div></div>
<h3><a name="Examples-zh-%E6%B3%9B%E5%8C%96%E5%AE%9E%E7%8E%B0"></a>泛化实现</h3>
<p>(<a href="Generic+Implementation-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Generic+Implementation-zh" title="Generic Implementation-zh">+</a>) (<a href="#Examples-zh-%E6%B3%9B%E5%8C%96%E5%AE%9E%E7%8E%B0">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>泛接口实现方式主要用于服务器端没有API接口及模型类元的情况,参数及返回值中的所有POJO均用Map表示,通常用于框架集成,比如:实现一个通用的远程服务Mock框架,可通过实现GenericService接口处理所有服务请求。</td></tr></table></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;bean id="genericService" class="com.foo.MyGenericService" /&gt;
&lt;dubbo:service interface="com.foo.BarService" ref="genericService" /&gt;]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.foo;
public class MyGenericService implements GenericService {
public Object $invoke(String methodName, String[] parameterTypes, Object[] args) throws GenericException {
if ("sayHello".equals(methodName)) {
return "Welcome " + args[0];
}
}
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[...
GenericService xxxService = new XxxGenericService(); // 用com.alibaba.dubbo.rpc.service.GenericService可以替代所有接口实现
ServiceConfig&lt;GenericService&gt; service = new ServiceConfig&lt;GenericService&gt;(); // 该实例很重量,里面封装了所有与注册中心及服务提供方连接,请缓存
service.setInterface("com.xxx.XxxService"); // 弱类型接口名
service.setVersion("1.0.0");
service.setRef(xxxService); // 指向一个通用服务实现
// 暴露及注册服务
service.export();]]></script>
</div></div>
<h3><a name="Examples-zh-%E5%9B%9E%E5%A3%B0%E6%B5%8B%E8%AF%95"></a>回声测试</h3>
<p>(<a href="Echo+Test-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Echo+Test-zh" title="Echo Test-zh">+</a>) (<a href="#Examples-zh-%E5%9B%9E%E5%A3%B0%E6%B5%8B%E8%AF%95">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>回声测试用于检测服务是否可用,回声测试按照正常请求流程执行,能够测试整个调用是否通畅,可用于监控。</td></tr></table></div>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>所有服务自动实现EchoService接口,只需将任意服务引用强制转型为EchoService,即可使用。</td></tr></table></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference id="memberService" interface="com.xxx.MemberService" /&gt;]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[MemberService memberService = ctx.getBean("memberService"); // 远程服务引用
EchoService echoService = (EchoService) memberService; // 强制转型为EchoService
String status = echoService.$echo("OK"); // 回声测试可用性
assert(status.equals("OK"))]]></script>
</div></div>
<h3><a name="Examples-zh-%E4%B8%8A%E4%B8%8B%E6%96%87%E4%BF%A1%E6%81%AF"></a>上下文信息</h3>
<p>(<a href="Rpc+Context-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Rpc+Context-zh" title="Rpc Context-zh">+</a>) (<a href="#Examples-zh-%E4%B8%8A%E4%B8%8B%E6%96%87%E4%BF%A1%E6%81%AF">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>上下文中存放的是当前调用过程中所需的环境信息。</td></tr></table></div>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>所有配置信息都将转换为URL的参数,参见《<a href="User+Guide.htm#UserGuide-ConfigurationReference" tppabs="http://10.20.160.198/wiki/display/dubbo/User+Guide#UserGuide-ConfigurationReference">配置项一览表</a>》中的“对应URL参数”一列。</td></tr></table></div>
<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="warning-3.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td><b>注意</b><br />RpcContext是一个ThreadLocal的临时状态记录器,当接收到RPC请求,或发起RPC请求时,RpcContext的状态都会变化。<br/>
比如:A调B,B再调C,则B机器上,在B调C之前,RpcContext记录的是A调B的信息,在B调C之后,RpcContext记录的是B调C的信息。</td></tr></table></div>
<h4><a name="Examples-zh-%281%29%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E6%96%B9"></a>(1) 服务消费方</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[xxxService.xxx(); // 远程调用
boolean isConsumerSide = RpcContext.getContext().isConsumerSide(); // 本端是否为消费端,这里会返回true
String serverIP = RpcContext.getContext().getRemoteHost(); // 获取最后一次调用的提供方IP地址
String application = RpcContext.getContext().getUrl().getParameter("application"); // 获取当前服务配置信息,所有配置信息都将转换为URL的参数
// ...
yyyService.yyy(); // 注意:每发起RPC调用,上下文状态会变化
// ...]]></script>
</div></div>
<h4><a name="Examples-zh-%282%29%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E6%96%B9"></a>(2) 服务提供方</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[public class XxxServiceImpl implements XxxService {
public void xxx() { // 服务方法实现
boolean isProviderSide = RpcContext.getContext().isProviderSide(); // 本端是否为提供端,这里会返回true
String clientIP = RpcContext.getContext().getRemoteHost(); // 获取调用方IP地址
String application = RpcContext.getContext().getUrl().getParameter("application"); // 获取当前服务配置信息,所有配置信息都将转换为URL的参数
// ...
yyyService.yyy(); // 注意:每发起RPC调用,上下文状态会变化
boolean isProviderSide = RpcContext.getContext().isProviderSide(); // 此时本端变成消费端,这里会返回false
// ...
}
}]]></script>
</div></div>
<h3><a name="Examples-zh-%E9%9A%90%E5%BC%8F%E4%BC%A0%E5%8F%82"></a>隐式传参</h3>
<p>(<a href="Attachment+Parameter-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Attachment+Parameter-zh" title="Attachment Parameter-zh">+</a>) (<a href="#Examples-zh-%E9%9A%90%E5%BC%8F%E4%BC%A0%E5%8F%82">&#35;</a>)</p>
<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="warning-3.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>注:path,group,version,dubbo,token,timeout几个key有特殊处理,请使用其它key值。</td></tr></table></div>
<p><span class="image-wrap" style=""><img src="context.png-version=1&modificationDate=1320941797000.png" tppabs="http://10.20.160.198/wiki/download/attachments/6950004/context.png?version=1&modificationDate=1320941797000" style="border: 0px solid black" /></span></p>
<h4><a name="Examples-zh-%281%29%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E6%96%B9"></a>(1) 服务消费方</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[RpcContext.getContext().setAttachment("index", "1"); // 隐式传参,后面的远程调用都会隐式将这些参数发送到服务器端,类似cookie,用于框架集成,不建议常规业务使用
xxxService.xxx(); // 远程调用
// ...]]></script>
</div></div>
<p>【注】 setAttachment设置的KV,在完成下面一次远程调用会被清空。即多次远程调用要多次设置。</p>
<h4><a name="Examples-zh-%282%29%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E6%96%B9"></a>(2) 服务提供方</h4>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[public class XxxServiceImpl implements XxxService {
public void xxx() { // 服务方法实现
String index = RpcContext.getContext().getAttachment("index"); // 获取客户端隐式传入的参数,用于框架集成,不建议常规业务使用
// ...
}
}]]></script>
</div></div>
<h3><a name="Examples-zh-%E5%BC%82%E6%AD%A5%E8%B0%83%E7%94%A8"></a>异步调用</h3>
<p>(<a href="Async+Call-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Async+Call-zh" title="Async Call-zh">+</a>) (<a href="#Examples-zh-%E5%BC%82%E6%AD%A5%E8%B0%83%E7%94%A8">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>基于NIO的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小。</td></tr></table></div>
<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="warning-3.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>2.0.6及其以上版本支持</td></tr></table></div>
<p><span class="image-wrap" style=""><img src="future.jpg-version=1&modificationDate=1320417743000.jpg" tppabs="http://10.20.160.198/wiki/download/attachments/6949442/future.jpg?version=1&modificationDate=1320417743000" style="border: 0px solid black" /></span></p>
<p><b>配置声明:</b></p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>consumer.xml</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference id="fooService" interface="com.alibaba.foo.FooService"&gt;
&lt;dubbo:method name="findFoo" async="true" /&gt;
&lt;/dubbo:reference&gt;
&lt;dubbo:reference id="barService" interface="com.alibaba.bar.BarService"&gt;
&lt;dubbo:method name="findBar" async="true" /&gt;
&lt;/dubbo:reference&gt;]]></script>
</div></div>
<p><b>调用代码:</b></p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[fooService.findFoo(fooId); // 此调用会立即返回null
Future&lt;Foo&gt; fooFuture = RpcContext.getContext().getFuture(); // 拿到调用的Future引用,当结果返回后,会被通知和设置到此Future。
barService.findBar(barId); // 此调用会立即返回null
Future&lt;Bar&gt; barFuture = RpcContext.getContext().getFuture(); // 拿到调用的Future引用,当结果返回后,会被通知和设置到此Future。
// 此时findFoo和findBar的请求同时在执行,客户端不需要启动多线程来支持并行,而是借助NIO的非阻塞完成。
Foo foo = fooFuture.get(); // 如果foo已返回,直接拿到返回值,否则线程wait住,等待foo返回后,线程会被notify唤醒。
Bar bar = barFuture.get(); // 同理等待bar返回。
// 如果foo需要5秒返回,bar需要6秒返回,实际只需等6秒,即可获取到foo和bar,进行接下来的处理。]]></script>
</div></div>
<p>你也可以设置是否等待消息发出:(异步总是不等待返回)</p>
<ul>
<li>sent="true" 等待消息发出,消息发送失败将抛出异常。</li>
<li>sent="false" 不等待消息发出,将消息放入IO队列,即刻返回。
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:method name="findFoo" async="true" sent="true" /&gt;]]></script>
</div></div></li>
</ul>
<p>如果你只是想异步,完全忽略返回值,可以配置return="false",以减少Future对象的创建和管理成本:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:method name="findFoo" async="true" return="false" /&gt;]]></script>
</div></div>
<h3><a name="Examples-zh-%E6%9C%AC%E5%9C%B0%E8%B0%83%E7%94%A8"></a>本地调用</h3>
<p>(<a href="Local+Call-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Local+Call-zh" title="Local Call-zh">+</a>) (<a href="#Examples-zh-%E6%9C%AC%E5%9C%B0%E8%B0%83%E7%94%A8">&#35;</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>本地调用,使用了Injvm协议,是一个伪协议,它不开启端口,不发起远程调用,只在JVM内直接关联,但执行Dubbo的Filter链。</td></tr></table></div>
<p>Define injvm protocol:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:protocol name="injvm" /&gt;]]></script>
</div></div>
<p>Set default protocol:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:provider protocol="injvm" /&gt;]]></script>
</div></div>
<p>Set service protocol:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:service protocol="injvm" /&gt;]]></script>
</div></div>
<p>Use injvm first:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:consumer injvm="true" .../&gt;
&lt;dubbo:provider injvm="true" .../&gt;]]></script>
</div></div>
<p></p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[&lt;dubbo:reference injvm="true" .../&gt;
&lt;dubbo:service injvm="true" .../&gt;]]></script>
</div></div>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>注意:服务暴露与服务引用都需要声明injvm="true"</td></tr></table></div>
<p><a name="Examples-zh-automatic"></a><b>自动暴露、引用本地服务</b></p>
<p>从 dubbo 2.2.0 开始,每个服务默认都会在本地暴露;在引用服务的时候,默认优先引用本地服务;如果希望引用远程服务可以使用一下配置强制引用远程服务。</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: xml; gutter: false"><![CDATA[...
&lt;dubbo:reference ... scope="remote" /&gt;
...]]></script>
</div></div>
<h3><a name="Examples-zh-%E5%8F%82%E6%95%B0%E5%9B%9E%E8%B0%83"></a>参数回调</h3>
<p>(<a href="Parameter+Callback-zh.htm" tppabs="http://10.20.160.198/wiki/display/dubbo/Parameter+Callback-zh" title="Parameter Callback-zh">+</a>) (<a href="#Examples-zh-%E5%8F%82%E6%95%B0%E5%9B%9E%E8%B0%83">#</a>)</p>
<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="check.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/check.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>参数回调方式与调用本地callback或listener相同,只需要在Spring的配置文件中声明哪个参数是callback类型即可,Dubbo将基于长连接生成反向代理,这样就可以从服务器端调用客户端逻辑。</td></tr></table></div>
<div class='panelMacro'><table class='noteMacro'><colgroup><col width='24'><col></colgroup><tr><td valign='top'><img src="warning-3.gif" tppabs="http://10.20.160.198/wiki/images/icons/emoticons/warning.gif" width="16" height="16" align="absmiddle" alt="" border="0"></td><td>2.0.6及其以上版本支持</td></tr></table></div>
<p>代码参见:<a href="javascript:if(confirm(%27https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/callback \n\nThis file was not retrieved by Teleport Ultra, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?%27))window.location=%27https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/callback%27" tppabs="https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/callback" class="external-link" rel="nofollow">https://github.com/alibaba/dubbo/tree/master/dubbo-test/dubbo-test-examples/src/main/java/com/alibaba/dubbo/examples/callback</a></p>
<p><b>(1) 共享服务接口:</b></p>
<p>服务接口示例:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>CallbackService.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.callback;
public interface CallbackService {
void addListener(String key, CallbackListener listener);
}]]></script>
</div></div>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>CallbackListener.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.callback;
public interface CallbackListener {
void changed(String msg);
}]]></script>
</div></div>
<p><b>(2) 服务提供者:</b></p>
<p>服务提供者接口实现示例:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeHeader panelHeader" style="border-bottom-width: 1px;"><b>CallbackServiceImpl.java</b></div><div class="codeContent panelContent">
<script type="syntaxhighlighter" class="theme: Confluence; brush: java; gutter: false"><![CDATA[package com.callback.impl;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.callback.CallbackListener;
import com.callback.CallbackService;
public class CallbackServiceImpl implements CallbackService {
private final Map&lt;String, CallbackListener&gt; listeners = new ConcurrentHashMap&lt;String, CallbackListener&gt;();
public CallbackServiceImpl() {
Thread t = new Thread(new Runnable() {
public void run() {
while(true) {
try {
for(Map.Entry&lt;String, CallbackListener&gt; entry : listeners.entrySet()){
try {
entry.getValue().changed(getChanged(entry.getKey()));
} catch (Throwable t) {
listeners.remove(entry.getKey());
}
}
Thread.sleep(5000); // 定时触发变更通知
} catch (Throwable t) { // 防御容错
t.printStackTrace();
}
}
}
});
t.setDaemon(true);