160 lines
19 KiB
HTML
160 lines
19 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en-us">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>Redkale(红菜苔)--基于Java 8全新的微服务开源框架 - Redkale官网</title>
|
||
<meta name="keywords" content="Redkale,redkale,java,微服务,架构"/>
|
||
<meta name="description" content="Redkale(红菜苔)是基于Java 8全新的微服务开源框架"/>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<link rel="stylesheet" type="text/css" href="stylesheets/stylesheet.css" media="screen">
|
||
</head>
|
||
<body>
|
||
<section class="page-header">
|
||
<a href="index.html" class="project-name">Redkale</a>
|
||
<h2 class="project-tagline"></h2>
|
||
<a href="redkale.html" class="btn">Redkale 入门</a>
|
||
<a href="convert.html" class="btn">Convert 组件</a>
|
||
<a href="service.html" class="btn">Service 组件</a>
|
||
<a href="source.html" class="btn">Source 组件</a>
|
||
<a href="net.html" class="btn">Net 组件</a>
|
||
<a href="watch.html" class="btn">Watch 组件</a>
|
||
<a href="plugins.html" class="btn">Redkale 插件</a>
|
||
<a href="articles.html" class="btn">技术文章</a>
|
||
</section>
|
||
|
||
<section class="main-content">
|
||
<h3>Redkale 让你重新认识Java</h3>
|
||
|
||
<p>
|
||
Java 已经走过了二十二个年头,依靠强大的功能、庞大的开发社区和无人能及的生态系统,成为当之无愧的业界之王。<br/>
|
||
</p>
|
||
|
||
<p> <b>太臃肿</b></p>
|
||
<p>
|
||
如今在Java界,Tomcat、Struts2、Hibernate、MyBatis、Jetty、Spring MVC/Spring Boot/Spring XXX这些框架大家都耳熟能详,似乎不懂两三个以上都不好意思说自己会Java。在一些新手眼里,Java就是Tomcat、Java就是Spring。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的注解方式才得到普及, 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更是迄今为止还没有异步接口。其次开源框架以异步接口为主的凤毛麟角。 所以Java程序员在写业务代码时基本都是用同步方式,特别是最耗时的数据源操作JDBC无法异步。
|
||
</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里,IO操作都是异步的。这也是为什么有的用Nodejs做的系统比Java还快。Java在语言上和(NIO/NIO.2)框架的性能优势弥补不了同步的副作用。
|
||
</p>
|
||
<p> <b>新设计</b></p>
|
||
<p>
|
||
Redkale 一个全新设计的Java异步微服务框架。集HTTP、WebSocket、REST、JSON、RPC、DB操作、依赖注入等功能于一身,其jar包大小仅790K,且不依赖任何第三方包。
|
||
</p>
|
||
<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/Reproduce.html" target="_blank">org.redkale.util.Reproduce</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?b4e05d7de8b5f3401dd93e3c6b35ffa5";
|
||
var s = document.getElementsByTagName("script")[0];
|
||
s.parentNode.insertBefore(hm, s);
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|