<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sparkle&#039;s Workshop</title>
	<atom:link href="http://weavesky.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://weavesky.com</link>
	<description></description>
	<lastBuildDate>Fri, 30 Dec 2011 08:14:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>sbt 0.7</title>
		<link>http://weavesky.com/2011/12/30/sbt-7/</link>
		<comments>http://weavesky.com/2011/12/30/sbt-7/#comments</comments>
		<pubDate>Fri, 30 Dec 2011 08:13:06 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[sbt]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=665</guid>
		<description><![CDATA[前言：sbt是一个用scala写的构建工具，跟maven、gradle差不多，目前最新的版本是0.11。不过本文是讲sbt 0.7的使用方法，sbt继承了scala优良的不兼容传统，从0.7升级到0.10是完全不兼容的两个版本，虽然0.7已经基本没人用了，但还是有一些开源项目还没切换到0.11上。我这篇文章比较早就完成了，但因为各种原因现在才发出来。 sbt 0.7的项目地址是 http://code.google.com/p/simple-build-tool/，官方为了让大家尽快升级到0.10以上的版本，已经将这个地址里面大部分文档都删除了，目前要找到0.7的资料已经很难了，建议大家新项目还是直接用0.11。 先来看一下sbt（没有特殊说明的话，以下sbt都是指sbt 0.7）的配置结构，sbt使用maven的约定目录来放置项目文件，比如说src/main/java、src/main/resources等等，当然这是可以通过配置进行修改。而sbt本身的配置，是放在项目根目录下的project目录下，如果你见到一些scala的开源项目有个project目录不要觉得奇怪，那是sbt的配置。如果你的项目是多个子项目组成的，只需要在总的根目录下进行sbt配置即可，不需要像maven那样每个项目下配置pom.xml。 一般来说，sbt的配置有以下三个文件 /project/build.properties /project/build/MyProject.scala （文件名随意） /project/plugins/Plugins.scala （文件名随意） 第一个文件是项目的基本信息配置，这里一个范例 project.organization=org.sparkle project.name=myproject project.version=1.0-SNAPSHOT sbt.version=0.7.7 build.scala.versions=2.9.0-1 前三项对应maven里面的groupId、artifactId、version 后面两项分别定义项目所用的sbt和scala版本 第二个文件是主要的配置文件，得益于scala强大的描述能力，项目配置直接用实际的scala代码来编写，具体的含义直接看代码中的注释 import sbt._ &#160; class MyProject&#40;info: ProjectInfo&#41; extends ParentProject&#40;info&#41; &#123; // 通过at方法定义的变量自动成为额外的jar下载路径 val mavenLocal = &#34;Local Maven Repository&#34; at &#8230; <a class="more-link" href="http://weavesky.com/2011/12/30/sbt-7/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>前言：sbt是一个用scala写的构建工具，跟maven、gradle差不多，目前最新的版本是0.11。不过本文是讲sbt 0.7的使用方法，sbt继承了scala优良的不兼容传统，从0.7升级到0.10是完全不兼容的两个版本，虽然0.7已经基本没人用了，但还是有一些开源项目还没切换到0.11上。我这篇文章比较早就完成了，但因为各种原因现在才发出来。</p>
<p>sbt 0.7的项目地址是 http://code.google.com/p/simple-build-tool/，官方为了让大家尽快升级到0.10以上的版本，已经将这个地址里面大部分文档都删除了，目前要找到0.7的资料已经很难了，建议大家新项目还是直接用0.11。</p>
<p>先来看一下sbt（没有特殊说明的话，以下sbt都是指sbt 0.7）的配置结构，sbt使用maven的约定目录来放置项目文件，比如说src/main/java、src/main/resources等等，当然这是可以通过配置进行修改。而sbt本身的配置，是放在项目根目录下的project目录下，如果你见到一些scala的开源项目有个project目录不要觉得奇怪，那是sbt的配置。如果你的项目是多个子项目组成的，只需要在总的根目录下进行sbt配置即可，不需要像maven那样每个项目下配置pom.xml。</p>
<p>一般来说，sbt的配置有以下三个文件</p>
<pre>
/project/build.properties
/project/build/MyProject.scala （文件名随意）
/project/plugins/Plugins.scala （文件名随意）
</pre>
<p>第一个文件是项目的基本信息配置，这里一个范例</p>
<pre>
project.organization=org.sparkle
project.name=myproject
project.version=1.0-SNAPSHOT
sbt.version=0.7.7
build.scala.versions=2.9.0-1
</pre>
<p>前三项对应maven里面的groupId、artifactId、version<br />
后面两项分别定义项目所用的sbt和scala版本</p>
<p>第二个文件是主要的配置文件，得益于scala强大的描述能力，项目配置直接用实际的scala代码来编写，具体的含义直接看代码中的注释</p>

<div class="wp_syntax"><div class="code"><pre class="scala" style="font-family:monospace;"><span style="color: #0000ff; font-weight: bold;">import</span> sbt.<span style="color: #000080;">_</span>
&nbsp;
<span style="color: #0000ff; font-weight: bold;">class</span> MyProject<span style="color: #F78811;">&#40;</span>info<span style="color: #000080;">:</span> ProjectInfo<span style="color: #F78811;">&#41;</span> <span style="color: #0000ff; font-weight: bold;">extends</span> ParentProject<span style="color: #F78811;">&#40;</span>info<span style="color: #F78811;">&#41;</span> <span style="color: #F78811;">&#123;</span>
  <span style="color: #008000; font-style: italic;">// 通过at方法定义的变量自动成为额外的jar下载路径</span>
  <span style="color: #0000ff; font-weight: bold;">val</span> mavenLocal <span style="color: #000080;">=</span> <span style="color: #6666FF;">&quot;Local Maven Repository&quot;</span> at <span style="color: #6666FF;">&quot;file://&quot;</span> + Path.<span style="color: #000000;">userHome</span> + <span style="color: #6666FF;">&quot;/.m2/repository&quot;</span>
  <span style="color: #0000ff; font-weight: bold;">val</span> central <span style="color: #000080;">=</span> <span style="color: #6666FF;">&quot;central&quot;</span> at <span style="color: #6666FF;">&quot;http://192.168.1.88:18081/nexus/content/groups/public/&quot;</span>
&nbsp;
  <span style="color: #008000; font-style: italic;">// 定义项目路径名、使用的定义类（见下方）、依赖关系（这里web依赖core）</span>
  lazy <span style="color: #0000ff; font-weight: bold;">val</span> myprojectCore <span style="color: #000080;">=</span> project<span style="color: #F78811;">&#40;</span><span style="color: #6666FF;">&quot;myproject-core&quot;</span>, <span style="color: #6666FF;">&quot;myproject-core&quot;</span>, <span style="color: #0000ff; font-weight: bold;">new</span> MyprojectCoreProject<span style="color: #F78811;">&#40;</span><span style="color: #000080;">_</span><span style="color: #F78811;">&#41;</span><span style="color: #F78811;">&#41;</span>
  lazy <span style="color: #0000ff; font-weight: bold;">val</span> myprojectWeb <span style="color: #000080;">=</span> project<span style="color: #F78811;">&#40;</span><span style="color: #6666FF;">&quot;myproject-web&quot;</span>, <span style="color: #6666FF;">&quot;myproject-web&quot;</span>, <span style="color: #0000ff; font-weight: bold;">new</span> MyprojectWebProject<span style="color: #F78811;">&#40;</span><span style="color: #000080;">_</span><span style="color: #F78811;">&#41;</span>, myprojectCore<span style="color: #F78811;">&#41;</span>
&nbsp;
  <span style="color: #008000; font-style: italic;">// 通过类继承来定义通用配置</span>
  <span style="color: #0000ff; font-weight: bold;">abstract</span> <span style="color: #0000ff; font-weight: bold;">class</span> MyprojectBaseProject<span style="color: #F78811;">&#40;</span>info<span style="color: #000080;">:</span> ProjectInfo<span style="color: #F78811;">&#41;</span> <span style="color: #0000ff; font-weight: bold;">extends</span> DefaultProject<span style="color: #F78811;">&#40;</span>info<span style="color: #F78811;">&#41;</span> <span style="color: #F78811;">&#123;</span>
    <span style="color: #008000; font-style: italic;">// 编译选项</span>
    <span style="color: #0000ff; font-weight: bold;">override</span> <span style="color: #0000ff; font-weight: bold;">def</span> javaCompileOptions <span style="color: #000080;">=</span> <span style="color: #0000ff; font-weight: bold;">super</span>.<span style="color: #000000;">javaCompileOptions</span> ++ javaCompileOptions<span style="color: #F78811;">&#40;</span><span style="color: #6666FF;">&quot;-encoding&quot;</span>, <span style="color: #6666FF;">&quot;utf8&quot;</span><span style="color: #F78811;">&#41;</span>
&nbsp;
    <span style="color: #008000; font-style: italic;">// 直接调整ivy配置</span>
    <span style="color: #0000ff; font-weight: bold;">override</span> <span style="color: #0000ff; font-weight: bold;">def</span> ivyXML <span style="color: #000080;">=</span>
      <span style="color: #000080;">&lt;</span>dependencies<span style="color: #000080;">&gt;</span>
          <span style="color: #000080;">&lt;</span>exclude module<span style="color: #000080;">=</span><span style="color: #6666FF;">&quot;commons-logging&quot;</span>/<span style="color: #000080;">&gt;</span>
      <span style="color: #000080;">&lt;</span>/dependencies<span style="color: #000080;">&gt;</span>
&nbsp;
    <span style="color: #008000; font-style: italic;">// 直接定义一个sbt指令，如果用maven实现的话新建一个plugin项目啊</span>
    <span style="color: #0000ff; font-weight: bold;">val</span> deployPath <span style="color: #000080;">=</span> <span style="color: #6666FF;">&quot;target&quot;</span> / <span style="color: #6666FF;">&quot;deploy&quot;</span>
    <span style="color: #0000ff; font-weight: bold;">val</span> deployClean <span style="color: #000080;">=</span> task <span style="color: #F78811;">&#123;</span>
      FileUtilities.<span style="color: #000000;">clean</span><span style="color: #F78811;">&#40;</span>deployPath, log<span style="color: #F78811;">&#41;</span>
      None
    <span style="color: #F78811;">&#125;</span>
  <span style="color: #F78811;">&#125;</span>
&nbsp;
  <span style="color: #008000; font-style: italic;">// 以下的代码都是定义项目所依赖的类库</span>
  <span style="color: #0000ff; font-weight: bold;">class</span> MyprojectCoreProject<span style="color: #F78811;">&#40;</span>info<span style="color: #000080;">:</span> ProjectInfo<span style="color: #F78811;">&#41;</span> <span style="color: #0000ff; font-weight: bold;">extends</span> MyprojectBaseProject<span style="color: #F78811;">&#40;</span>info<span style="color: #F78811;">&#41;</span> <span style="color: #F78811;">&#123;</span>
    <span style="color: #0000ff; font-weight: bold;">val</span> springJdbc <span style="color: #000080;">=</span> <span style="color: #6666FF;">&quot;org.springframework&quot;</span> <span style="color: #000080;">%</span> <span style="color: #6666FF;">&quot;spring-jdbc&quot;</span> <span style="color: #000080;">%</span> <span style="color: #6666FF;">&quot;3.0.5.RELEASE&quot;</span>
    <span style="color: #0000ff; font-weight: bold;">val</span> springContextSupport <span style="color: #000080;">=</span> <span style="color: #6666FF;">&quot;org.springframework&quot;</span> <span style="color: #000080;">%</span> <span style="color: #6666FF;">&quot;spring-context-support&quot;</span> <span style="color: #000080;">%</span> <span style="color: #6666FF;">&quot;3.0.5.RELEASE&quot;</span>
&nbsp;
    <span style="color: #008000; font-style: italic;">// runtime scope</span>
    <span style="color: #0000ff; font-weight: bold;">val</span> mysqlConnectorJava <span style="color: #000080;">=</span> <span style="color: #6666FF;">&quot;mysql&quot;</span> <span style="color: #000080;">%</span> <span style="color: #6666FF;">&quot;mysql-connector-java&quot;</span> <span style="color: #000080;">%</span> <span style="color: #6666FF;">&quot;5.1.16&quot;</span> <span style="color: #000080;">%</span> <span style="color: #6666FF;">&quot;runtime&quot;</span>
&nbsp;
    <span style="color: #008000; font-style: italic;">// test scope</span>
    <span style="color: #0000ff; font-weight: bold;">val</span> junit <span style="color: #000080;">=</span> <span style="color: #6666FF;">&quot;junit&quot;</span> <span style="color: #000080;">%</span> <span style="color: #6666FF;">&quot;junit&quot;</span> <span style="color: #000080;">%</span> <span style="color: #6666FF;">&quot;4.8.2&quot;</span> <span style="color: #000080;">%</span> <span style="color: #6666FF;">&quot;test&quot;</span>
  <span style="color: #F78811;">&#125;</span>
&nbsp;
  <span style="color: #0000ff; font-weight: bold;">class</span> MyprojectWebProject<span style="color: #F78811;">&#40;</span>info<span style="color: #000080;">:</span> ProjectInfo<span style="color: #F78811;">&#41;</span> <span style="color: #0000ff; font-weight: bold;">extends</span> MyprojectBaseProject<span style="color: #F78811;">&#40;</span>info<span style="color: #F78811;">&#41;</span> <span style="color: #F78811;">&#123;</span>
    <span style="color: #0000ff; font-weight: bold;">val</span> springWebmvc <span style="color: #000080;">=</span> <span style="color: #6666FF;">&quot;org.springframework&quot;</span> <span style="color: #000080;">%</span> <span style="color: #6666FF;">&quot;spring-webmvc&quot;</span> <span style="color: #000080;">%</span> <span style="color: #6666FF;">&quot;3.0.5.RELEASE&quot;</span>
&nbsp;
    <span style="color: #008000; font-style: italic;">// provided scope</span>
    <span style="color: #0000ff; font-weight: bold;">val</span> jetty6 <span style="color: #000080;">=</span> <span style="color: #6666FF;">&quot;org.mortbay.jetty&quot;</span> <span style="color: #000080;">%</span> <span style="color: #6666FF;">&quot;jetty&quot;</span> <span style="color: #000080;">%</span> <span style="color: #6666FF;">&quot;6.1.26&quot;</span> <span style="color: #000080;">%</span> <span style="color: #6666FF;">&quot;provided&quot;</span>
  <span style="color: #F78811;">&#125;</span>
<span style="color: #F78811;">&#125;</span></pre></div></div>

<p>是不是比maven的pom.xml简洁非常多，而且还可以直接inline使用scala代码实现各种额外的功能，<a href="http://weavesky.com/2011/08/19/write-maven-plugin-1/">maven就要开一个plugin项目才能实现</a> </p>
<p>第三个文件是插件配置，sbt支持插件，可以理解为maven中的插件，大致的写法跟上一个文件很类似</p>

<div class="wp_syntax"><div class="code"><pre class="scala" style="font-family:monospace;"><span style="color: #0000ff; font-weight: bold;">import</span> sbt.<span style="color: #000080;">_</span>
&nbsp;
<span style="color: #0000ff; font-weight: bold;">class</span> Plugins<span style="color: #F78811;">&#40;</span>info<span style="color: #000080;">:</span> ProjectInfo<span style="color: #F78811;">&#41;</span> <span style="color: #0000ff; font-weight: bold;">extends</span> PluginDefinition<span style="color: #F78811;">&#40;</span>info<span style="color: #F78811;">&#41;</span> <span style="color: #F78811;">&#123;</span>
  <span style="color: #008000; font-style: italic;">//val junitInterface = &quot;com.novocode&quot; % &quot;junit-interface&quot; % &quot;0.7&quot;</span>
<span style="color: #F78811;">&#125;</span></pre></div></div>

<h2  class="related_post_title">Most Commented Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2008/01/25/mercurial-and-me/" title="我与Mercurial">我与Mercurial</a></li><li><a href="http://weavesky.com/2008/01/28/deploy-cruisecontrol/" title="架设你的CruiseControl">架设你的CruiseControl</a></li><li><a href="http://weavesky.com/2008/05/07/no-more-cacti/" title="我为什么放弃使用cacti">我为什么放弃使用cacti</a></li><li><a href="http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/" title="python cmemcache是不是线程安全的">python cmemcache是不是线程安全的</a></li><li><a href="http://weavesky.com/2009/05/15/python-memcached-lib-in-production/" title="python在生产环境可选的memcached lib">python在生产环境可选的memcached lib</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2011/12/30/sbt-7/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>如何编写maven plugin（三） 测试</title>
		<link>http://weavesky.com/2011/08/23/write-maven-plugin-3/</link>
		<comments>http://weavesky.com/2011/08/23/write-maven-plugin-3/#comments</comments>
		<pubDate>Tue, 23 Aug 2011 08:23:45 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=653</guid>
		<description><![CDATA[写完一个插件之后，我们就需要对他进行测试 如果我们用人工测试的话，将会非常麻烦，因为maven插件本身的发布流程就非常复杂 你需要编译打包你的maven插件，然后安装到本地库（或远程私库中），然后写一个sample project，再运行，看一下是否正确 当然你也可以用单元测试来解决一些问题，但是单元测试比较难保证插件最终正确，而且maven插件很经常是跟文件打交道 这里我们就需要对maven插件进行自动化的集成测试 maven的生命周期是包含集成测试的，默认是没有绑定任何功能。不过如果你google一下，会找到一些maven进行集成测试的例子，大致就是启动jetty，然后通过http访问验证，再关闭jetty 我们这里使用的是maven-invoker-plugin，它就是用于maven插件的集成测试 先在pom.xml中加入 &#60;build&#62; &#60;plugins&#62; &#60;plugin&#62; &#60;artifactId&#62;maven-invoker-plugin&#60;/artifactId&#62; &#60;configuration&#62; &#60;cloneProjectsTo&#62;${project.build.directory}/it&#60;/cloneProjectsTo&#62; &#60;/configuration&#62; &#60;executions&#62; &#60;execution&#62; &#60;id&#62;integration-test&#60;/id&#62; &#60;goals&#62; &#60;goal&#62;install&#60;/goal&#62; &#60;goal&#62;run&#60;/goal&#62; &#60;/goals&#62; &#60;/execution&#62; &#60;/executions&#62; &#60;/plugin&#62; &#60;/plugins&#62; &#60;/build&#62; cloneProjectsTo是先将测试案例拷贝出来再运行 execution段的设定是把maven-invoker-plugin的两个goal绑定到integration-test上 integration-test这个生命周期会在mvn install之前调用 集成测试的内容放在 src/it 目录下，每新建一个目录代表一个独立的测试，里面放一个完整的maven项目，当然你在这个项目里面需要引入自己编写的maven插件并且运行 另外还需要一个postbuild.groovy文件，放在测试案例的根目录，这个脚本的用处是检查运行后的maven项目是否达到自己要的效果。很明显，看名字就知道用groovy来写，一般我们会检查一下，是否产生了某某文件等等来判定，如果不正确的话抛出异常 然后我们在maven插件目录运行mvn integration-test就能进行集成测试了 如何编写maven plugin（一） &#8230; <a class="more-link" href="http://weavesky.com/2011/08/23/write-maven-plugin-3/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>写完一个插件之后，我们就需要对他进行测试<br />
如果我们用人工测试的话，将会非常麻烦，因为maven插件本身的发布流程就非常复杂<br />
你需要编译打包你的maven插件，然后安装到本地库（或远程私库中），然后写一个sample project，再运行，看一下是否正确<br />
当然你也可以用单元测试来解决一些问题，但是单元测试比较难保证插件最终正确，而且maven插件很经常是跟文件打交道</p>
<p>这里我们就需要对maven插件进行自动化的集成测试<br />
maven的生命周期是包含集成测试的，默认是没有绑定任何功能。不过如果你google一下，会找到一些maven进行集成测试的例子，大致就是启动jetty，然后通过http访问验证，再关闭jetty</p>
<p>我们这里使用的是maven-invoker-plugin，它就是用于maven插件的集成测试</p>
<p>先在pom.xml中加入</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;build<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugins<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-invoker-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;cloneProjectsTo<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>${project.build.directory}/it<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/cloneProjectsTo<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>integration-test<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>install<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>run<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugins<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/build<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>cloneProjectsTo是先将测试案例拷贝出来再运行<br />
execution段的设定是把maven-invoker-plugin的两个goal绑定到integration-test上<br />
integration-test这个生命周期会在mvn install之前调用</p>
<p>集成测试的内容放在 src/it 目录下，每新建一个目录代表一个独立的测试，里面放一个完整的maven项目，当然你在这个项目里面需要引入自己编写的maven插件并且运行<br />
另外还需要一个postbuild.groovy文件，放在测试案例的根目录，这个脚本的用处是检查运行后的maven项目是否达到自己要的效果。很明显，看名字就知道用groovy来写，一般我们会检查一下，是否产生了某某文件等等来判定，如果不正确的话抛出异常</p>
<p>然后我们在maven插件目录运行mvn integration-test就能进行集成测试了</p>
<ul>
<li><a href="http://weavesky.com/2011/08/19/write-maven-plugin-1/">如何编写maven plugin（一） 基础</a></li>
<li><a href="http://weavesky.com/2011/08/22/write-maven-plugin-2/">如何编写maven plugin（二） 注入</a></li>
<li>如何编写maven plugin（三） 测试</li>
</ul>
<h2  class="related_post_title">Most Commented Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2008/01/25/mercurial-and-me/" title="我与Mercurial">我与Mercurial</a></li><li><a href="http://weavesky.com/2008/01/28/deploy-cruisecontrol/" title="架设你的CruiseControl">架设你的CruiseControl</a></li><li><a href="http://weavesky.com/2008/05/07/no-more-cacti/" title="我为什么放弃使用cacti">我为什么放弃使用cacti</a></li><li><a href="http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/" title="python cmemcache是不是线程安全的">python cmemcache是不是线程安全的</a></li><li><a href="http://weavesky.com/2009/05/15/python-memcached-lib-in-production/" title="python在生产环境可选的memcached lib">python在生产环境可选的memcached lib</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2011/08/23/write-maven-plugin-3/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>如何编写maven plugin（二） 注入</title>
		<link>http://weavesky.com/2011/08/22/write-maven-plugin-2/</link>
		<comments>http://weavesky.com/2011/08/22/write-maven-plugin-2/#comments</comments>
		<pubDate>Mon, 22 Aug 2011 08:57:15 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=647</guid>
		<description><![CDATA[Mojo是一个很简单的Java Bean模式的类，你会发现Mojo所继承的AbstractMojo里面之后非常少的方法。那我们需要在Mojo.execute里面获取当前运行中的上下文如何处理呢？答案是注入，就是跟spring ioc差不多的注入方式。 常用的注入主要有两种，第一种是xml配置中的额外设置 比如说我们有这么一个plugin的配置 &#60;plugin&#62; &#60;artifactId&#62;maven-eclipse-plugin&#60;/artifactId&#62; &#60;configuration&#62; &#60;downloadSources&#62;true&#60;/downloadSources&#62; &#60;/configuration&#62; &#60;/plugin&#62; 所有写在configuration里面的属性都可以注入到Mojo中，比如说以下代码 /** * @parameter */ private boolean downloadSources; 就可以通过downloadSources变量获得配置中的值 值得注意的是，这里是不用生成完整的JavaBean模式的get/set的，并且private是有效的 javadoc里面还可以加入其他属性，比如说 /** * @parameter default-value=&#34;true&#34; * @readonly */ private boolean downloadSources; 就是默认为true，并且不能通过配置修改（当然我们这里肯定不会有这样的需求） 更多的javadoc可以参看官方文档中的说明 第二种注入的数据就是上下文，跟HttpServlet.getServletContext这种写法不一样，如果我们需要Mojo运行期的上下文，也是通过注入获得的 /** * @parameter expression=&#34;${project}&#34; * &#8230; <a class="more-link" href="http://weavesky.com/2011/08/22/write-maven-plugin-2/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Mojo是一个很简单的Java Bean模式的类，你会发现Mojo所继承的AbstractMojo里面之后非常少的方法。那我们需要在Mojo.execute里面获取当前运行中的上下文如何处理呢？答案是注入，就是跟spring ioc差不多的注入方式。</p>
<p>常用的注入主要有两种，第一种是xml配置中的额外设置<br />
比如说我们有这么一个plugin的配置</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-eclipse-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;downloadSources<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/downloadSources<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>所有写在configuration里面的属性都可以注入到Mojo中，比如说以下代码</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * @parameter
 */</span>
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">boolean</span> downloadSources<span style="color: #339933;">;</span></pre></div></div>

<p>就可以通过downloadSources变量获得配置中的值<br />
值得注意的是，这里是不用生成完整的JavaBean模式的get/set的，并且private是有效的</p>
<p>javadoc里面还可以加入其他属性，比如说</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * @parameter default-value=&quot;true&quot;
 * @readonly
 */</span>
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000066; font-weight: bold;">boolean</span> downloadSources<span style="color: #339933;">;</span></pre></div></div>

<p>就是默认为true，并且不能通过配置修改（当然我们这里肯定不会有这样的需求）<br />
更多的javadoc可以参看官方文档中的说明</p>
<p>第二种注入的数据就是上下文，跟HttpServlet.getServletContext这种写法不一样，如果我们需要Mojo运行期的上下文，也是通过注入获得的</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">/**
 * @parameter expression=&quot;${project}&quot;
 * @readonly
 */
private MavenProject project;
&nbsp;
/**
 * @component
 * @readonly
 */
private ArtifactFactory artifactFactory;</pre></div></div>

<p>例如这里我们就能获得ArtifactFactory和MavenProject<br />
需要注意的是这里可能有两种方法，第一种跟xml配置获得的方法差不多，通过expression指定名字<br />
实际上，你在xml里面，也可以通过${project}获得相应的东西进行一些简单的操作（当然xml里面只能文本描述，这里是一个类）</p>
<p>另外一种就是使用@component这个标注，可以获得一些基本的组件实例</p>
<ul>
<li><a href="http://weavesky.com/2011/08/19/write-maven-plugin-1/">如何编写maven plugin（一） 基础</a></li>
<li>如何编写maven plugin（二） 注入</li>
<li><a href="http://weavesky.com/2011/08/23/write-maven-plugin-3/">如何编写maven plugin（三） 测试</a></li>
</ul>
<h2  class="related_post_title">Most Commented Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2008/01/25/mercurial-and-me/" title="我与Mercurial">我与Mercurial</a></li><li><a href="http://weavesky.com/2008/01/28/deploy-cruisecontrol/" title="架设你的CruiseControl">架设你的CruiseControl</a></li><li><a href="http://weavesky.com/2008/05/07/no-more-cacti/" title="我为什么放弃使用cacti">我为什么放弃使用cacti</a></li><li><a href="http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/" title="python cmemcache是不是线程安全的">python cmemcache是不是线程安全的</a></li><li><a href="http://weavesky.com/2009/05/15/python-memcached-lib-in-production/" title="python在生产环境可选的memcached lib">python在生产环境可选的memcached lib</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2011/08/22/write-maven-plugin-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>如何编写maven plugin（一） 基础</title>
		<link>http://weavesky.com/2011/08/19/write-maven-plugin-1/</link>
		<comments>http://weavesky.com/2011/08/19/write-maven-plugin-1/#comments</comments>
		<pubDate>Fri, 19 Aug 2011 07:41:53 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=639</guid>
		<description><![CDATA[当maven内置的功能不能满足需求的时候怎么办，那就只能给它写插件了。 （话说回来，给maven扩展只能写一个很完整的插件，而不能是一个简单的script，真的是太笨重了） 网络上很多maven的文章，但基本很少谈及如何给它写插件，即使你搜索maven plugin，也只是给你返回一堆如何使用maven插件的文章。希望这边文章能给一些maven使用者带来帮助。 我在这里先假设你已经懂得使用maven，我不会贴出完整的pom.xml文件 首先，你需要创建一个maven项目，插件是一种特殊的maven项目 然后修改pom.xml，将packaging改为maven-plugin &#60;packaging&#62;maven-plugin&#60;/packaging&#62; 通过properties定义maven的版本 &#60;properties&#62; &#60;maven.version&#62;2.2.1&#60;/maven.version&#62; &#60;/properties&#62; maven3已经出了很久，并且兼容maven2，因此我们团队内部都是统一使用maven3，但是我这里编写插件使用的是maven2，可以同时在maven2和maven3下使用，不过其实这个原因并不重要，真正的原因是因为maven3的代码实在太烂了，最初的时候我用maven3的api lib来写，发现里面很多代码根本没有注释，而且很多代码已经废弃，但是并没有明确说明究竟用什么方法代替。最后我使用了maven2中被maven3废弃的api来完成我的功能，跑的挺好的，就是有时可能会有一些使用准备废弃的api的提醒而已。 接着添加依赖 &#60;dependencies&#62; &#60;dependency&#62; &#60;groupId&#62;org.apache.maven&#60;/groupId&#62; &#60;artifactId&#62;maven-plugin-api&#60;/artifactId&#62; &#60;version&#62;${maven.version}&#60;/version&#62; &#60;/dependency&#62; &#60;dependency&#62; &#60;groupId&#62;org.apache.maven&#60;/groupId&#62; &#60;artifactId&#62;maven-core&#60;/artifactId&#62; &#60;version&#62;${maven.version}&#60;/version&#62; &#60;/dependency&#62; &#60;/dependencies&#62; 然后开始创建Mojo类，maven插件里面每一个具体的功能都是一个Mojo 比如说eclipse:clean和eclipse:eclipse就是两个Mojo /** * @goal helloWorld */ public class HelloWorldMojo extends AbstractMojo &#123; &#8230; <a class="more-link" href="http://weavesky.com/2011/08/19/write-maven-plugin-1/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>当maven内置的功能不能满足需求的时候怎么办，那就只能给它写插件了。<br />
（话说回来，给maven扩展只能写一个很完整的插件，而不能是一个简单的script，真的是太笨重了）</p>
<p>网络上很多maven的文章，但基本很少谈及如何给它写插件，即使你搜索maven plugin，也只是给你返回一堆如何使用maven插件的文章。希望这边文章能给一些maven使用者带来帮助。</p>
<p>我在这里先假设你已经懂得使用maven，我不会贴出完整的pom.xml文件</p>
<p>首先，你需要创建一个maven项目，插件是一种特殊的maven项目<br />
然后修改pom.xml，将packaging改为maven-plugin</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;packaging<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/packaging<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>通过properties定义maven的版本</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;properties<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;maven.version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.2.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/maven.version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/properties<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>maven3已经出了很久，并且兼容maven2，因此我们团队内部都是统一使用maven3，但是我这里编写插件使用的是maven2，可以同时在maven2和maven3下使用，不过其实这个原因并不重要，真正的原因是因为maven3的代码实在太烂了，最初的时候我用maven3的api lib来写，发现里面很多代码根本没有注释，而且很多代码已经废弃，但是并没有明确说明究竟用什么方法代替。最后我使用了maven2中被maven3废弃的api来完成我的功能，跑的挺好的，就是有时可能会有一些使用准备废弃的api的提醒而已。</p>
<p>接着添加依赖</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.maven<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-plugin-api<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>${maven.version}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.maven<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-core<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>${maven.version}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>然后开始创建Mojo类，maven插件里面每一个具体的功能都是一个Mojo<br />
比如说eclipse:clean和eclipse:eclipse就是两个Mojo</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * @goal helloWorld
 */</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> HelloWorldMojo <span style="color: #000000; font-weight: bold;">extends</span> AbstractMojo <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> execute<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> MojoExecutionException
    <span style="color: #009900;">&#123;</span>
        getLog<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">info</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Hello, world!&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>首先继承AbstractMojo，并且实现execute()方法，这个就是每次调用进入的地方<br />
然后需要在类的Javadoc上定义，这是一个annotation出来之前常用的定义方法（或许未来maven会将它改成annotation，那就能提供编译校验和IDE校验）。我们必须定义@goal，代表运行目标，简单来说就是eclipse:clean中的clean<br />
Mojo写在哪个package底下都是可以的</p>
<p>这样，我们就完成了一个简单的maven plugin，然后我们需要一个简单的测试来确定他正确运行<br />
先通过maven install将它安装到本地仓库</p>
<p>然后打开任意maven的项目（比如说我们原来已经在用maven的项目），在pom.xml增加一个plugin</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;build<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugins<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>xxx<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>xxx<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>xxx<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;phase<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>compile<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/phase<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
              <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>helloWorld<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
          <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
      <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugins<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/build<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>需要留意的是phase部分，我们将这个plugin绑定到compile这个周期<br />
然后我们运行mvn compile，就能成功看见Hello, world!输出<br />
（当然你也可以直接通过命令行运行，需要带上完整的groupId和artifactId才能调用）</p>
<ul>
<li>如何编写maven plugin（一） 基础</li>
<li><a href="http://weavesky.com/2011/08/22/write-maven-plugin-2/">如何编写maven plugin（二） 注入</a></li>
<li><a href="http://weavesky.com/2011/08/23/write-maven-plugin-3/">如何编写maven plugin（三） 测试</a></li>
</ul>
<h2  class="related_post_title">Most Commented Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2008/01/25/mercurial-and-me/" title="我与Mercurial">我与Mercurial</a></li><li><a href="http://weavesky.com/2008/01/28/deploy-cruisecontrol/" title="架设你的CruiseControl">架设你的CruiseControl</a></li><li><a href="http://weavesky.com/2008/05/07/no-more-cacti/" title="我为什么放弃使用cacti">我为什么放弃使用cacti</a></li><li><a href="http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/" title="python cmemcache是不是线程安全的">python cmemcache是不是线程安全的</a></li><li><a href="http://weavesky.com/2009/05/15/python-memcached-lib-in-production/" title="python在生产环境可选的memcached lib">python在生产环境可选的memcached lib</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2011/08/19/write-maven-plugin-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用maven进行scala项目的构建</title>
		<link>http://weavesky.com/2011/08/16/maven-scala/</link>
		<comments>http://weavesky.com/2011/08/16/maven-scala/#comments</comments>
		<pubDate>Tue, 16 Aug 2011 03:49:10 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=627</guid>
		<description><![CDATA[目标： 1、命令行用maven进行scala项目构建 2、产生eclipse项目文件 pom.xml文件 &#60;project xmlns=&#34;http://maven.apache.org/POM/4.0.0&#34; xmlns:xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34; xsi:schemaLocation=&#34;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&#34;&#62; &#60;groupId&#62;com.xxx&#60;/groupId&#62; &#60;artifactId&#62;xxx&#60;/artifactId&#62; &#60;version&#62;1.0-SNAPSHOT&#60;/version&#62; &#60;modelVersion&#62;4.0.0&#60;/modelVersion&#62; &#160; &#60;properties&#62; &#60;scala.version&#62;2.8.1&#60;/scala.version&#62; &#60;/properties&#62; &#160; &#60;build&#62; &#60;plugins&#62; &#60;plugin&#62; &#60;artifactId&#62;maven-eclipse-plugin&#60;/artifactId&#62; &#60;configuration&#62; &#60;downloadSources&#62;true&#60;/downloadSources&#62; &#60;buildcommands&#62; &#60;buildcommand&#62;org.scala-ide.sdt.core.scalabuilder&#60;/buildcommand&#62; &#60;/buildcommands&#62; &#60;projectnatures&#62; &#60;projectnature&#62;org.scala-ide.sdt.core.scalanature&#60;/projectnature&#62; &#60;projectnature&#62;org.eclipse.jdt.core.javanature&#60;/projectnature&#62; &#60;/projectnatures&#62; &#60;classpathContainers&#62; &#60;classpathContainer&#62;org.eclipse.jdt.launching.JRE_CONTAINER&#60;/classpathContainer&#62; &#60;classpathContainer&#62;org.scala-ide.sdt.launching.SCALA_CONTAINER&#60;/classpathContainer&#62; &#60;/classpathContainers&#62; &#60;sourceIncludes&#62; &#60;sourceInclude&#62;**/*.scala&#60;/sourceInclude&#62; &#60;/sourceIncludes&#62; &#60;/configuration&#62; &#60;/plugin&#62; &#8230; <a class="more-link" href="http://weavesky.com/2011/08/16/maven-scala/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>目标：</strong><br />
1、命令行用maven进行scala项目构建<br />
2、产生eclipse项目文件</p>
<p><strong>pom.xml文件</strong></p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;project</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://maven.apache.org/POM/4.0.0&quot;</span> <span style="color: #000066;">xmlns:xsi</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span>
<span style="color: #009900;">	<span style="color: #000066;">xsi:schemaLocation</span>=<span style="color: #ff0000;">&quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.xxx<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>xxx<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.0-SNAPSHOT<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;modelVersion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>4.0.0<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/modelVersion<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;properties<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scala.version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.8.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scala.version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/properties<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;build<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugins<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-eclipse-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;downloadSources<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/downloadSources<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;buildcommands<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;buildcommand<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.scala-ide.sdt.core.scalabuilder<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/buildcommand<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/buildcommands<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;projectnatures<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;projectnature<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.scala-ide.sdt.core.scalanature<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/projectnature<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;projectnature<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.eclipse.jdt.core.javanature<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/projectnature<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/projectnatures<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;classpathContainers<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;classpathContainer<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.eclipse.jdt.launching.JRE_CONTAINER<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/classpathContainer<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;classpathContainer<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.scala-ide.sdt.launching.SCALA_CONTAINER<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/classpathContainer<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/classpathContainers<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sourceIncludes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sourceInclude<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>**/*.scala<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sourceInclude<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sourceIncludes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.scala-tools<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-scala-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
							<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>compile<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
							<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>testCompile<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.codehaus.mojo<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>build-helper-maven-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>add-source<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;phase<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>generate-sources<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/phase<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
							<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>add-source<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
							<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sources<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
								<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;source<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>src/main/scala<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/source<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
							<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sources<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>add-test-source<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;phase<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>generate-sources<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/phase<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
							<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>add-test-source<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
							<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sources<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
								<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;source<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>src/test/scala<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/source<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
							<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sources<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
						<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
					<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
				<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
			<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugins<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/build<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/project<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p><strong>要点分析</strong></p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;properties<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
		<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scala.version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.8.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scala.version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/properties<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>通过properties定义scala的版本<br />
因为scala的版本是不兼容的，比如说2.8编译的class文件不能跟2.9的类库一起使用<br />
这个定义同时会影响maven-scala-plugin中使用的scala版本<br />
当然你也可以在dependencies中通过${scala.version}使用这个版本号</p>
<p>maven-eclipse-plugin部分是产生eclipse项目，对应使用scala-ide<br />
打开downloadSources下载类库源代码，可以在eclipse中直接查看<br />
sourceIncludes段必须加入，不然会出现代码目录中看不到scala文件的情况</p>
<p>maven-scala-plugin段用于命令行用maven进行构建</p>
<p>build-helper-maven-plugin段用于引入额外的代码目录<br />
这个配置同时对命令行构建和eclipse项目生成有效<br />
我这个是一个mixed Java/Scala项目</p>
<h2  class="related_post_title">Most Commented Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2008/01/25/mercurial-and-me/" title="我与Mercurial">我与Mercurial</a></li><li><a href="http://weavesky.com/2008/01/28/deploy-cruisecontrol/" title="架设你的CruiseControl">架设你的CruiseControl</a></li><li><a href="http://weavesky.com/2008/05/07/no-more-cacti/" title="我为什么放弃使用cacti">我为什么放弃使用cacti</a></li><li><a href="http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/" title="python cmemcache是不是线程安全的">python cmemcache是不是线程安全的</a></li><li><a href="http://weavesky.com/2009/05/15/python-memcached-lib-in-production/" title="python在生产环境可选的memcached lib">python在生产环境可选的memcached lib</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2011/08/16/maven-scala/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>在Sandy Bridge上安装Snow Leopard</title>
		<link>http://weavesky.com/2011/05/03/sandy-bridge-snow-leopard/</link>
		<comments>http://weavesky.com/2011/05/03/sandy-bridge-snow-leopard/#comments</comments>
		<pubDate>Tue, 03 May 2011 13:18:15 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=608</guid>
		<description><![CDATA[把家里的主机从AMD平台转到Intel平台之后，就一直想在上面装一个Snow Leopard来使用，虽然曾经拥有过一台最早的Intel MacBook，不过已经有一段时间没有使用Mac OS了。坦白说，三大操作系统（Windows、Linux、Mac OS）里面，Mac OS同时拥有对程序员良好的*NIX内核，比美Windows的操作界面（甚至更好），可能是最好的开发平台。 Mac的笔记本不算太贵，个人比较推荐，至于台式机部分，Mac mini有点太弱（不过外观相当好），iMac也相当划算（前提是你还没买显示器），我已经有了自己的主机，所以打算在上面装黑苹果。不过，如果你想用Mac OS来开发的话，其实最好买一台真正的Mac，这样可以减少你折腾的时间，把时间花在使用上。 先来说我的机器主要配置： 华擎 H67M + i5 2300 + 华硕 GT240（后加） 如果你不是太新或者太旧的Intel CPU的话，基本上都能支持，因为Mac用过这些CPU，所以AMD比较悲剧了，不过你依然能找到一些被修改过的kernel来使用。Sandy Bridge的CPU属于太新的CPU，虽然最新的MacBook Pro是使用这个CPU，但不知道为什么苹果是给他做了一个单独的10.6.7的更新包，也就是说默认的10.6.7更新包里面所包含的kernel是不支持Sandy Bridge的，有人从专用更新包里面提取了kernel出来，但是不知道为什么在很多主板上，这个kernel不能启动，我的主板就是这样的情况，因此我最后只能使用修改过的kernel。 一般来说，主板和CPU是决定你是否能够启动Snow Leopard的主要因素。不过，决定你的黑苹果是否好用的就是能否找到外设的驱动了，比如说网卡、声卡、显卡等等。目前黑苹果已经很成熟了，能找到很多爱好者写的驱动。我的主板上的外设基本上都被支持，可惜i5 2300的核显暂时还没有解决方案（虽然最新版的MacBook Pro就是使用这个显卡，理论上苹果已经提供了它的驱动，可惜目前还没有办法在黑苹果上使用它），于是上淘宝买了一张GT240，完美支持。 安装方法有几种，一个就是用一些已经打包好的整合碟，里面有破解内核和第三方驱动等，如果你是AMD的CPU最好用这些碟来安装，另一个就是用iBoot+MultiBeast和原版碟来安装，只支持Intel CPU，如果你是Intel CPU的话，推荐用这个方案，装出来的系统比较纯正一点。 网上已经有一些iBoot+MultiBeast的安装方法，大家可以搜索参考一些，这里就不说一些细节，重点是在Sandy Bridge的问题上。到http://www.tonymacx86.com/下载iBoot，必须注意的是必须使用Legacy版，因为Sandy Bridge CPU未被支持的缘故。刻碟启动，然后换Snow Leopard安装碟，安装。装完之后再用iBoot启动，就可以引导硬盘中的系统。 启动成功后，先安装10.6.7更新，不要重启，下载MultiBeast，安装。虽然DSDT的方法是最完美的，不过也很麻烦，需要导出主板等的BIOS来修改。我这里就用EasyBeast的方法来安装，必选EasyBeast、System Utilities，下面的驱动就看自己需要选择。声卡部分，我用ALC8xxHDA（优先选择，不行的话可以尝试VoodooHDA），还需要选上AppleHDA Rollback，这里还需要把自己的声卡ID写进DSDT里面，因为我不用DSDT，所以还需要勾上Non-DSDT HDAEnabler里面相应的声卡型号，显卡部分直接勾上NVEnabler就行了。 接下来是针对Sandy &#8230; <a class="more-link" href="http://weavesky.com/2011/05/03/sandy-bridge-snow-leopard/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>把家里的主机从AMD平台转到Intel平台之后，就一直想在上面装一个Snow Leopard来使用，虽然曾经拥有过一台最早的Intel MacBook，不过已经有一段时间没有使用Mac OS了。坦白说，三大操作系统（Windows、Linux、Mac OS）里面，Mac OS同时拥有对程序员良好的*NIX内核，比美Windows的操作界面（甚至更好），可能是最好的开发平台。</p>
<p>Mac的笔记本不算太贵，个人比较推荐，至于台式机部分，Mac mini有点太弱（不过外观相当好），iMac也相当划算（前提是你还没买显示器），我已经有了自己的主机，所以打算在上面装黑苹果。不过，如果你想用Mac OS来开发的话，其实最好买一台真正的Mac，这样可以减少你折腾的时间，把时间花在使用上。</p>
<p>先来说我的机器主要配置：<br />
华擎 H67M + i5 2300 + 华硕 GT240（后加）</p>
<p>如果你不是太新或者太旧的Intel CPU的话，基本上都能支持，因为Mac用过这些CPU，所以AMD比较悲剧了，不过你依然能找到一些被修改过的kernel来使用。Sandy Bridge的CPU属于太新的CPU，虽然最新的MacBook Pro是使用这个CPU，但不知道为什么苹果是给他做了一个单独的10.6.7的更新包，也就是说默认的10.6.7更新包里面所包含的kernel是不支持Sandy Bridge的，有人从专用更新包里面提取了kernel出来，但是不知道为什么在很多主板上，这个kernel不能启动，我的主板就是这样的情况，因此我最后只能使用修改过的kernel。</p>
<p>一般来说，主板和CPU是决定你是否能够启动Snow Leopard的主要因素。不过，决定你的黑苹果是否好用的就是能否找到外设的驱动了，比如说网卡、声卡、显卡等等。目前黑苹果已经很成熟了，能找到很多爱好者写的驱动。我的主板上的外设基本上都被支持，可惜i5 2300的核显暂时还没有解决方案（虽然最新版的MacBook Pro就是使用这个显卡，理论上苹果已经提供了它的驱动，可惜目前还没有办法在黑苹果上使用它），于是上淘宝买了一张GT240，完美支持。</p>
<p>安装方法有几种，一个就是用一些已经打包好的整合碟，里面有破解内核和第三方驱动等，如果你是AMD的CPU最好用这些碟来安装，另一个就是用iBoot+MultiBeast和原版碟来安装，只支持Intel CPU，如果你是Intel CPU的话，推荐用这个方案，装出来的系统比较纯正一点。</p>
<p>网上已经有一些iBoot+MultiBeast的安装方法，大家可以搜索参考一些，这里就不说一些细节，重点是在Sandy Bridge的问题上。到http://www.tonymacx86.com/下载iBoot，必须注意的是<strong>必须使用Legacy版</strong>，因为Sandy Bridge CPU未被支持的缘故。刻碟启动，然后换Snow Leopard安装碟，安装。装完之后再用iBoot启动，就可以引导硬盘中的系统。</p>
<p>启动成功后，先安装10.6.7更新，不要重启，下载MultiBeast，安装。虽然DSDT的方法是最完美的，不过也很麻烦，需要导出主板等的BIOS来修改。我这里就用EasyBeast的方法来安装，必选EasyBeast、System Utilities，下面的驱动就看自己需要选择。声卡部分，我用ALC8xxHDA（优先选择，不行的话可以尝试VoodooHDA），还需要选上AppleHDA Rollback，这里还需要把自己的声卡ID写进DSDT里面，因为我不用DSDT，所以还需要勾上Non-DSDT HDAEnabler里面相应的声卡型号，显卡部分直接勾上NVEnabler就行了。</p>
<p>接下来是针对Sandy Bridge的处理，官方给出的方法是一个BridgeHelper的软件，其实就是安装最新的MacBook Pro里面的kernel，你可以先试一下这个方案，如果可以启动系统的话，优先选择这个方案。可惜我的主板不行，于是我<strong>从iBoot Legacy里提取了kernel</strong>，替换系统的。</p>
<p>另外，我还遇到一个问题是鼠标的移动会很卡的情况，好像是因为时钟频率不正确的缘故，需要在启动参数里面<strong>增加busratio=28</strong>（28是我的CPU的实际倍频数）</p>
<p>这样，我的黑苹果就装好了。虽然还有些小问题，不过我暂时不打算处理了，能正常使用就行了。</p>
<p>下一步需要处理的问题有<br />
1、休眠。需要相应kernel的sleep enabler。由于我的是台式机，我觉得休眠不是很重要就不处理了。<br />
2、HDMI输出，并且带上声音。是的，黑苹果也能这样。tonymacx86上已经提供了解决方案<br />
3、DSDT，为了让系统属性里面正确显示各种硬件信息<br />
4、真正的Sandy Bridge支持。CPU和显卡</p>
<h2  class="related_post_title">Most Commented Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2008/01/25/mercurial-and-me/" title="我与Mercurial">我与Mercurial</a></li><li><a href="http://weavesky.com/2008/01/28/deploy-cruisecontrol/" title="架设你的CruiseControl">架设你的CruiseControl</a></li><li><a href="http://weavesky.com/2008/05/07/no-more-cacti/" title="我为什么放弃使用cacti">我为什么放弃使用cacti</a></li><li><a href="http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/" title="python cmemcache是不是线程安全的">python cmemcache是不是线程安全的</a></li><li><a href="http://weavesky.com/2009/05/15/python-memcached-lib-in-production/" title="python在生产环境可选的memcached lib">python在生产环境可选的memcached lib</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2011/05/03/sandy-bridge-snow-leopard/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MongoDB介绍</title>
		<link>http://weavesky.com/2010/11/22/mongodb/</link>
		<comments>http://weavesky.com/2010/11/22/mongodb/#comments</comments>
		<pubDate>Mon, 22 Nov 2010 08:59:25 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=603</guid>
		<description><![CDATA[2010-11-20在广州小沙龙的ppt，时间比较匆忙写的比较简单 MongoDB介绍 View more presentations from popeast. Most Commented Posts我与Mercurial架设你的CruiseControl我为什么放弃使用cactipython cmemcache是不是线程安全的python在生产环境可选的memcached lib]]></description>
			<content:encoded><![CDATA[<div id="__ss_5855482" style="width: 425px;">2010-11-20在广州小沙龙的ppt，时间比较匆忙写的比较简单</div>
<div style="width: 425px;"></div>
<div style="width: 425px;"><strong><a title="MongoDB介绍" href="http://www.slideshare.net/popeast/mongodb-5855482">MongoDB介绍</a></strong><object id="__sse5855482" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=mongodb-101121193802-phpapp02&amp;stripped_title=mongodb-5855482&amp;userName=popeast" /><param name="name" value="__sse5855482" /><param name="allowfullscreen" value="true" /><embed id="__sse5855482" type="application/x-shockwave-flash" width="425" height="355" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=mongodb-101121193802-phpapp02&amp;stripped_title=mongodb-5855482&amp;userName=popeast" name="__sse5855482" allowscriptaccess="always" allowfullscreen="true"></embed></object></div>
<div id="__ss_5855482" style="width: 425px;">
<div style="padding: 5px 0 12px;">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/popeast">popeast</a>.</div>
</div>
<h2  class="related_post_title">Most Commented Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2008/01/25/mercurial-and-me/" title="我与Mercurial">我与Mercurial</a></li><li><a href="http://weavesky.com/2008/01/28/deploy-cruisecontrol/" title="架设你的CruiseControl">架设你的CruiseControl</a></li><li><a href="http://weavesky.com/2008/05/07/no-more-cacti/" title="我为什么放弃使用cacti">我为什么放弃使用cacti</a></li><li><a href="http://weavesky.com/2009/02/14/is-python-cmemcache-threadsafe/" title="python cmemcache是不是线程安全的">python cmemcache是不是线程安全的</a></li><li><a href="http://weavesky.com/2009/05/15/python-memcached-lib-in-production/" title="python在生产环境可选的memcached lib">python在生产环境可选的memcached lib</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2010/11/22/mongodb/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>基于MINA构建简单高性能的NIO应用-优化指南</title>
		<link>http://weavesky.com/2010/02/19/mina-article-4/</link>
		<comments>http://weavesky.com/2010/02/19/mina-article-4/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 09:26:13 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[mina]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=600</guid>
		<description><![CDATA[本文为Sparkle发于《程序员》2008年2月刊的文章，与《程序员》的协议，可以在个人博客中发布，转载请保留出处。 优化指南 MINA默认配置的性能并不是很高的，部分原因是MINA目前还保留初期版本的架构，另外一个原因是因为JVM的发展。 首先我们关闭默认的ThreadModel设置 IoAcceptor acceptor = ...; IoServiceConfig acceptorConfig = acceptor.getDefaultConfig&#40;&#41;; acceptorConfig.setThreadModel&#40;ThreadModel.MANUAL&#41;; ThreadModel是一个很简单的线程实现，用于IoService。但是它实在太弱，以至于在并发环境产生大量问题。在MINA 2.0中，ThreadModel直接被取消。你应该使用ExecutorFilter来实现线程。 然后我们增加I/O处理线程(Article by Sparkle) 每一个Acceptor/Connector都使用一个线程来处理连接，然后把连接发送给I/O processor进行读写操作，我们只可以修改I/O processor使用的线程数，用以下代码设置 IoAcceptor acceptor = new SocketAcceptor&#40;Runtime.getRuntime&#40;&#41;.availableProcessors&#40;&#41; + 1, Executors.newCachedThreadPool&#40;&#41;&#41;; 当然是要将ExecutorFilter加入，上文已经很详细地描述了 acceptor.getDefaultConfig&#40;&#41;.getFilterChain&#40;&#41;.addLast&#40;&#34;threadPool&#34;, new ExecutorFilter&#40;Executors.newCachedThreadPool&#40;&#41;&#41;; 笔者在开发过程中，多次遇到OutOfMemoryError，经过研究之后才发现原因。MINA默认是使用direct memory实现ByteBuffer池的方案（以下简称direct buffer），通过JNI在内存开辟一段空间来使用，该方案在早期的MINA版本中是一个非常好的特性，那是因为MINA开发初期，JVM并没有现在的强大，带有池效果的direct buffer性能比较好。但是当我们使用-Xms -Xmx等指令增加JVM可使用的内存，那仅仅增加了堆的内存空间，而direct memory的空间并没有增加，导致MINA实际使用的时候经常出现OutOfMemoryError。如果你的确想使用direct memory，可以通过-XX:MaxDirectMemorySize选项来设置。不过笔者不建议这样做，因为最新的测试表明，在现代的JVM里面，direct &#8230; <a class="more-link" href="http://weavesky.com/2010/02/19/mina-article-4/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<blockquote><p>本文为Sparkle发于《程序员》2008年2月刊的文章，与《程序员》的协议，可以在个人博客中发布，转载请保留出处。</p></blockquote>
<p><strong>优化指南</strong><br />
MINA默认配置的性能并不是很高的，部分原因是MINA目前还保留初期版本的架构，另外一个原因是因为JVM的发展。</p>
<p>首先我们关闭默认的ThreadModel设置</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">IoAcceptor acceptor <span style="color: #339933;">=</span> ...<span style="color: #339933;">;</span>
IoServiceConfig acceptorConfig <span style="color: #339933;">=</span> acceptor.<span style="color: #006633;">getDefaultConfig</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
acceptorConfig.<span style="color: #006633;">setThreadModel</span><span style="color: #009900;">&#40;</span>ThreadModel.<span style="color: #006633;">MANUAL</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>ThreadModel是一个很简单的线程实现，用于IoService。但是它实在太弱，以至于在并发环境产生大量问题。在MINA 2.0中，ThreadModel直接被取消。你应该使用ExecutorFilter来实现线程。</p>
<p>然后我们增加I/O处理线程<span style="color: #ffffff;">(Article by Sparkle)</span><br />
每一个Acceptor/Connector都使用一个线程来处理连接，然后把连接发送给I/O processor进行读写操作，我们只可以修改I/O processor使用的线程数，用以下代码设置</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">IoAcceptor acceptor <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> SocketAcceptor<span style="color: #009900;">&#40;</span><span style="color: #003399;">Runtime</span>.<span style="color: #006633;">getRuntime</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">availableProcessors</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #cc66cc;">1</span>, Executors.<span style="color: #006633;">newCachedThreadPool</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>当然是要将ExecutorFilter加入，上文已经很详细地描述了</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">acceptor.<span style="color: #006633;">getDefaultConfig</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getFilterChain</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">addLast</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;threadPool&quot;</span>, <span style="color: #000000; font-weight: bold;">new</span> ExecutorFilter<span style="color: #009900;">&#40;</span>Executors.<span style="color: #006633;">newCachedThreadPool</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>笔者在开发过程中，多次遇到OutOfMemoryError，经过研究之后才发现原因。MINA默认是使用direct memory实现ByteBuffer池的方案（以下简称direct buffer），通过JNI在内存开辟一段空间来使用，该方案在早期的MINA版本中是一个非常好的特性，那是因为MINA开发初期，JVM并没有现在的强大，带有池效果的direct buffer性能比较好。但是当我们使用-Xms -Xmx等指令增加JVM可使用的内存，那仅仅增加了堆的内存空间，而direct memory的空间并没有增加，导致MINA实际使用的时候经常出现OutOfMemoryError。如果你的确想使用direct memory，可以通过-XX:MaxDirectMemorySize选项来设置。不过笔者不建议这样做，因为最新的测试表明，在现代的JVM里面，direct memory比堆的表现更差。这里可能有读者会觉得奇怪，为什么不用池，而要用堆呢，而且还需要gc。那是因为现在的JVM gc能力已经很强了，而且在并发环境里面，pool的同步也是一个性能的问题。我们可以通过这样的代码进行设置<span style="color: #ffffff;">(Article by Sparkle)</span></p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">ByteBuffer.<span style="color: #006633;">setUseDirectBuffers</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
ByteBuffer.<span style="color: #006633;">setAllocator</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> SimpleByteBufferAllocator<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>MINA 2.0已经默认把直接内存分配改成堆，为了提供最好的性能和稳定性。</p>
<p>最后一条优化技巧就是，把你的应用部署在Linux上，并且打开Java NIO使用Linux epoll的功能。可能你还没听过epoll，但是你应该听过Lighttpd、Nginx、Squid等，得益于epoll，它们提供很高的网络性能，还占用非常少的系统资源。JDK6已经默认把epoll配置打开，因此笔者建议把你的应用部署在JDK6上面，也同时因为JDK6还有别的优化特性。如果你的应用必须部署在JDK5上，你也可以通过参数把epoll支持打开。</p>
<p><strong>文章快速索引</strong></p>
<ol>
<li><a href="http://weavesky.com/2010/02/19/mina-article-1/">前言</a></li>
<li><a href="http://weavesky.com/2010/02/19/mina-article-2/">一个简单的例子</a></li>
<li><a href="http://weavesky.com/2010/02/19/mina-article-3/">MINA架构</a></li>
<li>优化指南</li>
</ol>
<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2010/02/19/mina-article-3/" title="基于MINA构建简单高性能的NIO应用-MINA架构">基于MINA构建简单高性能的NIO应用-MINA架构</a></li><li><a href="http://weavesky.com/2010/02/19/mina-article-2/" title="基于MINA构建简单高性能的NIO应用-一个简单的例子">基于MINA构建简单高性能的NIO应用-一个简单的例子</a></li><li><a href="http://weavesky.com/2010/02/19/mina-article-1/" title="基于MINA构建简单高性能的NIO应用-前言">基于MINA构建简单高性能的NIO应用-前言</a></li><li><a href="http://weavesky.com/2008/01/05/java-3des/" title="如何用Java进行3DES加密解密">如何用Java进行3DES加密解密</a></li><li><a href="http://weavesky.com/2008/01/05/java-des/" title="如何用Java进行DES加密解密">如何用Java进行DES加密解密</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2010/02/19/mina-article-4/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>基于MINA构建简单高性能的NIO应用-MINA架构</title>
		<link>http://weavesky.com/2010/02/19/mina-article-3/</link>
		<comments>http://weavesky.com/2010/02/19/mina-article-3/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 09:21:59 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[mina]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=585</guid>
		<description><![CDATA[本文为Sparkle发于《程序员》2008年2月刊的文章，与《程序员》的协议，可以在个人博客中发布，转载请保留出处。 MINA架构 这里，我借用了一张Trustin Lee在Asia 2006的ppt里面的图片来介绍MINA的架构。 (图略) Remote Peer就是客户端，而下方的框是MINA的主要结构，各个框之间的箭头代表数据流向。 大家可以对比刚刚的例子来看这个架构图，IoService就是整个MINA的入口，负责底层的IO操作，客户端发过来的消息就是由它处理。刚刚我们使用的IoAcceptor就是一个IoService，之所以抽象成IoService，是因为MINA用同样的架构来处理服务器和客户端编程，IoService的另一个子类就是IoConnector，用于客户端。不过根据笔者的使用经验，使用非阻塞的模型进行客户端编程非常的不方便，你最好寻求其他的阻塞通讯框架。 IoService把数据转化成一个一个的事件，传递给IoFilterChain。你可以加入一连串的IoFilter，进行各种功能。笔者的建议是将一些功能性的，业务不相关的代码，用IoFilter来实现，使得整个应用结构更清晰，也方便代码重用。(Article by Sparkle) 被IoFilter处理过的事件，发送给 IoHandler，然后我们在这里实现具体的业务逻辑。这个部分很简单，如果你有Swing的使用经验的话，你会发现它跟Swing的事件非常相像，你要做的事情，仅仅是重载你需要的方法，然后编写具体的业务功能。在这其中，最重要的一个方法就是messageReceived了。 值得留意的是一个IoSession的类，每一个IoSession实例代表这一个连接，我们需要对连接进行的任何操作都通过这个类来实现。 从IoHandler通过调用IoSession.write等方法向客户端发送的消息，会通过跟输入数据相反的次序依次传递，直至由IoService负责把数据发送给客户端。 这就已经是MINA的全部，是不是很简单。 接下来，我会详细介绍我们编写具体代码的时候主要涉及到的三个类，IoHandler、IoSession和IoFilter。 IoHandler public interface IoHandler &#123; void sessionCreated&#40;IoSession session&#41; throws Exception; void sessionOpened&#40;IoSession session&#41; throws Exception; void sessionClosed&#40;IoSession session&#41; throws Exception; void sessionIdle&#40;IoSession &#8230; <a class="more-link" href="http://weavesky.com/2010/02/19/mina-article-3/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<blockquote><p>本文为Sparkle发于《程序员》2008年2月刊的文章，与《程序员》的协议，可以在个人博客中发布，转载请保留出处。</p></blockquote>
<p><strong>MINA架构</strong></p>
<p>这里，我借用了一张Trustin Lee在Asia 2006的ppt里面的图片来介绍MINA的架构。</p>
<p>(图略)</p>
<p>Remote Peer就是客户端，而下方的框是MINA的主要结构，各个框之间的箭头代表数据流向。<br />
大家可以对比刚刚的例子来看这个架构图，IoService就是整个MINA的入口，负责底层的IO操作，客户端发过来的消息就是由它处理。刚刚我们使用的IoAcceptor就是一个IoService，之所以抽象成IoService，是因为MINA用同样的架构来处理服务器和客户端编程，IoService的另一个子类就是IoConnector，用于客户端。不过根据笔者的使用经验，使用非阻塞的模型进行客户端编程非常的不方便，你最好寻求其他的阻塞通讯框架。<br />
IoService把数据转化成一个一个的事件，传递给IoFilterChain。你可以加入一连串的IoFilter，进行各种功能。笔者的建议是将一些功能性的，业务不相关的代码，用IoFilter来实现，使得整个应用结构更清晰，也方便代码重用。<span style="color: #ffffff;">(Article by Sparkle)</span><br />
被IoFilter处理过的事件，发送给 IoHandler，然后我们在这里实现具体的业务逻辑。这个部分很简单，如果你有Swing的使用经验的话，你会发现它跟Swing的事件非常相像，你要做的事情，仅仅是重载你需要的方法，然后编写具体的业务功能。在这其中，最重要的一个方法就是messageReceived了。<br />
值得留意的是一个IoSession的类，每一个IoSession实例代表这一个连接，我们需要对连接进行的任何操作都通过这个类来实现。<br />
从IoHandler通过调用IoSession.write等方法向客户端发送的消息，会通过跟输入数据相反的次序依次传递，直至由IoService负责把数据发送给客户端。<br />
这就已经是MINA的全部，是不是很简单。</p>
<p>接下来，我会详细介绍我们编写具体代码的时候主要涉及到的三个类，IoHandler、IoSession和IoFilter。</p>
<p><strong> IoHandler</strong></p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">interface</span> IoHandler <span style="color: #009900;">&#123;</span>
  <span style="color: #000066; font-weight: bold;">void</span> sessionCreated<span style="color: #009900;">&#40;</span>IoSession session<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">void</span> sessionOpened<span style="color: #009900;">&#40;</span>IoSession session<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">void</span> sessionClosed<span style="color: #009900;">&#40;</span>IoSession session<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">void</span> sessionIdle<span style="color: #009900;">&#40;</span>IoSession session, IdleStatus status<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">void</span> exceptionCaught<span style="color: #009900;">&#40;</span>IoSession session, <span style="color: #003399;">Throwable</span> cause<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">void</span> messageReceived<span style="color: #009900;">&#40;</span>IoSession session, <span style="color: #003399;">Object</span> message<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span><span style="color: #339933;">;</span>
  <span style="color: #000066; font-weight: bold;">void</span> messageSent<span style="color: #009900;">&#40;</span>IoSession session, <span style="color: #003399;">Object</span> message<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>MINA的内部实现了一个事件模型，而IoHanlder则是所有事件最终产生响应的位置。每一个方法的名字很明确表明该事件的含义。messageReceived是接收客户端消息的事件，我们应该在这里实现业务逻辑。messageSent是服务器发送消息的事件，一般情况下我们不会使用它。sessionClosed是客户端断开连接的事件，可以在这里进行一些资源回收等操作。值得留意的是，客户端连接有两个事件，sessionCreated和sessionOpened，两者稍有不同，sessionCreated是由I/O processor线程触发的，而sessionOpened在其后，由业务线程触发的，由于MINA的I/O processor线程非常少，因此如果我们真的需要使用sessionCreated，也必须是耗时短的操作，一般情况下，我们应该把业务初始化的功能放在sessionOpened事件中。<span style="color: #ffffff;">(Article by Sparkle)</span><br />
细心的读者可能会发现，我们刚刚的例子继承的是IoHandlerAdapter，IoHandlerAdapter其实就是一个IoHanlder的空的实现，这样我们就可以不用重载不感兴趣的事件。</p>
<p><strong> IoSession</strong><br />
IoSession是一个接口，MINA里很多的地方都使用接口，很好地体现了面向接口编程的思想。它提供了对当前连接的操作功能，还有用户定义属性的存储功能，这点非常重要。IoSession是线程安全的，也就是我们能够在多线程环境中随意操作IoSession，这点给开发带来很大的好处。我们来看看具体提供的方法，笔者列举一些比较常用和重要的方法</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">WriteFuture write<span style="color: #009900;">&#40;</span><span style="color: #003399;">Object</span> message<span style="color: #009900;">&#41;</span>
CloseFuture close<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #003399;">Object</span> getAttribute<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> key<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003399;">Object</span> setAttribute<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> key, <span style="color: #003399;">Object</span> value<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003399;">Object</span> removeAttribute<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> key<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003399;">Set</span> getAttributeKeys<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000066; font-weight: bold;">boolean</span> isConnected<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">boolean</span> isClosing<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
SocketAddress getRemoteAddress<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">boolean</span> isIdle<span style="color: #009900;">&#40;</span>IdleStatus status<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>在这里，笔者把IoSession的方法大致分成三类<br />
第一类，连接操作功能。<br />
最主要的方法有两个，向客户端发送消息和断开连接。可以看的出，write接受的变量是一个Object，但是实际上应该传入什么类型呢？具体还得看你是否使用了ProtocolCodecFilter（下面会详细介绍），如果使用了ProtocolCodecFilter，那这个message将可能是一个String，或者是一个用户定义的JavaBean。默认的情况，message是一个ByteBuffer。ByteBuffer是MINA的一个类，跟java.nio.ByteBuffer类同名，MINA 2.0将会将它改成IoBuffer，以避免讨论上的误会。<span style="color: #ffffff;">(Article by Sparkle)</span><br />
另一个值得留意的是Future类，MINA是一个非阻塞的通信框架，其中一个明显的体现就是调用IoSession.write方法是不会阻塞的。用户调用了write方法之后，消息内容会发到底层等候发送，至于什么时候发出，就不得而知了。当然，实际上调用了write之后，数据几乎是立刻发出的，这得益与NIO的高性能。但是，如果我们必须确认了消息发出，然后进行某些处理，我们就需要使用Future类，以下是一个很常见的代码</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">IoSession session <span style="color: #339933;">=</span> ...<span style="color: #339933;">;</span>
WriteFuture future <span style="color: #339933;">=</span> session.<span style="color: #006633;">write</span><span style="color: #009900;">&#40;</span>...<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// Wait until the message is completely written out to the O/S buffer.</span>
future.<span style="color: #006633;">join</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> future.<span style="color: #006633;">isWritten</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>  <span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">// The message has been written successfully.</span>
<span style="color: #009900;">&#125;</span>  <span style="color: #000000; font-weight: bold;">else</span>  <span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">// The messsage couldn't be written out completely for some reason.</span>
  <span style="color: #666666; font-style: italic;">// (e.g. Connection is closed)</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>通过调用future.join，程序就会阻塞，直至消息处理结束。我们还能通过future.isWritten得知消息是否成功发送。<br />
在这里，笔者顺便说一个实际使用的发现，消息发送是会自动合并的，简单来说，如果在很短的时间里，对同一个IoSession进行了两次write操作，客户端有可能只收到一条消息，而这条消息就是服务器发出的两条消息前后接起来。这样的设计可以在高并发的时候节省网络开销，而笔者的实际使用过程中，效果也相当好。但是如果这样行为会导致客户端工作不正常，你也可以通过参数关闭它。</p>
<p>第二类，属性存储操作。<br />
通常来说，我们的系统是有用户状态的，我们就需要在连接上存储用户属性，IoSession的Attribute就是这样一个功能。例如两个连接同时连入服务器，一个连接是用户A，用户ID是13，另一个连接是用户B，用户ID是14，我们就可以在用户登录成功之后，调用IoSession.setAttribute(“login_id”,13)，然后在其后的操作中，通过IoSession.getAttribute(“login_id”)获得当前登录用户ID，并进行相应的操作。简单来说，就是一个类似HttpSession的功能，当然具体的实现方法不一样。<span style="color: #ffffff;">(Article by Sparkle)</span></p>
<p>第三类，连接状态。<br />
这里就不多说了，从方法名上我们就能知道它具体的功能。</p>
<p><strong> IoFilter</strong><br />
过滤器是MINA的一个很重要的功能。IoFilter也是一个接口，但是相对比较复杂，这里就不列举它的方法了。简单来说IoFilter就像ServletFilter，在事件被IoHandler处理之前或之后进行一些特定的操作，但是它比ServletFilter复杂，可以处理很多种事件，除了包括IoHandler的7个事件以外，还有一些内部的事件可以进行操作。<br />
MINA提供了一些常用的IoFilter实现，例如有LoggingFilter（日志功能）、BlacklistFilter（黑名单功能）、CompressionFilter（压缩功能）、SSLFilter（SSL支持），这些过滤器比较简单，通过阅读它们的源代码，能够更进一步理解过滤器的实现。笔者在这里要重点介绍两个过滤器，ProtocolCodecFilter和ExecutorFilter</p>
<p><strong>ProtocolCodecFilter</strong><br />
网络传输的内容其实本质是一个二进制流，但是我们的业务功能不会，或者说不应该去直接操作二进制流。MINA默认向IoHandler传入的message是一个ByteBuffer，如果我们直接在IoHandler操作ByteBuffer，会导致大量协议分析的代码和实际的业务代码混杂在一起。最适合的做法，就是在IoFilter把ByteBuffer转换成String或者JavaBean，ProtocolCodecFilter正是这样的一个功能的过滤器。<br />
使用ProtocolCodecFilter很简单，我们只要把ProtocolCodecFilter加入到FilterChain就可以了，但是我们需要提供一个ProtocolCodecFactory。其实ProtocolCodecFilter仅仅是实现了过滤器部分的功能，它会将最终的转换工作，交给从ProtocolCodecFactory获得的Encode和Decode。如果我们需要编写自己的ProtocolCodec，就应该从ProtocolCodecFactory入手。MINA内置了几个ProtocolCodecFactory，比较常用的就是ObjectSerializationCodecFactory和TextLineCodecFactory。<span style="color: #ffffff;">(Article by Sparkle)</span><br />
ObjectSerializationCodecFactory是Java Object序列化之后的内容直接跟ByteBuffer互相转化，比较适合两端都是Java的情况使用。TextLineCodecFactory就是String跟ByteBuffer的转化，说白了就是文本，例如你要实现一个SMTP服务器，或者POP服务器，就可以使用它。而笔者的实际使用，大多数情况都是使用TextLineCodecFactory。<br />
这里提及一下IoFilter的顺序问题，IoFilter是有加入顺序的，例如，先加入LoggingFilter再加入ProtocolCodecFilter，和先加入ProtocolCodecFilter再加入LoggingFilter的效果是不一样的，前者LoggingFilter写入日志的内容是ByteBuffer，而后者写入日志的是转换后具体的类，例如String。实际使用的时候，一定要处理好过滤器的顺序。</p>
<p><strong>ExecutorFilter</strong><br />
另一个重要的过滤器就是ExecutorFilter。这里，我需要先说明一下MINA的线程工作模式，MINA默认是单线程处理所有客户端的消息，也就是说，即使你在一台8CPU的机器上面跑，可能也只用到一个CPU，另外，如果某次消息处理太耗时，就会导致其他消息等待，整体的吞吐量下降。很多朋友抱怨MINA的性能差，其实是因为他们没有加入ExecutorFilter的缘故。ExecutorFilter设计的很精巧，大家可以仔细阅读一下源代码，它会将同一个连接的消息合并起来按顺序调用，不会出现两个线程同时处理同一个连接的情况。<span style="color: #ffffff;">(Article by Sparkle)</span><br />
这里再次提及IoFitler的顺序问题，一般情况下，我们会将ExecutorFilter放在ProtocolCodecFilter之后，因为我们不需要多线程地执行ProtocolCodec操作，用单一线程来进行ProtocolCodec性能会比较高，而具体的业务逻辑可能还设计数据库操作，因此更适合放在不同的线程中运行。</p>
<p><strong>文章快速索引</strong></p>
<ol>
<li><a href="http://weavesky.com/2010/02/19/mina-article-1/">前言</a></li>
<li><a href="http://weavesky.com/2010/02/19/mina-article-2/">一个简单的例子</a></li>
<li>MINA架构</li>
<li><a href="http://weavesky.com/2010/02/19/mina-article-4/">优化指南</a></li>
</ol>
<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2010/02/19/mina-article-4/" title="基于MINA构建简单高性能的NIO应用-优化指南">基于MINA构建简单高性能的NIO应用-优化指南</a></li><li><a href="http://weavesky.com/2010/02/19/mina-article-2/" title="基于MINA构建简单高性能的NIO应用-一个简单的例子">基于MINA构建简单高性能的NIO应用-一个简单的例子</a></li><li><a href="http://weavesky.com/2010/02/19/mina-article-1/" title="基于MINA构建简单高性能的NIO应用-前言">基于MINA构建简单高性能的NIO应用-前言</a></li><li><a href="http://weavesky.com/2008/01/05/java-3des/" title="如何用Java进行3DES加密解密">如何用Java进行3DES加密解密</a></li><li><a href="http://weavesky.com/2008/01/05/java-des/" title="如何用Java进行DES加密解密">如何用Java进行DES加密解密</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2010/02/19/mina-article-3/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>基于MINA构建简单高性能的NIO应用-一个简单的例子</title>
		<link>http://weavesky.com/2010/02/19/mina-article-2/</link>
		<comments>http://weavesky.com/2010/02/19/mina-article-2/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 09:05:57 +0000</pubDate>
		<dc:creator>Sparkle</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[mina]]></category>

		<guid isPermaLink="false">http://weavesky.com/?p=583</guid>
		<description><![CDATA[本文为Sparkle发于《程序员》2008年2月刊的文章，与《程序员》的协议，可以在个人博客中发布，转载请保留出处。 一个简单的例子 MINA使用非常简单，笔者以前做过一段时间传统的Java Socket开发，不过一直对Java NIO不是很理解，但是MINA很快就上手了，MINA封装了NIO繁琐的部分，使你可以更专注于业务功能实现。话不多说，让我们来看一个简单的例子，一个很常见的例子，时间服务器。(Article by Sparkle) 我们的实现目标是一个能响应多个客户端的请求，然后返回服务器当前的系统时间的功能。传统的Java Socket程序，我们需要每accept一个客户端连接，就创建一个新的线程来响应，这会令到系统整体负载能力有较大的限制，而且我们必须手工编写连接管理等代码。让我们来看看MINA是怎么处理的。 首先我们从官方网站下载MINA 1.1，这里我们假设JDK为1.5以上的版本，如果你使用的是JDK 1.4，请下载MINA 1.0，MINA 1.0跟1.1几乎一样，但是强烈建议使用JDK 1.5以上以获得更好的性能。 解开压缩包之后，能看见很多jar包，这里暂不介绍每个包的具体作用，可以把所有包都导入项目。值得留意的是MINA使用了一个slf4j的日志库，该日志库大有取缔common-logging之势。 public class TimeServer &#123; public static void main&#40;String&#91;&#93; args&#41; throws IOException &#123; IoAcceptor acceptor = new SocketAcceptor&#40;&#41;; &#160; SocketAcceptorConfig cfg = new SocketAcceptorConfig&#40;&#41;; cfg.getFilterChain&#40;&#41;.addLast&#40; &#8230; <a class="more-link" href="http://weavesky.com/2010/02/19/mina-article-2/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<blockquote><p>本文为Sparkle发于《程序员》2008年2月刊的文章，与《程序员》的协议，可以在个人博客中发布，转载请保留出处。</p></blockquote>
<p><strong>一个简单的例子</strong></p>
<p>MINA使用非常简单，笔者以前做过一段时间传统的Java Socket开发，不过一直对Java NIO不是很理解，但是MINA很快就上手了，MINA封装了NIO繁琐的部分，使你可以更专注于业务功能实现。话不多说，让我们来看一个简单的例子，一个很常见的例子，时间服务器。<span style="color: #ffffff;">(Article by Sparkle)</span><br />
我们的实现目标是一个能响应多个客户端的请求，然后返回服务器当前的系统时间的功能。传统的Java Socket程序，我们需要每accept一个客户端连接，就创建一个新的线程来响应，这会令到系统整体负载能力有较大的限制，而且我们必须手工编写连接管理等代码。让我们来看看MINA是怎么处理的。</p>
<p>首先我们从官方网站下载MINA 1.1，这里我们假设JDK为1.5以上的版本，如果你使用的是JDK 1.4，请下载MINA 1.0，MINA 1.0跟1.1几乎一样，但是强烈建议使用JDK 1.5以上以获得更好的性能。<br />
解开压缩包之后，能看见很多jar包，这里暂不介绍每个包的具体作用，可以把所有包都导入项目。值得留意的是MINA使用了一个slf4j的日志库，该日志库大有取缔common-logging之势。</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> TimeServer <span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> main<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> args<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">IOException</span> <span style="color: #009900;">&#123;</span>
    IoAcceptor acceptor <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> SocketAcceptor<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    SocketAcceptorConfig cfg <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> SocketAcceptorConfig<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    cfg.<span style="color: #006633;">getFilterChain</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">addLast</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;logger&quot;</span>, <span style="color: #000000; font-weight: bold;">new</span> LoggingFilter<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    cfg.<span style="color: #006633;">getFilterChain</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">addLast</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;codec&quot;</span>, <span style="color: #000000; font-weight: bold;">new</span> ProtocolCodecFilter<span style="color: #009900;">&#40;</span> <span style="color: #000000; font-weight: bold;">new</span> TextLineCodecFactory<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    acceptor.<span style="color: #006633;">bind</span><span style="color: #009900;">&#40;</span> <span style="color: #000000; font-weight: bold;">new</span> InetSocketAddress<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">8123</span><span style="color: #009900;">&#41;</span>, <span style="color: #000000; font-weight: bold;">new</span> TimeServerHandler<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, cfg<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Time server started.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>这里是我们的主程序，非常简单。<br />
首先我们需要一个IoAcceptor，这里我们选择了一个SocketAcceptor，也就是TCP协议。<br />
然后，我们给应用加上日志过滤器和协议编码过滤器。<span style="color: #ffffff;">(Article by Sparkle)</span><br />
最后，我们把acceptor bind到本机的8123端口，并且使用TimeServerHandler来实现协议。</p>
<p>TimeServerHandler是我们实现具体业务功能的地方。</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> TimeServerHandler <span style="color: #000000; font-weight: bold;">extends</span> IoHandlerAdapter <span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> messageReceived<span style="color: #009900;">&#40;</span>IoSession session, <span style="color: #003399;">Object</span> msg<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003399;">String</span> str <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span><span style="color: #009900;">&#41;</span> msg<span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;quit&quot;</span>.<span style="color: #006633;">equalsIgnoreCase</span><span style="color: #009900;">&#40;</span>str<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    session.<span style="color: #006633;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">return</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #003399;">Date</span> date <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Date</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  session.<span style="color: #006633;">write</span><span style="color: #009900;">&#40;</span> date.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Message written...&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> sessionCreated<span style="color: #009900;">&#40;</span>IoSession session<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Session created...&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>IoHandlerAdapter提供了7个事件方法，我们要做的事情仅仅是挑选我们需要做出响应的事件进行重载。在我这个例子了，我重载了两个方法。sessionCreated会在客户端连接的时候调用，通常我们会在这里进行一些初始化操作，我这里仅仅是打印一条信息。messageReceived就是整个Handler的中心部分，每一个从客户端发过来的消息都会转化成对该方法的调用。由于我们加入了协议编码过滤器，因此这里获得的Object msg是一个String，而不是默认的ByteBuffer（下文会详细介绍ProtocolCodecFilter）。这里我们实现了一个很简单的业务功能，如果用户输入的是quit，就断开连接，否则就输入当前时间。可以看出，IoSession封装了对当前连接的操作。</p>
<p>至此，我们就实现了一个时间服务器。</p>
<p><strong>文章快速索引</strong></p>
<ol>
<li><a href="http://weavesky.com/2010/02/19/mina-article-1/">前言</a></li>
<li>一个简单的例子</li>
<li><a href="http://weavesky.com/2010/02/19/mina-article-3/">MINA架构</a></li>
<li><a href="http://weavesky.com/2010/02/19/mina-article-4/">优化指南</a></li>
</ol>
<h2  class="related_post_title">Related Posts</h2><ul class="related_post"><li><a href="http://weavesky.com/2010/02/19/mina-article-4/" title="基于MINA构建简单高性能的NIO应用-优化指南">基于MINA构建简单高性能的NIO应用-优化指南</a></li><li><a href="http://weavesky.com/2010/02/19/mina-article-3/" title="基于MINA构建简单高性能的NIO应用-MINA架构">基于MINA构建简单高性能的NIO应用-MINA架构</a></li><li><a href="http://weavesky.com/2010/02/19/mina-article-1/" title="基于MINA构建简单高性能的NIO应用-前言">基于MINA构建简单高性能的NIO应用-前言</a></li><li><a href="http://weavesky.com/2008/01/05/java-3des/" title="如何用Java进行3DES加密解密">如何用Java进行3DES加密解密</a></li><li><a href="http://weavesky.com/2008/01/05/java-des/" title="如何用Java进行DES加密解密">如何用Java进行DES加密解密</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://weavesky.com/2010/02/19/mina-article-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

