644 lines
92 KiB
HTML
644 lines
92 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en-us">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>Redkale(红菜苔)--基于Java 8全新的微服务开源框架 - Redkale官网</title>
|
||
<meta name="keywords" content="Redkale,redkale,java,微服务,架构"/>
|
||
<meta name="description" content="Redkale(红菜苔)是基于Java 8全新的微服务开源框架"/>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<link rel="stylesheet" type="text/css" href="stylesheets/stylesheet.css" media="screen">
|
||
</head>
|
||
<body>
|
||
<section class="page-header">
|
||
<a href="index.html" class="project-name">Redkale</a>
|
||
<h2 class="project-tagline"></h2>
|
||
<a href="redkale.html" class="btn">Redkale 入门</a>
|
||
<a href="convert.html" class="btn">Convert 组件</a>
|
||
<a href="service.html" class="btn">Service 组件</a>
|
||
<a href="source.html" class="btn">Source 组件</a>
|
||
<a href="net.html" class="btn">Net 组件</a>
|
||
<a href="watch.html" class="btn">Watch 组件</a>
|
||
<a href="plugins.html" class="btn">Redkale 插件</a>
|
||
<a href="articles.html" class="btn">技术文章</a>
|
||
</section>
|
||
|
||
<section class="main-content">
|
||
<h3><a id="service_intro" class="anchor" href="#" aria-hidden="true"></a>Service 组件介绍</h3>
|
||
|
||
<p> Service 是Redkale最核心的组件,依赖于Convert、SNCP协议、Resource依赖注入。Service主要处理业务逻辑和操作数据层,是微服务架构中的单一原子服务。每一个Service实例分两种模式: <b>本地模式</b>和<b>远程模式</b>。其模式由 conf/application.xml 文件来配置。开发人员在调用过程中通常不需要区分当前Service实例是哪种模式。<br/>
|
||
为了能确保本地模式与远程模式自由切换,对Service的实现类有一定的约束: <br/>
|
||
1、Service实现类会被继承,不能修饰为 <b>final</b> <br/>
|
||
2、带@RpcMultiRun注解的方法会被重载,不能修饰为 <b>final</b> <br/>
|
||
Redkale进程启动时扫描可加载的Service实现类,根据配置文件配置的模式采用JDK 8内置的ASM技术动态生成相应的Service临时类进行实例化,并注册到ResourceFactory同其他Service、Servlet依赖注入。
|
||
</p>
|
||
|
||
<h3><a id="service_local" class="anchor" href="#" aria-hidden="true"></a>Service 本地模式</h3>
|
||
<p> 以一个简单的UserService类范例来说明动态生成的两种模式临时类。UserService提供查询用户、注册、登陆、修改用户名功能:</br></p>
|
||
|
||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserService</span> <span class="kd">implements</span> <span class="n">Service</span> <span class="o">{</span>
|
||
|
||
<span class="c1">//用户简单信息缓存</span>
|
||
<span class="kd">private</span> <span class="kd">final</span> <span class="n">Map</span><span class="o"><</span><span class="n">Integer</span><span class="o">,</span> <span class="n">UserInfo</span><span class="o">></span> <span class="n">users</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ConcurrentHashMap</span><span class="o"><>();</span>
|
||
|
||
<span class="c1">//存放手机号码与userid的对应关系</span>
|
||
<span class="kd">private</span> <span class="kd">final</span> <span class="n">Map</span><span class="o"><</span><span class="n">Long</span><span class="o">,</span> <span class="n">Integer</span><span class="o">></span> <span class="n">mobileToUserids</span> <span class="o">=</span> <span class="k">new</span> <span class="n">ConcurrentHashMap</span><span class="o"><>();</span>
|
||
|
||
<span class="kd">public</span> <span class="kd">final</span> <span class="n">String</span> <span class="nf">testLocalNodeName</span><span class="o">()</span> <span class="o">{</span>
|
||
<span class="k">return</span> <span class="s">"本地节点名"</span><span class="o">;</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="c1">//查询用户信息</span>
|
||
<span class="kd">public</span> <span class="n">UserInfo</span> <span class="nf">findUserInfo</span><span class="o">(</span><span class="kt">int</span> <span class="n">userid</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="k">return</span> <span class="n">users</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">userid</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="c1">//根据手机号码查询用户ID,没有返回0</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">findUserid</span><span class="o">(</span><span class="kt">long</span> <span class="n">mobile</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="n">Integer</span> <span class="n">rs</span> <span class="o">=</span> <span class="n">mobileToUserids</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">mobile</span><span class="o">);</span>
|
||
<span class="k">return</span> <span class="n">rs</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">rs</span><span class="o">;</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="c1">//缓存用户信息</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">putUserInfo</span><span class="o">(</span><span class="n">UserInfo</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="n">users</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">user</span><span class="o">.</span><span class="na">getUserid</span><span class="o">(),</span> <span class="n">user</span><span class="o">);</span>
|
||
<span class="k">if</span> <span class="o">(</span><span class="n">user</span><span class="o">.</span><span class="na">getMobile</span><span class="o">()</span> <span class="o">></span> <span class="mi">0</span><span class="o">)</span> <span class="n">mobileToUserids</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">user</span><span class="o">.</span><span class="na">getMobile</span><span class="o">(),</span> <span class="n">user</span><span class="o">.</span><span class="na">getUserid</span><span class="o">());</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="c1">//登录</span>
|
||
<span class="kd">public</span> <span class="n">RetResult</span><span class="o"><</span><span class="n">UserInfo</span><span class="o">></span> <span class="nf">login</span><span class="o">(</span><span class="n">LoginBean</span> <span class="n">bean</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="c1">// 登陆逻辑</span>
|
||
<span class="k">return</span> <span class="k">new</span> <span class="n">RetResult</span><span class="o"><>(</span><span class="mi">100</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="c1">//注册</span>
|
||
<span class="nd">@RpcMultiRun</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">register</span><span class="o">(</span><span class="n">UserInfo</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="k">this</span><span class="o">.</span><span class="na">users</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">user</span><span class="o">.</span><span class="na">getUserid</span><span class="o">(),</span> <span class="n">user</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="c1">//更新用户名</span>
|
||
<span class="nd">@RpcMultiRun</span><span class="o">(</span><span class="n">diffrun</span> <span class="o">=</span> <span class="kc">false</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="n">UserInfo</span> <span class="nf">updateUsername</span><span class="o">(</span><span class="kt">int</span> <span class="n">userid</span><span class="o">,</span> <span class="n">String</span> <span class="n">username</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="n">UserInfo</span> <span class="n">user</span> <span class="o">=</span> <span class="k">this</span><span class="o">.</span><span class="na">users</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">userid</span><span class="o">);</span>
|
||
<span class="k">if</span> <span class="o">(</span><span class="n">user</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="n">user</span><span class="o">.</span><span class="na">setUsername</span><span class="o">(</span><span class="n">username</span><span class="o">);</span>
|
||
<span class="k">return</span> <span class="n">user</span><span class="o">;</span>
|
||
<span class="o">}</span>
|
||
<span class="o">}</span>
|
||
</pre></div>
|
||
|
||
<p> 动态生成的本地模式UserService:</p>
|
||
<div class="highlight"><pre><span></span><span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">""</span><span class="o">)</span>
|
||
<span class="nd">@SncpDyn</span><span class="o">(</span><span class="n">remote</span> <span class="o">=</span> <span class="kc">false</span><span class="o">)</span>
|
||
<span class="nd">@ResourceType</span><span class="o">(</span><span class="n">UserService</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">_DynLocalUserService</span> <span class="kd">extends</span> <span class="n">UserService</span> <span class="o">{</span>
|
||
|
||
<span class="kd">private</span> <span class="n">SncpClient</span> <span class="n">_redkale_client</span><span class="o">;</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">register</span><span class="o">(</span><span class="n">UserInfo</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="k">this</span><span class="o">.</span><span class="na">_redkale_register</span><span class="o">(</span><span class="kc">true</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="n">user</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@SncpDyn</span><span class="o">(</span><span class="n">remote</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">_redkale_register</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">selfrunnable</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">samerunnable</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">diffrunnable</span><span class="o">,</span> <span class="n">UserInfo</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="k">if</span> <span class="o">(</span><span class="n">selfrunnable</span><span class="o">)</span> <span class="kd">super</span><span class="o">.</span><span class="na">register</span><span class="o">(</span><span class="n">user</span><span class="o">);</span>
|
||
<span class="k">if</span> <span class="o">(</span><span class="n">_redkale_client</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span><span class="o">;</span>
|
||
<span class="k">if</span> <span class="o">(</span><span class="n">samerunnable</span><span class="o">)</span> <span class="n">_redkale_client</span><span class="o">.</span><span class="na">remoteSameGroup</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="kc">false</span><span class="o">,</span> <span class="kc">false</span><span class="o">,</span> <span class="n">user</span><span class="o">);</span>
|
||
<span class="k">if</span> <span class="o">(</span><span class="n">diffrunnable</span><span class="o">)</span> <span class="n">_redkale_client</span><span class="o">.</span><span class="na">remoteDiffGroup</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="kc">false</span><span class="o">,</span> <span class="n">user</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="n">UserInfo</span> <span class="nf">updateUsername</span><span class="o">(</span><span class="kt">int</span> <span class="n">userid</span><span class="o">,</span> <span class="n">String</span> <span class="n">username</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">_redkale_updateUsername</span><span class="o">(</span><span class="kc">true</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="kc">false</span><span class="o">,</span> <span class="n">userid</span><span class="o">,</span> <span class="n">username</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@SncpDyn</span><span class="o">(</span><span class="n">remote</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">1</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="n">UserInfo</span> <span class="nf">_redkale_updateUsername</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">selfrunnable</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">samerunnable</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">diffrunnable</span><span class="o">,</span> <span class="kt">int</span> <span class="n">userid</span><span class="o">,</span> <span class="n">String</span> <span class="n">username</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="n">UserInfo</span> <span class="n">rs</span> <span class="o">=</span> <span class="kd">super</span><span class="o">.</span><span class="na">updateUsername</span><span class="o">(</span><span class="n">userid</span><span class="o">,</span> <span class="n">username</span><span class="o">);</span>
|
||
<span class="k">if</span> <span class="o">(</span><span class="n">_redkale_client</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
|
||
<span class="k">if</span> <span class="o">(</span><span class="n">samerunnable</span><span class="o">)</span> <span class="n">_redkale_client</span><span class="o">.</span><span class="na">remoteSameGroup</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="kc">false</span><span class="o">,</span> <span class="kc">false</span><span class="o">,</span> <span class="n">userid</span><span class="o">,</span> <span class="n">username</span><span class="o">);</span>
|
||
<span class="k">if</span> <span class="o">(</span><span class="n">diffrunnable</span><span class="o">)</span> <span class="n">_redkale_client</span><span class="o">.</span><span class="na">remoteDiffGroup</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="kc">false</span><span class="o">,</span> <span class="n">userid</span><span class="o">,</span> <span class="n">username</span><span class="o">);</span>
|
||
<span class="k">return</span> <span class="n">rs</span><span class="o">;</span>
|
||
<span class="o">}</span>
|
||
<span class="o">}</span>
|
||
</pre></div>
|
||
<p> 由以上等价的代码可以看出来,本地模式Service会重载被@RpcMultiRun注解的方法。@RpcMultiRun有以下几个参数: </p>
|
||
<div class="highlight"><pre><span class="kd">public</span> <span class="nd">@interface</span> <span class="n">RpcMultiRun</span> <span class="o">{</span>
|
||
|
||
<span class="kt">boolean</span> <span class="nf">selfrun</span><span class="o">()</span> <span class="k">default</span> <span class="kc">true</span><span class="o">;</span> <span class="c1">//当前本地实例是否运行指定操作;只有当指定操作的方法的返回值为void时,该值才能为true,否则忽略。</span>
|
||
|
||
<span class="kt">boolean</span> <span class="nf">samerun</span><span class="o">()</span> <span class="k">default</span> <span class="kc">true</span><span class="o">;</span> <span class="c1">//是否同组节点运行指定操作</span>
|
||
|
||
<span class="kt">boolean</span> <span class="nf">diffrun</span><span class="o">()</span> <span class="k">default</span> <span class="kc">true</span><span class="o">;</span> <span class="c1">//是否不同组节点运行指定操作</span>
|
||
|
||
<span class="kt">boolean</span> <span class="nf">async</span><span class="o">()</span> <span class="k">default</span> <span class="kc">true</span><span class="o">;</span> <span class="c1">//分布式运行是否采用异步模式</span>
|
||
<span class="o">}</span> </pre></div>
|
||
<p> 在动态生成的远程模式UserService时会根据不同参数生成相应的方法。若一个Service类没有含@RpcMultiRun注解的方法,那么动态类只会重载toString方法。当UserService服务仅需要部署一个进程,由于没有其他等同服务的进程因此在UserService实例化时_redkale_client会赋值为null。</p>
|
||
<div class="highlight"><pre><span class="nt"><resources></span>
|
||
<span class="nt"><group</span> <span class="na">name=</span><span class="s">"GROUP-A"</span><span class="nt">></span>
|
||
<span class="nt"><node</span> <span class="na">addr=</span><span class="s">"192.168.10.111"</span> <span class="na">port=</span><span class="s">"7070"</span><span class="nt">/></span>
|
||
<span class="nt"><node</span> <span class="na">addr=</span><span class="s">"192.168.10.112"</span> <span class="na">port=</span><span class="s">"7070"</span><span class="nt">/></span>
|
||
<span class="nt"><node</span> <span class="na">addr=</span><span class="s">"192.168.10.113"</span> <span class="na">port=</span><span class="s">"7070"</span><span class="nt">/></span>
|
||
<span class="nt"></group></span>
|
||
<span class="nt"><group</span> <span class="na">name=</span><span class="s">"GROUP-B"</span><span class="nt">></span>
|
||
<span class="nt"><node</span> <span class="na">addr=</span><span class="s">"192.168.20.121"</span> <span class="na">port=</span><span class="s">"7070"</span><span class="nt">/></span>
|
||
<span class="nt"><node</span> <span class="na">addr=</span><span class="s">"192.168.20.122"</span> <span class="na">port=</span><span class="s">"7070"</span><span class="nt">/></span>
|
||
<span class="nt"></group></span>
|
||
<span class="nt"><group</span> <span class="na">name=</span><span class="s">"GROUP-C"</span><span class="nt">></span>
|
||
<span class="nt"><node</span> <span class="na">addr=</span><span class="s">"192.168.30.131"</span> <span class="na">port=</span><span class="s">"7070"</span><span class="nt">/></span>
|
||
<span class="nt"><node</span> <span class="na">addr=</span><span class="s">"192.168.30.132"</span> <span class="na">port=</span><span class="s">"7070"</span><span class="nt">/></span>
|
||
<span class="nt"></group></span>
|
||
<span class="nt"></resources></span>
|
||
|
||
|
||
<span class="c"><!-- 配置UserService的节点组 ---></span>
|
||
<span class="nt"><service</span> <span class="na">name=</span><span class="s">""</span> <span class="na">value=</span><span class="s">"org.redkale.demo.user.UserService"</span> <span class="na">groups=</span><span class="s">"GROUP-A;GROUP-B;GROUP-C"</span><span class="nt">/></span>
|
||
</pre></div>
|
||
<p> 如上配置,若当前进程所在IP是192.168.10.111,则UserService采用本地模式加载。执行register方法时, 先本地执行超类的register,然后远程执行同组的进程(192.168.10.112、192.168.10.113),最后远程执行异组的进程(192.168.20.121、192.168.20.122、192.168.30.131、192.168.30.132)。若当前进程所在IP是192.168.10.100,则UserService采用远程模式加载。需要注意的一点是,每个IP所在的服务必须开通SNCP协议服务以便能接收远程的调用请求。</p>
|
||
|
||
<h3><a id="service_remote" class="anchor" href="#" aria-hidden="true"></a>Service 远程模式</h3>
|
||
<p> 动态生成的远程模式UserService:</p>
|
||
<div class="highlight"><pre><span></span><span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">""</span><span class="o">)</span>
|
||
<span class="nd">@SncpDyn</span><span class="o">(</span><span class="n">remote</span> <span class="o">=</span> <span class="kc">true</span><span class="o">)</span>
|
||
<span class="nd">@ResourceType</span><span class="o">(</span><span class="n">UserService</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">_DynRemoteUserService</span> <span class="kd">extends</span> <span class="n">UserService</span> <span class="o">{</span>
|
||
|
||
<span class="kd">private</span> <span class="n">SncpClient</span> <span class="n">_redkale_client</span><span class="o">;</span>
|
||
|
||
<span class="nd">@SncpDyn</span><span class="o">(</span><span class="n">remote</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">_redkale_register</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">selfrunnable</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">samerunnable</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">diffrunnable</span><span class="o">,</span> <span class="n">UserInfo</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="n">_redkale_client</span><span class="o">.</span><span class="na">remote</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="n">selfrunnable</span><span class="o">,</span> <span class="n">samerunnable</span><span class="o">,</span> <span class="n">diffrunnable</span><span class="o">,</span> <span class="n">user</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@SncpDyn</span><span class="o">(</span><span class="n">remote</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">1</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="n">UserInfo</span> <span class="nf">_redkale_updateUsername</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">selfrunnable</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">samerunnable</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">diffrunnable</span><span class="o">,</span> <span class="kt">int</span> <span class="n">userid</span><span class="o">,</span> <span class="n">String</span> <span class="n">username</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="k">return</span> <span class="n">_redkale_client</span><span class="o">.</span><span class="na">remote</span><span class="o">(</span><span class="mi">1</span><span class="o">,</span> <span class="n">selfrunnable</span><span class="o">,</span> <span class="n">samerunnable</span><span class="o">,</span> <span class="n">diffrunnable</span><span class="o">,</span> <span class="n">userid</span><span class="o">,</span> <span class="n">username</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="n">UserInfo</span> <span class="nf">findUserInfo</span><span class="o">(</span><span class="kt">int</span> <span class="n">userid</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="k">return</span> <span class="n">_redkale_client</span><span class="o">.</span><span class="na">remote</span><span class="o">(</span><span class="mi">2</span><span class="o">,</span> <span class="n">userid</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">findUserid</span><span class="o">(</span><span class="kt">long</span> <span class="n">mobile</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="k">return</span> <span class="n">_redkale_client</span><span class="o">.</span><span class="na">remote</span><span class="o">(</span><span class="mi">3</span><span class="o">,</span> <span class="n">mobile</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="n">RetResult</span><span class="o"><</span><span class="n">UserInfo</span><span class="o">></span> <span class="nf">login</span><span class="o">(</span><span class="n">LoginBean</span> <span class="n">bean</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="k">return</span> <span class="n">_redkale_client</span><span class="o">.</span><span class="na">remote</span><span class="o">(</span><span class="mi">4</span><span class="o">,</span> <span class="n">bean</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">putUserInfo</span><span class="o">(</span><span class="n">UserInfo</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="n">_redkale_client</span><span class="o">.</span><span class="na">remote</span><span class="o">(</span><span class="mi">5</span><span class="o">,</span> <span class="n">user</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">register</span><span class="o">(</span><span class="n">UserInfo</span> <span class="n">user</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="n">_redkale_client</span><span class="o">.</span><span class="na">remote</span><span class="o">(</span><span class="mi">6</span><span class="o">,</span> <span class="n">user</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="n">UserInfo</span> <span class="nf">updateUsername</span><span class="o">(</span><span class="kt">int</span> <span class="n">userid</span><span class="o">,</span> <span class="n">String</span> <span class="n">username</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="k">return</span> <span class="n">_redkale_client</span><span class="o">.</span><span class="na">remote</span><span class="o">(</span><span class="mi">7</span><span class="o">,</span> <span class="n">userid</span><span class="o">,</span> <span class="n">username</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
<span class="o">}</span>
|
||
</pre></div>
|
||
<p> 由以上代码可以看出来,远程模式Service是根据本地模式Service临时类动态生成的。远程类执行方法时通过SNCP协议将参数序列化并带上当前方法信息传输到远程服务器上,执行完后将结果流反序列化并返回, 其流程与WebService类似。</p>
|
||
|
||
<p id="service_dyncall"> <b>远程模式的@RpcCall回调</b> </p>
|
||
<p> 与WebService的区别除了更具性能的二进制的数据格式,更差异的是远程模式的Service允许修改参数本身的内容。范例如下:</p>
|
||
<div class="highlight"><pre><span class="cm">/**</span>
|
||
<span class="cm"> * 由于该方法在处理过程中修改了参数bean的内容,为了保证本地模式与远程模式的一致性,需要提供@RpcCall回调接口</span>
|
||
<span class="cm"> *</span>
|
||
<span class="cm"> * @param bean</span>
|
||
<span class="cm"> * @return</span>
|
||
<span class="cm"> */</span>
|
||
<span class="kd">public</span> <span class="n">RetResult</span><span class="o"><</span><span class="n">UserInfo</span><span class="o">></span> <span class="nf">login</span><span class="o">(</span><span class="nd">@RpcCall</span><span class="o">(</span><span class="n">RpcCallLoginBeanAttribute</span><span class="o">.</span><span class="k">class</span><span class="o">)</span> <span class="n">LoginBean</span> <span class="n">bean</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="n">bean</span><span class="o">.</span><span class="na">setLogintime</span><span class="o">(</span><span class="n">System</span><span class="o">.</span><span class="na">currentTimeMillis</span><span class="o">());</span>
|
||
<span class="n">bean</span><span class="o">.</span><span class="na">setSessionid</span><span class="o">(</span><span class="s">"SID"</span> <span class="o">+</span> <span class="n">System</span><span class="o">.</span><span class="na">currentTimeMillis</span><span class="o">());</span>
|
||
<span class="c1">// 登陆逻辑</span>
|
||
<span class="k">return</span> <span class="k">new</span> <span class="n">RetResult</span><span class="o"><>(</span><span class="mi">100</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
|
||
|
||
<span class="cm">/** RpcCallLoginBeanAttribute 的实现 **/</span>
|
||
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">RpcCallLoginBeanAttribute</span> <span class="kd">implements</span> <span class="n">Attribute</span><span class="o"><</span><span class="n">LoginBean</span><span class="o">,</span> <span class="n">Object</span><span class="o">[]></span> <span class="o">{</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="n">Object</span><span class="o">[]</span> <span class="nf">get</span><span class="o">(</span><span class="n">LoginBean</span> <span class="n">obj</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="k">return</span> <span class="k">new</span> <span class="n">Object</span><span class="o">[]{</span><span class="n">obj</span><span class="o">.</span><span class="na">getLogintime</span><span class="o">(),</span> <span class="n">obj</span><span class="o">.</span><span class="na">getSessionid</span><span class="o">()};</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">set</span><span class="o">(</span><span class="n">LoginBean</span> <span class="n">obj</span><span class="o">,</span> <span class="n">Object</span><span class="o">[]</span> <span class="n">value</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="n">obj</span><span class="o">.</span><span class="na">setLogintime</span><span class="o">((</span><span class="n">Long</span><span class="o">)</span> <span class="n">value</span><span class="o">[</span><span class="mi">0</span><span class="o">]);</span>
|
||
<span class="n">obj</span><span class="o">.</span><span class="na">setSessionid</span><span class="o">((</span><span class="n">String</span><span class="o">)</span> <span class="n">value</span><span class="o">[</span><span class="mi">1</span><span class="o">]);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="n">Class</span><span class="o"><?</span> <span class="kd">extends</span> <span class="n">Object</span><span class="o">[]></span> <span class="nf">type</span><span class="o">()</span> <span class="o">{</span>
|
||
<span class="k">return</span> <span class="n">Object</span><span class="o">[].</span><span class="k">class</span><span class="o">;</span> <span class="c1">//</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="n">Class</span><span class="o"><</span><span class="n">LoginBean</span><span class="o">></span> <span class="nf">declaringClass</span><span class="o">()</span> <span class="o">{</span>
|
||
<span class="k">return</span> <span class="n">LoginBean</span><span class="o">.</span><span class="k">class</span><span class="o">;</span> <span class="c1">//</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">field</span><span class="o">()</span> <span class="o">{</span>
|
||
<span class="k">return</span> <span class="s">""</span><span class="o">;</span> <span class="c1">//可以随意值</span>
|
||
<span class="o">}</span>
|
||
<span class="o">}</span>
|
||
</pre></div>
|
||
<p> 生成远程模式Service时发现参数带有@RpcCall注解的方法,在远程调用返回结果时会进行回调处理。</p>
|
||
|
||
<h3><a id="service_rest" class="anchor" href="#" aria-hidden="true"></a>Service REST</h3>
|
||
<p> RestService提供类似Spring Boot的功能。开启REST功能的HTTP Server在实例化标记为@RestService的Service后自动生成对应的HttpServlet,免去开发人员编写HttpServlet的工作量。主要通过<a href="/javadoc/org/redkale/net/http/RestService.html" target="_blank">@RestService</a>、<a href="/javadoc/org/redkale/net/http/RestMapping.html" target="_blank">@RestMapping</a>、<a href="/javadoc/org/redkale/net/http/RestParam.html" target="_blank">@RestParam</a>这三个注解来实现,同时为了获取其他类型的参数也有<a href="/javadoc/org/redkale/net/http/RestAddress.html" target="_blank">@RestAddress</a>、<a href="/javadoc/org/redkale/net/http/RestCookie.html" target="_blank">@RestCookie</a>、<a href="/javadoc/org/redkale/net/http/RestHeader.html" target="_blank">@RestHeader</a>、<a href="/javadoc/org/redkale/net/http/RestSessionid.html" target="_blank">@RestSessionid</a>、<a href="/javadoc/org/redkale/net/http/RestBody.html" target="_blank">@RestBody</a> 提供其扩展功能。<br/></p>
|
||
<p>
|
||
@RestService : <br>
|
||
</p>
|
||
<div class="highlight"><pre><span></span><span class="cm">/**</span>
|
||
<span class="cm"> * 只能依附在Service类上,name默认为Service的类名小写并去掉Service字样及后面的字符串 (如HelloService/HelloServiceImpl,的默认路径为 hello)。</span>
|
||
<span class="cm"> */</span>
|
||
<span class="nd">@Target</span><span class="o">({</span><span class="n">TYPE</span><span class="o">})</span>
|
||
<span class="nd">@Retention</span><span class="o">(</span><span class="n">RUNTIME</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="nd">@interface</span> <span class="n">RestService</span> <span class="o">{</span>
|
||
|
||
<span class="cm">/**</span>
|
||
<span class="cm"> * 模块名, 只能是模块名,不能含特殊字符, 只能小写字母+数字,且不能以数字开头</span>
|
||
<span class="cm"> *</span>
|
||
<span class="cm"> * @return 模块名</span>
|
||
<span class="cm"> */</span>
|
||
<span class="n">String</span> <span class="nf">name</span><span class="o">()</span> <span class="k">default</span> <span class="s">""</span><span class="o">;</span>
|
||
|
||
<span class="cm">/**</span>
|
||
<span class="cm"> * 目录名, 不能含特殊字符, 只能小写字母+数字,且不能以数字开头</span>
|
||
<span class="cm"> *</span>
|
||
<span class="cm"> * @return 目录名</span>
|
||
<span class="cm"> */</span>
|
||
<span class="n">String</span> <span class="nf">catalog</span><span class="o">()</span> <span class="k">default</span> <span class="s">""</span><span class="o">;</span>
|
||
|
||
<span class="cm">/**</span>
|
||
<span class="cm"> * 模块ID值,鉴权时用到, 对应&#64;WebServlet.moduleid</span>
|
||
<span class="cm"> *</span>
|
||
<span class="cm"> * @return 模块ID值</span>
|
||
<span class="cm"> */</span>
|
||
<span class="kt">int</span> <span class="nf">moduleid</span><span class="o">()</span> <span class="k">default</span> <span class="mi">0</span><span class="o">;</span>
|
||
|
||
<span class="cm">/**</span>
|
||
<span class="cm"> * 没有标记&#64;RestMapping的方法是否转换, 默认为false</span>
|
||
<span class="cm"> *</span>
|
||
<span class="cm"> * @return 默认false</span>
|
||
<span class="cm"> */</span>
|
||
<span class="kt">boolean</span> <span class="nf">automapping</span><span class="o">()</span> <span class="k">default</span> <span class="kc">false</span><span class="o">;</span>
|
||
|
||
<span class="cm">/**</span>
|
||
<span class="cm"> * 是否屏蔽该类的转换</span>
|
||
<span class="cm"> *</span>
|
||
<span class="cm"> * @return 默认false</span>
|
||
<span class="cm"> */</span>
|
||
<span class="kt">boolean</span> <span class="nf">ignore</span><span class="o">()</span> <span class="k">default</span> <span class="kc">false</span><span class="o">;</span>
|
||
|
||
<span class="cm">/**</span>
|
||
<span class="cm"> * 同&#64;WebServlet的repair属性</span>
|
||
<span class="cm"> *</span>
|
||
<span class="cm"> * @return 默认true</span>
|
||
<span class="cm"> */</span>
|
||
<span class="kt">boolean</span> <span class="nf">repair</span><span class="o">()</span> <span class="k">default</span> <span class="kc">true</span><span class="o">;</span>
|
||
|
||
<span class="cm">/**</span>
|
||
<span class="cm"> * 备注描述</span>
|
||
<span class="cm"> *</span>
|
||
<span class="cm"> * @return 备注描述</span>
|
||
<span class="cm"> */</span>
|
||
<span class="n">String</span> <span class="nf">comment</span><span class="o">()</span> <span class="k">default</span> <span class="s">""</span><span class="o">;</span>
|
||
<span class="o">}</span>
|
||
</pre></div>
|
||
|
||
<p>
|
||
@RestMapping : <br>
|
||
</p>
|
||
<div class="highlight"><pre><span class="cm">/**</span>
|
||
<span class="cm"> * 只能依附在Service实现类的public方法上</span>
|
||
<span class="cm"> * value默认为"/" + Service的类名去掉Service及后面字样的小写字符串 (如HelloService,的默认路径为/hello)。</span>
|
||
<span class="cm"> */</span>
|
||
<span class="nd">@Target</span><span class="o">({</span><span class="n">METHOD</span><span class="o">})</span>
|
||
<span class="kd">public</span> <span class="nd">@interface</span> <span class="n">RestMapping</span> <span class="o">{</span>
|
||
|
||
<span class="kt">boolean</span> <span class="nf">ignore</span><span class="o">()</span> <span class="k">default</span> <span class="kc">false</span><span class="o">;</span> <span class="c1">//是否屏蔽该方法的转换</span>
|
||
|
||
<span class="c1">//请求的方法名, 不能含特殊字符</span>
|
||
<span class="c1">//默认为方法名的小写(若方法名以createXXX、updateXXX、deleteXXX、queryXXX、findXXX且XXXService为Service的类名将只截取XXX之前)</span>
|
||
<span class="n">String</span> <span class="nf">name</span><span class="o">()</span> <span class="k">default</span> <span class="s">""</span><span class="o">;</span>
|
||
|
||
<span class="n">String</span> <span class="nf">comment</span><span class="o">()</span> <span class="k">default</span> <span class="s">""</span><span class="o">;</span> <span class="c1">//备注描述, 对应@HttpMapping.comment </span>
|
||
|
||
<span class="kt">boolean</span> <span class="nf">auth</span><span class="o">()</span> <span class="k">default</span> <span class="kc">true</span><span class="o">;</span> <span class="c1">//是否鉴权,默认需要鉴权, 对应@HttpMapping.auth </span>
|
||
|
||
<span class="kt">int</span> <span class="nf">cacheseconds</span><span class="o">()</span> <span class="k">default</span> <span class="mi">0</span><span class="o">;</span> <span class="c1">//结果缓存的秒数, 为0表示不缓存, 对应@HttpMapping.cacheseconds</span>
|
||
|
||
<span class="kt">int</span> <span class="nf">actionid</span><span class="o">()</span> <span class="k">default</span> <span class="mi">0</span><span class="o">;</span> <span class="c1">//操作ID值,鉴权时用到, 对应@HttpMapping.actionid</span>
|
||
|
||
<span class="n">String[]</span> <span class="nf">methods</span><span class="o">()</span> <span class="k">default</span> <span class="mi">{}</span><span class="o">;</span> <span class="c1">//允许方法(不区分大小写),如:GET/POST/PUT,为空表示允许所有方法, 对应@HttpMapping.methods</span>
|
||
<span class="o">}</span>
|
||
</pre></div>
|
||
|
||
<p>
|
||
@RestParam : <br>
|
||
</p>
|
||
<div class="highlight"><pre><span class="cm">/**</span>
|
||
<span class="cm"> * 只能依附在Service类的方法的参数上</span>
|
||
<span class="cm"> */</span>
|
||
<span class="nd">@Target</span><span class="o">({</span><span class="n">PARAMETER</span><span class="o">})</span>
|
||
<span class="kd">public</span> <span class="nd">@interface</span> <span class="n">RestParam</span> <span class="o">{</span>
|
||
|
||
<span class="c1">//参数名 name='&'表示当前用户;</span>
|
||
<span class="c1">//参数名 name='#'表示截取uri最后一段; </span>
|
||
<span class="c1">//参数名 name='#xxx:'表示从uri中/pipes/xxx:v/截取xxx:的值; </span>
|
||
<span class="c1">//若方法名以find、delete开头且方法的参数只有一个且参数类型是基本数据类型或String,则默认值为"#"; </span>
|
||
<span class="n">String</span> <span class="nf">name</span><span class="o">();</span>
|
||
|
||
<span class="kt">int</span> <span class="nf">radix</span><span class="o">()</span> <span class="k">default</span> <span class="mi">10</span><span class="o">;</span> <span class="c1">//转换数字byte/short/int/long时所用的进制数, 默认10进制</span>
|
||
|
||
<span class="kt">boolean</span> <span class="nf">required</span><span class="o">()</span> <span class="k">default</span> <span class="kc">true</span><span class="o">;</span> <span class="c1">//参数是否必传 </span>
|
||
|
||
<span class="n">String</span> <span class="nf">comment</span><span class="o">()</span> <span class="k">default</span> <span class="s">""</span><span class="o">;</span> <span class="c1">//备注描述, 对应@HttpMapping.comment </span>
|
||
<span class="o">}</span>
|
||
</pre></div>
|
||
<p> 开启REST功能的步骤很简单:在 <a href="redkale.html#redkale_confxml" target="_blank">application.xml</a> 的 <b><server></b> 节点下增加<b><rest></b>指明RestServlet的子类。<br/></p>
|
||
|
||
<div class="highlight"><pre><span></span><span class="c"><!-- </span>
|
||
<span class="c"> REST的核心配置项, 存在[rest]节点则Server启动时会加载REST服务, 当Server为SNCP协议时,则SncpServer会变成REST的HttpServer, 节点可以多个</span>
|
||
<span class="c"> path: servlet的ContextPath前缀 默认为空</span>
|
||
<span class="c"> base: REST服务的BaseServlet,必须是org.redkale.net.http.HttpServlet的子类,且子类必须标记 @HttpUserType。</span>
|
||
<span class="c"> autoload:默认值"true" 默认值. 加载当前server所能使用的Servce对象; </span>
|
||
<span class="c"> includes:当autoload="true", 拉取类名与includes中的正则表达式匹配的类, 多个正则表达式用分号;隔开</span>
|
||
<span class="c"> excludes:当autoload="true", 排除类名与excludes中的正则表达式匹配的类, 多个正则表达式用分号;隔开</span>
|
||
<span class="c">--></span>
|
||
<span class="p"><</span><span class="nt">rest</span> <span class="na">path</span><span class="o">=</span><span class="s">"/pipes"</span> <span class="na">base</span><span class="o">=</span><span class="s">"org.redkale.net.http.HttpServlet"</span> <span class="na">autoload</span><span class="o">=</span><span class="s">"true"</span> <span class="na">includes</span><span class="o">=</span><span class="s">""</span> <span class="na">excludes</span><span class="o">=</span><span class="s">""</span><span class="p">></span>
|
||
<span class="c"><!-- </span>
|
||
<span class="c"> value: Service类名,列出的表示必须被加载的Service对象</span>
|
||
<span class="c"> ignore: 是否忽略,设置为true则不会加载该Service对象,默认值为false</span>
|
||
<span class="c"> --></span>
|
||
<span class="p"><</span><span class="nt">service</span> <span class="na">value</span><span class="o">=</span><span class="s">"com.xxx.XXXXService"</span><span class="p">/></span>
|
||
<span class="p"></</span><span class="nt">rest</span><span class="p">></span>
|
||
</pre></div>
|
||
<p> Redkale中的REST并非严格遵循标准的REST规范,在尽量满足规范的同时也考虑到开发的灵活性和简易性。以下通过简单的实例来说明其特性。<br/></p>
|
||
<p>
|
||
通常配置都需要编写一个 <b>org.redkale.net.http.HttpServlet</b> 子类,主要用于获取当前用户信息和鉴权,且必须指定具体的User对象类。开发者的实现类可以参考 <a href="https://github.com/redkale/redkale-demo/tree/master/src/org/redkale/demo/base" target="_blank">redkale-demo</a> 中的BaseServlet类,以下是一个简单的范例: <br>
|
||
</p>
|
||
<div class="highlight"><pre><span></span><span class="nd">@HttpUserType</span><span class="o">(</span><span class="n">UserInfo</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">SimpleRestServlet</span> <span class="kd">extends</span> <span class="n">HttpServlet</span> <span class="o">{</span>
|
||
|
||
<span class="kd">protected</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">RetResult</span> <span class="n">RET_UNLOGIN</span> <span class="o">=</span> <span class="n">RetCodes</span><span class="o">.</span><span class="na">retResult</span><span class="o">(</span><span class="n">RetCodes</span><span class="o">.</span><span class="na">RET_USER_UNLOGIN</span><span class="o">);</span>
|
||
|
||
<span class="kd">protected</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">RetResult</span> <span class="n">RET_AUTHILLEGAL</span> <span class="o">=</span> <span class="n">RetCodes</span><span class="o">.</span><span class="na">retResult</span><span class="o">(</span><span class="n">RetCodes</span><span class="o">.</span><span class="na">RET_USER_AUTH_ILLEGAL</span><span class="o">);</span>
|
||
|
||
<span class="nd">@Resource</span>
|
||
<span class="kd">private</span> <span class="n">UserService</span> <span class="n">userService</span><span class="o">;</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">preExecute</span><span class="o">(</span><span class="n">HttpRequest</span> <span class="n">request</span><span class="o">,</span> <span class="n">HttpResponse</span> <span class="n">response</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
|
||
<span class="kd">final</span> <span class="n">String</span> <span class="n">sessionid</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="na">getSessionid</span><span class="o">(</span><span class="kc">false</span><span class="o">);</span>
|
||
<span class="k">if</span> <span class="o">(</span><span class="n">sessionid</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="n">request</span><span class="o">.</span><span class="na">setCurrentUser</span><span class="o">(</span><span class="n">userService</span><span class="o">.</span><span class="na">current</span><span class="o">(</span><span class="n">sessionid</span><span class="o">));</span>
|
||
<span class="n">response</span><span class="o">.</span><span class="na">nextEvent</span><span class="o">();</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="c1">//普通鉴权</span>
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">authenticate</span><span class="o">(</span><span class="n">HttpRequest</span> <span class="n">request</span><span class="o">,</span> <span class="n">HttpResponse</span> <span class="n">response</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
|
||
<span class="n">UserInfo</span> <span class="n">info</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="na">currentUser</span><span class="o">();</span>
|
||
<span class="k">if</span> <span class="o">(</span><span class="n">info</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="n">response</span><span class="o">.</span><span class="na">finishJson</span><span class="o">(</span><span class="n">RET_UNLOGIN</span><span class="o">);</span>
|
||
<span class="k">return</span><span class="o">;</span>
|
||
<span class="o">}</span> <span class="k">else</span> <span class="k">if</span> <span class="o">(!</span><span class="n">info</span><span class="o">.</span><span class="na">checkAuth</span><span class="o">(</span><span class="n">request</span><span class="o">.</span><span class="na">getModuleid</span><span class="o">(),</span> <span class="n">request</span><span class="o">.</span><span class="na">getActionid</span><span class="o">()))</span> <span class="o">{</span>
|
||
<span class="n">response</span><span class="o">.</span><span class="na">finishJson</span><span class="o">(</span><span class="n">RET_AUTHILLEGAL</span><span class="o">);</span>
|
||
<span class="k">return</span><span class="o">;</span>
|
||
<span class="o">}</span>
|
||
<span class="n">response</span><span class="o">.</span><span class="na">nextEvent</span><span class="o">();</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="o">}</span>
|
||
</pre></div>
|
||
<p>
|
||
REST的设置方式有两种: 一种采用默认REST注解,一种是显式的设置。 <br>
|
||
</p>
|
||
<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloBean</span> <span class="kd">implements</span> <span class="n">FilterBean</span> <span class="o">{</span>
|
||
|
||
<span class="kd">private</span> <span class="kt">int</span> <span class="n">helloid</span><span class="o">;</span>
|
||
|
||
<span class="nd">@RestHeader</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"User-Agent"</span><span class="o">)</span>
|
||
<span class="kd">private</span> <span class="n">String</span> <span class="n">useragent</span><span class="o">;</span> <span class="c1">//从Http Header中获取浏览器信息</span>
|
||
|
||
<span class="nd">@RestCookie</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"hello-cookie"</span><span class="o">)</span>
|
||
<span class="kd">private</span> <span class="n">String</span> <span class="n">rescookie</span><span class="o">;</span> <span class="c1">//从Cookie中获取名为hello-cookie的值</span>
|
||
|
||
<span class="nd">@RestAddress</span>
|
||
<span class="kd">private</span> <span class="n">String</span> <span class="n">clientaddr</span><span class="o">;</span> <span class="c1">//客户端请求IP</span>
|
||
|
||
<span class="nd">@RestSessionid</span>
|
||
<span class="kd">private</span> <span class="n">String</span> <span class="n">sessionid</span><span class="o">;</span> <span class="c1">//用户Sessionid, 未登录时为null</span>
|
||
|
||
<span class="cm">/** 以下省略getter setter方法 */</span>
|
||
<span class="o">}</span>
|
||
</pre></div>
|
||
|
||
<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloEntity</span> <span class="o">{</span>
|
||
|
||
<span class="nd">@Id</span>
|
||
<span class="kd">private</span> <span class="kt">int</span> <span class="n">helloid</span><span class="o">;</span>
|
||
|
||
<span class="kd">private</span> <span class="n">String</span> <span class="n">helloname</span><span class="o">;</span>
|
||
|
||
<span class="kd">private</span> <span class="kt">int</span> <span class="n">creator</span><span class="o">;</span>
|
||
|
||
<span class="kd">private</span> <span class="kt">long</span> <span class="n">updatetime</span><span class="o">;</span>
|
||
|
||
<span class="kd">private</span> <span class="kt">long</span> <span class="n">createtime</span><span class="o">;</span>
|
||
|
||
<span class="nd">@RestHeader</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"hello-res"</span><span class="o">)</span>
|
||
<span class="kd">private</span> <span class="n">String</span> <span class="n">resname</span><span class="o">;</span>
|
||
|
||
<span class="nd">@RestAddress</span>
|
||
<span class="kd">private</span> <span class="n">String</span> <span class="n">clientaddr</span><span class="o">;</span>
|
||
|
||
<span class="cm">/** 以下省略getter setter方法 */</span>
|
||
<span class="o">}</span>
|
||
</pre></div>
|
||
|
||
<div id="helloservice" class="highlight"><pre><span></span><span class="cm">/**</span>
|
||
<span class="cm"> * 类说明:</span>
|
||
<span class="cm"> * Flipper : Source组件中的翻页对象</span>
|
||
<span class="cm"> * UserInfo :当前用户类</span>
|
||
<span class="cm"> * HelloEntity: Hello模块的实体类</span>
|
||
<span class="cm"> * HelloBean: Hello模块实现FilterBean的过滤Bean类</span>
|
||
<span class="cm"> *</span>
|
||
<span class="cm"> */</span>
|
||
<span class="nd">@RestService</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"hello"</span><span class="o">,</span> <span class="n">moduleid</span> <span class="o">=</span> <span class="mi">0</span><span class="o">,</span> <span class="n">repair</span> <span class="o">=</span> <span class="kc">true</span><span class="o">,</span> <span class="n">ignore</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"Hello服务模块"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloService</span> <span class="kd">implements</span> <span class="n">Service</span> <span class="o">{</span>
|
||
|
||
<span class="nd">@Resource</span>
|
||
<span class="kd">private</span> <span class="n">DataSource</span> <span class="n">source</span><span class="o">;</span>
|
||
|
||
<span class="c1">//增加记录</span>
|
||
<span class="nd">@RestMapping</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"create"</span><span class="o">,</span> <span class="n">auth</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"创建Hello对象"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="n">RetResult</span><span class="o"><</span><span class="n">HelloEntity</span><span class="o">></span> <span class="nf">createHello</span><span class="o">(</span><span class="n">UserInfo</span> <span class="n">info</span><span class="o">,</span> <span class="nd">@RestParam</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"bean"</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"Hello对象"</span><span class="o">)</span> <span class="n">HelloEntity</span> <span class="n">entity</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="n">entity</span><span class="o">.</span><span class="na">setCreator</span><span class="o">(</span><span class="n">info</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">?</span> <span class="mi">0</span> <span class="o">:</span> <span class="n">info</span><span class="o">.</span><span class="na">getUserid</span><span class="o">());</span> <span class="c1">//设置当前用户ID</span>
|
||
<span class="n">entity</span><span class="o">.</span><span class="na">setCreatetime</span><span class="o">(</span><span class="n">System</span><span class="o">.</span><span class="na">currentTimeMillis</span><span class="o">());</span>
|
||
<span class="n">source</span><span class="o">.</span><span class="na">insert</span><span class="o">(</span><span class="n">entity</span><span class="o">);</span>
|
||
<span class="k">return</span> <span class="k">new</span> <span class="n">RetResult</span><span class="o"><>(</span><span class="n">entity</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="c1">//删除记录</span>
|
||
<span class="nd">@RestMapping</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"delete"</span><span class="o">,</span> <span class="n">auth</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"根据id删除Hello对象"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">deleteHello</span><span class="o">(</span><span class="nd">@RestParam</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"#"</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"Hello对象id"</span><span class="o">)</span> <span class="kt">int</span> <span class="n">id</span><span class="o">)</span> <span class="o">{</span> <span class="c1">//通过 /hello/delete/1234 删除对象</span>
|
||
<span class="n">source</span><span class="o">.</span><span class="na">delete</span><span class="o">(</span><span class="n">HelloEntity</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">id</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="c1">//修改记录</span>
|
||
<span class="nd">@RestMapping</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"update"</span><span class="o">,</span> <span class="n">auth</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"修改Hello对象"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">updateHello</span><span class="o">(</span><span class="nd">@RestParam</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"bean"</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"Hello对象"</span><span class="o">)</span> <span class="n">HelloEntity</span> <span class="n">entity</span><span class="o">)</span> <span class="o">{</span> <span class="c1">//通过 /hello/update?bean={...} 修改对象</span>
|
||
<span class="n">entity</span><span class="o">.</span><span class="na">setUpdatetime</span><span class="o">(</span><span class="n">System</span><span class="o">.</span><span class="na">currentTimeMillis</span><span class="o">());</span>
|
||
<span class="n">source</span><span class="o">.</span><span class="na">update</span><span class="o">(</span><span class="n">entity</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="c1">//查询列表</span>
|
||
<span class="c1">//通过 /hello/query/offset:0/limit:20?bean={...} 获取结果</span>
|
||
<span class="nd">@RestMapping</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"query"</span><span class="o">,</span> <span class="n">auth</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"查询Hello对象列表"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="n">Sheet</span><span class="o"><</span><span class="n">HelloEntity</span><span class="o">></span> <span class="nf">queryHello</span><span class="o">(</span><span class="nd">@RestParam</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"bean"</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"过滤条件"</span><span class="o">)</span> <span class="n">HelloBean</span> <span class="n">bean</span><span class="o">,</span> <span class="n">Flipper</span> <span class="n">flipper</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="k">return</span> <span class="n">source</span><span class="o">.</span><span class="na">querySheet</span><span class="o">(</span><span class="n">HelloEntity</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">flipper</span><span class="o">,</span> <span class="n">bean</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="c1">//查询单个</span>
|
||
<span class="nd">@RestMapping</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"find"</span><span class="o">,</span> <span class="n">auth</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"根据id查找单个Hello对象"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="n">HelloEntity</span> <span class="nf">findHello</span><span class="o">(</span><span class="nd">@RestParam</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"#"</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"Hello对象id"</span><span class="o">)</span> <span class="kt">int</span> <span class="n">id</span><span class="o">)</span> <span class="o">{</span> <span class="c1">//通过 /hello/find/1234 查询对象</span>
|
||
<span class="k">return</span> <span class="n">source</span><span class="o">.</span><span class="na">find</span><span class="o">(</span><span class="n">HelloEntity</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">id</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="c1"><b>//异步查询单个</b></span>
|
||
<span class="nd">@RestMapping</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"asyncfind"</span><span class="o">,</span> <span class="n">auth</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"根据id查找单个Hello对象"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="n">CompletableFuture<HelloEntity></span> <span class="nf">findAsyncHello</span><span class="o">(</span><span class="nd">@RestParam</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"#"</span><span class="o">)</span> <span class="kt">int</span> <span class="n">id</span><span class="o">)</span> <span class="o">{</span> <span class="c1">//通过 /pipes/hello/asyncfind/1234 查询对象</span>
|
||
<span class="k">return</span> <span class="n">source</span><span class="o">.</span><span class="na">findAsync</span><span class="o">(</span><span class="n">HelloEntity</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">id</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
<span class="o">}</span>
|
||
</pre></div>
|
||
|
||
<p>
|
||
根据默认命名规则可以看出,以上范例生成的HttpServlet与去掉所有@RestService、@RestMapping、@RestParam后的Service生成的是完全相同的。 REST根据Service会动态生成HttpServlet,以上范例自动生成的HttpServlet如下:<br>
|
||
</p>
|
||
|
||
<div class="highlight"><pre><span></span><span class="nd">@WebServlet</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="o">{</span><span class="s">"/hello/*"</span><span class="o">},</span> <span class="n">repair</span> <span class="o">=</span> <span class="kc">true</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">_DynHelloRestServlet</span> <span class="kd">extends</span> <span class="n">SimpleRestServlet</span> <span class="o">{</span>
|
||
|
||
<span class="nd">@Resource</span>
|
||
<span class="kd">private</span> <span class="n">HelloService</span> <span class="n">_service</span><span class="o">;</span>
|
||
|
||
<span class="nd">@Resource</span>
|
||
<span class="kd">private</span> <span class="n">Map</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">HelloService</span><span class="o">></span> <span class="n">_servicemap</span><span class="o">;</span>
|
||
|
||
<span class="nd">@HttpMapping</span><span class="o">(</span><span class="n">url</span> <span class="o">=</span> <span class="s">"/hello/create"</span><span class="o">,</span> <span class="n">auth</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"创建Hello对象"</span><span class="o">)</span>
|
||
<span class="nd">@HttpParam</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"bean"</span><span class="o">,</span> <span class="n">type</span> <span class="o">=</span> <span class="n">HelloEntity</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"Hello对象"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">create</span><span class="o">(</span><span class="n">HttpRequest</span> <span class="n">req</span><span class="o">,</span> <span class="n">HttpResponse</span> <span class="n">resp</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
|
||
<span class="n">HelloService</span> <span class="n">service</span> <span class="o">=</span> <span class="n">_servicemap</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">?</span> <span class="n">_service</span> <span class="o">:</span> <span class="n">_servicemap</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getHeader</span><span class="o">(</span><span class="n">Rest</span><span class="o">.</span><span class="na">REST_HEADER_RESOURCE_NAME</span><span class="o">,</span> <span class="s">""</span><span class="o">));</span>
|
||
<span class="n">HelloEntity</span> <span class="n">bean</span> <span class="o">=</span> <span class="n">req</span><span class="o">.</span><span class="na">getJsonParameter</span><span class="o">(</span><span class="n">HelloEntity</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="s">"bean"</span><span class="o">);</span>
|
||
<span class="n">bean</span><span class="o">.</span><span class="na">setClientaddr</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getRemoteAddr</span><span class="o">());</span>
|
||
<span class="n">bean</span><span class="o">.</span><span class="na">setResname</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getHeader</span><span class="o">(</span><span class="s">"hello-res"</span><span class="o">));</span>
|
||
<span class="n">UserInfo</span> <span class="n">user</span> <span class="o">=</span> <span class="n">currentUser</span><span class="o">(</span><span class="n">req</span><span class="o">);</span>
|
||
<span class="n">RetResult</span><span class="o"><</span><span class="n">HelloEntity</span><span class="o">></span> <span class="n">result</span> <span class="o">=</span> <span class="n">service</span><span class="o">.</span><span class="na">createHello</span><span class="o">(</span><span class="n">user</span><span class="o">,</span> <span class="n">bean</span><span class="o">);</span>
|
||
<span class="n">resp</span><span class="o">.</span><span class="na">finishJson</span><span class="o">(</span><span class="n">result</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@HttpMapping</span><span class="o">(</span><span class="n">url</span> <span class="o">=</span> <span class="s">"/hello/delete/"</span><span class="o">,</span> <span class="n">auth</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"根据id删除Hello对象"</span><span class="o">)</span>
|
||
<span class="nd">@HttpParam</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"#"</span><span class="o">,</span> <span class="n">type</span> <span class="o">=</span> <span class="kt">int</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"Hello对象id"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">delete</span><span class="o">(</span><span class="n">HttpRequest</span> <span class="n">req</span><span class="o">,</span> <span class="n">HttpResponse</span> <span class="n">resp</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
|
||
<span class="n">HelloService</span> <span class="n">service</span> <span class="o">=</span> <span class="n">_servicemap</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">?</span> <span class="n">_service</span> <span class="o">:</span> <span class="n">_servicemap</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getHeader</span><span class="o">(</span><span class="n">Rest</span><span class="o">.</span><span class="na">REST_HEADER_RESOURCE_NAME</span><span class="o">,</span> <span class="s">""</span><span class="o">));</span>
|
||
<span class="kt">int</span> <span class="n">id</span> <span class="o">=</span> <span class="n">Integer</span><span class="o">.</span><span class="na">parseInt</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getRequstURILastPath</span><span class="o">());</span>
|
||
<span class="n">service</span><span class="o">.</span><span class="na">deleteHello</span><span class="o">(</span><span class="n">id</span><span class="o">);</span>
|
||
<span class="n">resp</span><span class="o">.</span><span class="na">finishJson</span><span class="o">(</span><span class="n">RetResult</span><span class="o">.</span><span class="na">success</span><span class="o">());</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@HttpMapping</span><span class="o">(</span><span class="n">url</span> <span class="o">=</span> <span class="s">"/hello/update"</span><span class="o">,</span> <span class="n">auth</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"修改Hello对象"</span><span class="o">)</span>
|
||
<span class="nd">@HttpParam</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"bean"</span><span class="o">,</span> <span class="n">type</span> <span class="o">=</span> <span class="n">HelloEntity</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"Hello对象"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">update</span><span class="o">(</span><span class="n">HttpRequest</span> <span class="n">req</span><span class="o">,</span> <span class="n">HttpResponse</span> <span class="n">resp</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
|
||
<span class="n">HelloService</span> <span class="n">service</span> <span class="o">=</span> <span class="n">_servicemap</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">?</span> <span class="n">_service</span> <span class="o">:</span> <span class="n">_servicemap</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getHeader</span><span class="o">(</span><span class="n">Rest</span><span class="o">.</span><span class="na">REST_HEADER_RESOURCE_NAME</span><span class="o">,</span> <span class="s">""</span><span class="o">));</span>
|
||
<span class="n">HelloEntity</span> <span class="n">bean</span> <span class="o">=</span> <span class="n">req</span><span class="o">.</span><span class="na">getJsonParameter</span><span class="o">(</span><span class="n">HelloEntity</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="s">"bean"</span><span class="o">);</span>
|
||
<span class="n">bean</span><span class="o">.</span><span class="na">setClientaddr</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getRemoteAddr</span><span class="o">());</span>
|
||
<span class="n">bean</span><span class="o">.</span><span class="na">setResname</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getHeader</span><span class="o">(</span><span class="s">"hello-res"</span><span class="o">));</span>
|
||
<span class="n">service</span><span class="o">.</span><span class="na">updateHello</span><span class="o">(</span><span class="n">bean</span><span class="o">);</span>
|
||
<span class="n">resp</span><span class="o">.</span><span class="na">finishJson</span><span class="o">(</span><span class="n">RetResult</span><span class="o">.</span><span class="na">success</span><span class="o">());</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@HttpMapping</span><span class="o">(</span><span class="n">url</span> <span class="o">=</span> <span class="s">"/hello/query"</span><span class="o">,</span> <span class="n">auth</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"查询Hello对象列表"</span><span class="o">)</span>
|
||
<span class="nd">@HttpParam</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"bean"</span><span class="o">,</span> <span class="n">type</span> <span class="o">=</span> <span class="n">HelloBean</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"过滤条件"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">query</span><span class="o">(</span><span class="n">HttpRequest</span> <span class="n">req</span><span class="o">,</span> <span class="n">HttpResponse</span> <span class="n">resp</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
|
||
<span class="n">HelloService</span> <span class="n">service</span> <span class="o">=</span> <span class="n">_servicemap</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">?</span> <span class="n">_service</span> <span class="o">:</span> <span class="n">_servicemap</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getHeader</span><span class="o">(</span><span class="n">Rest</span><span class="o">.</span><span class="na">REST_HEADER_RESOURCE_NAME</span><span class="o">,</span> <span class="s">""</span><span class="o">));</span>
|
||
<span class="n">HelloBean</span> <span class="n">bean</span> <span class="o">=</span> <span class="n">req</span><span class="o">.</span><span class="na">getJsonParameter</span><span class="o">(</span><span class="n">HelloBean</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="s">"bean"</span><span class="o">);</span>
|
||
<span class="n">bean</span><span class="o">.</span><span class="na">setClientaddr</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getRemoteAddr</span><span class="o">());</span>
|
||
<span class="n">bean</span><span class="o">.</span><span class="na">setUseragent</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getHeader</span><span class="o">(</span><span class="s">"User-Agent"</span><span class="o">));</span>
|
||
<span class="n">bean</span><span class="o">.</span><span class="na">setRescookie</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getCookie</span><span class="o">(</span><span class="s">"hello-cookie"</span><span class="o">));</span>
|
||
<span class="n">bean</span><span class="o">.</span><span class="na">setSessionid</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getSessionid</span><span class="o">(</span><span class="kc">false</span><span class="o">));</span>
|
||
<span class="n">Flipper</span> <span class="n">flipper</span> <span class="o">=</span> <span class="n">req</span><span class="o">.</span><span class="na">getFlipper</span><span class="o">();</span>
|
||
<span class="n">Sheet</span><span class="o"><</span><span class="n">HelloEntity</span><span class="o">></span> <span class="n">result</span> <span class="o">=</span> <span class="n">service</span><span class="o">.</span><span class="na">queryHello</span><span class="o">(</span><span class="n">bean</span><span class="o">,</span> <span class="n">flipper</span><span class="o">);</span>
|
||
<span class="n">resp</span><span class="o">.</span><span class="na">finishJson</span><span class="o">(</span><span class="n">result</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@HttpMapping</span><span class="o">(</span><span class="n">url</span> <span class="o">=</span> <span class="s">"/hello/find/"</span><span class="o">,</span> <span class="n">auth</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"根据id查找单个Hello对象"</span><span class="o">)</span>
|
||
<span class="nd">@HttpParam</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"#"</span><span class="o">,</span> <span class="n">type</span> <span class="o">=</span> <span class="kt">int</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"Hello对象id"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">find</span><span class="o">(</span><span class="n">HttpRequest</span> <span class="n">req</span><span class="o">,</span> <span class="n">HttpResponse</span> <span class="n">resp</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
|
||
<span class="n">HelloService</span> <span class="n">service</span> <span class="o">=</span> <span class="n">_servicemap</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">?</span> <span class="n">_service</span> <span class="o">:</span> <span class="n">_servicemap</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getHeader</span><span class="o">(</span><span class="n">Rest</span><span class="o">.</span><span class="na">REST_HEADER_RESOURCE_NAME</span><span class="o">,</span> <span class="s">""</span><span class="o">));</span>
|
||
<span class="kt">int</span> <span class="n">id</span> <span class="o">=</span> <span class="n">Integer</span><span class="o">.</span><span class="na">parseInt</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getRequstURILastPath</span><span class="o">());</span>
|
||
<span class="n">HelloEntity</span> <span class="n">bean</span> <span class="o">=</span> <span class="n">service</span><span class="o">.</span><span class="na">findHello</span><span class="o">(</span><span class="n">id</span><span class="o">);</span>
|
||
<span class="n">resp</span><span class="o">.</span><span class="na">finishJson</span><span class="o">(</span><span class="n">bean</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@HttpMapping</span><span class="o">(</span><span class="n">url</span> <span class="o">=</span> <span class="s">"/hello/asyncfind/"</span><span class="o">,</span> <span class="n">auth</span> <span class="o">=</span> <span class="kc">false</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"根据id查找单个Hello对象"</span><span class="o">)</span>
|
||
<span class="nd">@HttpParam</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"#"</span><span class="o">,</span> <span class="n">type</span> <span class="o">=</span> <span class="kt">int</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"Hello对象id"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">asyncfind</span><span class="o">(</span><span class="n">HttpRequest</span> <span class="n">req</span><span class="o">,</span> <span class="n">HttpResponse</span> <span class="n">resp</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
|
||
<span class="n">HelloService</span> <span class="n">service</span> <span class="o">=</span> <span class="n">_servicemap</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">?</span> <span class="n">_service</span> <span class="o">:</span> <span class="n">_servicemap</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getHeader</span><span class="o">(</span><span class="n">Rest</span><span class="o">.</span><span class="na">REST_HEADER_RESOURCE_NAME</span><span class="o">,</span> <span class="s">""</span><span class="o">));</span>
|
||
<span class="kt">int</span> <span class="n">id</span> <span class="o">=</span> <span class="n">Integer</span><span class="o">.</span><span class="na">parseInt</span><span class="o">(</span><span class="n">req</span><span class="o">.</span><span class="na">getRequstURILastPath</span><span class="o">());</span>
|
||
<span class="n">resp</span><span class="o">.</span><span class="na">finishJson</span><span class="o">(</span><span class="n">service</span><span class="o">.</span><span class="na">findAsyncHello</span><span class="o">(</span><span class="n">id</span><span class="o">));</span>
|
||
<span class="o">}</span>
|
||
<span class="o">}</span>
|
||
</pre></div>
|
||
|
||
|
||
<h3><a id="service_async" class="anchor" href="#" aria-hidden="true"></a>Service 异步调用</h3>
|
||
<p> 远程模式不仅对@RpcCall注解进行处理,而且对方法含有 <b>CompletionHandler</b> 的参数或返回类型为<b>CompletableFuture</b>也进行异步特殊处理。异步调用对远程模式非常有意义,可以减少同步方式对当前线程的占用时间。也给Source组件的异步调用提供了基础。</p>
|
||
<div class="highlight"><pre> <span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="kt">void</span> <span class="nf">updateAsync</span><span class="o">(</span><span class="kd">final</span> <span class="n">CompletionHandler</span><span class="o"><</span><span class="n">Void</span><span class="o">,</span> <span class="n">T</span><span class="o">[]></span> <span class="n">handler</span><span class="o">,</span> <span class="nd">@RpcAttachment</span> <span class="kd">final</span> <span class="n">T</span><span class="o">...</span> <span class="n">values</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="n">source</span><span class="o">.</span><span class="na">update</span><span class="o">(</span><span class="n">values</span><span class="o">);</span>
|
||
<span class="k">if</span> <span class="o">(</span><span class="n">handler</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="n">handler</span><span class="o">.</span><span class="na">completed</span><span class="o">(</span><span class="kc">null</span><span class="o">,</span> <span class="n">values</span><span class="o">);</span>
|
||
<span class="o">}</span></pre></div>
|
||
<p>
|
||
如上图源码,异步接口(含<b>CompletionHandler</b>参数或返回类型为<b>CompletableFuture</b>)与同步接口执行流程相同。当Service为远程模式时,调用异步接口时,通信接口发到远程服务器时CompletionHandler参数的值传<b>null</b>,返回数据后再调用本地的CompletionHandler参数值执行。<br/>
|
||
异步调用方式是提高服务并发性的有效手段,特别是在远程模式Service比较多的情况下效果更明显。以HTTP服务为例,在Tomcat刚刚改版成NIO的时候,网上随处可见都是大谈NIO性能比BIO多好,认为BIO与NIO的不同,是BIO往往会引入多线程,每个连接一个单独的线程;NIO则是使用单线程或者只使用少量的多线程,每个连接共用一个线程。而事实上呢,通常还是通过增加线程数来提高并发量。为什么NIO作用不大呢, 因为一个HTTP动态请求耗时最多是业务逻辑层,特别是操作数据库,IO操作的耗时比重小得多,只有在静态资源请求这种纯IO操作才能体现NIO、AIO(NIO.2)的优势。举例一个简单的数据查询请求,采用BIO方式耗时(为了方便比较将所耗时间扩大几倍)如下: <br>
|
||
1、服务器TCP连接开始到进入HttpServlet,耗时 10ms <br>
|
||
2、用户态判断和参数验证, 耗时 10ms <br>
|
||
3、调用远程数据源(DataSource)查询数据,耗时 150ms <br>
|
||
4、数据序列化与response的IO输出, 耗时 10ms <br>
|
||
如上描述,一个请求处理耗时 180ms,同时占用一个线程的时间也是 180ms。若换成NIO使IO耗时减少,为了方便计算假设IO耗时为0(实际情况是不可能的), 那么步骤1、4的耗时忽略不计,线程的占用时间由180ms变成160ms。 假设数据查询接口IO操作本身耗时也是10ms,那么有140ms是用于等待。若采用DataSource异步接口, 则140ms的等待时间可以释放当前线程资源。虽然整个请求的处理时间还是180ms,但是线程的占用时间却只有20ms。可以看出减少耗时多的步骤的等待时间才能事半功倍,大幅度地提高性能。异步接口的主要作用是远程请求在等待过程中释放当前线程资源,大大减少线程数。
|
||
</p>
|
||
|
||
<footer class="site-footer">
|
||
<span class="site-footer-owner"> 欢迎加入Redkale QQ群: 527523235</span>
|
||
</footer>
|
||
|
||
</section>
|
||
|
||
<script>
|
||
var _hmt = _hmt || [];
|
||
(function () {
|
||
var hm = document.createElement("script");
|
||
hm.src = "//hm.baidu.com/hm.js?b4e05d7de8b5f3401dd93e3c6b35ffa5";
|
||
var s = document.getElementsByTagName("script")[0];
|
||
s.parentNode.insertBefore(hm, s);
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|