688 lines
82 KiB
HTML
688 lines
82 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="articles.html" class="btn">技术文章</a>
|
||
<a href="plugins.html" class="btn">Redkale 插件</a>
|
||
</section>
|
||
|
||
<section class="main-content">
|
||
<h3><a id="net_intro" class="anchor" href="#" aria-hidden="true"></a>Net 组件介绍</h3>
|
||
<p> Net 组件是基于AIO(NIO.2)的一套TCP/UDP的网络框架,且只提供异步接口。org.redkale.net 是所有网络协议服务的基础包。Redkale内置HTTP和远程模式Service依赖的SNCP(Service Node Communicate Protocol)协议的实现包。Redkale启动的<b><server></b>节点服务都是基于Net组件实现的协议。下面详细介绍 <a href="#net_http">HTTP服务</a> 和 <a href="#net_sncp">SNCP协议</a>。</p>
|
||
|
||
<h3><a id="net_http" class="anchor" href="#" aria-hidden="true"></a>HTTP 服务</h3>
|
||
<p> Redkale自实现的HTTP服务接口并不遵循Java EE规范JSR 340(Servlet 3.1),Redkale提倡的是HTTP+JSON的服务接口方式因此没有实现JSP规范,HTTP+JSON服务接口几乎适合所有类型的客户端(PC应用程序、PC Web、微信H5、移动APP、移动Web)开发。其与JSR 340(Servlet 3.1)的主要区别如下:<br/>
|
||
1、内置参数的JSON反序列化和响应结果的序列化接口。<br/>
|
||
2、对数值型的参数和header值提供简易接口。<br/>
|
||
3、不支持JSP,提倡的是HTTP+JSON接口方式。<br/>
|
||
4、无HttpSession对象,session可通过配置CacheSource实现。<br/>
|
||
5、内置文件上传接口,且可自实现断点续传。<br/>
|
||
6、对响应结果内容可以进行短期缓存从而减少数据源操作的压力。<br/>
|
||
7、内置WebSocket的集群与组功能,且提供伪WebSocket连接功能。<br/>
|
||
8、HttpResponse只能异步输出。<br/>
|
||
</p>
|
||
<p> 编写Redkale的HttpServlet与 JSR 340中的javax.servlet.http.HttpServlet 基本相同,只需继承 org.redkale.net.http.HttpServlet, Redkale也提供了更友好的基类 org.redkale.net.http.BasedHttpServlet, 比较好的习惯是一个项目先定义一个项目级的BaseServlet类,这样方便以后加入类似javax.servlet.Filter的功能。 <br/> <br/>
|
||
一个典型的BaseSerlvet实现:
|
||
</p>
|
||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">BaseSerlvet</span> <span class="kd">extends</span> <span class="n">org</span><span class="o">.</span><span class="na">redkale</span><span class="o">.</span><span class="na">net</span><span class="o">.</span><span class="na">http</span><span class="o">.</span><span class="na">BasedHttpServlet</span> <span class="o">{</span>
|
||
|
||
<span class="kd">protected</span> <span class="kd">final</span> <span class="n">Logger</span> <span class="n">logger</span> <span class="o">=</span> <span class="n">Logger</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">getClass</span><span class="o">().</span><span class="na">getSimpleName</span><span class="o">());</span>
|
||
|
||
<span class="kd">protected</span> <span class="kd">final</span> <span class="kt">boolean</span> <span class="n">fine</span> <span class="o">=</span> <span class="n">logger</span><span class="o">.</span><span class="na">isLoggable</span><span class="o">(</span><span class="n">Level</span><span class="o">.</span><span class="na">FINE</span><span class="o">);</span>
|
||
|
||
<span class="nd">@Resource</span> <span class="c1">//[Redkale内置资源] 进程的启动时间</span>
|
||
<span class="kd">protected</span> <span class="kt">long</span> <span class="n">serverCreateTime</span><span class="o">;</span>
|
||
|
||
<span class="nd">@Resource</span> <span class="c1">//[Redkale内置资源]</span>
|
||
<span class="kd">protected</span> <span class="n">JsonConvert</span> <span class="n">jsonConvert</span><span class="o">;</span>
|
||
|
||
<span class="nd">@Resource</span> <span class="c1">//[Redkale内置资源]</span>
|
||
<span class="kd">protected</span> <span class="n">JsonFactory</span> <span class="n">jsonFactory</span><span class="o">;</span>
|
||
|
||
<span class="c1">//[Redkale内置资源], 当前进程的根目录,字段类型可以是 String、java.io.File、java.nio.file.Path</span>
|
||
<span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"APP_HOME"</span><span class="o">)</span>
|
||
<span class="kd">protected</span> <span class="n">File</span> <span class="n">home</span><span class="o">;</span>
|
||
|
||
<span class="c1">//[Redkale内置资源], 当前Http Server的web页面的根目录,字段类型可以是 String、java.io.File、java.nio.file.Path</span>
|
||
<span class="nd">@Resource</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"SERVER_ROOT"</span><span class="o">)</span>
|
||
<span class="kd">protected</span> <span class="n">File</span> <span class="n">webroot</span><span class="o">;</span>
|
||
|
||
<span class="nd">@Resource</span>
|
||
<span class="kd">private</span> <span class="n">UserService</span> <span class="n">service</span><span class="o">;</span>
|
||
|
||
<span class="c1">//在调用authenticate之前调用, 返回false表示请求不合法</span>
|
||
<span class="c1">//该方法可以用于判断请求源是否合法或加入一些全局的拦截操作</span>
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">preExecute</span><span class="o">(</span><span class="kd">final</span> <span class="n">HttpRequest</span> <span class="n">request</span><span class="o">,</span> <span class="kd">final</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="k">if</span> <span class="o">(!</span><span class="n">request</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="s">""</span><span class="o">).</span><span class="na">contains</span><span class="o">(</span><span class="s">"Redkale-Agent"</span><span class="o">))</span> <span class="o">{</span> <span class="c1">//只用移动APP的接口可以判断User-Agent是否正确</span>
|
||
<span class="n">response</span><span class="o">.</span><span class="na">addHeader</span><span class="o">(</span><span class="s">"retcode"</span><span class="o">,</span> <span class="s">"10001"</span><span class="o">);</span>
|
||
<span class="n">response</span><span class="o">.</span><span class="na">addHeader</span><span class="o">(</span><span class="s">"retmessage"</span><span class="o">,</span> <span class="s">"User-Agent error"</span><span class="o">);</span>
|
||
<span class="n">response</span><span class="o">.</span><span class="na">finish</span><span class="o">(</span><span class="mi">201</span><span class="o">,</span> <span class="s">"{'success':false, 'message':'User-Agent error, must be Redkale-Agent'}"</span><span class="o">);</span>
|
||
<span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
|
||
<span class="o">}</span>
|
||
<span class="c1">//可以加上一些统计操作</span>
|
||
<span class="k">if</span> <span class="o">(</span><span class="n">fine</span><span class="o">)</span> <span class="n">response</span><span class="o">.</span><span class="na">setRecycleListener</span><span class="o">((</span><span class="n">req</span><span class="o">,</span> <span class="n">resp</span><span class="o">)</span> <span class="o">-></span> <span class="o">{</span> <span class="c1">//记录处理时间太长的请求操作</span>
|
||
<span class="kt">long</span> <span class="n">e</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="o">-</span> <span class="n">request</span><span class="o">.</span><span class="na">getCreatetime</span><span class="o">();</span>
|
||
<span class="k">if</span> <span class="o">(</span><span class="n">e</span> <span class="o">></span> <span class="mi">500</span><span class="o">)</span> <span class="n">logger</span><span class="o">.</span><span class="na">fine</span><span class="o">(</span><span class="s">"耗时居然用了 "</span> <span class="o">+</span> <span class="n">e</span> <span class="o">+</span> <span class="s">" 毫秒. 请求为: "</span> <span class="o">+</span> <span class="n">req</span><span class="o">);</span>
|
||
<span class="o">});</span>
|
||
<span class="k">return</span> <span class="kc">true</span><span class="o">;</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="c1">//标记为@AuthIgnore 的方法将不会调用authenticate方法</span>
|
||
<span class="c1">//一般用于判断用户的登录态, 返回false表示鉴权失败</span>
|
||
<span class="c1">//moduleid值来自 @WebServlet.moduleid()用于定义模块ID; actionid值自来@WebAction.actionid()用于定义操作ID; 需要系统化的鉴权需要定义这两个值</span>
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">authenticate</span><span class="o">(</span><span class="kt">int</span> <span class="n">moduleid</span><span class="o">,</span> <span class="kt">int</span> <span class="n">actionid</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">user</span> <span class="o">=</span> <span class="o">(</span><span class="n">UserInfo</span><span class="o">)</span> <span class="n">request</span><span class="o">.</span><span class="na">getAttribute</span><span class="o">(</span><span class="s">"_current_userinfo"</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="k">return</span> <span class="kc">true</span><span class="o">;</span> <span class="c1">//已经判断过了</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="k">return</span> <span class="kc">false</span><span class="o">;</span> <span class="c1">//没有sessionid表示没有登录</span>
|
||
<span class="n">user</span> <span class="o">=</span> <span class="n">service</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="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">request</span><span class="o">.</span><span class="na">setAttribute</span><span class="o">(</span><span class="s">"_current_userinfo"</span><span class="o">,</span> <span class="n">user</span><span class="o">);</span>
|
||
<span class="k">return</span> <span class="n">user</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">;</span> <span class="c1">//存在用户表示登录态正常</span>
|
||
<span class="o">}</span>
|
||
<span class="o">}</span></pre></div>
|
||
|
||
<p> 继承BasedHttpServlet的子类可以使用其自带的鉴权、请求分支、缓存等功能, 一个典型的操作用户HttpServlet: </p>
|
||
<div class="highlight"><pre><span class="nd">@WebServlet</span><span class="o">({</span><span class="s">"/user/*"</span><span class="o">})</span> <span class="c1">//拦截所有 /user/ 开头的请求</span>
|
||
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserServlet</span> <span class="kd">extends</span> <span class="n">BaseSerlvet</span> <span class="o">{</span>
|
||
|
||
<span class="nd">@Resource</span>
|
||
<span class="kd">private</span> <span class="n">UserService</span> <span class="n">service</span><span class="o">;</span>
|
||
|
||
<span class="c1">//登录操作 </span>
|
||
<span class="nd">@AuthIgnore</span> <span class="c1">//登录操作不要判断登录态,所以需要标记为@AuthIgnore,不会调用 BaseSerlvet.authenticate 方法</span>
|
||
<span class="c1">//因为WebAction的判断规则用的是String.startsWith,所以WebAction.url不能用正则表达式,只能是getRequestURI的前缀</span>
|
||
<span class="c1">//且同一个HttpServlet类内的所有WebAction不能存在包含关系, 如 /user/myinfo 和 /user/myinforecord 不能存在同一HttpServlet中。</span>
|
||
<span class="nd">@WebAction</span><span class="o">(</span><span class="n">url</span> <span class="o">=</span> <span class="s">"/user/login"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">login</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">LoginBean</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">LoginBean</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="c1">//获取参数</span>
|
||
<span class="n">RetResult</span><span class="o"><</span><span class="n">UserInfo</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">login</span><span class="o">(</span><span class="n">bean</span><span class="o">);</span> <span class="c1">//登录操作, service内部判断bean的合法性</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="c1">//输出结果</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="c1">//获取当前用户信息</span>
|
||
<span class="c1">//未登录的请求会被BaseSerlvet.authenticate方法拦截,因此能进入该方法说明用户态存在</span>
|
||
<span class="nd">@WebAction</span><span class="o">(</span><span class="n">url</span> <span class="o">=</span> <span class="s">"/user/myinfo"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">myinfo</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">UserInfo</span> <span class="n">user</span> <span class="o">=</span> <span class="n">service</span><span class="o">.</span><span class="na">current</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="c1">//或者使用 user = req.getAttribute("_current_userinfo"); 因为BaseSerlvet.authenticate方法已经将UserInfo注入到_current_userinfo属性中</span>
|
||
<span class="n">resp</span><span class="o">.</span><span class="na">finishJson</span><span class="o">(</span><span class="n">user</span><span class="o">);</span> <span class="c1">//输出用户信息</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="c1">//获取指定用户ID的用户信息, 请求如: /user/username/43565443</span>
|
||
<span class="nd">@AuthIgnore</span>
|
||
<span class="c1">// 默认缓存时间是15秒,BasedHttpServlet会将每个进入该方法的请求的响应结果缓存15秒,缓存命中时不会再进入该方法,过期会清空。</span>
|
||
<span class="c1">// @HttpCacheable 必须配合 @AuthIgnore 使用, 因为跟当前用户有关的请求一般不适合所有用户请求。 </span>
|
||
<span class="c1">// 翻页查询想缓存就需要将翻页信息带进url: /user/query/page:2/size:50 。</span>
|
||
<span class="nd">@HttpCacheable</span><span class="o">(</span><span class="n">timeout</span> <span class="o">=</span> <span class="mi">30</span><span class="o">)</span> <span class="c1">//有效期30秒</span>
|
||
<span class="nd">@WebAction</span><span class="o">(</span><span class="n">url</span> <span class="o">=</span> <span class="s">"/user/userinfo/"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">userinfo</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">UserInfo</span> <span class="n">user</span> <span class="o">=</span> <span class="n">service</span><span class="o">.</span><span class="na">findUserInfo</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">user</span><span class="o">);</span> <span class="c1">//输出用户信息</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="c1">//更新个人头像</span>
|
||
<span class="nd">@WebAction</span><span class="o">(</span><span class="n">url</span> <span class="o">=</span> <span class="s">"/user/updateface"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">updateface</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">UserInfo</span> <span class="n">user</span> <span class="o">=</span> <span class="n">service</span><span class="o">.</span><span class="na">current</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="k">for</span> <span class="o">(</span><span class="n">MultiPart</span> <span class="n">part</span> <span class="o">:</span> <span class="n">req</span><span class="o">.</span><span class="na">multiParts</span><span class="o">())</span> <span class="o">{</span> <span class="c1">//遍历上传文件列表 </span>
|
||
<span class="kt">byte</span><span class="o">[]</span> <span class="n">byts</span> <span class="o">=</span> <span class="n">part</span><span class="o">.</span><span class="na">getContentBytes</span><span class="o">(</span><span class="mi">5</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024L</span><span class="o">);</span> <span class="c1">//图片大小不能超过5M,超过5M返回null</span>
|
||
<span class="k">if</span> <span class="o">(</span><span class="n">byts</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</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="k">new</span> <span class="nf">RetResult</span><span class="o">(</span><span class="mi">102</span><span class="o">,</span> <span class="s">"上传的文件过大"</span><span class="o">));</span>
|
||
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
|
||
<span class="n">BufferedImage</span> <span class="n">img</span> <span class="o">=</span> <span class="n">ImageIO</span><span class="o">.</span><span class="na">read</span><span class="o">(</span><span class="k">new</span> <span class="nf">ByteArrayInputStream</span><span class="o">(</span><span class="n">byts</span><span class="o">));</span>
|
||
<span class="c1">//... 此处处理并存储头像图片</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="c1">//输出成功信息</span>
|
||
<span class="o">}</span>
|
||
<span class="k">return</span><span class="o">;</span> <span class="c1">//头像图片仅会传一个, 只需要读取一个即可返回</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="k">new</span> <span class="nf">RetResult</span><span class="o">(</span><span class="mi">103</span><span class="o">,</span> <span class="s">"没有上传图片"</span><span class="o">));</span>
|
||
<span class="o">}</span>
|
||
<span class="o">}</span></pre></div>
|
||
<p> 如上,所有/user/前缀的请求都会进入UserServlet,若没匹配的则返回505错误,为了方便以后编写前方静动分离服务器转发规则,比较好的习惯是将项目中所有动态Servlet加一个固定前缀,在 <a href="redkale.html#redkale_confxml" target="_blank">application.xml</a> 里设置path即可。</p>
|
||
<div class="highlight"><pre><span class="nt"><server</span> <span class="na">protocol=</span><span class="s">"HTTP"</span> <span class="na">port=</span><span class="s">"6060"</span> <span class="na">root=</span><span class="s">"root"</span><span class="nt">></span>
|
||
<span class="nt"><services</span> <span class="na">autoload=</span><span class="s">"true"</span> <span class="nt">/></span>
|
||
<span class="nt"><servlets</span> <b><span class="na">path=</span><span class="s">"/pipes"</span></b> <span class="na">autoload=</span><span class="s">"true"</span><span class="nt">/></span>
|
||
<span class="nt"></server></span></pre></div>
|
||
<p> 如上, 配置了/pipes 前缀后,客户端发送Servlet请求需带上前缀,请求当前用户信息的url就变成:/pipes/user/myinfo 。</p>
|
||
<br/>
|
||
|
||
<p id="net_ws"> <b> WebSokcet 服务</b> </p>
|
||
<p> WebSokcet协议遵循<a href="http://tools.ietf.org/html/rfc645" target="_blank">IETF RFC 6455</a>,其接口并不符合Java EE中的WebSocket的接口规范。<br/>
|
||
一个WebSocket连接对应一个WebSocket实体,即一个WebSocket会绑定一个TCP连接。且有两种模式:<br/>
|
||
1) 普通模式: 协议上符合HTML5规范, 其流程顺序如下:<br/>
|
||
1.1 onOpen 若返回null,视为WebSocket的连接不合法,强制关闭WebSocket连接;通常用于判断登录态。<br/>
|
||
1.2 createGroupid 若返回null,视为WebSocket的连接不合法,强制关闭WebSocket连接;通常用于判断用户权限是否符合。<br/>
|
||
1.3 onConnected WebSocket成功连接后在准备接收数据前回调此方法。<br/>
|
||
1.4 onMessage/onFragment+ WebSocket接收到消息后回调此消息类方法。<br/>
|
||
1.5 onClose WebSocket被关闭后回调此方法。<br/>
|
||
此模式下 以上方法都应该被重载。<br/>
|
||
<br/>
|
||
2) 原始二进制模式: 此模式有别于HTML5规范,可以视为原始的TCP连接。通常用于音频视频通讯场景。其流程顺序如下:<br/>
|
||
2.1 onOpen 如果方法返回null,视为WebSocket的连接不合法,强制关闭WebSocket连接;通常用于判断登录态。<br/>
|
||
2.2 createGroupid 若返回null,视为WebSocket的连接不合法,强制关闭WebSocket连接;通常用于判断用户权限是否符合。<br/>
|
||
2.3 onRead WebSocket成功连接后回调此方法, 由此方法处理原始的TCP连接, 同时业务代码去控制WebSocket的关闭。<br/>
|
||
此模式下 以上方法都应该被重载。<br/>
|
||
</p>
|
||
<p> 实现一个WebSocket服务需要继承 org.redkale.net.http.WebSocketServlet,以下是一个简单的聊天范例:</p>
|
||
<div class="highlight"><pre><span class="nd">@WebServlet</span><span class="o">(</span><span class="s">"/ws/chat"</span><span class="o">)</span>
|
||
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ChatWebSocketServlet</span> <span class="kd">extends</span> <span class="n">WebSocketServlet</span> <span class="o">{</span>
|
||
|
||
<span class="nd">@Resource</span> <span class="c1">//[Redkale内置资源]</span>
|
||
<span class="kd">protected</span> <span class="n">JsonConvert</span> <span class="n">jsonConvert</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">init</span><span class="o">(</span><span class="n">HttpContext</span> <span class="n">context</span><span class="o">,</span> <span class="n">AnyValue</span> <span class="n">conf</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"本实例的WebSocketEngine: "</span> <span class="o">+</span> <span class="kd">super</span><span class="o">.</span><span class="na">engine</span><span class="o">);</span>
|
||
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"本实例的WebSocketNode: "</span> <span class="o">+</span> <span class="kd">super</span><span class="o">.</span><span class="na">node</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">destroy</span><span class="o">(</span><span class="n">HttpContext</span> <span class="n">context</span><span class="o">,</span> <span class="n">AnyValue</span> <span class="n">conf</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="n">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"关闭了ChatWebSocketServlet"</span><span class="o">);</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">protected</span> <span class="n">WebSocket</span> <span class="nf">createWebSocket</span><span class="o">()</span> <span class="o">{</span>
|
||
|
||
<span class="k">return</span> <span class="k">new</span> <span class="nf">WebSocket</span><span class="o">()</span> <span class="o">{</span>
|
||
|
||
<span class="kd">private</span> <span class="n">UserInfo</span> <span class="n">user</span><span class="o">;</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onMessage</span><span class="o">(</span><span class="n">String</span> <span class="n">text</span><span class="o">)</span> <span class="o">{</span> <span class="c1">// text 接收的格式: {"receiveid":200000001, "content":"Hi Redkale!"}</span>
|
||
<span class="kd">final</span> <span class="n">ChatMessage</span> <span class="n">message</span> <span class="o">=</span> <span class="n">jsonConvert</span><span class="o">.</span><span class="na">convertFrom</span><span class="o">(</span><span class="n">ChatMessage</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">text</span><span class="o">);</span> <span class="c1">//获取给对方的消息体信息</span>
|
||
<span class="n">message</span><span class="o">.</span><span class="na">sendid</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="c1">//将当前用户设为消息的发送方</span>
|
||
<span class="n">message</span><span class="o">.</span><span class="na">sendtime</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="c1">//给接收方发送消息, 即使接收方在其他WebSocket进程节点上有链接,Redkale也会自动发送到其他链接进程节点上。</span>
|
||
<span class="kd">super</span><span class="o">.</span><span class="na">sendEachMessage</span><span class="o">(</span><span class="n">message</span><span class="o">.</span><span class="na">receiveid</span><span class="o">,</span> <span class="n">jsonConvert</span><span class="o">.</span><span class="na">convertTo</span><span class="o">(</span><span class="n">message</span><span class="o">));</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">protected</span> <span class="n">Serializable</span> <span class="nf">createGroupid</span><span class="o">()</span> <span class="o">{</span> <span class="c1">//以用户ID作为WebSocketGroup的groupid</span>
|
||
<span class="k">this</span><span class="o">.</span><span class="na">user</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">String</span><span class="o">.</span><span class="na">valueOf</span><span class="o">(</span><span class="kd">super</span><span class="o">.</span><span class="na">getSessionid</span><span class="o">()));</span>
|
||
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">user</span> <span class="o">==</span> <span class="kc">null</span> <span class="o">?</span> <span class="kc">null</span> <span class="o">:</span> <span class="k">this</span><span class="o">.</span><span class="na">user</span><span class="o">.</span><span class="na">getUserid</span><span class="o">();</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="nd">@Override</span>
|
||
<span class="kd">public</span> <span class="n">Serializable</span> <span class="nf">onOpen</span><span class="o">(</span><span class="n">HttpRequest</span> <span class="n">request</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="k">return</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="c1">//以request中的sessionid字符串作为WebSocket的sessionid</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="o">};</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">ChatMessage</span> <span class="o">{</span>
|
||
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="n">sendid</span><span class="o">;</span> <span class="c1">//发送方用户ID</span>
|
||
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="n">receiveid</span><span class="o">;</span> <span class="c1">//接收方用户ID </span>
|
||
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="n">content</span><span class="o">;</span> <span class="c1">//文本消息内容</span>
|
||
|
||
<span class="kd">public</span> <span class="kt">long</span> <span class="n">sendtime</span><span class="o">;</span> <span class="c1">//消息发送时间</span>
|
||
<span class="o">}</span>
|
||
<span class="o">}</span></pre></div>
|
||
|
||
<p id="net_httprequest"> <b>. HttpRequest 对象</b> </p>
|
||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">HttpRequest</span> <span class="o">{</span>
|
||
|
||
<span class="c1">//获取请求方法 GET、POST等</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getMethod</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取协议名 http、https、ws、wss等</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getProtocol</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取Host的Header值</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getHost</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取请求内容的长度, 为-1表示内容长度不确定</span>
|
||
<span class="kd">public</span> <span class="kt">long</span> <span class="nf">getContentLength</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取Content-Type的header值</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getContentType</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取Connection的Header值</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getConnection</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取客户端地址IP</span>
|
||
<span class="kd">public</span> <span class="n">SocketAddress</span> <span class="nf">getRemoteAddress</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取客户端地址IP, 与getRemoteAddres() 的区别在于:本方法优先取header中指定为RemoteAddress名的值,没有则返回getRemoteAddres()。</span>
|
||
<span class="c1">//本方法适用于服务前端有如nginx的代理服务器进行中转,通过getRemoteAddres()是获取不到客户端的真实IP。</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getRemoteAddr</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取请求内容指定的编码字符串</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getBody</span><span class="o">(</span><span class="n">Charset</span> <span class="n">charset</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取请求内容的UTF-8编码字符串</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getBodyUTF8</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取文件上传对象</span>
|
||
<span class="kd">public</span> <span class="n">MultiContext</span> <span class="nf">getMultiContext</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取文件上传信息列表 等价于 getMultiContext().parts();</span>
|
||
<span class="kd">public</span> <span class="n">Iterable</span><span class="o"><</span><span class="n">MultiPart</span><span class="o">></span> <span class="nf">multiParts</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">IOException</span><span class="o">;</span>
|
||
|
||
<span class="c1">//获取sessionid</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getSessionid</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">autoCreate</span><span class="o">);</span>
|
||
|
||
<span class="c1">//更新sessionid</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">changeSessionid</span><span class="o">();</span>
|
||
|
||
<span class="c1">//使sessionid失效</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">invalidateSession</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取所有Cookie对象</span>
|
||
<span class="kd">public</span> <span class="n">java</span><span class="o">.</span><span class="na">net</span><span class="o">.</span><span class="na">HttpCookie</span><span class="o">[]</span> <span class="nf">getCookies</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取Cookie值, 没有返回默认值</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getCookie</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="n">String</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取Cookie值</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getCookie</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取请求的URL</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getRequestURI</span><span class="o">();</span>
|
||
|
||
<span class="c1">//截取getRequestURI最后的一个/后面的部分</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getRequstURILastPath</span><span class="o">();</span>
|
||
|
||
<span class="c1">//从prefix之后截取getRequestURI再对"/"进行分隔</span>
|
||
<span class="kd">public</span> <span class="n">String</span><span class="o">[]</span> <span class="nf">getRequstURIPaths</span><span class="o">(</span><span class="n">String</span> <span class="n">prefix</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取请求URL分段中含prefix段的long值</span>
|
||
<span class="c1">// 例如请求URL /pipes/record/query/time:1453104341363/id:40</span>
|
||
<span class="c1">// 获取time参数: long time = request.getRequstURIPath("time:", 0L);</span>
|
||
<span class="kd">public</span> <span class="kt">long</span> <span class="nf">getRequstURIPath</span><span class="o">(</span><span class="n">String</span> <span class="n">prefix</span><span class="o">,</span> <span class="kt">long</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取请求URL分段中含prefix段的int值</span>
|
||
<span class="c1">// 例如请求URL /pipes/record/query/page:2/size:50</span>
|
||
<span class="c1">// 获取page参数: int page = request.getRequstURIPath("page:", 1);</span>
|
||
<span class="c1">// 获取size参数: int size = request.getRequstURIPath("size:", 20);</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">getRequstURIPath</span><span class="o">(</span><span class="n">String</span> <span class="n">prefix</span><span class="o">,</span> <span class="kt">int</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取请求URL分段中含prefix段的值</span>
|
||
<span class="c1">//例如请求URL /pipes/record/query/name:hello</span>
|
||
<span class="c1">//获取name参数: String name = request.getRequstURIPath("name:", "none");</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getRequstURIPath</span><span class="o">(</span><span class="n">String</span> <span class="n">prefix</span><span class="o">,</span> <span class="n">String</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">// 获取请求URL分段中含prefix段的short值</span>
|
||
<span class="c1">// 例如请求URL /pipes/record/query/type:10</span>
|
||
<span class="c1">// 获取type参数: short type = request.getRequstURIPath("type:", (short)0);</span>
|
||
<span class="kd">public</span> <span class="kt">short</span> <span class="nf">getRequstURIPath</span><span class="o">(</span><span class="n">String</span> <span class="n">prefix</span><span class="o">,</span> <span class="kt">short</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取所有的header名</span>
|
||
<span class="kd">public</span> <span class="n">String</span><span class="o">[]</span> <span class="nf">getHeaderNames</span><span class="o">();</span>
|
||
|
||
<span class="c1">// 获取指定的header值</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getHeader</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取指定的header值, 没有返回默认值</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getHeader</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="n">String</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取指定的header的json值</span>
|
||
<span class="kd">public</span> <span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="n">T</span> <span class="nf">getJsonHeader</span><span class="o">(</span><span class="n">JsonConvert</span> <span class="n">convert</span><span class="o">,</span> <span class="n">Class</span><span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="n">clazz</span><span class="o">,</span> <span class="n">String</span> <span class="n">name</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取指定的header的json值</span>
|
||
<span class="kd">public</span> <span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="n">T</span> <span class="nf">getJsonHeader</span><span class="o">(</span><span class="n">Class</span><span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="n">clazz</span><span class="o">,</span> <span class="n">String</span> <span class="n">name</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取指定的header的boolean值, 没有返回默认boolean值</span>
|
||
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">getBooleanHeader</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">// 获取指定的header的short值, 没有返回默认short值</span>
|
||
<span class="kd">public</span> <span class="kt">short</span> <span class="nf">getShortHeader</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">short</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取指定的header的int值, 没有返回默认int值</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">getIntHeader</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">int</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">// 获取指定的header的float值, 没有返回默认float值</span>
|
||
<span class="kd">public</span> <span class="kt">float</span> <span class="nf">getFloatHeader</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">float</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">// 获取指定的header的long值, 没有返回默认long值</span>
|
||
<span class="kd">public</span> <span class="kt">long</span> <span class="nf">getLongHeader</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">long</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取指定的header的double值, 没有返回默认double值</span>
|
||
<span class="kd">public</span> <span class="kt">double</span> <span class="nf">getDoubleHeader</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">double</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取所有参数名</span>
|
||
<span class="kd">public</span> <span class="n">String</span><span class="o">[]</span> <span class="nf">getParameterNames</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取指定的参数值</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getParameter</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取指定的参数值, 没有返回默认值</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getParameter</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="n">String</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取指定的参数json值</span>
|
||
<span class="kd">public</span> <span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="n">T</span> <span class="nf">getJsonParameter</span><span class="o">(</span><span class="n">JsonConvert</span> <span class="n">convert</span><span class="o">,</span> <span class="n">Class</span><span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="n">clazz</span><span class="o">,</span> <span class="n">String</span> <span class="n">name</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取指定的参数json值</span>
|
||
<span class="kd">public</span> <span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="n">T</span> <span class="nf">getJsonParameter</span><span class="o">(</span><span class="n">Class</span><span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="n">clazz</span><span class="o">,</span> <span class="n">String</span> <span class="n">name</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取指定的参数boolean值, 没有返回默认boolean值</span>
|
||
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">getBooleanParameter</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取指定的参数short值, 没有返回默认short值</span>
|
||
<span class="kd">public</span> <span class="kt">short</span> <span class="nf">getShortParameter</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">short</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取指定的参数int值, 没有返回默认int值</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">getIntParameter</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">int</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取指定的参数float值, 没有返回默认float值</span>
|
||
<span class="kd">public</span> <span class="kt">float</span> <span class="nf">getFloatParameter</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">float</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取指定的参数long值, 没有返回默认long值</span>
|
||
<span class="kd">public</span> <span class="kt">long</span> <span class="nf">getLongParameter</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">long</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取指定的参数double值, 没有返回默认double值</span>
|
||
<span class="kd">public</span> <span class="kt">double</span> <span class="nf">getDoubleParameter</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="kt">double</span> <span class="n">defaultValue</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取HTTP上下文对象</span>
|
||
<span class="kd">public</span> <span class="n">HttpContext</span> <span class="nf">getContext</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取所有属性值, servlet执行完后会被清空</span>
|
||
<span class="kd">public</span> <span class="n">Map</span><span class="o"><</span><span class="n">String</span><span class="o">,</span> <span class="n">Object</span><span class="o">></span> <span class="nf">getAttributes</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取指定属性值</span>
|
||
<span class="kd">public</span> <span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="n">T</span> <span class="nf">getAttribute</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">);</span>
|
||
|
||
<span class="c1">//删除指定属性</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">removeAttribute</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">);</span>
|
||
|
||
<span class="c1">//设置属性值</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setAttribute</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="n">Object</span> <span class="n">value</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取request创建时间</span>
|
||
<span class="kd">public</span> <span class="kt">long</span> <span class="nf">getCreatetime</span><span class="o">();</span>
|
||
<span class="o">}</span></pre></div>
|
||
|
||
|
||
<p id="net_httpresponse"> <b>. HttpResponse 对象</b> </p>
|
||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">HttpResponse</span> <span class="o">{</span>
|
||
|
||
<span class="c1">//设置状态码</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setStatus</span><span class="o">(</span><span class="kt">int</span> <span class="n">status</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取状态码</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">getStatus</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取 ContentType</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getContentType</span><span class="o">();</span>
|
||
|
||
<span class="c1">//设置 ContentType</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setContentType</span><span class="o">(</span><span class="n">String</span> <span class="n">contentType</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取内容长度</span>
|
||
<span class="kd">public</span> <span class="kt">long</span> <span class="nf">getContentLength</span><span class="o">();</span>
|
||
|
||
<span class="c1">//设置内容长度</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setContentLength</span><span class="o">(</span><span class="kt">long</span> <span class="n">contentLength</span><span class="o">);</span>
|
||
|
||
<span class="c1">//设置Header值</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setHeader</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="n">Object</span> <span class="n">value</span><span class="o">);</span>
|
||
|
||
<span class="c1">//添加Header值</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">addHeader</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="n">Object</span> <span class="n">value</span><span class="o">);</span>
|
||
|
||
<span class="c1">//跳过header的输出</span>
|
||
<span class="c1">//通常应用场景是,调用者的输出内容里已经包含了HTTP的响应头信息,因此需要调用此方法避免重复输出HTTP响应头信息。</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">skipHeader</span><span class="o">();</span>
|
||
|
||
<span class="c1">//增加Cookie值</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">addCookie</span><span class="o">(</span><span class="n">HttpCookie</span><span class="o">...</span> <span class="n">cookies</span><span class="o">);</span>
|
||
|
||
<span class="c1">//异步输出指定内容</span>
|
||
<span class="kd">public</span> <span class="o"><</span><span class="n">A</span><span class="o">></span> <span class="kt">void</span> <span class="nf">sendBody</span><span class="o">(</span><span class="n">ByteBuffer</span> <span class="n">buffer</span><span class="o">,</span> <span class="n">A</span> <span class="n">attachment</span><span class="o">,</span> <span class="n">CompletionHandler</span><span class="o"><</span><span class="n">Integer</span><span class="o">,</span> <span class="n">A</span><span class="o">></span> <span class="n">handler</span><span class="o">);</span>
|
||
|
||
<span class="c1">//关闭HTTP连接,如果是keep-alive则不强制关闭</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finish</span><span class="o">();</span>
|
||
|
||
<span class="c1">//强制关闭HTTP连接</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finish</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">kill</span><span class="o">);</span>
|
||
|
||
<span class="c1">//将对象以JSON格式输出</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finishJson</span><span class="o">(</span><span class="n">Object</span> <span class="n">obj</span><span class="o">);</span>
|
||
|
||
<span class="c1">//将对象以JSON格式输出</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finishJson</span><span class="o">(</span><span class="n">JsonConvert</span> <span class="n">convert</span><span class="o">,</span> <span class="n">Object</span> <span class="n">obj</span><span class="o">);</span>
|
||
|
||
<span class="c1">//将对象以JSON格式输出</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finishJson</span><span class="o">(</span><span class="n">Type</span> <span class="n">type</span><span class="o">,</span> <span class="n">Object</span> <span class="n">obj</span><span class="o">);</span>
|
||
|
||
<span class="c1">//将对象以JSON格式输出</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finishJson</span><span class="o">(</span><span class="kd">final</span> <span class="n">JsonConvert</span> <span class="n">convert</span><span class="o">,</span> <span class="kd">final</span> <span class="n">Type</span> <span class="n">type</span><span class="o">,</span> <span class="kd">final</span> <span class="n">Object</span> <span class="n">obj</span><span class="o">);</span>
|
||
|
||
<span class="c1">//将对象以JSON格式输出</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finishJson</span><span class="o">(</span><span class="kd">final</span> <span class="n">Object</span><span class="o">...</span> <span class="n">objs</span><span class="o">);</span>
|
||
|
||
<span class="c1">//将指定字符串以响应结果输出</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finish</span><span class="o">(</span><span class="n">String</span> <span class="n">obj</span><span class="o">);</span>
|
||
|
||
<span class="c1">//以指定响应码附带内容输出, message 可以为null</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finish</span><span class="o">(</span><span class="kt">int</span> <span class="n">status</span><span class="o">,</span> <span class="n">String</span> <span class="n">message</span><span class="o">);</span>
|
||
|
||
<span class="c1">//以304状态码输出</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finish304</span><span class="o">();</span>
|
||
|
||
<span class="c1">//以404状态码输出</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finish404</span><span class="o">();</span>
|
||
|
||
<span class="c1">//将指定ByteBuffer按响应结果输出</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finish</span><span class="o">(</span><span class="n">ByteBuffer</span> <span class="n">buffer</span><span class="o">);</span>
|
||
|
||
<span class="c1">//将指定ByteBuffer按响应结果输出</span>
|
||
<span class="c1">//kill 输出后是否强制关闭连接</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finish</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">kill</span><span class="o">,</span> <span class="n">ByteBuffer</span> <span class="n">buffer</span><span class="o">);</span>
|
||
|
||
<span class="c1">//将指定ByteBuffer数组按响应结果输出</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finish</span><span class="o">(</span><span class="n">ByteBuffer</span><span class="o">...</span> <span class="n">buffers</span><span class="o">);</span>
|
||
|
||
<span class="c1">//将指定ByteBuffer数组按响应结果输出</span>
|
||
<span class="c1">//kill 输出后是否强制关闭连接</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finish</span><span class="o">(</span><span class="kt">boolean</span> <span class="n">kill</span><span class="o">,</span> <span class="n">ByteBuffer</span><span class="o">...</span> <span class="n">buffers</span><span class="o">);</span>
|
||
|
||
<span class="c1">//将指定文件按响应结果输出</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">finish</span><span class="o">(</span><span class="n">File</span> <span class="n">file</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">IOException</span><span class="o">;</span>
|
||
<span class="o">}</span></pre></div>
|
||
|
||
|
||
<p id="net_websocket"> <b>. WebSocket 对象</b> </p>
|
||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">abstract</span> <span class="kd">class</span> <span class="nc">WebSocket</span> <span class="o">{</span>
|
||
|
||
<span class="c1">//发送消息体, 包含二进制/文本 返回结果0表示成功,非0表示错误码</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">send</span><span class="o">(</span><span class="n">WebSocketPacket</span> <span class="n">packet</span><span class="o">);</span>
|
||
|
||
<span class="c1">//发送单一的文本消息 返回结果0表示成功,非0表示错误码</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">send</span><span class="o">(</span><span class="n">String</span> <span class="n">text</span><span class="o">);</span>
|
||
|
||
<span class="c1">//发送文本消息 返回结果0表示成功,非0表示错误码</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">send</span><span class="o">(</span><span class="n">String</span> <span class="n">text</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">last</span><span class="o">);</span>
|
||
|
||
<span class="c1">//发送单一的二进制消息 返回结果0表示成功,非0表示错误码</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">send</span><span class="o">(</span><span class="kt">byte</span><span class="o">[]</span> <span class="n">data</span><span class="o">);</span>
|
||
|
||
<span class="c1">//发送单一的二进制消息 返回结果0表示成功,非0表示错误码</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">send</span><span class="o">(</span><span class="kt">byte</span><span class="o">[]</span> <span class="n">data</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">last</span><span class="o">);</span>
|
||
|
||
<span class="c1">//发送消息, 消息类型是String或byte[] 返回结果0表示成功,非0表示错误码</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">send</span><span class="o">(</span><span class="n">Serializable</span> <span class="n">message</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">last</span><span class="o">);</span>
|
||
|
||
<span class="c1">//给指定groupid的WebSocketGroup下所有WebSocket节点发送文本消息</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">sendEachMessage</span><span class="o">(</span><span class="n">Serializable</span> <span class="n">groupid</span><span class="o">,</span> <span class="n">String</span> <span class="n">text</span><span class="o">);</span>
|
||
|
||
<span class="c1">//给指定groupid的WebSocketGroup下所有WebSocket节点发送文本消息</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">sendEachMessage</span><span class="o">(</span><span class="n">Serializable</span> <span class="n">groupid</span><span class="o">,</span> <span class="n">String</span> <span class="n">text</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">last</span><span class="o">);</span>
|
||
|
||
<span class="c1">//给指定groupid的WebSocketGroup下所有WebSocket节点发送二进制消息</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">sendEachMessage</span><span class="o">(</span><span class="n">Serializable</span> <span class="n">groupid</span><span class="o">,</span> <span class="kt">byte</span><span class="o">[]</span> <span class="n">data</span><span class="o">);</span>
|
||
|
||
<span class="c1">//给指定groupid的WebSocketGroup下所有WebSocket节点发送二进制消息</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">sendEachMessage</span><span class="o">(</span><span class="n">Serializable</span> <span class="n">groupid</span><span class="o">,</span> <span class="kt">byte</span><span class="o">[]</span> <span class="n">data</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">last</span><span class="o">);</span>
|
||
|
||
<span class="c1">//给指定groupid的WebSocketGroup下最近接入的WebSocket节点发送文本消息</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">sendRecentMessage</span><span class="o">(</span><span class="n">Serializable</span> <span class="n">groupid</span><span class="o">,</span> <span class="n">String</span> <span class="n">text</span><span class="o">);</span>
|
||
|
||
<span class="c1">//给指定groupid的WebSocketGroup下最近接入的WebSocket节点发送文本消息</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">sendRecentMessage</span><span class="o">(</span><span class="n">Serializable</span> <span class="n">groupid</span><span class="o">,</span> <span class="n">String</span> <span class="n">text</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">last</span><span class="o">);</span>
|
||
|
||
<span class="c1">//给指定groupid的WebSocketGroup下最近接入的WebSocket节点发送二进制消息</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">sendRecentMessage</span><span class="o">(</span><span class="n">Serializable</span> <span class="n">groupid</span><span class="o">,</span> <span class="kt">byte</span><span class="o">[]</span> <span class="n">data</span><span class="o">);</span>
|
||
|
||
<span class="c1">//给指定groupid的WebSocketGroup下最近接入的WebSocket节点发送二进制消息</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">sendRecentMessage</span><span class="o">(</span><span class="n">Serializable</span> <span class="n">groupid</span><span class="o">,</span> <span class="kt">byte</span><span class="o">[]</span> <span class="n">data</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">last</span><span class="o">);</span>
|
||
|
||
<span class="c1">//发送PING消息 返回结果0表示成功,非0表示错误码</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">sendPing</span><span class="o">();</span>
|
||
|
||
<span class="c1">//发送PING消息,附带其他信息 返回结果0表示成功,非0表示错误码</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">sendPing</span><span class="o">(</span><span class="kt">byte</span><span class="o">[]</span> <span class="n">data</span><span class="o">);</span>
|
||
|
||
<span class="c1">//发送PONG消息,附带其他信息 返回结果0表示成功,非0表示错误码</span>
|
||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">sendPong</span><span class="o">(</span><span class="kt">byte</span><span class="o">[]</span> <span class="n">data</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取当前WebSocket下的属性</span>
|
||
<span class="kd">public</span> <span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="n">T</span> <span class="nf">getAttribute</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">);</span>
|
||
|
||
<span class="c1">//移出当前WebSocket下的属性</span>
|
||
<span class="kd">public</span> <span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="n">T</span> <span class="nf">removeAttribute</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">);</span>
|
||
|
||
<span class="c1">//给当前WebSocket下的增加属性</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setAttribute</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">,</span> <span class="n">Object</span> <span class="n">value</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取当前WebSocket所属的groupid</span>
|
||
<span class="kd">public</span> <span class="n">Serializable</span> <span class="nf">getGroupid</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取当前WebSocket的会话ID, 不会为null</span>
|
||
<span class="kd">public</span> <span class="n">Serializable</span> <span class="nf">getSessionid</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取客户端直接地址, 当WebSocket连接是由代理服务器转发的,则该值固定为代理服务器的IP地址</span>
|
||
<span class="kd">public</span> <span class="n">SocketAddress</span> <span class="nf">getRemoteAddress</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取客户端真实地址 同 HttpRequest.getRemoteAddr()</span>
|
||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getRemoteAddr</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取WebSocket创建时间</span>
|
||
<span class="kd">public</span> <span class="kt">long</span> <span class="nf">getCreatetime</span><span class="o">();</span>
|
||
|
||
<span class="c1">//显式地关闭WebSocket</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">close</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取当前WebSocket所属的WebSocketGroup, 不会为null</span>
|
||
<span class="kd">protected</span> <span class="n">WebSocketGroup</span> <span class="nf">getWebSocketGroup</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取指定groupid的WebSocketGroup, 没有返回null</span>
|
||
<span class="kd">protected</span> <span class="n">WebSocketGroup</span> <span class="nf">getWebSocketGroup</span><span class="o">(</span><span class="n">Serializable</span> <span class="n">groupid</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取当前进程节点所有在线的WebSocketGroup</span>
|
||
<span class="kd">protected</span> <span class="n">Collection</span><span class="o"><</span><span class="n">WebSocketGroup</span><span class="o">></span> <span class="nf">getWebSocketGroups</span><span class="o">();</span>
|
||
|
||
<span class="c1">//获取在线用户的节点地址列表</span>
|
||
<span class="kd">protected</span> <span class="n">Collection</span><span class="o"><</span><span class="n">InetSocketAddress</span><span class="o">></span> <span class="nf">getOnlineNodes</span><span class="o">(</span><span class="n">Serializable</span> <span class="n">groupid</span><span class="o">);</span>
|
||
|
||
<span class="c1">//获取在线用户的详细连接信息</span>
|
||
<span class="kd">protected</span> <span class="n">Map</span><span class="o"><</span><span class="n">InetSocketAddress</span><span class="o">,</span> <span class="n">List</span><span class="o"><</span><span class="n">String</span><span class="o">>></span> <span class="nf">getOnlineRemoteAddress</span><span class="o">(</span><span class="n">Serializable</span> <span class="n">groupid</span><span class="o">);</span>
|
||
|
||
<span class="c1">//返回sessionid, null表示连接不合法或异常,默认实现是request.getSessionid(false),通常需要重写该方法</span>
|
||
<span class="kd">public</span> <span class="n">Serializable</span> <span class="nf">onOpen</span><span class="o">(</span><span class="kd">final</span> <span class="n">HttpRequest</span> <span class="n">request</span><span class="o">);</span>
|
||
|
||
<span class="c1">//创建groupid, null表示异常, 必须实现该方法, 通常为用户ID为groupid</span>
|
||
<span class="kd">protected</span> <span class="kd">abstract</span> <span class="n">Serializable</span> <span class="nf">createGroupid</span><span class="o">();</span>
|
||
|
||
<span class="c1">//标记为@WebSocketBinary才需要重写此方法</span>
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onRead</span><span class="o">(</span><span class="n">AsyncConnection</span> <span class="n">channel</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onConnected</span><span class="o">()</span> <span class="o">{</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onMessage</span><span class="o">(</span><span class="n">String</span> <span class="n">text</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onPing</span><span class="o">(</span><span class="kt">byte</span><span class="o">[]</span> <span class="n">bytes</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onPong</span><span class="o">(</span><span class="kt">byte</span><span class="o">[]</span> <span class="n">bytes</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onMessage</span><span class="o">(</span><span class="kt">byte</span><span class="o">[]</span> <span class="n">bytes</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onFragment</span><span class="o">(</span><span class="n">String</span> <span class="n">text</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">last</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onFragment</span><span class="o">(</span><span class="kt">byte</span><span class="o">[]</span> <span class="n">bytes</span><span class="o">,</span> <span class="kt">boolean</span> <span class="n">last</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="o">}</span>
|
||
|
||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onClose</span><span class="o">(</span><span class="kt">int</span> <span class="n">code</span><span class="o">,</span> <span class="n">String</span> <span class="n">reason</span><span class="o">)</span> <span class="o">{</span>
|
||
<span class="o">}</span>
|
||
<span class="o">}</span></pre></div>
|
||
|
||
<h3><a id="net_sncp" class="anchor" href="#" aria-hidden="true"></a>SNCP 协议</h3>
|
||
<p>
|
||
SNCP(Service Node Communicate Protocol)协议是Redkale独有的一种传输协议,用于进程之间的通信,即请求方的<a href="service.html#service_remote" target="_blank">远程模式Service</a>与响应方的Service之间的通信。是RPC(远程过程调用协议)的同类型协议,主要区别在于Redkale里SNCP几乎是透明的,写一个普通的Service通过配置即可实现远程调用,而不需要专门针对远程写接口。SNCP服务的配置与HTTP差不多,只是SNCP不需要Servlet,SncpServlet是通过Service动态生成的。<br/>
|
||
SNCP的数据包分包头和包体。包头描述请求的Service信息,请求包的包体描述参数的<a href="convert.html#convert_bson_struct" target="_blank">BSON值</a>,响应包的包体描述回调的参数对象和结果对象的<a href="convert.html#convert_bson_struct" target="_blank">BSON值</a>。<br/>
|
||
包头长度固定,其结构如下:
|
||
</p>
|
||
<table style="margin: auto;">
|
||
<tr><th>字 段</th><th>占用字节数</th><th>描 述</th></tr>
|
||
<tr><td>序列号</td><td style="text-align: center;">8</td><td>请求的唯一序列号</td></tr>
|
||
<tr><td>包头长度</td><td style="text-align: center;">2</td><td>值固定为56</td></tr>
|
||
<tr><td>Service资源hash值</td><td style="text-align: center;">16</td><td>Service资源名class.getName():@Resource.name()的MD5值</td></tr>
|
||
<tr><td>Service方法hash值</td><td style="text-align: center;">16</td><td>Service方法method.toString()的MD5值</td></tr>
|
||
<tr><td>发送方地址</td><td style="text-align: center;">6</td><td>前4字节为地址,后2字节为端口号</td></tr>
|
||
<tr><td>包体长度</td><td style="text-align: center;">4</td><td>整个包体的长度</td></tr>
|
||
<tr><td>结果码</td><td style="text-align: center;">4</td><td>请求方的值固定为0,响应方的值视为错误码,为0表示成功,非0为失败。</td></tr>
|
||
</table>
|
||
<p>
|
||
包体数据结构为 ([参数序号][参数BSON值])* N + [0][结果对象BSON]。 其中参数序号从1开始,只有当Service的方法存在<a href="service.html#service_dyncall" target="_blank">@DynCall回调</a>才会有参数<a href="convert.html#convert_bson_struct" target="_blank">BSON值</a>,序号为0表示为结果对象的<a href="convert.html#convert_bson_struct" target="_blank">BSON值</a>。若方法为<font color="blue">void</font>返回类型,则不存在结果对象<a href="convert.html#convert_bson_struct" target="_blank">BSON值</a>。
|
||
</p>
|
||
|
||
<h3><a id="net_diy" class="anchor" href="#" aria-hidden="true"></a>自定义协议</h3>
|
||
<p> 协议的网络框架包含五种对象: <br/>
|
||
Context : 协议上下文对象 <br/>
|
||
Request : 服务请求对象 <br/>
|
||
Response : 服务响应对象 <br/>
|
||
Servlet : 服务逻辑处理对象 <br/>
|
||
Server : 服务监听对象 <br/>
|
||
通常自定义协议需要继承上面五种对象类,同时为了让Redkale能识别和加载自定义协议服务需要继承 <b>org.redkale.boot.NodeServer</b> 并指明 <b>@NodeProtocol</b>,实现可以参考 <a href="https://github.com/redkale/redkale-plugins/tree/master/src/org/redkale/net/socks" target="_blank" >基于SOCKS5协议的反向代理服务器</a>
|
||
</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>
|