<?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>没有比人更高的山 &#187; Java</title>
	<atom:link href="http://www.zhlwish.com/tag/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.zhlwish.com</link>
	<description>Where there is a will there is a way.</description>
	<lastBuildDate>Fri, 13 Jan 2012 08:13:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Eclipse JFace Binding/绑定 (3)</title>
		<link>http://www.zhlwish.com/2011/09/17/eclipse-jface-binding-3/</link>
		<comments>http://www.zhlwish.com/2011/09/17/eclipse-jface-binding-3/#comments</comments>
		<pubDate>Sat, 17 Sep 2011 14:28:19 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Eclipse RCP]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Eclispe RCP]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=786</guid>
		<description><![CDATA[前文Eclipse JFace Binding/绑定 (1)”和Eclipse JFace Binding/绑定 (2)”分别讲述了JavaBean API的事件机制和Eclipse JFace Binding的SWT控件属性和JavaBean属性的绑定。本文是本系列的最后一篇，讲述JFace中TableViewer、TreeViewer和ListViewer的绑定，由于TableViewer比较有代表性，因此使用TableViewer作为示例。 为什么需要WritableList、WritableSet和WritableMap 在做任何事情之前，先要提出一个为什么，“当你保持一颗好奇的心，当你愿意去问“为什么”，而不是一味得不假思索得接受，你便能够从一件事物的不同角度去审度，你就站得更高，看得更远”——这是 《Sandra Lee: 人生很短，做自己喜欢的事 》中的一句话，我很喜欢。 提出这个问题，潜台词肯定是为什么不能直接用List、Set、Map呢？原因在于集合对象不同于普通对象，集合对象包括了一组对象，这组对象本身的属性改变需要监听自然不必说，对象的添加、删除也是需要监听的，因此Java Collection API中的List、Set和Map就不够用了，更何况几何对象中所包括的那一组对象还必须封装到一个WritableValue对象中，不然元素和GUI的绑定又得失效了。 那么这么多复杂的工作就让WritableList去干吧。 JavaBean中的List属性 我们先模拟一下有钱人，他们都能买几套房子，因此都有几个地址，将地址列表作为有钱人的一个属性。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 &#8230; <a href="http://www.zhlwish.com/2011/09/17/eclipse-jface-binding-3/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2011/09/17/eclipse-jface-binding-3/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Eclipse JFace Binding/绑定 (2)</title>
		<link>http://www.zhlwish.com/2011/09/17/eclipse-jface-binding-2/</link>
		<comments>http://www.zhlwish.com/2011/09/17/eclipse-jface-binding-2/#comments</comments>
		<pubDate>Sat, 17 Sep 2011 13:15:11 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Eclipse RCP]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Eclispe RCP]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=775</guid>
		<description><![CDATA[前文《Eclipse JFace Binding/绑定 (1)》介绍了JavaBean的事件机制，Eclipse的绑定利用了这种机制，（据说Eclipse Binding的下一个目标是Pojo对象的双向绑定，利用asm这样的字节码操作库）。 绑定针对对象实例而不是类型 在深入之前，需要明确的是，在Java中绑定永远是针对对象实例的绑定，而不是针对对象类型的绑定。也就是说下面的代码会使model之前注册的监听器失效。 Model model = new Model&#40;&#41;; model.addPropertyChangeListener&#40;new IPropertyChangeListener&#40;&#41;&#123; public void propertyChangeListener&#40;PropertyChangeEvent evt&#41;&#123; System.out.println&#40;evt.getPropertyName&#40;&#41; + “ changed”&#41;; &#125; &#125;&#41;; model = new Model&#40;&#41;; IObservable接口 Eclipse绑定的核心是IObservableValue、IObservableList，通过实现这些接口对GUI和模型进行监听，我把实现了这些接口的对象成为绑定对象。包括： IObservable &#8211; 所有Observable接口的根接口，提供了对对象实例变化的监听机制 IObservableValue &#8211; 提供了getValue()和setValue()方法，提供了监听value改变的机制 IVetoableValue &#8211; 继承自IObservableValue，提供了在value变化之前进行事件处理的机制 IObservableCollection &#8230; <a href="http://www.zhlwish.com/2011/09/17/eclipse-jface-binding-2/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2011/09/17/eclipse-jface-binding-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Eclipse JFace Binding/绑定 (1)</title>
		<link>http://www.zhlwish.com/2011/09/17/eclipse-jface-binding-1/</link>
		<comments>http://www.zhlwish.com/2011/09/17/eclipse-jface-binding-1/#comments</comments>
		<pubDate>Sat, 17 Sep 2011 08:08:55 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Eclipse RCP]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Eclispe RCP]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=767</guid>
		<description><![CDATA[binding这个词挺有意思的，中文意译为“绑定”，音译也可以是”绑定“，但是“绑定”这个词看起来又不是像“巴士”这样的词一样属于外来词。我深深地感觉第一个把binding翻译成“绑定”的人当时一定感觉很好。 为什么需要“绑定” 在MVC架构中，View（GUI）上的控件的值来源于Model，用户在View上的操作也需要更新到Model。由于桌面应用程序的实时响应特性，后台服务（如数字校验、根据单价和数量计算总价）对Model的更新也需要实时通过View反馈给用户。 Java应用中，Model和View都是相互独立的JavaBean。JavaBean API中，Bean之间的通信通过事件传递实现。事件在一方属性变化时被创建，然后传递给响应变化的一方，后者从事件对象中获取事件信息，进而调用相应的方法实现响应操作。 一般情况下，GUI操作以及Model的属性变化被封装成一个事件对象（Event），事件对象一般包括了事件发生的来源（控件或者模型），变化之前的值和变化之后的值。如对于JavaBean API中定义的类PropertyChangeEvent，有source、propertyName、oldValue、newValue四个属性。 模拟Model和View的“绑定” GUI和Model的绑定使用观察者模式来实现，也就是常说的Observable模式，不过在JavaBean的事件模型里面叫做Listener模式。不同的叫法实质是一样的，Observable是针对被观察的对象而言，Listener则是针对观察其他对象的对象而言。 Observable模式在Java API中有支持，可以直接继承java.util.Observable来实现一个被观察类，通过实现java.util.Observer接口实现观察者，然后调用Observable.addObserver(Observer)方法来建立消息发送渠道。这种方法存在的问题就是，被观察者类必须继承Observable类，由于Java是单继承，因此这个类就不能继承其他类了。 JavaBean API中提供IPropertyChangeListener接口和PropertyChangeSupport类来实现Bean之间的事件通信。我们创建如下两个类： Window：模拟GUI中的窗口，包括txtUsername和txtPassword两个文本输入框 Model：模式实体类，包括username和password两个字符串属性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 &#8230; <a href="http://www.zhlwish.com/2011/09/17/eclipse-jface-binding-1/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2011/09/17/eclipse-jface-binding-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一步一步实现GEF – 9</title>
		<link>http://www.zhlwish.com/2011/09/09/gef-step-by-step-9/</link>
		<comments>http://www.zhlwish.com/2011/09/09/gef-step-by-step-9/#comments</comments>
		<pubDate>Fri, 09 Sep 2011 06:32:48 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Eclipse RCP]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[Eclispe RCP]]></category>
		<category><![CDATA[GEF]]></category>
		<category><![CDATA[rcp]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=747</guid>
		<description><![CDATA[很长一段时间没有继续写了，很多东西都快忘记了，赶紧捡起来 让你的GEF图元可以拖动和缩放 拖动算是最简单的用户交互吧，不过麻雀虽小，肝胆俱全，不理解其原理和设计思路，很难谈得上去应用，但是要理解这一整套交互模型又有相当的难度，本文虽重在实践，这里也略做介绍。后文中所述图元指EditPart对象实例。 GEF用户交互有四个重要的概念：Command，Policy，Request，Role GEF图元对于用户操作的响应（具体的执行操作）被称为Command，这是命令模式的典型实现 GEF图元对于用户操作采用何种响应（操作->响应）被称为EditPolicy，这是策略模式的典型实现，Policy可以认为是一个Map，输入一个Request，输出其对应的Command 用户对图元的操作（拖拽、选择）被称为Request 用户对图元的操作是可以分类的，这个类型被称为Role。比如拖动图元移动位置，拖动图元边框改变图元大小是影响布局的操作，称为LAYOUT_ROLE；双击图元修改图元上的文字信息，双击连线上的问题修改连线的说明，这些都是直接对图元进行修改的操作，称为DIRECT_EDIT_ROLE……，这样的操作类型有很多，以后有机会再进行系统的总结。 对于用户的操作，图元使用那种响应策略（是边框变粗、还是Label变成Input接受用户输入），取决于图元上注册的事件响应类型（Role），当然我们可以向图元同时注册多个响应策略，用于响应不同的用户输入： installEditPolicy&#40;EditPolicy.LAYOUT_ROLE, new DiagramLayoutEditPolicy&#40;&#41;&#41;; 关于此installEditPolicy()方法，我同组的小牛分析得比较透彻，看他：http://www.thankcreate.com/java/357 OK, 下面我们开始编码。 创建Command 首先创建一个Command类，用于响应用户的拖拽操作，com.zhlwish.learngef.command.AjustNodeConstraintCommand继承自org.eclipse.gef.commands.Command，代码如下： 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 &#8230; <a href="http://www.zhlwish.com/2011/09/09/gef-step-by-step-9/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2011/09/09/gef-step-by-step-9/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Java实践：最好提供无参数的构造函数</title>
		<link>http://www.zhlwish.com/2011/08/11/provide-none-param-constructor-in-java/</link>
		<comments>http://www.zhlwish.com/2011/08/11/provide-none-param-constructor-in-java/#comments</comments>
		<pubDate>Thu, 11 Aug 2011 08:02:06 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=605</guid>
		<description><![CDATA[一个类在没有显式定义构造函数的时候，Java会隐式提供一个无参数的构造函数。但是当显式定义了构造函数的情况下，Java就不会提供这个无参数的构造函数了。这是由于在显式定义的构造函数中可能进行了一些必要的初始化工作，此时如果错误调用默认无参构造函数会导致这些必须的初始化工作并没有完成，进而导致程序异常。 经过编程实践，本人认为还是有必要再显式定义了有参构造函数的情况下，仍然显式定义一个无参构造函数。主要原因是“最好提供缺省值”（It will be better to provide a default value），另外一个原因则是在工厂方法中大量使用的java.lang.Class.newInstance()方法只能调用无参构造函数。 提供缺省值 在定义类的时候，最好为属性设置缺省值，以免出现Java中最常见的NullPointException，如下所示，当然此代码并不涉及构造函数神马事情，此处省略不相关的部分，下文类似。 1 2 3 public class NodeEditPart&#123; private List&#60;Connection&#62; incomings = new ArrayList&#60;Connection&#62;&#40;0&#41;; &#125; 通过构造函数设置属性值是非常常见的。下面代码摘取自java.awt.Label类，其中定义了空的构造函数，并且设置文本默认为空字符串。 1 2 3 4 5 6 7 8 9 10 public Label&#40;&#41; &#123; this&#40;&#34;&#34;, &#8230; <a href="http://www.zhlwish.com/2011/08/11/provide-none-param-constructor-in-java/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2011/08/11/provide-none-param-constructor-in-java/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JFace中的GridLayoutFactory和GridDataFactory</title>
		<link>http://www.zhlwish.com/2011/08/05/jface_gridlayoutfactory_griddatafactory/</link>
		<comments>http://www.zhlwish.com/2011/08/05/jface_gridlayoutfactory_griddatafactory/#comments</comments>
		<pubDate>Fri, 05 Aug 2011 08:08:01 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Eclipse RCP]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[Eclispe RCP]]></category>
		<category><![CDATA[rcp]]></category>
		<category><![CDATA[SWT. JFace]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=556</guid>
		<description><![CDATA[研究SWT Layout原理的时候，找到一个视频：《Creating a Custom Window Layout in Eclipse RCP Applications》，顿时被作者使用的GridLayoutFactory和GridDataFactory惊艳了，前些天，我还傻乎乎的自己写了几个简单的类实现相同的功能，无知真可怕。本文介绍了此两个类的用法，最后有一个简单的示例。 GridLayout SWT有四种布局方式：FillLayout，RowLayout，GridLayout，FormLayout，其中使用后三种布局方式的时候，需要为每个子控件指定专门的layout data，分别是RowData，GridData和FormData，这些布局方式和相关的设置，有篇德文的文章《SWT Layout-Manager》讲解得异常清楚，不懂德文不要紧，就看里面的图就行了，在此我转载两张关于GridLayout的图： GridLayout的属性 GridData的属性 使用GridLayoutFactory 先说GridLayoutFactory，一般我们要创建一个GridLayout需要这样： GridLayout layout = new GridLayout&#40;2, false&#41;; layout.marginHeight = 10; layout.marginWidth = 10; layout.horizontalSpacing = 5; layout.verticalSpacing = 5; 而GridLayoutFactory则可以这样创建： GridLayoutFactory.fillDefaults&#40;&#41;.numColumns&#40;2&#41;.margins&#40;10, 10&#41;.spacing&#40;5, 5&#41;.create&#40;&#41;; &#8230; <a href="http://www.zhlwish.com/2011/08/05/jface_gridlayoutfactory_griddatafactory/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2011/08/05/jface_gridlayoutfactory_griddatafactory/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Eclipse RCP中获取Plugin/Bundle中文件资源的绝对路径</title>
		<link>http://www.zhlwish.com/2011/08/02/find-file-in-bundles-of-eclipse-rcp/</link>
		<comments>http://www.zhlwish.com/2011/08/02/find-file-in-bundles-of-eclipse-rcp/#comments</comments>
		<pubDate>Tue, 02 Aug 2011 13:15:47 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Eclipse RCP]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[Eclispe RCP]]></category>
		<category><![CDATA[rcp]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=543</guid>
		<description><![CDATA[摘要：在进行Eclipse RCP开发的过程中，需要使用一些其他的资源（如图片、声音、配置文件、数据库等），我们一般将这些资源放到Plugin/Bundle的相应目录下（如图片资源放到icons目录，声音放到sounds目录，数据库文件放到data目录）。本文先对Eclipse Plugin和Bundle进行分析，之后讲解了如何使用Eclipse API通过这些资源的相对路径（相对于Plugin/Bundle）获取这些资源的绝对路径的方法，最后总结了org.osgi.framework.Bundle接口和FileLocator工具类的使用方法。 Bundle和Plugin Eclipse Platform架构于OSGi核心之上，每个Eclipse Plugin就是OSGi的一个Bundle，因此在Eclipse RCP中Plugin和Bundle是等价的概念。 OSGi框架中定义了org.osgi.framework.IBundle接口，表示运行于OSGi环境中的一个Bundle。Eclipse RCP中定义了org.eclipse.core.runtime.Plugin抽象类，代表一个Eclipse插件。但是Plugin抽象类并没有实现IBundle接口，而是在内部拥有一个IBundle对象实例。Plugin类实现了BundleActivator，控制其内部的IBundle对象的启动和停止，并负责将BundleContext注入到IBundle对象实例中。 我们可以发现，在IBundle接口中定义了如下几个方法，可以获取位于在Bundle文件目录中的资源： 方法 解释 URL getResource(String name); 通过Bundle的Class Loader加载资源，和Class.getResource(String)类似，注意如果当前的bundle是一个fregment，则返回null Enumeration getResources(String name) 和上面的方法一样，不过由于Eclipse插件可以包括多个Fregment，每个Fregment中可以分别包含相对路径相同的文件，因此通过一个相对路径可能找到多个匹配的资源 URL getEntry(String path); 在当前Bundle中根据Path找相应的Entry（此处的entry和resource到底有什么区别我还尚不清楚） Enumeration getEntryPaths(String path); 和上面的方法一样，同getResources(String) Enumeration findEntries(String path, String filePattern, boolean recurse); 根据path和pattern找相应的资源文件，可以使用通配符，如需要查找所有语言文件： bundle.findEntries(“OSGI-INF/l10n”, &#8230; <a href="http://www.zhlwish.com/2011/08/02/find-file-in-bundles-of-eclipse-rcp/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2011/08/02/find-file-in-bundles-of-eclipse-rcp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spring 3 MVC 教程集合</title>
		<link>http://www.zhlwish.com/2010/12/02/spring3mvc/</link>
		<comments>http://www.zhlwish.com/2010/12/02/spring3mvc/#comments</comments>
		<pubDate>Thu, 02 Dec 2010 13:21:18 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[jsp]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[servlet]]></category>
		<category><![CDATA[spring]]></category>
		<category><![CDATA[spring3]]></category>
		<category><![CDATA[web后台]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=263</guid>
		<description><![CDATA[Spring MVC 3相对于之前的版本变化相当大，本系列文章是一个入门，非常详细，有图！ Part 1: Introduction to Spring 3.0 MVC framework Part 2: Create Hello World Application in Spring 3.0 MVC Part 3: Handling Forms in Spring 3.0 MVC Part 4: Spring 3 MVC Tiles Plugin Tutorial with Example in &#8230; <a href="http://www.zhlwish.com/2010/12/02/spring3mvc/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2010/12/02/spring3mvc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ubuntu下Eclipse安装反编译插件JadClipse</title>
		<link>http://www.zhlwish.com/2010/11/16/eclipse-decompiler-jadclipse/</link>
		<comments>http://www.zhlwish.com/2010/11/16/eclipse-decompiler-jadclipse/#comments</comments>
		<pubDate>Tue, 16 Nov 2010 04:26:25 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[jad]]></category>
		<category><![CDATA[反编译]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=254</guid>
		<description><![CDATA[我是在Ubuntu中使用Eclipe helios，即eclipse 3.6，参考了这篇文章http://www.blogjava.net/hongjunli/archive/2007/08/15/137054.html安装jodeclipse不成功，打开class文件，报错“the editor&#8217;s class name was mistyped in plugin.xml.”，可能是因为jodeclipse不支持新版本的eclipse吧，于是考虑安装jadclipse，jadclipse是在一个非常不错的Java反编译工具，之前写过一篇博客介绍《Java反编译工具Jad详解》，这个作为续篇，介绍如何在Eclipse里面使用jad。 首先，还是到http://www.varaneckas.com/jad下载jad，为了给开源做点贡献，我也把windows和linux的两个版本下来，做个备份： 1. Jad 1.5.8g for Windows 9x/NT/2000 on Intel platform 2. Jad 1.5.8e for Linux (statically linked) 以下以ubuntu为例，把下载后的jad解压到/opt/jad目录，我的eclipse安装在/opt/eclipse目录。cd到/opt/jad目录，执行./jad，输出版本和帮助信息就OK说明jad本身没有问题了。 到http://sourceforge.net/projects/jadclipse/下载jadeclipse，当前版本为3.3.0版本，支持eclipse3.3以上，下载后就是一个jar文件，直接放到/opt/eclipse/plugins目录，重启eclipse。 依次点击：Window -&#62; Preferences -&#62; Java，如果出现JadClipse，即说明jadclipse安装成功，不急，还有两个设置： 点击JadClipse，把Path to decompiler设置为/opt/jad/jad 点击General -&#62; Editors &#8230; <a href="http://www.zhlwish.com/2010/11/16/eclipse-decompiler-jadclipse/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2010/11/16/eclipse-decompiler-jadclipse/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java反编译工具Jad详解</title>
		<link>http://www.zhlwish.com/2010/06/26/jad/</link>
		<comments>http://www.zhlwish.com/2010/06/26/jad/#comments</comments>
		<pubDate>Sat, 26 Jun 2010 11:18:34 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[jad]]></category>
		<category><![CDATA[反编译]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=196</guid>
		<description><![CDATA[做项目过程中需要反编译一个jar包，于是作了一些学习，记录下来。 Jad(JAva Decompiler)是一个Java的反编译器，可以通过命令行把Java的class文件反编译成源代码。 如果你在使用编写代码的时候遇到找不到源代码的第三方库，而且你又需要看看这个库的具体实现，那么你就需要使用这个东西。而且如果你是使用Eclipse的话，还有一个Eclipse插件JadClipse，JadClipse提供一个class文件查看器可以直接打开class文件查看其反编译后的源代码， 太方便了，太方便了！ 不过，可惜的是这个开源项目似乎已经关闭了，官方网站已经上不去了，有个叫Tomas Varaneckas的好心人收集了所有的版本提供给大家下载：JAD Java Decompiler Download 而且这个最新的版本也只支持Java 4，不支持Java 5。还有一个叫做JD-Core的工具支持Java 5的新特性，如enum等，而且它提供独立的GUI程序JD-GUI和基于Eclipse的插件JD-Eclipse，也很方便。但是对于JD-Core，作者没有提供下载的链接，他说“Open the sources of JD-Core is not on my roadmap: I spent too many time on this project.”当然后面也有一大篇文章是别人用来骂他的，可以看Add JD-Core to the download list，蛮有意思。 我的项目中需要将第三方库反编译出来，让后对其进行修改，然后再编译，不仅仅是查看，因此只能用命令行的Jad来做。 使用方法： [1] 反编译一个class文件：jad &#8230; <a href="http://www.zhlwish.com/2010/06/26/jad/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2010/06/26/jad/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Java注释中的@deprecated与源代码中的@Deprecated</title>
		<link>http://www.zhlwish.com/2010/05/10/java_deprecated/</link>
		<comments>http://www.zhlwish.com/2010/05/10/java_deprecated/#comments</comments>
		<pubDate>Mon, 10 May 2010 12:55:25 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[java annotation]]></category>
		<category><![CDATA[javadoc]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=187</guid>
		<description><![CDATA[首先，请注意标题，这两个标记有大小写之分，一个是D，一个是d。 源代码标记@Deprecated是在JDK1.5中作为内置的annotation引入的，用于表明类(class)、方法(method)、字段(field)已经不再推荐使用，并且在以后的JDK版本中可能将其删除，编译器在默认情况下检测到有此标记的时候会提示警告信息。 Java注释中的@deprecated用于在用Javadoc工具生成文档的时候，标注此类/接口、方法、字段已经被废止。 不过后者还有一个功能就是和源代码标记@Deprecated同样的功能，在JDK1.4版本之后，该功能被@Deprecated所取代。]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2010/05/10/java_deprecated/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java int型转换中文大写数字表示方法</title>
		<link>http://www.zhlwish.com/2010/01/21/java-int-to-chinese-number/</link>
		<comments>http://www.zhlwish.com/2010/01/21/java-int-to-chinese-number/#comments</comments>
		<pubDate>Thu, 21 Jan 2010 10:10:22 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=150</guid>
		<description><![CDATA[之前写过一篇博客，记录的是如何将Java中文大写数字转int型，今天遇到的问题是将Java int型转换成中文大写数字表示。 下面是程序，很容易理解，不过，只支持10000以内的数字转换： 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 &#8230; <a href="http://www.zhlwish.com/2010/01/21/java-int-to-chinese-number/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2010/01/21/java-int-to-chinese-number/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JSP中获取表单中多选列表(Multiple Select)提交的值</title>
		<link>http://www.zhlwish.com/2009/11/26/jsp_multiple_select/</link>
		<comments>http://www.zhlwish.com/2009/11/26/jsp_multiple_select/#comments</comments>
		<pubDate>Wed, 25 Nov 2009 16:56:19 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[jsp]]></category>
		<category><![CDATA[servlet]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=93</guid>
		<description><![CDATA[在select标签中添加multiple=”multiple”属性，可以使下拉列表（drop down list）变成多选列表（multiple select list），但是在jsp与servlet中使用获取表单值常用的request.getParameter(“value”)获取到的只是多选列表中的第一个选中值，经过查询资料，原来HttpServletRequest还有一个方法getParameterValues(String key)，其返回值为String类型的数组，里面存放的正是多选列表中的选中的值。 也就是说，jsp和servlet中对于表单中的多选控件提交的值都是通过此getParameterValues方法来获取的，比如checkbox list（复选框列表）等，示例代码如下： &#60;form action=”index.jsp” method=”POST”&#62;     &#60;select name=”value” multiple=”multiple”&#62;         &#60;option value=”val1&#8243;&#62;Value 1&#60;/option&#62;         &#60;option value=”val2&#8243;&#62;Value 2&#60;/option&#62;         &#60;option value=”val3&#8243;&#62;Value 3&#60;/option&#62;         &#60;option value=”val4&#8243;&#62;Value 4&#60;/option&#62;         &#60;option value=”val5&#8243;&#62;Value 5&#60;/option&#62;      &#60;/select&#62;      &#60;input type=”submit” &#8230; <a href="http://www.zhlwish.com/2009/11/26/jsp_multiple_select/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2009/11/26/jsp_multiple_select/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JSF异常消息机制及应用</title>
		<link>http://www.zhlwish.com/2009/11/18/jsf_message/</link>
		<comments>http://www.zhlwish.com/2009/11/18/jsf_message/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 02:49:46 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JSF]]></category>
		<category><![CDATA[web后台]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=77</guid>
		<description><![CDATA[JSF有两种异常消息： [1] JSF提供的标准异常信息，如标准的验证器和转换器生成的异常信息等 [2] 自定义的异常信息 与消息相关的类是javax.faces.application.FacesMessage，他封装了单一的、本地化的、人类可以理解的消息，除了消息字符串本身外，FacesMessage还有三个属性：severity(严重性),summary（摘要）,detail（详细信息） serverity被定义成FacesMessage的内部类，有四种类型：Info、Warn、Error、Fatal FacesContext负责维护FacesMessage的两个逻辑集合，一个和组件相关的消息集合、一个不与组件相关的消息集合，定义了如下的和消息相关的方法 public Iterator&#60;FacesMessage&#62; getMessages(); public Iterator&#60;FacesMessage&#62; getMessages(String clientId); public Iterator&#60;String&#62; getClientIdsWithMessages();//返回有消息绑定的组件id public void addMessage(String clientId, javax.faces.application.FacesMessage message);//向FacesContext中加入一条FacesMessage public FacesMessage.Severity getMaximumSeverity();//返回最严重的问题的严重性 FacesMessage的部分源代码如下： private FacesMessage.Severity _severity; private String _summary; private String _detail; public FacesMessage() { &#8230; <a href="http://www.zhlwish.com/2009/11/18/jsf_message/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2009/11/18/jsf_message/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DbUnit中文教程——核心组件</title>
		<link>http://www.zhlwish.com/2009/11/15/dbunit-lesson-core/</link>
		<comments>http://www.zhlwish.com/2009/11/15/dbunit-lesson-core/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 01:41:01 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[DbUnit]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[测试]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=67</guid>
		<description><![CDATA[注：本文基本翻译自DbUnit的文档，翻译不好朋友见谅 本文主要介绍在使用DBUnit编写测试用例的时候会常用的几个接口和类 IDatabaseConnection：接口，DbUnit的数据库连接对象，封装了java.sql.Connection IDataSet：接口，DbUnit的数据集对象，里面可以放多个数据表 DataBaseOperation：抽象类，数据库操作类 IDatabaseConnection有两个子类： DatabaseConnection：封装了一个普通的JDBC连接 DatabaseDataSourceConnection：封装了一个JDBC数据源连接 IDataSet是DbUnit用来存储数据的一种数据结构 FlatXmlDataSet：最普遍使用的数据集，每个XML元素代表数据表中的一行数据，XML元素的名称是表明，属性名是列名 XmlDataSet StreamingDataSet DatabaseDataSet QueryDataSet DefaultDataSet CompositeDateSet FilteredDataSet XlsDataSet ReplacementDataSet DatabaseOperation DatabaseOperation.UPDATE：这个操作将从测试数据源中读取的数据集的内容更新到数据库中，注意这个操作正确执行的前提是测试数据表已经存在，如果不存在这个测试用例将会失败 DatabaseOperation.INSERT：这个操作把从测试数据源中读取的数据集的内容插入到数据库中，注意这个操作正确执行的前提是测试数据表不存在，这个操作将新建数据表。如果测试数据表已经存在这个测试用例将会失败。另外，在执行这个操作的时候要特别注意数据集中数据表的顺序，否则可能会因为违反外键约束而造成测试用例失败 DatabaseOperation.DELETE：这个操作会从数据库中删除数据，注意，这个操作只删除数据集中存在的数据行而不是整个数据表中的数据 DatabaseOperation.DELETE_ALL：这个操作删除数据表中的所有行，注意，这个操作也只影响数据集中声明了的数据表，数据集中没有涉及到的数据表中的数据不会删除 DatabaseOperation.TRUNCATE：这个操作将删除数据集中声明的数据表，如果数据中有些表并没有在预定义的数据集中提到，这个数据表将不会被影响。注意，这个操作是按照相反的顺序执行的 DatabaseOperation.REFRESH：顾名思义，这个操作将把预定义数据集中的数据同步到数据库中，也就是说这个操作将更新数据数中已有的数据、插入数据库中没有的数据。数据库中已有的、但是数据集中没有的行将不会被影响。我们用一个产品数据库的拷贝进行测试的时候可以使用这个操作将预定义数据同步到产品数据库中 DatabaseOperation.CLEAN_INSERT：删除所有的数据表中的数据，然后插入数据集中定义的数据，如果你想保证数据库是受控的，这个你会比较喜欢。 DatabaseOperation.NONE：不执行任何操作 CompositeOperation：将多个操作组合成一个，便以维护和重用 TransactionOperation：在一个事物内执行多个操作 IdentityInsertOperation：在使用MSSQL的时候，插入数据时IDENTITY列我们是没有办法控制的，用这个就可以控制了，只有在使用MSSQL的时候才会用得到]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2009/11/15/dbunit-lesson-core/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DbUnit中文教程——基本原理和简单开始</title>
		<link>http://www.zhlwish.com/2009/11/15/dbunit-lesson-simple-start/</link>
		<comments>http://www.zhlwish.com/2009/11/15/dbunit-lesson-simple-start/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 01:39:32 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[DbUnit]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[测试]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=65</guid>
		<description><![CDATA[DBUnit是JUnit的一个扩展，对于数据库驱动的项目而言（基本上所有的Web项目都是数据库驱动的），对于服务层的单元测试非常麻烦，因为不能保证每次测试时数据库都是同一个状态，所以开发者不敢写断言（assertEquals()）。我个人也是因为这个原因所以对驱动测试开发总是敬而远之。 有了DBUnit，一切都变了，DBUnit的目的就是在每个单元测试运行之前将数据库初始化成一个预定义的状态，以保证单元测试时的断言不会因为数据库状态发生了变化而失败，同时可以解决前一个单元测试失败导致对数据库的操作未按照测试用例执行而影响后一个单元测试的问题。 DBUnit可以将数据库中的数据导出成XML数据集，也可以将XML数据集重新导入到数据库中，这也是DBUnit实现测试前初始化数据库状态的实现方法，而且，DBUnit还可以验证数据库中的模式和数据是不是和XML数据集中的模式和数据是否一样，也就是真正意义上的“数据库测试”，不过DBUnit貌似还不支持数据库存储过程、触发器、视图等高级功能的测试。DBUnit2.0增强了对于流模式下巨型XML数据集的支持。 相信信仰单元测试驱动开发或者有意向在开发中加入单元测试的开发者很容易理解上面的叙述，下面用一个示例演示DBUnit的功能。 假设我们开发中已经建立了一个数据库，里面只有一个数据表user： create table user ( id bigint auto_increament primary key, username char(48) not null, password char(48) not null, name varchar(48) not null ); 其中有一行数据： insert into user(id, username, password, name) values(1, 'admin', '123', 'Administrator'); 第一步是根据测试数据建立XML数据集，DBUnit用下面的格式来表示一行数据： &#60;user &#8230; <a href="http://www.zhlwish.com/2009/11/15/dbunit-lesson-simple-start/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2009/11/15/dbunit-lesson-simple-start/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Java中文大写数字转int型</title>
		<link>http://www.zhlwish.com/2009/11/15/java-chinese-number-to-int/</link>
		<comments>http://www.zhlwish.com/2009/11/15/java-chinese-number-to-int/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 01:34:38 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=62</guid>
		<description><![CDATA[暂时不支持万以上级别，后面会加上这个。道理很简单，但我搜了一下google，找到的代码没有几个能直接用，所以分享下，直接贴代码了：     public static int chnNumToIntConverter(String chnNum){         HashMap&#60;String, Integer&#62; numbers = new HashMap&#60;String, Integer&#62;();         numbers.put(“零”, 0);         numbers.put(“一”, 1);         numbers.put(“二”, 2);         numbers.put(“三”, 3);         numbers.put(“四”, 4);         numbers.put(“五”, 5); &#8230; <a href="http://www.zhlwish.com/2009/11/15/java-chinese-number-to-int/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2009/11/15/java-chinese-number-to-int/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Working copy path &#8216;*&#8217; does not exist in repository的解决方法</title>
		<link>http://www.zhlwish.com/2009/11/15/working-copy-path-does-not-exist-in-repository/</link>
		<comments>http://www.zhlwish.com/2009/11/15/working-copy-path-does-not-exist-in-repository/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 01:28:12 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=55</guid>
		<description><![CDATA[开发中对一个working copy进行update操作的时候出现了标题所示的错误，因为在update之前对其进行了switch操作，因此猜想可能是因为这个缘故，上网查了一下，找到一篇文章《SVN merger errors: Working copy path &#8216;*&#8217; does not exist in repo》。 按照其描述的方法并不能解决我的问题，但是让我对.svn文件夹下的这个entry文件产生了兴趣，仔细的看了一下，发现这个文件里面有一行是写的版本号，紧接着下一行就是文件夹路径，但是这个文件夹路径是错误的。 对其进行了改正后，重新update，正常了，看来是svn的一个bug吧。]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2009/11/15/working-copy-path-does-not-exist-in-repository/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lucene中的TooManyClause异常</title>
		<link>http://www.zhlwish.com/2009/11/15/lucene-too-many-clause/</link>
		<comments>http://www.zhlwish.com/2009/11/15/lucene-too-many-clause/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 01:26:36 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Lucene]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=52</guid>
		<description><![CDATA[为什么会产生这个异常： 使用Lucene检索过程中如果用到RangeQuery,PrefixQuery,WildcardQuery,FuzzyQuery这四种Query，可能会产生TooManyClauses异常。为什么会产生这个异常呢？举例说明： 以RangeQuery为例，如果日期范围为19990101到20091231，在索引文件中有19990102，19990103等等这些日期词组，那么RangeQuery会被扩展成“19990102 OR 19990103”，成了2个子句。可以想象，如果索引文件里面在这个时间段内的日期有很多，那么就会产生很多子句。 PrefixQuery等也是同样的道理，如查询词为“法*”，如果索引文件中有“法律”、“法场”、“法医”、“法典”等等，这个Query就会被扩展成“法律 OR 法场 OR 法医 OR 法典”，或许会更多更多。 而为了节省内存，Lucene默认将子句数目限制为1024，如果超出限制，就会抛出TooManyClauses异常。 怎么解决这个问题呢，Lucene提供了三种方法： 【1】使用filter替代Query，当然这是以牺牲查询速度为代价的，不过可以通过缓存的方式缓解这个问题。仍然以前面RangeQuery为例，可以使用RangeFilter来替代RangeQuery，如下： 之前的代码： BooleanQuery simpleQuery = new BooleanQuery&#40;&#41;; Term dateLower = new Term&#40;&#34;publishDate&#34;, startYear + &#34;0101&#34;&#41;; Term dateUpper = new Term&#40;&#34;publishDate&#34;, endYear + &#34;1231&#34;&#41;; RangeQuery dateQuery = &#8230; <a href="http://www.zhlwish.com/2009/11/15/lucene-too-many-clause/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2009/11/15/lucene-too-many-clause/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lucene多条件检索</title>
		<link>http://www.zhlwish.com/2009/11/15/lucene-muti-query/</link>
		<comments>http://www.zhlwish.com/2009/11/15/lucene-muti-query/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 01:19:29 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Lucene]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=46</guid>
		<description><![CDATA[多条件检索需要使用BooleanQuery来实现，代码如下，这个例子需要使用时间范围和关键进行检索： BooleanQuery simpleQuery = new BooleanQuery&#40;&#41;;//建立BooleanQuery 建立关键字Query QueryParser keywordParser = new QueryParser&#40;type, new PaodingAnalyzer&#40;&#41;&#41;; org.apache.lucene.search.Query keywordQuery = keywordParser.parse&#40;keyword&#41;; 建立RangeQuery Term dateLower = new Term&#40;&#34;publishDate&#34;, startYear + &#34;0101&#34;&#41;; Term dateUpper = new Term&#40;&#34;publishDate&#34;, endYear + &#34;1231&#34;&#41;; RangeQuery dateQuery = new RangeQuery&#40;dateLower, &#8230; <a href="http://www.zhlwish.com/2009/11/15/lucene-muti-query/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2009/11/15/lucene-muti-query/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一个ant的build.xml文件实例</title>
		<link>http://www.zhlwish.com/2009/11/15/ant-build-xml-example/</link>
		<comments>http://www.zhlwish.com/2009/11/15/ant-build-xml-example/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 01:15:09 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[ant]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=43</guid>
		<description><![CDATA[很简单，很实用，写完之后，发现，嘿嘿！我居然可以不翻doc写build文件了。 &#38;lt;?xml version=&#34;1.0&#34; encoding=&#34;utf-8&#34; ?&#38;gt; &#38;lt;project name=&#34;dian_bid&#34; basedir=&#34;.&#34; default=&#34;deploy&#34;&#38;gt; &#160;  &#38;lt;property name=&#34;source&#34; location=&#34;src&#34; /&#38;gt;  &#38;lt;property name=&#34;resource&#34; location=&#34;res&#34; /&#38;gt;  &#38;lt;property name=&#34;test-srouce&#34; location=&#34;test&#34; /&#38;gt;  &#38;lt;property name=&#34;release-resource&#34; location=&#34;release&#34; /&#38;gt;  &#38;lt;property name=&#34;dest&#34; location=&#34;dest&#34; /&#38;gt; &#160;  &#38;lt;property name=&#34;webroot&#34; location=&#34;web&#34;/&#38;gt;  &#38;lt;property name=&#34;tomcat-root&#34; location=&#34;D:/Java/apache-tomcat-a&#34;/&#38;gt; &#160;  &#38;lt;target name=&#34;clean&#34;&#38;gt; &#8230; <a href="http://www.zhlwish.com/2009/11/15/ant-build-xml-example/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2009/11/15/ant-build-xml-example/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>maven中文教程——一个简单的应用实例</title>
		<link>http://www.zhlwish.com/2009/11/15/maven-lesson-simple-example/</link>
		<comments>http://www.zhlwish.com/2009/11/15/maven-lesson-simple-example/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 01:08:23 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Maven]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=38</guid>
		<description><![CDATA[我突然有个想法，我们使用hibernate search来构建一个全文检索（本文的内容不会重点放在hibernate search，对此感兴趣可以下载本文的代码）。假设我们的数据库中有一些数码相机的数据，对于这些数据的维护采用hibernate，这样我们可以使用hibernate search架设一个全文检索系统，以提供更好的产品检索服务。 心动不如行动，马上动手吧。 第一步，在命令行中敲入“mvn archetype:generate”，这个命令好处是可以不用我们记那么多的参数，在前面的文章中我已经说明了。 第二步，选择 “internal -&#62; maven-archetype-quickstart ()”这一项，自需要选择编号，我这里的编号是17，这个号码在每个电脑上可能有不同。 第三部，按照提示输入相关信息，之后，maven即生成了项目的结构，如下： Define value for groupId: : com.zhlwish Define value for artifactId: : jpastudy Define value for version:  1.0-SNAPSHOT: : Define value for package:  com.zhlwish: : com.zhlwish.jpastudy Confirm properties &#8230; <a href="http://www.zhlwish.com/2009/11/15/maven-lesson-simple-example/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2009/11/15/maven-lesson-simple-example/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>maven中文教程——坐标与包依赖管理</title>
		<link>http://www.zhlwish.com/2009/11/15/maven-lesson-dependency/</link>
		<comments>http://www.zhlwish.com/2009/11/15/maven-lesson-dependency/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 01:06:47 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Maven]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=36</guid>
		<description><![CDATA[maven用“坐标（Coordinate）”这个词来唯一标识一个库文件，所谓“坐标”就是库文件的“主键”（借用一下数据库的概念），而且这个“主键”是个复合组件，包含四个部分：groupId, artifactId, version和packaging，分别对应pom文件中的下面四个结点： &#60;groupId&#62;com.zhlwish&#60;/groupId&#62;   项目开发组织标识 &#60;artifactId&#62;simple&#60;/artifactId&#62;  项目标识（一般是项目名称） &#60;packaging&#62;jar&#60;/packaging&#62;       打包类型（可能是jar、war、ear） &#60;version&#62;1.0-SNAPSHOT&#60;/version&#62;  版本（按照apache版本命名规则来命名，一般为“主版本.次版本.增量版本-限定版本号”） snapshot、release、latest是maven中常用的三个“限定版本号”，snapshot表示项目正处于活动的开发状态；latest是指项目的最新的发布版，或者最近被发布到仓库的快照版(snapshot)；release是指仓库中的最后一个非快照版本。 maven最强大的地方就是能够对库文件（俗称“包、package”）的依赖进行管理。对于一个应用项目而言，不可避免的会引入很多第三方的类库。如一个项目采用struts2开发，使用struts2的2.1.6版本，而这个struts2又依赖于apache commons的某些包，如果我们不使用maven开发的话，需要下载这么多库文件，然后全部copy到项目的classpath路径下面，当依赖的第三方库越来越多，而且很多还有传递依赖，每当Java虚拟机抛出class not found exceptions时头都大了，而且一旦库升级，随之而来的又是一大堆问题。另外，如果我们将库文件纳入到版本库的管理中，也会造成版本库的急剧增大。 maven的出现解决了这个问题。她可以很好的管理这些问题，包括传递依赖。我们在pom文件里面加入： &#60;dependencies&#62; &#60;dependency&#62; &#60;groupId&#62;log4j&#60;/groupId&#62; &#60;artifactId&#62;log4j&#60;/artifactId&#62; &#60;version&#62;1.2.14&#60;/version&#62; &#60;/dependency&#62; &#60;dependency&#62; &#60;groupId&#62;dom4j&#60;/groupId&#62; &#60;artifactId&#62;dom4j&#60;/artifactId&#62; &#60;version&#62;1.6.1&#60;/version&#62; &#60;/dependency&#62; &#60;dependency&#62; &#60;groupId&#62;junit&#60;/groupId&#62; &#60;artifactId&#62;junit&#60;/artifactId&#62; &#60;version&#62;3.8.1&#60;/version&#62; &#60;scope&#62;test&#60;/scope&#62; &#60;/dependency&#62; &#60;dependencies&#62; 上面代码的意思是我们为项目添加了log4j和dom4j以及junit的依赖，我们不用去找这些jar文件然后复制到classpath里面了，maven会自动去找这些包（本地或者远程仓库），每个dependency结点下面就是一个库文件的“主键”。 对于最后一个还有一个scope结点，标识了这个库文件的使用范围，有如下五种，其中compile是默认的： compile：编译需要，在pachakge生命周期阶段如果使用”mvn assembly:assembly”命令，所有的包都会一起导出 provided：编译期间需要，但是由于部署环境中已经存在，打包时就不用输出了，如servlet.jar，在开发时编译需要的，但是部署到servlet容器中后，servlet容器肯定有这个库文件，所以就不用打包输出。 test：编译测试代码和运行测试期间需要 runtime：运行期间需要，但是编译期间不需要 system：表示这个包由jvm或者jdk提供 &#8230; <a href="http://www.zhlwish.com/2009/11/15/maven-lesson-dependency/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2009/11/15/maven-lesson-dependency/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>maven中文教程——构建的生命周期</title>
		<link>http://www.zhlwish.com/2009/11/15/maven-lesson-lifecycle/</link>
		<comments>http://www.zhlwish.com/2009/11/15/maven-lesson-lifecycle/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 01:03:50 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Maven]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=34</guid>
		<description><![CDATA[maven的支持者在提及maven的优点的时候总会提到这么一点，那就是maven是有生命周期的，而ant没有，你需要手工的编写target，然后编写每个target中的任务。 其实在我看来这个是纠缠概念，所谓的maven生命周期实际上是构建过程的生命周期。在ant中你需要手动的设定文件夹的结果，告诉ant哪个是源代码文件夹、哪个是测试代码文件夹，哪个是目标文件夹等等，因此对于使用ant每个项目都有不一样的代码。因为maven已经将项目的文件夹结构固定好了，不用程序员再指定，所以就可以将编译、打包、部署等这样一些过程都可以做成自动化的，也就是所谓的maven的生命周期。 其实，完全可以自定义ant的target来实现maven所谓的“生命周期”这个概念。 构建即俗称building（team-building也是一种构建），我的理解是在java开发中构建组要是指编译源代码、打包、部署、运行这样一个完整的过程，很多时候这个过程被IDE封装成了一个run按钮，当你写完代码按下run的时候，IDE会将所有的事情做完，对于coder，这一系列过程是透明的。 那又会有同学要问了，既然IDE已经可以做这些事情了，而且不用我操心，我干嘛需要maven呢？一方面，在持续集成和自动化构建过程中显然不可能去用IDE封装好的这一套，这里非得使用ant或者maven不可；另一方面，maven的最核心功能并不是这个而是包依赖的管理。 maven中默认的生命周期阶段可以参考《maven权威指南》chapter10 构建生命周期，我们会常用的有这么一些，你可以使用“mvn 生命周期的阶段名称”这样的命令来用maven自动构建： validate 验证项目是否正确，以及所有为了完整构建必要的信息是否可用 compile 编译项目的源代码 test-compile 编译测试源代码 test 运行单元测试 package 将编译好的代码打包成可发布的格式，如war、jar、ear等 install 安装包到本地仓库，以备其他项目可用 deploy 将本地包发布到远程仓库（一般是开发团队搭建的maven私服） site 生成项目文档和报道，和apache的一般网站风格很相似，这一点太强大了 maven的生命周期其实是“约定优于配置”这个思想的最好体现，觉得ant脚本难写的朋友可以感受一下maven的强大。]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2009/11/15/maven-lesson-lifecycle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>maven中文教程——命令</title>
		<link>http://www.zhlwish.com/2009/11/15/maven-lesson-command/</link>
		<comments>http://www.zhlwish.com/2009/11/15/maven-lesson-command/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 00:57:38 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Maven]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=31</guid>
		<description><![CDATA[这是我第二遍学习maven了，决定写一些东西记录一下，以防像第一次学习之后全部忘光光的情况出现，另外也是告诉自己，必须坚持记录学习进展，不能荒废了这一片净土。 看到这个题目，有人会告诉我《Maven权威指南》，我看了一些，但是一开头就被“mvn archetype:create -DgroupId=org.sonatype.mavenbook.ch03 -DartifactId=simple -DpackageName=org.sonatype.mavenbook”这样的命令吓到了，与其去记这么复杂的命令，我还不如回去用ant，最近apache不是又整出个ivy，也可以管理版本依赖么？简简单单，多好。直到我偶然浏览一篇springside论坛的一篇帖子，里面写到： “其实谁都有菜鸟的的阶段，不过我们要学习的话，不要总是看重运行结果，要学习整个的过程和细节。比如很多人都头痛的maven，就是一个学习的好机会，我第一次学习maven也是下载ss后才迫使自己学习的，当时也是隐隐的骂，觉得太费劲了。但是当你真正的做过之后才发现，很多时候我们讨厌的事物，恰巧是我们没有真正了解和操作前的误区。直言不讳地说，那些自称是菜鸟而不愿以使用maven的人很可能不是菜鸟，而是懒鸟。如果你是懒鸟，请暂时不要再研究springside了，因为影响你日后发展的主要原因很可能就是懒惰而不是技术。 ” 仔细想了一下，觉得很有道理，学习嘛，都有循序渐进的过程，一开始遇到问题很正常，如果不能坚持，永远学不到真正的东西。于是，从maven开始。 回头看这个命令mvn archetype:create(省略了后面的参数)，其中archetype是一个插件（plugin）的名字，而create是这个插件的一个任务（task），这个插件都有哪些任务可以用mvn help:describe -Dplugin=archetype 这个命令来查看，同样，help是一个插件，describe是一个任务的名字，maven里面的参数传递采用“-D”这种Java用来设置系统属性的方式，mvn这个脚本只是把这个参数传递给java的类了。 同样如果需要查看help插件的详细信息，可以使用mvn help:describe -Dplugin=help，如果需要查看详细的参数信息，则需要再加上-Dfull参数，即mvn help:describe -Dplugin=archetype -Dfull=true 创建了一个项目之后，可以使用maven的其他命令来执行编译、构建、发布过程了，对于一些常用的命令，maven也有简写形式，如mvn compile:compile可以简写为mvn compile 常用的有这么一些： mvn compile 编译项目源代码 mvn test-compile 编译测试代码 mvn test 运行测试 mvn package 打包应用 mvn install 将应用发布到本地仓库 mvn deploy &#8230; <a href="http://www.zhlwish.com/2009/11/15/maven-lesson-command/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2009/11/15/maven-lesson-command/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java读取文件的编码问题</title>
		<link>http://www.zhlwish.com/2009/11/15/java-file-encoding/</link>
		<comments>http://www.zhlwish.com/2009/11/15/java-file-encoding/#comments</comments>
		<pubDate>Sun, 15 Nov 2009 00:53:57 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[编码]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=29</guid>
		<description><![CDATA[在Java的文件操作中，如果一个文件是UTF-8格式，那么一定要使用UTF-8的编码格式去读取，如果按其他格式读取之后再做转换，可能会发生不可预料的问题，如“乱码”，具体原因我没有搞清楚，因为JDK读取文件时采用了sun.nio.cs.StreamDecoder这个类，这个是sun公司的代码实现，并没有源代码可以参考。 下面就两种方式做记录： 1.Java按一定编码读取文件 InputStream is = Main.class.getResourceAsStream(fileName); BufferedReader br = new BufferedReader(new InputStreamReader(is, "utf-8")); String tmp; while((tmp = br.readLine()) != null){     System.out.println(tmp); } 2.Java字符串编码转换 FileReader reader = new FileReader(fileName); BufferedReader br = new BufferedReader(reader); String tmp; while((tmp = br.readLine()) != &#8230; <a href="http://www.zhlwish.com/2009/11/15/java-file-encoding/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2009/11/15/java-file-encoding/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java中的静态导入：import static</title>
		<link>http://www.zhlwish.com/2009/11/15/java-import-static/</link>
		<comments>http://www.zhlwish.com/2009/11/15/java-import-static/#comments</comments>
		<pubDate>Sat, 14 Nov 2009 22:14:04 +0000</pubDate>
		<dc:creator>周亮</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.zhlwish.com/?p=4</guid>
		<description><![CDATA[静态导入是JDK1.5里面的新的特性 一般我们常写 import java.util.*; 意思是导入util包下的所有类，然后使用下面的语句用sort对alist进行排序。 Collections.sort(alist); 在jdk1.5中，我们可以写 import static java.util.Collections.*; 意思是导入Collections类的所有静态方法（注意只是静态方法），这样我们可以使用下面的语句达到同样的效果： sort(alist); 读到这里，可能很多人就要想了，System.out.println(“”);应该也可以写简单一点吧（我开始也是这么想的）。不好意思，呵呵，println是out的实例方法，非静态方法，不能用上面的简写的。 但是可以用一种变通的方法，自己实现一个静态的println，然后调用这个就行了。 import的作用就是告诉编译器，当你遇到无法解析的名字时，去某个路径找。所以当编译器遇到sort后，就在java.util.Collections下找到了sort这个名字（函数签名），然后再找是否有匹配的函数。结果以下的奇怪东西就有意思了： import static java.util.Arrays.sort; import static java.util.Collections.sort; 两个sort毫无冲突，因为这两个类没有相同的sort函数（函数签名不一样），邻里融洽。 其实这种方法真是很无奈。]]></description>
		<wfw:commentRss>http://www.zhlwish.com/2009/11/15/java-import-static/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

