Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1aa19c444 | ||
|
|
31acee979f | ||
|
|
a183cb045c | ||
|
|
7fccef8aea | ||
|
|
2c57cbc6f0 |
BIN
.gitbook/assets/1623316769(1).jpg
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
.gitbook/assets/1623316875(1) (1).jpg
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
.gitbook/assets/1623316875(1).jpg
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
.gitbook/assets/image (1).png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
.gitbook/assets/image (10).png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
.gitbook/assets/image (11).png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
.gitbook/assets/image (12).png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
.gitbook/assets/image (13).png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
.gitbook/assets/image (14).png
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
.gitbook/assets/image (15).png
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
.gitbook/assets/image (16).png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
.gitbook/assets/image (17).png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
.gitbook/assets/image (18).png
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
.gitbook/assets/image (19).png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
.gitbook/assets/image (2).png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
.gitbook/assets/image (20).png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
.gitbook/assets/image (21).png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
.gitbook/assets/image (22).png
Normal file
|
After Width: | Height: | Size: 112 KiB |
BIN
.gitbook/assets/image (23).png
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
.gitbook/assets/image (3).png
Normal file
|
After Width: | Height: | Size: 131 KiB |
BIN
.gitbook/assets/image (4).png
Normal file
|
After Width: | Height: | Size: 70 KiB |
BIN
.gitbook/assets/image (5).png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
.gitbook/assets/image (6).png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
.gitbook/assets/image (7).png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
.gitbook/assets/image (8).png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
.gitbook/assets/image (9).png
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
.gitbook/assets/image.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
21
README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
description: Java 全栈式微服务开源框架
|
||||
---
|
||||
|
||||
# 简介
|
||||
|
||||
  Redkale(中文名: 红菜苔,湖北特产蔬菜)是基于Java 11全新的微服务开源框架, 包含HTTP、WebSocket、TCP/UDP、数据序列化、数据缓存、依赖注入等功能。 本框架致力于简化集中式和微服务架构的开发,在增强开发敏捷性的同时保持高性能。 
|
||||
|
||||
  Redkale 有如下主要特点: \
|
||||
  1、大量使用Java 8新特性(接口默认值、Stream、Lambda、JDk8内置的ASM等) \
|
||||
  2、提供HTTP服务,同时内置JSON功能与限时缓存功能 \
|
||||
  3、TCP层使用NIO,并统一TCP与UDP的接口 \
|
||||
  4、提供分布式与集中式部署的无缝切换 \
|
||||
  5、提供类似JPA功能,包含数据缓存自动同步、分表分库与简洁的数据层操作接口 \
|
||||
  6、支持依赖注入的资源的动态修改 \
|
||||
  7、Servlet、Service、Source组件均支持异步接口 
|
||||
|
||||
\
|
||||
  作为一个全新的微服务框架,Redkale在接口定义上使用了Java 8大量的新语法,接口有默认实现、接口带静态方法、重复注解等特性,同时在设计上与主流框架有很大不同。Redkale是按组件形式设计的,而非以容器为主,几乎每个子包都是能提供独立功能的组件。如Tomcat是按容器设计的,所有web资源/配置由Tomcat控制,开发者很能难控制到Tomcat内部,而Redkale的HTTP服务只是个组件,开发者既可以自己启动和配置HttpServer,也可以把Redkale当成容器通过Redkale进程来初始化服务。Spring的Ioc容器也是如此,Redkale提供的依赖注入仅通过ResouceFactory一个类来控制,非常轻量,并且可动态更改已注入的资源。Spring提倡控制反转思想,而自身的容器却让开发者很难控制。Redkale是一个既能以组件形式也能以容器形式存在的框架。从整体上看,Redkale的架构分两层:接口和默认实现。开发者若想替换掉Redkale内置的HTTP服务而使用符合JavaEE规范的HttpServlet, 可以采用自定义协议基于JSR 340(Servlet 3.1)来实现自己的HTTP服务;若想使用Hibernate作为数据库操作,可以写一个自己的DataSource实现类;JSON的序列化和反序列化也可以使用第三方的实现;Memcached或Redis也可以作为另一个CacheSource的实现替换Redkale的默认实现。这其实包含了控制反转的思想,让框架里的各个组件均可让开发者控制。 \
|
||||
  与主流框架比,功能上Redkale显得很简单,这体现了Redkale的简易性,而并非是不足,从一个良好的设计习惯或架构上来看,有些常用功能是不需要提供的,如Redkale的HTTP服务不支持HTTPS和JSP,HTTPS比HTTP多了一层加密解密,这种密集型的计算不是Java的专长,通常提供HTTP服务的架构不会将Java动态服务器放在最前端,而是在前方会放nginx或apache,除了负载均衡还能静动分离,因此HTTPS的加解密应交给nginx这样的高性能服务器处理。Redkale再提供HTTPS服务就显得鸡肋。JSP其实算是一个落后的技术,现在是一个多样化终端的时代,终端不只局限于桌面程序和PC浏览器,还有原生App、混合式App、微信端、移动H5、提供第三方接口等各种形式的终端,这些都不是JSP能方便兼顾的,而HTTP+JSON作为通用性接口可以避免重复开发,模版引擎的功能加上各种强大的JS框架足以取代JSP。Redkale在功能上做了筛选,不会为了迎合主流而提供,而是以良好的设计思想为指导。这是Redkale的主导思维。
|
||||
|
||||
17
SUMMARY.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Table of contents
|
||||
|
||||
* [简介](README.md)
|
||||
* [快速入门](quick-start.md)
|
||||
* [Service 组件](service-zu-jian.md)
|
||||
* [Convert 组件](convert-zu-jian.md)
|
||||
* [HTTP 服务](http-fu-wu.md)
|
||||
* [SNCP 服务](sncp-fu-wu.md)
|
||||
* [WATCH 服务](watch-fu-wu.md)
|
||||
* [CacheSource缓存组件](cachesource-huan-cun-zu-jian.md)
|
||||
* [DataSource数据库组件](datasource-shu-ju-ku-zu-jian.md)
|
||||
* [Client 组件](client-zu-jian.md)
|
||||
* [PropertiesAgent 配置中心](propertiesagent-pei-zhi-zhong-xin.md)
|
||||
* [ClusterAgent 服务注册中心](clusteragent-fu-wu-zhu-ce-zhong-xin.md)
|
||||
* [MessageAgent MQ中心](messageagent-mq-zhong-xin.md)
|
||||
* [配置文件](readme.md)
|
||||
* [版本更新](ban-ben-geng-xin.md)
|
||||
@@ -1,68 +0,0 @@
|
||||
<!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>Redkale 技术详解 03 -- Convert高性能序列化</h3>
|
||||
|
||||
<p>
|
||||
<a href="/convert.html" target="_blank">Convert</a>是个重复造轮子的组件,却是个飞速的轮子。Redkale之所以重复造轮子主要追求性能和需要与网络数据的序列化很好的结合(<a href="/convert.html#json_net_bytebuffer" target="_blank">Convert与ByteBuffer的结合</a>)。 Convert在API设计思路上也与其他同类型的框架不一样,配置与序列化方法是分开的,大部分场景下配置项是固定的,因此不同的配置会动态生成对应的处理类以保证性能。
|
||||
</p>
|
||||
<p>
|
||||
从包结构可以看出,Convert分三层:序列化与反序列化的抽象基础包;JSON包、Protobuf包。即使boolean、int、String这种基础数据类型都不是包含在Convert基础包中。以下是详细的结构图:
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/convertimg_1.png" alt=""/></p>
|
||||
<p>
|
||||
从上图可以看出,JSON与PROTOBUF是Convert基础包的实现,主要是实现Reader与Writer类。若需要实现XML格式的序列化,可以以JSON为参考自己编写。对于不是内置(ext子包下的数据类型)的且没有自定义处理(Encoder、Decoder)的数据类型, Convert会动态生成ObjectEncoder、ObjectDecoder对象。
|
||||
</p>
|
||||
<p>Convert 的性能</p>
|
||||
<p>
|
||||
一切不谈性能的框架都是在耍流氓!下面以JSON为例,与其他主流的JSON框架做个简单的性能比较(测试环境: DELL的普通笔记本),fastjson一直号称是Java性能最好的JSON解析框架,其使用Benchmark是 <a href="https://github.com/eishay/jvm-serializers/wiki" target="_blank">https://github.com/eishay/jvm-serializers/wiki</a>,Redkale根据该数据编写了<a href="https://github.com/redkale/redkale/tree/master/test/org/redkale/test/convert/media" target="_blank">MediaContent</a>类。实例由MediaContent.createDefault()方法所得。
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/convertimg_2.png" alt=""/></p>
|
||||
<p>
|
||||
由上图第一份报告看出,以MediaContent对象进行比较,fastjson的反序列化性能是最好的,gson性能最差。redkale、fastjson、jackson在序列化方面差距不大。第二份报告的测试对象是将第一份的MediaContent对象中所有的数值改成负数进行测试的,可以看出fastjson对于负数的处理性能很差,只是比gson稍强。第三份报告的测试对象是<a href="https://github.com/redkale/redkale/blob/master/test/org/redkale/test/convert/ConvertRecord.java" target="_blank">ConvertRecord</a>对象,该对象的特点是包含int[]、long[]、List、Map数据。从结果可以看出fastjson的反序列化性能最差。redkale与jackson一直保持高性能。<br/>
|
||||
综合起来看,Redkale的Convert性能是最好的。数据相差50毫秒以下的差距基本可以忽略,因为每次测试的结果会上下波动几十毫秒。
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/article_convert.html" target="_blank">https://redkale.org/article_convert.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,205 +0,0 @@
|
||||
<!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>Redkale 技术详解 02 -- Creator构建对象</h3>
|
||||
|
||||
<p>
|
||||
org.redkale.util.Creator是采用ASM技术来实现代替反射构造函数的对象构建类。在根据流反序列化成对象、数据表记录转换成对象时都需要构建对象。常见的处理办法是利用反射,如Gson框架中反序列化是通过反射进行对象创建。众所周知反射的性能是比较低的,所以Redkale需要自实现一个对象构建类。
|
||||
</p>
|
||||
<p>
|
||||
Creator是一个接口, 只有一个public T create(Object... params)方法,可变参数既适合空参数的Constructor也适合含参数的Constructor。得利于Java 8的新语法特性可以在接口上加上静态方法,Creator对象可以通过Creator.create(Class clazz)方法创建。构建原理是通过Constructor的参数来动态创建的。
|
||||
</p>
|
||||
<div class="highlight"><pre><span></span> <span class="nx">Constructor</span><span class="o"><</span><span class="nx">T</span><span class="o">></span> <span class="nx">constructor0</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
|
||||
<span class="nx">SimpleEntry</span><span class="o"><</span><span class="nb">String</span><span class="p">,</span> <span class="nx">Class</span><span class="o">></span><span class="p">[]</span> <span class="nx">constructorParameters0</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span> <span class="c1">//构造函数的参数</span>
|
||||
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">constructor0</span> <span class="o">==</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 1、查找public的空参数构造函数</span>
|
||||
<span class="k">for</span> <span class="p">(</span><span class="nx">Constructor</span> <span class="nx">c</span> <span class="o">:</span> <span class="nx">clazz</span><span class="p">.</span><span class="nx">getConstructors</span><span class="p">())</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">getParameterCount</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">constructor0</span> <span class="o">=</span> <span class="nx">c</span><span class="p">;</span>
|
||||
<span class="nx">constructorParameters0</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">SimpleEntry</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
|
||||
<span class="k">break</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">constructor0</span> <span class="o">==</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 2、查找public带ConstructorProperties注解的构造函数</span>
|
||||
<span class="k">for</span> <span class="p">(</span><span class="nx">Constructor</span> <span class="nx">c</span> <span class="o">:</span> <span class="nx">clazz</span><span class="p">.</span><span class="nx">getConstructors</span><span class="p">())</span> <span class="p">{</span>
|
||||
<span class="nx">ConstructorProperties</span> <span class="nx">cp</span> <span class="o">=</span> <span class="p">(</span><span class="nx">ConstructorProperties</span><span class="p">)</span> <span class="nx">c</span><span class="p">.</span><span class="nx">getAnnotation</span><span class="p">(</span><span class="nx">ConstructorProperties</span><span class="p">.</span><span class="kr">class</span><span class="p">);</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">cp</span> <span class="o">==</span> <span class="kc">null</span><span class="p">)</span> <span class="k">continue</span><span class="p">;</span>
|
||||
<span class="nx">SimpleEntry</span><span class="o"><</span><span class="nb">String</span><span class="p">,</span> <span class="nx">Class</span><span class="o">></span><span class="p">[]</span> <span class="nx">fields</span> <span class="o">=</span> <span class="nx">ConstructorParameters</span><span class="p">.</span><span class="nx">CreatorInner</span><span class="p">.</span><span class="nx">getConstructorField</span><span class="p">(</span><span class="nx">clazz</span><span class="p">,</span> <span class="nx">cp</span><span class="p">.</span><span class="nx">value</span><span class="p">());</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">fields</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">constructor0</span> <span class="o">=</span> <span class="nx">c</span><span class="p">;</span>
|
||||
<span class="nx">constructorParameters0</span> <span class="o">=</span> <span class="nx">fields</span><span class="p">;</span>
|
||||
<span class="k">break</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">constructor0</span> <span class="o">==</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 3、查找public且不带ConstructorProperties注解的构造函数</span>
|
||||
<span class="nx">List</span><span class="o"><</span><span class="nx">Constructor</span><span class="o">></span> <span class="nx">cs</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ArrayList</span><span class="o"><></span><span class="p">();</span>
|
||||
<span class="k">for</span> <span class="p">(</span><span class="nx">Constructor</span> <span class="nx">c</span> <span class="o">:</span> <span class="nx">clazz</span><span class="p">.</span><span class="nx">getConstructors</span><span class="p">())</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">getAnnotation</span><span class="p">(</span><span class="nx">ConstructorProperties</span><span class="p">.</span><span class="kr">class</span><span class="p">)</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="k">continue</span><span class="p">;</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">getParameterCount</span><span class="p">()</span> <span class="o"><</span> <span class="mi">1</span><span class="p">)</span> <span class="k">continue</span><span class="p">;</span>
|
||||
<span class="nx">cs</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">c</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
<span class="c1">//优先参数最多的构造函数</span>
|
||||
<span class="nx">cs</span><span class="p">.</span><span class="nx">sort</span><span class="p">((</span><span class="nx">o1</span><span class="p">,</span> <span class="nx">o2</span><span class="p">)</span> <span class="o">-></span> <span class="nx">o2</span><span class="p">.</span><span class="nx">getParameterCount</span><span class="p">()</span> <span class="o">-</span> <span class="nx">o1</span><span class="p">.</span><span class="nx">getParameterCount</span><span class="p">());</span>
|
||||
<span class="k">for</span> <span class="p">(</span><span class="nx">Constructor</span> <span class="nx">c</span> <span class="o">:</span> <span class="nx">cs</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">SimpleEntry</span><span class="o"><</span><span class="nb">String</span><span class="p">,</span> <span class="nx">Class</span><span class="o">></span><span class="p">[]</span> <span class="nx">fields</span> <span class="o">=</span> <span class="nx">ConstructorParameters</span><span class="p">.</span><span class="nx">CreatorInner</span><span class="p">.</span><span class="nx">getConstructorField</span><span class="p">(</span><span class="nx">clazz</span><span class="p">,</span> <span class="nx">Type</span><span class="p">.</span><span class="nx">getConstructorDescriptor</span><span class="p">(</span><span class="nx">c</span><span class="p">));</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">fields</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">constructor0</span> <span class="o">=</span> <span class="nx">c</span><span class="p">;</span>
|
||||
<span class="nx">constructorParameters0</span> <span class="o">=</span> <span class="nx">fields</span><span class="p">;</span>
|
||||
<span class="k">break</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">constructor0</span> <span class="o">==</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 4、查找非private带ConstructorProperties的构造函数</span>
|
||||
<span class="k">for</span> <span class="p">(</span><span class="nx">Constructor</span> <span class="nx">c</span> <span class="o">:</span> <span class="nx">clazz</span><span class="p">.</span><span class="nx">getDeclaredConstructors</span><span class="p">())</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">Modifier</span><span class="p">.</span><span class="nx">isPublic</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">getModifiers</span><span class="p">())</span> <span class="o">||</span> <span class="nx">Modifier</span><span class="p">.</span><span class="nx">isPrivate</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">getModifiers</span><span class="p">()))</span> <span class="k">continue</span><span class="p">;</span>
|
||||
<span class="nx">ConstructorProperties</span> <span class="nx">cp</span> <span class="o">=</span> <span class="p">(</span><span class="nx">ConstructorProperties</span><span class="p">)</span> <span class="nx">c</span><span class="p">.</span><span class="nx">getAnnotation</span><span class="p">(</span><span class="nx">ConstructorProperties</span><span class="p">.</span><span class="kr">class</span><span class="p">);</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">cp</span> <span class="o">==</span> <span class="kc">null</span><span class="p">)</span> <span class="k">continue</span><span class="p">;</span>
|
||||
<span class="nx">SimpleEntry</span><span class="o"><</span><span class="nb">String</span><span class="p">,</span> <span class="nx">Class</span><span class="o">></span><span class="p">[]</span> <span class="nx">fields</span> <span class="o">=</span> <span class="nx">ConstructorParameters</span><span class="p">.</span><span class="nx">CreatorInner</span><span class="p">.</span><span class="nx">getConstructorField</span><span class="p">(</span><span class="nx">clazz</span><span class="p">,</span> <span class="nx">cp</span><span class="p">.</span><span class="nx">value</span><span class="p">());</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">fields</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">constructor0</span> <span class="o">=</span> <span class="nx">c</span><span class="p">;</span>
|
||||
<span class="nx">constructorParameters0</span> <span class="o">=</span> <span class="nx">fields</span><span class="p">;</span>
|
||||
<span class="k">break</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">constructor0</span> <span class="o">==</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// 5、查找非private且不带ConstructorProperties的构造函数</span>
|
||||
<span class="nx">List</span><span class="o"><</span><span class="nx">Constructor</span><span class="o">></span> <span class="nx">cs</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ArrayList</span><span class="o"><></span><span class="p">();</span>
|
||||
<span class="k">for</span> <span class="p">(</span><span class="nx">Constructor</span> <span class="nx">c</span> <span class="o">:</span> <span class="nx">clazz</span><span class="p">.</span><span class="nx">getDeclaredConstructors</span><span class="p">())</span> <span class="p">{</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">Modifier</span><span class="p">.</span><span class="nx">isPublic</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">getModifiers</span><span class="p">())</span> <span class="o">||</span> <span class="nx">Modifier</span><span class="p">.</span><span class="nx">isPrivate</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">getModifiers</span><span class="p">()))</span> <span class="k">continue</span><span class="p">;</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">getAnnotation</span><span class="p">(</span><span class="nx">ConstructorProperties</span><span class="p">.</span><span class="kr">class</span><span class="p">)</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="k">continue</span><span class="p">;</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">getParameterCount</span><span class="p">()</span> <span class="o"><</span> <span class="mi">1</span><span class="p">)</span> <span class="k">continue</span><span class="p">;</span>
|
||||
<span class="nx">cs</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">c</span><span class="p">);</span>
|
||||
<span class="p">}</span>
|
||||
<span class="c1">//优先参数最多的构造函数</span>
|
||||
<span class="nx">cs</span><span class="p">.</span><span class="nx">sort</span><span class="p">((</span><span class="nx">o1</span><span class="p">,</span> <span class="nx">o2</span><span class="p">)</span> <span class="o">-></span> <span class="nx">o2</span><span class="p">.</span><span class="nx">getParameterCount</span><span class="p">()</span> <span class="o">-</span> <span class="nx">o1</span><span class="p">.</span><span class="nx">getParameterCount</span><span class="p">());</span>
|
||||
<span class="k">for</span> <span class="p">(</span><span class="nx">Constructor</span> <span class="nx">c</span> <span class="o">:</span> <span class="nx">cs</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">SimpleEntry</span><span class="o"><</span><span class="nb">String</span><span class="p">,</span> <span class="nx">Class</span><span class="o">></span><span class="p">[]</span> <span class="nx">fields</span> <span class="o">=</span> <span class="nx">ConstructorParameters</span><span class="p">.</span><span class="nx">CreatorInner</span><span class="p">.</span><span class="nx">getConstructorField</span><span class="p">(</span><span class="nx">clazz</span><span class="p">,</span> <span class="nx">Type</span><span class="p">.</span><span class="nx">getConstructorDescriptor</span><span class="p">(</span><span class="nx">c</span><span class="p">));</span>
|
||||
<span class="k">if</span> <span class="p">(</span><span class="nx">fields</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">constructor0</span> <span class="o">=</span> <span class="nx">c</span><span class="p">;</span>
|
||||
<span class="nx">constructorParameters0</span> <span class="o">=</span> <span class="nx">fields</span><span class="p">;</span>
|
||||
<span class="k">break</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
<p>
|
||||
从以上代码可以看出,根据优先级选择Constructor,为了减少学习成本,Creator直接重用了java.beans.ConstructorProperties注解,又因ConstructorProperties只能标记在Constructor上,因此定义一个Creator.ConstructorParameters注解,用于标记在Creator的create方法上。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Record</span> <span class="o">{</span>
|
||||
|
||||
<span class="kd">private</span> <span class="kd">final</span> <span class="kt">int</span> <span class="n">id</span><span class="o">;</span>
|
||||
|
||||
<span class="kd">private</span> <span class="n">String</span> <span class="n">name</span><span class="o">;</span>
|
||||
|
||||
<span class="nd">@ConstructorProperties</span><span class="o">({</span><span class="s">"id"</span><span class="o">,</span> <span class="s">"name"</span><span class="o">})</span>
|
||||
<span class="n">Record</span><span class="o">(</span><span class="kt">int</span> <span class="n">id</span><span class="o">,</span> <span class="n">String</span> <span class="n">name</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">id</span> <span class="o">=</span> <span class="n">id</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">name</span> <span class="o">=</span> <span class="n">name</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">getId</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">id</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getName</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">name</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setName</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">name</span> <span class="o">=</span> <span class="n">name</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
|
||||
<span class="na"><b>Record.class通过ASM自动构建与Record同package的Creator类如下:</b></span>
|
||||
|
||||
<span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">Record_DynCreator</span> <span class="kd">implements</span> <span class="n">Creator</span><span class="o"><</span><span class="n">Record</span><span class="o">></span> <span class="o">{</span>
|
||||
|
||||
<span class="nd">@Override</span>
|
||||
<span class="nd">@Creator.ConstructorParameters</span><span class="o">({</span><span class="s">"id"</span><span class="o">,</span> <span class="s">"name"</span><span class="o">})</span>
|
||||
<span class="kd">public</span> <span class="n">Record</span> <span class="nf">create</span><span class="o">(</span><span class="n">Object</span><span class="o">...</span> <span class="n">params</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">params</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="n">params</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="k">new</span> <span class="nf">Record</span><span class="o">((</span><span class="n">Integer</span><span class="o">)</span> <span class="n">params</span><span class="o">[</span><span class="mi">0</span><span class="o">],</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span> <span class="n">params</span><span class="o">[</span><span class="mi">1</span><span class="o">]);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
如上代码,若构造参数是primitive类,而Creator.create传入的参数可能是null,因此需要给null的primitive对象赋予默认值0。细心的人可能发现了Record的构造函数并不是public的,虽然Record_DynCreator与Record在同一package,但由于两者不是同一个ClassLoader,故不能直接new Record。Redkale曲线救国,通过URLClassLoader的私有方法在Record.class的ClassLoader加载Record_DynCreator。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="k">if</span> <span class="o">(</span><span class="n">loader</span> <span class="k">instanceof</span> <span class="n">URLClassLoader</span> <span class="o">&&</span> <span class="o">!</span><span class="n">Modifier</span><span class="o">.</span><span class="na">isPublic</span><span class="o">(</span><span class="n">constructor</span><span class="o">.</span><span class="na">getModifiers</span><span class="o">()))</span> <span class="o">{</span>
|
||||
<span class="k">try</span> <span class="o">{</span>
|
||||
<span class="kd">final</span> <span class="n">URLClassLoader</span> <span class="n">urlLoader</span> <span class="o">=</span> <span class="o">(</span><span class="n">URLClassLoader</span><span class="o">)</span> <span class="n">loader</span><span class="o">;</span>
|
||||
<span class="kd">final</span> <span class="n">URL</span> <span class="n">url</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">URL</span><span class="o">(</span><span class="s">"memclass"</span><span class="o">,</span> <span class="s">"localhost"</span><span class="o">,</span> <span class="o">-</span><span class="mi">1</span><span class="o">,</span> <span class="s">"/"</span> <span class="o">+</span> <span class="n">newDynName</span><span class="o">.</span><span class="na">replace</span><span class="o">(</span><span class="sc">'/'</span><span class="o">,</span> <span class="sc">'.'</span><span class="o">)</span> <span class="o">+</span> <span class="s">"/"</span><span class="o">,</span> <span class="k">new</span> <span class="nf">URLStreamHandler</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="nd">@Override</span>
|
||||
<span class="kd">protected</span> <span class="n">URLConnection</span> <span class="nf">openConnection</span><span class="o">(</span><span class="n">URL</span> <span class="n">u</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="k">new</span> <span class="nf">URLConnection</span><span class="o">(</span><span class="n">u</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">connect</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="nd">@Override</span>
|
||||
<span class="kd">public</span> <span class="n">InputStream</span> <span class="nf">getInputStream</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="k">new</span> <span class="nf">ByteArrayInputStream</span><span class="o">(</span><span class="n">bytes</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">};</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">});</span>
|
||||
<span class="n">Method</span> <span class="n">addURLMethod</span> <span class="o">=</span> <span class="n">URLClassLoader</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">getDeclaredMethod</span><span class="o">(</span><span class="s">"addURL"</span><span class="o">,</span> <span class="n">URL</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
|
||||
<span class="n">addURLMethod</span><span class="o">.</span><span class="na">setAccessible</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>
|
||||
<span class="n">addURLMethod</span><span class="o">.</span><span class="na">invoke</span><span class="o">(</span><span class="n">urlLoader</span><span class="o">,</span> <span class="n">url</span><span class="o">);</span>
|
||||
<span class="n">resultClazz</span> <span class="o">=</span> <span class="n">urlLoader</span><span class="o">.</span><span class="na">loadClass</span><span class="o">(</span><span class="n">newDynName</span><span class="o">.</span><span class="na">replace</span><span class="o">(</span><span class="sc">'/'</span><span class="o">,</span> <span class="sc">'.'</span><span class="o">));</span>
|
||||
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">Throwable</span> <span class="n">t</span><span class="o">)</span> <span class="o">{</span> <span class="c1">//异常无需理会, 使用下一种loader方式</span>
|
||||
<span class="n">t</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
如上代码,构建一个虚拟协议的URL来实现加载,若Record.class的ClassLoader不是URLClassLoader导致resultClazz为null则会抛出异常。
|
||||
</p>
|
||||
<p>
|
||||
Creator是一个典型通过ASM构建一个简单功能地动态类,同类型还有 <a href="https://redkale.org/javadoc/org/redkale/util/Attribute.html" target="_blank">org.redkale.util.Attribute</a>、<a href="https://redkale.org/javadoc/org/redkale/util/Copier.html" target="_blank">org.redkale.util.Copier</a>。
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/article_creator.html" target="_blank">https://redkale.org/article_creator.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,111 +0,0 @@
|
||||
<!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>Redkale 技术详解 01 -- 双亲委托模型</h3>
|
||||
|
||||
<p>
|
||||
<a href="index.html" target="_blank">Redkale</a> 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。<br/>
|
||||
</p>
|
||||
|
||||
<p>ClassLoader类加载</p>
|
||||
<p>
|
||||
双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。<br/>
|
||||
ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
|
||||
</p>
|
||||
|
||||
<p>Redkale 双亲委托</p>
|
||||
<p>
|
||||
ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">findEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">rs</span> <span class="o">=</span> <span class="o">(</span><span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">>)</span> <span class="n">encoders</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">rs</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">rs</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">parent</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">parent</span><span class="o">.</span><span class="na">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">loadEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">GenericArrayType</span><span class="o">)</span> <span class="k">return</span> <span class="k">new</span> <span class="nf">ArrayEncoder</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">type</span><span class="o">);</span>
|
||||
<span class="n">Class</span> <span class="n">clazz</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">ParameterizedType</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="kd">final</span> <span class="n">ParameterizedType</span> <span class="n">pts</span> <span class="o">=</span> <span class="o">(</span><span class="n">ParameterizedType</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="o">(</span><span class="n">pts</span><span class="o">).</span><span class="na">getRawType</span><span class="o">();</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">TypeVariable</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">TypeVariable</span> <span class="n">tv</span> <span class="o">=</span> <span class="o">(</span><span class="n">TypeVariable</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">Type</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">().</span><span class="na">length</span> <span class="o">==</span> <span class="mi">1</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">t</span> <span class="o">=</span> <span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">()[</span><span class="mi">0</span><span class="o">];</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(!(</span><span class="n">t</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">))</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</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="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConvertException</span><span class="o">(</span><span class="s">"not support the type ("</span> <span class="o">+</span> <span class="n">type</span> <span class="o">+</span> <span class="s">")"</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="nf">createEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">,</span> <span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 <a href="convert.html#convert_base" target="_blank">Convert基本用法</a> 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。
|
||||
</p>
|
||||
<p>
|
||||
Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="nf">NodeServer</span><span class="o">(</span><span class="n">Application</span> <span class="n">application</span><span class="o">,</span> <span class="n">Server</span> <span class="n">server</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">application</span> <span class="o">=</span> <span class="n">application</span><span class="o">;</span>
|
||||
<b><span class="k">this</span><span class="o">.</span><span class="na">resourceFactory</span> <span class="o">=</span> <span class="n">application</span><span class="o">.</span><span class="na">getResourceFactory</span><span class="o">().</span><span class="na">createChild</span><span class="o">();</span></b>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">server</span> <span class="o">=</span> <span class="n">server</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">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="o">}</span></pre></div>
|
||||
<p>
|
||||
双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/article_parents.html" target="_blank">https://redkale.org/article_parents.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,135 +0,0 @@
|
||||
<!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>Redkale 让你重新认识Java</h3>
|
||||
|
||||
<p>
|
||||
Java 已经22岁了,依靠强大的功能、庞大的开发社区和无人能及的生态系统,长期占据世界编程语言排行榜首,成为当之无愧的业界之王。本人在大学时期被这种很有艺术性的开发语言所吸引,果断抛弃C,学习方式很简单,只看JDK API源码,直到现在都是如此。刚毕业就一直从事Java开发方面的工作,至今也有十来年了。从JSP、WebWork到Struts、JSF,从JDBC、Hibernate到TopLink、JPA。从NIO、Mina到Netty、Grizzly。很多框架都用过,研究过。后来渐渐觉得各阶段主流的框架功能很强大,设计理念也很好,但是我们大部分情况只使用其中一小部分功能,框架在实现上性能也普遍一般(除少数追求性能的框架),且适应新版JDK发布的版本普及也会滞后两三年以上。慢慢地发现用了那么多整合的框架并没有比JBuilder时代的开发速度敏捷多少,很多时候在原始的Servlet、JDBC基础上做一定的封装就能满足大部分的需求。个人觉得一个优秀的框架除了保证性能和稳定性,也要注重简易性,而不是满足开发者需求的同时大量依赖包、繁琐的配置(过多的配置性的注解也是配置)和臃肿的jar刷其存在感。在长期看JDK API源码、学习开源框架设计理念和参考JavaEE规范接口设计的习惯下自然有了自己的思路和设计想法,开始学写自己的框架。于是,在2015年框架基本雏形出来并命名为<a href="http://redkale.org" target="_blank">Redkale</a>,2016年正式开源。<br/>
|
||||
</p>
|
||||
|
||||
<p> <b>太臃肿</b></p>
|
||||
<p>
|
||||
如今在Java界,Tomcat、Struts2、Hibernate、MyBatis、Jetty、Spring MVC/Spring Boot/Spring XXX这些框架大家都耳熟能详,似乎不懂其中一二都不好意思说自己会Java,Spring已经成了Java的代名词,很多四五年以上的开发人员只识开源框架不识JDK,谈起这些框架的原理、优缺点,各种SOA、集群、分布式、事务、微服务概念头头是道,都可以出书了,但是写出来的代码或做出来的数据结构设计,堪比实习生。2004年发布正式版的Spring以其轻量著称,一战成名,打败了J2EE,成为Java事实上的"标准"。然而经过十几年的发展,其生态越来越庞大,功能的增多,复杂的配置,兼容性,历史包袱,使得整个框架体系越来越臃肿,还有不计其数的衍生插件,已经不比当年J2EE轻多少了。在那个JBuilder还是主流IDE的年代,建一个Web系统还是比较简单,除了Tomcat比较大点,其他都算轻量。现在很多人建一个Web项目,需要复杂的Maven建工程,一行代码还没开始写,仅仅是导入SSH/SSM这些框架就需要好几十M,还得进行一堆SSH配置,简单的日志都需要配备log4j/snf4j。可能只是简单的管理系统,必须要搞这么复杂吗? 现在一个1-2M的框架大家都认为是轻量级,MyBatis是JDBC基础上的再次封装,jar包大小近6M,但比Hibernate还是轻量些。这些只是基础框架,如果系统还需要其他功能性的框架(Lucene、Mail、Json) 会使开发包更大。同时大量的开源框架抑制了新JDK的普及,NIO出来都十五年, AIO(NIO.2)也出来六年了,如今还有很多人把NIO给贴上高性能的标签,JDK 5——Java第一个重大更新的版本在2004年发布,直到五-六年后Spring的注解方式才得到普及(Spring旧版本xml方式普及度高), Java第二个重大更新的版本JDK 8发布也有三年了,大部分人还停留在只识语法糖Lambda的程度,在JDK功能越来越强大的情况下,开发Java系统并不简化多少。相对于现在流行的NodeJs做个Web系统来说,Java就是个巨无霸。其实呢,Java无需这么复杂,真的可以很简单。
|
||||
</p>
|
||||
|
||||
<p> <b>异步呢</b></p>
|
||||
<p>
|
||||
用Java开发异步系统是件很难的事情,首先Java规范中异步接口很少,Servlet 3.0虽然支持异步,也出来好几年了,但现在直接用Servlet写代码的人已经不多,而基于Servlet的Struts、Spring Boot这些框架又没把异步太当回事,基本都是实现的Servet同步方法。其次JDBC更是迄今为止还没有异步接口,基于JDBC的Hibernate、MyBatis同样不会有异步接口。再者开源框架以异步接口为主的凤毛麟角。 所以Java程序员在写业务代码时基本都是用同步方式,特别是最耗时的数据源操作JDBC无法异步。
|
||||
</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">"/order/*"</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="kd">class</span> <span class="nc">OrderServlet</span> <span class="kd">extends</span> <span class="n">HttpBaseServlet</span> <span class="o">{</span>
|
||||
|
||||
<span class="nd">@Resource</span>
|
||||
<span class="kd">private</span> <span class="n">OrderService</span> <span class="n">service</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">"/order/find"</span><span class="o">,</span> <span class="n">comment</span> <span class="o">=</span> <span class="s">"查询单个订单"</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">long</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">"订单ID"</span><span class="o">)</span>
|
||||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">logout</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="kt">long</span> <span class="n">orderid</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="mi">0</span><span class="n">L</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">findOrder</span><span class="o">(</span><span class="n">orderid</span><span class="o">));</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
|
||||
<span class="nd">@Comment</span><span class="o">(</span><span class="s">"订单服务"</span><span class="o">)</span>
|
||||
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">OrderService</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="nd">@Comment</span><span class="o">(</span><span class="s">"查询单个订单"</span><span class="o">)</span>
|
||||
<span class="kd">public</span> <span class="n">Order</span> <span class="nf">findOrder</span><span class="o">(</span><span class="kt">long</span> <span class="n">orderid</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">find</span><span class="o">(</span><span class="n">Order</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">orderid</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
</pre></div>
|
||||
<p>
|
||||
以上范例是大多数Java开发者的常规写法,Servlet调用Service,Serivce调用数据库操作返回结果,都是同步操作, 而基于JDBC的开发使得最耗时的数据库操作占用了大量的线程时间,即使HTTP使用NIO、AIO(NIO.2)都收效甚微。而在NodeJs里,IO操作都是异步的。如下:
|
||||
</p>
|
||||
<div class="highlight"><pre><span></span><span class="nx">http</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="s">"/url"</span><span class="p">,</span> <span class="p">{</span><span class="nx">id</span><span class="o">:</span><span class="mi">10</span><span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">request</span><span class="p">,</span> <span class="nx">response</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">service</span><span class="p">.</span><span class="nx">getResource</span><span class="p">(</span><span class="nx">request</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">result</span><span class="p">){</span>
|
||||
<span class="nx">response</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">result</span><span class="p">));</span>
|
||||
<span class="nx">response</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">});</span>
|
||||
|
||||
<span class="kd">var</span> <span class="nx">mysql</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s">'mysql'</span><span class="p">);</span>
|
||||
<span class="kd">var</span> <span class="nx">pool</span> <span class="o">=</span> <span class="nx">mysql</span><span class="p">.</span><span class="nx">createPool</span><span class="p">(</span><span class="nx">config</span><span class="p">);</span>
|
||||
<span class="nx">pool</span><span class="p">.</span><span class="nx">getConnection</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">connection</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">connection</span><span class="p">.</span><span class="nx">query</span><span class="p">(</span> <span class="s">'SELECT * FROM table'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">,</span> <span class="nx">rows</span><span class="p">)</span> <span class="p">{</span>
|
||||
<span class="nx">connection</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
|
||||
<span class="p">});</span>
|
||||
<span class="p">});</span>
|
||||
</pre></div>
|
||||
<p>
|
||||
这也是Nodejs做些小系统比Java还快。Java在语言和IO上的性能优势弥补不了同步来带的线程消耗。
|
||||
</p>
|
||||
|
||||
<p> <b><a href="http://redkale.org" target="_blank">Redkale</a></b></p>
|
||||
<p>
|
||||
<a href="http://redkale.org" target="_blank">Redkale</a> 一个全新设计的Java异步微服务框架。集HTTP、WebSocket、REST、JSON、RPC、DB操作、依赖注入等功能于一身,其 <a href="http://repo.maven.apache.org/maven2/org/redkale/redkale/1.6.1/" target="_blank">redkale-1.6.1.jar</a> 包大小仅790K,且不依赖任何第三方包。大部分框架自身就很庞大,满足了开发者的需求同时也带来复杂的配置。如同上班只有三四里路,要买辆汽车代步,开车轻松的同时会带来车的保险保养,堵车,加油,下车库,找停车位等副作用, 其效果还不如一辆自行车来得简单高效。<a href="http://redkale.org" target="_blank">Redkale</a> 返璞归真,抛弃沉重的历史包袱(javax.servlet、JPA等),基于JDK 8设计微服务架构,尽可能挖掘新JDK的优势,在保证高性能的情况下追求框架的简易性。其核心分三层结构:接入层Servlet、逻辑层Service、数据层Source。 并且三层都支持异步接口,从HTTP接收请求到Service处理逻辑再到Source拉取数据,全程都可异步,最大限度的提高CPU使用率。为适应前后台分工的开发场景,<a href="http://redkale.org" target="_blank">Redkale</a>提供方便的API文档生成功能,无需编写标准的Doc文档也能让前端开发人员知道后台API接口。<br>
|
||||
</p>
|
||||
<p> <b>Servlet</b></p>
|
||||
<p>
|
||||
在API设计上,<a href="http://redkale.org" target="_blank">Redkale</a>下足了功夫,敢于抛弃标准。其HTTP服务不再是javax.servlet——J2EE中使用最多的规范的实现,在接口形式上与NodeJs的HTTP模块很类似,易于操作。Servlet规范对于现在的应用来说过于体系化。时下移动APP、发达的前端、高性能浏览器、静动分离、REST、分布式这些因素已经让JSP、PHP、ASP这些通过后台生成页面的集中式开发框架显得不适时宜。NodeJs中的HTTP模块源码不过十几K,而Java里HTTP服务主流还是Tomcat——一个8M的重型机器。 <a href="http://redkale.org" target="_blank">Redkale</a>摒弃了已经落伍的规范和功能(JSP、InputStream/OutputStream操作、Session对象等),弱化Web概念,HTTP与SNCP服务一样,只是接入层,无需做过重的设计。 <br>
|
||||
其他语言的HTTP框架在处理请求后大多是以response关闭整个请求处理的方式为主,而Servlet规范却是在service方法执行后关闭,Servlet3.0规范虽然支持异步,显然与其他语言框架比,比较生涩难懂,其API使用方式还需与同步方式区别对待,且接口设计本身就会导致实现上性能不佳,而response关闭的方式天然的把同步与异步等同对待,无论是当前线程还是另开线程处理请求,都由response来结束请求处理。同样Servlet规范中WebSocket接口设计上也是过于复杂,且只是针对协议本身的实现,没有考虑大多开发者的使用场景,WebSocket本质上就像一个keepalive的Http请求,雷同HttpServlet。所以<a href="http://redkale.org" target="_blank">Redkale</a>在设计WebSocket时尽量与HttpServlet形态保持一致,同时还集成了分布式功能,让开发者也可以很简单的实现多部署。 <br>
|
||||
</p>
|
||||
<p> <b>Service</b></p>
|
||||
<p>
|
||||
<a href="http://redkale.org" target="_blank">Redkale</a>所有API设计中最精简的当属RPC功能,RPC没有直接调用的API,其功能依附在Service。RPC或类似功能的框架在Java里一直是比较重量级的,从古老的Corba、RMI到后来的EJB、WebService,还有其他很多RPC开源框架,都有着复杂的配置和大量API学习成本,有些还需要区分客户端和服务端(如WebService)。 Service不仅只是个逻辑层的规范定义,还集成了很强大的RPC和异步调用功能,远程模式的Service就是RPC功能,系统在依赖注入过程中创建Service时通过基本的IP配置自动识别是创建本地模式的Service还是远程模式的Service,远程模式的Service使用的就是RPC,但在代码层Service的调用本地模式与远程模式完全一样。更神奇的是,带有异步回调函数CompletionHandler 或返回类型为CompletableFuture的Service方法同样能执行远程模式。这种RPC的简易性是其他框架都无可匹敌的。REST风格的Service在接口设计上尽量减少注解性的配置,同时保留灵活性,减少HttpServlet的编写。<br>
|
||||
</p>
|
||||
<p> <b>Source</b></p>
|
||||
<p>
|
||||
除了开发类似数据库管理工具,大部分情况下开发者只用基本的增删改查操作,Hibernate、MyBatis这些框架对于对象新增/更新/删除和主键查找对象等接口定义都比较简单,但是带有过滤条件的操作,就变得难用。MyBatis需要配各种SQL,大量if else,Hibernate需要写HQL或SQL,JPA规范需要写JPQL或使用Criteria功能。过滤查询、翻页查询、过滤修改、局部修改、过滤删除都是很常见的操作,而主流ORM框架对这类操作进行简化程度很有限。<a href="http://redkale.org" target="_blank">Redkale</a> 结合常规的使用场景,以JavaBean的方式提供过滤功能,无需编写SQL或类似SQL的配置,使过滤性的操作(删改查)API变得异常简单。DataSource另一个亮点是分表分库操作与单表操作的API一样。同时每个操作都提供成异步接口,但是又限于JDBC的同步性,DataSource的默认实现提供的异步接口也只是JDBC的同步操作,若开发者追求性能极致的话,可以使用AIO(NIO.2)技术编写不基于JDBC的DataSource异步实现。 DataSource提供的缓存功能还能保持进程间的同步(得利于RPC)。<br>
|
||||
</p>
|
||||
<p> <b>思维</b></p>
|
||||
<p>
|
||||
<a href="http://redkale.org" target="_blank">Redkale</a> 追求大道至简,不仅提供高性能的功能和简易的API,还带来不同的设计思维。作为一名有追求的开发者,不能只停留在API层面,更多的是需要掌握设计能力,一个好的设计方案往往能少写很多代码。Java里很多规范和框架就是考虑太过全面,为了迎合各种良莠不齐的想法和设计。比如HTTP服务,只是系统的一个接入层,有必须设计ServletConfig、ServletContextListener、HttpSessionListener等这么多API吗,开发者在系统初期养成定义全局的BaseHttpServlet这些基类的习惯就可以控制很多东西,普通功能也无需去使用什么拦截器或AOP功能。提交表单前先将表单数据转换成JSON字符串传给后台,后台的接口既可用于Web也可用于APP,非要按原始表单提交,那只能使用Struts这类笨重的框架了。再如DB操作,开发者设计好的数据结构可以把关系型数据库当NoSQL数据库操作,会发现对JDBC做一定的封装就可以基本杜绝写SQL。非要写存储过程、关联五六张表进行复杂查询,再好的DB框架都满足不了你。再如Date,Date对象的本质是long值,很多人习惯性的数据库就用Date类型,这样会增加很多麻烦,增加数据库的通用性难度,JSON还需要提供各种DateFormat,如果使用long类型,时间只交给页面去format就简单很多,long的性能也更好。说了这么多,只是想表达一个观点,开发时摆脱传统思维的桎栲,换个思路去思考,很多东西会变得很简单。<br>
|
||||
</p>
|
||||
<p>
|
||||
想了解更多关于Redkale的资料, 请访问Redkale官网: :<a href="http://redkale.org" target="_blank">http://redkale.org</a>。
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/article_regain.html" target="_blank">https://redkale.org/article_regain.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,181 +0,0 @@
|
||||
<!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>Redkale 技术详解 04 -- DataSource简易的DB操作</h3>
|
||||
|
||||
<p>
|
||||
长期以来,Hibernate和Mybatis一直是大家使用最多的持久层开发框架。针对这两种框架网络上是各种比较,各种讨论优缺点。其实这两个框架(算上前身ibatis)都是2002年左右发布, 迄今已有15载已笨重不堪,一个mybatis.jar包大小6M左右,Hibernate更是巨大,毫无轻巧灵活可言,提供简化SQL操作的同时带来了复杂繁琐的配置和高学习门槛。而Redkale的Source组件非常轻量级,通过十多个<span style="color: #2041B4;">interface</span>、<span style="color: #2041B4;">enum</span>和十多个<span style="color: #2041B4;">class</span>完成常见的DB操作功能。<br/>
|
||||
Source组件在接口设计上参考了JPA接口,为了降低学习成本,部分注解仍沿用javax.persistence中的类,以多个注解结合一个主操作类 <a href="http://redkale.org/javadoc/org/redkale/source/DataSource.html" target="_blank">DataSource</a> 的方式提供API。在没有IDE自动生成代码的插件支持的情况下Redkale提供了一个Demo代码<a href="https://github.com/redkale/redkale-demo/blob/master/src/org/redkale/demo/base/AutoClassCreator.java" target="_blank"> AutoClassCreator</a> 能很方便的将数据库表生成Entity类。
|
||||
</p>
|
||||
<p>
|
||||
。<br/>
|
||||
Source组件在接口设计上参考了JPA接口,为了降低学习成本,部分注解仍沿用javax.persistence中的类,以多个注解结合一个主操作类 <a href="http://redkale.org/javadoc/org/redkale/source/DataSource.html" target="_blank">DataSource</a> 的方式提供API。在没有IDE自动生成代码的插件支持的情况下Redkale提供了一个Demo代码<a href="https://github.com/redkale/redkale-demo/blob/master/src/org/redkale/demo/base/AutoClassCreator.java" target="_blank"> AutoClassCreator</a> 能很方便的将数据库表生成Entity类。
|
||||
</p>
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="n">Constructor</span><span class="o"><</span><span class="n">T</span><span class="o">></span> <span class="n">constructor0</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
|
||||
<span class="k">for</span> <span class="o">(</span><span class="n">Constructor</span> <span class="n">c</span> <span class="o">:</span> <span class="n">clazz</span><span class="o">.</span><span class="na">getConstructors</span><span class="o">())</span> <span class="o">{</span> <span class="c1">//优先找public 的构造函数</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">c</span><span class="o">.</span><span class="na">getParameterCount</span><span class="o">()</span> <span class="o">==</span> <span class="mi">0</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">constructor0</span> <span class="o">=</span> <span class="n">c</span><span class="o">;</span>
|
||||
<span class="k">break</span><span class="o">;</span>
|
||||
<a href="articles.html"></a>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">constructor0</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span><span class="c1">//其次找非private带ConstructorProperties的构造函数</span>
|
||||
<span class="k">for</span> <span class="o">(</span><span class="n">Constructor</span> <span class="n">c</span> <span class="o">:</span> <span class="n">clazz</span><span class="o">.</span><span class="na">getDeclaredConstructors</span><span class="o">())</span> <span class="o">{</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">Modifier</span><span class="o">.</span><span class="na">isPrivate</span><span class="o">(</span><span class="n">c</span><span class="o">.</span><span class="na">getModifiers</span><span class="o">()))</span> <span class="k">continue</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">c</span><span class="o">.</span><span class="na">getAnnotation</span><span class="o">(</span><span class="n">ConstructorProperties</span><span class="o">.</span><span class="na">class</span><span class="o">)</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">constructor0</span> <span class="o">=</span> <span class="n">c</span><span class="o">;</span>
|
||||
<span class="k">break</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">constructor0</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span><span class="c1">//再次找非private且带-parameters编译项的构造函数 java 8以上才支持</span>
|
||||
<span class="k">for</span> <span class="o">(</span><span class="n">Constructor</span> <span class="n">c</span> <span class="o">:</span> <span class="n">clazz</span><span class="o">.</span><span class="na">getDeclaredConstructors</span><span class="o">())</span> <span class="o">{</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">Modifier</span><span class="o">.</span><span class="na">isPrivate</span><span class="o">(</span><span class="n">c</span><span class="o">.</span><span class="na">getModifiers</span><span class="o">()))</span> <span class="k">continue</span><span class="o">;</span>
|
||||
<span class="n">Parameter</span><span class="o">[]</span> <span class="n">params</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="na">getParameters</span><span class="o">();</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">params</span><span class="o">.</span><span class="na">length</span> <span class="o">==</span> <span class="mi">0</span><span class="o">)</span> <span class="k">continue</span><span class="o">;</span>
|
||||
<span class="kt">boolean</span> <span class="n">flag</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span>
|
||||
<span class="k">for</span> <span class="o">(</span><span class="n">Parameter</span> <span class="n">param</span> <span class="o">:</span> <span class="n">params</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">try</span> <span class="o">{</span>
|
||||
<span class="n">clazz</span><span class="o">.</span><span class="na">getDeclaredField</span><span class="o">(</span><span class="n">param</span><span class="o">.</span><span class="na">getName</span><span class="o">());</span>
|
||||
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">Exception</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">flag</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span>
|
||||
<span class="k">break</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">flag</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">constructor0</span> <span class="o">=</span> <span class="n">c</span><span class="o">;</span>
|
||||
<span class="k">break</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">constructor0</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span><span class="c1">//最后找非private的空构造函数</span>
|
||||
<span class="k">for</span> <span class="o">(</span><span class="n">Constructor</span> <span class="n">c</span> <span class="o">:</span> <span class="n">clazz</span><span class="o">.</span><span class="na">getDeclaredConstructors</span><span class="o">())</span> <span class="o">{</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">Modifier</span><span class="o">.</span><span class="na">isPrivate</span><span class="o">(</span><span class="n">c</span><span class="o">.</span><span class="na">getModifiers</span><span class="o">()))</span> <span class="k">continue</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">c</span><span class="o">.</span><span class="na">getParameterCount</span><span class="o">()</span> <span class="o">==</span> <span class="mi">0</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">constructor0</span> <span class="o">=</span> <span class="n">c</span><span class="o">;</span>
|
||||
<span class="k">break</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
从以上代码可以看出,根据优先级选择Constructor,为了减少学习成本,Creator直接重用了java.beans.ConstructorProperties注解,又因ConstructorProperties只能标记在Constructor上,因此定义一个Creator.ConstructorParameters注解,用于标记在Creator的create方法上。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Record</span> <span class="o">{</span>
|
||||
|
||||
<span class="kd">private</span> <span class="kd">final</span> <span class="kt">int</span> <span class="n">id</span><span class="o">;</span>
|
||||
|
||||
<span class="kd">private</span> <span class="n">String</span> <span class="n">name</span><span class="o">;</span>
|
||||
|
||||
<span class="nd">@ConstructorProperties</span><span class="o">({</span><span class="s">"id"</span><span class="o">,</span> <span class="s">"name"</span><span class="o">})</span>
|
||||
<span class="n">Record</span><span class="o">(</span><span class="kt">int</span> <span class="n">id</span><span class="o">,</span> <span class="n">String</span> <span class="n">name</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">id</span> <span class="o">=</span> <span class="n">id</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">name</span> <span class="o">=</span> <span class="n">name</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">getId</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">id</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getName</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">name</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">setName</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">name</span> <span class="o">=</span> <span class="n">name</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
|
||||
<span class="na"><b>Record.class通过ASM自动构建与Record同package的Creator类如下:</b></span>
|
||||
|
||||
<span class="kd">public</span> <span class="kd">final</span> <span class="kd">class</span> <span class="nc">Record_DynCreator</span> <span class="kd">implements</span> <span class="n">Creator</span><span class="o"><</span><span class="n">Record</span><span class="o">></span> <span class="o">{</span>
|
||||
|
||||
<span class="nd">@Override</span>
|
||||
<span class="nd">@Creator.ConstructorParameters</span><span class="o">({</span><span class="s">"id"</span><span class="o">,</span> <span class="s">"name"</span><span class="o">})</span>
|
||||
<span class="kd">public</span> <span class="n">Record</span> <span class="nf">create</span><span class="o">(</span><span class="n">Object</span><span class="o">...</span> <span class="n">params</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">params</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="n">params</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="k">new</span> <span class="nf">Record</span><span class="o">((</span><span class="n">Integer</span><span class="o">)</span> <span class="n">params</span><span class="o">[</span><span class="mi">0</span><span class="o">],</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span> <span class="n">params</span><span class="o">[</span><span class="mi">1</span><span class="o">]);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
如上代码,若构造参数是primitive类,而Creator.create传入的参数可能是null,因此需要给null的primitive对象赋予默认值0。细心的人可能发现了Record的构造函数并不是public的,虽然Record_DynCreator与Record在同一package,但由于两者不是同一个ClassLoader,故不能直接new Record。Redkale曲线救国,通过URLClassLoader的私有方法在Record.class的ClassLoader加载Record_DynCreator。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="k">if</span> <span class="o">(</span><span class="n">loader</span> <span class="k">instanceof</span> <span class="n">URLClassLoader</span> <span class="o">&&</span> <span class="o">!</span><span class="n">Modifier</span><span class="o">.</span><span class="na">isPublic</span><span class="o">(</span><span class="n">constructor</span><span class="o">.</span><span class="na">getModifiers</span><span class="o">()))</span> <span class="o">{</span>
|
||||
<span class="k">try</span> <span class="o">{</span>
|
||||
<span class="kd">final</span> <span class="n">URLClassLoader</span> <span class="n">urlLoader</span> <span class="o">=</span> <span class="o">(</span><span class="n">URLClassLoader</span><span class="o">)</span> <span class="n">loader</span><span class="o">;</span>
|
||||
<span class="kd">final</span> <span class="n">URL</span> <span class="n">url</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">URL</span><span class="o">(</span><span class="s">"memclass"</span><span class="o">,</span> <span class="s">"localhost"</span><span class="o">,</span> <span class="o">-</span><span class="mi">1</span><span class="o">,</span> <span class="s">"/"</span> <span class="o">+</span> <span class="n">newDynName</span><span class="o">.</span><span class="na">replace</span><span class="o">(</span><span class="sc">'/'</span><span class="o">,</span> <span class="sc">'.'</span><span class="o">)</span> <span class="o">+</span> <span class="s">"/"</span><span class="o">,</span> <span class="k">new</span> <span class="nf">URLStreamHandler</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="nd">@Override</span>
|
||||
<span class="kd">protected</span> <span class="n">URLConnection</span> <span class="nf">openConnection</span><span class="o">(</span><span class="n">URL</span> <span class="n">u</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="k">new</span> <span class="nf">URLConnection</span><span class="o">(</span><span class="n">u</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">connect</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="nd">@Override</span>
|
||||
<span class="kd">public</span> <span class="n">InputStream</span> <span class="nf">getInputStream</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">IOException</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="k">new</span> <span class="nf">ByteArrayInputStream</span><span class="o">(</span><span class="n">bytes</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">};</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">});</span>
|
||||
<span class="n">Method</span> <span class="n">addURLMethod</span> <span class="o">=</span> <span class="n">URLClassLoader</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">getDeclaredMethod</span><span class="o">(</span><span class="s">"addURL"</span><span class="o">,</span> <span class="n">URL</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
|
||||
<span class="n">addURLMethod</span><span class="o">.</span><span class="na">setAccessible</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>
|
||||
<span class="n">addURLMethod</span><span class="o">.</span><span class="na">invoke</span><span class="o">(</span><span class="n">urlLoader</span><span class="o">,</span> <span class="n">url</span><span class="o">);</span>
|
||||
<span class="n">resultClazz</span> <span class="o">=</span> <span class="n">urlLoader</span><span class="o">.</span><span class="na">loadClass</span><span class="o">(</span><span class="n">newDynName</span><span class="o">.</span><span class="na">replace</span><span class="o">(</span><span class="sc">'/'</span><span class="o">,</span> <span class="sc">'.'</span><span class="o">));</span>
|
||||
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="n">Throwable</span> <span class="n">t</span><span class="o">)</span> <span class="o">{</span> <span class="c1">//异常无需理会, 使用下一种loader方式</span>
|
||||
<span class="n">t</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
如上代码,构建一个虚拟协议的URL来实现加载,若Record.class的ClassLoader不是URLClassLoader导致resultClazz为null则会抛出异常。
|
||||
</p>
|
||||
<p>
|
||||
Creator是一个典型通过ASM构建一个简单功能地动态类,同类型还有 <a href="https://redkale.org/javadoc/org/redkale/util/Attribute.html" target="_blank">org.redkale.util.Attribute</a>、<a href="https://redkale.org/javadoc/org/redkale/util/Copier.html" target="_blank">org.redkale.util.Copier</a>。
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/article_source.html" target="_blank">https://redkale.org/article_creator.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
128
articles.html
@@ -1,128 +0,0 @@
|
||||
<!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">
|
||||
|
||||
<p style="display: none;" class="art-list">
|
||||
<a href="course11_sncp.html" target="_blank" class="art-title">Redkale 入门教程 11 -- SNCP分布式部署</a>
|
||||
<label class="art-date">2017-06</label><br/>
|
||||
<label class="art-desc">Redkale 入门教程 </label>
|
||||
</p>
|
||||
|
||||
<p style="display: none;" class="art-list">
|
||||
<a href="course10_websocket.html" target="_blank" class="art-title">Redkale 入门教程 10 -- WebSocket</a>
|
||||
<label class="art-date">2017-06</label><br/>
|
||||
<label class="art-desc">Redkale 入门教程 </label>
|
||||
</p>
|
||||
|
||||
<p style="display: none;" class="art-list">
|
||||
<a href="course09_fileup.html" target="_blank" class="art-title">Redkale 入门教程 09 -- 文件上传下载</a>
|
||||
<label class="art-date">2017-06</label><br/>
|
||||
<label class="art-desc">Redkale 入门教程 </label>
|
||||
</p>
|
||||
|
||||
<p style="display: none;" class="art-list">
|
||||
<a href="course08_httpservlet.html" target="_blank" class="art-title">Redkale 入门教程 08 -- HttpServlet</a>
|
||||
<label class="art-date">2017-06</label><br/>
|
||||
<label class="art-desc">Redkale 入门教程 </label>
|
||||
</p>
|
||||
|
||||
<p style="display: none;" class="art-list">
|
||||
<a href="course07_convert.html" target="_blank" class="art-title">Redkale 入门教程 07 -- Convert</a>
|
||||
<label class="art-date">2017-06</label><br/>
|
||||
<label class="art-desc">Redkale 入门教程 </label>
|
||||
</p>
|
||||
|
||||
<p style="display: none;" class="art-list">
|
||||
<a href="course06_dbdis.html" target="_blank" class="art-title">Redkale 入门教程 06 -- DataSource 分库分表</a>
|
||||
<label class="art-date">2017-06</label><br/>
|
||||
<label class="art-desc">Redkale 入门教程 </label>
|
||||
</p>
|
||||
|
||||
<p style="display: none;" class="art-list">
|
||||
<a href="course05_dbaction.html" target="_blank" class="art-title">Redkale 入门教程 05 -- DataSource 增删改查</a>
|
||||
<label class="art-date">2017-06</label><br/>
|
||||
<label class="art-desc">Redkale 入门教程 </label>
|
||||
</p>
|
||||
|
||||
<p style="display: none;" class="art-list">
|
||||
<a href="course04_cachedb.html" target="_blank" class="art-title">Redkale 入门教程 04 -- CacheSource缓存数据源</a>
|
||||
<label class="art-date">2017-06</label><br/>
|
||||
<label class="art-desc">Redkale 入门教程 </label>
|
||||
</p>
|
||||
|
||||
<p style="display: none;" class="art-list">
|
||||
<a href="course03_userauth.html" target="_blank" class="art-title">Redkale 入门教程 03 -- 用户鉴权</a>
|
||||
<label class="art-date">2017-06</label><br/>
|
||||
<label class="art-desc">Redkale 入门教程 </label>
|
||||
</p>
|
||||
|
||||
<p class="art-list">
|
||||
<a href="course02_rest.html" target="_blank" class="art-title">Redkale 入门教程 02 -- REST敏捷开发</a>
|
||||
<label class="art-date">2017-06</label><br/>
|
||||
<label class="art-desc">Redkale 入门教程 </label>
|
||||
</p>
|
||||
|
||||
<p class="art-list">
|
||||
<a href="course01_hello.html" target="_blank" class="art-title">Redkale 入门教程 01 -- Hello Word!</a>
|
||||
<label class="art-date">2017-06</label><br/>
|
||||
<label class="art-desc">Redkale 入门教程 </label>
|
||||
</p>
|
||||
|
||||
<p class="art-list">
|
||||
<a href="article_convert.html" target="_blank" class="art-title">Redkale 技术详解 03 -- Convert高性能序列化</a>
|
||||
<label class="art-date">2016-03</label><br/>
|
||||
<label class="art-desc">Convert是个重复造轮子的组件,却是个飞速的轮子。</label>
|
||||
</p>
|
||||
|
||||
<p class="art-list">
|
||||
<a href="article_creator.html" target="_blank" class="art-title">Redkale 技术详解 02 -- Creator构建对象</a>
|
||||
<label class="art-date">2016-02</label><br/>
|
||||
<label class="art-desc">org.redkale.util.Creator是采用ASM技术来实现代替反射构造函数的对象构建类。</label>
|
||||
</p>
|
||||
|
||||
<p class="art-list">
|
||||
<a href="article_parents.html" target="_blank" class="art-title">Redkale 技术详解 01 -- 双亲委托模型</a>
|
||||
<label class="art-date">2016-02</label><br/>
|
||||
<label class="art-desc">Redkale 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。</label>
|
||||
</p>
|
||||
|
||||
<br/>
|
||||
<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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
39
ban-ben-geng-xin.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# 版本更新
|
||||
|
||||
## v2.7.0 - 2022-07-07
|
||||
|
||||
### Fixed
|
||||
|
||||
* 修复 HttpResponse.finish 结果 status=404 时按 200 输出的 bug 
|
||||
* 修复 HttpMessageLocalClient 创建 request 时没有赋值给 currentUserid 值 
|
||||
* 修复 Rest.createRestServlet 带特定泛型问题 
|
||||
* 修复 Convert 模块中父类含 public field,subclass 不传父类会导致 NoSuchFieldError 的 bug 
|
||||
* 修复 ApiDocCommand 在没有运行时不能生成 doc 的 bug 
|
||||
* 修复 JsonWriter.writeWrapper 按 latin1 编码写的 bug 
|
||||
* 修复 JsonDynEncoder 在定制字段情况下会被全量字段的动态类覆盖的 bug
|
||||
|
||||
### Changed
|
||||
|
||||
* 优化 PrepareServlet 中 HttpRender 的初始化顺序 
|
||||
* 日志支持 java.util.logging.ConsoleHandler.denyreg 配置 
|
||||
* FilterColumn 支持 least=0 时空字符串也参与过滤 
|
||||
* HttpRequest 兼容参数名为空字符串 
|
||||
* 移除 CryptColumn、CryptHandler 功能 
|
||||
* PrepareServlet 更名为 DispatcherServlet 
|
||||
* @WebServlet 合并 url
|
||||
|
||||
### Added
|
||||
|
||||
* 增加 ConvertCoder 功能,可以自定义字段的序列化 
|
||||
* 增加 JsonMultiDecoder、JsonMultiObjectDecoder、OneOrList 功能 
|
||||
* JsonConvert 全面兼容 JSON5 
|
||||
* 增加 redkale 命令行 
|
||||
* 增加 HttpRpcAuthenticator 功能 
|
||||
* MessageAgent 增加配置 MessageCoder 功能 
|
||||
* 实现 LoggingSearchHandler 功能 
|
||||
* ConvertFactory 增加 mapFieldFunc、ignoreMapColumns 功能 
|
||||
* 增加 PropertiesAgent 功能
|
||||
* 增加链路 ID Traces 
|
||||
* 增加 ResourceListener.different 功能 
|
||||
* 增加 Environment 类 
|
||||
* 增加 RestLocale 功能
|
||||
2
cachesource-huan-cun-zu-jian.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# CacheSource缓存组件
|
||||
|
||||
2
client-zu-jian.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# Client 组件
|
||||
|
||||
2
clusteragent-fu-wu-zhu-ce-zhong-xin.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# ClusterAgent 服务注册中心
|
||||
|
||||
51
code.html
@@ -1,51 +0,0 @@
|
||||
<!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="code.html" class="btn">Java 源码</a>
|
||||
</section>
|
||||
|
||||
<section class="main-content">
|
||||
|
||||
<h3><a id="github" class="anchor" href="#" aria-hidden="true"></a>Github 源码</h3>
|
||||
|
||||
<p> <a href="https://github.com/redkale" target="_blank" >Redkale Github 源码</a></p>
|
||||
|
||||
<h3><a id="javadoc" class="anchor" href="#" aria-hidden="true"></a>Javadoc API</h3>
|
||||
|
||||
<p> <a href="javadoc/index.html" target="_blank" >在线 Javadoc API</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
2
convert-zu-jian.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# Convert 组件
|
||||
|
||||
413
convert.html
@@ -1,413 +0,0 @@
|
||||
<!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/normalize.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/stylesheet.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/github-light.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/highlight.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="convert_intro" class="anchor" href="#" aria-hidden="true"></a>Convert 组件介绍</h3>
|
||||
|
||||
<p> Convert 是一个比较独立的组件,仅依赖于util包。提供Java对象的序列化与反序列化功能。支持JSON、PROTOBUF两种格式化。 两种格式使用方式完全一样,其性能都大幅度超过其他JSON框架。同时JSON内置于HTTP服务中,PROTOBUF也是SNCP协议数据序列化的基础。<br/></p>
|
||||
|
||||
<h3><a id="convert_study" class="anchor" href="#" aria-hidden="true"></a>Convert 快速上手</h3>
|
||||
<p> 本介绍仅以JSON为例(PROTOBUF与JSON使用方式雷同)。其操作类主要是JsonConvert,配置类主要是JsonFactory、ConvertColumn。JsonFactory采用同ClassLoader类似的双亲委托方式设计。</br></p>
|
||||
<p> JsonConvert 序列化encode方法:</p>
|
||||
|
||||
<div class="highlight"><pre> <span class="kd">public</span> <span class="n">String</span> <span class="nf">convertTo</span><span class="o">(<span class="kd">final</span> </span><span class="n">Object</span> <span class="n">value</span><span class="o">);</span>
|
||||
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">convertTo</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">value</span><span class="o">);</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">convertTo</span><span class="o">(</span><span class="kd">final</span> <span class="n">OutputStream</span> <span class="n">out</span><span class="o">,</span> <span class="kd">final</span> <span class="n">Object</span> <span class="n">value</span><span class="o">);</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">convertTo</span><span class="o">(</span><span class="kd">final</span> <span class="n">OutputStream</span> <span class="n">out</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">value</span><span class="o">);</span>
|
||||
|
||||
<span class="kd">public</span> <span class="n">ByteBuffer</span><span class="o">[]</span> <span class="nf">convertTo</span><span class="o">(</span><span class="kd">final</span> <span class="n"><b>java.util.function.Supplier</b></span><span class="o"><</span><span class="n">ByteBuffer</span><span class="o">></span> <span class="n">supplier</span><span class="o">,</span> <span class="kd">final</span> <span class="n">Object</span> <span class="n">value</span><span class="o">);</span>
|
||||
|
||||
<span class="kd">public</span> <span class="n">ByteBuffer</span><span class="o">[]</span> <span class="nf">convertTo</span><span class="o">(</span><span class="kd">final</span> <span class="n"><b>java.util.function.Supplier</b></span><span class="o"><</span><span class="n">ByteBuffer</span><span class="o">></span> <span class="n">supplier</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">value</span><span class="o">);</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">convertTo</span><span class="o">(</span><span class="kd">final</span> <span class="n">JsonWriter</span> <span class="n">writer</span><span class="o">,</span> <span class="kd">final</span> <span class="n">Object</span> <span class="n">value</span><span class="o">);</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">convertTo</span><span class="o">(</span><span class="kd">final</span> <span class="n">JsonWriter</span> <span class="n">writer</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">value</span><span class="o">);</span></pre></div>
|
||||
|
||||
<p> JsonConvert 反序列化decode方法:</p>
|
||||
<div class="highlight"><pre> <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">convertFrom</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">String</span> <span class="n">text</span><span class="o">);</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">convertFrom</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="kt">char</span><span class="o">[]</span> <span class="n">text</span><span class="o">);</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">convertFrom</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="kt">char</span><span class="o">[]</span> <span class="n">text</span><span class="o">,</span> <span class="kd">final</span> <span class="kt">int</span> <span class="n">start</span><span class="o">,</span> <span class="kd">final</span> <span class="kt">int</span> <span class="n">len</span><span class="o">);</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">convertFrom</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">InputStream</span> <span class="n">in</span><span class="o">);</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">convertFrom</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">ByteBuffer</span><span class="o">...</span> <span class="n">buffers</span><span class="o">);</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">convertFrom</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">JsonReader</span> <span class="n">reader</span><span class="o">);</span></pre></div>
|
||||
|
||||
<p id="json_net_bytebuffer"> Convert 与 ByteBuffer 的结合 </p>
|
||||
<p> 从以上的方法可以看出,与其他JSON框架相比Convert多了与ByteBuffer结合的方法。特别是convertTo方法加了Supplier<ByteBuffer>方法,这么做是为了提高数据传输的性能。在大部分情况下JSON序列化得到的数据流是为了传输出去,常见的场景就是HTTP+JSON接口。Convert提供ByteBuffer接口会大量减少中间临时数据的产生。大部分输出JSON数据的方法如下:
|
||||
</p>
|
||||
<div class="highlight"><pre> <span class="kd">public</span> <span class="kt">void</span> <span class="nf">doPost</span><span class="o">(</span><span class="n">HttpServletRequest</span> <span class="n">req</span><span class="o">,</span> <span class="n">HttpServletResponse</span> <span class="n">resp</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">ServletException</span><span class="o">,</span> <span class="n">IOException</span> <span class="o">{</span>
|
||||
<span class="n">String</span> <span class="n">json</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Gson()</span><span class="o">.</span><span class="na">toJson</span><span class="o">(record);</span>
|
||||
<span class="n">resp</span><span class="o">.</span><span class="na">setContentType</span><span class="o">(</span><span class="s">"text/json; charset=UTF-8"</span><span class="o">);</span>
|
||||
<span class="n">resp</span><span class="o">.</span><span class="na">getOutputStream</span><span class="o">().</span><span class="na">write</span><span class="o">(</span><span class="n">json</span><span class="o">.</span><span class="na">getBytes</span><span class="o">(</span><span class="s">"UTF-8"</span><span class="o">));</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p> 几乎所有的JSON框架提供的接口以String作为返回结果为主,其内在都是以char[]作为JsonWriter的载体。以Gson为例,Gson拼接JSON默认使用的是StringWriter,StringWriter的扩容策略是翻倍。为了方便计算,假设一个对象转换成JSON字符串大小为了10K。Gson在转换过程中产生的临时的char[]的大小: 16 + 32 + 64 + 128 + 256 + 512 + 1K + 2K + 4K + 8K + 16K = 32K, char[]转换成最终的String结果又会产生10K的char[], 最后在response输出时又会产生10K的byte[](方便计算不考虑双字节),也就是说整个对象输出过程中会产生52K的临时数据。而且常见的HTTP服务器(如实现java-servlet规范的服务器)不会把底层的ByteBuffer对象池暴露给上层。所以以String为输出结果的JSON方法都会产生5倍于数据体积大小(其他低于1倍扩容策略的框架会产生更多)的垃圾数据。<br/>
|
||||
Redkale框架的HTTP服务内置了Convert的JSON接口,避免了大量的垃圾数据产生。Redkale的HTTP是基于AIO(NIO.2)实现且存在ByteBuffer对象池,response的finishJson系列方法将HTTP服务的ByteBuffer对象池传给Convert, 使Convert在序列化过程中直接以UTF-8编码方式输出到ByteBuffer里,输出结束后将ByteBuffer交给对象池回收,从而减少大量构建bye[]、char[]所产生的临时数据。</p>
|
||||
<div class="highlight"><pre> <span class="kd">protected</span> <span class="kt">void</span> <span class="nf">execute</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">resp</span><span class="o">.</span><span class="na">finishJson</span><span class="o">(</span><span class="n">record</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<br/>
|
||||
|
||||
<p id="convert_base"> Convert 基本用法:</p>
|
||||
<div class="highlight"><pre> <span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserRecord</span> <span class="o">{</span>
|
||||
|
||||
<span class="kd">private</span> <span class="kt">int</span> <span class="n">userid</span><span class="o">;</span>
|
||||
|
||||
<span class="kd">private</span> <span class="n">String</span> <span class="n">username</span> <span class="o">=</span> <span class="s">""</span><span class="o">;</span>
|
||||
|
||||
<span class="kd">private</span> <span class="n">String</span> <span class="n">password</span> <span class="o">=</span> <span class="s">""</span><span class="o">;</span>
|
||||
|
||||
<span class="kd">public</span> <span class="nf">UserRecord</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="o">/**</span> <span class="n">以下省略getter</span> <span class="n">setter方法</span> <span class="o">*/</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="n">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{</span>
|
||||
<span class="n">UserRecord</span> <span class="n">user</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">UserRecord</span><span class="o">();</span>
|
||||
<span class="n">user</span><span class="o">.</span><span class="na">setUserid</span><span class="o">(</span><span class="mi">100</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="s">"redkalename"</span><span class="o">);</span>
|
||||
<span class="n">user</span><span class="o">.</span><span class="na">setPassword</span><span class="o">(</span><span class="s">"123456"</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="n">JsonConvert</span><span class="o">.</span><span class="na">root</span><span class="o">();</span>
|
||||
<span class="n">String</span> <span class="n">json</span> <span class="o">=</span> <span class="n">convert</span><span class="o">.</span><span class="na">convertTo</span><span class="o">(</span><span class="n">user</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="n">json</span><span class="o">);</span> <span class="c1">//应该是 {"password":"123456","userid":100,"username":"redkalename"}</span>
|
||||
<span class="n">UserRecord</span> <span class="n">user2</span> <span class="o">=</span> <span class="n">convert</span><span class="o">.</span><span class="na">convertFrom</span><span class="o">(</span><span class="n">UserRecord</span><span class="o">.</span><span class="k">class</span><span class="o">,</span> <span class="n">json</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="n">convert</span><span class="o">.</span><span class="na">convertTo</span><span class="o">(</span><span class="n">user2</span><span class="o">));</span> <span class="c1">//应该也是 {"password":"123456","userid":100,"username":"redkalename"}</span>
|
||||
|
||||
<span class="cm">/**</span>
|
||||
<span class="cm"> * 以下功能是为了屏蔽password字段。</span>
|
||||
<span class="cm"> * 等价于 public String getPassword() 加上 @ConvertColumn :</span>
|
||||
<span class="cm"> *</span>
|
||||
<span class="cm"> * @ConvertColumn(ignore = true, type = ConvertType.JSON)</span>
|
||||
<span class="cm"> * public String getPassword() {</span>
|
||||
<span class="cm"> * return password;</span>
|
||||
<span class="cm"> * }</span>
|
||||
<span class="cm"> **/</span>
|
||||
<span class="kd">final</span> <span class="n">JsonFactory</span> <span class="n">childFactory</span> <span class="o">=</span> <span class="n">JsonFactory</span><span class="o">.</span><span class="na">root</span><span class="o">().</span><span class="na">createChild</span><span class="o">();</span>
|
||||
<span class="n">childFactory</span><span class="o">.</span><span class="na">register</span><span class="o">(</span><span class="n">UserRecord</span><span class="o">.</span><span class="k">class</span><span class="o">,</span> <span class="kc">true</span><span class="o">,</span> <span class="s">"password"</span><span class="o">);</span> <span class="c1">//屏蔽掉password字段使其不输出</span>
|
||||
<span class="n">childFactory</span><span class="o">.</span><span class="na">reloadCoder</span><span class="o">(</span><span class="n">UserRecord</span><span class="o">.</span><span class="k">class</span><span class="o">);</span> <span class="c1">//重新加载Coder使之覆盖父Factory的配置</span>
|
||||
<span class="kd">final</span> <span class="n">JsonConvert</span> <span class="n">childConvert</span> <span class="o">=</span> <span class="n">childFactory</span><span class="o">.</span><span class="na">getConvert</span><span class="o">();</span>
|
||||
<span class="n">json</span> <span class="o">=</span> <span class="n">childConvert</span><span class="o">.</span><span class="na">convertTo</span><span class="o">(</span><span class="n">user</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="n">json</span><span class="o">);</span> <span class="c1">//应该是 {"userid":100,"username":"redkalename"}</span>
|
||||
<span class="n">user2</span> <span class="o">=</span> <span class="n">childConvert</span><span class="o">.</span><span class="na">convertFrom</span><span class="o">(</span><span class="n">UserRecord</span><span class="o">.</span><span class="k">class</span><span class="o">,</span> <span class="n">json</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="n">childConvert</span><span class="o">.</span><span class="na">convertTo</span><span class="o">(</span><span class="n">user2</span><span class="o">));</span> <span class="c1">//应该也是 {"userid":100,"username":"redkalename"}</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p> 在Redkale里存在默认的JsonConvert、ProtobufConvert对象。 只需在所有Service、Servlet中增加依赖注入资源。</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">XXXService</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">JsonConvert</span> <span class="n">jsonConvert</span><span class="o">;</span>
|
||||
|
||||
<span class="nd">@Resource</span>
|
||||
<span class="kd">private</span> <span class="n">ProtobufConvert</span> <span class="n">protobufConvert</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">XXXServlet</span> <span class="kd">extends</span> <span class="n">HttpServlet</span> <span class="o">{</span>
|
||||
|
||||
<span class="nd">@Resource</span>
|
||||
<span class="kd">private</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">ProtobufConvert</span> <span class="n">protobufConvert</span><span class="o">;</span>
|
||||
|
||||
<span class="o">}</span>
|
||||
</pre></div>
|
||||
<p id="convert_diffout"> 同一类型数据通过设置新的JsonFactory可以有不同的输出。</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserSimpleInfo</span> <span class="o">{</span>
|
||||
|
||||
<span class="kd">private</span> <span class="kt">int</span> <span class="n">userid</span><span class="o">;</span>
|
||||
|
||||
<span class="kd">private</span> <span class="n">String</span> <span class="n">username</span> <span class="o">=</span> <span class="s">""</span><span class="o">;</span>
|
||||
|
||||
<span class="nd">@ConvertColumn</span><span class="o">(</span><span class="n">ignore</span> <span class="o">=</span> <span class="kc">true</span><span class="o">,</span> <span class="n">type</span> <span class="o">=</span> <span class="n">ConvertType</span><span class="o">.</span><span class="na">JSON</span><span class="o">)</span>
|
||||
<span class="kd">private</span> <span class="kt">long</span> <span class="n">regtime</span><span class="o">;</span> <span class="c1">//注册时间</span>
|
||||
|
||||
<span class="nd">@ConvertColumn</span><span class="o">(</span><span class="n">ignore</span> <span class="o">=</span> <span class="kc">true</span><span class="o">,</span> <span class="n">type</span> <span class="o">=</span> <span class="n">ConvertType</span><span class="o">.</span><span class="na">JSON</span><span class="o">)</span>
|
||||
<span class="kd">private</span> <span class="n">String</span> <span class="n">regaddr</span> <span class="o">=</span> <span class="s">""</span><span class="o">;</span> <span class="c1">//注册IP</span>
|
||||
|
||||
<span class="o">/**</span> <span class="n">以下省略getter</span> <span class="n">setter方法</span> <span class="o">*/</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
|
||||
|
||||
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserInfoServlet</span> <span class="kd">extends</span> <span class="n">HttpBaseServlet</span> <span class="o">{</span>
|
||||
|
||||
<span class="nd">@Resource</span>
|
||||
<span class="kd">private</span> <span class="n">UserSerice</span> <span class="n">service</span><span class="o">;</span>
|
||||
|
||||
<span class="nd">@Resource</span>
|
||||
<span class="kd">private</span> <span class="n">JsonFactory</span> <span class="n">jsonRootFactory</span><span class="o">;</span>
|
||||
|
||||
<span class="nd">@Resource</span>
|
||||
<span class="kd">private</span> <span class="n">JsonConvert</span> <span class="n">detailConvert</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">config</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="kd">final</span> <span class="n">JsonFactory</span> <span class="n">childFactory</span> <span class="o">=</span> <span class="n">jsonRootFactory</span><span class="o">.</span><span class="na">createChild</span><span class="o">();</span>
|
||||
<span class="n">childFactory</span><span class="o">.</span><span class="na">register</span><span class="o">(</span><span class="n">UserSimpleInfo</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="kc">false</span><span class="o">,</span> <span class="s">"regtime"</span><span class="o">,</span> <span class="s">"regaddr"</span><span class="o">);</span> <span class="c1">//允许输出注册时间与注册地址</span>
|
||||
<span class="n">childFactory</span><span class="o">.</span><span class="na">reloadCoder</span><span class="o">(</span><span class="n">UserSimpleInfo</span><span class="o">.</span><span class="na">class</span><span class="o">);</span> <span class="c1">//重新加载Coder使之覆盖父Factory的配置</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">detailConvert</span> <span class="o">=</span> <span class="n">childFactory</span><span class="o">.</span><span class="na">getConvert</span><span class="o">();</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="c1">// 获取他人基本信息</span>
|
||||
<span class="nd">@HttpMapping</span><span class="o">(</span><span class="n">url</span> <span class="o">=</span> <span class="s">"/user/info/"</span><span class="o">)</span>
|
||||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">info</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="kt">int</span> <span class="n">userid</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">UserSimpleInfo</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">userid</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">@HttpMapping</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">mydetail</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="kt">int</span> <span class="n">userid</span> <span class="o">=</span> <span class="n">req</span><span class="o">.</span><span class="n">currentUser</span><span class="o">().</span><span class="na">getUserid</span><span class="o">();</span> <span class="c1">//获取当前用户ID</span>
|
||||
<span class="n">UserSimpleInfo</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">userid</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">detailConvert</span><span class="o">,</span> <span class="n">user</span><span class="o">);</span> <span class="c1">// 包含用户的注册时间和注册地址字段信息</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
</pre></div>
|
||||
<br/>
|
||||
|
||||
<p> Convert 支持带参数构造函数。</p>
|
||||
<p> 1. <b>public</b> 带参数的构造函数加上 @ConstructorParameters 注解:</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserRecord</span> <span class="o">{</span>
|
||||
|
||||
<span class="kd">private</span> <span class="kt">int</span> <span class="n">userid</span><span class="o">;</span>
|
||||
|
||||
<span class="kd">private</span> <span class="n">String</span> <span class="n">username</span> <span class="o">=</span> <span class="s">""</span><span class="o">;</span>
|
||||
|
||||
<span class="kd">private</span> <span class="n">String</span> <span class="n">password</span> <span class="o">=</span> <span class="s">""</span><span class="o">;</span>
|
||||
|
||||
<span class="nd">@ConstructorParameters</span><span class="o">({</span><span class="s">"userid"</span><span class="o">,</span> <span class="s">"username"</span><span class="o">,</span> <span class="s">"password"</span><span class="o">})</span>
|
||||
<span class="kd">public</span> <span class="nf">UserRecord</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="n">String</span> <span class="n">password</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">userid</span> <span class="o">=</span> <span class="n">userid</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">username</span> <span class="o">=</span> <span class="n">username</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">password</span> <span class="o">=</span> <span class="n">password</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">getUserid</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">userid</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getUsername</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">username</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getPassword</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">password</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p> 2. 自定义Creator:</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">UserRecord</span> <span class="o">{</span>
|
||||
|
||||
<span class="kd">private</span> <span class="kt">int</span> <span class="n">userid</span><span class="o">;</span>
|
||||
|
||||
<span class="kd">private</span> <span class="n">String</span> <span class="n">username</span> <span class="o">=</span> <span class="s">""</span><span class="o">;</span>
|
||||
|
||||
<span class="kd">private</span> <span class="n">String</span> <span class="n">password</span> <span class="o">=</span> <span class="s">""</span><span class="o">;</span>
|
||||
|
||||
<span class="n">UserRecord</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="n">String</span> <span class="n">password</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">userid</span> <span class="o">=</span> <span class="n">userid</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">username</span> <span class="o">=</span> <span class="n">username</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">password</span> <span class="o">=</span> <span class="n">password</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">getUserid</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">userid</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getUsername</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">username</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getPassword</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">password</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="cm">/**</span>
|
||||
<span class="cm"> * 自定义Creator方法。</span>
|
||||
<span class="cm"> * 1) 方法名可以随意。</span>
|
||||
<span class="cm"> * 2) 方法必须是static。<b>声明为private的方法只能被当前类使用,若想方法被子类使用,需要声明protected</b></span>
|
||||
<span class="cm"> * 3)方法的参数必须为空。</span>
|
||||
<span class="cm"> * 4)方法的返回类型必须是Creator。</span>
|
||||
<span class="cm"> *</span>
|
||||
<span class="cm"> * @return</span>
|
||||
<span class="cm"> */</span>
|
||||
<span class="kd">private</span> <span class="kd">static</span> <span class="n">Creator</span><span class="o"><</span><span class="n">UserRecord</span><span class="o">></span> <span class="nf">creator</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="k">new</span> <span class="n">Creator</span><span class="o"><</span><span class="n">UserRecord</span><span class="o">>()</span> <span class="o">{</span>
|
||||
<span class="nd">@Override</span>
|
||||
<span class="nd">@ConstructorParameters</span><span class="o">({</span><span class="s">"userid"</span><span class="o">,</span> <span class="s">"username"</span><span class="o">,</span> <span class="s">"password"</span><span class="o">})</span> <span class="c1">//带参数的构造函数必须有ConstructorParameters注解</span>
|
||||
<span class="kd">public</span> <span class="n">UserRecord</span> <span class="nf">create</span><span class="o">(</span><span class="n">Object</span><span class="o">...</span> <span class="n">params</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="k">new</span> <span class="nf">UserRecord</span><span class="o">((</span><span class="n">params</span><span class="o">[</span><span class="mi">0</span><span class="o">]</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="o">(</span><span class="n">Integer</span><span class="o">)</span> <span class="n">params</span><span class="o">[</span><span class="mi">0</span><span class="o">]),</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span> <span class="n">params</span><span class="o">[</span><span class="mi">1</span><span class="o">],</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span> <span class="n">params</span><span class="o">[</span><span class="mi">2</span><span class="o">]);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">};</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
</pre></div>
|
||||
<p> 通常JavaBean类默认有个public空参数的构造函数,因此大部分情况下不要自定义Creator,其实只要不是private的空参数构造函数Convert都能自动支持(其他的框架都仅支持public的构造函数),只有仅含private的构造函数才需要自定义Creator。带参数的构造函数就需要标记@ConstructorParameters,常见于Immutable Object。<br/>
|
||||
<br/>
|
||||
|
||||
<p> Convert 支持自定义Decode、Encode。</p>
|
||||
<p> 1. 通过ConvertFactory显式的注册:</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">FileSimpleCoder</span><span class="o"><</span><span class="n">R</span> <span class="kd">extends</span> <span class="n">Reader</span><span class="o">,</span> <span class="n">W</span> <span class="kd">extends</span> <span class="n">Writer</span><span class="o">></span> <span class="kd">extends</span> <span class="n">SimpledCoder</span><span class="o"><</span><span class="n">R</span><span class="o">,</span> <span class="n">W</span><span class="o">,</span> <span class="n">File</span><span class="o">></span> <span class="o">{</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">FileSimpleCoder</span> <span class="n">instance</span> <span class="o">=</span> <span class="k">new</span> <span class="nf">FileSimpleCoder</span><span class="o">();</span>
|
||||
|
||||
<span class="nd">@Override</span>
|
||||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">convertTo</span><span class="o">(</span><span class="n">W</span> <span class="n">out</span><span class="o">,</span> <span class="n">File</span> <span class="n">value</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">out</span><span class="o">.</span><span class="na">writeString</span><span class="o">(</span><span class="n">value</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="n">value</span><span class="o">.</span><span class="na">getPath</span><span class="o">());</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="nd">@Override</span>
|
||||
<span class="kd">public</span> <span class="n">File</span> <span class="nf">convertFrom</span><span class="o">(</span><span class="n">R</span> <span class="n">in</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">String</span> <span class="n">path</span> <span class="o">=</span> <span class="n">in</span><span class="o">.</span><span class="na">readString</span><span class="o">();</span>
|
||||
<span class="k">return</span> <span class="n">path</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">new</span> <span class="nf">File</span><span class="o">(</span><span class="n">path</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="n">JsonFactory</span><span class="o">.</span><span class="na">root</span><span class="o">().</span><span class="na">register</span><span class="o">(</span><span class="n">java</span><span class="o">.</span><span class="na">io</span><span class="o">.</span><span class="na">File</span><span class="o">.</span><span class="kd">class</span><span class="o">,</span> <span class="n">FileSimpleCoder</span><span class="o">.</span><span class="na">instance</span><span class="o">);</span>
|
||||
|
||||
<span class="n">ProtobufFactory</span><span class="o">.</span><span class="na">root</span><span class="o">().</span><span class="na">register</span><span class="o">(</span><span class="n">java</span><span class="o">.</span><span class="na">io</span><span class="o">.</span><span class="na">File</span><span class="o">.</span><span class="kd">class</span><span class="o">,</span> <span class="n">FileSimpleCoder</span><span class="o">.</span><span class="na">instance</span><span class="o">);</span>
|
||||
</pre></div>
|
||||
|
||||
<p> 2. 通过JavaBean类自定义静态方法自动加载:</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">class</span> <span class="nc">InnerCoderEntity</span> <span class="o">{</span>
|
||||
|
||||
<span class="kd">private</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">val</span><span class="o">;</span>
|
||||
|
||||
<span class="kd">private</span> <span class="kd">final</span> <span class="kt">int</span> <span class="n">id</span><span class="o">;</span>
|
||||
|
||||
<span class="kd">private</span> <span class="nf">InnerCoderEntity</span><span class="o">(</span><span class="kt">int</span> <span class="n">id</span><span class="o">,</span> <span class="n">String</span> <span class="n">value</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">id</span> <span class="o">=</span> <span class="n">id</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">val</span> <span class="o">=</span> <span class="n">value</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kd">static</span> <span class="n">InnerCoderEntity</span> <span class="nf">create</span><span class="o">(</span><span class="kt">int</span> <span class="n">id</span><span class="o">,</span> <span class="n">String</span> <span class="n">value</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="k">new</span> <span class="nf">InnerCoderEntity</span><span class="o">(</span><span class="n">id</span><span class="o">,</span> <span class="n">value</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="cm">/**</span>
|
||||
<span class="cm"> * 该方法提供给Convert组件自动加载。</span>
|
||||
<span class="cm"> * 1) 方法名可以随意。</span>
|
||||
<span class="cm"> * 2) 方法必须是static</span>
|
||||
<span class="cm"> * 3)方法的参数有且只能有一个, 且必须是org.redkale.convert.ConvertFactory或子类。</span>
|
||||
<span class="cm"> * —3.1) 参数类型为org.redkale.convert.ConvertFactory 表示适合JSON和PROTOBUF。</span>
|
||||
<span class="cm"> * —3.2) 参数类型为org.redkale.convert.json.JsonFactory 表示仅适合JSON。</span>
|
||||
<span class="cm"> * —3.3) 参数类型为org.redkale.convert.pb.ProtobufFactory 表示仅适合PROTOBUF。</span>
|
||||
<span class="cm"> * 4)方法的返回类型必须是org.redkale.convert.Decodeable/org.redkale.convert.Encodeable/org.redkale.convert.SimpledCoder</span>
|
||||
<span class="cm"> * 若返回类型不是org.redkale.convert.SimpledCoder, 就必须提供两个方法: 一个返回Decodeable 一个返回 Encodeable。</span>
|
||||
<span class="cm"> *</span>
|
||||
<span class="cm"> * @param factory</span>
|
||||
<span class="cm"> * @return</span>
|
||||
<span class="cm"> */</span>
|
||||
<span class="kd">private</span> <span class="kd">static</span> <span class="n">SimpledCoder</span><span class="o"><</span><span class="n">Reader</span><span class="o">,</span> <span class="n">Writer</span><span class="o">,</span> <span class="n">InnerCoderEntity</span><span class="o">></span> <span class="nf">createConvertCoder</span><span class="o">(</span><span class="kd">final</span> <span class="n">org</span><span class="o">.</span><span class="na">redkale</span><span class="o">.</span><span class="na">convert</span><span class="o">.</span><span class="na">ConvertFactory</span> <span class="n">factory</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="k">new</span> <span class="n">SimpledCoder</span><span class="o"><</span><span class="n">Reader</span><span class="o">,</span> <span class="n">Writer</span><span class="o">,</span> <span class="n">InnerCoderEntity</span><span class="o">>()</span> <span class="o">{</span>
|
||||
|
||||
<span class="c1">//必须与EnMember[] 顺序一致</span>
|
||||
<span class="kd">private</span> <span class="kd">final</span> <span class="n">DeMember</span><span class="o">[]</span> <span class="n">deMembers</span> <span class="o">=</span> <span class="k">new</span> <span class="n">DeMember</span><span class="o">[]{</span>
|
||||
<span class="n">DeMember</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="n">factory</span><span class="o">,</span> <span class="n">InnerCoderEntity</span><span class="o">.</span><span class="k">class</span><span class="o">,</span> <span class="s">"id"</span><span class="o">),</span>
|
||||
<span class="n">DeMember</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="n">factory</span><span class="o">,</span> <span class="n">InnerCoderEntity</span><span class="o">.</span><span class="k">class</span><span class="o">,</span> <span class="s">"val"</span><span class="o">)};</span>
|
||||
|
||||
<span class="c1">//必须与DeMember[] 顺序一致</span>
|
||||
<span class="kd">private</span> <span class="kd">final</span> <span class="n">EnMember</span><span class="o">[]</span> <span class="n">enMembers</span> <span class="o">=</span> <span class="k">new</span> <span class="n">EnMember</span><span class="o">[]{</span>
|
||||
<span class="n">EnMember</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="n">factory</span><span class="o">,</span> <span class="n">InnerCoderEntity</span><span class="o">.</span><span class="k">class</span><span class="o">,</span> <span class="s">"id"</span><span class="o">),</span>
|
||||
<span class="n">EnMember</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="n">factory</span><span class="o">,</span> <span class="n">InnerCoderEntity</span><span class="o">.</span><span class="k">class</span><span class="o">,</span> <span class="s">"val"</span><span class="o">)};</span>
|
||||
|
||||
<span class="nd">@Override</span>
|
||||
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">convertTo</span><span class="o">(</span><span class="n">Writer</span> <span class="n">out</span><span class="o">,</span> <span class="n">InnerCoderEntity</span> <span class="n">value</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">value</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">out</span><span class="o">.</span><span class="na">writeObjectNull</span><span class="o">(</span><span class="n">InnerCoderEntity</span><span class="o">.</span><span class="k">class</span><span class="o">);</span>
|
||||
<span class="k">return</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
<span class="n">out</span><span class="o">.</span><span class="na">writeObjectB</span><span class="o">(</span><span class="n">value</span><span class="o">);</span>
|
||||
<span class="k">for</span> <span class="o">(</span><span class="n">EnMember</span> <span class="n">member</span> <span class="o">:</span> <span class="n">enMembers</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">out</span><span class="o">.</span><span class="na">writeObjectField</span><span class="o">(</span><span class="n">member</span><span class="o">,</span> <span class="n">value</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="n">out</span><span class="o">.</span><span class="na">writeObjectE</span><span class="o">(</span><span class="n">value</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="nd">@Override</span>
|
||||
<span class="kd">public</span> <span class="n">InnerCoderEntity</span> <span class="nf">convertFrom</span><span class="o">(</span><span class="n">Reader</span> <span class="n">in</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">in</span><span class="o">.</span><span class="na">readObjectB</span><span class="o">(</span><span class="n">InnerCoderEntity</span><span class="o">.</span><span class="k">class</span><span class="o">)</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="kt">int</span> <span class="n">index</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
|
||||
<span class="kd">final</span> <span class="n">Object</span><span class="o">[]</span> <span class="n">params</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Object</span><span class="o">[</span><span class="n">deMembers</span><span class="o">.</span><span class="na">length</span><span class="o">];</span>
|
||||
<span class="k">while</span> <span class="o">(</span><span class="n">in</span><span class="o">.</span><span class="na">hasNext</span><span class="o">())</span> <span class="o">{</span>
|
||||
<span class="n">DeMember</span> <span class="n">member</span> <span class="o">=</span> <span class="n">in</span><span class="o">.</span><span class="na">readFieldName</span><span class="o">(</span><span class="n">deMembers</span><span class="o">);</span> <span class="c1">//读取字段名</span>
|
||||
<span class="n">in</span><span class="o">.</span><span class="na">readBlank</span><span class="o">();</span> <span class="c1">//读取字段名与字段值之间的间隔符,JSON则是跳过冒号:</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">member</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">in</span><span class="o">.</span><span class="na">skipValue</span><span class="o">();</span> <span class="c1">//跳过不存在的字段的值, 一般不会发生</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
|
||||
<span class="n">params</span><span class="o">[</span><span class="n">index</span><span class="o">++]</span> <span class="o">=</span> <span class="n">member</span><span class="o">.</span><span class="na">read</span><span class="o">(</span><span class="n">in</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
<span class="n">in</span><span class="o">.</span><span class="na">readObjectE</span><span class="o">(</span><span class="n">InnerCoderEntity</span><span class="o">.</span><span class="k">class</span><span class="o">);</span>
|
||||
<span class="k">return</span> <span class="n">InnerCoderEntity</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="n">params</span><span class="o">[</span><span class="mi">0</span><span class="o">]</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="o">(</span><span class="n">Integer</span><span class="o">)</span> <span class="n">params</span><span class="o">[</span><span class="mi">0</span><span class="o">],</span> <span class="o">(</span><span class="n">String</span><span class="o">)</span> <span class="n">params</span><span class="o">[</span><span class="mi">1</span><span class="o">]);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">};</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="kt">int</span> <span class="nf">getId</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">id</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">getVal</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">val</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="nd">@Override</span>
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">toString</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">JsonConvert</span><span class="o">.</span><span class="na">root</span><span class="o">().</span><span class="na">convertTo</span><span class="o">(</span><span class="k">this</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="o">}</span>
|
||||
</pre></div>
|
||||
<p> 由上可以看出,Convert的自定义配置完全符合面向对象思想,提倡在JavaBean内部去自定义非常规的构造函数或Decode、Encode方法,通过ConvertFactory显式配置的方式通常用于非自己定义的数据类(如 java.io.File)。</p>
|
||||
<br/>
|
||||
|
||||
<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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,177 +0,0 @@
|
||||
<!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>Redkale 入门教程 01 -- Hello Word!</h3>
|
||||
|
||||
<p>
|
||||
<a href="index.html" target="_blank">Redkale</a> 可以说是Java界最精简的框架,不到1M的jar包可以替代Tomcat、Spring/Spring Boot、Hibernate/MyBatis、JackJson/fastjson、Netty的集合,四两拨千斤。低调开源一年多,经过两次大的改善后终于达到让自己满意的地步。Redkale不仅仅提供简易的API,还附有很多不同于传统思维的设计思路。由于时间有限,一年多也没写入门教程,现在开始抽点时间写一些教程,希望能给想学Redkale的同学一点帮助。 废话不多说,下面进入正题。<br/>
|
||||
</p>
|
||||
|
||||
<p>下载Redkale</p>
|
||||
<p>
|
||||
源码可以从 <a href="https://github.com/redkale" target="_blank" >https://github.com/redkale</a> 和 <a href="http://git.oschina.net/redkale/redkale" target="_blank" >http://git.oschina.net/redkale/redkale</a> 下载 。<br/>
|
||||
jar包可以从 <a href="http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.redkale%22%20AND%20a%3A%22redkale%22" target="_blank" >http://search.maven.org</a> 和 <a href="https://repo1.maven.org/maven2/org/redkale/redkale/" target="_blank" >https://repo1.maven.org/maven2/org/redkale/redkale/</a> 下载最新版本的包。<br/>
|
||||
当前最新版为 1.8, 下载 redkale-1.8.0.tar.gz 放在本地。<br/>
|
||||
</p>
|
||||
|
||||
<p>创建工程</p>
|
||||
<p>
|
||||
本人使用NetBeans很多年了,所以本教程以NetBeans来创建工程, 使用Eclipse的同学请自行参考。
|
||||
</p>
|
||||
<p>
|
||||
IntelliJ IDEA 使用者见 <a href="course01_helloidea.html">Redkale 入门教程 01 -- Hello Word!(IntelliJ IDEA Maven版)</a>。
|
||||
|
||||
</p>
|
||||
<p>
|
||||
首先创建一个"<b>Java应用程序</b>"项目, 注意: 不管是否Web项目,都不要创建Web应用程序。
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/hello_01.png" alt=""/><img src="images/hello_02.png" alt=""/></p>
|
||||
<p>
|
||||
创建完空项目后,将 redkale-1.8.0.tar.gz 解压覆盖到项目的目录下。
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/hello_03.png" alt=""/><img src="images/hello_04.png" alt=""/></p>
|
||||
<p>
|
||||
点击项目右键进入“属性”-> “库”中,点击 “添加JAR/文件夹”找到项目lib目录下的redkale-1.8.0.jar 并导入。
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/hello_05.png" alt=""/><img src="images/hello_06.png" alt=""/></p>
|
||||
<p>
|
||||
点击“源”,在下面测试包中导入项目目录下的conf目录,这样方便编辑conf下的配置文件(在上面src中导入会打包进jar中)。
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/hello_07.png" alt=""/></p>
|
||||
<p>
|
||||
点击“运行”,在主类中输入 "<b>org.redkale.boot.Application</b>",然后点击“确定”。
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/hello_08.png" alt=""/></p>
|
||||
<p>
|
||||
编写HelloService类。
|
||||
</p>
|
||||
<div class="highlight"><pre><span></span><span class="kn">package</span> <span class="n">com.redkale.demo</span><span class="o">;</span>
|
||||
|
||||
<span class="kn">import</span> <span class="n">org.redkale.net.http.*</span><span class="o">;</span>
|
||||
<span class="kn">import</span> <span class="n">org.redkale.service.Service</span><span class="o">;</span>
|
||||
|
||||
<span class="nd">@RestService</span><span class="o">(</span><span class="n">automapping</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">HelloService</span> <span class="kd">implements</span> <span class="n">Service</span> <span class="o">{</span>
|
||||
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">sayHello</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="s">"Hello World!"</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">hi</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="s">"Hi, "</span> <span class="o">+</span> <span class="n">name</span> <span class="o">+</span> <span class="s">"!"</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
此类提供两个方法:say 和 hi。编写完后按"<b>F6</b>" 直接运行。
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/hello_09.png" alt=""/></p>
|
||||
<p>
|
||||
在浏览器输入: http://127.0.0.1:6060/pipes/hello/say 可以看到结果:
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/hello_10.png" alt=""/></p>
|
||||
<p>
|
||||
在浏览器输入: http://127.0.0.1:6060/pipes/hello/hi?name=Redkale 可以看到结果:
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/hello_11.png" alt=""/></p>
|
||||
<p>
|
||||
访问地址的端口6060和前缀pipes是通过conf/application.xml文件进行配置:
|
||||
</p>
|
||||
<div class="highlight"><pre><span></span><span class="p"><</span><span class="nt">application</span> <span class="na">port</span><span class="o">=</span><span class="s">"5050"</span><span class="p">></span>
|
||||
|
||||
<span class="c"><!-- 详细配置说明见: http://redkale.org/redkale.html#redkale_confxml --></span>
|
||||
|
||||
<span class="p"><</span><span class="nt">resources</span><span class="p">></span>
|
||||
<span class="c"><!-- </span>
|
||||
<span class="c"> <properties></span>
|
||||
<span class="c"> <property name="system.property.convert.json.tiny" value="true"/></span>
|
||||
<span class="c"> </properties></span>
|
||||
<span class="c"> --></span>
|
||||
<span class="p"></</span><span class="nt">resources</span><span class="p">></span>
|
||||
|
||||
<span class="p"><</span><span class="nt">server</span> <span class="na">protocol</span><span class="o">=</span><span class="s">"HTTP"</span> <span class="na">host</span><span class="o">=</span><span class="s">"0.0.0.0"</span> <span class="na">port</span><span class="o">=</span><span class="s">"6060"</span> <span class="na">root</span><span class="o">=</span><span class="s">"root"</span><span class="p">></span>
|
||||
|
||||
<span class="p"><</span><span class="nt">services</span> <span class="na">autoload</span><span class="o">=</span><span class="s">"true"</span><span class="p">/></span>
|
||||
|
||||
<span class="c"><!-- base指定的自定义HttpServlet子类必须标记@HttpUserType, 不设置base则视为没有当前用户信息设置 --></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">autoload</span><span class="o">=</span><span class="s">"true"</span> <span class="p">/></span>
|
||||
|
||||
<span class="p"><</span><span class="nt">servlets</span> <span class="na">path</span><span class="o">=</span><span class="s">"/pipes"</span> <span class="na">autoload</span><span class="o">=</span><span class="s">"true"</span> <span class="p">/></span>
|
||||
|
||||
<span class="p"></</span><span class="nt">server</span><span class="p">></span>
|
||||
|
||||
<span class="p"></</span><span class="nt">application</span><span class="p">></span>
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
至此,一个简单的Hello服务就开发和调试完成了。可以看出,代码简单很多,不需要太多配置、maven和其他依赖包。<br>
|
||||
可能有人会疑惑: HelloServie为什么能分配到hello前缀? sayHello为什么会映射到/pipes/hello/say 请求? Redkale为了减少Annotation配置采取了一些默认值的策略, 在Redkale里, 一个Service视为一个模块或服务,所以需要有模块(服务)名的概念,用于服务管理和鉴权,通常需要通过@RestServie.name来指定模块名,没有指定则默认将Service类名的Service字样之前的字符串视为模块名,如HelloService和HelloServiceImpl都会采用hello作为模块名。方法名的默认值策略也是类似,将模块名字样之前的字符串作为方法名,如sayHello和sayHelloMe 都会用say作为默认值。参数名如果没有指定@RestParam.name会自动采用代码的变量名。 完全标记Rest注解的HelloService源码如下:
|
||||
</p>
|
||||
<div class="highlight"><pre><span></span><span class="kn">package</span> <span class="n">com.redkale.demo</span><span class="o">;</span>
|
||||
|
||||
<span class="kn">import</span> <span class="n">org.redkale.net.http.*</span><span class="o">;</span>
|
||||
<span class="kn">import</span> <span class="n">org.redkale.service.Service</span><span class="o">;</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="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">@RestMapping</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"say"</span><span class="o">)</span>
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">sayHello</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="s">"Hello World!"</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="nd">@RestMapping</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"hi"</span><span class="o">)</span>
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">hi</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">"name"</span><span class="o">)</span> <span class="n">String</span> <span class="n">name</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="s">"Hi, "</span> <span class="o">+</span> <span class="n">name</span> <span class="o">+</span> <span class="s">"!"</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="o">}</span>
|
||||
</pre></div>
|
||||
<br/>
|
||||
<p>
|
||||
这段代码与上面那段是等价的。部署也很简单, 将项目目录中dist目录下的redkale-demo.jar复制到lib下,运行bin/start.bat 即可启动HTTP服务。
|
||||
</p>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/course01_hello.html" target="_blank">https://redkale.org/course01_hello.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,164 +0,0 @@
|
||||
<!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>Redkale 入门教程 01 -- Hello Word!(IntelliJ IDEA Maven版)</h3>
|
||||
|
||||
<p>
|
||||
<a href="index.html" target="_blank">Redkale</a> 可以说是Java界最精简的框架,不到1M的jar包可以替代Tomcat、Spring/Spring Boot、Hibernate/MyBatis、JackJson/fastjson、Netty的集合,四两拨千斤。低调开源一年多,经过两次大的改善后终于达到让自己满意的地步。Redkale不仅仅提供简易的API,还附有很多不同于传统思维的设计思路。由于时间有限,一年多也没写入门教程,现在开始抽点时间写一些教程,希望能给想学Redkale的同学一点帮助。 废话不多说,下面进入正题。<br/>
|
||||
</p>
|
||||
|
||||
<p>创建工程</p>
|
||||
<p>
|
||||
首先创建一个Maven项目。
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/hello_21.png" alt=""/><img src="images/hello_22.png" alt=""/></p>
|
||||
<p style="text-align: center;"><img src="images/hello_23.png" alt=""/><img src="images/hello_24.png" alt=""/></p>
|
||||
<p>
|
||||
创建完项目后会自动打开pom.xml文件, 按下Alt+Insert组合键添加redkale依赖。
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/hello_25.png" alt=""/><img src="images/hello_26.png" alt=""/></p>
|
||||
<p>
|
||||
然后将redkale下的bin和conf文件夹(可以通过github或者maven里<a href="https://repo1.maven.org/maven2/org/redkale/redkale/1.9.5/redkale-1.9.5.tar.gz" target="_blank">redkale-1.9.5.tar.gz</a>解压得到)复制到工程的目录下。
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/hello_27.png" alt=""/></p>
|
||||
<p>
|
||||
编写HelloService类。
|
||||
</p>
|
||||
<div class="highlight"><pre><span></span><span class="kn">package</span> <span class="n">com.redkale.examples.hello</span><span class="o">;</span>
|
||||
|
||||
<span class="kn">import</span> <span class="n">org.redkale.net.http.*</span><span class="o">;</span>
|
||||
<span class="kn">import</span> <span class="n">org.redkale.service.Service</span><span class="o">;</span>
|
||||
|
||||
<span class="nd">@RestService</span><span class="o">(</span><span class="n">automapping</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">HelloService</span> <span class="kd">implements</span> <span class="n">Service</span> <span class="o">{</span>
|
||||
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">sayHello</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="s">"Hello World!"</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">hi</span><span class="o">(</span><span class="n">String</span> <span class="n">name</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="s">"Hi, "</span> <span class="o">+</span> <span class="n">name</span> <span class="o">+</span> <span class="s">"!"</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
</pre></div>
|
||||
<p style="text-align: center;"><img src="images/hello_28.png" alt=""/></p>
|
||||
|
||||
<p>
|
||||
然后开始调试运行。
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/hello_29.png" alt=""/></p>
|
||||
<p style="text-align: center;"><img src="images/hello_30.png" alt=""/></p>
|
||||
<p style="text-align: center;"><img src="images/hello_31.png" alt=""/></p>
|
||||
<p style="text-align: center;"><img src="images/hello_32.png" alt=""/></p>
|
||||
<p style="text-align: center;"><img src="images/hello_33.png" alt=""/></p>
|
||||
<p>
|
||||
在浏览器输入: http://127.0.0.1:6060/pipes/hello/say 可以看到结果:
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/hello_34.png" alt=""/></p>
|
||||
<p>
|
||||
在浏览器输入: http://127.0.0.1:6060/pipes/hello/hi?name=Redkale 可以看到结果:
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/hello_35.png" alt=""/></p>
|
||||
<p>
|
||||
访问地址的端口6060和前缀pipes是通过conf/application.xml文件进行配置:
|
||||
</p>
|
||||
<div class="highlight"><pre><span></span><span class="p"><</span><span class="nt">application</span> <span class="na">port</span><span class="o">=</span><span class="s">"2121"</span><span class="p">></span>
|
||||
|
||||
<span class="c"><!-- 详细配置说明见: http://redkale.org/redkale.html#redkale_confxml --></span>
|
||||
|
||||
<span class="p"><</span><span class="nt">resources</span><span class="p">></span>
|
||||
<span class="c"><!-- </span>
|
||||
<span class="c"> <properties></span>
|
||||
<span class="c"> <property name="system.property.convert.json.tiny" value="true"/></span>
|
||||
<span class="c"> </properties></span>
|
||||
<span class="c"> --></span>
|
||||
<span class="p"></</span><span class="nt">resources</span><span class="p">></span>
|
||||
|
||||
<span class="p"><</span><span class="nt">server</span> <span class="na">protocol</span><span class="o">=</span><span class="s">"HTTP"</span> <span class="na">host</span><span class="o">=</span><span class="s">"0.0.0.0"</span> <span class="na">port</span><span class="o">=</span><span class="s">"6060"</span> <span class="na">root</span><span class="o">=</span><span class="s">"root"</span><span class="p">></span>
|
||||
|
||||
<span class="p"><</span><span class="nt">services</span> <span class="na">autoload</span><span class="o">=</span><span class="s">"true"</span><span class="p">/></span>
|
||||
|
||||
<span class="c"><!-- base指定的自定义HttpServlet子类必须标记@HttpUserType, 不设置base则视为没有当前用户信息设置 --></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">autoload</span><span class="o">=</span><span class="s">"true"</span> <span class="p">/></span>
|
||||
|
||||
<span class="p"><</span><span class="nt">servlets</span> <span class="na">path</span><span class="o">=</span><span class="s">"/pipes"</span> <span class="na">autoload</span><span class="o">=</span><span class="s">"true"</span> <span class="p">/></span>
|
||||
|
||||
<span class="p"></</span><span class="nt">server</span><span class="p">></span>
|
||||
|
||||
<span class="p"></</span><span class="nt">application</span><span class="p">></span>
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
至此,一个简单的Hello服务就开发和调试完成了。可以看出,代码简单很多,不需要太多配置、maven和其他依赖包。<br>
|
||||
可能有人会疑惑: HelloServie为什么能分配到hello前缀? sayHello为什么会映射到/pipes/hello/say 请求? Redkale为了减少Annotation配置采取了一些默认值的策略, 在Redkale里, 一个Service视为一个模块或服务,所以需要有模块(服务)名的概念,用于服务管理和鉴权,通常需要通过@RestServie.name来指定模块名,没有指定则默认将Service类名的Service字样之前的字符串视为模块名,如HelloService和HelloServiceImpl都会采用hello作为模块名。方法名的默认值策略也是类似,将模块名字样之前的字符串作为方法名,如sayHello和sayHelloMe 都会用say作为默认值。参数名如果没有指定@RestParam.name会自动采用代码的变量名。 完全标记Rest注解的HelloService源码如下:
|
||||
</p>
|
||||
<div class="highlight"><pre><span></span><span class="kn">package</span> <span class="n">com.redkale.examples.hello</span><span class="o">;</span>
|
||||
|
||||
<span class="kn">import</span> <span class="n">org.redkale.net.http.*</span><span class="o">;</span>
|
||||
<span class="kn">import</span> <span class="n">org.redkale.service.Service</span><span class="o">;</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="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">@RestMapping</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"say"</span><span class="o">)</span>
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">sayHello</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="s">"Hello World!"</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="nd">@RestMapping</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"hi"</span><span class="o">)</span>
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">hi</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">"name"</span><span class="o">)</span> <span class="n">String</span> <span class="n">name</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="s">"Hi, "</span> <span class="o">+</span> <span class="n">name</span> <span class="o">+</span> <span class="s">"!"</span><span class="o">;</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="o">}</span>
|
||||
</pre></div>
|
||||
<br/>
|
||||
<p>
|
||||
这段代码与上面那段是等价的。部署也很简单, 将项目编译后的jar和redkale-1.9.5.jar复制到lib下(也可通过修改pom.xml让maven来处理),运行bin/start.bat 即可启动HTTP服务。
|
||||
</p>
|
||||
<p>
|
||||
本工程源码可以在 <a href="https://github.com/redkale/redkale-examples/tree/master/redkale-helloword" target="_blank">https://github.com/redkale/redkale-examples/tree/master/redkale-helloword</a> 下载。
|
||||
</p>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/course01_helloidea.html" target="_blank">https://redkale.org/course01_helloidea.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,111 +0,0 @@
|
||||
<!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>Redkale 入门教程 02 -- DataSource 连接</h3>
|
||||
|
||||
<p>
|
||||
<a href="index.html" target="_blank">Redkale</a> 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。<br/>
|
||||
</p>
|
||||
|
||||
<p>ClassLoader类加载</p>
|
||||
<p>
|
||||
双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。<br/>
|
||||
ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
|
||||
</p>
|
||||
|
||||
<p>Redkale 双亲委托</p>
|
||||
<p>
|
||||
ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">findEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">rs</span> <span class="o">=</span> <span class="o">(</span><span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">>)</span> <span class="n">encoders</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">rs</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">rs</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">parent</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">parent</span><span class="o">.</span><span class="na">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">loadEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">GenericArrayType</span><span class="o">)</span> <span class="k">return</span> <span class="k">new</span> <span class="nf">ArrayEncoder</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">type</span><span class="o">);</span>
|
||||
<span class="n">Class</span> <span class="n">clazz</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">ParameterizedType</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="kd">final</span> <span class="n">ParameterizedType</span> <span class="n">pts</span> <span class="o">=</span> <span class="o">(</span><span class="n">ParameterizedType</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="o">(</span><span class="n">pts</span><span class="o">).</span><span class="na">getRawType</span><span class="o">();</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">TypeVariable</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">TypeVariable</span> <span class="n">tv</span> <span class="o">=</span> <span class="o">(</span><span class="n">TypeVariable</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">Type</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">().</span><span class="na">length</span> <span class="o">==</span> <span class="mi">1</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">t</span> <span class="o">=</span> <span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">()[</span><span class="mi">0</span><span class="o">];</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(!(</span><span class="n">t</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">))</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</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="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConvertException</span><span class="o">(</span><span class="s">"not support the type ("</span> <span class="o">+</span> <span class="n">type</span> <span class="o">+</span> <span class="s">")"</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="nf">createEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">,</span> <span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 <a href="convert.html#convert_base" target="_blank">Convert基本用法</a> 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。
|
||||
</p>
|
||||
<p>
|
||||
Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="nf">NodeServer</span><span class="o">(</span><span class="n">Application</span> <span class="n">application</span><span class="o">,</span> <span class="n">Server</span> <span class="n">server</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">application</span> <span class="o">=</span> <span class="n">application</span><span class="o">;</span>
|
||||
<b><span class="k">this</span><span class="o">.</span><span class="na">resourceFactory</span> <span class="o">=</span> <span class="n">application</span><span class="o">.</span><span class="na">getResourceFactory</span><span class="o">().</span><span class="na">createChild</span><span class="o">();</span></b>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">server</span> <span class="o">=</span> <span class="n">server</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">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="o">}</span></pre></div>
|
||||
<p>
|
||||
双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/article_parents.html" target="_blank">https://redkale.org/article_parents.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,218 +0,0 @@
|
||||
<!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>Redkale 入门教程 02 -- REST敏捷开发</h3>
|
||||
|
||||
<p>
|
||||
REST是 <a href="index.html" target="_blank">Redkale</a> 的主要功能之一,REST提供的功能是根据Service自动生成HttpServlet,需要注意的是 <b>Redkale里的REST与标准的RESTfull规范完全不同,仅仅名称类似</b>。标准的REST规范比较死板,只是在请求URL和Method上做文章,功能单一。Redkale里的REST功能是很强大的, 无论登陆、鉴权、文件上传下载、WebSocket都可以REST化,几乎完全可以省去HttpServlet。<br/>
|
||||
</p>
|
||||
|
||||
<table style="margin: auto;">
|
||||
<tr><th>注解类名</th><th>功能描述</th></tr>
|
||||
<tr><td style="text-align: left;">@RestService</td><td>标记Service需要REST化。</td></tr>
|
||||
<tr><td style="text-align: left;">@RestMapping</td><td>标记请求的方法名,同一方法上可重复标记(需确保name值在Service中是唯一的)。<br><b>其标记的Service方法只能throws IOException或不抛异常</b>。</td></tr>
|
||||
<tr><td style="text-align: left;">@RestConvert</td><td>标记请求的方法名上,对返回值以JSON形式输出时进行字段的屏蔽或开启进行设置</b>。</td></tr>
|
||||
<tr><td style="text-align: left;">@RestConvertCoder</td><td>标记请求的方法名上,对返回值以JSON形式输出时对类指定的字段的进行设置</b>。</td></tr>
|
||||
<tr><td style="text-align: left;">@RestParam</td><td>获取常规参数值, 字段类型可以是 基础数据类型/Flipper/CompletionHandler/String/JavaBean<br>name='&' 表示当前用户(@HttpUserType)<br>name='#' 表示截取uri最后一段<br>name='#xxx:' 表示从uri中/pipes/xxx:v/截取xxx:的值</td></tr>
|
||||
<tr><td style="text-align: left;">@RestHeader</td><td>通过request.getHeader获取参数值, 字段类型只能是String</td></tr>
|
||||
<tr><td style="text-align: left;">@RestCookie</td><td>通过request.getCookie获取Cookie值, 字段类型只能是String</td></tr>
|
||||
<tr><td style="text-align: left;">@RestBody<td>通过request.getBody获取参数值, 字段类型只能是String/byte[]/JavaBean</td></tr>
|
||||
<tr><td style="text-align: left;">@RestSessionid<td>获取sessionid, 字段类型只能是String</td></tr>
|
||||
<tr><td style="text-align: left;">@RestAddress<td>获取客户端IP地址, 字段类型只能是String</td></tr>
|
||||
<tr><td style="text-align: left;">@RestURI</td><td>获取请求URL, 字段类型只能是String</td></tr>
|
||||
<tr><td style="text-align: left;">@RestUploadFile</td><td>获取上传文件, 字段类型只能是File/File[]/byte[]</td></tr>
|
||||
<tr><td style="text-align: center;font-size: 0.9rem;" colspan="2"><b>WebSocket</b></td></tr>
|
||||
<tr><td style="text-align: left;">@RestWebSocket</td><td>标记WebSocket需要REST化,只能标记在WebSocket的子类上</td></tr>
|
||||
<tr><td style="text-align: left;">@RestOnMessage</td><td>WebSocket的消息路由,类似@RestMapping,不同的请求映射到不同的方法</td></tr>
|
||||
</table>
|
||||
<p>
|
||||
标记@RestService的Service对象在服务启动时会自动生成原始的HttpServlet加载到当前的HttpServer中,其HttpServlet的请求URL规则为:path + "/" + @RestService.catalog() + "/" + @RestService.name() + "/*", 其中path为application.xml文件中<rest>节点的path属性值。节点rest和servlets设计一个path属性是为了所有动态请求加个前缀方便静动分离,没有采取.jsp .do那种刷存在感的后缀方式也是处于安全考虑,外界根据URL无法判断后台使用的是什么语言或框架开发。<br/>
|
||||
REST会根据Service方法的返回类型不同做出不同的结果输出。
|
||||
<table style="margin: auto;">
|
||||
<tr><th>返回类型</th><th>功能描述</th></tr>
|
||||
<tr><td style="text-align: left;">void</td><td>以RetResult.success()的JSON形式输出。</td></tr>
|
||||
<tr><td style="text-align: left;">String</td><td>以字符串输出。</td></tr>
|
||||
<tr><td style="text-align: left;">File</td><td>以下载文件形式输出。</td></tr>
|
||||
<tr><td style="text-align: left;">HttpResult</td><td>将HttpHeader、HttpCookie、Result统一输出</td></tr>
|
||||
<tr><td style="text-align: left;">CompletableFuture<td>异步输出,根据CompletableFuture.get()结果类型进行不同形式输出</td></tr>
|
||||
<tr><td style="text-align: left;">JavaBean/其他<td>以JSON形式输出</td></tr>
|
||||
</table>
|
||||
</p>
|
||||
<p>
|
||||
要开启REST功能需要在application.xml对应的HttpServer下加入rest节点:
|
||||
</p>
|
||||
<p style="text-align: center;"><img src="images/rest_01.png" alt=""/></p>
|
||||
<p>
|
||||
如果需要加入鉴权功能更,需要自定义HttpServlet基类,并重载preExecute、authenticate方法。详情见 <a href="http://redkale.org/net.html#baseservlet">BaseHttpServlet</a>
|
||||
</p>
|
||||
<p>用户登陆范例</p>
|
||||
<div class="highlight"><pre><span></span><span class="nd">@RestService</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"user"</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="kd">class</span> <span class="nc">UserService</span> <span class="kd">extends</span> <span class="n">AbstractService</span> <span class="o">{</span>
|
||||
|
||||
<span class="nd">@RestMapping</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"login"</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">"用户登陆"</span><span class="o">)</span>
|
||||
<span class="kd">public</span> <span class="n">RetResult</span> <span class="nf">login</span><span class="o">(</span><span class="n">String</span> <span class="n">account</span><span class="o">,</span> <span class="n">String</span> <span class="n">password</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="n">String</span> <span class="n">agent</span><span class="o">,</span>
|
||||
<span class="nd">@RestSessionid</span><span class="o">(</span><span class="n">create</span> <span class="o">=</span> <span class="kc">true</span><span class="o">)</span> <span class="n">String</span> <span class="n">sessionid</span><span class="o">,</span> <span class="nd">@RestAddress</span> <span class="n">String</span> <span class="n">clientAddr</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">if</span> <span class="o">(!</span><span class="s">"redkale"</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">account</span><span class="o">))</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="mi">1001</span><span class="o">,</span> <span class="s">"账号不是redkale"</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(!</span><span class="s">"123456"</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">password</span><span class="o">))</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="mi">1002</span><span class="o">,</span> <span class="s">"密码错误"</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">"用户("</span> <span class="o">+</span> <span class="n">account</span> <span class="o">+</span> <span class="s">")的回话ID为: "</span> <span class="o">+</span> <span class="n">sessionid</span> <span class="o">+</span> <span class="s">", 通过客户端("</span> <span class="o">+</span> <span class="n">agent</span> <span class="o">+</span> <span class="s">")在"</span> <span class="o">+</span> <span class="n">clientAddr</span> <span class="o">+</span> <span class="s">"登陆。"</span><span class="o">);</span>
|
||||
<span class="k">return</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="o">}</span>
|
||||
</pre></div>
|
||||
<p>
|
||||
浏览器输入: http://127.0.0.1:6060/pipes/user/login?account=redkale&password=123456 <br>
|
||||
返回结果: {"retcode":0,"success":true} <br>
|
||||
后台打印: 用户(redkale)的回话ID为: 6110627db03b2b4a2c45a2fcb2aa1403, 通过客户端(Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36)在127.0.0.1登陆。
|
||||
</p>
|
||||
<p>
|
||||
REST的注解不仅可以注解在Service的方法参数上, 还可以在Service的方法的JavaBean参数的类里的字段进行注解。
|
||||
</p>
|
||||
<div class="highlight"><pre><span></span><span class="kd">public</span> <span class="kd">class</span> <span class="nc">LoginBean</span> <span class="o">{</span>
|
||||
|
||||
<span class="kd">private</span> <span class="n">String</span> <span class="n">account</span><span class="o">;</span>
|
||||
|
||||
<span class="kd">private</span> <span class="n">String</span> <span class="n">password</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">agent</span><span class="o">;</span>
|
||||
|
||||
<span class="nd">@RestSessionid</span><span class="o">(</span><span class="n">create</span> <span class="o">=</span> <span class="kc">true</span><span class="o">)</span>
|
||||
<span class="kd">private</span> <span class="n">String</span> <span class="n">sessionid</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="nd">@Override</span>
|
||||
<span class="kd">public</span> <span class="n">String</span> <span class="nf">toString</span><span class="o">()</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="n">JsonConvert</span><span class="o">.</span><span class="na">root</span><span class="o">().</span><span class="na">convertTo</span><span class="o">(</span><span class="k">this</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="cm">/** 以下省略getter setter方法 */</span>
|
||||
|
||||
<span class="o">}</span>
|
||||
|
||||
<span class="nd">@RestService</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"user"</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="kd">class</span> <span class="nc">UserService</span> <span class="kd">extends</span> <span class="n">AbstractService</span> <span class="o">{</span>
|
||||
|
||||
<span class="nd">@RestMapping</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"login"</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">"用户登陆"</span><span class="o">)</span>
|
||||
<span class="kd">public</span> <span class="n">RetResult</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">if</span> <span class="o">(</span><span class="n">bean</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</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="mi">1000</span><span class="o">,</span> <span class="s">"没有登陆信息"</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(!</span><span class="s">"redkale"</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">bean</span><span class="o">.</span><span class="na">getAccount</span><span class="o">()))</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="mi">1001</span><span class="o">,</span> <span class="s">"账号不是redkale"</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(!</span><span class="s">"123456"</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">bean</span><span class="o">.</span><span class="na">getPassword</span><span class="o">()))</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="mi">1002</span><span class="o">,</span> <span class="s">"密码错误"</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">"用户("</span> <span class="o">+</span> <span class="n">bean</span><span class="o">.</span><span class="na">getAccount</span><span class="o">()</span> <span class="o">+</span> <span class="s">")通过客户端("</span> <span class="o">+</span> <span class="n">bean</span><span class="o">.</span><span class="na">getAgent</span><span class="o">()</span> <span class="o">+</span> <span class="s">")在"</span> <span class="o">+</span> <span class="n">bean</span><span class="o">.</span><span class="na">getClientAddr</span><span class="o">()</span> <span class="o">+</span> <span class="s">"登陆。"</span><span class="o">);</span>
|
||||
<span class="k">return</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="o">}</span>
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
浏览器输入: http://127.0.0.1:6160/pipes/user/login?bean={account:redkale,password:123456} <br>
|
||||
返回结果: {"retcode":0,"success":true} <br>
|
||||
后台打印: 用户(redkale)通过客户端(Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36)在127.0.0.1登陆。
|
||||
</p>
|
||||
<p>
|
||||
如果用户登陆成功后需要跳转到首页或者还可能需要输出一些Cookie值,就需要使用HttpResult作为返回结果,例如:
|
||||
</p>
|
||||
<div class="highlight"><pre><span></span><span class="nd">@RestService</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"user"</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="kd">class</span> <span class="nc">UserService</span> <span class="kd">extends</span> <span class="n">AbstractService</span> <span class="o">{</span>
|
||||
|
||||
<span class="nd">@RestMapping</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"login"</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">"用户登陆"</span><span class="o">)</span>
|
||||
<span class="kd">public</span> <span class="n">HttpResult</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">if</span> <span class="o">(</span><span class="n">bean</span> <span class="o">==</span> <span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="k">new</span> <span class="n">HttpResult</span><span class="o"><>(</span><span class="k">new</span> <span class="n">RetResult</span><span class="o">(</span><span class="mi">1000</span><span class="o">,</span> <span class="s">"没有登陆信息"</span><span class="o">));</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(!</span><span class="s">"redkale"</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">bean</span><span class="o">.</span><span class="na">getAccount</span><span class="o">()))</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="k">new</span> <span class="n">HttpResult</span><span class="o"><>(</span><span class="k">new</span> <span class="n">RetResult</span><span class="o">(</span><span class="mi">1001</span><span class="o">,</span> <span class="s">"账号不是redkale"</span><span class="o">));</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(!</span><span class="s">"123456"</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">bean</span><span class="o">.</span><span class="na">getPassword</span><span class="o">()))</span> <span class="o">{</span>
|
||||
<span class="k">return</span> <span class="k">new</span> <span class="n">HttpResult</span><span class="o"><>(</span><span class="k">new</span> <span class="n">RetResult</span><span class="o">(</span><span class="mi">1002</span><span class="o">,</span> <span class="s">"密码错误"</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">"用户("</span> <span class="o">+</span> <span class="n">bean</span><span class="o">.</span><span class="na">getAccount</span><span class="o">()</span> <span class="o">+</span> <span class="s">")通过客户端("</span> <span class="o">+</span> <span class="n">bean</span><span class="o">.</span><span class="na">getAgent</span><span class="o">()</span> <span class="o">+</span> <span class="s">")在"</span> <span class="o">+</span> <span class="n">bean</span><span class="o">.</span><span class="na">getClientAddr</span><span class="o">()</span> <span class="o">+</span> <span class="s">"登陆。"</span><span class="o">);</span>
|
||||
<span class="k">return</span> <span class="k">new</span> <span class="n">HttpResult</span><span class="o">().</span><span class="na">header</span><span class="o">(</span><span class="s">"Location"</span><span class="o">,</span> <span class="s">"/index.html"</span><span class="o">).</span><span class="na">cookie</span><span class="o">(</span><span class="k">new</span> <span class="n">HttpCookie</span><span class="o">(</span><span class="s">"curraccount"</span><span class="o">,</span> <span class="n">bean</span><span class="o">.</span><span class="na">getAccount</span><span class="o">()));</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span>
|
||||
</pre></div>
|
||||
|
||||
<p>文件上传</p>
|
||||
<div class="highlight"><pre><span></span><span class="nd">@RestService</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"file"</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="kd">class</span> <span class="nc">FileService</span> <span class="kd">extends</span> <span class="n">AbstractService</span> <span class="o">{</span>
|
||||
|
||||
<span class="kd">private</span> <span class="kd">static</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="n">FileService</span><span class="o">.</span><span class="na">class</span><span class="o">.</span><span class="na">getSimpleName</span><span class="o">());</span>
|
||||
|
||||
<span class="kd">private</span> <span class="kd">static</span> <span class="kd">final</span> <span class="n">String</span> <span class="n">format</span> <span class="o">=</span> <span class="s">"%1$tY%1$tm%1$td%1$tH%1$tM%1$tS"</span><span class="o">;</span>
|
||||
|
||||
<span class="nd">@RestMapping</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"upload"</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">"文件上传,不鉴权"</span><span class="o">)</span>
|
||||
<span class="kd">public</span> <span class="n">RetResult</span> <span class="nf">upload</span><span class="o">(</span><span class="nd">@RestUploadFile</span><span class="o">(</span><span class="n">maxLength</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">*</span> <span class="mi">1024</span> <span class="o">*</span> <span class="mi">1024</span><span class="o">,</span> <span class="n">fileNameReg</span> <span class="o">=</span> <span class="s">".*\\.doc$"</span><span class="o">)</span> <span class="n">File</span> <span class="n">tmpFile</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">tmpFile</span> <span class="o">==</span> <span class="kc">null</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="mi">1001</span><span class="o">,</span> <span class="s">"没有上传文件或文件大小超过1M或文件不是.doc后缀"</span><span class="o">);</span>
|
||||
<span class="c1">//按日期命名 如 file-20170601133520.doc</span>
|
||||
<span class="k">try</span> <span class="o">{</span>
|
||||
<span class="n">logger</span><span class="o">.</span><span class="na">finest</span><span class="o">(</span><span class="s">"用户上传的文件名为: "</span> <span class="o">+</span> <span class="n">MultiContext</span><span class="o">.</span><span class="na">getFileName</span><span class="o">(</span><span class="n">tmpFile</span><span class="o">));</span>
|
||||
<span class="n">File</span> <span class="n">destFile</span> <span class="o">=</span> <span class="k">new</span> <span class="n">File</span><span class="o">(</span><span class="s">"D:/docs/file-"</span> <span class="o">+</span> <span class="n">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="n">format</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="s">".doc"</span><span class="o">);</span>
|
||||
<span class="n">destFile</span><span class="o">.</span><span class="na">getParentFile</span><span class="o">().</span><span class="na">mkdirs</span><span class="o">();</span>
|
||||
<span class="k">if</span> <span class="o">(!</span><span class="n">tmpFile</span><span class="o">.</span><span class="na">renameTo</span><span class="o">(</span><span class="n">destFile</span><span class="o">))</span> <span class="o">{</span> <span class="c1">//tmpFile与destFile不在同一盘符下会导致renameTo失败</span>
|
||||
<span class="n">java</span><span class="o">.</span><span class="na">nio</span><span class="o">.</span><span class="na">file</span><span class="o">.</span><span class="na">Files</span><span class="o">.</span><span class="na">copy</span><span class="o">(</span><span class="n">tmpFile</span><span class="o">.</span><span class="na">toPath</span><span class="o">(),</span> <span class="n">destFile</span><span class="o">.</span><span class="na">toPath</span><span class="o">(),</span> <span class="n">StandardCopyOption</span><span class="o">.</span><span class="na">ATOMIC_MOVE</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="o">}</span> <span class="k">finally</span> <span class="o">{</span> <span class="c1">//如果发生异常,将临时文件从{APP_HOME}/tmp 目录下删除</span>
|
||||
<span class="n">tmpFile</span><span class="o">.</span><span class="na">delete</span><span class="o">();</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">return</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="o">}</span>
|
||||
</pre></div>
|
||||
<p>
|
||||
WebSocket与其REST化将在以后的章节详细介绍。
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/course02_rest.html" target="_blank">https://redkale.org/course02_rest.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,111 +0,0 @@
|
||||
<!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>Redkale 入门教程 03 -- 用户鉴权</h3>
|
||||
|
||||
<p>
|
||||
<a href="index.html" target="_blank">Redkale</a> 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。<br/>
|
||||
</p>
|
||||
|
||||
<p>ClassLoader类加载</p>
|
||||
<p>
|
||||
双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。<br/>
|
||||
ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
|
||||
</p>
|
||||
|
||||
<p>Redkale 双亲委托</p>
|
||||
<p>
|
||||
ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">findEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">rs</span> <span class="o">=</span> <span class="o">(</span><span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">>)</span> <span class="n">encoders</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">rs</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">rs</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">parent</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">parent</span><span class="o">.</span><span class="na">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">loadEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">GenericArrayType</span><span class="o">)</span> <span class="k">return</span> <span class="k">new</span> <span class="nf">ArrayEncoder</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">type</span><span class="o">);</span>
|
||||
<span class="n">Class</span> <span class="n">clazz</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">ParameterizedType</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="kd">final</span> <span class="n">ParameterizedType</span> <span class="n">pts</span> <span class="o">=</span> <span class="o">(</span><span class="n">ParameterizedType</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="o">(</span><span class="n">pts</span><span class="o">).</span><span class="na">getRawType</span><span class="o">();</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">TypeVariable</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">TypeVariable</span> <span class="n">tv</span> <span class="o">=</span> <span class="o">(</span><span class="n">TypeVariable</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">Type</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">().</span><span class="na">length</span> <span class="o">==</span> <span class="mi">1</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">t</span> <span class="o">=</span> <span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">()[</span><span class="mi">0</span><span class="o">];</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(!(</span><span class="n">t</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">))</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</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="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConvertException</span><span class="o">(</span><span class="s">"not support the type ("</span> <span class="o">+</span> <span class="n">type</span> <span class="o">+</span> <span class="s">")"</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="nf">createEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">,</span> <span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 <a href="convert.html#convert_base" target="_blank">Convert基本用法</a> 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。
|
||||
</p>
|
||||
<p>
|
||||
Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="nf">NodeServer</span><span class="o">(</span><span class="n">Application</span> <span class="n">application</span><span class="o">,</span> <span class="n">Server</span> <span class="n">server</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">application</span> <span class="o">=</span> <span class="n">application</span><span class="o">;</span>
|
||||
<b><span class="k">this</span><span class="o">.</span><span class="na">resourceFactory</span> <span class="o">=</span> <span class="n">application</span><span class="o">.</span><span class="na">getResourceFactory</span><span class="o">().</span><span class="na">createChild</span><span class="o">();</span></b>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">server</span> <span class="o">=</span> <span class="n">server</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">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="o">}</span></pre></div>
|
||||
<p>
|
||||
双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/article_parents.html" target="_blank">https://redkale.org/article_parents.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,111 +0,0 @@
|
||||
<!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>Redkale 入门教程 04 -- CacheSource缓存数据源</h3>
|
||||
|
||||
<p>
|
||||
<a href="index.html" target="_blank">Redkale</a> 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。<br/>
|
||||
</p>
|
||||
|
||||
<p>ClassLoader类加载</p>
|
||||
<p>
|
||||
双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。<br/>
|
||||
ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
|
||||
</p>
|
||||
|
||||
<p>Redkale 双亲委托</p>
|
||||
<p>
|
||||
ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">findEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">rs</span> <span class="o">=</span> <span class="o">(</span><span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">>)</span> <span class="n">encoders</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">rs</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">rs</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">parent</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">parent</span><span class="o">.</span><span class="na">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">loadEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">GenericArrayType</span><span class="o">)</span> <span class="k">return</span> <span class="k">new</span> <span class="nf">ArrayEncoder</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">type</span><span class="o">);</span>
|
||||
<span class="n">Class</span> <span class="n">clazz</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">ParameterizedType</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="kd">final</span> <span class="n">ParameterizedType</span> <span class="n">pts</span> <span class="o">=</span> <span class="o">(</span><span class="n">ParameterizedType</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="o">(</span><span class="n">pts</span><span class="o">).</span><span class="na">getRawType</span><span class="o">();</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">TypeVariable</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">TypeVariable</span> <span class="n">tv</span> <span class="o">=</span> <span class="o">(</span><span class="n">TypeVariable</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">Type</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">().</span><span class="na">length</span> <span class="o">==</span> <span class="mi">1</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">t</span> <span class="o">=</span> <span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">()[</span><span class="mi">0</span><span class="o">];</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(!(</span><span class="n">t</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">))</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</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="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConvertException</span><span class="o">(</span><span class="s">"not support the type ("</span> <span class="o">+</span> <span class="n">type</span> <span class="o">+</span> <span class="s">")"</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="nf">createEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">,</span> <span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 <a href="convert.html#convert_base" target="_blank">Convert基本用法</a> 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。
|
||||
</p>
|
||||
<p>
|
||||
Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="nf">NodeServer</span><span class="o">(</span><span class="n">Application</span> <span class="n">application</span><span class="o">,</span> <span class="n">Server</span> <span class="n">server</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">application</span> <span class="o">=</span> <span class="n">application</span><span class="o">;</span>
|
||||
<b><span class="k">this</span><span class="o">.</span><span class="na">resourceFactory</span> <span class="o">=</span> <span class="n">application</span><span class="o">.</span><span class="na">getResourceFactory</span><span class="o">().</span><span class="na">createChild</span><span class="o">();</span></b>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">server</span> <span class="o">=</span> <span class="n">server</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">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="o">}</span></pre></div>
|
||||
<p>
|
||||
双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/article_parents.html" target="_blank">https://redkale.org/article_parents.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,111 +0,0 @@
|
||||
<!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>Redkale 入门教程 05 -- DataSource 增删改查</h3>
|
||||
|
||||
<p>
|
||||
<a href="index.html" target="_blank">Redkale</a> 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。<br/>
|
||||
</p>
|
||||
|
||||
<p>ClassLoader类加载</p>
|
||||
<p>
|
||||
双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。<br/>
|
||||
ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
|
||||
</p>
|
||||
|
||||
<p>Redkale 双亲委托</p>
|
||||
<p>
|
||||
ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">findEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">rs</span> <span class="o">=</span> <span class="o">(</span><span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">>)</span> <span class="n">encoders</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">rs</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">rs</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">parent</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">parent</span><span class="o">.</span><span class="na">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">loadEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">GenericArrayType</span><span class="o">)</span> <span class="k">return</span> <span class="k">new</span> <span class="nf">ArrayEncoder</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">type</span><span class="o">);</span>
|
||||
<span class="n">Class</span> <span class="n">clazz</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">ParameterizedType</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="kd">final</span> <span class="n">ParameterizedType</span> <span class="n">pts</span> <span class="o">=</span> <span class="o">(</span><span class="n">ParameterizedType</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="o">(</span><span class="n">pts</span><span class="o">).</span><span class="na">getRawType</span><span class="o">();</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">TypeVariable</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">TypeVariable</span> <span class="n">tv</span> <span class="o">=</span> <span class="o">(</span><span class="n">TypeVariable</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">Type</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">().</span><span class="na">length</span> <span class="o">==</span> <span class="mi">1</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">t</span> <span class="o">=</span> <span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">()[</span><span class="mi">0</span><span class="o">];</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(!(</span><span class="n">t</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">))</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</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="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConvertException</span><span class="o">(</span><span class="s">"not support the type ("</span> <span class="o">+</span> <span class="n">type</span> <span class="o">+</span> <span class="s">")"</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="nf">createEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">,</span> <span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 <a href="convert.html#convert_base" target="_blank">Convert基本用法</a> 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。
|
||||
</p>
|
||||
<p>
|
||||
Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="nf">NodeServer</span><span class="o">(</span><span class="n">Application</span> <span class="n">application</span><span class="o">,</span> <span class="n">Server</span> <span class="n">server</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">application</span> <span class="o">=</span> <span class="n">application</span><span class="o">;</span>
|
||||
<b><span class="k">this</span><span class="o">.</span><span class="na">resourceFactory</span> <span class="o">=</span> <span class="n">application</span><span class="o">.</span><span class="na">getResourceFactory</span><span class="o">().</span><span class="na">createChild</span><span class="o">();</span></b>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">server</span> <span class="o">=</span> <span class="n">server</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">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="o">}</span></pre></div>
|
||||
<p>
|
||||
双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/article_parents.html" target="_blank">https://redkale.org/article_parents.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,111 +0,0 @@
|
||||
<!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>Redkale 入门教程 06 -- DataSource 分库分表</h3>
|
||||
|
||||
<p>
|
||||
<a href="index.html" target="_blank">Redkale</a> 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。<br/>
|
||||
</p>
|
||||
|
||||
<p>ClassLoader类加载</p>
|
||||
<p>
|
||||
双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。<br/>
|
||||
ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
|
||||
</p>
|
||||
|
||||
<p>Redkale 双亲委托</p>
|
||||
<p>
|
||||
ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">findEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">rs</span> <span class="o">=</span> <span class="o">(</span><span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">>)</span> <span class="n">encoders</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">rs</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">rs</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">parent</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">parent</span><span class="o">.</span><span class="na">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">loadEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">GenericArrayType</span><span class="o">)</span> <span class="k">return</span> <span class="k">new</span> <span class="nf">ArrayEncoder</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">type</span><span class="o">);</span>
|
||||
<span class="n">Class</span> <span class="n">clazz</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">ParameterizedType</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="kd">final</span> <span class="n">ParameterizedType</span> <span class="n">pts</span> <span class="o">=</span> <span class="o">(</span><span class="n">ParameterizedType</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="o">(</span><span class="n">pts</span><span class="o">).</span><span class="na">getRawType</span><span class="o">();</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">TypeVariable</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">TypeVariable</span> <span class="n">tv</span> <span class="o">=</span> <span class="o">(</span><span class="n">TypeVariable</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">Type</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">().</span><span class="na">length</span> <span class="o">==</span> <span class="mi">1</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">t</span> <span class="o">=</span> <span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">()[</span><span class="mi">0</span><span class="o">];</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(!(</span><span class="n">t</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">))</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</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="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConvertException</span><span class="o">(</span><span class="s">"not support the type ("</span> <span class="o">+</span> <span class="n">type</span> <span class="o">+</span> <span class="s">")"</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="nf">createEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">,</span> <span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 <a href="convert.html#convert_base" target="_blank">Convert基本用法</a> 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。
|
||||
</p>
|
||||
<p>
|
||||
Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="nf">NodeServer</span><span class="o">(</span><span class="n">Application</span> <span class="n">application</span><span class="o">,</span> <span class="n">Server</span> <span class="n">server</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">application</span> <span class="o">=</span> <span class="n">application</span><span class="o">;</span>
|
||||
<b><span class="k">this</span><span class="o">.</span><span class="na">resourceFactory</span> <span class="o">=</span> <span class="n">application</span><span class="o">.</span><span class="na">getResourceFactory</span><span class="o">().</span><span class="na">createChild</span><span class="o">();</span></b>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">server</span> <span class="o">=</span> <span class="n">server</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">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="o">}</span></pre></div>
|
||||
<p>
|
||||
双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/article_parents.html" target="_blank">https://redkale.org/article_parents.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,111 +0,0 @@
|
||||
<!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>Redkale 入门教程 07 -- Convert</h3>
|
||||
|
||||
<p>
|
||||
<a href="index.html" target="_blank">Redkale</a> 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。<br/>
|
||||
</p>
|
||||
|
||||
<p>ClassLoader类加载</p>
|
||||
<p>
|
||||
双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。<br/>
|
||||
ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
|
||||
</p>
|
||||
|
||||
<p>Redkale 双亲委托</p>
|
||||
<p>
|
||||
ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">findEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">rs</span> <span class="o">=</span> <span class="o">(</span><span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">>)</span> <span class="n">encoders</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">rs</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">rs</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">parent</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">parent</span><span class="o">.</span><span class="na">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">loadEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">GenericArrayType</span><span class="o">)</span> <span class="k">return</span> <span class="k">new</span> <span class="nf">ArrayEncoder</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">type</span><span class="o">);</span>
|
||||
<span class="n">Class</span> <span class="n">clazz</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">ParameterizedType</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="kd">final</span> <span class="n">ParameterizedType</span> <span class="n">pts</span> <span class="o">=</span> <span class="o">(</span><span class="n">ParameterizedType</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="o">(</span><span class="n">pts</span><span class="o">).</span><span class="na">getRawType</span><span class="o">();</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">TypeVariable</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">TypeVariable</span> <span class="n">tv</span> <span class="o">=</span> <span class="o">(</span><span class="n">TypeVariable</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">Type</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">().</span><span class="na">length</span> <span class="o">==</span> <span class="mi">1</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">t</span> <span class="o">=</span> <span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">()[</span><span class="mi">0</span><span class="o">];</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(!(</span><span class="n">t</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">))</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</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="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConvertException</span><span class="o">(</span><span class="s">"not support the type ("</span> <span class="o">+</span> <span class="n">type</span> <span class="o">+</span> <span class="s">")"</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="nf">createEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">,</span> <span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 <a href="convert.html#convert_base" target="_blank">Convert基本用法</a> 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。
|
||||
</p>
|
||||
<p>
|
||||
Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="nf">NodeServer</span><span class="o">(</span><span class="n">Application</span> <span class="n">application</span><span class="o">,</span> <span class="n">Server</span> <span class="n">server</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">application</span> <span class="o">=</span> <span class="n">application</span><span class="o">;</span>
|
||||
<b><span class="k">this</span><span class="o">.</span><span class="na">resourceFactory</span> <span class="o">=</span> <span class="n">application</span><span class="o">.</span><span class="na">getResourceFactory</span><span class="o">().</span><span class="na">createChild</span><span class="o">();</span></b>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">server</span> <span class="o">=</span> <span class="n">server</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">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="o">}</span></pre></div>
|
||||
<p>
|
||||
双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/article_parents.html" target="_blank">https://redkale.org/article_parents.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,111 +0,0 @@
|
||||
<!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>Redkale 入门教程 08 -- HttpServlet</h3>
|
||||
|
||||
<p>
|
||||
<a href="index.html" target="_blank">Redkale</a> 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。<br/>
|
||||
</p>
|
||||
|
||||
<p>ClassLoader类加载</p>
|
||||
<p>
|
||||
双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。<br/>
|
||||
ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
|
||||
</p>
|
||||
|
||||
<p>Redkale 双亲委托</p>
|
||||
<p>
|
||||
ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">findEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">rs</span> <span class="o">=</span> <span class="o">(</span><span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">>)</span> <span class="n">encoders</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">rs</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">rs</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">parent</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">parent</span><span class="o">.</span><span class="na">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">loadEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">GenericArrayType</span><span class="o">)</span> <span class="k">return</span> <span class="k">new</span> <span class="nf">ArrayEncoder</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">type</span><span class="o">);</span>
|
||||
<span class="n">Class</span> <span class="n">clazz</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">ParameterizedType</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="kd">final</span> <span class="n">ParameterizedType</span> <span class="n">pts</span> <span class="o">=</span> <span class="o">(</span><span class="n">ParameterizedType</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="o">(</span><span class="n">pts</span><span class="o">).</span><span class="na">getRawType</span><span class="o">();</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">TypeVariable</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">TypeVariable</span> <span class="n">tv</span> <span class="o">=</span> <span class="o">(</span><span class="n">TypeVariable</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">Type</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">().</span><span class="na">length</span> <span class="o">==</span> <span class="mi">1</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">t</span> <span class="o">=</span> <span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">()[</span><span class="mi">0</span><span class="o">];</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(!(</span><span class="n">t</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">))</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</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="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConvertException</span><span class="o">(</span><span class="s">"not support the type ("</span> <span class="o">+</span> <span class="n">type</span> <span class="o">+</span> <span class="s">")"</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="nf">createEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">,</span> <span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 <a href="convert.html#convert_base" target="_blank">Convert基本用法</a> 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。
|
||||
</p>
|
||||
<p>
|
||||
Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="nf">NodeServer</span><span class="o">(</span><span class="n">Application</span> <span class="n">application</span><span class="o">,</span> <span class="n">Server</span> <span class="n">server</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">application</span> <span class="o">=</span> <span class="n">application</span><span class="o">;</span>
|
||||
<b><span class="k">this</span><span class="o">.</span><span class="na">resourceFactory</span> <span class="o">=</span> <span class="n">application</span><span class="o">.</span><span class="na">getResourceFactory</span><span class="o">().</span><span class="na">createChild</span><span class="o">();</span></b>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">server</span> <span class="o">=</span> <span class="n">server</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">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="o">}</span></pre></div>
|
||||
<p>
|
||||
双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/article_parents.html" target="_blank">https://redkale.org/article_parents.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,111 +0,0 @@
|
||||
<!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>Redkale 入门教程 09 -- 文件上传下载</h3>
|
||||
|
||||
<p>
|
||||
<a href="index.html" target="_blank">Redkale</a> 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。<br/>
|
||||
</p>
|
||||
|
||||
<p>ClassLoader类加载</p>
|
||||
<p>
|
||||
双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。<br/>
|
||||
ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
|
||||
</p>
|
||||
|
||||
<p>Redkale 双亲委托</p>
|
||||
<p>
|
||||
ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">findEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">rs</span> <span class="o">=</span> <span class="o">(</span><span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">>)</span> <span class="n">encoders</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">rs</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">rs</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">parent</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">parent</span><span class="o">.</span><span class="na">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">loadEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">GenericArrayType</span><span class="o">)</span> <span class="k">return</span> <span class="k">new</span> <span class="nf">ArrayEncoder</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">type</span><span class="o">);</span>
|
||||
<span class="n">Class</span> <span class="n">clazz</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">ParameterizedType</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="kd">final</span> <span class="n">ParameterizedType</span> <span class="n">pts</span> <span class="o">=</span> <span class="o">(</span><span class="n">ParameterizedType</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="o">(</span><span class="n">pts</span><span class="o">).</span><span class="na">getRawType</span><span class="o">();</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">TypeVariable</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">TypeVariable</span> <span class="n">tv</span> <span class="o">=</span> <span class="o">(</span><span class="n">TypeVariable</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">Type</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">().</span><span class="na">length</span> <span class="o">==</span> <span class="mi">1</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">t</span> <span class="o">=</span> <span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">()[</span><span class="mi">0</span><span class="o">];</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(!(</span><span class="n">t</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">))</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</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="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConvertException</span><span class="o">(</span><span class="s">"not support the type ("</span> <span class="o">+</span> <span class="n">type</span> <span class="o">+</span> <span class="s">")"</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="nf">createEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">,</span> <span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 <a href="convert.html#convert_base" target="_blank">Convert基本用法</a> 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。
|
||||
</p>
|
||||
<p>
|
||||
Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="nf">NodeServer</span><span class="o">(</span><span class="n">Application</span> <span class="n">application</span><span class="o">,</span> <span class="n">Server</span> <span class="n">server</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">application</span> <span class="o">=</span> <span class="n">application</span><span class="o">;</span>
|
||||
<b><span class="k">this</span><span class="o">.</span><span class="na">resourceFactory</span> <span class="o">=</span> <span class="n">application</span><span class="o">.</span><span class="na">getResourceFactory</span><span class="o">().</span><span class="na">createChild</span><span class="o">();</span></b>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">server</span> <span class="o">=</span> <span class="n">server</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">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="o">}</span></pre></div>
|
||||
<p>
|
||||
双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/article_parents.html" target="_blank">https://redkale.org/article_parents.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,111 +0,0 @@
|
||||
<!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>Redkale 入门教程 10 -- WebSocket</h3>
|
||||
|
||||
<p>
|
||||
<a href="index.html" target="_blank">Redkale</a> 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。<br/>
|
||||
</p>
|
||||
|
||||
<p>ClassLoader类加载</p>
|
||||
<p>
|
||||
双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。<br/>
|
||||
ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
|
||||
</p>
|
||||
|
||||
<p>Redkale 双亲委托</p>
|
||||
<p>
|
||||
ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">findEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">rs</span> <span class="o">=</span> <span class="o">(</span><span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">>)</span> <span class="n">encoders</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">rs</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">rs</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">parent</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">parent</span><span class="o">.</span><span class="na">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">loadEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">GenericArrayType</span><span class="o">)</span> <span class="k">return</span> <span class="k">new</span> <span class="nf">ArrayEncoder</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">type</span><span class="o">);</span>
|
||||
<span class="n">Class</span> <span class="n">clazz</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">ParameterizedType</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="kd">final</span> <span class="n">ParameterizedType</span> <span class="n">pts</span> <span class="o">=</span> <span class="o">(</span><span class="n">ParameterizedType</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="o">(</span><span class="n">pts</span><span class="o">).</span><span class="na">getRawType</span><span class="o">();</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">TypeVariable</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">TypeVariable</span> <span class="n">tv</span> <span class="o">=</span> <span class="o">(</span><span class="n">TypeVariable</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">Type</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">().</span><span class="na">length</span> <span class="o">==</span> <span class="mi">1</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">t</span> <span class="o">=</span> <span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">()[</span><span class="mi">0</span><span class="o">];</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(!(</span><span class="n">t</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">))</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</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="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConvertException</span><span class="o">(</span><span class="s">"not support the type ("</span> <span class="o">+</span> <span class="n">type</span> <span class="o">+</span> <span class="s">")"</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="nf">createEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">,</span> <span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 <a href="convert.html#convert_base" target="_blank">Convert基本用法</a> 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。
|
||||
</p>
|
||||
<p>
|
||||
Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="nf">NodeServer</span><span class="o">(</span><span class="n">Application</span> <span class="n">application</span><span class="o">,</span> <span class="n">Server</span> <span class="n">server</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">application</span> <span class="o">=</span> <span class="n">application</span><span class="o">;</span>
|
||||
<b><span class="k">this</span><span class="o">.</span><span class="na">resourceFactory</span> <span class="o">=</span> <span class="n">application</span><span class="o">.</span><span class="na">getResourceFactory</span><span class="o">().</span><span class="na">createChild</span><span class="o">();</span></b>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">server</span> <span class="o">=</span> <span class="n">server</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">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="o">}</span></pre></div>
|
||||
<p>
|
||||
双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/article_parents.html" target="_blank">https://redkale.org/article_parents.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,111 +0,0 @@
|
||||
<!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>Redkale 入门教程 11 -- SNCP分布式部署</h3>
|
||||
|
||||
<p>
|
||||
<a href="index.html" target="_blank">Redkale</a> 里大量使用了双亲委托模型,序列化的ConvertFactory、依赖注入的ResourceFactory、服务管理的WatchFactory均采用双亲委托模型。用于优先加载自定义的处理类,同时也保证两个同级的子Factory不会相互干扰。<br/>
|
||||
</p>
|
||||
|
||||
<p>ClassLoader类加载</p>
|
||||
<p>
|
||||
双亲委托模型最经典的例子就是JVM的类加载器ClassLoader。每个ClassLoader实例都有一个父类加载器的引用(不是继承关系,是包含关系),虚拟机内置的类加载器(Bootstrap ClassLoader)本身没有父类加载器,但可以用作其它ClassLoader实例的的父类加载器。当一个ClassLoader实例需要加载某个类时,它会试图亲自搜索某个类之前,先把这个任务委托给它的父类加载器,这个过程是由上至下依次检查的,首先由最顶层的类加载器Bootstrap ClassLoader试图加载,如果没加载到,则把任务转交给Extension ClassLoader试图加载,如果也没加载到,则转交给App ClassLoader 进行加载,如果它也没有加载得到的话,则返回给委托的发起者,由它到指定的文件系统或网络等URL中加载该类。如果它们都没有加载到这个类时,则抛出ClassNotFoundException异常。否则将这个找到的类生成一个类的定义,并将它加载到内存当中,最后返回这个类在内存中的Class实例对象。<br/>
|
||||
ClassLoader采用双亲委托有两个好处:避免类的重复加载和保证类的安全性。由类加载的顺序可以看出父加载器加载过的类在子加载器中不会被重复加载,同时也保证了安全性,一些非系统的class是不可靠的,若定义一个恶意的java.io.File类覆盖JDK自带的类会带来不安全性。而使用双亲委托机制的话该File类永远不会被调用,因为委托BootStrapClassLoader加载后会加载JDK中的File类而不会加载自定义的这个。
|
||||
</p>
|
||||
|
||||
<p>Redkale 双亲委托</p>
|
||||
<p>
|
||||
ConvertFactory、ResourceFactory、WatchFactory三者的双亲委托模型设计完全一样。下面以ConvertFactory为例说明,ConvertFactory的搜索顺序与ClassLoader相反,ClassLoader为了避免类的重复而先加载父加载器后加载子加载器,ConvertFactory为了优先加载自定义的Encoder和Decoder先搜索自身的ConvertFactory,找不到再从父ConvertFactory中搜索。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">findEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">rs</span> <span class="o">=</span> <span class="o">(</span><span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">>)</span> <span class="n">encoders</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">rs</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">rs</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">parent</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">parent</span><span class="o">.</span><span class="na">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
当搜索不到Encoder、Decoder时,自身的ConvertFactory会自动创建一个ObjectEncoder、ObjectDecoder。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="kd">final</span> <span class="o"><</span><span class="n">E</span><span class="o">></span> <span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="nf">loadEncoder</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="o">{</span>
|
||||
<span class="n">Encodeable</span><span class="o"><</span><span class="n">W</span><span class="o">,</span> <span class="n">E</span><span class="o">></span> <span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">GenericArrayType</span><span class="o">)</span> <span class="k">return</span> <span class="k">new</span> <span class="nf">ArrayEncoder</span><span class="o">(</span><span class="k">this</span><span class="o">,</span> <span class="n">type</span><span class="o">);</span>
|
||||
<span class="n">Class</span> <span class="n">clazz</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">ParameterizedType</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="kd">final</span> <span class="n">ParameterizedType</span> <span class="n">pts</span> <span class="o">=</span> <span class="o">(</span><span class="n">ParameterizedType</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="o">(</span><span class="n">pts</span><span class="o">).</span><span class="na">getRawType</span><span class="o">();</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">TypeVariable</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">TypeVariable</span> <span class="n">tv</span> <span class="o">=</span> <span class="o">(</span><span class="n">TypeVariable</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="n">Type</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">().</span><span class="na">length</span> <span class="o">==</span> <span class="mi">1</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">t</span> <span class="o">=</span> <span class="n">tv</span><span class="o">.</span><span class="na">getBounds</span><span class="o">()[</span><span class="mi">0</span><span class="o">];</span>
|
||||
<span class="o">}</span>
|
||||
<span class="k">if</span> <span class="o">(!(</span><span class="n">t</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">))</span> <span class="n">t</span> <span class="o">=</span> <span class="n">Object</span><span class="o">.</span><span class="na">class</span><span class="o">;</span>
|
||||
<span class="n">clazz</span> <span class="o">=</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="o">}</span> <span class="k">else</span> <span class="nf">if</span> <span class="o">(</span><span class="n">type</span> <span class="k">instanceof</span> <span class="n">Class</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="n">clazz</span> <span class="o">=</span> <span class="o">(</span><span class="n">Class</span><span class="o">)</span> <span class="n">type</span><span class="o">;</span>
|
||||
<span class="o">}</span> <span class="k">else</span> <span class="o">{</span>
|
||||
<span class="k">throw</span> <span class="k">new</span> <span class="nf">ConvertException</span><span class="o">(</span><span class="s">"not support the type ("</span> <span class="o">+</span> <span class="n">type</span> <span class="o">+</span> <span class="s">")"</span><span class="o">);</span>
|
||||
<span class="o">}</span>
|
||||
<span class="n">encoder</span> <span class="o">=</span> <span class="n">findEncoder</span><span class="o">(</span><span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="k">if</span> <span class="o">(</span><span class="n">encoder</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span> <span class="k">return</span> <span class="n">encoder</span><span class="o">;</span>
|
||||
<span class="k">return</span> <span class="nf">createEncoder</span><span class="o">(</span><span class="n">type</span><span class="o">,</span> <span class="n">clazz</span><span class="o">);</span>
|
||||
<span class="o">}</span></pre></div>
|
||||
<p>
|
||||
大部分情况下Convert的处理对象会根据JavaBean类自定生成,而有些场景需要覆盖处理类,这样需要子ConvertFactory,如 <a href="convert.html#convert_base" target="_blank">Convert基本用法</a> 例子中使用JsonFactory.root().createChild()重定义。且与JsonFactory.root()中的定义可以并存,也不会产出冲突。
|
||||
</p>
|
||||
<p>
|
||||
Redkale可以启动多个协议Server服务(配置文件中含多个server节点),为避免冲突,每个非SNCP的Server的ResourceFactory也是独立的。
|
||||
</p>
|
||||
<div class="highlight"><pre><span class="kd">public</span> <span class="nf">NodeServer</span><span class="o">(</span><span class="n">Application</span> <span class="n">application</span><span class="o">,</span> <span class="n">Server</span> <span class="n">server</span><span class="o">)</span> <span class="o">{</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">application</span> <span class="o">=</span> <span class="n">application</span><span class="o">;</span>
|
||||
<b><span class="k">this</span><span class="o">.</span><span class="na">resourceFactory</span> <span class="o">=</span> <span class="n">application</span><span class="o">.</span><span class="na">getResourceFactory</span><span class="o">().</span><span class="na">createChild</span><span class="o">();</span></b>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">server</span> <span class="o">=</span> <span class="n">server</span><span class="o">;</span>
|
||||
<span class="k">this</span><span class="o">.</span><span class="na">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="o">}</span></pre></div>
|
||||
<p>
|
||||
双亲委托模型既可让同级子Factory保持独立,也可重用父Factory内的配置,因此在Redkale这种支持多Server、多种配置的场景下很是适合。
|
||||
</p>
|
||||
<br/>
|
||||
<p>
|
||||
转载请注明出处:<a href="https://redkale.org/article_parents.html" target="_blank">https://redkale.org/article_parents.html</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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
2
datasource-shu-ju-ku-zu-jian.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# DataSource数据库组件
|
||||
|
||||
BIN
doc/分布式架构图.vsdx
BIN
favicon.ico
|
Before Width: | Height: | Size: 4.2 KiB |
2
http-fu-wu.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# HTTP 服务
|
||||
|
||||
|
Before Width: | Height: | Size: 282 KiB |
|
Before Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 152 KiB |
|
Before Width: | Height: | Size: 197 KiB |
|
Before Width: | Height: | Size: 304 KiB |
|
Before Width: | Height: | Size: 181 KiB |
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 93 KiB |
|
Before Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 91 KiB |
|
Before Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 130 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 12 KiB |
101
index.html
@@ -1,101 +0,0 @@
|
||||
<!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="redkale_intro" class="anchor" href="#" aria-hidden="true"></a>Redkale 介绍</h3>
|
||||
|
||||
<p> Redkale(中文名: 红菜苔,湖北特产蔬菜)是基于Java 11全新的微服务开源框架, 包含HTTP、WebSocket、TCP/UDP、数据序列化、数据缓存、依赖注入等功能。
|
||||
本框架致力于简化集中式和微服务架构的开发,在增强开发敏捷性的同时保持高性能。<br/>
|
||||
Redkale 有如下主要特点: <br/>
|
||||
1、提供了动态依赖注入和动态字节码生成类功能 <br/>
|
||||
2、提供HTTP服务,同时内置JSON功能与限时缓存功能 <br/>
|
||||
3、TCP层完全使用NIO.2,并统一TCP与UDP的接口 <br/>
|
||||
4、提供分布式与集中式部署的无缝切换 <br/>
|
||||
5、提供类似JPA功能,包含数据缓存自动同步、分表分库与简洁的数据层操作接口 <br/>
|
||||
6、提供了MQ消息消费与生产简洁化API <br/>
|
||||
7、Servlet、Service、Source组件均支持异步接口 <br/>
|
||||
</p>
|
||||
|
||||
<h3><a id="redkale_think" class="anchor" href="#" aria-hidden="true"></a>设计理念</h3>
|
||||
<p> 作为一个全新的微服务框架,Redkale在接口定义上使用了默认实现、接口带静态方法、重复注解等特性,同时在设计上与主流框架有很大不同。Redkale是按组件形式设计的,而非以容器为主,几乎每个子包都是能提供独立功能的组件。如Tomcat是按容器设计的,所有web资源/配置由Tomcat控制,开发者很能难控制到Tomcat内部,而Redkale的HTTP服务只是个组件,开发者既可以自己启动和配置HttpServer,也可以把Redkale当成容器通过Redkale进程来初始化服务。Spring的Ioc容器也是如此,Redkale提供的依赖注入仅通过ResouceFactory一个类来控制,非常轻量,并且可动态更改已注入的资源。Spring提倡控制反转思想,而自身的容器却让开发者很难控制。Redkale是一个既能以组件形式也能以容器形式存在的框架。从整体上看,Redkale的架构分两层:接口和默认实现。开发者若想替换掉Redkale内置的HTTP服务而使用符合JavaEE规范的HttpServlet, 可以采用自定义协议基于JSR 340(Servlet 3.1)来实现自己的HTTP服务;若想使用Hibernate作为数据库操作,可以写一个自己的DataSource实现类;JSON的序列化和反序列化也可以使用第三方的实现;Memcached或Redis也可以作为另一个CacheSource的实现替换Redkale的默认实现。这其实包含了控制反转的思想,让框架里的各个组件均可让开发者控制。<br/>
|
||||
与主流框架比,功能上Redkale显得很简单,这体现了Redkale的简易性,而并非是不足,从一个良好的设计习惯或架构上来看,有些常用功能是不需要提供的,如Redkale的HTTP服务不支持HTTPS和JSP,HTTPS比HTTP多了一层加密解密,这种密集型的计算不是Java的专长,通常提供HTTP服务的架构不会将Java动态服务器放在最前端,而是在前方会放nginx或apache,除了负载均衡还能静动分离,因此HTTPS的加解密应交给nginx这样的高性能服务器处理。Redkale再提供HTTPS服务就显得鸡肋。JSP其实算是一个落后的技术,现在是一个多样化终端的时代,终端不只局限于桌面程序和PC浏览器,还有原生App、混合式App、微信端、移动H5、提供第三方接口等各种形式的终端,这些都不是JSP能方便兼顾的,而HTTP+JSON作为通用性接口可以避免重复开发,模版引擎的功能加上各种强大的JS框架足以取代JSP。Redkale在功能上做了筛选,不会为了迎合主流而提供,而是以良好的设计思想为指导。这是Redkale的主导思维。</p>
|
||||
|
||||
|
||||
<h3><a class="anchor" href="convert.html" target="_blank" aria-hidden="true">亮点一. 序列化与反序列化</a></h3>
|
||||
|
||||
<p> Convert包是Redkale内一个独立的组件, 用于数据的序列化与反序列化。包分三块:基本包、JSON包、PB(Protobuf)包。基本包可以用于扩展其他序列化格式(如: XML),其JSON性能是其他任何JSON框架不能媲美的,对于非常规的POJO类也提供了方便的自定义接口。BSON用于数据的二进制序列化与反序列化,支持很复杂的泛型数据,是SNCP协议的基础。</p>
|
||||
|
||||
|
||||
<h3><a class="anchor" href="source.html#source_datasource" target="_blank" aria-hidden="true">亮点二. DataSource</a></h3>
|
||||
|
||||
<p> Redkale提供DataSource类对数据层进行操作,其功能类似JPA。最大程度的简化数据层的操作,免去SQL/JPQL语句的编写。同时提供过滤查询与JavaBean的结合、读写分离、数据库热切换、本地/远程部署、数据分表分库、进程间缓存自动同步等功能。<br/>
|
||||
CacheSource是缓存的统一接口,像JDBC接口定义,不管是内存模式还是Memcached、Redis或其他缓存系统, 只要提供对应的实现就可使用,每个接口都提供同步和异步两种方式。</p>
|
||||
|
||||
|
||||
<h3><a class="anchor" href="net.html#net_http" target="_blank" aria-hidden="true">亮点三. HTTP协议</a></h3>
|
||||
|
||||
<p> HTTP组件是基于异步NIO.2实现的,HttpRequest的输入与HttpResponse的输出均是异步操作,HttpRequest内置JSON参数的获取和文件上传功能,HttpResponse提供数据对象和文件的数据,同时集成了REST ,因此并不遵循JSR 340规范(Servlet 3.1)且也没有实现JSP规范。 HTTP Server只提供四个对象:HttpContext、HttpRequest、HttpResponse、HttpServlet。 传统Session则由数据层实现。Redkale提倡HTTP+JSON接口(网站、PC客户端、APP移动端、第三方接口均可统一接口), 故内置了JSON序列化与反序列化接口,同时内置HTTP缓存机制。<br/>
|
||||
Redkale 的<a href="net.html#net_ws" target="_blank">WebSocket服务</a>接口不同于JSR 340(Servlet 3.1), 除了提供基本的WebSocket功能, 还提供分布式与集中式部署, 当部署多个WebSocket进程时,通过配置文件可以实现WebSocket之间连接信息的数据同步。</p>
|
||||
|
||||
|
||||
<h3><a class="anchor" href="net.html#net_sncp" target="_blank" aria-hidden="true">亮点四. SNCP协议</a></h3>
|
||||
|
||||
<p> SNCP(Service Node Communicate Protocol)是Redkale独有的RPC协议, 主要用于进程间的数据传输,支持泛型和子类的数据转换。开发人员通过配置文件可以轻易的将Service由<a href="service.html#service_local" target="_blank">本地模式</a>变成<a href="service.html#service_remote" target="_blank">远程模式</a>。<a href="service.html#service_remote" target="_blank">远程模式Service</a>使用SNCP协议与其他进程的Service通信。开发人员无需对远程通信接口使用类似Mina的第三方包进行开发。SNCP是Redkale的核心功能,其微服务架构都是基于<a href="service.html#service_local" target="_blank">本地模式Service</a>和<a href="service.html#service_remote" target="_blank">远程模式Service</a>。</p>
|
||||
|
||||
|
||||
<h3><a class="anchor" href="net.html#net_sncp" target="_blank" aria-hidden="true">亮点五. WATCH协议</a></h3>
|
||||
|
||||
<p> WATCH协议其实就是HTTP协议,主要用于进程的微服务和监控管理。接口以HTTP形式提供, Redkale自带部分常规的Watch功能,如动态更新DataSource配置,动态加载Service、Servlet、Filter,查看Server基本信息等。开发者也可自定义WatchService进行监控或管理操作。</p>
|
||||
|
||||
|
||||
<h3><a class="anchor" href="net.html#net_sncp" target="_blank" aria-hidden="true">亮点六. 异步接口</a></h3>
|
||||
|
||||
<p> Net、Service、DataSource、CacheSource都支持异步接口,<a href="service.html#service_local" target="_blank">本地模式</a>、<a href="service.html#service_remote" target="_blank">远程模式</a>的Service均支持。</p>
|
||||
|
||||
<h3><a id="redkale_code" class="anchor" href="#" aria-hidden="true"></a>Java 源码</h3>
|
||||
<p> <a href="https://gitee.com/redkale" target="_blank" ><b> 码云 源码 https://gitee.com/redkale</b></a><br/><br/>
|
||||
<a href="https://github.com/redkale" target="_blank" >Github 源码 https://github.com/redkale</a><br/>
|
||||
<br/>
|
||||
<a href="javadoc/index.html" target="_blank" >在线 Javadoc API</a></p>
|
||||
|
||||
<br/>
|
||||
<p> Redkale官网: <a href="https://redkale.org" target="_blank"><b>https://redkale.org</b></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?aee2e6e1addaf28cd4e21e2d5a509123";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||