﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-分享ｊａｖａ带来的快乐-文章分类-Java</title><link>http://www.blogjava.net/lyjjq/category/9246.html</link><description>我喜欢ｊａｖａ新东西</description><language>zh-cn</language><lastBuildDate>Wed, 26 Sep 2012 22:07:44 GMT</lastBuildDate><pubDate>Wed, 26 Sep 2012 22:07:44 GMT</pubDate><ttl>60</ttl><item><title>fn 标签库</title><link>http://www.blogjava.net/lyjjq/articles/388631.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Wed, 26 Sep 2012 13:57:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/388631.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/388631.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/388631.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/388631.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/388631.html</trackback:ping><description><![CDATA[<p style="text-indent: 2em;" align="left"><span style="font-size: small;">在jstl中的fn标签也是我们在网页设计中经常要用到的很关键的标签，在使用的时候要先加上头</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">&lt;%@ taglib uri="</span><a href="http://java.sun.com/jsp/jstl/functions"><span style="color: rgb(40, 134, 228); font-size: small;">http://java.sun.com/jsp/jstl/functions</span></a><span style="font-size: small;">" prefix="fn"%&gt;就可以使用fn标签了。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">具体使用方法请参见下表： </span></p><p style="text-indent: 2em;" align="left"><table border="0"><tbody><tr><td><p> </p><p style="text-indent: 2em;"><table border="1" cellspacing="1" cellpadding="3" align="center"><tbody><tr><td height="24"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">函数</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">描述</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:contains(string, substring)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">如果参数string中包含参数substring，返回true</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:containsIgnoreCase(string, substring)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">如果参数string中包含参数substring（忽略大小写），返回true</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:endsWith(string, suffix)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">如果参数 string 以参数suffix结尾，返回true</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:escapeXml(string)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">将有特殊意义的XML (和HTML)转换为对应的XML character entity code，并返回</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:indexOf(string, substring)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">返回参数substring在参数string中第一次出现的位置</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:join(array, separator)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">将一个给定的数组array用给定的间隔符separator串在一起，组成一个新的字符串并返回。</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:length(item)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">返回参数item中包含元素的数量。参数Item类型是数组、collection或者String。如果是String类型,返回值是String中的字符数。</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:replace(string, before, after)</span></strong></p></td><td valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">返回一个String对象。用参数after字符串替换参数string中所有出现参数before字符串的地方，并返回替换后的结果</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:split(string, separator)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">返回一个数组，以参数separator 为分割符分割参数string，分割后的每一部分就是数组的一个元素</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:startsWith(string, prefix)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">如果参数string以参数prefix</span></strong></p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">开头，返回true</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:substring(string, begin, end)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">返回参数string部分字符串, 从参数begin开始到参数end位置，包括end位置的字符</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:substringAfter(string, substring)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">返回参数substring在参数string中后面的那一部分字符串</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:substringBefore(string, substring)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">返回参数substring在参数string中前面的那一部分字符串</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:toLowerCase(string)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">将参数string所有的字符变为小写，并将其返回</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:toUpperCase(string)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">将参数string所有的字符变为大写，并将其返回</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:trim(string)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">去除参数string 首尾的空格，并将其返回</span></strong></p></td></tr></tbody></table><p>&nbsp;</p><p style="text-indent: 2em;"> </p></td></tr></tbody></table><p>&nbsp;</p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">称呼Functions标签库为标签库，倒不如称呼其为函数库来得更容易理解些。因为Functions标签库并没有提供传统的标签来为JSP页面的工作服务，而是被用于EL表达式语句中。在JSP2.0规范下出现的Functions标签库为EL表达式语句提供了许多更为有用的功能。Functions标签库分为两大类，共16个函数。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">长度函数：fn:length</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">字符串处理函数：fn:contains、fn:containsIgnoreCase、fn:endsWith、fn:escapeXml、fn:indexOf、fn:join、fn:replace、fn:split、fn:startsWith、fn:substring、fn:substringAfter、fn:substringBefore、fn:toLowerCase、fn:toUpperCase、fn:trim</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">以下是各个函数的用途和属性以及简单示例。</span></p><p style="text-indent: 2em;" align="left"><strong><span style="color: rgb(255, 153, 0);"><span style="font-size: small;">9.7.1 长度函数fn:length函数 </span></span></strong></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">长度函数fn:length的出现有重要的意义。在JSTL1.0中，有一个功能被忽略了，那就是对集合的长度取值。虽然java.util.Collection接口定义了size方法，但是该方法不是一个标准的JavaBean属性方法（没有get,set方法），因此，无法通过EL表达式&#8220;${collection.size}&#8221;来轻松取得。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:length函数正是为了解决这个问题而被设计出来的。它的参数为input，将计算通过该属性传入的对象长度。该对象应该为集合类型或String类型。其返回结果是一个int类型的值。下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">&lt;%ArrayList arrayList1 = new ArrayList();</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">arrayList1.add("aa");</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">arrayList1.add("bb");</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">arrayList1.add("cc");</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">%&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">&lt;%request.getSession().setAttribute("arrayList1", arrayList1);%&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:length(sessionScope.arrayList1)}</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">假设一个ArrayList类型的实例&#8220;arrayList1&#8221;，并为其添加三个字符串对象，使用fn:length函数后就可以取得返回结果为&#8220;3&#8221;。</span></p><p style="text-indent: 2em;" align="left"><strong><span style="color: rgb(255, 153, 0);"><span style="font-size: small;">9.7.2 判断函数fn:contains函数 </span></span></strong></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:contains函数用来判断源字符串是否包含子字符串。它包括string和substring两个参数，它们都是String类型，分布表示源字符串和子字符串。其返回结果为一个boolean类型的值。下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:contains("ABC", "a")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:contains("ABC", "A")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">前者返回&#8220;false&#8221;，后者返回&#8220;true&#8221;。</span></p><p style="text-indent: 2em;" align="left"><strong><span style="color: rgb(255, 153, 0);"><span style="font-size: small;">9.7.3 fn:containsIgnoreCase函数 </span></span></strong></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:containsIgnoreCase函数与fn:contains函数的功能差不多，唯一的区别是fn:containsIgnoreCase函数对于子字符串的包含比较将忽略大小写。它与fn:contains函数相同，包括string和substring两个参数，并返回一个boolean类型的值。下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:containsIgnoreCase("ABC", "a")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:containsIgnoreCase("ABC", "A")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">前者和后者都会返回&#8220;true&#8221;。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;"><strong><span style="color: rgb(255, 153, 0);">9.7.4 词头判断函数fn:startsWith函数</span></strong> </span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:startsWith函数用来判断源字符串是否符合一连串的特定词头。它除了包含一个string参数外，还包含一个subffx参数，表示词头字符串，同样是String类型。该函数返回一个boolean类型的值。下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:startsWith ("ABC", "ab")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:startsWith ("ABC", "AB")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">前者返回&#8220;false&#8221;，后者返回&#8220;true&#8221;。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;"><strong><span style="color: rgb(255, 153, 0);">9.7.5 词尾判断函数fn:endsWith函数</span></strong> </span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:endsWith函数用来判断源字符串是否符合一连串的特定词尾。它与fn:startsWith函数相同，包括string和subffx两个参数，并返回一个boolean类型的值。下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:endsWith("ABC", "bc")}&lt;br&gt; ${fn:endsWith("ABC", "BC")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">前者返回&#8220;false&#8221;，后者返回&#8220;true&#8221;。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;"><span style="color: rgb(255, 153, 0);"><strong>9.7.6 字符实体转换函数fn:escapeXml函数</strong></span> </span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:escapeXml函数用于将所有特殊字符转化为字符实体码。它只包含一个string参数，返回一个String类型的值。</span></p><p style="text-indent: 2em;" align="left"><strong><span style="color: rgb(255, 153, 0); font-size: small;">9.7.8 字符匹配函数fn:indexOf函数 </span></strong></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:indexOf函数用于取得子字符串与源字符串匹配的开始位置，若子字符串与源字符串中的内容没有匹配成功将返回&#8220;-1&#8221;。它包括string和substring两个参数，返回结果为int类型。下面看一个示例。 </span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:indexOf("ABCD","aBC")}&lt;br&gt; ${fn:indexOf("ABCD","BC")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">前者由于没有匹配成功，所以返回-1，后者匹配成功将返回位置的下标，为1。</span></p><p style="text-indent: 2em;" align="left"><strong><span style="color: rgb(255, 153, 0);"><span style="font-size: small;">9.7.9 分隔符函数fn:join函数 </span></span></strong></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:join函数允许为一个字符串数组中的每一个字符串加上分隔符，并连接起来。它的参数、返回结果和描述如表9.25所示：</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">表9.25　fn:join函数</span></p><p style="text-indent: 2em;" align="left"><table border="1" cellspacing="0" cellpadding="0"><tbody><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">参数</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">描述</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">array</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">字符串数组。其类型必须为String[]类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">separator</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">分隔符。其类型必须为String类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">返回结果</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">返回一个String类型的值</span></p></td></tr></tbody></table><p>&nbsp;</p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">&lt;% String[] stringArray = {"a","b","c"}; %&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">&lt;%request.getSession().setAttribute("stringArray", stringArray);%&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:join(sessionScope.stringArray,";")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">定义数组并放置到Session中，然后通过Session得到该字符串数组，使用fn:join函数并传入分隔符&#8220;;&#8221;，得到的结果为&#8220;a;b;c&#8221;。</span></p><p style="text-indent: 2em;" align="left"><strong><span style="color: rgb(255, 153, 0);"><span style="font-size: small;">9.7.10 替换函数fn:replace函数 </span></span></strong></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:replace函数允许为源字符串做替换的工作。它的参数、返回结果和描述如表9.26所示：</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">表9.26　 fn:replace函数</span></p><p style="text-indent: 2em;" align="left"><table border="1" cellspacing="0" cellpadding="0"><tbody><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">参数</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">描述</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">inputString</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">源字符串。其类型必须为String类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">beforeSubstring</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">指定被替换字符串。其类型必须为String类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">afterSubstring</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">指定替换字符串。其类型必须为String类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">返回结果</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">返回一个String类型的值</span></p></td></tr></tbody></table><p>&nbsp;</p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:replace("ABC","A","B")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">将&#8220;ABC&#8221;字符串替换为&#8220;BBC&#8221;，在&#8220;ABC&#8221;字符串中用&#8220;B&#8221;替换了&#8220;A&#8221;。</span></p><p style="text-indent: 2em;" align="left"><strong><span style="color: rgb(255, 153, 0);"><span style="font-size: small;">9.7.11 分隔符转换数组函数fn:split函数 </span></span></strong></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:split函数用于将一组由分隔符分隔的字符串转换成字符串数组。它的参数、返回结果和描述如表9.27所示：</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">表9.27　 fn:split函数</span></p><p style="text-indent: 2em;" align="left"><table border="1" cellspacing="0" cellpadding="0"><tbody><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">参数</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">描述</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">string</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">源字符串。其类型必须为String类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">delimiters</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">指定分隔符。其类型必须为String类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">返回结果</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">返回一个String[]类型的值</span></p></td></tr></tbody></table><p>&nbsp;</p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:split("A,B,C",",")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">将&#8220;A,B,C&#8221;字符串转换为数组{A,B,C}。</span></p><p style="text-indent: 2em;" align="left"><strong><span style="color: rgb(255, 153, 0);"><span style="font-size: small;">9.7.12 字符串截取函数fn:substring函数 </span></span></strong></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:substring函数用于截取字符串。它的参数、返回结果和描述如表9.28所示：</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">表9.28　 fn:substring函数</span></p><p style="text-indent: 2em;" align="left"><table style="width: 532px; height: 96px;" border="1" cellspacing="0" cellpadding="0"><tbody><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">参数</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">描述</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">string</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">源字符串。其类型必须为String类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">beginIndex</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">指定起始下标（值从0开始）。其类型必须为int类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">endIndex</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">指定结束下标（值从0开始）。其类型必须为int类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">返回结果</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">返回一个String类型的值</span></p></td></tr></tbody></table><p>&nbsp;</p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:substring("ABC","1","2")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">截取结果为&#8220;B&#8221;。</span></p><img src ="http://www.blogjava.net/lyjjq/aggbug/388631.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2012-09-26 21:57 <a href="http://www.blogjava.net/lyjjq/articles/388631.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>fn 标签库</title><link>http://www.blogjava.net/lyjjq/articles/388632.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Wed, 26 Sep 2012 13:57:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/388632.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/388632.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/388632.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/388632.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/388632.html</trackback:ping><description><![CDATA[<p style="text-indent: 2em;" align="left"><span style="font-size: small;">在jstl中的fn标签也是我们在网页设计中经常要用到的很关键的标签，在使用的时候要先加上头</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">&lt;%@ taglib uri="</span><a href="http://java.sun.com/jsp/jstl/functions"><span style="color: rgb(40, 134, 228); font-size: small;">http://java.sun.com/jsp/jstl/functions</span></a><span style="font-size: small;">" prefix="fn"%&gt;就可以使用fn标签了。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">具体使用方法请参见下表： </span></p><p style="text-indent: 2em;" align="left"><table border="0"><tbody><tr><td><p> </p><p style="text-indent: 2em;"><table border="1" cellspacing="1" cellpadding="3" align="center"><tbody><tr><td height="24"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">函数</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">描述</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:contains(string, substring)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">如果参数string中包含参数substring，返回true</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:containsIgnoreCase(string, substring)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">如果参数string中包含参数substring（忽略大小写），返回true</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:endsWith(string, suffix)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">如果参数 string 以参数suffix结尾，返回true</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:escapeXml(string)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">将有特殊意义的XML (和HTML)转换为对应的XML character entity code，并返回</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:indexOf(string, substring)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">返回参数substring在参数string中第一次出现的位置</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:join(array, separator)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">将一个给定的数组array用给定的间隔符separator串在一起，组成一个新的字符串并返回。</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:length(item)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">返回参数item中包含元素的数量。参数Item类型是数组、collection或者String。如果是String类型,返回值是String中的字符数。</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:replace(string, before, after)</span></strong></p></td><td valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">返回一个String对象。用参数after字符串替换参数string中所有出现参数before字符串的地方，并返回替换后的结果</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:split(string, separator)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">返回一个数组，以参数separator 为分割符分割参数string，分割后的每一部分就是数组的一个元素</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:startsWith(string, prefix)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">如果参数string以参数prefix</span></strong></p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">开头，返回true</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:substring(string, begin, end)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">返回参数string部分字符串, 从参数begin开始到参数end位置，包括end位置的字符</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:substringAfter(string, substring)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">返回参数substring在参数string中后面的那一部分字符串</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:substringBefore(string, substring)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">返回参数substring在参数string中前面的那一部分字符串</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:toLowerCase(string)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">将参数string所有的字符变为小写，并将其返回</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:toUpperCase(string)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">将参数string所有的字符变为大写，并将其返回</span></strong></p></td></tr><tr><td height="24" valign="top"><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">fn:trim(string)</span></strong></p></td><td><p> </p><p style="text-indent: 2em;"><strong><span style="color: rgb(11, 83, 148); font-size: small;">去除参数string 首尾的空格，并将其返回</span></strong></p></td></tr></tbody></table><p>&nbsp;</p><p style="text-indent: 2em;"> </p></td></tr></tbody></table><p>&nbsp;</p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">称呼Functions标签库为标签库，倒不如称呼其为函数库来得更容易理解些。因为Functions标签库并没有提供传统的标签来为JSP页面的工作服务，而是被用于EL表达式语句中。在JSP2.0规范下出现的Functions标签库为EL表达式语句提供了许多更为有用的功能。Functions标签库分为两大类，共16个函数。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">长度函数：fn:length</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">字符串处理函数：fn:contains、fn:containsIgnoreCase、fn:endsWith、fn:escapeXml、fn:indexOf、fn:join、fn:replace、fn:split、fn:startsWith、fn:substring、fn:substringAfter、fn:substringBefore、fn:toLowerCase、fn:toUpperCase、fn:trim</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">以下是各个函数的用途和属性以及简单示例。</span></p><p style="text-indent: 2em;" align="left"><strong><span style="color: rgb(255, 153, 0);"><span style="font-size: small;">9.7.1 长度函数fn:length函数 </span></span></strong></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">长度函数fn:length的出现有重要的意义。在JSTL1.0中，有一个功能被忽略了，那就是对集合的长度取值。虽然java.util.Collection接口定义了size方法，但是该方法不是一个标准的JavaBean属性方法（没有get,set方法），因此，无法通过EL表达式&#8220;${collection.size}&#8221;来轻松取得。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:length函数正是为了解决这个问题而被设计出来的。它的参数为input，将计算通过该属性传入的对象长度。该对象应该为集合类型或String类型。其返回结果是一个int类型的值。下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">&lt;%ArrayList arrayList1 = new ArrayList();</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">arrayList1.add("aa");</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">arrayList1.add("bb");</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">arrayList1.add("cc");</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">%&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">&lt;%request.getSession().setAttribute("arrayList1", arrayList1);%&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:length(sessionScope.arrayList1)}</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">假设一个ArrayList类型的实例&#8220;arrayList1&#8221;，并为其添加三个字符串对象，使用fn:length函数后就可以取得返回结果为&#8220;3&#8221;。</span></p><p style="text-indent: 2em;" align="left"><strong><span style="color: rgb(255, 153, 0);"><span style="font-size: small;">9.7.2 判断函数fn:contains函数 </span></span></strong></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:contains函数用来判断源字符串是否包含子字符串。它包括string和substring两个参数，它们都是String类型，分布表示源字符串和子字符串。其返回结果为一个boolean类型的值。下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:contains("ABC", "a")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:contains("ABC", "A")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">前者返回&#8220;false&#8221;，后者返回&#8220;true&#8221;。</span></p><p style="text-indent: 2em;" align="left"><strong><span style="color: rgb(255, 153, 0);"><span style="font-size: small;">9.7.3 fn:containsIgnoreCase函数 </span></span></strong></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:containsIgnoreCase函数与fn:contains函数的功能差不多，唯一的区别是fn:containsIgnoreCase函数对于子字符串的包含比较将忽略大小写。它与fn:contains函数相同，包括string和substring两个参数，并返回一个boolean类型的值。下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:containsIgnoreCase("ABC", "a")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:containsIgnoreCase("ABC", "A")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">前者和后者都会返回&#8220;true&#8221;。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;"><strong><span style="color: rgb(255, 153, 0);">9.7.4 词头判断函数fn:startsWith函数</span></strong> </span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:startsWith函数用来判断源字符串是否符合一连串的特定词头。它除了包含一个string参数外，还包含一个subffx参数，表示词头字符串，同样是String类型。该函数返回一个boolean类型的值。下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:startsWith ("ABC", "ab")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:startsWith ("ABC", "AB")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">前者返回&#8220;false&#8221;，后者返回&#8220;true&#8221;。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;"><strong><span style="color: rgb(255, 153, 0);">9.7.5 词尾判断函数fn:endsWith函数</span></strong> </span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:endsWith函数用来判断源字符串是否符合一连串的特定词尾。它与fn:startsWith函数相同，包括string和subffx两个参数，并返回一个boolean类型的值。下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:endsWith("ABC", "bc")}&lt;br&gt; ${fn:endsWith("ABC", "BC")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">前者返回&#8220;false&#8221;，后者返回&#8220;true&#8221;。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;"><span style="color: rgb(255, 153, 0);"><strong>9.7.6 字符实体转换函数fn:escapeXml函数</strong></span> </span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:escapeXml函数用于将所有特殊字符转化为字符实体码。它只包含一个string参数，返回一个String类型的值。</span></p><p style="text-indent: 2em;" align="left"><strong><span style="color: rgb(255, 153, 0); font-size: small;">9.7.8 字符匹配函数fn:indexOf函数 </span></strong></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:indexOf函数用于取得子字符串与源字符串匹配的开始位置，若子字符串与源字符串中的内容没有匹配成功将返回&#8220;-1&#8221;。它包括string和substring两个参数，返回结果为int类型。下面看一个示例。 </span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:indexOf("ABCD","aBC")}&lt;br&gt; ${fn:indexOf("ABCD","BC")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">前者由于没有匹配成功，所以返回-1，后者匹配成功将返回位置的下标，为1。</span></p><p style="text-indent: 2em;" align="left"><strong><span style="color: rgb(255, 153, 0);"><span style="font-size: small;">9.7.9 分隔符函数fn:join函数 </span></span></strong></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:join函数允许为一个字符串数组中的每一个字符串加上分隔符，并连接起来。它的参数、返回结果和描述如表9.25所示：</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">表9.25　fn:join函数</span></p><p style="text-indent: 2em;" align="left"><table border="1" cellspacing="0" cellpadding="0"><tbody><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">参数</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">描述</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">array</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">字符串数组。其类型必须为String[]类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">separator</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">分隔符。其类型必须为String类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">返回结果</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">返回一个String类型的值</span></p></td></tr></tbody></table><p>&nbsp;</p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">&lt;% String[] stringArray = {"a","b","c"}; %&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">&lt;%request.getSession().setAttribute("stringArray", stringArray);%&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:join(sessionScope.stringArray,";")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">定义数组并放置到Session中，然后通过Session得到该字符串数组，使用fn:join函数并传入分隔符&#8220;;&#8221;，得到的结果为&#8220;a;b;c&#8221;。</span></p><p style="text-indent: 2em;" align="left"><strong><span style="color: rgb(255, 153, 0);"><span style="font-size: small;">9.7.10 替换函数fn:replace函数 </span></span></strong></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:replace函数允许为源字符串做替换的工作。它的参数、返回结果和描述如表9.26所示：</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">表9.26　 fn:replace函数</span></p><p style="text-indent: 2em;" align="left"><table border="1" cellspacing="0" cellpadding="0"><tbody><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">参数</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">描述</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">inputString</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">源字符串。其类型必须为String类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">beforeSubstring</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">指定被替换字符串。其类型必须为String类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">afterSubstring</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">指定替换字符串。其类型必须为String类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">返回结果</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">返回一个String类型的值</span></p></td></tr></tbody></table><p>&nbsp;</p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:replace("ABC","A","B")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">将&#8220;ABC&#8221;字符串替换为&#8220;BBC&#8221;，在&#8220;ABC&#8221;字符串中用&#8220;B&#8221;替换了&#8220;A&#8221;。</span></p><p style="text-indent: 2em;" align="left"><strong><span style="color: rgb(255, 153, 0);"><span style="font-size: small;">9.7.11 分隔符转换数组函数fn:split函数 </span></span></strong></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:split函数用于将一组由分隔符分隔的字符串转换成字符串数组。它的参数、返回结果和描述如表9.27所示：</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">表9.27　 fn:split函数</span></p><p style="text-indent: 2em;" align="left"><table border="1" cellspacing="0" cellpadding="0"><tbody><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">参数</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">描述</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">string</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">源字符串。其类型必须为String类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">delimiters</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">指定分隔符。其类型必须为String类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">返回结果</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">返回一个String[]类型的值</span></p></td></tr></tbody></table><p>&nbsp;</p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:split("A,B,C",",")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">将&#8220;A,B,C&#8221;字符串转换为数组{A,B,C}。</span></p><p style="text-indent: 2em;" align="left"><strong><span style="color: rgb(255, 153, 0);"><span style="font-size: small;">9.7.12 字符串截取函数fn:substring函数 </span></span></strong></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">fn:substring函数用于截取字符串。它的参数、返回结果和描述如表9.28所示：</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">表9.28　 fn:substring函数</span></p><p style="text-indent: 2em;" align="left"><table style="width: 532px; height: 96px;" border="1" cellspacing="0" cellpadding="0"><tbody><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">参数</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">描述</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">string</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">源字符串。其类型必须为String类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">beginIndex</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">指定起始下标（值从0开始）。其类型必须为int类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">endIndex</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">指定结束下标（值从0开始）。其类型必须为int类型</span></p></td></tr><tr><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">返回结果</span></p></td><td><p> </p><p style="text-indent: 2em;"><span style="font-size: small;">返回一个String类型的值</span></p></td></tr></tbody></table><p>&nbsp;</p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">下面看一个示例。</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">${fn:substring("ABC","1","2")}&lt;br&gt;</span></p><p style="text-indent: 2em;" align="left"><span style="font-size: small;">截取结果为&#8220;B&#8221;。</span></p><img src ="http://www.blogjava.net/lyjjq/aggbug/388632.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2012-09-26 21:57 <a href="http://www.blogjava.net/lyjjq/articles/388632.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>StringUilts的方法详解</title><link>http://www.blogjava.net/lyjjq/articles/387453.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Tue, 11 Sep 2012 04:54:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/387453.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/387453.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/387453.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/387453.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/387453.html</trackback:ping><description><![CDATA[public static void TestStr(){<br />&nbsp;&nbsp;&nbsp; //null 和 ""操作~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />&nbsp;&nbsp;&nbsp; //判断是否Null 或者 ""<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.isEmpty(null));<br />    //System.out.println(StringUtils.isNotEmpty(null));<br />&nbsp;&nbsp;&nbsp; //判断是否null 或者 "" 去空格~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.isBlank("&nbsp; "));<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.isNotBlank(null));<br />&nbsp;&nbsp;&nbsp; //去空格.Null返回null~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.trim(null));<br />&nbsp;&nbsp;&nbsp; //去空格，将Null和"" 转换为Null<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.trimToNull(""));<br />&nbsp;&nbsp;&nbsp; //去空格，将NULL 和 "" 转换为""<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.trimToEmpty(null));<br />&nbsp;&nbsp;&nbsp; //可能是对特殊空格符号去除？？<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.strip("大家好&nbsp; 啊&nbsp; \t"));<br />&nbsp;&nbsp;&nbsp; //同上，将""和null转换为Null<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.stripToNull(" \t"));<br />&nbsp;&nbsp;&nbsp; //同上，将""和null转换为""<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.stripToEmpty(null));<br />&nbsp;&nbsp;&nbsp; //将""或者Null 转换为 ""<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.defaultString(null));<br />&nbsp;&nbsp;&nbsp; //仅当字符串为Null时 转换为指定的字符串(二参数)<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.defaultString("", "df"));<br />&nbsp;&nbsp;&nbsp; //当字符串为null或者""时，转换为指定的字符串(二参数)<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.defaultIfEmpty(null, "sos"));<br />&nbsp;&nbsp;&nbsp; //去空格.去字符~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />&nbsp;&nbsp;&nbsp; //如果第二个参数为null去空格(否则去掉字符串2边一样的字符，到不一样为止)<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.strip("fsfsdf", "f"));<br />&nbsp;&nbsp;&nbsp; //如果第二个参数为null只去前面空格(否则去掉字符串前面一样的字符，到不一样为止)<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.stripStart("ddsuuu ", "d"));<br />&nbsp;&nbsp;&nbsp; //如果第二个参数为null只去后面空格，(否则去掉字符串后面一样的字符，到不一样为止)<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.stripEnd("dabads", "das"));<br />&nbsp;&nbsp;&nbsp; //对数组没个字符串进行去空格。<br />&nbsp;&nbsp;&nbsp; //ArrayToList(StringUtils.stripAll(new String[]{" 中华 ", "民 国 ", "共和 "}));<br />&nbsp;&nbsp;&nbsp; //如果第二个参数为null.对数组每个字符串进行去空格。(否则去掉数组每个元素开始和结尾一样的字符)<br />&nbsp;&nbsp;&nbsp; //ArrayToList(StringUtils.stripAll(new String[]{" 中华 ", "民 国", "国共和国"}, "国"));<br />&nbsp;&nbsp;&nbsp; //查找,判断~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />&nbsp;&nbsp;&nbsp; //判断2个字符串是否相等相等,Null也相等<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.equals(null, null));<br />&nbsp;&nbsp;&nbsp; //不区分大小写比较<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.equalsIgnoreCase("abc", "ABc"));<br />&nbsp;&nbsp;&nbsp; //查找，不知道怎么弄这么多查找，很多不知道区别在哪？费劲~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />&nbsp;&nbsp;&nbsp; //普通查找字符，如果一参数为null或者""返回-1<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.indexOf(null, "a"));<br />&nbsp;&nbsp;&nbsp; //从指定位置(三参数)开始查找，本例从第2个字符开始查找k字符<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.indexOf("akfekcd中华", "k", 2));<br />&nbsp;&nbsp;&nbsp; //未发现不同之处<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.ordinalIndexOf("akfekcd中华", "k", 2));<br />&nbsp;&nbsp;&nbsp; //查找,不区分大小写<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.indexOfIgnoreCase("adfs", "D"));<br />&nbsp;&nbsp;&nbsp; //从指定位置(三参数)开始查找,不区分大小写<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.indexOfIgnoreCase("adfs", "a", 3));<br />&nbsp;&nbsp;&nbsp; //从后往前查找<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.lastIndexOf("adfas", "a"));<br />&nbsp;&nbsp;&nbsp; //未理解,此结果为2<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.lastIndexOf("d饿abasdafs我", "a", 3));<br />&nbsp;&nbsp;&nbsp; //未解,此结果为-1<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.lastOrdinalIndexOf("yksdfdht", "f", 2));<br />&nbsp;&nbsp;&nbsp; //从后往前查，不区分大小写<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.lastIndexOfIgnoreCase("sdffet", "E"));<br />&nbsp;&nbsp;&nbsp; //未解,此结果为1<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.lastIndexOfIgnoreCase("efefrfs看", "F" , 2));<br />&nbsp;&nbsp;&nbsp; //检查是否查到，返回boolean,null返回假<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.contains("sdf", "dg"));<br />&nbsp;&nbsp;&nbsp; //检查是否查到，返回boolean,null返回假,不区分大小写<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.containsIgnoreCase("sdf", "D"));<br />&nbsp;&nbsp;&nbsp; //检查是否有含有空格,返回boolean<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.containsWhitespace(" d"));<br />&nbsp;&nbsp;&nbsp; //查询字符串跟数组任一元素相同的第一次相同的位置<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.indexOfAny("absfekf", new String[]{"f", "b"}));<br />&nbsp;&nbsp;&nbsp; //查询字符串中指定字符串(参数二)出现的次数<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.indexOfAny("afefes", "e"));<br />&nbsp;&nbsp;&nbsp; //查找字符串中是否有字符数组中相同的字符，返回boolean<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.containsAny("asfsd", new char[]{'k', 'e', 's'}));<br />&nbsp;&nbsp;&nbsp; //未理解与lastIndexOf不同之处。是否查到，返回boolean<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.containsAny("啡f咖啡", "咖"));<br />&nbsp;&nbsp;&nbsp; //未解<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.indexOfAnyBut("seefaff", "af"));<br />&nbsp;&nbsp;&nbsp; //判断字符串中所有字符，都是出自参数二中。<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.containsOnly("中华华", "华"));<br />&nbsp;&nbsp;&nbsp; //判断字符串中所有字符，都是出自参数二的数组中。<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.containsOnly("中华中", new char[]{'中', '华'}));<br />&nbsp;&nbsp;&nbsp; //判断字符串中所有字符，都不在参数二中。<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.containsNone("中华华", "国"));<br />&nbsp;&nbsp;&nbsp; //判断字符串中所有字符，都不在参数二的数组中。<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.containsNone("中华中", new char[]{'中', '达人'}));<br />&nbsp;&nbsp;&nbsp; //从后往前查找字符串中与字符数组中相同的元素第一次出现的位置。本例为4<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.lastIndexOfAny("中国人民共和国", new String[]{"国人", "共和"}));<br />&nbsp;&nbsp;&nbsp; //未发现与indexOfAny不同之处&nbsp; 查询字符串中指定字符串(参数二)出现的次数<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.countMatches("中国人民共和中国", "中国"));<br />&nbsp;&nbsp;&nbsp; //检查是否CharSequence的只包含Unicode的字母。空将返回false。一个空的CharSequence（长（）= 0）将返回true<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.isAlpha("这是干什么的2"));<br />&nbsp;&nbsp;&nbsp; //检查是否只包含Unicode的CharSequence的字母和空格（''）。空将返回一个空的CharSequence假（长（）= 0）将返回true。<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.isAlphaSpace("NBA直播 "));<br />&nbsp;&nbsp;&nbsp; //检查是否只包含Unicode的CharSequence的字母或数字。空将返回false。一个空的CharSequence（长（）= 0）将返回true。<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.isAlphanumeric("NBA直播"));<br />&nbsp;&nbsp;&nbsp; //如果检查的Unicode CharSequence的只包含字母，数字或空格（''）。空将返回false。一个空的CharSequence（长（）= 0）将返回true。<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.isAlphanumericSpace("NBA直播"));<br />&nbsp;&nbsp;&nbsp; //检查是否只包含ASCII可CharSequence的字符。空将返回false。一个空的CharSequence（长（）= 0）将返回true。<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.isAsciiPrintable("NBA直播"));<br />&nbsp;&nbsp;&nbsp; //检查是否只包含数值。<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.isNumeric("NBA直播"));<br />&nbsp;&nbsp;&nbsp; //检查是否只包含数值或者空格<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.isNumericSpace("33 545"));<br />&nbsp;&nbsp;&nbsp; //检查是否只是空格或""。<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.isWhitespace(" "));<br />&nbsp;&nbsp;&nbsp; //检查是否全是英文小写。<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.isAllLowerCase("kjk33"));<br />&nbsp;&nbsp;&nbsp; //检查是否全是英文大写。<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.isAllUpperCase("KJKJ"));<br />&nbsp;&nbsp;&nbsp; //交集操作~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />&nbsp;&nbsp;&nbsp; //去掉参数2字符串中在参数一中开头部分共有的部分，结果为:人民共和加油<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.difference("中国加油", "中国人民共和加油"));<br />&nbsp;&nbsp;&nbsp; //统计2个字符串开始部分共有的字符个数<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.indexOfDifference("ww.taobao", "www.taobao.com"));<br />&nbsp;&nbsp;&nbsp; //统计数组中各个元素的字符串开始都一样的字符个数<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.indexOfDifference(new String[] {"中国加油", "中国共和", "中国人民"}));<br />&nbsp;&nbsp;&nbsp; //取数组每个元素共同的部分字符串<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.getCommonPrefix(new String[] {"中国加油", "中国共和", "中国人民"}));<br />&nbsp;&nbsp;&nbsp; //统计参数一中每个字符与参数二中每个字符不同部分的字符个数<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.getLevenshteinDistance("中国共和发国人民", "共和国"));<br />&nbsp;&nbsp;&nbsp; //判断开始部分是否与二参数相同<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.startsWith("中国共和国人民", "中国"));<br />&nbsp;&nbsp;&nbsp; //判断开始部分是否与二参数相同。不区分大小写<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.startsWithIgnoreCase("中国共和国人民", "中国"));<br />&nbsp;&nbsp;&nbsp; //判断字符串开始部分是否与数组中的某一元素相同<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.startsWithAny("abef", new String[]{"ge", "af", "ab"}));<br />&nbsp;&nbsp;&nbsp; //判断结尾是否相同<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.endsWith("abcdef", "def"));<br />&nbsp;&nbsp;&nbsp; //判断结尾是否相同，不区分大小写<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.endsWithIgnoreCase("abcdef", "Def"));<br />&nbsp;&nbsp;&nbsp; //字符串截取~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />&nbsp;&nbsp;&nbsp; //截取指定位置的字符，null返回null.""返回""<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.substring("国民党", 2));<br />&nbsp;&nbsp;&nbsp; //截取指定区间的字符<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.substring("中国人民共和国", 2, 4));<br />&nbsp;&nbsp;&nbsp; //从左截取指定长度的字符串<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.left("说点什么好呢", 3));<br />&nbsp;&nbsp;&nbsp; //从右截取指定长度的字符串<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.right("说点什么好呢", 3));<br />&nbsp;&nbsp;&nbsp; //从第几个开始截取，三参数表示截取的长度<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.mid("说点什么好呢", 3, 2));<br />&nbsp;&nbsp;&nbsp; //截取到等于第二个参数的字符串为止<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.substringBefore("说点什么好呢", "好"));<br />&nbsp;&nbsp;&nbsp; //从左往右查到相等的字符开始，保留后边的，不包含等于的字符。本例：什么好呢<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.substringAfter("说点什么好呢", "点"));<br />&nbsp;&nbsp;&nbsp; //这个也是截取到相等的字符，但是是从右往左.本例结果：说点什么好<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.substringBeforeLast("说点什么好点呢", "点"));<br />&nbsp;&nbsp;&nbsp; //这个截取同上是从右往左。但是保留右边的字符<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.substringAfterLast("说点什么好点呢？", "点"));<br />&nbsp;&nbsp;&nbsp; //截取查找到第一次的位置，和第二次的位置中间的字符。如果没找到第二个返回null。本例结果:2010世界杯在<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.substringBetween("南非2010世界杯在南非，在南非", "南非"));<br />&nbsp;&nbsp;&nbsp; //返回参数二和参数三中间的字符串，返回数组形式<br />&nbsp;&nbsp;&nbsp; //ArrayToList(StringUtils.substringsBetween("[a][b][c]", "[", "]"));<br />&nbsp;&nbsp;&nbsp; //分割~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />&nbsp;&nbsp;&nbsp; //用空格分割成数组，null为null<br />&nbsp;&nbsp;&nbsp; //ArrayToList(StringUtils.split("中华 人民&nbsp; 共和"));<br />&nbsp;&nbsp;&nbsp; //以指定字符分割成数组<br />&nbsp;&nbsp;&nbsp; //ArrayToList(StringUtils.split("中华 ,人民,共和", ","));<br />&nbsp;&nbsp;&nbsp; //以指定字符分割成数组，第三个参数表示分隔成数组的长度，如果为0全体分割<br />&nbsp;&nbsp;&nbsp; //ArrayToList(StringUtils.split("中华 ：人民：共和", "：", 2));<br />&nbsp;&nbsp;&nbsp; //未发现不同的地方,指定字符分割成数组<br />&nbsp;&nbsp;&nbsp; //ArrayToList(StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-"));<br />&nbsp;&nbsp;&nbsp; //未发现不同的地方,以指定字符分割成数组，第三个参数表示分隔成数组的长度<br />&nbsp;&nbsp;&nbsp; //ArrayToList(StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2));<br />&nbsp;&nbsp;&nbsp; //分割，但" "不会被忽略算一个元素,二参数为null默认为空格分隔<br />&nbsp;&nbsp;&nbsp; //ArrayToList(StringUtils.splitByWholeSeparatorPreserveAllTokens(" ab&nbsp;&nbsp; de fg ", null));<br />&nbsp;&nbsp;&nbsp; //同上，分割," "不会被忽略算一个元素。第三个参数代表分割的数组长度。<br />&nbsp;&nbsp;&nbsp; //ArrayToList(StringUtils.splitByWholeSeparatorPreserveAllTokens("ab&nbsp;&nbsp; de fg", null, 3));<br />&nbsp;&nbsp;&nbsp; //未发现不同地方,分割<br />&nbsp;&nbsp;&nbsp; //ArrayToList(StringUtils.splitPreserveAllTokens(" ab&nbsp;&nbsp; de fg "));<br />&nbsp;&nbsp;&nbsp; //未发现不同地方,指定字符分割成数组<br />&nbsp;&nbsp;&nbsp; //ArrayToList(StringUtils.splitPreserveAllTokens(" ab&nbsp;&nbsp; de fg ", null));<br />&nbsp;&nbsp;&nbsp; //未发现不同地方,以指定字符分割成数组，第三个参数表示分隔成数组的长度<br />&nbsp;&nbsp;&nbsp; //ArrayToList(StringUtils.splitPreserveAllTokens(" ab&nbsp;&nbsp; de fg ", null, 2));<br />&nbsp;&nbsp;&nbsp; //以不同类型进行分隔<br />&nbsp;&nbsp;&nbsp; //ArrayToList(StringUtils.splitByCharacterType("AEkjKr i39:。中文"));<br />&nbsp;&nbsp;&nbsp; //未解<br />&nbsp;&nbsp;&nbsp; //ArrayToList(StringUtils.splitByCharacterTypeCamelCase("ASFSRules234"));<br />&nbsp;&nbsp;&nbsp; //拼接~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />&nbsp;&nbsp;&nbsp; //将数组转换为字符串形式<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.concat(getArrayData()));<br />&nbsp;&nbsp;&nbsp; //拼接时用参数一得字符相连接.注意null也用连接符连接了<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.concatWith(",", getArrayData()));<br />&nbsp;&nbsp;&nbsp; //也是拼接。未发现区别<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.join(getArrayData()));<br />&nbsp;&nbsp;&nbsp; //用连接符拼接，为发现区别<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.join(getArrayData(), ":"));<br />&nbsp;&nbsp;&nbsp; //拼接指定数组下标的开始(三参数)和结束(四参数,不包含)的中间这些元素，用连接符连接<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.join(getArrayData(), ":", 1, 3));<br />&nbsp;&nbsp;&nbsp; //用于集合连接字符串.用于集合<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.join(getListData(), ":"));<br />&nbsp;&nbsp;&nbsp; //移除，删除~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />&nbsp;&nbsp;&nbsp; //删除所有空格符<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.deleteWhitespace(" s 中 你 4j"));<br />&nbsp;&nbsp;&nbsp; //移除开始部分的相同的字符<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.removeStart("www.baidu.com", "www."));<br />&nbsp;&nbsp;&nbsp; //移除开始部分的相同的字符,不区分大小写<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.removeStartIgnoreCase("www.baidu.com", "WWW"));<br />&nbsp;&nbsp;&nbsp; //移除后面相同的部分<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.removeEnd("www.baidu.com", ".com"));<br />&nbsp;&nbsp;&nbsp; //移除后面相同的部分，不区分大小写<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.removeEndIgnoreCase("www.baidu.com", ".COM"));<br />&nbsp;&nbsp;&nbsp; //移除所有相同的部分<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.remove("www.baidu.com/baidu", "bai"));<br />&nbsp;&nbsp;&nbsp; //移除结尾字符为"\n", "\r", 或者 "\r\n".<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.chomp("abcrabc\r"));<br />&nbsp;&nbsp;&nbsp; //也是移除，未解。去结尾相同字符<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.chomp("baidu.com", "com"));<br />&nbsp;&nbsp;&nbsp; //去掉末尾最后一个字符.如果是"\n", "\r", 或者 "\r\n"也去除<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.chop("wwe.baidu"));<br />&nbsp;&nbsp;&nbsp; //替换~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />&nbsp;&nbsp;&nbsp; //替换指定的字符，只替换第一次出现的<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.replaceOnce("www.baidu.com/baidu", "baidu", "hao123"));<br />&nbsp;&nbsp;&nbsp; //替换所有出现过的字符<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.replace("www.baidu.com/baidu", "baidu", "hao123"));<br />&nbsp;&nbsp;&nbsp; //也是替换，最后一个参数表示替换几个<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.replace("www.baidu.com/baidu", "baidu", "hao123", 1));<br />&nbsp;&nbsp;&nbsp; //这个有意识，二三参数对应的数组，查找二参数数组一样的值，替换三参数对应数组的值。本例:baidu替换为taobao。com替换为net<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.replaceEach("www.baidu.com/baidu", new String[]{"baidu", "com"}, new String[]{"taobao", "net"}));<br />&nbsp;&nbsp;&nbsp; //同上，未发现不同<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.replaceEachRepeatedly("www.baidu.com/baidu", new String[]{"baidu", "com"}, new String[]{"taobao", "net"}));<br />&nbsp;&nbsp;&nbsp; //这个更好，不是数组对应，是字符串参数二和参数三对应替换.(二三参数不对应的话，自己看后果)<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.replaceChars("www.baidu.com", "bdm", "qo"));<br />&nbsp;&nbsp;&nbsp; //替换指定开始(参数三)和结束(参数四)中间的所有字符<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.overlay("www.baidu.com", "hao123", 4, 9));<br />&nbsp;&nbsp;&nbsp; //添加，增加~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />&nbsp;&nbsp;&nbsp; //复制参数一的字符串，参数二为复制的次数<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.repeat("ba", 3));<br />&nbsp;&nbsp;&nbsp; //复制参数一的字符串，参数三为复制的次数。参数二为复制字符串中间的连接字符串<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.repeat("ab", "ou", 3));<br />&nbsp;&nbsp;&nbsp; //如何字符串长度小于参数二的值，末尾加空格补全。(小于字符串长度不处理返回)<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.rightPad("海川", 4));<br />&nbsp;&nbsp;&nbsp; //字符串长度小于二参数，末尾用参数三补上，多于的截取(截取补上的字符串)<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.rightPad("海川", 4, "河流啊"));<br />&nbsp;&nbsp;&nbsp; //同上在前面补全空格<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.leftPad("海川", 4));<br />&nbsp;&nbsp;&nbsp; //字符串长度小于二参数，前面用参数三补上，多于的截取(截取补上的字符串)<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.leftPad("海川", 4, "大家好"));<br />&nbsp;&nbsp;&nbsp; //字符串长度小于二参数。在两侧用空格平均补全（测试后面补空格优先）<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.center("海川", 3));<br />&nbsp;&nbsp;&nbsp; //字符串长度小于二参数。在两侧用三参数的字符串平均补全（测试后面补空格优先）<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.center("海川", 5, "流"));<br />&nbsp;&nbsp;&nbsp; //只显示指定数量(二参数)的字符,后面以三个点补充(参数一截取+三个点=二参数)<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.abbreviate("中华人民共和国", 5));<br />&nbsp;&nbsp;&nbsp; //2头加点这个有点乱。本例结果: ...ijklmno<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.abbreviate("abcdefghijklmno", 12, 10));<br />&nbsp;&nbsp;&nbsp; //保留指定长度，最后一个字符前加点.本例结果: ab.f<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.abbreviateMiddle("abcdef", ".", 4));<br />&nbsp;&nbsp;&nbsp; //转换,刷选~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~<br />&nbsp;&nbsp;&nbsp; //转换第一个字符为大写.如何第一个字符是大写原始返回<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.capitalize("Ddf"));<br />&nbsp;&nbsp;&nbsp; //转换第一个字符为大写.如何第一个字符是大写原始返回<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.uncapitalize("DTf"));<br />&nbsp;&nbsp;&nbsp; //反向转换，大写变小写，小写变大写<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.swapCase("I am Jiang, Hello"));<br />&nbsp;&nbsp;&nbsp; //将字符串倒序排列<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.reverse("中国人民"));<br />&nbsp;&nbsp;&nbsp; //根据特定字符(二参数)分隔进行反转<br />&nbsp;&nbsp;&nbsp; //System.out.println(StringUtils.reverseDelimited("中:国:人民", ':'));<br />}<br /><br />//将数组转换为List<br />private static void ArrayToList(String[] str){<br />&nbsp;&nbsp;&nbsp; System.out.println(Arrays.asList(str) + " 长度:" + str.length);<br />}<br /><br />//获得集合数据<br />private static List getListData(){<br />&nbsp;&nbsp;&nbsp; List list = new ArrayList();<br />&nbsp;&nbsp;&nbsp; list.add("你好");<br />&nbsp;&nbsp;&nbsp; list.add(null);<br />&nbsp;&nbsp;&nbsp; list.add("他好");<br />&nbsp;&nbsp;&nbsp; list.add("大家好");<br />&nbsp;&nbsp;&nbsp; return list;<br />}<br /><br />//获得数组数据 <br />private static String[] getArrayData(){<br />&nbsp;&nbsp;&nbsp; return (String[]) getListData().toArray(new String[0]);<br />}<br /><br />public static void main(String[] args) {<br />&nbsp;&nbsp;&nbsp; TestStr();<br />}<img src ="http://www.blogjava.net/lyjjq/aggbug/387453.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2012-09-11 12:54 <a href="http://www.blogjava.net/lyjjq/articles/387453.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Eclipse console 中文乱码解决</title><link>http://www.blogjava.net/lyjjq/articles/386969.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Tue, 04 Sep 2012 08:43:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/386969.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/386969.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/386969.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/386969.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/386969.html</trackback:ping><description><![CDATA[<div class="articalTitle"><br /><h2 id="t_4c73bcc801011deo" class="titName SG_txta">Eclipse console 中文乱码解决<br /></h2></div><div id="sina_keyword_ad_area2" class="articalContent  "><div><br />在Eclipse里面点击<br />run--&gt;Run Configurations <br />...<br />然后找到Common下面的 <br />Encoding<br />在Other里选择你所要的编码格式(我用的是UTF-8,中文OK)<br /><br />如果还不行就改成GBK...</div></div><img src ="http://www.blogjava.net/lyjjq/aggbug/386969.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2012-09-04 16:43 <a href="http://www.blogjava.net/lyjjq/articles/386969.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java 线程组</title><link>http://www.blogjava.net/lyjjq/articles/381678.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Thu, 28 Jun 2012 00:53:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/381678.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/381678.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/381678.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/381678.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/381678.html</trackback:ping><description><![CDATA[<p>ThreadGroup其实比ExecutorService更好<br />&nbsp;<br />&nbsp;&nbsp; 用java做抓取的时候免不了要用到多线程的了，因为要同时抓取多个网站或一条线程抓取一个网站的话实在太慢，而且有时一条线程抓取同一个网站的话也比较浪费CPU资源。要用到多线程的等方面，也就免不了对线程的控制或用到线程池。&nbsp;&nbsp; 我在做我们现在的那一个抓取框架的时候，就曾经用过java.util.concurrent.ExecutorService作为线程池，关于ExecutorService的使用代码大概如下：<br />java.util.concurrent.Executors类的API提供大量创建连接池的静态方法：1.固定大小的线程池：<br />&nbsp;</p><p><br />package BackStage;</p><p>&nbsp;import java.util.concurrent.Executors;<br />&nbsp;import java.util.concurrent.ExecutorService;</p><p>&nbsp;public class JavaThreadPool {<br />&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 创建一个可重用固定线程数的线程池<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ExecutorService pool = Executors.newFixedThreadPool(2);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 创建实现了Runnable接口对象，Thread对象当然也实现了Runnable接口<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread t1 = new MyThread();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread t2 = new MyThread();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread t3 = new MyThread();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread t4 = new MyThread();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread t5 = new MyThread();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 将线程放入池中进行执行<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pool.execute(t1);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pool.execute(t2);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pool.execute(t3);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pool.execute(t4);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pool.execute(t5);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 关闭线程池<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pool.shutdown();<br />&nbsp;&nbsp;&nbsp; }<br />}</p><p>class MyThread extends Thread {<br />&nbsp;&nbsp;&nbsp; @Override<br />&nbsp;&nbsp;&nbsp; public void run() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(Thread.currentThread().getName() + "正在执行。。。");<br />&nbsp;&nbsp;&nbsp; }<br />} </p><p><br />&nbsp;&nbsp; 后来发现ExecutorService的功能没有想像中的那么好，而且最多只是提供一个线程的容器而然，所以后来我用改用了java.lang.ThreadGroup，ThreadGroup有很多优势，最重要的一点就是它可以对线程进行遍历，知道那些线程已经运行完毕，还有那些线程在运行。关于ThreadGroup的使用代码如下：<br />&nbsp;</p><p>class MyThread extends Thread {&nbsp;&nbsp; <br />&nbsp;&nbsp; boolean stopped;&nbsp;&nbsp; <br />&nbsp;&nbsp; MyThread(ThreadGroup tg, String name) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(tg, name);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stopped = false;&nbsp;&nbsp; <br />&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp; public void run() {&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(Thread.currentThread().getName() + " starting.");&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 1; i &lt; 1000; i++) {&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.print(".");&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(250);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (this) {&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (stopped)break;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (Exception exc) {&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(Thread.currentThread().getName() + " interrupted.");&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(Thread.currentThread().getName() + " exiting.");&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp; <br />&nbsp;&nbsp;&nbsp; synchronized void myStop() {&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stopped = true;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp; <br />}&nbsp; <br />public class Main {&nbsp; <br />&nbsp;&nbsp;&nbsp; public static void main(String args[]) throws Exception {&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ThreadGroup tg = new ThreadGroup("My Group");&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyThread thrd = new MyThread(tg, "MyThread #1");&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyThread thrd2 = new MyThread(tg, "MyThread #2");&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyThread thrd3 = new MyThread(tg, "MyThread #3");&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thrd.start();&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thrd2.start();&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thrd3.start();&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(1000);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(tg.activeCount() + " threads in thread group.");&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread thrds[] = new Thread[tg.activeCount()];&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tg.enumerate(thrds);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (Thread t : thrds)&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(t.getName());&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thrd.myStop();&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(1000);&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(tg.activeCount() + " threads in tg.");&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tg.interrupt();&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp; <br />}&nbsp; </p><p>&nbsp;<br />&nbsp; 由以上的代码可以看出：ThreadGroup比ExecutorService多以下几个优势&nbsp; <br />&nbsp;<br />1.ThreadGroup可以遍历线程，知道那些线程已经运行完毕，那些还在运行&nbsp; <br />&nbsp;<br />2.可以通过ThreadGroup.activeCount知道有多少线程从而可以控制插入的线程数<br /></p><img src ="http://www.blogjava.net/lyjjq/aggbug/381678.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2012-06-28 08:53 <a href="http://www.blogjava.net/lyjjq/articles/381678.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java synchronized详解</title><link>http://www.blogjava.net/lyjjq/articles/381415.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Mon, 25 Jun 2012 04:06:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/381415.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/381415.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/381415.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/381415.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/381415.html</trackback:ping><description><![CDATA[一直对这些不是很懂。找了一下，看一下，供我以后再看:<br /><div><span style='line-height: 25px; font-family: "Trebuchet MS", "Lucida Console", "Lucida Sans";'><br /><p style="margin: 10px 0px; word-break: break-all;">第一篇：　　</p><br /><p style="margin: 10px 0px; word-break: break-all;">Java语言的关键字，当它用来修饰一个方法或者一个代码块的时候，能够保证在同一时刻最多只有一个线程执行该段代码。 <br style="word-break: break-all;" /></p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; <br />一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时，一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。</p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; <br />二、然而，当一个线程访问object的一个synchronized(this)同步代码块时，另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。</p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; <br />三、尤其关键的是，当一个线程访问object的一个synchronized(this)同步代码块时，其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。</p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; <br />四、第三个例子同样适用其它同步代码块。也就是说，当一个线程访问object的一个synchronized(this)同步代码块时，它就获得了这个object的对象锁。结果，其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。</p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; 五、以上规则对其它对象锁同样适用.</p><br /><p style="margin: 10px 0px; word-break: break-all;">举例说明： <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时，一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。</p><br /><p style="margin: 10px 0px; word-break: break-all;">package ths;</p><br /><p style="margin: 10px 0px; word-break: break-all;">public class Thread1 <br />implements Runnable { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; public void run() <br />{ <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(this) { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; 5; i++) <br />{ <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />System.out.println(Thread.currentThread().getName() + " synchronized loop " + <br />i); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />} <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) <br />{ <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread1 t1 = new Thread1(); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread ta = new Thread(t1, "A"); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread tb = new Thread(t1, "B"); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ta.start(); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tb.start(); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; }<br style="word-break: break-all;" />}</p><br /><p style="margin: 10px 0px; word-break: break-all;">结果： <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; A synchronized loop 0 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; A synchronized loop 1 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; A synchronized loop 2 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; A synchronized loop 3 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; A synchronized loop 4 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; B synchronized loop 0 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; B synchronized loop 1 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; B synchronized loop 2 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; B synchronized loop 3 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; B synchronized loop 4</p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; <br />二、然而，当一个线程访问object的一个synchronized(this)同步代码块时，另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。</p><br /><p style="margin: 10px 0px; word-break: break-all;">package ths;</p><br /><p style="margin: 10px 0px; word-break: break-all;">public class Thread2 { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; public void m4t1() { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(this) { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i = 5; <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while( i-- &gt; 0) { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />System.out.println(Thread.currentThread().getName() + " : " + i); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(500); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (InterruptedException <br />ie) { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />} <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; public void m4t2() { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i = 5; <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while( i-- &gt; 0) { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />System.out.println(Thread.currentThread().getName() + " : " + i); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(500); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (InterruptedException ie) <br />{ <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />} <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) <br />{ <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final Thread2 myt2 = new <br />Thread2(); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread t1 = new Thread(&nbsp; <br />new Runnable() {&nbsp; public void run() {&nbsp; myt2.m4t1();&nbsp; }&nbsp; }, "t1"&nbsp; ); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread t2 = new Thread(&nbsp; new Runnable() <br />{&nbsp; public void run() { myt2.m4t2();&nbsp;&nbsp; }&nbsp; }, "t2"&nbsp; ); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t1.start(); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t2.start(); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; }<br style="word-break: break-all;" />}</p><br /><p style="margin: 10px 0px; word-break: break-all;">结果： <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : 4 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />t2 : 4 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : 3 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : 3 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />t1 : 2 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : 2 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : 1 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />t2 : 1 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : 0 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : 0</p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; <br />三、尤其关键的是，当一个线程访问object的一个synchronized(this)同步代码块时，其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。</p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; <br />//修改Thread2.m4t2()方法： <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; public void m4t2() <br />{ <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(this) { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i = 5; <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while( i-- &gt; 0) { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />System.out.println(Thread.currentThread().getName() + " : " + i); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(500); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (InterruptedException <br />ie) { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; }</p><br /><p style="margin: 10px 0px; word-break: break-all;">结果：</p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; t1 : 4 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : 3 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />t1 : 2 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : 1 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : 0 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />t2 : 4 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : 3 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : 2 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />t2 : 1 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : 0</p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; <br />四、第三个例子同样适用其它同步代码块。也就是说，当一个线程访问object的一个synchronized(this)同步代码块时，它就获得了这个object的对象锁。结果，其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。</p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; <br />//修改Thread2.m4t2()方法如下：</p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; public synchronized void <br />m4t2() { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i = 5; <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while( i-- &gt; 0) { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />System.out.println(Thread.currentThread().getName() + " : " + i); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(500); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (InterruptedException ie) <br />{ <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />}</p><br /><p style="margin: 10px 0px; word-break: break-all;">结果： <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : 4 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />t1 : 3 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : 2 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : 1 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />t1 : 0 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : 4 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : 3 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />t2 : 2 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : 1 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : 0</p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; 五、以上规则对其它对象锁同样适用:</p><br /><p style="margin: 10px 0px; word-break: break-all;">package ths;</p><br /><p style="margin: 10px 0px; word-break: break-all;">public class Thread3 {<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; class Inner {<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void m4t1() {<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i = 5;<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(i-- &gt; 0) {<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />System.out.println(Thread.currentThread().getName() + " : Inner.m4t1()=" + <br />i);<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(500);<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch(InterruptedException <br />ie) {<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void m4t2() {<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i = 5;<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(i-- &gt; 0) {<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + <br />i);<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(500);<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch(InterruptedException <br />ie) {<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />}<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; private void m4t1(Inner inner) {<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(inner) { //使用对象锁<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inner.m4t1();<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; }<br style="word-break: break-all;" /> <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; private void m4t2(Inner inner) {<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inner.m4t2();<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; }<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp; <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final Thread3 myt3 = new Thread3();<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; final Inner inner = myt3.new Inner();<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread t1 = new Thread( new Runnable() <br />{public void run() { myt3.m4t1(inner);} }, "t1");<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; Thread t2 = new Thread( new Runnable() <br />{public void run() { myt3.m4t2(inner);} }, "t2");<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1.start();<br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2.start();<br style="word-break: break-all;" />&nbsp; }<br style="word-break: break-all;" />}<br style="word-break: break-all;" /></p><br /><p style="margin: 10px 0px; word-break: break-all;"> </p><br /><p style="margin: 10px 0px; word-break: break-all;">结果：</p><br /><p style="margin: 10px 0px; word-break: break-all;">尽管线程t1获得了对Inner的对象锁，但由于线程t2访问的是同一个Inner中的非同步部分。所以两个线程互不干扰。</p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; t1 : Inner.m4t1()=4 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : Inner.m4t2()=4 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : Inner.m4t1()=3 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : Inner.m4t2()=3 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : Inner.m4t1()=2 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : Inner.m4t2()=2 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : Inner.m4t1()=1 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : Inner.m4t2()=1 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : Inner.m4t1()=0 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : Inner.m4t2()=0</p><br /><p style="margin: 10px 0px; word-break: break-all;">现在在Inner.m4t2()前面加上synchronized：</p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; private synchronized <br />void m4t2() { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i = 5; <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(i-- &gt; 0) { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />System.out.println(Thread.currentThread().getName() + " : Inner.m4t2()=" + <br />i); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try { <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.sleep(500); <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch(InterruptedException ie) <br />{ <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />}</p><br /><p style="margin: 10px 0px; word-break: break-all;">结果：</p><br /><p style="margin: 10px 0px; word-break: break-all;">尽管线程t1与t2访问了同一个Inner对象中两个毫不相关的部分,但因为t1先获得了对Inner的对象锁，所以t2对Inner.m4t2()的访问也被阻塞，因为m4t2()是Inner中的一个同步方法。</p><br /><p style="margin: 10px 0px; word-break: break-all;">&nbsp;&nbsp;&nbsp;&nbsp; t1 : Inner.m4t1()=4 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : Inner.m4t1()=3 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : Inner.m4t1()=2 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : Inner.m4t1()=1 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t1 : Inner.m4t1()=0 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : Inner.m4t2()=4 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : Inner.m4t2()=3 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : Inner.m4t2()=2 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : Inner.m4t2()=1 <br style="word-break: break-all;" />&nbsp;&nbsp;&nbsp;&nbsp; t2 : Inner.m4t2()=0</p><br /><p style="margin: 10px 0px; word-break: break-all;">第二篇：</p><br /><p style="margin: 10px 0px; word-break: break-all;"><span style="color: rgb(51, 51, 51); line-height: 20px; font-family: Arial; -webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px;"></span></p><br /><table style="width: 947px; table-layout: fixed;"><br /><tbody><br /><tr><br /><td style="line-height: 18px; font-family: Arial; font-size: 12px; filter: none; word-break: break-all; word-wrap: break-word;"><br /><div style="color: rgb(51, 51, 51); line-height: 20px; font-family: Arial; font-size: 14px; filter: none; word-break: normal; overflow-x: hidden; overflow-y: hidden; word-wrap: break-word;"><br /><p style="line-height: normal;">synchronized 关键字，它包括两种用法：synchronized 方法和 <br />synchronized 块。 <br style="line-height: normal;" />　　1. synchronized 方法：通过在方法声明中加入 <br />synchronized关键字来声明 synchronized 方法。如： <br style="line-height: normal;" />　　public <br />synchronized void accessVal(int newVal); <br style="line-height: normal;" />　　synchronized 方法控制对类成员变量的访问：每个类实例对应一把锁，每个 <br />synchronized 方法都必须获得调用该方法的类实例的锁方能</p><br /><p style="line-height: normal;">执行，否则所属线程阻塞，方法一旦执行，就独占该锁，直到从该方法返回时才将锁释放，此后被阻塞的线程方能获得该锁，重新进入可执行</p><br /><p style="line-height: normal;">状态。这种机制确保了同一时刻对于每一个类实例，其所有声明为 synchronized <br />的成员函数中至多只有一个处于可执行状态（因为至多只有</p><br /><p style="line-height: normal;">一个能够获得该类实例对应的锁），从而有效避免了类成员变量的访问冲突（只要所有可能访问类成员变量的方法均被声明为 <br />synchronized）</p><br /><p style="line-height: normal;">。 <br style="line-height: normal;" />　　在 Java <br />中，不光是类实例，每一个类也对应一把锁，这样我们也可将类的静态成员函数声明为 synchronized ，以控制其对类的静态成</p><br /><p style="line-height: normal;">员变量的访问。 <br style="line-height: normal;" />　　synchronized 方法的缺陷：若将一个大的方法声明为synchronized <br />将会大大影响效率，典型地，若将线程类的方法 run() 声明为</p><br /><p style="line-height: normal;">synchronized ，由于在线程的整个生命期内它一直在运行，因此将导致它对本类任何 <br />synchronized 方法的调用都永远不会成功。当然我们可</p><br /><p style="line-height: normal;">以通过将访问类成员变量的代码放到专门的方法中，将其声明为 synchronized <br />，并在主方法中调用来解决这一问题，但是 Java 为我们提供</p><br /><p style="line-height: normal;">了更好的解决办法，那就是 synchronized 块。 <br style="line-height: normal;" />　　2. synchronized 块：通过 <br />synchronized关键字来声明synchronized 块。语法如下： <br style="line-height: normal;" />　　synchronized(syncObject) { <br style="line-height: normal;" />　　//允许访问控制的代码 <br style="line-height: normal;" />　　} <br style="line-height: normal;" />　　 synchronized <br />块是这样一个代码块，其中的代码必须获得对象 syncObject （如前所述，可以是类实例或类）的锁方能执行，具体机</p><br /><p style="line-height: normal;">制同前所述。由于可以针对任意代码块，且可任意指定上锁的对象，故灵活性较高。 <br style="line-height: normal;" />　　对synchronized(this)的一些理解<br style="line-height: normal;" />　　一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时，一个时间内只能有一个线程得到执行。另一个线</p><br /><p style="line-height: normal;">程必须等待当前线程执行完这个代码块以后才能执行该代码块。 <br style="line-height: normal;" />　　二、然而，当一个线程访问object的一个synchronized(this)同步代码块时，另一个线程仍然可以访问该object中的非synchronized</p><br /><p style="line-height: normal;">(this)同步代码块。 <br style="line-height: normal;" />　　三、尤其关键的是，当一个线程访问object的一个synchronized(this)同步代码块时，其他线程对object中所有其它synchronized(this)</p><br /><p style="line-height: normal;">同步代码块的访问将被阻塞。 <br style="line-height: normal;" />　　四、第三个例子同样适用其它同步代码块。也就是说，当一个线程访问object的一个synchronized(this)同步代码块时，它就获得了这个</p><br /><p style="line-height: normal;">object的对象锁。结果，其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。 <br style="line-height: normal;" />　　五、以上规则对其它对象锁同样适用</p><br /><p style="line-height: normal;"><br style="line-height: normal;" /><a style="line-height: normal; text-decoration: none;" href="http://hi.baidu.com/sunshibing/blog/item/5235b9b731d48ff430add14a.html" rel="nofollow">http://hi.baidu.com/sunshibing/blog/item/5235b9b731d48ff430add14a.html</a><br style="line-height: normal;" /><strong style="line-height: normal;">java中synchronized用法</strong></p><br /><p style="line-height: normal;">打个比方：一个object就像一个大房子，大门永远打开。房子里有 很多房间（也就是方法）。</p><br /><p style="line-height: normal;">这些房间有上锁的（synchronized方法）， <br />和不上锁之分（普通方法）。房门口放着一把钥匙（key），这把钥匙可以打开所有上锁的房间。</p><br /><p style="line-height: normal;">另外我把所有想调用该对象方法的线程比喻成想进入这房子某个 <br />房间的人。所有的东西就这么多了，下面我们看看这些东西之间如何作用的。</p><br /><p style="line-height: normal;">在此我们先来明确一下我们的前提条件。该对象至少有一个synchronized方法，否则这个key还有啥意义。当然也就不会有我们的这个主题了。</p><br /><p style="line-height: normal;">一个人想进入某间上了锁的房间，他来到房子门口，看见钥匙在那儿（说明暂时还没有其他人要使用上锁的 <br />房间）。于是他走上去拿到了钥匙</p><br /><p style="line-height: normal;">，并且按照自己 <br />的计划使用那些房间。注意一点，他每次使用完一次上锁的房间后会马上把钥匙还回去。即使他要连续使用两间上锁的房间，</p><br /><p style="line-height: normal;">中间他也要把钥匙还回去，再取回来。</p><br /><p style="line-height: normal;">因此，普通情况下钥匙的使用原则是：&#8220;随用随借，用完即还。&#8221;</p><br /><p style="line-height: normal;">这时其他人可以不受限制的使用那些不上锁的房间，一个人用一间可以，两个人用一间也可以，没限制。但是如果当某个人想要进入上锁的房</p><br /><p style="line-height: normal;">间，他就要跑到大门口去看看了。有钥匙当然拿了就走，没有的话，就只能等了。</p><br /><p style="line-height: normal;">要是很多人在等这把钥匙，等钥匙还回来以后，谁会优先得到钥匙？Not <br />guaranteed。象前面例子里那个想连续使用两个上锁房间的家伙，他</p><br /><p style="line-height: normal;">中间还钥匙的时候如果还有其他人在等钥匙，那么没有任何保证这家伙能再次拿到。 <br />（JAVA规范在很多地方都明确说明不保证，象</p><br /><p style="line-height: normal;">Thread.sleep()休息后多久会返回运行，相同优先权的线程那个首先被执行，当要访问对象的锁被 <br />释放后处于等待池的多个线程哪个会优先得</p><br /><p style="line-height: normal;">到，等等。我想最终的决定权是在JVM，之所以不保证，就是因为JVM在做出上述决定的时候，绝不是简简单单根据 <br />一个条件来做出判断，而是</p><br /><p style="line-height: normal;">根据很多条。而由于判断条件太多，如果说出来可能会影响JAVA的推广，也可能是因为知识产权保护的原因吧。SUN给了个不保证 <br />就混过去了</p><br /><p style="line-height: normal;">。无可厚非。但我相信这些不确定，并非完全不确定。因为计算机这东西本身就是按指令运行的。即使看起来很随机的现象，其实都是有规律</p><br /><p style="line-height: normal;">可寻。学过 <br />计算机的都知道，计算机里随机数的学名是伪随机数，是人运用一定的方法写出来的，看上去随机罢了。另外，或许是因为要想弄</p><br /><p style="line-height: normal;">的确定太费事，也没多大意义，所 以不确定就不确定了吧。）</p><br /><p style="line-height: normal;">再来看看同步代码块。和同步方法有小小的不同。</p><br /><p style="line-height: normal;">1.从尺寸上讲，同步代码块比同步方法小。你可以把同步代码块看成是没上锁房间里的一块用带锁的屏风隔开的空间。</p><br /><p style="line-height: normal;">2.同步代码块还可以人为的指定获得某个其它对象的key。就像是指定用哪一把钥匙才能开这个屏风的锁，你可以用本房的钥匙；你也可以指定</p><br /><p style="line-height: normal;">用另一个房子的钥匙才能开，这样的话，你要跑到另一栋房子那儿把那个钥匙拿来，并用那个房子的钥匙来打开这个房子的带锁的屏风。</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 记住你获得的那另一栋房子的钥匙，并不影响其他人进入那栋房子没有锁的房间。</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />为什么要使用同步代码块呢？我想应该是这样的：首先对程序来讲同步的部分很影响运行效率，而一个方法通常是先创建一些局部变</p><br /><p style="line-height: normal;">量，再对这些变量做一些 <br />操作，如运算，显示等等；而同步所覆盖的代码越多，对效率的影响就越严重。因此我们通常尽量缩小其影响范围。</p><br /><p style="line-height: normal;">如何做？同步代码块。我们只把一个方法中该同 步的地方同步，比如运算。</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />另外，同步代码块可以指定钥匙这一特点有个额外的好处，是可以在一定时期内霸占某个对象的key。还记得前面说过普通情况下钥</p><br /><p style="line-height: normal;">匙的使用原则吗。现在不是普通情况了。你所取得的那把钥匙不是永远不还，而是在退出同步代码块时才还。</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />还用前面那个想连续用两个上锁房间的家伙打比方。怎样才能在用完一间以后，继续使用另一间呢。用同步代码块吧。先创建另外</p><br /><p style="line-height: normal;">一个线程，做一个同步代码 <br />块，把那个代码块的锁指向这个房子的钥匙。然后启动那个线程。只要你能在进入那个代码块时抓到这房子的钥匙</p><br /><p style="line-height: normal;">，你就可以一直保留到退出那个代码块。也就是说 <br />你甚至可以对本房内所有上锁的房间遍历，甚至再sleep(10*60*1000)，而房门口却还有</p><br /><p style="line-height: normal;">1000个线程在等这把钥匙呢。很过瘾吧。</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />在此对sleep()方法和钥匙的关联性讲一下。一个线程在拿到key后，且没有完成同步的内容时，如果被强制sleep()了，那key还一</p><br /><p style="line-height: normal;">直在 <br />它那儿。直到它再次运行，做完所有同步内容，才会归还key。记住，那家伙只是干活干累了，去休息一下，他并没干完他要干的事。为</p><br /><p style="line-height: normal;">了避免别人进入那个房间 把里面搞的一团糟，即使在睡觉的时候他也要把那唯一的钥匙戴在身上。</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />最后，也许有人会问，为什么要一把钥匙通开，而不是一个钥匙一个门呢？我想这纯粹是因为复杂性问题。一个钥匙一个门当然更</p><br /><p style="line-height: normal;">安全，但是会牵扯好多问题。钥匙 <br />的产生，保管，获得，归还等等。其复杂性有可能随同步方法的增加呈几何级数增加，严重影响效率。这也</p><br /><p style="line-height: normal;">算是一个权衡的问题吧。为了增加一点点安全性，导致效 率大大降低，是多么不可取啊。</p><br /><p style="line-height: normal;">synchronized的一个简单例子</p><br /><p style="line-height: normal;">public class TextThread {</p><br /><p style="line-height: normal;">public static void main(String[] args) {<br style="line-height: normal;" />&nbsp;&nbsp; TxtThread tt = new TxtThread();<br style="line-height: normal;" />&nbsp;&nbsp; new Thread(tt).start();<br style="line-height: normal;" />&nbsp;&nbsp; new Thread(tt).start();<br style="line-height: normal;" />&nbsp;&nbsp; new Thread(tt).start();<br style="line-height: normal;" />&nbsp;&nbsp; new Thread(tt).start();<br style="line-height: normal;" />}<br style="line-height: normal;" />}</p><br /><p style="line-height: normal;">class TxtThread implements Runnable {<br style="line-height: normal;" />int num = 100;<br style="line-height: normal;" />String <br />str = new String();</p><br /><p style="line-height: normal;">public void run() {<br style="line-height: normal;" />&nbsp;&nbsp; synchronized (str) {<br style="line-height: normal;" />&nbsp;&nbsp;&nbsp; while (num &gt; 0) {</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp; try {<br style="line-height: normal;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />Thread.sleep(1);<br style="line-height: normal;" />&nbsp;&nbsp;&nbsp;&nbsp; } catch (Exception e) {<br style="line-height: normal;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.getMessage();<br style="line-height: normal;" />&nbsp;&nbsp;&nbsp;&nbsp; }<br style="line-height: normal;" />&nbsp;&nbsp;&nbsp;&nbsp; <br />System.out.println(Thread.currentThread().getName()<br style="line-height: normal;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + "this is " + num--);<br style="line-height: normal;" />&nbsp;&nbsp;&nbsp; }<br style="line-height: normal;" />&nbsp;&nbsp; }<br style="line-height: normal;" />}<br style="line-height: normal;" />}</p><br /><p style="line-height: normal;">上面的例子中为了制造一个时间差,也就是出错的机会,使用了Thread.sleep(10)</p><br /><p style="line-height: normal;">Java对多线程的支持与同步机制深受大家的喜爱，似乎看起来使用了synchronized关键字就可以轻松地解决多线程共享数据同步问题。到底如</p><br /><p style="line-height: normal;">何？&#8213;&#8213;还得对synchronized关键字的作用进行深入了解才可定论。</p><br /><p style="line-height: normal;">总的说来，synchronized关键字可以作为函数的修饰符，也可作为函数内的语句，也就是平时说的同步方法和同步语句块。如果再细的分类，</p><br /><p style="line-height: normal;">synchronized可作用于instance变量、object <br />reference（对象引用）、static函数和class literals(类名称字面常量)身上。</p><br /><p style="line-height: normal;">在进一步阐述之前，我们需要明确几点：</p><br /><p style="line-height: normal;">A．无论synchronized关键字加在方法上还是对象上，它取得的锁都是对象，而不是把一段代码或函数当作锁&#8213;&#8213;而且同步方法很可能还会被其</p><br /><p style="line-height: normal;">他线程的对象访问。</p><br /><p style="line-height: normal;">B．每个对象只有一个锁（lock）与之相关联。</p><br /><p style="line-height: normal;">C．实现同步是要很大的系统开销作为代价的，甚至可能造成死锁，所以尽量避免无谓的同步控制。</p><br /><p style="line-height: normal;">接着来讨论synchronized用到不同地方对代码产生的影响：</p><br /><p style="line-height: normal;">假设P1、P2是同一个类的不同对象，这个类中定义了以下几种情况的同步块或同步方法，P1、P2就都可以调用它们。</p><br /><p style="line-height: normal;">1． 把synchronized当作函数修饰符时，示例代码如下：</p><br /><p style="line-height: normal;">Public synchronized void methodAAA()</p><br /><p style="line-height: normal;">{</p><br /><p style="line-height: normal;">//&#8230;.</p><br /><p style="line-height: normal;">}</p><br /><p style="line-height: normal;">这也就是同步方法，那这时synchronized锁定的是哪个对象呢？它锁定的是调用这个同步方法对象。也就是说，当一个对象P1在不同的线程中</p><br /><p style="line-height: normal;">执行这个同步方法时，它们之间会形成互斥，达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了</p><br /><p style="line-height: normal;">synchronized关键字的方法。</p><br /><p style="line-height: normal;">上边的示例代码等同于如下代码：</p><br /><p style="line-height: normal;">public void methodAAA()</p><br /><p style="line-height: normal;">{</p><br /><p style="line-height: normal;">synchronized (this)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // (1)</p><br /><p style="line-height: normal;">{</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&#8230;..</p><br /><p style="line-height: normal;">}</p><br /><p style="line-height: normal;">}</p><br /><p style="line-height: normal;">(1)处的this指的是什么呢？它指的就是调用这个方法的对象，如P1。可见同步方法实质是将synchronized作用于object <br />reference。&#8213;&#8213;那个</p><br /><p style="line-height: normal;">拿到了P1对象锁的线程，才可以调用P1的同步方法，而对P2而言，P1这个锁与它毫不相干，程序也可能在这种情形下摆脱同步机制的控制，造</p><br /><p style="line-height: normal;">成数据混乱：（</p><br /><p style="line-height: normal;">2．同步块，示例代码如下：</p><br /><p style="line-height: normal;">public void method3(SomeObject so)</p><br /><p style="line-height: normal;">{</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp; synchronized(so)</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp; {<br style="line-height: normal;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />//&#8230;..<br style="line-height: normal;" />&nbsp;&nbsp;&nbsp; }</p><br /><p style="line-height: normal;">}</p><br /><p style="line-height: normal;">这时，锁就是so这个对象，谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时，就可以这样写程序，但当没有明</p><br /><p style="line-height: normal;">确的对象作为锁，只是想让一段代码同步时，可以创建一个特殊的instance变量（它得是一个对象）来充当锁：</p><br /><p style="line-height: normal;">class Foo implements Runnable</p><br /><p style="line-height: normal;">{</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private byte[] lock = new byte[0]; // <br />特殊的instance变量</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Public void methodA()<br style="line-height: normal;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(lock) { //&#8230; }</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&#8230;..</p><br /><p style="line-height: normal;">}</p><br /><p style="line-height: normal;">注：零长度的byte数组对象创建起来将比任何对象都经济&#8213;&#8213;查看编译后的字节码：生成零长度的byte[]对象只需3条操作码，而Object <br />lock</p><br /><p style="line-height: normal;">= new Object()则需要7行操作码。</p><br /><p style="line-height: normal;">3．将synchronized作用于static 函数，示例代码如下：</p><br /><p style="line-height: normal;">Class Foo<br style="line-height: normal;" />{</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp; public synchronized static void methodAAA()&nbsp;&nbsp; <br />// 同步的static 函数<br style="line-height: normal;" />&nbsp;&nbsp;&nbsp; {<br style="line-height: normal;" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&#8230;.<br style="line-height: normal;" />&nbsp;&nbsp;&nbsp; <br />}</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp; public void methodBBB()<br style="line-height: normal;" />&nbsp;&nbsp;&nbsp; {</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized(Foo.class)&nbsp;&nbsp; // class <br />literal(类名称字面常量)</p><br /><p style="line-height: normal;">&nbsp;&nbsp;&nbsp; }<br style="line-height: normal;" />}</p><br /><p style="line-height: normal;">&nbsp;&nbsp; 代码中的methodBBB()方法是把class <br />literal作为锁的情况，它和同步的static函数产生的效果是一样的，取得的锁很特别，是当前调用这</p><br /><p style="line-height: normal;">个方法的对象所属的类（Class，而不再是由这个Class产生的某个具体对象了）。</p><br /><p style="line-height: normal;">记得在《Effective Java》一书中看到过将 Foo.class和 <br />P1.getClass()用于作同步锁还不一样，不能用P1.getClass()来达到锁这个Class的</p><br /><p style="line-height: normal;">目的。P1指的是由Foo类产生的对象。</p><br /><p style="line-height: normal;">可以推断：如果一个类中定义了一个synchronized的static函数A，也定义了一个synchronized <br />的instance函数B，那么这个类的同一对象Obj</p><br /><p style="line-height: normal;">在多线程中分别访问A和B两个方法时，不会构成同步，因为它们的锁都不一样。A方法的锁是Obj这个对象，而B的锁是Obj所属的那个Class。</p><br /><p style="line-height: normal;">小结如下：</p><br /><p style="line-height: normal;">搞清楚synchronized锁定的是哪个对象，就能帮助我们设计更安全的多线程程序。</p><br /><p style="line-height: normal;">还有一些技巧可以让我们对共享资源的同步访问更加安全：</p><br /><p style="line-height: normal;">1． 定义private 的instance变量+它的 <br />get方法，而不要定义public/protected的instance变量。如果将变量定义为public，对象在外界可以</p><br /><p style="line-height: normal;">绕过同步方法的控制而直接取得它，并改动它。这也是JavaBean的标准实现方式之一。</p><br /><p style="line-height: normal;">2． <br />如果instance变量是一个对象，如数组或ArrayList什么的，那上述方法仍然不安全，因为当外界对象通过get方法拿到这个instance对象</p><br /><p style="line-height: normal;">的引用后，又将其指向另一个对象，那么这个private变量也就变了，岂不是很危险。 <br />这个时候就需要将get方法也加上synchronized同步，并</p><br /><p style="line-height: normal;">且，只返回这个private对象的clone()&#8213;&#8213;这样，调用端得到的就是对象副本的引用了</p></div></td></tr></tbody></table></span></div><img src ="http://www.blogjava.net/lyjjq/aggbug/381415.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2012-06-25 12:06 <a href="http://www.blogjava.net/lyjjq/articles/381415.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最近在使用MyEclipse的SVN插件时总是弹出一个大大的对话框，报一个Failed to load JavaHL Library.错误</title><link>http://www.blogjava.net/lyjjq/articles/361321.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Fri, 14 Oct 2011 15:04:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/361321.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/361321.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/361321.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/361321.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/361321.html</trackback:ping><description><![CDATA[<div class="article_content">
<div class="article_content">
<p>最近在使用MyEclipse的SVN插件时总是弹出一个大大的对话框，报一个Failed to load JavaHL Library.错误</p>
<div class="dp-highlighter bg_java">
<div class="bar">
<div class="tools"><a class="ViewSource" title="view plain" href="http://blog.csdn.net/holly_puck/article/details/6690216#"><u><font color="#0066cc">view plain</font></u></a></div></div>
<ol class="dp-j"><li class="alt"><span>Failed&nbsp;to&nbsp;load&nbsp;JavaHL&nbsp;Library.&nbsp;&nbsp;</span></li><li><span>These&nbsp;are&nbsp;the&nbsp;errors&nbsp;that&nbsp;were&nbsp;encountered:&nbsp;&nbsp;</span></li><li class="alt"><span>D:\Genuitec\Common\plugins\org.tigris.subversion.clientadapter.javahl.win32_1.<span class="number">6.17</span><span>\ssleay32.dll:&nbsp;操作系统无法运行&nbsp;%</span><span class="number">1</span><span>。&nbsp;&nbsp;</span></span></li><li><span>D:\Genuitec\Common\plugins\org.tigris.subversion.clientadapter.javahl.win32_1.<span class="number">6.17</span><span>\libsvn_subr-</span><span class="number">1</span><span>.dll:&nbsp;找不到指定的程序。&nbsp;&nbsp;</span></span></li><li class="alt"><span>D:\Genuitec\Common\plugins\org.tigris.subversion.clientadapter.javahl.win32_1.<span class="number">6.17</span><span>\libsvn_delta-</span><span class="number">1</span><span>.dll:&nbsp;找不到指定的程序。&nbsp;&nbsp;</span></span></li><li><span>D:\Genuitec\Common\plugins\org.tigris.subversion.clientadapter.javahl.win32_1.<span class="number">6.17</span><span>\libsvn_diff-</span><span class="number">1</span><span>.dll:&nbsp;找不到指定的程序。&nbsp;&nbsp;</span></span></li><li class="alt"><span>D:\Genuitec\Common\plugins\org.tigris.subversion.clientadapter.javahl.win32_1.<span class="number">6.17</span><span>\libsvn_wc-</span><span class="number">1</span><span>.dll:&nbsp;找不到指定的程序。&nbsp;&nbsp;</span></span></li><li><span>D:\Genuitec\Common\plugins\org.tigris.subversion.clientadapter.javahl.win32_1.<span class="number">6.17</span><span>\libsvn_fs-</span><span class="number">1</span><span>.dll:&nbsp;找不到指定的程序。&nbsp;&nbsp;</span></span></li><li class="alt"><span>D:\Genuitec\Common\plugins\org.tigris.subversion.clientadapter.javahl.win32_1.<span class="number">6.17</span><span>\libsvn_repos-</span><span class="number">1</span><span>.dll:&nbsp;找不到指定的程序。&nbsp;&nbsp;</span></span></li><li><span>D:\Genuitec\Common\plugins\org.tigris.subversion.clientadapter.javahl.win32_1.<span class="number">6.17</span><span>\libsvn_ra-</span><span class="number">1</span><span>.dll:&nbsp;找不到指定的程序。&nbsp;&nbsp;</span></span></li><li class="alt"><span>D:\Genuitec\Common\plugins\org.tigris.subversion.clientadapter.javahl.win32_1.<span class="number">6.17</span><span>\libsvn_client-</span><span class="number">1</span><span>.dll:&nbsp;找不到指定的程序。&nbsp;&nbsp;</span></span></li><li><span>D:\Genuitec\Common\plugins\org.tigris.subversion.clientadapter.javahl.win32_1.<span class="number">6.17</span><span>\libsvnjavahl-</span><span class="number">1</span><span>.dll:&nbsp;找不到指定的程序。&nbsp;&nbsp;</span></span></li><li class="alt"><span>no&nbsp;svnjavahl-<span class="number">1</span><span>&nbsp;in&nbsp;java.library.path&nbsp;&nbsp;</span></span></li><li><span>no&nbsp;svnjavahl&nbsp;in&nbsp;java.library.path&nbsp;&nbsp;</span></li><li class="alt"><span>java.library.path&nbsp;=&nbsp;D:\Genuitec\MyEclipse&nbsp;<span class="number">7.5</span><span>;.;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;D:/Genuitec/Common/binary/com.sun.java.jdk.win32.x86_1.</span><span class="number">6.0</span><span>.</span><span class="number">013</span><span>/jre/bin/client;D:/Genuitec/Common/binary/com.sun.java.jdk.win32.x86_1.</span><span class="number">6.0</span><span>.</span><span class="number">013</span><span>/jre/bin;D:\Tomcat5\bin;F:\Java\jdk1.</span><span class="number">5</span><span>\bin;D:\apache-ant-</span><span class="number">1.8</span><span>.</span><span class="number">1</span><span>\bin;F:\Java\jdk1.</span><span class="number">5</span><span>\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program&nbsp;Files\Common&nbsp;Files\Thunder&nbsp;Network\KanKan\Codecs;D:\Server\MySql\bin;D:\Program&nbsp;Files\TortoiseSVN\bin&nbsp;&nbsp;</span></span></li></ol></div>
<p>虽然不是很影响正常使用，但是当你编着编着代码就偶尔弹出这么个大框来着实不爽。</p>
<p>于是在网络上找了答案，按照其中一种方法操作，果然不再报错。</p>
<p>其法为：</p>
<p>1.windows-&gt;preferences-&gt;Team-&gt;SVN-&gt;SVN接口</p>
<p>2.选择SVNKit (Pure Java) xxxxxx</p>
<p>如下图所示</p>
<p><img alt="" src="http://hi.csdn.net/attachment/201108/15/0_13134225113DKU.gif" /></p>
<p>重启之后不再报错。</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>另外附上其他解决办法（未经测试，不知正确与否）：</p>
<p>安装好Eclipse以后</p>
<p>&nbsp;进入菜单Help-&gt;Install new Software...-&gt;add... 地址选择，如果安装的Eclipse版本是3.2以上</p>
<p>&nbsp;恐怕没人装旧版的了，那么使用如下地址 http://subclipse.tigris.org/update_1.6.x 具体版本信息参看http://subclipse.tigris.org中的Download and Install页面</p>
<p>&nbsp;然后点确定</p>
<p>&nbsp;全选</p>
<p>&nbsp;安装</p>
<p>&nbsp;重启Eclipse. 在SVN资源库研究中新加源</p>
<p>&nbsp;可以用以下地址测试 svn://www.svnhost.cn/test 加好后点击展开 就可以看到里面的内容</p>
<p>&nbsp;如果不成功</p>
<p>&nbsp;1.打开eclipse.ini文件，结尾添加一行 -Djava.library.path=/usr/lib/jni 然后重启Eclipse </p>
<p>&nbsp;2.或者在Windows-&gt;Team-&gt;SVN中选择SVN接口为SVNkit... 保存退出</p>
<p>&nbsp;之前无法连接到源，改接口也不成功，报Incompatible JavaHL library loaded错误。</p>
<p>&nbsp;其实是subclipse版本不对。卸载掉重装新版本即可。</p>
<p>&nbsp;卸载在Help-&gt;About Eclipse-&gt;Installation Details中选择。<br /></p>
<p>可能遇到得问题：ubuntu eclipse 安装subclipse插件遇到的javaHL问题 </p>
<p>subclipse 安装windows版本的eclipse时会把所有依赖的文件全部自动安装，但换到ubuntu就不行了。 </p>
<p>应为linux的版本太多了它不可能为每个版本都写一份程序。所以只能自己动手了 </p>
<p>第一步 现象</p>
<p>点选eclipse的 Window-&gt;Preferences-&gt;Team-&gt;SVN" preferences: 时就会出现下面的错误 </p>
<p>Failed to load JavaHL Library. </p>
<p>These are the errors that were encountered:</p>
<p>no libsvnjavahl-1 in java.library.path </p>
<p>no svnjavahl-1 in java.library.path </p>
<p>no svnjavahl in java.library.path </p>
<p>java.library.path = /usr/lib/jvm/java-6-sun-1.6.0.03/jre/lib/i386/client::/ usr/lib/jvm/java-6-sun-1.6.0.03/jre/lib/i386::/usr/lib/firefox:/usr/lib/ firefox/:/usr/java/packages/lib/i386:/lib:/usr/lib</p>
<p>第二步 安装</p>
<p>javahl sudo apt-get install libsvn-java eclipse目录下的eclipse.ini添加 -Djava.library.path=/usr/lib/jni 做完这些后再次启动eclipse 问题迎刃而解.</p></div></div>
<div id="sharePanel" class="share_buttons"><span>分享到：</span> <a class="share_sina" title="分享到新浪微博" name="sina" jquery1318604461713="2"></a><a class="share_qq" title="分享到腾讯微博" name="qq" jquery1318604461713="3"></a></div>
<div class="article_next_prev"></li><li class="prev_article"><span>上一篇：</span><a href="http://blog.csdn.net/jiangfangyuan/article/details/6801973">日期 时间 货币 格式化</a></li><li class="next_article"><span>下一篇：</span><a href="http://blog.csdn.net/jiangfangyuan/article/details/6865121">sell</a></li></div><img src ="http://www.blogjava.net/lyjjq/aggbug/361321.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2011-10-14 23:04 <a href="http://www.blogjava.net/lyjjq/articles/361321.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>List Set Map 数组之间转换 </title><link>http://www.blogjava.net/lyjjq/articles/360295.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Sun, 09 Oct 2011 09:19:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/360295.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/360295.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/360295.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/360295.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/360295.html</trackback:ping><description><![CDATA[1.list转化成数组<br /><br />List&lt;String&gt; strlist = new ArrayList&lt;String&gt;();<br />String[] array=(String[]) strlist.toArray(new String[strlist.size()]);<br /><br />2.set转化成list<br /><br />Set BoardSet=new HashSet&lt;Board&gt;();<br />this.boardList = new ArrayList&lt;Board&gt;(BoardSet);<br /><br />3.list转化成set<br /><br />List list = new ArrayList(new Hashset()); <br />Set set = new HashSet(list); <br />--------------------------------------------------------------- <br /><br /><br />List list = Arrays.asList(array); //数组转化成list<br /><br />list = new LinkedList(Arrays.asList(array)); <br /><br />Set set = new HashSet(Arrays.asList(array)); <br /><br />4.将map转化成数组<br /><br />Map parent = new HashMap&lt;String, String&gt;();<br /><br />Set set = parent.entrySet();<img src ="http://www.blogjava.net/lyjjq/aggbug/360295.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2011-10-09 17:19 <a href="http://www.blogjava.net/lyjjq/articles/360295.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AES加密是key的字节数</title><link>http://www.blogjava.net/lyjjq/articles/355086.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Tue, 26 Jul 2011 13:56:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/355086.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/355086.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/355086.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/355086.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/355086.html</trackback:ping><description><![CDATA[<p>Exception in thread "main" java.security.InvalidKeyException: Invalid AES key length: 6 bytes <br />at com.sun.crypto.provider.AESCipher.engineGetKeySize(DashoA13*..) <br />at javax.crypto.Cipher.b(DashoA13*..) <br />at javax.crypto.Cipher.a(DashoA13*..) <br />at javax.crypto.Cipher.a(DashoA13*..) <br />at javax.crypto.Cipher.a(DashoA13*..) <br />at javax.crypto.Cipher.init(DashoA13*..) <br />at javax.crypto.Cipher.init(DashoA13*..) <br />at AES.main(AES.java:48) </p>
<p>The problem is surely with the length of the key, I have tried different length but I am getting the same, could you please tell me the length of the key please, I am new to cryptography, I have made some research but still can't figure out the problem. Thanks a lot for your answers. </p>
<p>&nbsp;<br />AES supports 128, 192 and 256 bit keys, so the number of bytes needs to be 16, 24, or 32. Note that the latter two may not be available in all circumstances (as the comment in the "kgen.init(128)" line mentions).&nbsp; <br /></p><img src ="http://www.blogjava.net/lyjjq/aggbug/355086.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2011-07-26 21:56 <a href="http://www.blogjava.net/lyjjq/articles/355086.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java定时器的使用（Timer） </title><link>http://www.blogjava.net/lyjjq/articles/351889.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Tue, 07 Jun 2011 15:39:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/351889.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/351889.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/351889.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/351889.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/351889.html</trackback:ping><description><![CDATA[<div id="cnblogs_post_body">
<div style="color: #993300">1、在应用开发中，经常需要一些周期性的操作，比如每5分钟执行某一操作等。对于这样的操作最方便、高效的实现方式就是使用java.util.Timer工具类。 
<p style="color: #993300">private java.util.Timer timer; <br />timer = new Timer(true); <br />timer.schedule(<br />new java.util.TimerTask() { public void run() { //server.checkNewMail();&nbsp;要操作的方法 } }, 0, 5*60*1000);&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;第一个参数是要操作的方法，第二个参数是要设定延迟的时间，第三个参数是周期的设定，每隔多长时间执行该操作。</p>
<p style="color: #993300">&nbsp;&nbsp;&nbsp; 使用这几行代码之后，Timer本身会每隔5分钟调用一遍server.checkNewMail()方法，不需要自己启动线程。Timer本身也是多线程同步的，多个线程可以共用一个Timer，不需要外部的同步代码。 </p></div>
<div style="color: #993300"></div>
<div style="color: #993300">2、<br />(1)Timer.schedule(TimerTask task,Date time)安排在制定的时间执行指定的任务。<br />(2)Timer.schedule(TimerTask task,Date firstTime ,long period)安排指定的任务在指定的时间开始进行重复的固定延迟执行．<br />(3)Timer.schedule(TimerTask task,long delay)安排在指定延迟后执行指定的任务．<br />(4)Timer.schedule(TimerTask task,long delay,long period)安排指定的任务从指定的延迟后开始进行重复的固定延迟执行．<br />(5)Timer.scheduleAtFixedRate(TimerTask task,Date firstTime,long period)安排指定的任务在指定的时间开始进行重复的固定速率执行．<br />(6)Timer.scheduleAtFixedRate(TimerTask task,long delay,long period)安排指定的任务在指定的延迟后开始进行重复的固定速率执行．</div></div><img src ="http://www.blogjava.net/lyjjq/aggbug/351889.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2011-06-07 23:39 <a href="http://www.blogjava.net/lyjjq/articles/351889.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>重新总结struts标签嵌套错误</title><link>http://www.blogjava.net/lyjjq/articles/351342.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Mon, 30 May 2011 07:33:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/351342.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/351342.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/351342.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/351342.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/351342.html</trackback:ping><description><![CDATA[<div id="blog_text" class="cnt">
<p>首先，上一篇中转的html:select标签的示例二中的嵌套是错误的。</p>
<div>
<div>其實struts標簽是不能夠嵌套的；</div>
<div><font color="#ff6600">例一</font>：&lt;logic:iterate id="cl" name="Ids"&gt; //循环取得id&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //比较beanname中的id是否和cl中的id相同，如果相同就显示cl中的name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;logic:equal name="beanname" property="id" <font color="#ff0000">value="&lt;bean:write name="cl" property="id"/&gt;"<font color="#000000">&gt;&nbsp;&nbsp;</font>&nbsp;&nbsp;&nbsp;&nbsp;</font><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean:write name="cl" property="name"/&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/logic:equal&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/logic:iterate&gt;&nbsp;&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 紅色文字區就是錯誤的嵌套了，這樣是得不到想要的結果的，可改爲</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;logic:iterate id="cl" name="Ids"&gt; //循环取得id <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean:define id="temId" name="cl" property="id" type="java.lang.String"/&gt; </div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //比较beanname中的id是否和cl中的id相同，如果相同就显示cl中的name<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;logic:equal name="beanname" property="id" value="&lt;%=temId%&gt;"&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean:write name="cl" property="name"/&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/logic:equal&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/logic:iterate&gt;&nbsp;&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 這樣先定義，后使用，就ok了。</div>
<div><font color="#ff6600">例二</font>：&lt;html:submit value="&lt;bean:message key="welcome.login" bundle="base"/&gt;"/&gt;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 應該為</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;html:submit&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean:message key = "welcome.logon" bundle = "base"/&gt; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/html:submit&gt;</div></div>
<p>&nbsp;&nbsp;&nbsp;</p>
<p>刚开始使用struts标签时，很痛苦，三个人窝在实验室里把struts骂了个遍，但用还是得用，而且强制用，必须学会。我因为之前用的是webwork，所以老是拿两个做对比，不过现在好了，struts2出来啦！！<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struts标签的用法网上很多，这里也就不说了，要说的是在这次运用struts标签过程中的一些问题和经验。<br />&nbsp;&nbsp;&nbsp; 1、<font color="#993300"><strong>页面action嵌套，</strong><font color="#000000">因为是分工合作，三个人分别完成各自模块，最后进行组装。所以避免不了，一个页面会有多个action组成。那么怎么运用struts标签进行action组装呢？<br /><font color="#000000"><strong>&lt;bean:include id="<font color="#993300">liststeptype</font>" page="/step/steptype.html?event=listStepType" /&gt;<br />&lt;bean:write name="<font color="#993300">liststeptype</font>" filter="<font color="#ff0000">false</font>"/&gt;<br /></strong>&nbsp;&nbsp;&nbsp; 先利用include创建一个id为liststeptype的模块，page的值为指定action的url，再通过write将其显示出来，filter如果为ture则显示页面源码，为false显示html页面。</font></font></font>&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; 2、<font color="#993300"><strong>Date型数据的页面显示</strong></font>，理想状态是显示为&#8220;YYYY-mm-DD&#8221;，如果是formbean中的属性还好办一点，直接在进行数据类型转换的时候就 把样式给format了，但是如果是对象列表呢，通过循环标签显示，没法利用struts标签调用format函数（struts标签不支持此功能），对 此想个多个方案，最高的一个是重写Date的toString方法，最简单的是利用<font color="#993300"><strong>bean:write</strong></font> 中的<strong><font color="#993300">format</font></strong>的属性（这是郁闷了很久后无意中发现的）。<br />&nbsp;&nbsp;&nbsp; 3、<font color="#993300"><strong>formbean</strong></font>中不能接收Object类型的属性，这点着实郁闷了很久，所以遇到需要用到Object类型的数据时只能再手动转换。<br />&nbsp;&nbsp;&nbsp; 4、<font color="#993300"><strong>复选框的运用</strong></font>。struts标签中，到系统完成都没能很好运用的便是复选框，所以每次遇到需要用到复选框就直接使用jsp标签替代了，简单快速。<br />&nbsp;&nbsp;&nbsp; 5、<font color="#993300"><strong>struts标签不能嵌套。</strong><font color="#000000">struts标签中的html标签，一般来说value值为与property同名的formbean中的属性值，当然value的值也能指定，但却不能动态获取，比如要想property1的value等于formbean中property2的值</font></font>。对此讨论除了两个方案，使用jsp标签或者EL表达式（即<font color="#993300">${<font color="#000000">property2</font>}</font>）。<br />&nbsp;&nbsp; 6、<font color="#993300"><strong>下拉框的运用</strong></font>。<br />&lt;html:select property="mnEquipmentId"&gt;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;html:option value="0"&gt;------请选择------&lt;/html:option&gt;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;<font color="#993300"><strong>html:optionsCollection</strong></font> property="equipmentList" label="name" value="id"/&gt; <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; <font color="#993300">或</font>&lt;<font color="#993300"><strong>html:options </strong><font color="#000000">collection</font></font>="equipmentList" labelProperty="name" property="id" /&gt; <br />&lt;/html:select&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 把结果存入一个ArrayList作为 <font color="#993300">request </font>的一个属性传到页面上， 这时一般用 &lt;html:options .../&gt; 标签；如果数据放到 <font color="#993300">formbean</font>里，作为属性在页面上取，这时一般用 &lt;html:optionsCollection ... /&gt;</p></div><br /><img src ="http://www.blogjava.net/lyjjq/aggbug/351342.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2011-05-30 15:33 <a href="http://www.blogjava.net/lyjjq/articles/351342.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最后一个奇数汉字出现乱码解决方案</title><link>http://www.blogjava.net/lyjjq/articles/328073.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Thu, 05 Aug 2010 13:57:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/328073.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/328073.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/328073.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/328073.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/328073.html</trackback:ping><description><![CDATA[<div class="blog_content">1.统一用UTF-8编码，即Tomcat的server.xml、页面、过滤器都用UTF-8 <br />
2. <br />
请求参数,需要编码 <br />
<br />
&lt;a href="newsAction?name=&lt;%=java.net.URLEncoder.encode("表数据管理","UTF-8")%&gt;" <br />
target="frameset"&gt;Xls表数据管理 &lt;/a&gt; <br />
<br />
假如是java代码的话直接写java.net.URLEncoder.encode("测试吗","UTF-8"); <br />
<br />
下面引用Qieqie的一段代码： <br />
<br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" onclick="dp.sh.Toolbar.CopyToClipboard(this);return false;" href="http://huangdonghui.javaeye.com/blog/587651#"><img alt="复制代码" src="http://huangdonghui.javaeye.com/images/icon_copy.gif" /></a></div>
</div>
<ol class="dp-j">
    <li><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;main(String[]&nbsp;args)&nbsp;</span><span class="keyword">throws</span><span>&nbsp;UnsupportedEncodingException&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//给定某3个汉字 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;src&nbsp;=&nbsp;</span><span class="string">"你好啊"</span><span>; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//String&nbsp;src&nbsp;=&nbsp;"一二三"; </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//浏览器进行utf-8编码，并传送到服务器 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">byte</span><span>[]&nbsp;bytes1&nbsp;=&nbsp;src.getBytes(</span><span class="string">"utf-8"</span><span>); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(bytes1.length);</span><span class="comment">//9 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//tomcat以gbk方式解码(这个片段的说明仅针对gbk处理汉字的情况) </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//如果一对汉字字节不符合gbk编码规范，则每个字节使用'?'(ascii&nbsp;63)代替 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//万幸的话，只是最后一个(第9个)字节因不能成对,变成问号(比如当src="你好啊"时) </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//不幸的话，中间某些字节就通不过gbk编码规范出现'?'了(比如当src="一二三"时) </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//总之temp的最后一位必定是问号'?' </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;temp&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;String(bytes1,&nbsp;</span><span class="string">"gbk"</span><span>);&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//你的action中的代码 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//由于以上的tomcat以gbk解释utf-8不能成功 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//所以此时bytes2和bytes1不一样 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">byte</span><span>[]&nbsp;bytes2&nbsp;=&nbsp;temp.getBytes(</span><span class="string">"gbk"</span><span>); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(bytes2.length); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">int</span><span>&nbsp;i&nbsp;=&nbsp;</span><span class="number">0</span><span>;&nbsp;i&nbsp;&lt;&nbsp;bytes1.length;&nbsp;i++)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.print(bytes1[i]&nbsp;&amp;&nbsp;</span><span class="number">0xff</span><span>); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.print(</span><span class="string">"\t"</span><span>); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">int</span><span>&nbsp;i&nbsp;=&nbsp;</span><span class="number">0</span><span>;&nbsp;i&nbsp;&lt;&nbsp;bytes2.length;&nbsp;i++)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.print(bytes2[i]&nbsp;&amp;&nbsp;</span><span class="number">0xff</span><span>); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.print(</span><span class="string">"\t"</span><span>); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//构建出来的dest自然不是原先的src </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;dest&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;String(bytes2,&nbsp;</span><span class="string">"utf-8"</span><span>); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(dest); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
</div>
<img src ="http://www.blogjava.net/lyjjq/aggbug/328073.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2010-08-05 21:57 <a href="http://www.blogjava.net/lyjjq/articles/328073.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>将收集的正则表达式归纳。以后持续跟进。</title><link>http://www.blogjava.net/lyjjq/articles/304069.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Sat, 28 Nov 2009 17:32:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/304069.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/304069.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/304069.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/304069.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/304069.html</trackback:ping><description><![CDATA[<p><span style="font-size: 10pt">匹配中文字符的正则表达式： [\u4e00-\u9fa5]<br />
评注：匹配中文还真是个头疼的事，有了这个表达式就好办了</span></p>
<p><span style="font-size: 10pt">匹配双字节字符(包括汉字在内)：[^\x00-\xff]<br />
评注：可以用来计算字符串的长度（一个双字节字符长度计2，ASCII字符计1）</span></p>
<p><span style="font-size: 10pt">字符串中只能输入汉字："^[\u4e00-\u9fa5]{0,}$"</span></p>
<p><span style="font-size: 10pt">评注：可以对汉字串进行验证 </span></p>
<p><span style="font-size: 10pt">匹配空白行的正则表达式：\n\s*\r<br />
评注：可以用来删除空白行</span></p>
<p><span style="font-size: 10pt">匹配HTML标记的正则表达式：&lt; (\S*?)[^&gt;]*&gt;.*?|&lt; .*? /&gt;<br />
评注：网上流传的版本太糟糕，上面这个也仅仅能匹配部分，对于复杂的嵌套标记依旧无能为力</span></p>
<p><span style="font-size: 10pt">匹配首尾空白字符的正则表达式：^\s*|\s*$<br />
评注：可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等)，非常有用的表达式</span></p>
<p><span style="font-size: 10pt">匹配Email地址的正则表达式：\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*<br />
评注：表单验证时很实用</span></p>
<p><span style="font-size: 10pt">匹配网址URL的正则表达式：[a-zA-z]+://[^\s]*<br />
评注：网上流传的版本功能很有限，上面这个基本可以满足需求</span></p>
<p><span style="font-size: 10pt">匹配帐号是否合法(字母开头，允许5-16字节，允许字母数字下划线)：^[a-zA-Z][a-zA-Z0-9_]{4,15}$<br />
评注：表单验证时很实用</span></p>
<p><span style="font-size: 10pt">匹配国内电话号码：\d{3}-\d{8}|\d{4}-\d{7}<br />
评注：匹配形式如 0511-4405222 或 021-87888822</span></p>
<p><span style="font-size: 10pt">匹配腾讯QQ号：[1-9][0-9]{4,}<br />
评注：腾讯QQ号从10000开始</span></p>
<p><span style="font-size: 10pt">匹配中国邮政编码：[1-9]\d{5}(?!\d)<br />
评注：中国邮政编码为6位数字</span></p>
<p><span style="font-size: 10pt">匹配身份证：\d{15}|\d{18}<br />
评注：中国的身份证为15位或18位</span></p>
<p><span style="font-size: 10pt">匹配ip地址：\d+\.\d+\.\d+\.\d+<br />
评注：提取ip地址时有用</span></p>
<p><span style="font-size: 10pt"><span style="font-size: 10pt">匹配特定数字：<br />
</span></span><span style="font-size: 10pt">整数或者小数：^[0-9]+\.{0,1}[0-9]{0,2}$<br />
只能输入数字："^[0-9]*$"。<br />
只能输入n位的数字："^\d{n}$"。<br />
只能输入至少n位的数字："^\d{n,}$"。<br />
只能输入m~n位的数字：。"^\d{m,n}$"<br />
只能输入零和非零开头的数字："^(0|[1-9][0-9]*)$"。<br />
只能输入有两位小数的正实数："^[0-9]+(.[0-9]{2})?$"。<br />
只能输入有1~3位小数的正实数："^[0-9]+(.[0-9]{1,3})?$"。<br />
只能输入非零的正整数："^\+?[1-9][0-9]*$"。<br />
只能<span style="font-size: 10pt">输入非零的负整数："^\-[1-9][]0-9"*$。</span></span></p>
<p><span style="font-size: 10pt"><span style="font-size: 10pt"><span style="font-size: 10pt">只能输入非负整数(正整数+0):"^\d+$"　&nbsp;&nbsp;&nbsp;&nbsp; 或者&nbsp; ^[1-9]\d*|0$<br />
只能输入正整数："^[0-9]*[1-9][0-9]*$"&nbsp; 或者&nbsp; ^[1-9]\d*$<br />
</span>只能输入非正整数(负整数+0)："^((-\d+)|(0+))$"&nbsp; 或者&nbsp; ^-[1-9]\d*|0$<br />
只能输入负整数："^-[0-9]*[1-9][0-9]*$"&nbsp; 或者 ^-[1-9]\d*$<br />
只能输入整数："^-?\d+$"&nbsp;&nbsp;&nbsp; 或者 ^-?[1-9]\d*$</span></span></p>
<p><span style="font-size: 10pt"><span style="font-size: 10pt">只能输入非负浮点数(正浮点数+0)："^\d+(\.\d+)?$"&nbsp;&nbsp; 或者&nbsp; ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$<br />
只能输入正浮点数："^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$"&nbsp;&nbsp; 或者&nbsp; ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ </span></span></p>
<p><span style="font-size: 10pt"><span style="font-size: 10pt">只能输入非正浮点数(负浮点数+0)："^((-\d+(\.\d+)?)|(0+(\.0+)?))$"　&nbsp; 或者&nbsp; ^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ </span></span></p>
<p><span style="font-size: 10pt"><span style="font-size: 10pt">只能输入负浮点数："^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$" </span></span></p>
<p><span style="font-size: 10pt"><span style="font-size: 10pt">或者 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$<br />
只能输入浮点数："^(-?\d+)(\.\d+)?$"&nbsp; 或者&nbsp; ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$</span></span></p>
<p><span style="font-size: 10pt"><span style="font-size: 10pt">匹配特定字符串：<br />
</span>只能输入长度为3的字符："^.{3}$"。<br />
只能输入由26个英文字母组成的字符串："^[A-Za-z]+$"。<br />
只能输入由26个大写英文字母组成的字符串："^[A-Z]+$"。<br />
只能输入由26个小写英文字母组成的字符串："^[a-z]+$"。<br />
只能输入由数字和26个英文字母组成的字符串："^[A-Za-z0-9]+$"。</span></p>
<p><span style="font-size: 10pt">只能输入由数字、26个英文字母或者下划线组成的字符串："^\w+$"。</span></p>
<p><span style="font-size: 10pt"><br />
验证用户密码："^[a-zA-Z]\w{5,17}$"正确格式为：以字母开头，长度在6~18之间，只能包含字符、数字和下划线。<br />
验证是否含有^%&amp;',;=?$"等字符："[^%&amp;',;=?$\x22]+"。<br />
验证Email地址："^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"。<br />
验证InternetURL："^http://([\w-]+\.)+[\w-]+(/[\w-./?%&amp;=]*)?$"。<br />
验证电话号码："^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$"正确格式为："XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX"。<br />
验证身份证号（15位或18位数字）："^\d{15}|\d{18}$"。<br />
验证一年的12个月："^(0?[1-9]|1[0-2])$"正确格式为："01"～"09"和"1"～"12"。<br />
验证一个月的31天："^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为；"01"～"09"和"1"～"31"。</span></p>
<p><span style="font-size: 10pt"><br />
在asp.net中使用RegularExpressionValidator控件，可以将正则表达式和asp.net控件结合起来。</span></p>
<p>例子：如何检查当TextBox设置为多行时是不是超长了？<br />
&lt;asp:RegularExpressionValidator id="revTextBox1" runat="server" ForeColor="Red" Display="Dynamic" ControlToValidate="textBox1" ValidationExpression="(\w|\W){1,100}"&gt;格式错误-只能输入不超过100个字符&lt; /asp:RegularExpressionValidator&gt;</p>
<img src ="http://www.blogjava.net/lyjjq/aggbug/304069.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2009-11-29 01:32 <a href="http://www.blogjava.net/lyjjq/articles/304069.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于Java语言的内存泄漏</title><link>http://www.blogjava.net/lyjjq/articles/295151.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Tue, 15 Sep 2009 07:14:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/295151.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/295151.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/295151.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/295151.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/295151.html</trackback:ping><description><![CDATA[Java的一个重要优点就是通过垃圾收集器(Garbage Collection，GC)自动管理内存的回收，程序员不需要通过调用函数来释放内存。因此，很多程序员认为Java不存在内存泄漏问题，或者认为即使有内存泄漏也不是程序的责任，而是GC或JVM的问题。其实，这种想法是不正确的，因为Java也存在内存泄露，但它的表现与C++不同。<br />
　　随着越来越多的服务器程序采用Java技术，例如JSP，Servlet， EJB等，服务器程序往往长期运行。另外，在很多嵌入式系统中，内存的总量非常有限。内存泄露问题也就变得十分关键，即使每次运行少量泄漏，长期运行之后，系统也是面临崩溃的危险。<br />
　　<strong>一 Java是如何管理内存</strong><br />
　　为了判断Java中是否有内存泄露，我们首先必须了解Java是如何管理内存的。Java的内存管理就是对象的分配和释放问题。在Java中，程序员需要通过关键字new为每个对象申请内存空间 (基本类型除外)，所有的对象都在堆 (Heap)中分配空间。另外，对象的释放是由GC决定和执行的。在Java中，内存的分配是由程序完成的，而内存的释放是有GC完成的，这种收支两条线的方法确实简化了程序员的工作。但同时，它也加重了JVM的工作。这也是Java程序运行速度较慢的原因之一。因为，GC为了能够正确释放对象，GC必须监控每一个对象的运行状态，包括对象的申请、引用、被引用、赋值等，GC都需要进行监控。<br />
　　监视对象状态是为了更加准确地、及时地释放对象，而释放对象的根本原则就是该对象不再被引用。<br />
　　为了更好理解GC的工作原理，我们可以将对象考虑为有向图的顶点，将引用关系考虑为图的有向边，有向边从引用者指向被引对象。另外，每个线程对象可以作为一个图的起始顶点，例如大多程序从main进程开始执行，那么该图就是以main进程顶点开始的一棵根树。在这个有向图中，根顶点可达的对象都是有效对象，GC将不回收这些对象。如果某个对象 (连通子图)与这个根顶点不可达(注意，该图为有向图)，那么我们认为这个(这些)对象不再被引用，可以被GC回收。<br />
　　以下，我们举一个例子说明如何用有向图表示内存管理。对于程序的每一个时刻，我们都有一个有向图表示JVM的内存分配情况。以下右图，就是左边程序运行到第6行的示意图。<br />
　　Java使用有向图的方式进行内存管理，可以消除引用循环的问题，例如有三个对象，相互引用，只要它们和根进程不可达的，那么GC也是可以回收它们的。这种方式的优点是管理内存的精度很高，但是效率较低。另外一种常用的内存管理技术是使用计数器，例如COM模型采用计数器方式管理构件，它与有向图相比，精度行低(很难处理循环引用的问题)，但执行效率很高。<br />
<strong>　　二 什么是Java中的内存泄露</strong><br />
　　下面，我们就可以描述什么是内存泄漏。在Java中，内存泄漏就是存在一些被分配的对象，这些对象有下面两个特点，首先，这些对象是可达的，即在有向图中，存在通路可以与其相连;其次，这些对象是无用的，即程序以后不会再使用这些对象。如果对象满足这两个条件，这些对象就可以判定为Java中的内存泄漏，这些对象不会被GC所回收，然而它却占用内存。<br />
　　在C++中，内存泄漏的范围更大一些。有些对象被分配了内存空间，然后却不可达，由于C++中没有GC，这些内存将永远收不回来。在Java中，这些不可达的对象都由GC负责回收，因此程序员不需要考虑这部分的内存泄露。<br />
　　通过分析，我们得知，对于C++，程序员需要自己管理边和顶点，而对于Java程序员只需要管理边就可以了(不需要管理顶点的释放)。通过这种方式，Java提高了编程的效率。<br />
　　因此，通过以上分析，我们知道在Java中也有内存泄漏，但范围比C++要小一些。因为Java从语言上保证，任何对象都是可达的，所有的不可达对象都由GC管理。<br />
　　对于程序员来说，GC基本是透明的，不可见的。虽然，我们只有几个函数可以访问GC，例如运行GC的函数System.gc()，但是根据Java语言规范定义， 该函数不保证JVM的垃圾收集器一定会执行。因为，不同的JVM实现者可能使用不同的算法管理GC。通常，GC的线程的优先级别较低。JVM调用GC的策略也有很多种，有的是内存使用到达一定程度时，GC才开始工作，也有定时执行的，有的是平缓执行GC，有的是中式执行GC。但通常来说，我们不需要关心这些。除非在一些特定的场合，GC的执行影响应用程序的性能，例如对于基于Web的实时系统，如网络游戏等，用户不希望GC突然中断应用程序执行而进行垃圾回收，那么我们需要调整GC的参数，让GC能够通过平缓的方式释放内存，例如将垃圾回收分解为一系列的小步骤执行，Sun提供的HotSpot JVM就支持这一特性。<br />
　　下面给出了一个简单的内存泄露的例子。在这个例子中，我们循环申请Object对象，并将所申请的对象放入一个Vector中，如果我们仅仅释放引用本身，那么Vector仍然引用该对象，所以这个对象对GC来说是不可回收的。因此，如果对象加入到Vector后，还必须从Vector中删除，最简单的方法就是将Vector对象设置为null。<br />
Vector v=new Vector(10);<br />
　　for (int i=1;i&lt;100; i++)<br />
　　{<br />
　　Object o=new Object();<br />
　　v.add(o);<br />
　　o=null;<br />
　　}<br />
　　//此时，所有的Object对象都没有被释放，因为变量v引用这些对象。<br />
<strong>　　三 如何检测内存泄漏</strong><br />
　　最后一个重要的问题，就是如何检测Java的内存泄漏。Examda提示: 我们通常使用一些工具来检查Java程序的内存泄漏问题。市场上已有几种专业检查Java内存泄漏的工具，它们的基本工作原理大同小异，都是通过监测Java程序运行时，所有对象的申请、释放等动作，将内存管理的所有信息进行统计、分析、可视化。开发人员将根据这些信息判断程序是否有内存泄漏问题。这些工具包括Optimizeit Profiler，JProbe Profiler，JinSight , Rational 公司的Purify等。<br />
　　下面，我们将简单介绍Optimizeit的基本功能和工作原理。<br />
　　Optimizeit Profiler版本4.11支持Application，Applet，Servlet和Romote Application四类应用，并且可以支持大多数类型的JVM，包括SUN JDK系列，IBM的JDK系列，和Jbuilder的JVM等。并且，该软件是由Java编写，因此它支持多种操作系统。Optimizeit系列还包括Thread Debugger和Code Coverage两个工具，分别用于监测运行时的线程状态和代码覆盖面。<br />
　　当设置好所有的参数了，我们就可以在OptimizeIt环境下运行被测程序，在程序运行过程中，Optimizeit可以监视内存的使用曲线(如下图)，包括JVM申请的堆(heap)的大小，和实际使用的内存大小。另外，在运行过程中，我们可以随时暂停程序的运行，甚至强行调用GC，让GC进行内存回收。通过内存使用曲线，我们可以整体了解程序使用内存的情况。这种监测对于长期运行的应用程序非常有必要，也很容易发现内存泄露。<br />
　　在运行过程中，我们还可以从不同视角观查内存的使用情况，Examda提示: Optimizeit提供了四种方式：<br />
　　<strong>堆视角。</strong> 这是一个全面的视角，我们可以了解堆中的所有的对象信息(数量和种类)，并进行统计、排序，过滤。了解相关对象的变化情况。<br />
　　<strong>方法视角。</strong>通过方法视角，我们可以得知每一种类的对象，都分配在哪些方法中，以及它们的数量。<br />
　　<strong>对象视角。</strong>给定一个对象，通过对象视角，我们可以显示它的所有出引用和入引用对象，我们可以了解这个对象的所有引用关系。<br />
　　<strong>引用图。</strong> 给定一个根，通过引用图，我们可以显示从该顶点出发的所有出引用。<br />
　　在运行过程中，我们可以随时观察内存的使用情况，通过这种方式，我们可以很快找到那些长期不被释放，并且不再使用的对象。我们通过检查这些对象的生存周期，确认其是否为内存泄露。在实践当中，寻找内存泄露是一件非常麻烦的事情，它需要程序员对整个程序的代码比较清楚，并且需要丰富的调试经验，但是这个过程对于很多关键的Java程序都是十分重要的。<br />
　　综上所述，Java也存在内存泄露问题，其原因主要是一些对象虽然不再被使用，但它们仍然被引用。为了解决这些问题，我们可以通过软件工具来检查内存泄露，检查的主要原理就是暴露出所有堆中的对象，让程序员寻找那些无用但仍被引用的对象
<img src ="http://www.blogjava.net/lyjjq/aggbug/295151.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2009-09-15 15:14 <a href="http://www.blogjava.net/lyjjq/articles/295151.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring2.5+struts2</title><link>http://www.blogjava.net/lyjjq/articles/294904.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Sat, 12 Sep 2009 16:25:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/294904.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/294904.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/294904.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/294904.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/294904.html</trackback:ping><description><![CDATA[http://www.ibm.com/developerworks/cn/java/j-lo-spring25-ioc/ <br />
http://javeye.javaeye.com/blog/358744 <br />
http://blog.csdn.net/eastlift/archive/2008/05/20/2463243.aspx 
 <img src ="http://www.blogjava.net/lyjjq/aggbug/294904.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2009-09-13 00:25 <a href="http://www.blogjava.net/lyjjq/articles/294904.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ant 指定java编译器</title><link>http://www.blogjava.net/lyjjq/articles/292909.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Thu, 27 Aug 2009 14:36:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/292909.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/292909.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/292909.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/292909.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/292909.html</trackback:ping><description><![CDATA[&lt;javac srcdir="${src.dir}" destdir="${build.dir}" fork="true" executable="d:\j2sdk1.4.2_03\bin\javac" encoding="GBK" debug="true"&nbsp;deprecation="false" optimize="true" memorymaximumsize="256m" &gt;<br />
&nbsp;&nbsp;&nbsp;&lt;classpath refid="project.classpath" /&gt;<br />
&nbsp;&nbsp;&lt;/javac&gt;<br />
注意这里 debug="true" 打出的war或jar包中的class如果出异常时，将能定位到具体的行数
<img src ="http://www.blogjava.net/lyjjq/aggbug/292909.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2009-08-27 22:36 <a href="http://www.blogjava.net/lyjjq/articles/292909.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Jocky混淆JAVA代码</title><link>http://www.blogjava.net/lyjjq/articles/259704.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Sat, 14 Mar 2009 05:05:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/259704.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/259704.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/259704.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/259704.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/259704.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Jocky混淆JAVA代码（保护你的JAVA项目） 一、前言1.1 什么是Jocky?&nbsp;&nbsp;&nbsp;我们知道，Java是一种跨平台的编程语言，其源码(.java文件)被编译成与平台无关的字节码(.class文件)，然后在运行期动态链接。这样，编译后的类文件中将包含有符号表，从而使得Java程序很容易被反编译。相信每一个Java开发人员，都曾经用过诸如Jad之类的反...&nbsp;&nbsp;<a href='http://www.blogjava.net/lyjjq/articles/259704.html'>阅读全文</a><img src ="http://www.blogjava.net/lyjjq/aggbug/259704.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2009-03-14 13:05 <a href="http://www.blogjava.net/lyjjq/articles/259704.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在spring中利用axis工具配置webservice成功案例</title><link>http://www.blogjava.net/lyjjq/articles/256369.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Mon, 23 Feb 2009 16:32:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/256369.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/256369.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/256369.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/256369.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/256369.html</trackback:ping><description><![CDATA[<p>第一步：确认你用到的spring bean存在并且有效　比如　inviteService<br />
第二步：创建要发布的服务方法<br />
</p>
<p>/**<br />
&nbsp;* <br />
&nbsp;*/<br />
package com.chinamobile.survey.webservice;</p>
<p>import java.util.List;</p>
<p>import org.springframework.remoting.jaxrpc.ServletEndpointSupport;</p>
<p>import com.chinamobile.survey.entity.vo.ExamPlanContainer;<br />
import com.chinamobile.survey.invite.business.IInviteService;</p>
<p>/**<br />
&nbsp;* @author jianqiang.jiang<br />
&nbsp;* <br />
&nbsp;*/<br />
public class InviteEndPoint extends ServletEndpointSupport implements<br />
&nbsp;&nbsp;IInviteService {<br />
&nbsp;// 将真实的业务bean包装成WebService</p>
<p>&nbsp;private IInviteService inviteService;</p>
<p>&nbsp;// 该方法由Spring调用，将目标业务bean注入。</p>
<p>&nbsp;protected void onInit() {<br />
&nbsp;&nbsp;this.inviteService = (IInviteService) getWebApplicationContext()<br />
&nbsp;&nbsp;&nbsp;&nbsp;.getBean("inviteService");<br />
&nbsp;}</p>
<p>&nbsp;// 将业务bean的业务方法暴露成WebService<br />
&nbsp;public int getAllowAnswerExamPlanCount(long userId) throws Exception {<br />
&nbsp;&nbsp;return inviteService.getAllowAnswerExamPlanCount(userId);<br />
&nbsp;}</p>
<p>&nbsp;public ExamPlanContainer getAllowAnswerExamPlanContainer(long userId, long offset, long maxRow)<br />
&nbsp;&nbsp;&nbsp;throws Exception {<br />
&nbsp;&nbsp;return inviteService.getAllowAnswerExamPlanContainer(userId, offset, maxRow);<br />
&nbsp;}</p>
<p>&nbsp;}<br />
注意里面的 ServletEndpointSupport 和对bean的引用</p>
<p>第三步.编辑两个文件<br />
　　1.web.xml中<br />
　　增加<br />
&nbsp; &lt;!--&nbsp; 定义AxisServlet--&gt;<br />
&nbsp;&lt;servlet&gt;<br />
&nbsp;&nbsp;&lt;servlet-name&gt;AxisServlet&lt;/servlet-name&gt;<br />
&nbsp;&nbsp;&lt;servlet-class&gt;<br />
&nbsp;&nbsp;&nbsp;org.apache.axis.transport.http.AxisServlet<br />
&nbsp;&nbsp;&lt;/servlet-class&gt;<br />
&nbsp;&lt;/servlet&gt;<br />
&nbsp;&lt;!--&nbsp; 映射AxisServlet,使用通配符--&gt;<br />
&nbsp;&lt;servlet-mapping&gt;<br />
&nbsp;&nbsp;&lt;servlet-name&gt;AxisServlet&lt;/servlet-name&gt;<br />
&nbsp;&nbsp;&lt;url-pattern&gt;/services/*&lt;/url-pattern&gt;<br />
&nbsp;&lt;/servlet-mapping&gt;<br />
&nbsp;&nbsp;&nbsp; 2.生成server-config.wsdd,放在WEB-INF下<br />
　</p>
<p>&lt;deployment xmlns="http://xml.apache.org/axis/wsdd/"<br />
&nbsp;xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"&gt;<br />
&nbsp;&lt;handler name="URLMapper"<br />
&nbsp;&nbsp;type="java:org.apache.axis.handlers.http.URLMapper" /&gt;<br />
&nbsp;&lt;service name="ExamService" provider="java:RPC"&gt;<br />
&nbsp;&nbsp;&lt;parameter name="className"<br />
&nbsp;&nbsp;&nbsp;value="com.chinamobile.survey.webservice.InviteEndPoint" /&gt;<br />
&nbsp;&nbsp;&lt;parameter name="allowedMethods"<br />
&nbsp;&nbsp;&nbsp;value="getAllowAnswerExamPlanCount,getAllowAnswerExamPlanContainer" /&gt;<br />
&nbsp;&nbsp;&lt;parameter name="allowedRoles" value="user1,user2" /&gt;<br />
&nbsp;&lt;/service&gt;<br />
&nbsp;&lt;transport name="http"&gt;<br />
&nbsp;&nbsp;&lt;requestFlow&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;handler type="URLMapper" /&gt;<br />
&nbsp;&nbsp;&lt;/requestFlow&gt;<br />
&nbsp;&lt;/transport&gt;<br />
<span style="color: red">&nbsp;&lt;beanMapping qname="myNS:ExamPlanContainer"<br />
&nbsp;&nbsp;xmlns:myNS="urn:BeanService"<br />
&nbsp;&nbsp;languageSpecificType="java:com.chinamobile.survey.entity.vo.ExamPlanContainer" /&gt;<br />
&nbsp;&lt;beanMapping qname="myNS:WsExamPlan" xmlns:myNS="urn:BeanService"<br />
&nbsp;&nbsp;languageSpecificType="java:com.chinamobile.survey.entity.vo.WsExamPlan" /&gt;</span></p>
<p>&lt;/deployment&gt;<br />
</p>
<p>注意其中的&nbsp;返回类型注册，<br />
<br />
第四步.<br />
生成客户端测试代码：<br />
</p>
<p>package com.chinamobile.survey.webservice;</p>
<p>import java.util.Iterator;<br />
import java.util.List;</p>
<p>import javax.xml.namespace.QName;<br />
import javax.xml.rpc.ParameterMode;</p>
<p>import org.apache.axis.client.Call;<br />
import org.apache.axis.client.Service;<br />
import org.apache.axis.encoding.XMLType;<br />
import org.apache.axis.encoding.ser.BeanDeserializerFactory;<br />
import org.apache.axis.encoding.ser.BeanSerializerFactory;</p>
<p>import com.chinamobile.survey.entity.vo.ExamPlanContainer;<br />
import com.chinamobile.survey.entity.vo.WsExamPlan;</p>
<p>public class ArchiveClient {</p>
<p>&nbsp;public static void main(String args[]) throws Exception {</p>
<p>&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;String endpoint = "http://localhost:8080/exam/services/ExamService";<br />
&nbsp;&nbsp;&nbsp;Service service = new Service();<br />
&nbsp;&nbsp;&nbsp;Call call = (Call) service.createCall();</p>
<p>&nbsp;&nbsp;&nbsp;QName searchresultqn = new QName("urn:BeanService",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"ExamPlanContainer");<br />
&nbsp;&nbsp;&nbsp;Class searchresultcls = ExamPlanContainer.class;<br />
&nbsp;&nbsp;&nbsp;call<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.registerTypeMapping(searchresultcls, searchresultqn,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new BeanSerializerFactory(searchresultcls,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;searchresultqn),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new BeanDeserializerFactory(searchresultcls,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;searchresultqn));<br />
&nbsp;&nbsp;&nbsp;QName wsExamPlanQN = new QName("urn:BeanService", "WsExamPlan");<br />
&nbsp;&nbsp;&nbsp;Class wsepcls = WsExamPlan.class;<br />
&nbsp;&nbsp;&nbsp;call.registerTypeMapping(wsepcls, wsExamPlanQN,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new BeanSerializerFactory(wsepcls, wsExamPlanQN),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new BeanDeserializerFactory(wsepcls, wsExamPlanQN));</p>
<p>&nbsp;&nbsp;&nbsp;call.setTargetEndpointAddress(new java.net.URL(endpoint));<br />
&nbsp;&nbsp;&nbsp;call.setOperationName(new QName("ExamService",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"getAllowAnswerExamPlanContainer"));</p>
<p>&nbsp;&nbsp;&nbsp;call.addParameter("userId", XMLType.XSD_LONG, ParameterMode.IN);<br />
&nbsp;&nbsp;&nbsp;call.addParameter("offset", XMLType.XSD_LONG, ParameterMode.IN);<br />
&nbsp;&nbsp;&nbsp;call.addParameter("maxRow", XMLType.XSD_LONG, ParameterMode.IN);</p>
<p>&nbsp;&nbsp;&nbsp;call.setReturnType(searchresultqn);<br />
&nbsp;&nbsp;&nbsp;ExamPlanContainer result = (ExamPlanContainer) call<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.invoke(new Object[] { new Long(1), new Long(0),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new Long(1000) });<br />
&nbsp;&nbsp;&nbsp;if (result != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;List list = result.getExamPlanList();<br />
&nbsp;&nbsp;&nbsp;&nbsp;for (Iterator iter = list.iterator(); iter.hasNext();) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WsExamPlan wsExamPlan = (WsExamPlan) iter.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(wsExamPlan.getName());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;} catch (javax.xml.rpc.ServiceException e) {<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;} catch (java.net.MalformedURLException e) {<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;} catch (java.rmi.RemoteException e) {<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;}<br />
&nbsp;}</p>
<p>&nbsp;public static void testCount() {<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;String endpoint = "http://localhost:8080/exam/services/ExamService";<br />
&nbsp;&nbsp;&nbsp;Service service = new Service();<br />
&nbsp;&nbsp;&nbsp;Call call = (Call) service.createCall();</p>
<p>&nbsp;&nbsp;&nbsp;call.setTargetEndpointAddress(new java.net.URL(endpoint));<br />
&nbsp;&nbsp;&nbsp;call.setOperationName(new QName("ExamService",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"getAllowAnswerExamPlanCount"));</p>
<p>&nbsp;&nbsp;&nbsp;call.addParameter("userId", XMLType.XSD_LONG, ParameterMode.IN);<br />
&nbsp;&nbsp;&nbsp;call.setReturnType(XMLType.XSD_INT);<br />
&nbsp;&nbsp;&nbsp;Integer result = (Integer) call<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.invoke(new Object[] { new Long(1) });<br />
&nbsp;&nbsp;&nbsp;System.out.println(result);<br />
&nbsp;&nbsp;} catch (javax.xml.rpc.ServiceException e) {<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;} catch (java.net.MalformedURLException e) {<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;} catch (java.rmi.RemoteException e) {<br />
&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
}<br />
</p>
<p>第五步：get方式访问测试<br />
&nbsp;<span style="color: #ff0000">http://localhost:8080/exam/services/ExamService?method=getAllowAnswerExamPlanContainer&amp;paramter0=1&amp;paramter1=1&amp;paramter2=1</span></p>
&nbsp;&nbsp;&nbsp; 
<img src ="http://www.blogjava.net/lyjjq/aggbug/256369.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2009-02-24 00:32 <a href="http://www.blogjava.net/lyjjq/articles/256369.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AXIS(Java WebSerivce)全攻略</title><link>http://www.blogjava.net/lyjjq/articles/256365.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Mon, 23 Feb 2009 15:50:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/256365.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/256365.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/256365.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/256365.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/256365.html</trackback:ping><description><![CDATA[<p>一、Axis简介</p>
<p><br />
1. 什么是SOAP</p>
<p>SOAP是一个基于XML的用于应用程序之间通信数据编码的传输协议。 最初由微软和Userland Software提出，随着不断地完善和改进，SOAP很快被业界广泛应用，目前完全发布版本是1.1。在其发展过程中，W3C XML标准工作小组积极促成SOAP成为一个真正的开放标准。在写作此文档之时，SOAP1.2草案已经发布，1.2对1.1中相对混乱的部分做了改进。<br />
SOAP被广泛作为新一代跨平台、跨语言分布计算Web Services的重要部分。</p>
<p><br />
2. 什么是Axis</p>
<p>Axis是Apache组织推出的SOAP引擎，Axis项目是Apache组织著名的SOAP项目的后继项目，目前最新版本是采用Java开发的1.1版本，C++的版本正在开发之中。Axis v1.1软件包可以从http://ws.apache.org/axis/dist/1_1/下载得到。<br />
但是Axis不仅仅是一个SOAP引擎，它还包括：<br />
&nbsp;&nbsp;&nbsp; 一个独立运行的SOAP服务器<br />
&nbsp;&nbsp;&nbsp; 一个servlet引擎的插件，这个servlet引擎可以是Tomcat<br />
&nbsp;&nbsp;&nbsp; 对WSDL的扩展支持<br />
&nbsp;&nbsp;&nbsp; 一个将WSDL的描述生成JAVA类的工具<br />
&nbsp;&nbsp;&nbsp; 一些示例代码<br />
&nbsp;&nbsp;&nbsp; 还有一个监控TCP/IP包的工具<br />
&nbsp;<br />
二、Axis的安装</p>
<p>应用Axis开发Web Services，你需要安装如下软件：<br />
1.JDK1.4.2<br />
2.一个支持Servlet的服务器引擎，比如广为人知的Tomcat。</p>
<p>当安装好Tomcat之后，只需将下载的Axis软件包解压缩，将其中的&#8220;webapps&#8221;目录下的&#8220;axis&#8221;目录整个拷贝到Tomcat安装目录下的&#8220;webapps&#8221;目录下即可。</p>
<p>三、Axis的配置</p>
<p>Axis基于Java开发，可以部署于多种操作系统，使用前需要配置一系列的系统变量，在此假定你已经在本机上装好了Tomcat 4.0以上的版本，需要配置的系统变量如下表所示：</p>
<p>CATALINA_HOME<br />
C:\Tomcat_4_1</p>
<p>（此处应为Tomcat的安装位置，注意路径名中不要有空格）</p>
<p>AXIS_HOME<br />
%CATALINA_HOME%\webapps\axis</p>
<p>AXIS_LIB<br />
%AXIS_HOME%\lib</p>
<p>AXISCLASSPATH<br />
%AXIS_LIB%\axis.jar;%AXIS_LIB%\commons-discovery.jar; %AXIS_LIB%\commons-logging.jar;%AXIS_LIB%\jaxrpc.jar; %AXIS_LIB%\saaj.jar;%AXIS_LIB%\log4j-1.2.8.jar; %AXIS_LIB%\xml-apis.jar;%AXIS_LIB%\xercesImpl.jar</p>
<p>CLASSPATH 中加入：<br />
%AXIS_LIB%\axis.jar;%AXIS_LIB%\commons-discovery.jar; %AXIS_LIB%\commons-logging.jar;%AXIS_LIB%\jaxrpc.jar; %AXIS_LIB%\saaj.jar;%AXIS_LIB%\log4j-1.2.8.jar; %AXIS_LIB%\xml-apis.jar;%AXIS_LIB%\xercesImpl.jar</p>
<p>四、Axis的测试</p>
<p>安装配置完毕后，应测试一下是否Axis可以正确运行了。</p>
<p>　　启动Tomcat服务器，在浏览器中访问http://localhost:8080/axis/happyaxis.jsp，如果页面显示有错误，则需要回头检查一下相关配置是否正确，如果浏览页面能正确显示出系统组件、属性等参数配置信息，则表示安装成功。现在可以开始开发你的Web Services应用了。</p>
<p>五、服务的发布<br />
Axis提供了两种服务发布方式，一种是即时发布（Instant Deployment），一种是定制发布（Custom Deployment）。</p>
<p>1. 使用即时发布 Java Web Service(JWS)</p>
<p>　　对即时发布的支持是Axis的特色之一，使用即时发布使用户只需有提供服务的Java类的源代码，即可将其迅速发布成Web服务。每当用户调用这类服务的时候，Axis会自动进行编译，即使服务器重启了也不必对其做任何处理，使用非常简单快捷。</p>
<p>　　使用即时发布首先需要一个实现服务功能的Java源文件，将其扩展名改为.jws（Java Web Service的缩写），然后将该文件放到&#8220;&#8230;&#8230;\webapps\axis&#8221;目录下即可。<br />
&nbsp;&nbsp;&nbsp; 在此给出一个从英里到公里的长度单位转换的服务，其源码如下：</p>
<p>文件Distance.jws</p>
<p>public class Distance<br />
{<br />
&nbsp;&nbsp;&nbsp; public double convertMile2Kilometre( double mile )<br />
&nbsp;&nbsp;&nbsp; { <br />
&nbsp;return mile * 1.609;&nbsp; //实现英里到公里的距离转换<br />
&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p>将其放到&#8220;&#8230;&#8230;\webapps\axis&#8221;目录，通过访问http://localhost:8080/axis/Distance.jws?wsdl可以看到这个服务的WSDL描述文件，这说明Distance服务被成功发布了。描述的WDSL代码如下：<br />
&lt;?xml version="1.0" encoding="UTF-8" ?&gt; <br />
- &lt;wsdl:definitions targetNamespace="http://192.168.0.26:8080/axis/Distance.jws" xmlns="http://schemas.xmlsoap.org/wsdl/"&nbsp; <br />
&nbsp;&nbsp; xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://192.168.0.26:8080/axis/Distance.jws" xmlns:intf="http://192.168.0.26:8080/axis/Distance.jws" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;<br />
- &lt;wsdl:message name="convertMile2KilometreRequest"&gt;<br />
&nbsp; &lt;wsdl:part name="mile" type="xsd:double" /&gt; <br />
&nbsp; &lt;/wsdl:message&gt;<br />
- &lt;wsdl:message name="convertMile2KilometreResponse"&gt;<br />
&nbsp; &lt;wsdl:part name="convertMile2KilometreReturn" type="xsd:double" /&gt; <br />
&nbsp; &lt;/wsdl:message&gt;<br />
- &lt;wsdl:portType name="Distance"&gt;<br />
- &lt;wsdl:operation name="convertMile2Kilometre" parameterOrder="mile"&gt;<br />
&nbsp; &lt;wsdl:input message="impl:convertMile2KilometreRequest" name="convertMile2KilometreRequest" /&gt; <br />
&nbsp; &lt;wsdl:output message="impl:convertMile2KilometreResponse" name="convertMile2KilometreResponse" /&gt; <br />
&nbsp; &lt;/wsdl:operation&gt;<br />
&nbsp; &lt;/wsdl:portType&gt;<br />
- &lt;wsdl:binding name="DistanceSoapBinding" type="impl:Distance"&gt;<br />
&nbsp; &lt;wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /&gt; <br />
- &lt;wsdl:operation name="convertMile2Kilometre"&gt;<br />
&nbsp; &lt;wsdlsoap:operation soapAction="" /&gt; <br />
- &lt;wsdl:input name="convertMile2KilometreRequest"&gt;<br />
&nbsp; &lt;wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://DefaultNamespace" use="encoded" /&gt; <br />
&nbsp; &lt;/wsdl:input&gt;<br />
- &lt;wsdl:output name="convertMile2KilometreResponse"&gt;<br />
&nbsp; &lt;wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://192.168.0.26:8080/axis/Distance.jws" use="encoded" /&gt; <br />
&nbsp; &lt;/wsdl:output&gt;<br />
&nbsp; &lt;/wsdl:operation&gt;<br />
&nbsp; &lt;/wsdl:binding&gt;<br />
- &lt;wsdl:service name="DistanceService"&gt;<br />
- &lt;wsdl:port binding="impl:DistanceSoapBinding" name="Distance"&gt;<br />
&nbsp; &lt;wsdlsoap:address location="http://192.168.0.26:8080/axis/Distance.jws" /&gt; <br />
&nbsp; &lt;/wsdl:port&gt;<br />
&nbsp; &lt;/wsdl:service&gt;<br />
&nbsp; &lt;/wsdl:definitions&gt;</p>
<p>需要注意的是：JWS的web服务发布是一个很简单的Web服务发布方式，在页面中你不能使用包，而且由于代码是在运行期被编译的，所以在部署之后，你也很难找到错误所在。</p>
<p>2. 使用定制发布 Web Service Deployment Descriptor(WSDD)</p>
<p>　 　即时发布是一项令人激动的技术，它使Web服务的开发变得如此简单；然而即时发布并不总是最好的选择，比如有些应用系统是第三方提供的，我们没 有购买源代码，只有.class文件，但我们又希望将这个应用系统的一些功能对外发布成Web服务，使其能够在更大范围内产生作用，这个时候即时发布技术 就无能为力了。此外，即时发布技术并不灵活，无法进行更多的服务配置，这使得它并不能满足一些特定系统的需求。</p>
<p>　　因此，Axis提供了另一种服务发布方式，这就是定制发布。</p>
<p>　　在此给出一个从加仑到升的容积单位转换的服务，其源码如下：</p>
<p>　　文件Capacity.java<br />
&nbsp;&nbsp;&nbsp; package samples.capacity;<br />
&nbsp;&nbsp;&nbsp; public class Capacity<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public double convertGallon2Litre( double gallon )<br />
&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp; return gallon * 4.546;//实现加仑到升的容积转换<br />
&nbsp;}//convertGallon2Litre()</p>
<p>&nbsp;&nbsp;&nbsp; }/* Capacity */<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp; 将其编译成.class文件，放置到&#8220;&#8230;&#8230;\webapps\axis\samples\capacity&#8221;目录下，即可着手进行发布。<br />
&nbsp;&nbsp;&nbsp; 定制发布不需要构建.jws文件，但必须创建服务发布描述文件deploy.wsdd（Web Service Deployment Descriptor的缩写），这个文件负责描述服务的名称、入口等信息，其内容如下：<br />
&nbsp;&nbsp;&nbsp; 文件deploy.wsdd</p>
<p>&nbsp;&nbsp;&nbsp; &lt;deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"&gt;<br />
&nbsp;&lt;service name="Capacity" provider="java:RPC"&gt;<br />
&nbsp;&lt;parameter name="className" value="samples.capacity.Capacity"/&gt;<br />
&nbsp;&lt;parameter name="allowedMethods" value="*"/&gt;<br />
&nbsp;&lt;/service&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/deployment&gt;</p>
<p>&nbsp;&nbsp;&nbsp; 在这里服务的提供者是&#8220;java:RPC&#8221;，它被内建在Axis中，而且指明了一个JAVA RPC服务，做这个处理的类是org.apache.axis.providers.java.RPCProvider。<br />
&nbsp;&nbsp;&nbsp; 我们是通过一个&lt;parameter&gt;标签告诉RPC服务应该调用的类，而另外一个&lt;parameter&gt;标签则告诉引擎，它可 以调用这个类中的任何的Public方法。你也可以指定通过使用名字空间或者一些可以调用的方法列表，来指明那些方法可以被调用。</p>
<p>　　将该文件也放到&#8220;&#8230;&#8230;\webapps\axis\samples\capacity&#8221;目录下，然后可以采用Axis提供的一个客户端管理工具——AdminClient来完成服务的定制发布。<br />
&nbsp;&nbsp; 在&#8220;&#8230;&#8230;\webapps\axis\samples\capacity&#8221;目录下，运行：</p>
<p>&nbsp;&nbsp; JAVA-cp %AXISCLASSPATH% org.apache.axis.client.AdminClient deploy.wsdd</p>
<p>&nbsp;&nbsp; 如果运行时说没有找到类，那么可能是类路径没有配置好，建议将所有的与axis相关的jar都写到classpath中去。这样只要运行:</p>
<p>&nbsp;&nbsp; java org.apache.axis.client.AdminClient deploy.wsdd<br />
&nbsp;&nbsp; 可以看到以下运行结果：</p>
<p>&nbsp;Processing file deploy.wsdd<br />
&nbsp;&lt;Admin&gt;Doneprocessing&lt;/Admin&gt;</p>
<p>　　这表明Capacity服务定制发布完成。<br />
&nbsp;<br />
&nbsp;&nbsp; 你也可以调用：<br />
&nbsp;java org.apache.axis.client.AdminClient undeploy.wsdd&nbsp; 来取消部署。</p>
<p>&nbsp;&nbsp; 你也可以调用：<br />
&nbsp;java org.apache.axis.client.AdminClient list 来获得所有的已经部署的服务的列表。在这里你会看到services, handlers, transports等等，注意这个调用只是列出了WEB-INF\server-config.wsdd的文件内容。</p>
<p>&nbsp;&nbsp; 一定要注意：编译后的class文件要拷贝到web-inf/classes的目录中，如果该文件中有包存在的话，别忘了还要在classes目录下创建包的目录<br />
&nbsp;&nbsp; 通过访问http://localhost:8080/axis/services/Capacity?wsdl可以看到这个服务的WSDL描述文件，这说明Capacity服务被成功发布了。<br />
&nbsp;&nbsp; 你也可以通过访问http://localhost:8080/axis/servlet/AxisServlet查看所有定制发布的服务。<br />
&nbsp;&nbsp; WDSL如下：<br />
&nbsp; &lt;?xml version="1.0" encoding="UTF-8" ?&gt; <br />
- &lt;wsdl:definitions targetNamespace="http://localhost:8080/axis/services/Capacity" xmlns="http://schemas.xmlsoap.org/wsdl/"<br />
&nbsp;&nbsp;&nbsp; xmlns:apachesoap="http://xml.apache.org/xml-soap" xmlns:impl="http://localhost:8080/axis/services/Capacity" xmlns:intf="http://localhost:8080/axis/services/Capacity" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;<br />
- &lt;wsdl:message name="convertGallon2LitreResponse"&gt;<br />
&nbsp; &lt;wsdl:part name="convertGallon2LitreReturn" type="xsd:double" /&gt; <br />
&nbsp; &lt;/wsdl:message&gt;<br />
- &lt;wsdl:message name="convertGallon2LitreRequest"&gt;<br />
&nbsp; &lt;wsdl:part name="in0" type="xsd:double" /&gt; <br />
&nbsp; &lt;/wsdl:message&gt;<br />
- &lt;wsdl:portType name="Capacity"&gt;<br />
- &lt;wsdl:operation name="convertGallon2Litre" parameterOrder="in0"&gt;<br />
&nbsp; &lt;wsdl:input message="impl:convertGallon2LitreRequest" name="convertGallon2LitreRequest" /&gt; <br />
&nbsp; &lt;wsdl:output message="impl:convertGallon2LitreResponse" name="convertGallon2LitreResponse" /&gt; <br />
&nbsp; &lt;/wsdl:operation&gt;<br />
&nbsp; &lt;/wsdl:portType&gt;<br />
- &lt;wsdl:binding name="CapacitySoapBinding" type="impl:Capacity"&gt;<br />
&nbsp; &lt;wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /&gt; <br />
- &lt;wsdl:operation name="convertGallon2Litre"&gt;<br />
&nbsp; &lt;wsdlsoap:operation soapAction="" /&gt; <br />
- &lt;wsdl:input name="convertGallon2LitreRequest"&gt;<br />
&nbsp; &lt;wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://capacity.samples" use="encoded" /&gt; <br />
&nbsp; &lt;/wsdl:input&gt;<br />
- &lt;wsdl:output name="convertGallon2LitreResponse"&gt;<br />
&nbsp; &lt;wsdlsoap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost:8080/axis/services/Capacity" use="encoded" /&gt; <br />
&nbsp; &lt;/wsdl:output&gt;<br />
&nbsp; &lt;/wsdl:operation&gt;<br />
&nbsp; &lt;/wsdl:binding&gt;<br />
- &lt;wsdl:service name="CapacityService"&gt;<br />
- &lt;wsdl:port binding="impl:CapacitySoapBinding" name="Capacity"&gt;<br />
&nbsp; &lt;wsdlsoap:address location="http://localhost:8080/axis/services/Capacity" /&gt; <br />
&nbsp; &lt;/wsdl:port&gt;<br />
&nbsp; &lt;/wsdl:service&gt;<br />
&nbsp; &lt;/wsdl:definitions&gt;</p>
<p>&nbsp; WSDD 的高级功能：<br />
&nbsp; (1) AXIS支持三种对象范围：<br />
&nbsp;&nbsp;&nbsp;&nbsp; "request"范围：这是默认的情况，每一次Soap请求的时候都将创建新的对象。<br />
&nbsp;&nbsp;&nbsp;&nbsp; "application"范围：将会为所有的请求生成一个单独的共享的对象。<br />
&nbsp;&nbsp;&nbsp;&nbsp; "session"范围：为每一个session期的客户端请求创建一个对象。<br />
&nbsp; 指定方法如下：<br />
&nbsp; &lt;service name="MyService"...&gt;<br />
&nbsp; &lt;parameter name="scope" value="value"/&gt;<br />
&nbsp; ...<br />
&nbsp; &lt;/service&gt;<br />
&nbsp; (2) 更多部署内容：Handlers and Chains<br />
&nbsp; 让我们来深入挖掘一下Axis引擎的更强大的特性。如果我们想跟踪我们的服务被调用了多少次，那么我们只需要包含一个简单的handler，它存放在 samples/log目录下。要使用这个handler，你就首先应该部署这个handler，然后使用在部署服务时给它指定的名字。下面是一个 wsdd文件的例子：<br />
&nbsp; &lt;deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"&gt;<br />
&nbsp;&nbsp; &lt;!-- define the logging handler configuration --&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;handler name="track" type="java:samples.userguide.example4.LogHandler"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;parameter name="filename" value="MyService.log"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/handler&gt;<br />
&nbsp; <br />
&nbsp;&nbsp; &lt;!-- define the service, using the log handler we just defined --&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;service name="LogTestService" provider="java:RPC"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;requestFlow&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;handler type="track"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/requestFlow&gt;<br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;parameter name="className" value="samples.userguide.example4.Service"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;parameter name="allowedMethods" value="*"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/service&gt;<br />
&nbsp; &lt;/deployment&gt;</p>
<p>&nbsp; 第一段指明了一个名为track的handler，它是samples.userguide.example4.LogHandler类的实例。另外还指定了一个参数filename，用于指定日志文件名称。<br />
&nbsp; 下面的那段指明了一个RPC服务，和我们在上面的例子中看到的一样，所不同的是在service标签中的&lt;requestFlow&gt;标签，它 指定了一些在调用服务前应该被调用的handler集。也就是由于我们在部署中插入了这个"track"的引用，所以我们确定每次调用服务的时候都将被记 录到日志文件中去。<br />
&nbsp; <br />
&nbsp; (3)远程管理：<br />
&nbsp; &lt;service name="AdminService" provider="java:MSG"&gt;<br />
&nbsp;&lt;parameter name="className" value="org.apache.axis.util.Admin"/&gt;<br />
&nbsp;&lt;parameter name="allowedMethods" value="*"/&gt;<br />
&nbsp;&lt;parameter name="enableRemoteAdmin" value="true"/&gt;<br />
&nbsp; &lt;/service&gt;<br />
&nbsp; WARNING: enabling remote administration may give unauthorized parties access to your machine. If you do this, please make sure to add security to your configuration!<br />
&nbsp; 所以远程管理涉及到安全问题，不建议采用。</p>
<p>六、服务的访问</p>
<p>　　GET方式的服务访问</p>
<p>　　一般的SOAP消息都是采用POST方式实现传递，但也可以通过GET方式来访问。比如以下给出的一个服务——&#8220;HelloWorld&#8221;，其源码如下： </p>
<p>文件HelloWorld.jws<br />
public class HelloWorld<br />
{<br />
&nbsp;&nbsp;&nbsp; public String helloWorld()<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println( "Hello World!" );//在服务器端打印输出 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "Hello World!";//返回相应字符串<br />
&nbsp;&nbsp;&nbsp; }<br />
}</p>
<p>　 　这个服务给出一个名为&#8220;helloWorld&#8221;的无入口参数的操作，返回一个内容为&#8220;Hello World！的字符串&#8221;，同时在服务器端打印&#8220;Hello World！&#8221;，将该文件放到&#8220;&#8230;&#8230;\webapps\axis&#8221;目录下，即可通过GET方法直接访问该服务，访问的地址为http://localhost:8080/axis/HelloWorld.jws?method=helloWorld，可以看到返回的SOAP信封消息，同时服务器端给出了相应的显示信息&#8220;Hello World！&#8221;这表明HelloWorld服务被成功访问了，生成的SOAP信封消息为：<br />
&nbsp;&lt;?xml version="1.0" encoding="UTF-8" ?&gt; <br />
- &lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"<br />
&nbsp;&nbsp;&nbsp; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;<br />
- &lt;soapenv:Body&gt;<br />
- &lt;helloWorldResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"&gt;<br />
&nbsp; &lt;helloWorldReturn xsi:type="xsd:string"&gt;Hello World!&lt;/helloWorldReturn&gt; <br />
&nbsp; &lt;/helloWorldResponse&gt;<br />
&nbsp; &lt;/soapenv:Body&gt;<br />
&nbsp; &lt;/soapenv:Envelope&gt;</p>
<p><br />
七、客户端服务访问编程</p>
<p>　　Axis提供了一套API来实现SOAP，从http://localhost:8080/axis/docs/apiDocs/index.html可以看到Axis的API文档。</p>
<p>　 　其中，org.apache.axis.client.Call和org.apache.axis.client.Service是两个比较常 用的类，一般的客户端程序欲访问一个Web Service时，都要生成一个客户端的Service对象和Call对象，在访问服务之前，首先要对Call对象设置相应的参数，包括服务的位置、操作 名、入口参数、返回值类型等，最后调用Call对象的invoke方法访问服务。</p>
<p>　　以下给出了一个客户端访问Web服务的例程——AXISTest.java：</p>
<p>　　文件AXISTest.java</p>
<p>package axisexercise;</p>
<p>import org.apache.axis.client.Call;</p>
<p>import org.apache.axis.client.Service;</p>
<p>import org.apache.axis.encoding.XMLType;</p>
<p>import javax.xml.rpc.ParameterMode;</p>
<p>public class AXISTest<br />
{<br />
&nbsp;&nbsp;&nbsp; public static void main( String[] args ) throws Exception<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 创建service和call对象，这些对象是标准的JAX-RPC对象，这些对象用于存储服务调用的数据（metadata）。</p>
<p>&nbsp;Service service = new Service();<br />
&nbsp;Call call = ( Call ) service.createCall();<br />
&nbsp;//////////访问即时发布的Distance服务</p>
<p>&nbsp;//设置访问点<br />
&nbsp;call.setTargetEndpointAddress( "http://localhost:8080/axis/Distance.jws" );</p>
<p>&nbsp;//设置操作名<br />
&nbsp;call.setOperationName( "convertMile2Kilometre" );</p>
<p>&nbsp;//设置入口参数<br />
&nbsp;call.addParameter( "op1", XMLType.XSD_DOUBLE, ParameterMode.IN );</p>
<p>&nbsp;//设置返回参数类型<br />
&nbsp;call.setReturnType( XMLType.XSD_DOUBLE );<br />
&nbsp;Double d1 = new Double( 190 );</p>
<p>&nbsp;//调用服务，在invoke方法中传入的是包含调用参数的数组<br />
&nbsp;System.out.println( d1 + " 英里相当于 " + <br />
&nbsp;call.invoke( new Object[] {d1} ) + " 公里！" );</p>
<p>&nbsp;//////////访问定制发布的Capacity服务<br />
&nbsp;call = ( Call ) service.createCall();</p>
<p>&nbsp;//设置访问点<br />
&nbsp;call.setTargetEndpointAddress( "http://localhost:8080/axis/services/Capacity" );</p>
<p>&nbsp;//设置操作名<br />
&nbsp;call.setOperationName( "convertGallon2Litre" );</p>
<p>&nbsp;//设置入口参数<br />
&nbsp;call.addParameter( "op1", XMLType.XSD_DOUBLE, ParameterMode.IN );<br />
&nbsp;call.setReturnType( XMLType.XSD_DOUBLE );<br />
&nbsp;d1 = new Double( 10.00 );</p>
<p>&nbsp;//调用服务<br />
&nbsp;System.out.println( d1 + " 加仑相当于 " + <br />
&nbsp;call.invoke( new Object[] {d1} ) + " 升！" );</p>
<p>&nbsp;&nbsp;&nbsp; } //main()</p>
<p>}/* AXISTest */</p>
<p>编译运行后运行可以看到以下的结果：</p>
<p>190.0英里相当于305.71公里！</p>
<p>10.0加仑相当于45.46升！</p>
<p>注意程序在访问即时发布的Distance服务和定制发布的Capacity服务时的不同，前者的服务访问点地址为http://localhost:8080/axis/HelloWorld.jws，而后者的则为http://localhost:8080/axis/services/Capacity。</p>
<p><br />
八、服务类型：RPC, Document, Wrapped, and Message<br />
在Axis中，有四种服务类型：</p>
<p>1. RPC服务：<br />
PRC 服务是AXIS中的默认服务，当你通过&lt;service ... provider="java:RPC"&gt; or &lt;service ... style="RPC"&gt;标签进行部署的时候，使用的就是RPC服务。RPC服务遵循SOAP RPC和其编码规范。AXIS可以将XML反序列化成java对象，并将其传给服务的方法。并且可以将服务的方法返回的JAVA对象序列化成XML。</p>
<p>2.Document / Wrapped services<br />
Document services and wrapped services are similar in that neither uses the SOAP encoding for data; it's just plain old XML schema. In both cases, however, Axis still "binds" Java representations to the XML (see the databinding section for more), so you end up dealing with Java objects, not directly with XML constructs.</p>
<p>Document和Wrapped服务都不使用SOAP编码数据，这一点是他们相似的地方。他们仅仅使用旧的XML模式。然而，在这两种服务中，AXIS将捆绑Java的表示到XML文档中，所以你最终处理的是java对象而不直接处理XML。</p>
<p>下面是包含定单的一个简单的SOAP消息，你可以看到Document 和 Wrapped 服务的区别所在：<br />
&lt;soap:Envelope xmlns="http://xml.apache.org/axis/wsdd/"<br />
&nbsp;&nbsp; xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"&gt;<br />
&nbsp; &lt;soap:Body&gt;<br />
&nbsp;&lt;myNS:PurchaseOrder xmlns:myNS="http://commerce.com/PO"&gt;<br />
&nbsp;&nbsp; &lt;item&gt;SK001&lt;/item&gt;<br />
&nbsp;&nbsp; &lt;quantity&gt;1&lt;/quantity&gt;<br />
&nbsp;&nbsp; &lt;description&gt;Sushi Knife&lt;/description&gt;<br />
&nbsp;&lt;/myNS:PurchaseOrder&gt;<br />
&nbsp; &lt;/soap:Body&gt;<br />
&lt;/soap:Envelope&gt;</p>
<p>相应的XML模式如下：</p>
<p>&lt;schema targetNamespace="http://commerce.com/PO"&gt;<br />
&nbsp; &lt;complexType name="POType"&gt;<br />
&nbsp;&lt;sequence&gt;<br />
&nbsp;&nbsp; &lt;element name="item" type="xsd:string"/&gt;<br />
&nbsp;&nbsp; &lt;element name="quantity" type="xsd:int"/&gt;<br />
&nbsp;&nbsp; &lt;element name="description" type="xsd:string"/&gt;<br />
&nbsp;&lt;/sequence&gt;<br />
&nbsp; &lt;/complexType&gt;<br />
&nbsp; &lt;element name="PurchaseOrder" type="POType"/&gt;<br />
&lt;/deployment&gt;</p>
<p>对于Document类型服务，他将映射成下面的方法：<br />
public void method(PurchaseOrder po)</p>
<p><br />
八、soap envolop(soap信封)<br />
1. soap信封<br />
在 客户端发出服务请求以及服务端返回请求结果的时候，在 网络中传输的是SOAP信封。首先客户端程序将请求参数及请求的方法序列到XML的文件中（SOAP信封），并将SOAP信封传送到服务器端。服务器端接 受到SOAP信封后，将解析这个SOAP信封并反序列化调用参数及方法并将该方法的调用结果封装成SOAP信封（序列到XML的文件中）返回给客户端，客 户端同样将SOAP信封中封装的返回结果反序列化为想要得到的结果。</p>
<p>我们来看下面这段客户端程序的SOAP信封：<br />
(1) 客户端程序：<br />
&nbsp; import org.apache.axis.client.Call;<br />
&nbsp; import org.apache.axis.client.Service;<br />
&nbsp; import javax.xml.namespace.QName;<br />
&nbsp; <br />
&nbsp; public class TestClient <br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String [] args) <br />
&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String endpoint = "http://nagoya.apache.org:5049/axis/services/echo";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Service&nbsp; service = new Service();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Call&nbsp; call = (Call) service.createCall();<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call.setTargetEndpointAddress( new java.net.URL(endpoint) );<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call.setOperationName(new QName("http://soapinterop.org/", "echoString"));<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String ret = (String) call.invoke( new Object[] { "Hello!" } );<br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Sent 'Hello!', got '" + ret + "'");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
&nbsp; catch (Exception e) <br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.err.println(e.toString());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp; }</p>
<p>(2) SOAP信封：<br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;<br />
&nbsp; &lt;SOAP-ENV:Body&gt;<br />
&nbsp;&lt;ns1:echoString xmlns:ns1="http://soapinterop.org/"&gt;<br />
&nbsp;&nbsp; &lt;arg0 xsi:type="xsd:string"&gt;Hello!&lt;/arg0&gt;<br />
&nbsp;&lt;/ns1:echoString&gt;<br />
&nbsp; &lt;/SOAP-ENV:Body&gt;<br />
&lt;/SOAP-ENV:Envelope&gt;</p>
<p>2. 参数命名：<br />
在上面的代码中，AXIS自动将在Soap消息中的函数调用参数命名为arg0,arg1等等，如果你想按照自己定义的参数名调用方法的话，很简单，在你调用invoke函数之前只要调用addParameter()函数即可。如下所示：</p>
<p>&nbsp;&nbsp; call.addParameter("testParam", <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.apache.axis.Constants.XSD_STRING,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; javax.xml.rpc.ParameterMode.IN);<br />
&nbsp;&nbsp; call.setReturnType(org.apache.axis.Constants.XSD_STRING);<br />
将testParam定义为调用函数的第一个参数（这里也只有一个参数），这里也可以同时定义该参数的类型以及该参数是输入、输出还是输入输出类型。在这里它是一个输入类型，现在当你运行程序，你将得到下面的消息：<br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;<br />
&nbsp; &lt;SOAP-ENV:Body&gt;<br />
&nbsp;&lt;ns1:echoString xmlns:ns1="http://soapinterop.org/"&gt;<br />
&nbsp;&nbsp; &lt;testParam xsi:type="xsd:string"&gt;Hello!&lt;/testParam&gt;<br />
&nbsp;&lt;/ns1:echoString&gt;<br />
&nbsp; &lt;/SOAP-ENV:Body&gt;<br />
&lt;/SOAP-ENV:Envelope&gt;</p>
<p>3. 返回类型<br />
在上面的代码中我们知道echoString函数将返回一个String对象，而且我们也希望通过客户端的调用能够返回预期的String对象。下面是一个典型的通过调用echoString函数后获得的Soap信封（消息）。<br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt; <br />
&nbsp; &lt;SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" <br />
&nbsp;&nbsp;&nbsp;&nbsp; xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"<br />
&nbsp;&nbsp;&nbsp;&nbsp; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt; <br />
&nbsp; &lt;SOAP-ENV:Body&gt;<br />
&nbsp;&nbsp; &lt;ns1:echoStringResponse xmlns:ns1="http://soapinterop.org/"&gt; <br />
&nbsp;&lt;result xsi:type="xsd:string"&gt;Hello!&lt;/result&gt;<br />
&nbsp;&nbsp; &lt;/ns1:echoStringResponse&gt; <br />
&nbsp; &lt;/SOAP-ENV:Body&gt;<br />
&nbsp;&lt;/SOAP-ENV:Envelope&gt;<br />
我们可以看到这里已经声明了返回类型（&lt;result xsi:type="xsd:string"&gt;）是一个String对象。这样Axis就可以将返回结果反序列化成我们想要的String对象了。<br />
很 多工具都会将这种确定的类型信息放到XML文件中，以生成消息的&#8220;自我描述部分&#8221;，另一方面，还有一些工具是象下面这样返回响应的：(Many toolkits put this kind of explicit typing information in the XML to make the message "self-describing". On the other hand, some toolkits return responses that look like this:)<br />
&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;<br />
&nbsp;&lt;SOAP-ENV:Body&gt;<br />
&nbsp; &lt;ns1:echoStringResponse xmlns:ns1="http://soapinterop.org/"&gt;<br />
&nbsp;&nbsp; &lt;result&gt;Hello, I'm a string!&lt;/result&gt;<br />
&nbsp; &lt;/ns1:echoStringResponse&gt;<br />
&nbsp;&lt;/SOAP-ENV:Body&gt;<br />
&lt;/SOAP-ENV:Envelope&gt;<br />
在这里并没有返回类型，那么我们怎么知道应该将返回结果反序列化成什么类型的结果呢？答案是metadata，在这种情况下，我们需要一个描述来指明我们期望的返回类型，下面这行代码说明了在客户端应该如何去做：<br />
call.setReturnType( org.apache.axis.Constants.XSD_STRING );<br />
这个方法将会告诉Axis客户端，如果返回的结果没有指明类型的话，那么Axis将会把返回类型指明为xsi:type属性所预定义的SOAP类型，在这里XSD_STRING属性所指明的是String类型。</p>
<p>所以也有这样一个相似的方法，允许你指定所期望返回的Java的类。<br />
call.setReturnClass(String.class);</p>
url get调用方式<br />
<span style="color: #ff0000">http://localhost:8080/exam/services/ExamService?method=getAllowAnswerExamPlanContainer&amp;paramter0=1&amp;paramter1=1&amp;paramter2=1<br />
<br />
WEB-INF/server-config.wsdd</span><br />
&lt;deployment xmlns="http://xml.apache.org/axis/wsdd/"<br />
&nbsp;xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"&gt;<br />
&nbsp;&lt;handler name="URLMapper"<br />
&nbsp;&nbsp;type="java:org.apache.axis.handlers.http.URLMapper" /&gt;<br />
&nbsp;&lt;service name="ExamService" provider="java:RPC"&gt;<br />
&nbsp;&nbsp;&lt;parameter name="className"<br />
&nbsp;&nbsp;&nbsp;value="com.chinamobile.survey.webservice.InviteEndPoint" /&gt;<br />
&nbsp;&nbsp;&lt;parameter name="allowedMethods"<br />
&nbsp;&nbsp;&nbsp;value="getAllowAnswerExamPlanCount,getAllowAnswerExamPlanContainer" /&gt;<br />
&nbsp;&nbsp;&lt;parameter name="allowedRoles" value="user1,user2" /&gt;<br />
&nbsp;&lt;/service&gt;<br />
&nbsp;&lt;transport name="http"&gt;<br />
&nbsp;&nbsp;&lt;requestFlow&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;handler type="URLMapper" /&gt;<br />
&nbsp;&nbsp;&lt;/requestFlow&gt;<br />
&nbsp;&lt;/transport&gt;<br />
&nbsp;&lt;beanMapping qname="myNS:ExamPlanContainer"<br />
&nbsp;&nbsp;xmlns:myNS="urn:BeanService"<br />
&nbsp;&nbsp;languageSpecificType="java:com.chinamobile.survey.entity.vo.ExamPlanContainer" /&gt;<br />
&nbsp;&lt;beanMapping qname="myNS:WsExamPlan" xmlns:myNS="urn:BeanService"<br />
&nbsp;&nbsp;languageSpecificType="java:com.chinamobile.survey.entity.vo.WsExamPlan" /&gt;
<p>&lt;/deployment&gt;<br />
</p>
<br />
<img src ="http://www.blogjava.net/lyjjq/aggbug/256365.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2009-02-23 23:50 <a href="http://www.blogjava.net/lyjjq/articles/256365.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>提交多行数据到Struts的ActionForm的List属性中  </title><link>http://www.blogjava.net/lyjjq/articles/249570.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Fri, 02 Jan 2009 13:58:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/249570.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/249570.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/249570.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/249570.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/249570.html</trackback:ping><description><![CDATA[<table class="diary_bg1" cellspacing="3" cellpadding="3" width="100%" border="0">
    <tbody>
        <tr style="word-break: break-all">
            <td class="diary_title_td" align="left"></td>
        </tr>
        <tr>
            <td height="15"></td>
        </tr>
        <tr style="word-break: break-all">
            <td class="font_diary" align="left"><span id="diary_group_textDIV" style="line-height: 150%">WEB 应用中一般都会处理主从表的信息, 或者称之为头层与行层的一对多的关系数据,如订单头/订单明细. 对于这种关系数据提交到后台的 Struts 的 ActionForm 的话, 这个 ActionForm 就要好好的设计一下, 不然会给自已带来许多额外的代码. 比如有的人的处理方法就是把页面提交到后台的毫无关系的散装数据非常吃力的拼凑一对多的关系对象出来. <br />
            <!----><br />
            <!---->下面举一个如今非常现实的关于股票的例子, 简单的应用场景是: 记录某个帐户所持有的股票信息,提交到后台,然后显示出来. 输入页面如下图<br />
            <!----><br />
            <!---->帐户信息包括帐户名和资金帐号;持有股票的每一行信息包括股票代码, 股票名称, 成本价, 股票数量. 股票行可以动态增删.<br />
            <!----><br />
            <!---->
            <div align="center"><img alt="" src="http://images.blogcn.com/2007/5/22/12/unmi,2007052223111.jpg" align="absMiddle" border="1" /><br />
            输入页面 input.jsp<!----><br />
            <!----></div>
            <div align="center"><br />
            <!----><img alt="" src="http://images.blogcn.com/2007/5/27/6/unmi,2007052711545.png" /><br />
            后台处理类图</div>
            <br />
            <!---->为了简化不必要的代码, 我们要实现的终及目标是: 在输入页面上点击 "保存数据" 按钮, 由 Struts 的 RequestProcessor.processPopulate() 方法把页面提交的基本信息组装到 AccountStockForm 的 account 的对应属性中,股票行信息对应生成一个 Stock 实例加到 AccountStockForm的 List 属性 stocks 中, 后续在 AccountStockAction 中直接处理account和stocks属性就非常简单了. AccountStockForm在这里只作为一个壳.<br />
            <!----><br />
            <!---->下面从前台到后台说明关键性的代码, 完整的 MyEclipse 工程包可以点击 <a href="http://www.blog.com.cn/user86/unmi/upload/523417378.zip">TestStruts135.zip</a>下载到.<br />
            <!----><br />
            <!---->一: struts-config.xml 配置<br />
            <!----><!----><textarea class="xml" name="code" rows="5" cols="120">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
            &lt;!DOCTYPE struts-config PUBLIC
            "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
            "http://struts.apache.org/dtds/struts-config_1_3.dtd"&gt;
            &lt;struts-config&gt;
            &lt;form-beans&gt;
            &lt;form-bean name="accountStockForm"
            type="com.unmi.form.AccountStockForm"/&gt;
            &lt;/form-beans&gt;
            &lt;action-mappings&gt;
            &lt;action path="/showStock" name="accountStockForm"
            type="com.unmi.action.AccountStockAction" scope="request"&gt;
            &lt;forward name="show" path="/show.jsp"/&gt;
            &lt;/action&gt;
            &lt;/action-mappings&gt;
            &lt;/struts-config&gt;
            </textarea> <br />
            <!----><br />
            <!---->二: 输入页面 input.jsp, 注意表单域命名<br />
            <!----><textarea class="xml" name="code" rows="5" cols="120">&lt;html:form action="/showStock"&gt;
            &lt;h3&gt;记录持有的股票&lt;br&gt;&lt;/h3&gt;
            &lt;fieldset&gt;&lt;legend&gt;基本信息&lt;/legend&gt;
            &lt;table width="100%" border=0&gt;&lt;tr&gt;
            &lt;td&gt;帐户名:&lt;html:text property="account.name"/&gt;&lt;/td&gt;
            &lt;td&gt;资金帐号:&lt;html:text property="account.number"/&gt;&lt;/td&gt;
            &lt;/tr&gt;&lt;/table&gt;
            &lt;/fieldset&gt;
            &lt;br&gt;
            &lt;fieldset&gt;&lt;legend&gt;持有股票&lt;/legend&gt;
            &lt;table width=100% border=0 id="stockTable"&gt;
            &lt;tr&gt;
            &lt;td&gt;&lt;input type="checkbox" onclick="checkAll(this)"&gt;&lt;/td&gt;
            &lt;td&gt;股票代码&lt;/td&gt;
            &lt;td&gt;股票名称&lt;/td&gt;
            &lt;td&gt;成本价&lt;/td&gt;
            &lt;td&gt;股票数量&lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr&gt;
            &lt;td&gt;&lt;input type="checkbox" name="check"&gt;&lt;/td&gt;
            &lt;td&gt;&lt;input name="stocks[0].code" size="15"&gt;&lt;/td&gt;
            &lt;td&gt;&lt;input name="stocks[0].name" size="15"&gt;&lt;/td&gt;
            &lt;td&gt;&lt;input name="stocks[0].price" size="15"&gt;&lt;/td&gt;
            &lt;td&gt;&lt;input name="stocks[0].quantity" size="15"&gt;&lt;/td&gt;
            &lt;/tr&gt;
            &lt;/table&gt;
            &lt;/html:form&gt;
            </textarea> <br />
            <!---->例如输入框名 account.name 提交后能设置到 accountStockForm 的account的name属性<br />
            <!---->输入框名为 stocks[0].code 提交后会设置到 accountStockForm 的 List stocks的第一个元素的code属性.以此类推<br />
            <!---->在提交表单前要重排行层的索引,从 0 起, 否则到后右的 Form 会一些空数据.<br />
            <!----><br />
            <!---->三: AccountStockForm 的关键代码<br />
            <!----><textarea class="java" name="code" rows="5" cols="120">    private Account account = new Account();
            private List stocks = new AutoArrayList(Stock.class);
            public void setStocks(List stocks)
            {
            this.stocks.clear();
            this.stocks.addAll(stocks);
            }
            </textarea> <br />
            <!---->定义了两个属性,分别是一个bean(Account,接受基本信息)和一个List(stocks,接受股票行信息),注意这两个属性必须初始化,不然在表单提交后会出现空指针错误. setStocks方法是让stocks属性永远保有持是一个 AutoArrayList 实例. 这样在表单提交后设置值是总能调用 AutoArrayList 的 get(int index) 方法.<br />
            <!----><br />
            <!---->四: 自定义的 AutoArrayList<br />
            <!----><textarea class="java" name="code" rows="5" cols="120">public class AutoArrayList extends ArrayList {
            private Class itemClass;
            public AutoArrayList(Class itemClass) {
            this.itemClass = itemClass;
            }
            public Object get(int index) {
            try {
            while (index &gt;= size()) {
            add(itemClass.newInstance());
            }
            } catch (Exception e) {
            e.printStackTrace();
            }
            return super.get(index);
            }
            }
            </textarea> <br />
            <!---->理解为什么要继承一个ArrayList, 覆写get(int index)方法要简单了解&nbsp;Struts 处理提交数据的工作原理: 大致如下: 页面提交后,&nbsp;由 ActionServlet交给RequestProcessor的processPopulate()方法,由processPopulate()方法收集请求数据,放在map中,key为表单域的name属性,如 name, account.name, stocks[0].code. 然后借助于 Common-beanutils 工具包设置到 ActionForm 的相应属性中<br />
            <!----><!---->如果key是简单的'name',直接form.setName(map.get('name'));<br />
            <!---->如果key是'account.name', 执行的操作是 form.getAccount().setName(map.get('account.name');<br />
            <!---->如果key是'stocks[0].code', 它可以对应到数据或集合中,如对于数组 form.stocks[0].code=map.get('stocks[0].code'); 对于集合(List) form.get(0).setCode(map.get('stocks[0].code'))<br />
            <!---->从上也能理解为什么 form 中的那两个属性必须实始化,不然会出现空指针错. 而且为什么 stocks 要用 AutoArrayList 实例化, 避免出现索引越界的错误.<br />
            <!----><br />
            <!---->五: 在 AccountStockAction 中可以打印出提交的数据<br />
            <!----><textarea class="java" name="code" rows="5" cols="88">        AccountStockForm asForm = (AccountStockForm)form;
            Account account = asForm.getAccount();
            System.out.println("Account Name:"+account.getName()+
            " Number:"+account.getNumber());
            List stocks = asForm.getStocks();
            for (int i=0; i&lt;stocks.size() ;i++)
            {
            Stock stock = (Stock)stocks.get(i);
            System.out.println("Stock["+i+"]Code:"+stock.getCode()+
            " Name:"+stock.getName()+
            " Price:"+stock.getPrice()+
            " Quantity:"+stock.getQuantity());
            }
            return mapping.findForward("show");
            </textarea> <br />
            <!---->在Action中就能直接取用提交来的数据了,不需要 getParameterValues()了.<br />
            <!----><!----><br />
            <!---->六: 最后一步, 对于这样的 ActionForm 我们应该如何显示出来呢,我们用了 nested 标签 (show.jsp)<br />
            <!----><textarea class="xml" name="code" rows="5" cols="88">&lt;html:form action="/showStock"&gt;
            &lt;h3&gt;修改持有的股票&lt;br&gt;&lt;/h3&gt;
            &lt;fieldset&gt;&lt;legend&gt;基本信息&lt;/legend&gt;
            &lt;table width="100%" border=0&gt;&lt;tr&gt;
            &lt;nested:nest property="account"&gt;
            &lt;td&gt;帐户名:&lt;nested:text property="name" readonly="true"/&gt;&lt;/td&gt;
            &lt;td&gt;资金帐号:&lt;nested:text property="number" readonly="true"/&gt;&lt;/td&gt;
            &lt;/nested:nest&gt;
            &lt;/tr&gt;&lt;/table&gt;
            &lt;/fieldset&gt;
            &lt;br&gt;
            &lt;fieldset&gt;&lt;legend&gt;持有股票&lt;/legend&gt;
            &lt;table width=100% border=0  id="stockTable"&gt;
            &lt;tr&gt;
            &lt;td&gt;&lt;input type="checkbox" onclick="checkAll(this)"&gt;&lt;/td&gt;
            &lt;td&gt;股票代码&lt;/td&gt;
            &lt;td&gt;股票名称&lt;/td&gt;
            &lt;td&gt;成本价&lt;/td&gt;
            &lt;td&gt;股票数量&lt;/td&gt;
            &lt;/tr&gt;
            &lt;nested:iterate id="stock" property="stocks"&gt;
            &lt;tr&gt;
            &lt;td&gt;&lt;input type="checkbox" name="check"&gt;&lt;/td&gt;
            &lt;td&gt;&lt;nested:text property="code" size="15"/&gt;&lt;/td&gt;
            &lt;td&gt;&lt;nested:text property="name" size="15"/&gt;&lt;/td&gt;
            &lt;td&gt;&lt;nested:text property="price" size="15"/&gt;&lt;/td&gt;
            &lt;td&gt;&lt;nested:text property="quantity" size="15"/&gt;&lt;/td&gt;
            &lt;/tr&gt;
            &lt;/nested:iterate&gt;
            &lt;/table&gt;
            &lt;/html:form&gt;
            </textarea> <br />
            <!---->可以查看生成的HTML源文件, 你就能更好理解 input.jsp 中的表单域为什么要那么命名了.<br />
            <!----><br />
            <!----><br />
            <!---->小结的内容是请注意以下几个重点:<br />
            1. 输入信息的页面 input.jsp 没有使用 Struts 标签,目的是让大家理解,表单域应如何命名才能对应上 ActionForm 中的哪一个属性<br />
            2. 显示数据的页面是用的 Struts 标签,并留意 nested 标签的应用. 可以从生成的 HTML 源文件中体会出什么<br />
            3. 提交数据前要重新编排行层中输入框 Name 属性的下标植.<br />
            4. 回味为什么要引入 ArrayList 的子类 AutoArrayList, 关键在 get(int index) 方法的覆写<br />
            5. 最后是 ActionForm 中 List 属性 stocks 的 setter 方法的实现, 保持那个 List 的运行时具体类型不变 <br />
            <!----><br />
            <!---->参考:<br />
            <!---->&nbsp;&nbsp;&nbsp; 1. <a href="http://bookmark.blogcn.com/wz/pages/goto.aspx?uid=22254178&amp;addressid=503580">移：使用Struts提交多行数据 - kent的专栏 - CSDNBlog</a> <br />
            <!----><br />
            <!---->完整&nbsp;MyEclipse 工程文件下载 <a href="http://www.blog.com.cn/user86/unmi/upload/523417378.zip">TestStruts135.zip<!----> </a>, 不包含 Struts1.35 的jar. </span></td>
        </tr>
        <tr style="word-break: break-all">
            <td valign="middle" align="left" height="30"><span class="diary_tag">标签:</span>&nbsp;<span id="diary_tagDIV"><a class="diary_tag_info" href="http://search.blogcn.com/ArticleResult.aspx?SearchType=0&amp;PageIndex=1&amp;txtQuery=Struts" target="_blank">Struts</a>,<a class="diary_tag_info" href="http://search.blogcn.com/ArticleResult.aspx?SearchType=0&amp;PageIndex=1&amp;txtQuery=List" target="_blank">List</a>,<a class="diary_tag_info" href="http://search.blogcn.com/ArticleResult.aspx?SearchType=0&amp;PageIndex=1&amp;txtQuery=Form" target="_blank">Form</a>,<a class="diary_tag_info" href="http://search.blogcn.com/ArticleResult.aspx?SearchType=0&amp;PageIndex=1&amp;txtQuery=%u591A%u884C" target="_blank">多行</a></span></td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/lyjjq/aggbug/249570.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2009-01-02 21:58 <a href="http://www.blogjava.net/lyjjq/articles/249570.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>有时启动Eclipse未加载插件，解决方法很多，总结一下</title><link>http://www.blogjava.net/lyjjq/articles/236450.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Fri, 24 Oct 2008 09:23:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/236450.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/236450.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/236450.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/236450.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/236450.html</trackback:ping><description><![CDATA[　　a 、 删除整个目录/eclipse/configuration/org.eclipse.update/，重启Eclipse<br />
　　<br />
　　b 、在启动Eclipse时带上 -clean参数<br />
　　如：d:\eclipse\eclipse.exe -clean<br />
　　<br />
　　c 、 如果Eclipse启动找不到插件了，解决办法: 在/configuration/config.ini文件中加入一行<br />
　　osgi.checkConfiguration=true<br />
　　这样它会寻找并安装插件，找到后可以把那行再注释掉，这样以后每次启动就不会因寻找插件而显得慢了。
<img src ="http://www.blogjava.net/lyjjq/aggbug/236450.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2008-10-24 17:23 <a href="http://www.blogjava.net/lyjjq/articles/236450.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate中使用类映射文件创建数据库表</title><link>http://www.blogjava.net/lyjjq/articles/230915.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Wed, 24 Sep 2008 08:09:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/230915.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/230915.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/230915.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/230915.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/230915.html</trackback:ping><description><![CDATA[<h1 class="ContentTitle"><strong></strong>&nbsp;</h1>
<div class="Content-body" id="logPanel">1.加入Hibernate&nbsp;3支持；<br />
2.定义实体类；<br />
3.创建实体类的映射文件；<br />
4.通过配置文件hibernate.cfg.xml将映射文件加入到Hibernate中；<br />
5.使用SchemaExport类创建数据库。<br />
6.创建序列实现自增字段：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;id&nbsp;name="id"&nbsp;type="java.lang.Long"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;column&nbsp;name="ID"&nbsp;precision="22"&nbsp;scale="0"&nbsp;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;generator&nbsp;class="sequence"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param&nbsp;name="sequence"&gt;SEQ_HB_USER_ID&lt;/param&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/generator&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/id&gt;<br />
<br />
<br />
hibernate.cfg.xml:<br />
<div class="UBBPanel">
<div class="UBBTitle"><img style="margin: 0px 2px -3px 0px" alt="程序代码" src="http://mgc.ahau.edu.cn/images/code.gif" /> 程序代码</div>
<div class="UBBContent"><br />
&lt;?xml&nbsp;version='1.0'&nbsp;encoding='UTF-8'?&gt;<br />
&lt;!DOCTYPE&nbsp;hibernate-configuration&nbsp;PUBLIC<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"-//Hibernate/Hibernate&nbsp;Configuration&nbsp;DTD&nbsp;3.0//EN"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"&gt;<br />
<br />
&lt;!--&nbsp;Generated&nbsp;by&nbsp;MyEclipse&nbsp;Hibernate&nbsp;Tools.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;--&gt;<br />
&lt;hibernate-configuration&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;session-factory&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="connection.username"&gt;scott&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="connection.url"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jdbc:oracle:thin:@127.0.0.1:1521:MGC<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="dialect"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;org.hibernate.dialect.Oracle9Dialect<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="myeclipse.connection.profile"&gt;MGC&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="connection.password"&gt;tiger&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="connection.driver_class"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;oracle.jdbc.driver.OracleDriver<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;mapping&nbsp;resource="cn/edu/ahau/mgc/hibernate/simple/pojo/User.hbm.xml"&nbsp;/&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/session-factory&gt;<br />
<br />
&lt;/hibernate-configuration&gt;<br />
</div>
</div>
<br />
<br />
User.java:<br />
<div class="UBBPanel">
<div class="UBBTitle"><img style="margin: 0px 2px -3px 0px" alt="程序代码" src="http://mgc.ahau.edu.cn/images/code.gif" /> 程序代码</div>
<div class="UBBContent"><br />
package&nbsp;cn.edu.ahau.mgc.hibernate.simple.pojo;<br />
<br />
public&nbsp;class&nbsp;User&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;int&nbsp;id;<br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;String&nbsp;userName;<br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;String&nbsp;password;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;getId()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;id;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setId(int&nbsp;id)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.id&nbsp;=&nbsp;id;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;getUserName()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;userName;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setUserName(String&nbsp;userName)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.userName&nbsp;=&nbsp;userName;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;getPassword()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;password;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setPassword(String&nbsp;password)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.password&nbsp;=&nbsp;password;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}<br />
<br />
</div>
</div>
<br />
<br />
User.hbm.xml:<br />
<div class="UBBPanel">
<div class="UBBTitle"><img style="margin: 0px 2px -3px 0px" alt="程序代码" src="http://mgc.ahau.edu.cn/images/code.gif" /> 程序代码</div>
<div class="UBBContent"><br />
&lt;?xml&nbsp;version="1.0"&nbsp;encoding="utf-8"?&gt;<br />
&lt;!DOCTYPE&nbsp;hibernate-mapping&nbsp;PUBLIC&nbsp;"-//Hibernate/Hibernate&nbsp;Mapping&nbsp;DTD&nbsp;3.0//EN"<br />
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"&gt;<br />
&lt;!--&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;Mapping&nbsp;file&nbsp;autogenerated&nbsp;by&nbsp;MyEclipse&nbsp;Persistence&nbsp;Tools<br />
--&gt;<br />
&lt;hibernate-mapping&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;class&nbsp;name="cn.edu.ahau.mgc.hibernate.simple.pojo.User"&nbsp;table="HB_USER"&nbsp;schema="SCOTT"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;id&nbsp;name="id"&nbsp;type="java.lang.Long"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;column&nbsp;name="ID"&nbsp;precision="22"&nbsp;scale="0"&nbsp;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;generator&nbsp;class="sequence"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param&nbsp;name="sequence"&gt;SEQ_HB_USER_ID&lt;/param&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/generator&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/id&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="username"&nbsp;type="java.lang.String"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;column&nbsp;name="USERNAME"&nbsp;length="10"&nbsp;not-null="true"&nbsp;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;property&nbsp;name="password"&nbsp;type="java.lang.String"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;column&nbsp;name="PASSWORD"&nbsp;length="10"&nbsp;not-null="true"&nbsp;/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/class&gt;<br />
&lt;/hibernate-mapping&gt;<br />
<br />
<br />
</div>
</div>
<br />
<br />
ExportToDB.java:<br />
<div class="UBBPanel">
<div class="UBBTitle"><img style="margin: 0px 2px -3px 0px" alt="程序代码" src="http://mgc.ahau.edu.cn/images/code.gif" /> 程序代码</div>
<div class="UBBContent"><br />
package&nbsp;cn.edu.ahau.mgc.hibernate.simple.export;<br />
<br />
import&nbsp;org.hibernate.cfg.Configuration;<br />
import&nbsp;org.hibernate.tool.hbm2ddl.SchemaExport;<br />
<br />
public&nbsp;class&nbsp;ExportToDB&nbsp;{<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Configuration&nbsp;cfg&nbsp;=&nbsp;new&nbsp;Configuration().configure();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SchemaExport&nbsp;export&nbsp;=&nbsp;new&nbsp;SchemaExport(cfg);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;export.create(true,&nbsp;true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
}<br />
</div>
</div>
</div>
<img src ="http://www.blogjava.net/lyjjq/aggbug/230915.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2008-09-24 16:09 <a href="http://www.blogjava.net/lyjjq/articles/230915.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>replaceAll详解</title><link>http://www.blogjava.net/lyjjq/articles/126691.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Wed, 27 Jun 2007 23:09:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/126691.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/126691.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/126691.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/126691.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/126691.html</trackback:ping><description><![CDATA[<span class=tpc_content>System.out.println("= \"" + "\na".replaceAll("\n", "\\\\n") + "\"");中<br><br>"\na".replaceAll("\n", "\\\\n") 返回的结果是： "\\na",replaceAll是把"\n"替换成"\\n"，但是表达"\\n"要用"\\\\n"来表示。<br><br>"\\\\n"可以分解成"\\"+"\\"+"n" 就是\\n，"\\n"可以分解成"\\"+"n",就是\n。<br><br>对于\的个数为偶数是，没操作一次,\的个数就减半。<br><br>"\\\\n"在replaceAll时变成了"\\n"在println时就成了\n。<br></span>
<img src ="http://www.blogjava.net/lyjjq/aggbug/126691.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2007-06-28 07:09 <a href="http://www.blogjava.net/lyjjq/articles/126691.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>log4j使用详解</title><link>http://www.blogjava.net/lyjjq/articles/122256.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Tue, 05 Jun 2007 15:22:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/122256.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/122256.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/122256.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/122256.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/122256.html</trackback:ping><description><![CDATA[<div class=box2><span class=Tit>log4j</span></div>
<div class="box2 p14">在强调可重用组件开发的今天，除了自己从头到尾开发一个可重用的日志操作类外，Apache为我们提供了一个强有力的日志操作包-Log4j。<br><br>Log4j是Apache的一个开放源代码项目，通过使用Log4j，我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务 器、NT的事件记录器、UNIX Syslog守护进程等；我们也可以控制每一条日志的输出格式；通过定义每一条日志信息的级别，我们能够更加细致地控制日志的生成过程。最令人感兴趣的就 是，这些可以通过一个配置文件来灵活地进行配置，而不需要修改应用的代码。<br><br>此外，通过Log4j其他语言接口，您可以在C、C++、.Net、PL/SQL程序中使用Log4j，其语法和用法与在Java程序中一样，使得多语言 分布式系统得到一个统一一致的日志组件模块。而且，通过使用各种第三方扩展，您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中。<br><br>说明：下面分为三部分，第一部分讲解如何配置log4j，第二部分为对log4j.properties配置文件中的各个属性的讲解，第三部分为对 log4j的详细讲解，如果只想配置上log4j，那么只需要看前两个部分就可以，如果想对log4j深入了解，则还需看第三部分。<br><br>一、Log4j配置<br><br>第一步：加入log4j-1.2.8.jar到lib下。<br><br>第二步：在CLASSPATH下建立log4j.properties。内容如下：<br><br>1 log4j.rootCategory=INFO, stdout , R<br><br>2<br><br>3 log4j.appender.stdout=org.apache.log4j.ConsoleAppender<br><br>4 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout<br><br>5 log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n<br><br>6<br><br>7 log4j.appender.R=org.apache.log4j.DailyRollingFileAppender<br><br>8 log4j.appender.R.File=D:\Tomcat 5.5\logs\qc.log<br><br>9 log4j.appender.R.layout=org.apache.log4j.PatternLayout<br><br>10 log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n<br><br>11<br><br>12 log4j.logger.com.neusoft=DEBUG<br><br>13 log4j.logger.com.opensymphony.oscache=ERROR<br><br>14 log4j.logger.net.sf.navigator=ERROR<br><br>15 log4j.logger.org.apache.commons=ERROR<br><br>16 log4j.logger.org.apache.struts=WARN<br><br>17 log4j.logger.org.displaytag=ERROR<br><br>18 log4j.logger.org.springframework=DEBUG<br><br>19 log4j.logger.com.ibatis.db=WARN<br><br>20 log4j.logger.org.apache.velocity=FATAL<br><br>21<br><br>22 log4j.logger.com.canoo.webtest=WARN<br><br>23<br><br>24 log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN<br><br>25 log4j.logger.org.hibernate=DEBUG<br><br>26 log4j.logger.org.logicalcobwebs=WARN<br><br>第三步：相应的修改其中属性，修改之前就必须知道这些都是干什么的，在第二部分讲解。<br><br>第四步：在要输出日志的类中加入相关语句：<br><br>定义属性：protected final Log log = LogFactory.getLog(getClass());<br><br>在相应的方法中：<br><br>if (log.isDebugEnabled())<br><br>{<br><br>log.debug(&#8220;System &#8230;..&#8221;);<br><br>}<br><br>二、Log4j说明<br><br>1 log4j.rootCategory=INFO, stdout , R<br><br>此句为将等级为INFO的日志信息输出到stdout和R这两个目的地，stdout和R的定义在下面的代码，可以任意起名。等级可分为OFF、 FATAL、ERROR、WARN、INFO、DEBUG、ALL，如果配置OFF则不打出任何信息，如果配置为INFO这样只显示INFO, WARN, ERROR的log信息，而DEBUG信息不会被显示，具体讲解可参照第三部分定义配置文件中的logger。<br><br>3 log4j.appender.stdout=org.apache.log4j.ConsoleAppender<br><br>此句为定义名为stdout的输出端是哪种类型，可以是<br><br>org.apache.log4j.ConsoleAppender（控制台），<br><br>org.apache.log4j.FileAppender（文件），<br><br>org.apache.log4j.DailyRollingFileAppender（每天产生一个日志文件），<br><br>org.apache.log4j.RollingFileAppender（文件大小到达指定尺寸的时候产生一个新的文件）<br><br>org.apache.log4j.WriterAppender（将日志信息以流格式发送到任意指定的地方）<br><br>具体讲解可参照第三部分定义配置文件中的Appender。<br><br>4 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout<br><br>此句为定义名为stdout的输出端的layout是哪种类型，可以是<br><br>org.apache.log4j.HTMLLayout（以HTML表格形式布局），<br><br>org.apache.log4j.PatternLayout（可以灵活地指定布局模式），<br><br>org.apache.log4j.SimpleLayout（包含日志信息的级别和信息字符串），<br><br>org.apache.log4j.TTCCLayout（包含日志产生的时间、线程、类别等等信息）<br><br>具体讲解可参照第三部分定义配置文件中的Layout。<br><br>5 log4j.appender.stdout.layout.ConversionPattern= [QC] %p [%t] %C.%M(%L) | %m%n<br><br>如果使用pattern布局就要指定的打印信息的具体格式ConversionPattern，打印参数如下：<br><br>%m 输出代码中指定的消息<br><br>%p 输出优先级，即DEBUG，INFO，WARN，ERROR，FATAL<br><br>%r 输出自应用启动到输出该log信息耗费的毫秒数<br><br>%c 输出所属的类目，通常就是所在类的全名<br><br>%t 输出产生该日志事件的线程名<br><br>%n 输出一个回车换行符，Windows平台为&#8220;rn&#8221;，Unix平台为&#8220;n&#8221;<br><br>%d 输出日志时间点的日期或时间，默认格式为ISO8601，也可以在其后指定格式，比如：%d{yyyy MMM dd HH:mm:ss,SSS}，输出类似：2002年10月18日 22：10：28，921<br><br>%l 输出日志事件的发生位置，包括类目名、发生的线程，以及在代码中的行数。<br><br>[QC]是log信息的开头，可以为任意字符，一般为项目简称。<br><br>输出的信息<br><br>[TS] DEBUG [main] AbstractBeanFactory.getBean(189) | Returning cached instance of singleton bean 'MyAutoProxy'<br><br>具体讲解可参照第三部分定义配置文件中的格式化日志信息。<br><br>7 log4j.appender.R=org.apache.log4j.DailyRollingFileAppender<br><br>此句与第3行一样。定义名为R的输出端的类型为每天产生一个日志文件。<br><br>8 log4j.appender.R.File=D:\Tomcat 5.5\logs\qc.log<br><br>此句为定义名为R的输出端的文件名为D:\Tomcat 5.5\logs\qc.log<br><br>可以自行修改。<br><br>9 log4j.appender.R.layout=org.apache.log4j.PatternLayout<br><br>与第4行相同。<br><br>10 log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n<br><br>与第5行相同。<br><br>12 log4j.logger.com. neusoft =DEBUG<br><br>指定com.neusoft包下的所有类的等级为DEBUG。<br><br>可以把com.neusoft改为自己项目所用的包名。<br><br>13 log4j.logger.com.opensymphony.oscache=ERROR<br><br>14 log4j.logger.net.sf.navigator=ERROR<br><br>这两句是把这两个包下出现的错误的等级设为ERROR，如果项目中没有配置EHCache，则不需要这两句。<br><br>15 log4j.logger.org.apache.commons=ERROR<br><br>16 log4j.logger.org.apache.struts=WARN<br><br>这两句是struts的包。<br><br>17 log4j.logger.org.displaytag=ERROR<br><br>这句是displaytag的包。（QC问题列表页面所用）<br><br>18 log4j.logger.org.springframework=DEBUG<br><br>此句为Spring的包。<br><br>24 log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN<br><br>25 log4j.logger.org.hibernate=DEBUG<br><br>此两句是hibernate的包。<br><br>以上这些包的设置可根据项目的实际情况而自行定制。<br><br>三、log4j详解<br><br>1、定义配置文件<br><br>Log4j支持两种配置文件格式，一种是XML格式的文件，一种是Java特性文件log4j.properties（键=值）。下面将介绍使用log4j.properties文件作为配置文件的方法:<br><br>①、配置根Logger<br><br>Logger 负责处理日志记录的大部分操作。<br><br>其语法为：<br><br>log4j.rootLogger = [ level ] , appenderName, appenderName, &#8230;<br><br>其中，level 是日志记录的优先级，分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的级别。Log4j建议只使用四个级别，优 先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别，您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定 义了INFO级别，只有等于及高于这个级别的才进行处理，则应用程序中所有DEBUG级别的日志信息将不被打印出来。ALL:打印所有的日志，OFF：关 闭所有的日志输出。 appenderName就是指定日志信息输出到哪个地方。可同时指定多个输出目的地。<br><br>②、配置日志信息输出目的地 Appender<br><br>Appender 负责控制日志记录操作的输出。<br><br>其语法为：<br><br>log4j.appender.appenderName = fully.qualified.name.of.appender.class<br><br>log4j.appender.appenderName.option1 = value1<br><br>&#8230;<br><br>log4j.appender.appenderName.optionN = valueN<br><br>这里的appenderName为在①里定义的，可任意起名。<br><br>其中，Log4j提供的appender有以下几种：<br><br>org.apache.log4j.ConsoleAppender（控制台），<br><br>org.apache.log4j.FileAppender（文件），<br><br>org.apache.log4j.DailyRollingFileAppender（每天产生一个日志文件），<br><br>org.apache.log4j.RollingFileAppender（文件大小到达指定尺寸的时候产生一个新的文件），可通过 log4j.appender.R.MaxFileSize=100KB设置文件大小，还可通过 log4j.appender.R.MaxBackupIndex=1设置为保存一个备份文件。<br><br>org.apache.log4j.WriterAppender（将日志信息以流格式发送到任意指定的地方）<br><br>例如：log4j.appender.stdout=org.apache.log4j.ConsoleAppender<br><br>定义一个名为stdout的输出目的地，ConsoleAppender为控制台。<br><br>③、配置日志信息的格式（布局）Layout<br><br>Layout 负责格式化Appender的输出。<br><br>其语法为：<br><br>log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class<br><br>log4j.appender.appenderName.layout.option1 = value1<br><br>&#8230;<br><br>log4j.appender.appenderName.layout.optionN = valueN<br><br>其中，Log4j提供的layout有以下几种：<br><br>org.apache.log4j.HTMLLayout（以HTML表格形式布局），<br><br>org.apache.log4j.PatternLayout（可以灵活地指定布局模式），<br><br>org.apache.log4j.SimpleLayout（包含日志信息的级别和信息字符串），<br><br>org.apache.log4j.TTCCLayout（包含日志产生的时间、线程、类别等等信息）<br><br>2、格式化日志信息<br><br>Log4J采用类似C语言中的printf函数的打印格式格式化日志信息，打印参数如下：<br><br>%m 输出代码中指定的消息<br><br>%p 输出优先级，即DEBUG，INFO，WARN，ERROR，FATAL<br><br>%r 输出自应用启动到输出该log信息耗费的毫秒数<br><br>%c 输出所属的类目，通常就是所在类的全名<br><br>%t 输出产生该日志事件的线程名<br><br>%n 输出一个回车换行符，Windows平台为&#8220;rn&#8221;，Unix平台为&#8220;n&#8221;<br><br>%d 输出日志时间点的日期或时间，默认格式为ISO8601，也可以在其后指定格式，比如：%d{yyyy MMM dd HH:mm:ss,SSS}，输出类似：2002年10月18日 22：10：28，921<br><br>%l 输出日志事件的发生位置，包括类目名、发生的线程，以及在代码中的行数。<br><br>3、在代码中使用Log4j<br><br>我们在需要输出日志信息的类中做如下的三个工作：<br><br>1、导入所有需的commongs-logging类：<br><br>import org.apache.commons.logging.Log;<br><br>import org.apache.commons.logging.LogFactory;<br><br>2、在自己的类中定义一个org.apache.commons.logging.Log类的私有静态类成员：<br><br>private final Log log = LogFactory.getLog(getClass());<br><br>LogFactory.getLog()方法的参数使用的是当前类的class。<br><br>3、使用org.apache.commons.logging.Log类的成员方法输出日志信息：<br><br>if (log.isDebugEnabled())<br><br>{<br><br>log.debug("111");<br><br>}<br><br>if (log.isInfoEnabled())<br><br>{<br><br>log.info("222");<br><br>}<br><br>if (log.isWarnEnabled())<br><br>{<br><br>log.warn("333");<br><br>}<br><br>if (log.isErrorEnabled())<br><br>{<br><br>log.error("444");<br><br>}<br><br>if (log.isFatalEnabled())<br><br>{<br><br>log.fatal("555")<br><br>}</div>
<img src ="http://www.blogjava.net/lyjjq/aggbug/122256.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2007-06-05 23:22 <a href="http://www.blogjava.net/lyjjq/articles/122256.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Can't connect to X11 window server using ':0.0' as the value of the DISPLAY variable.</title><link>http://www.blogjava.net/lyjjq/articles/67731.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Tue, 05 Sep 2006 01:40:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/67731.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/67731.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/67731.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/67731.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/67731.html</trackback:ping><description><![CDATA[
		<p>在linux上在画图和chart时好多人会碰到 Can't connect to X11 window server using ':0.0' as the value of the DISPLAY variable. <br /><br />原因：因为用到了图形处理，java程序会去寻找linux上的图形界面是否启动<br />解决：不让java寻找linux图形界面即可，在java 启动时加选项java -Djava.awt.headless=true  <br />实现：如果是tomcat，在/usr/local/tomcat/bin/catalina.sh中修改为<br /><br />JAVA_OPTS=-Djava.awt.headless=true</p>
		<p>echo "Using CATALINA_BASE:   $CATALINA_BASE"<br />echo "Using CATALINA_HOME:   $CATALINA_HOME"<br />echo "Using CATALINA_TMPDIR: $CATALINA_TMPDIR"<br />echo "Using RUNJAVA:       $_RUNJAVA"<br />echo "Using JAVA_OPTS:  $JAVA_OPTS"<br /><br />java将不需检测，问题自然解决<br /><br />推荐大家使用 SwiffChartGen321-Eval-WXP.exe，SwiffChartGen321-Eval-Linux.tar.gz，都是评估版的，上面会打评估版水印，如果有能力可以破解，在linux版flash生成器上会出现中文问题方块显示问题，这个问题的解决方案是用SwiffChart32-Pro-Eval-WXP.exe 制作新的Style，sytle中只要牵涉显示中文的地方均选择宋体，或华文中宋即可<br />下载地址<a href="http://www.globfx.com/">http://www.globfx.com/</a></p>
<img src ="http://www.blogjava.net/lyjjq/aggbug/67731.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2006-09-05 09:40 <a href="http://www.blogjava.net/lyjjq/articles/67731.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JFreeChart教程</title><link>http://www.blogjava.net/lyjjq/articles/61325.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Wed, 02 Aug 2006 04:42:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/61325.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/61325.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/61325.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/61325.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/61325.html</trackback:ping><description><![CDATA[
		<span style="FONT-WEIGHT: bold">一、jFreeChart产生图形的流程</span>
		<br />创建一个数据源（dataset）来包含将要在图形中显示的数据&gt;&gt;创建一个 JFreeChart 对象来代表要显示的图形<br />&gt;&gt;把图形输出<br />重要的类和接口：<br />org.jfree.data.general.Dataset 所有数据源类都要实现的接口<br />org.jfree.chart.ChartFactory 由它来产生 JFreeChart 对象<br />org.jfree.chart.JFreeChart 所有对图形的调整都是通过它噢！！<br />org.jfree.chart.plot.Plot 通过JFreeChart 对象获得它，然后再通过它对图形外部部分（例：坐标轴）调整<br />注意：它有很多子类，一般都下嗍造型到它的子类！<br />org.jfree.chart.renderer.AbstractRenderer 通过JFreeChart 对象获得它，然后再通过它对图形内部部分<br />（例：折线的类型）调整。同样，针对不同类型的报表图，它有<br />着不同的子类实现！在下面我们简称它为 Renderer<br />下面我们结合不同类型的图形来具体分析这个流程。<br /><br /><a id="more-95"></a><span style="FONT-WEIGHT: bold">二、饼图</span><br />饼图的dataset 一般是用PieDataset 接口，具体实现类是 DefaultPieDataset<br />1、创建一个数据源（dataset）：<br />private static PieDataset createDataset()<br />{<br />DefaultPieDataset defaultpiedataset = new DefaultPieDataset(); //注意是DefaultPieDataset！！<br />defaultpiedataset.setValue(”One”, new Double(43.200000000000003D));<br />defaultpiedataset.setValue(”Two”, new Double(10D));<br />defaultpiedataset.setValue(”Three”, new Double(27.5D));<br />defaultpiedataset.setValue(”Four”, new Double(17.5D));<br />return defaultpiedataset;<br />}<br />2、由ChartFactory 产生 JFreeChart 对象<br />private static JFreeChart createChart(PieDataset piedataset)<br />{<br />JFreeChart jfreechart = ChartFactory.createPieChart(”Pie Chart Demo 1″, //图形标题名称<br />piedataset, // dataset<br />true, // legend?<br />true, // tooltips?<br />false); //URLs?<br />PiePlot pieplot = (PiePlot)jfreechart.getPlot(); //通过JFreeChart 对象获得 plot：PiePlot！！<br />pieplot.setNoDataMessage(”No data available”); // 没有数据的时候显示的内容<br />return jfreechart;<br />}<br />一些重要的方法：<br />pieplot.setExplodePercent(0,0.3D) //把Lable 为”One” 的那一块”挖”出来30%<br />3、输出略<br /><br /><span style="FONT-WEIGHT: bold">三、柱状图</span><br />柱状图的dataset 一般是用CatagoryDataset接口(具体实现类是DefaultCategoryDataset),也会用 IntervalXYDataset<br />接口<br />1、创建一个数据源（dataset）：<br />private static CategoryDataset createDataset()<br />{<br />String series1 = “First”;<br />String series2 = “Second”;<br />String series3 = “Third”;<br />String category1 = “Category 1″;<br />String category2 = “Category 2″;<br />String category3 = “Category 3″;<br />String category4 = “Category 4″;<br />String category5 = “Category 5″;<br />DefaultCategoryDataset defaultcategorydataset = new DefaultCategoryDataset();<br />defaultcategorydataset.addValue(1.0D, series1, category1);<br />defaultcategorydataset.addValue(4D, series1, category2);<br />defaultcategorydataset.addValue(3D, series1, category3);<br />defaultcategorydataset.addValue(5D, series1, category4);<br />defaultcategorydataset.addValue(5D, series1, category5);<br /><br />defaultcategorydataset.addValue(5D, series2, category1);<br />defaultcategorydataset.addValue(7D, series2, category2);<br />defaultcategorydataset.addValue(6D, series2, category3);<br />defaultcategorydataset.addValue(8D, series2, category4);<br />defaultcategorydataset.addValue(4D, series2, category5);<br /><br />defaultcategorydataset.addValue(4D, series3, category1);<br />defaultcategorydataset.addValue(3D, series3, category2);<br />defaultcategorydataset.addValue(2D, series3, category3);<br />defaultcategorydataset.addValue(3D, series3, category4);<br />defaultcategorydataset.addValue(6D, series3, category5);<br />return defaultcategorydataset;<br />}<br />2、由ChartFactory 产生 JFreeChart 对象<br />private static JFreeChart createChart(CategoryDataset categorydataset)<br />{<br />JFreeChart jfreechart = ChartFactory.createBarChart(”Bar Chart Demo”, //图形标题名称<br />“Category”,//domain 轴 Lable<br />这里先简单理解为横坐标Lable好了<br />“Value”, //range 轴 Lable<br />这里也先简单理解为纵坐标Lable好了<br />categorydataset, // dataset<br />PlotOrientation.VERTICAL, //垂直显示<br />true, // legend?<br />true, // tooltips?<br />false); //URLs?<br />jfreechart.setBackgroundPaint(Color.white); //设定背景色为白色<br />CategoryPlot categoryplot = jfreechart.getCategoryPlot(); //获得 plot：CategoryPlot！！<br />categoryplot.setBackgroundPaint(Color.lightGray); //设定图表数据显示部分背景色<br />categoryplot.setDomainGridlinePaint(Color.white); //横坐标网格线白色<br />categoryplot.setDomainGridlinesVisible(true); //可见<br />categoryplot.setRangeGridlinePaint(Color.white); //纵坐标网格线白色<br />//下面两行使纵坐标的最小单位格为整数<br />NumberAxis numberaxis = (NumberAxis)categoryplot.getRangeAxis();<br />numberaxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());<br />BarRenderer barrenderer = (BarRenderer)categoryplot.getRenderer(); //获得renderer 注意这里是下嗍造型<br />到BarRenderer！！<br />barrenderer.setDrawBarOutline(false); // Bar的外轮廓线不画<br />GradientPaint gradientpaint = new GradientPaint(0.0F, 0.0F, Color.blue,<br />0.0F, 0.0F, new Color(0, 0, 64)); //设定特定颜色<br />GradientPaint gradientpaint1 = new GradientPaint(0.0F, 0.0F, Color.green,<br />0.0F, 0.0F, new Color(0, 64, 0));<br />GradientPaint gradientpaint2 = new GradientPaint(0.0F, 0.0F, Color.red,<br />0.0F, 0.0F, new Color(64, 0, 0));<br />barrenderer.setSeriesPaint(0, gradientpaint); //给series1 Bar设定上面定义的颜色<br />barrenderer.setSeriesPaint(1, gradientpaint1); //给series2 Bar 设定上面定义的颜色<br />barrenderer.setSeriesPaint(2, gradientpaint2); //给series3 Bar 设定上面定义的颜色<br />CategoryAxis categoryaxis = categoryplot.getDomainAxis(); //横轴上的 Lable 45度倾斜<br />categoryaxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);<br />return jfreechart;<br />}<br />一些重要的方法：（增加一块标记）<br />IntervalMarker intervalmarker = new IntervalMarker(4.5D, 7.5D);<br />intervalmarker.setLabel(”Target Range”);<br />intervalmarker.setLabelFont(new Font(”SansSerif”, 2, 11));<br />intervalmarker.setLabelAnchor(RectangleAnchor.LEFT);<br />intervalmarker.setLabelTextAnchor(TextAnchor.CENTER_LEFT);<br />intervalmarker.setPaint(new Color(222, 222, 255, 128));<br />categoryplot.addRangeMarker(intervalmarker, Layer.BACKGROUND);<br /><br /><span style="FONT-WEIGHT: bold">四、折线图</span><br />折线图的dataset 两种CatagoryDataset接口(具体实现类是DefaultCategoryDataset),XYDataset 接口<br />1、CatagoryDataset接口：<br />A、创建一个数据源（dataset）：<br />private static CategoryDataset createDataset()<br />{<br />String series1 = “First”;<br />String series2 = “Second”;<br />String series3 = “Third”;<br />String type1 = “Type 1″;<br />String type2 = “Type 2″;<br />String type3 = “Type 3″;<br />String type4 = “Type 4″;<br />String type5 = “Type 5″;<br />String type6 = “Type 6″;<br />String type7 = “Type 7″;<br />String type8 = “Type 8″;<br />DefaultCategoryDataset defaultcategorydataset = new DefaultCategoryDataset();<br />defaultcategorydataset.addValue(1.0D, series1, type1);<br />defaultcategorydataset.addValue(4D, series1, type2);<br />defaultcategorydataset.addValue(3D, series1, type3);<br />defaultcategorydataset.addValue(5D, series1, type4);<br />defaultcategorydataset.addValue(5D, series1, type5);<br />defaultcategorydataset.addValue(7D, series1, type6);<br />defaultcategorydataset.addValue(7D, series1, type7);<br />defaultcategorydataset.addValue(8D, series1, type8);<br /><br />defaultcategorydataset.addValue(5D, series2, type1);<br />defaultcategorydataset.addValue(7D, series2, type2);<br />defaultcategorydataset.addValue(6D, series2, type3);<br />defaultcategorydataset.addValue(8D, series2, type4);<br />defaultcategorydataset.addValue(4D, series2, type5);<br />defaultcategorydataset.addValue(4D, series2, type6);<br />defaultcategorydataset.addValue(2D, series2, type7);<br />defaultcategorydataset.addValue(1.0D, series2, type8);<br /><br />defaultcategorydataset.addValue(4D, series3, type1);<br />defaultcategorydataset.addValue(3D, series3, type2);<br />defaultcategorydataset.addValue(2D, series3, type3);<br />defaultcategorydataset.addValue(3D, series3, type4);<br />defaultcategorydataset.addValue(6D, series3, type5);<br />defaultcategorydataset.addValue(3D, series3, type6);<br />defaultcategorydataset.addValue(4D, series3, type7);<br />defaultcategorydataset.addValue(3D, series3, type8);<br />return defaultcategorydataset;<br />}<br />B、由ChartFactory 产生 JFreeChart 对象 (与上面重复的部分就不再注释）<br />private static JFreeChart createChart(CategoryDataset categorydataset)<br />{<br />JFreeChart jfreechart = ChartFactory.createLineChart(”Line Chart Demo 1″,<br />“Type”,<br />“Value”,<br />categorydataset,<br />PlotOrientation.VERTICAL,<br />true,<br />true,<br />false);<br />jfreechart.setBackgroundPaint(Color.white);<br />CategoryPlot categoryplot = (CategoryPlot)jfreechart.getPlot();<br />categoryplot.setBackgroundPaint(Color.lightGray);<br />categoryplot.setRangeGridlinePaint(Color.white);<br />NumberAxis numberaxis = (NumberAxis)categoryplot.getRangeAxis();<br />numberaxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());<br />numberaxis.setAutoRangeIncludesZero(true);<br />//获得renderer 注意这里是下嗍造型到lineandshaperenderer！！<br />LineAndShapeRenderer lineandshaperenderer = (LineAndShapeRenderer)categoryplot.getRenderer();<br />lineandshaperenderer.setShapesVisible(true); //series 点（即数据点）可见<br />lineandshaperenderer.setSeriesStroke(0, new BasicStroke(2.0F, 1, 1, 1.0F, new float[] {<br />10F, 6F<br />}, 0.0F)); //定义series为”First”的（即series1）点之间的连线 ，这里是虚线，默认是直线<br />lineandshaperenderer.setSeriesStroke(1, new BasicStroke(2.0F, 1, 1, 1.0F, new float[] {<br />6F, 6F<br />}, 0.0F)); //定义series为”Second”的（即series2）点之间的连线<br />lineandshaperenderer.setSeriesStroke(2, new BasicStroke(2.0F, 1, 1, 1.0F, new float[] {<br />2.0F, 6F<br />}, 0.0F)); //定义series为”Third”的（即series3）点之间的连线<br />return jfreechart;<br />}<br />一些重要的方法：<br />lineandshaperenderer.setLineVisible(true) //series 点（即数据点）间有连线可见<br />2、XYDataset 接口：<br />A、创建一个数据源（dataset）：<br />private static XYDataset createDataset()<br />{<br />XYSeries xyseries = new XYSeries(”First”); //先产生XYSeries 对象<br />xyseries.add(1.0D, 1.0D);<br />xyseries.add(2D, 4D);<br />xyseries.add(3D, 3D);<br />xyseries.add(4D, 5D);<br />xyseries.add(5D, 5D);<br />xyseries.add(6D, 7D);<br />xyseries.add(7D, 7D);<br />xyseries.add(8D, 8D);<br /><br />XYSeries xyseries1 = new XYSeries(”Second”);<br />xyseries1.add(1.0D, 5D);<br />xyseries1.add(2D, 7D);<br />xyseries1.add(3D, 6D);<br />xyseries1.add(4D, 8D);<br />xyseries1.add(5D, 4D);<br />xyseries1.add(6D, 4D);<br />xyseries1.add(7D, 2D);<br />xyseries1.add(8D, 1.0D);<br /><br />XYSeries xyseries2 = new XYSeries(”Third”);<br />xyseries2.add(3D, 4D);<br />xyseries2.add(4D, 3D);<br />xyseries2.add(5D, 2D);<br />xyseries2.add(6D, 3D);<br />xyseries2.add(7D, 6D);<br />xyseries2.add(8D, 3D);<br />xyseries2.add(9D, 4D);<br />xyseries2.add(10D, 3D);<br /><br />XYSeriesCollection xyseriescollection = new XYSeriesCollection(); //再用XYSeriesCollection添加入XYSeries 对象<br />xyseriescollection.addSeries(xyseries);<br />xyseriescollection.addSeries(xyseries1);<br />xyseriescollection.addSeries(xyseries2);<br />return xyseriescollection;<br />}<br />B、由ChartFactory 产生 JFreeChart 对象<br />private static JFreeChart createChart(XYDataset xydataset)<br />{<br />JFreeChart jfreechart = ChartFactory.createXYLineChart(”Line Chart Demo 2″,<br />“X”,<br />“Y”,<br />xydataset,<br />PlotOrientation.VERTICAL,<br />true,<br />true,<br />false);<br />jfreechart.setBackgroundPaint(Color.white);<br />XYPlot xyplot = (XYPlot)jfreechart.getPlot(); //获得 plot：XYPlot！！<br />xyplot.setBackgroundPaint(Color.lightGray); //设定图表数据显示部分背景色<br />xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D)); //设定坐标轴与图表数据显示部分距离<br />xyplot.setDomainGridlinePaint(Color.white); //网格线颜色<br />xyplot.setRangeGridlinePaint(Color.white);<br />//获得 renderer 注意这里是XYLineAndShapeRenderer ！！<br />XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer)xyplot.getRenderer();<br />xylineandshaperenderer.setShapesVisible(true); //数据点可见<br />xylineandshaperenderer.setShapesFilled(true); //数据点被填充即不是空心点<br />NumberAxis numberaxis = (NumberAxis)xyplot.getRangeAxis();<br />numberaxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());<br />return jfreechart;<br />}<br />一些重要的方法：<br />XYLineAndShapeRenderer xylineandshaperenderer = new XYLineAndShapeRenderer();<br />xylineandshaperenderer.setSeriesLinesVisible(0, false); //第一个XYSeries数据点间连线不可见<br />xylineandshaperenderer.setSeriesShapesVisible(1, false); //第二个XYSeries数据点不可见<br />xyplot.setRenderer(xylineandshaperenderer);<br /><br /><span style="FONT-WEIGHT: bold">五、时间序列图</span><br />时间序列图和折线图很相似，不同的是它在 domain轴的数据是时间而不是数字。 时间序列图的dataset 是<br />XYDataset 接口，具体实现类是TimeSeriesCollection ，和上面类似，有TimeSeries 对象，它被添加入<br />TimeSeriesCollection 。<br />1、创建一个数据源（dataset）：<br />private static XYDataset createDataset()<br />{<br />TimeSeries timeseries = new TimeSeries(”L&amp;G European Index Trust”,Month.class);<br />timeseries.add(new Month(2, 2001), 181.8D);//这里用的是Month.class，同样还有Day.class Year.class 等等<br />timeseries.add(new Month(3, 2001), 167.3D);<br />timeseries.add(new Month(4, 2001), 153.8D);<br />timeseries.add(new Month(5, 2001), 167.6D);<br />timeseries.add(new Month(6, 2001), 158.8D);<br />timeseries.add(new Month(7, 2001), 148.3D);<br />timeseries.add(new Month(8, 2001), 153.9D);<br />timeseries.add(new Month(9, 2001), 142.7D);<br />timeseries.add(new Month(10, 2001), 123.2D);<br />timeseries.add(new Month(11, 2001), 131.8D);<br />timeseries.add(new Month(12, 2001), 139.6D);<br />timeseries.add(new Month(1, 2002), 142.9D);<br />timeseries.add(new Month(2, 2002), 138.7D);<br />timeseries.add(new Month(3, 2002), 137.3D);<br />timeseries.add(new Month(4, 2002), 143.9D);<br />timeseries.add(new Month(5, 2002), 139.8D);<br />timeseries.add(new Month(6, 2002), 137D);<br />timeseries.add(new Month(7, 2002), 132.8D);<br /><br />TimeSeries timeseries1 = new TimeSeries(”L&amp;G UK Index Trust”,Month.class);<br />timeseries1.add(new Month(2, 2001), 129.6D);<br />timeseries1.add(new Month(3, 2001), 123.2D);<br />timeseries1.add(new Month(4, 2001), 117.2D);<br />timeseries1.add(new Month(5, 2001), 124.1D);<br />timeseries1.add(new Month(6, 2001), 122.6D);<br />timeseries1.add(new Month(7, 2001), 119.2D);<br />timeseries1.add(new Month(8, 2001), 116.5D);<br />timeseries1.add(new Month(9, 2001), 112.7D);<br />timeseries1.add(new Month(10, 2001), 101.5D);<br />timeseries1.add(new Month(11, 2001), 106.1D);<br />timeseries1.add(new Month(12, 2001), 110.3D);<br />timeseries1.add(new Month(1, 2002), 111.7D);<br />timeseries1.add(new Month(2, 2002), 111D);<br />timeseries1.add(new Month(3, 2002), 109.6D);<br />timeseries1.add(new Month(4, 2002), 113.2D);<br />timeseries1.add(new Month(5, 2002), 111.6D);<br />timeseries1.add(new Month(6, 2002), 108.8D);<br />timeseries1.add(new Month(7, 2002), 101.6D);<br />TimeSeriesCollection timeseriescollection = new TimeSeriesCollection();<br />timeseriescollection.addSeries(timeseries);<br />timeseriescollection.addSeries(timeseries1);<br />timeseriescollection.setDomainIsPointsInTime(true); //domain轴上的刻度点代表的是时间点而不是时间段<br />return timeseriescollection;<br />}<br />2、由ChartFactory 产生 JFreeChart 对象<br />private static JFreeChart createChart(XYDataset xydataset)<br />{<br />JFreeChart jfreechart = ChartFactory.createTimeSeriesChart(”Legal &amp; General Unit Trust Prices”,<br />“Date”,<br />“Price Per Unit”,<br />xydataset,<br />true,<br />true,<br />false);<br />jfreechart.setBackgroundPaint(Color.white);<br />XYPlot xyplot = (XYPlot)jfreechart.getPlot(); //获得 plot : XYPlot!!<br />xyplot.setBackgroundPaint(Color.lightGray);<br />xyplot.setDomainGridlinePaint(Color.white);<br />xyplot.setRangeGridlinePaint(Color.white);<br />xyplot.setAxisOffset(new RectangleInsets(5D, 5D, 5D, 5D));<br />xyplot.setDomainCrosshairVisible(true);<br />xyplot.setRangeCrosshairVisible(true);<br />org.jfree.chart.renderer.xy.XYItemRenderer xyitemrenderer = xyplot.getRenderer();<br />if(xyitemrenderer instanceof XYLineAndShapeRenderer)<br />{<br />XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer)xyitemrenderer;<br />xylineandshaperenderer.setDefaultShapesVisible(true); //数据点可见<br />xylineandshaperenderer.setDefaultShapesFilled(true); //数据点是实心点<br />}<br />DateAxis dateaxis = (DateAxis)xyplot.getDomainAxis(); //对domain 轴上日期显示格式定义<br />dateaxis.setDateFormatOverride(new SimpleDateFormat(”MMM-yyyy”));<br />return jfreechart;<br />}<br />一些重要的方法：<br />A、增加标记线：<br />xyplot.addRangeMarker(new ValueMarker(550D)); //数值轴<br />Quarter quarter = new Quarter(2, 2002);<br />xyplot.addDomainMarker(new ValueMarker(quarter.getMiddleMillisecond())); //时间轴<br />B、数据点的调整<br />XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer)xyplot.getRenderer();<br />xylineandshaperenderer.setDefaultShapesVisible(true); //数据点可见<br />xylineandshaperenderer.setSeriesFillPaint(0, Color.red); //数据点填充为红色<br />xylineandshaperenderer.setSeriesFillPaint(1, Color.white); //数据点填充为白色<br />xylineandshaperenderer.setUseFillPaint(true); //应用<br />C、平均值曲线<br />这个曲线有什么用呢？很简单的例子，这里有一个以半年每天为单位的数据绘制的曲线，我们想看看以月为单位数据<br />的变化，这时就可以用到它了。<br />TimeSeries timeseries = createEURTimeSeries(); //就是以半年每天为单位的数据<br />TimeSeries timeseries1 = MovingAverage.createMovingAverage(timeseries,<br />“30 day moving average”,<br />30, //30天为一个周期<br />30); //最开始的30天跳过<br />TimeSeriesCollection timeseriescollection = new TimeSeriesCollection();<br />timeseriescollection.addSeries(timeseries);<br />timeseriescollection.addSeries(timeseries1);<br />return timeseriescollection;<br /><br /><span style="FONT-WEIGHT: bold">六、总结一下</span><br />dataset plot renderer<br />饼图 PieDataset（DefaultPieDataset） PiePlot ——<br />柱状图 CatagoryDataset（DefaultCategoryDataset） CategoryPlot BarRenderer<br />折线图 CatagoryDataset（DefaultCategoryDataset） CategoryPlot LineAndShapeRenderer<br />XYDataset（XYSeriesCollection） XYPlot XYLineAndShapeRenderer<br />时间序列图 XYDataset （TimeSeriesCollection） XYPlot XYLineAndShapeRenderer<br />这里只是一些常用的方法，具体还是看API<br /><span style="FONT-WEIGHT: bold">七、Item Lable</span><br />这里以柱状图为例说明，具体来说就是在每个柱状上显示它的数据，具体有下面内容：<br />A、使 Item Lable 可见<br />B、调整 Item Lable 的颜色、字体等<br />C、调整 Item Lable 的位置<br />D、定制 Item Lable 的内容<br />1、分配一个 Lable Generator 给 renderer<br />BarRenderer barrenderer = (BarRenderer)categoryplot.getRenderer();<br />GategoryLableGenerator generator =new StandardGategoryLableGenerator(<br />“{2}”, new DecimalFormat(”0.00″) //调整显示的数字和字符格式<br />);<br />barrenderer.setLableGenerator(generator);<br />2、使 Item Lable 可见<br />barrenderer.setItemLableVisible(true);<br />3、调整 Item Lable 的颜色、字体等<br />barrenderer.setItemLablePaint(Color.red);<br />barrenderer.setItemLableFont(new Font(”SansSerif”,Font.PLAIN,10));<br />4、调整 Item Lable 的位置<br />这里涉及到一个新的对象 ItemLablePosition , ItemLablePosition的构造函数有两个或四个参数<br />public ItemLabelPosition(ItemLabelAnchor itemLabelAnchor,<br />org.jfree.ui.TextAnchor textAnchor,<br />org.jfree.ui.TextAnchor rotationAnchor,<br />double angle)<br />itemLabelAnchor - Item Lable 的位置 （最重要的！！）<br />textAnchor - Item Lable里包含的正文相对于Item Lable 的位置<br />rotationAnchor - Item Lable里包含的正文旋转的位置<br />angle - 旋转的角度<br />ItemLabelPosition itemlabelposition = new ItemLabelPosition(ItemLabelAnchor.INSIDE12,<br />TextAnchor.CENTER_RIGHT,<br />TextAnchor.CENTER_RIGHT,<br />-1.57D);<br />barrenderer.setPositiveItemLabelPosition(itemlabelposition);<br />这样就可以每个柱状上显示它的数据了，当然可以定制 Item Lable 的内容，比如 Item Lable text 超过100的才<br />显示，这样就需要定制自己的类，它要实现GategoryLableGenerator 接口，实现generateItemLable()方法<img src ="http://www.blogjava.net/lyjjq/aggbug/61325.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2006-08-02 12:42 <a href="http://www.blogjava.net/lyjjq/articles/61325.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JFreeChart 常用API</title><link>http://www.blogjava.net/lyjjq/articles/61324.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Wed, 02 Aug 2006 04:39:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/61324.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/61324.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/61324.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/61324.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/61324.html</trackback:ping><description><![CDATA[
		<div class="navigation">
				<a title="Permanent Link: JFreeChart API" href="http://www.yangzhe.net/blog/index.php/20060416/94.html" rel="bookmark">JFreeChart API</a>
		</div>
		<div class="post">
				<div class="entrytext">
						<p>
								<br />
						</p>
						<div>JFreeChart类：<br />void setAntiAlias(boolean flag) 字体模糊边界<br />void setBackgroundImage(Image image) 背景图片<br />void setBackgroundImageAlignment(int alignment) 背景图片对齐方式（参数常量在org.jfree.ui.Align类中定义）<br />void setBackgroundImageAlpha(float alpha) 背景图片透明度（0.0～1.0）<br />void setBackgroundPaint(Paint paint) 背景色<br />void setBorderPaint(Paint paint) 边界线条颜色<br />void setBorderStroke(Stroke stroke) 边界线条笔触<br />void setBorderVisible(boolean visible) 边界线条是否可见</div>
						<p>
								<br />
						</p>
						<div>
								<br />
								<p>———————————————————————————————————–<br /></p>
								<p>TextTitle类：<br />void setFont(Font font) 标题字体<br />void setPaint(Paint paint) 标题字体颜色<br />void setText(String text) 标题内容<br /></p>
								<p>———————————————————————————————————–<br /></p>
								<p>StandardLegend(Legend)类：<br />void setBackgroundPaint(Paint paint) 图示背景色<br />void setTitle(String title) 图示标题内容<br />void setTitleFont(Font font) 图示标题字体<br />void setBoundingBoxArcWidth(int arcWidth) 图示边界圆角宽<br />void setBoundingBoxArcHeight(int arcHeight) 图示边界圆角高<br />void setOutlinePaint(Paint paint) 图示边界线条颜色<br />void setOutlineStroke(Stroke stroke) 图示边界线条笔触<br />void setDisplaySeriesLines(boolean flag) 图示项是否显示横线（折线图有效）<br />void setDisplaySeriesShapes(boolean flag) 图示项是否显示形状（折线图有效）<br />void setItemFont(Font font) 图示项字体<br />void setItemPaint(Paint paint) 图示项字体颜色<br />void setAnchor(int anchor) 图示在图表中的显示位置（参数常量在Legend类中定义）<br /></p>
								<p>———————————————————————————————————–<br /></p>
								<p>Axis类：<br />void setVisible(boolean flag) 坐标轴是否可见<br />void setAxisLinePaint(Paint paint) 坐标轴线条颜色（3D轴无效）<br />void setAxisLineStroke(Stroke stroke) 坐标轴线条笔触（3D轴无效）<br />void setAxisLineVisible(boolean visible) 坐标轴线条是否可见（3D轴无效）<br />void setFixedDimension(double dimension) （用于复合表中对多坐标轴的设置）<br />void setLabel(String label) 坐标轴标题<br />void setLabelFont(Font font) 坐标轴标题字体<br />void setLabelPaint(Paint paint) 坐标轴标题颜色<br />void setLabelAngle(double angle)` 坐标轴标题旋转角度（纵坐标可以旋转）<br />void setTickLabelFont(Font font) 坐标轴标尺值字体<br />void setTickLabelPaint(Paint paint) 坐标轴标尺值颜色<br />void setTickLabelsVisible(boolean flag) 坐标轴标尺值是否显示<br />void setTickMarkPaint(Paint paint) 坐标轴标尺颜色<br />void setTickMarkStroke(Stroke stroke) 坐标轴标尺笔触<br />void setTickMarksVisible(boolean flag) 坐标轴标尺是否显示<br /></p>
								<p>ValueAxis(Axis)类：<br />void setAutoRange(boolean auto) 自动设置数据轴数据范围<br />void setAutoRangeMinimumSize(double size) 自动设置数据轴数据范围时数据范围的最小跨度<br />void setAutoTickUnitSelection(boolean flag) 数据轴的数据标签是否自动确定（默认为true）<br />void setFixedAutoRange(double length) 数据轴固定数据范围（设置100的话就是显示MAXVALUE到MAXVALUE-100那段数据范围）<br />void setInverted(boolean flag) 数据轴是否反向（默认为false）<br />void setLowerMargin(double margin) 数据轴下（左）边距<br />void setUpperMargin(double margin) 数据轴上（右）边距<br />void setLowerBound(double min) 数据轴上的显示最小值<br />void setUpperBound(double max) 数据轴上的显示最大值<br />void setPositiveArrowVisible(boolean visible) 是否显示正向箭头（3D轴无效）<br />void setNegativeArrowVisible(boolean visible) 是否显示反向箭头（3D轴无效）<br />void setVerticalTickLabels(boolean flag) 数据轴数据标签是否旋转到垂直<br />void setStandardTickUnits(TickUnitSource source) 数据轴的数据标签（可以只显示整数标签，需要将AutoTickUnitSelection设false）<br /></p>
								<p>NumberAxis(ValueAxis)类：<br />void setAutoRangeIncludesZero(boolean flag) 是否强制在自动选择的数据范围中包含0<br />void setAutoRangeStickyZero(boolean flag) 是否强制在整个数据轴中包含0，即使0不在数据范围中<br />void setNumberFormatOverride(NumberFormat formatter) 数据轴数据标签的显示格式<br />void setTickUnit(NumberTickUnit unit) 数据轴的数据标签（需要将AutoTickUnitSelection设false）<br /></p>
								<p>DateAxis(ValueAxis)类：<br />void setMaximumDate(Date maximumDate) 日期轴上的最小日期<br />void setMinimumDate(Date minimumDate) 日期轴上的最大日期<br />void setRange(Date lower,Date upper) 日期轴范围<br />void setDateFormatOverride(DateFormat formatter) 日期轴日期标签的显示格式<br />void setTickUnit(DateTickUnit unit) 日期轴的日期标签（需要将AutoTickUnitSelection设false）<br />void setTickMarkPosition(DateTickMarkPosition position) 日期标签位置（参数常量在org.jfree.chart.axis.DateTickMarkPosition类中定义）<br /></p>
								<p>CategoryAxis(Axis)类：<br />void setCategoryMargin(double margin) 分类轴边距<br />void setLowerMargin(double margin) 分类轴下（左）边距<br />void setUpperMargin(double margin) 分类轴上（右）边距<br />void setVerticalCategoryLabels(boolean flag) 分类轴标题是否旋转到垂直<br />void setMaxCategoryLabelWidthRatio(float ratio) 分类轴分类标签的最大宽度<br /></p>
								<p>———————————————————————————————————–<br /></p>
								<p>Plot类：<br />void setBackgroundImage(Image image) 数据区的背景图片<br />void setBackgroundImageAlignment(int alignment) 数据区的背景图片对齐方式（参数常量在org.jfree.ui.Align类中定义）<br />void setBackgroundPaint(Paint paint) 数据区的背景图片背景色<br />void setBackgroundAlpha(float alpha) 数据区的背景透明度（0.0～1.0）<br />void setForegroundAlpha(float alpha) 数据区的前景透明度（0.0～1.0）<br />void setDataAreaRatio(double ratio) 数据区占整个图表区的百分比<br />void setOutLinePaint(Paint paint) 数据区的边界线条颜色<br />void setOutLineStroke(Stroke stroke) 数据区的边界线条笔触<br />void setNoDataMessage(String message) 没有数据时显示的消息<br />void setNoDataMessageFont(Font font) 没有数据时显示的消息字体<br />void setNoDataMessagePaint(Paint paint) 没有数据时显示的消息颜色<br /></p>
								<p>CategoryPlot(Plot)类：<br />void setDataset(CategoryDataset dataset) 数据区的2维数据表<br />void setColumnRenderingOrder(SortOrder order) 数据分类的排序方式<br />void setAxisOffset(Spacer offset) 坐标轴到数据区的间距<br />void setOrientation(PlotOrientation orientation) 数据区的方向（PlotOrientation.HORIZONTAL或PlotOrientation.VERTICAL）<br />void setDomainAxis(CategoryAxis axis) 数据区的分类轴<br />void setDomainAxisLocation(AxisLocation location) 分类轴的位置（参数常量在org.jfree.chart.axis.AxisLocation类中定义）<br />void setDomainGridlinesVisible(boolean visible) 分类轴网格是否可见<br />void setDomainGridlinePaint(Paint paint) 分类轴网格线条颜色<br />void setDomainGridlineStroke(Stroke stroke) 分类轴网格线条笔触<br />void setRangeAxis(ValueAxis axis) 数据区的数据轴<br />void setRangeAxisLocation(AxisLocation location) 数据轴的位置（参数常量在org.jfree.chart.axis.AxisLocation类中定义）<br />void setRangeGridlinesVisible(boolean visible) 数据轴网格是否可见<br />void setRangeGridlinePaint(Paint paint) 数据轴网格线条颜色<br />void setRangeGridlineStroke(Stroke stroke) 数据轴网格线条笔触<br />void setRenderer(CategoryItemRenderer renderer) 数据区的表示者（详见Renderer组）<br />void addAnnotation(CategoryAnnotation annotation) 给数据区加一个注释<br />void addRangeMarker(Marker marker,Layer layer) 给数据区加一个数值范围区域<br /></p>
								<p>PiePlot(Plot)类：<br />void setDataset(PieDataset dataset) 数据区的1维数据表<br />void setIgnoreNullValues(boolean flag) 忽略无值的分类<br />void setCircular(boolean flag) 饼图是否一定是正圆<br />void setStartAngle(double angle) 饼图的初始角度<br />void setDirection(Rotation direction) 饼图的旋转方向<br />void setExplodePercent(int section,double percent) 抽取的那块（1维数据表的分类下标）以及抽取出来的距离（0.0～1.0），3D饼图无效<br />void setLabelBackgroundPaint(Paint paint) 分类标签的底色<br />void setLabelFont(Font font) 分类标签的字体<br />void setLabelPaint(Paint paint) 分类标签的字体颜色<br />void setLabelLinkMargin(double margin) 分类标签与图的连接线边距<br />void setLabelLinkPaint(Paint paint) 分类标签与图的连接线颜色<br />void setLabelLinkStroke(Stroke stroke) 分类标签与图的连接线笔触<br />void setLabelOutlinePaint(Paint paint) 分类标签边框颜色<br />void setLabelOutlineStroke(Paint paint) 分类标签边框笔触<br />void setLabelShadowPaint(Paint paint) 分类标签阴影颜色<br />void setMaximumLabelWidth(double width) 分类标签的最大长度（0.0～1.0）<br />void setPieIndex(int index) 饼图的索引（复合饼图中用到）<br />void setSectionOutlinePaint(int section,Paint paint) 指定分类饼的边框颜色<br />void setSectionOutlineStroke(int section,Stroke stroke) 指定分类饼的边框笔触<br />void setSectionPaint(int section,Paint paint) 指定分类饼的颜色<br />void setShadowPaint(Paint paint) 饼图的阴影颜色<br />void setShadowXOffset(double offset) 饼图的阴影相对图的水平偏移<br />void setShadowYOffset(double offset) 饼图的阴影相对图的垂直偏移<br />void setLabelGenerator(PieSectionLabelGenerator generator) 分类标签的格式，设置成null则整个标签包括连接线都不显示<br />void setToolTipGenerator(PieToolTipGenerator generator) MAP中鼠标移上的显示格式<br />void setURLGenerator(PieURLGenerator generator) MAP中钻取链接格式<br /></p>
								<p>PiePlot3D(PiePlot)类：<br />void setDepthFactor(double factor) 3D饼图的Z轴高度（0.0～1.0）<br /></p>
								<p>MultiplePiePlot(Plot)类：<br />void setLimit(double limit) 每个饼图之间的数据关联（详细比较复杂）<br />void setPieChart(JFreeChart pieChart) 每个饼图的显示方式（见JFreeChart类个PiePlot类）<br /></p>
								<p>———————————————————————————————————–<br /></p>
								<p>AbstractRenderer类：<br />void setItemLabelAnchorOffset(double offset) 数据标签的与数据点的偏移<br />void setItemLabelsVisible(boolean visible) 数据标签是否可见<br />void setItemLabelFont(Font font) 数据标签的字体<br />void setItemLabelPaint(Paint paint) 数据标签的字体颜色<br />void setItemLabelPosition(ItemLabelPosition position) 数据标签位置<br />void setPositiveItemLabelPosition(ItemLabelPosition position) 正数标签位置<br />void setNegativeItemLabelPosition(ItemLabelPosition position) 负数标签位置<br />void setOutLinePaint(Paint paint) 图形边框的线条颜色<br />void setOutLineStroke(Stroke stroke) 图形边框的线条笔触<br />void setPaint(Paint paint) 所有分类图形的颜色<br />void setShape(Shape shape) 所有分类图形的形状（如折线图的点）<br />void setStroke(Stroke stroke) 所有分类图形的笔触（如折线图的线）<br />void setSeriesItemLabelsVisible(int series,boolean visible) 指定分类的数据标签是否可见<br />void setSeriesItemLabelFont(int series,Font font) 指定分类的数据标签的字体<br />void setSeriesItemLabelPaint(int series,Paint paint) 指定分类的数据标签的字体颜色<br />void setSeriesItemLabelPosition(int series,ItemLabelPosition position) 数据标签位置<br />void setSeriesPositiveItemLabelPosition(int series,ItemLabelPosition position) 正数标签位置<br />void setSeriesNegativeItemLabelPosition(int series,ItemLabelPosition position) 负数标签位置<br />void setSeriesOutLinePaint(int series,Paint paint) 指定分类的图形边框的线条颜色<br />void setSeriesOutLineStroke(int series,Stroke stroke) 指定分类的图形边框的线条笔触<br />void setSeriesPaint(int series,Paint paint) 指定分类图形的颜色<br />void setSeriesShape(int series,Shape shape) 指定分类图形的形状（如折线图的点）<br />void setSeriesStroke(int series,Stroke stroke) 指定分类图形的笔触（如折线图的线）<br /></p>
								<p>AbstractCategoryItemRenderer(AbstractRenderer)类：<br />void setLabelGenerator(CategoryLabelGenerator generator) 数据标签的格式<br />void setToolTipGenerator(CategoryToolTipGenerator generator) MAP中鼠标移上的显示格式<br />void setItemURLGenerator(CategoryURLGenerator generator) MAP中钻取链接格式<br />void setSeriesLabelGenerator(int series,CategoryLabelGenerator generator) 指定分类的数据标签的格式<br />void setSeriesToolTipGenerator(int series,CategoryToolTipGenerator generator) 指定分类的MAP中鼠标移上的显示格式<br />void setSeriesItemURLGenerator(int series,CategoryURLGenerator generator) 指定分类的MAP中钻取链接格式<br /></p>
								<p>BarRenderer(AbstractCategoryItemRenderer)类：<br />void setDrawBarOutline(boolean draw) 是否画图形边框<br />void setItemMargin(double percent) 每个BAR之间的间隔<br />void setMaxBarWidth(double percent) 每个BAR的最大宽度<br />void setMinimumBarLength(double min) 最短的BAR长度，避免数值太小而显示不出<br />void setPositiveItemLabelPositionFallback(ItemLabelPosition position) 无法在BAR中显示的正数标签位置<br />void setNegativeItemLabelPositionFallback(ItemLabelPosition position) 无法在BAR中显示的负数标签位置<br /></p>
								<p>BarRenderer3D(BarRenderer)类：<br />void setWallPaint(Paint paint) 3D坐标轴的墙体颜色<br /></p>
								<p>StackedBarRenderer(BarRenderer)类：<br />没有特殊的设置<br /></p>
								<p>StackedBarRenderer3D(BarRenderer3D)类：<br />没有特殊的设置<br /></p>
								<p>GroupedStackedBarRenderer(StackedBarRenderer)类：<br />void setSeriesToGroupMap(KeyToGroupMap map) 将分类自由的映射成若干个组（KeyToGroupMap.mapKeyToGroup(series,group)）<br /></p>
								<p>LayeredBarRenderer(BarRenderer)类：<br />void setSeriesBarWidth(int series,double width) 设定每个分类的宽度（注意设置不要使某分类被覆盖）<br /></p>
								<p>WaterfallBarRenderer(BarRenderer)类：<br />void setFirstBarPaint(Paint paint) 第一个柱图的颜色<br />void setLastBarPaint(Paint paint) 最后一个柱图的颜色<br />void setPositiveBarPaint(Paint paint) 正值柱图的颜色<br />void setNegativeBarPaint(Paint paint) 负值柱图的颜色<br /></p>
								<p>IntervalBarRenderer(BarRenderer)类：<br />需要传IntervalCategoryDataset作为数据源<br /></p>
								<p>GanttBarRenderer(IntervalBarRenderer)类：<br />void setCompletePaint(Paint paint) 完成进度颜色<br />void setIncompletePaint(Paint paint) 未完成进度颜色<br />void setStartPercent(double percent) 设置进度条在整条中的起始位置（0.0～1.0）<br />void setEndPercent(double percent) 设置进度条在整条中的结束位置（0.0～1.0）<br /></p>
								<p>StatisticBarRenderer(BarRenderer)类：<br />需要传StatisticCategoryDataset作为数据源<br /></p>
								<p>LineAndShapeRenderer(AbstractCategoryItemRenderer)类：<br />void setDrawLines(boolean draw) 是否折线的数据点之间用线连<br />void setDrawShapes(boolean draw) 是否折线的数据点根据分类使用不同的形状<br />void setShapesFilled(boolean filled) 所有分类是否填充数据点图形<br />void setSeriesShapesFilled(int series,boolean filled) 指定分类是否填充数据点图形<br />void setUseFillPaintForShapeOutline(boolean use) 指定是否填充数据点的Paint也被用于画数据点形状的边框<br /></p>
								<p>LevelRenderer(AbstractCategoryItemRenderer)类：<br />void setItemMargin(double percent) 每个分类之间的间隔<br />void setMaxItemWidth(double percent) 每个分类的最大宽度<br /></p>
								<p>CategoryStepRenderer(AbstractCategoryItemRenderer)类：<br />void setStagger(boolean shouldStagger) 不同分类的图是否交错<br /></p>
								<p>MinMaxCategoryRenderer(AbstractCategoryItemRenderer)类：<br />void setDrawLines(boolean drawLines) 是否在每个分类线间画连接线<br />void setGroupPaint(Paint groupPaint) 一组图形连接线的颜色<br />void setGroupStroke(Stroke groupStroke) 一组图形连接线的笔触<br />void setMaxIcon(Icon maxIcon) 最大值的ICON<br />void setMinIcon(Icon minIcon) 最小值的ICON<br />void setObjectIcon(Icon objectIcon) 所有值的ICON<br /></p>
								<p>AreaRender(AbstractCategoryItemRenderer)类：<br />没有特殊的设置<br /></p>
								<p>StackedAreaRender(AreaRender)类：<br />没有特殊的设置</p>
						</div>
				</div>
		</div>
<img src ="http://www.blogjava.net/lyjjq/aggbug/61324.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2006-08-02 12:39 <a href="http://www.blogjava.net/lyjjq/articles/61324.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>displaytag 改造后能一行显示多列,输出字段非常方便,还可以按需查询数据,而且原有功能不丢失</title><link>http://www.blogjava.net/lyjjq/articles/38396.html</link><dc:creator>强强</dc:creator><author>强强</author><pubDate>Fri, 31 Mar 2006 02:03:00 GMT</pubDate><guid>http://www.blogjava.net/lyjjq/articles/38396.html</guid><wfw:comment>http://www.blogjava.net/lyjjq/comments/38396.html</wfw:comment><comments>http://www.blogjava.net/lyjjq/articles/38396.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lyjjq/comments/commentRss/38396.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lyjjq/services/trackbacks/38396.html</trackback:ping><description><![CDATA[
		<p>&lt;%@ page contentType="text/html;charset=UTF-8" language="java"%&gt;<br />&lt;%@ taglib prefix="display" uri="displaytag"%&gt;<br />&lt;%@ taglib prefix="linktone" uri="linktonetag"%&gt;<br />&lt;%@ page<br /> import="com.lee.orderdish.util.ParamUtils,org.displaytag.sample.*,java.util.*,org.displaytag.tags.TableTag,com.linktone.taglib.displaytagpage.PageInfo"%&gt;<br />&lt;html&gt;<br />&lt;head&gt;<br />&lt;title&gt;Simple jsp page&lt;/title&gt;<br />&lt;link rel="stylesheet" href="&lt;%=request.getContextPath()%&gt;/css/style.css" type="text/css" /&gt;<br />&lt;/head&gt;</p>
		<p>&lt;body&gt;<br />&lt;%int currentPage = ParamUtils.getIntParameter(request,<br />     "currentPage", 1);</p>
		<p>   TestList list = new TestList(100, false);<br />   PageInfo pageInfo = new PageInfo();<br />   pageInfo.setMaxCount(100);<br />   pageInfo.setPageSize(6);<br />   pageInfo.setCurrentPage(currentPage);<br />   int startindex = pageInfo.getStart() - 1;<br />   int endindex = pageInfo.getEnd() &lt;= list.size() ? pageInfo.getEnd()<br />     : list.size();<br />   out.println("startIndex:" + startindex);<br />   out.println("endIndex:" + endindex);<br />   java.util.List subList = list.subList(startindex, endindex);</p>
		<p>   request.setAttribute("test", subList);<br />   int type = 1;<br />   int maxsize = 24;</p>
		<p>   %&gt;<br />&lt;center&gt;<br />&lt;linktone:displaywrap uid="aa" name="test" pagesize="6"<br /> maxsize="&lt;%=maxsize%&gt;" append="age=34&amp;type=1" requestURI="displaytagdemo.jsp" /&gt;<br /> <br />&lt;display:table uid="currentElement" name="test" pagesize="6"<br /> width="100%" class="Mars"&gt;<br /> &lt;display:column property="id" nowrap="true" title="ID" align="left" /&gt;<br /> &lt;display:column property="name" nowrap="true" title="名称" align="left" /&gt;<br /> &lt;display:column nowrap="true" title="编辑" align="left"&gt;<br />  &lt;a<br />   href="javascript:alert('&lt;%=((ListObject)currentElement).getId() %&gt;')"&gt;编辑&lt;/a&gt;<br /> &lt;/display:column&gt;<br />&lt;/display:table&gt;<br />&lt;display:table border="1" name="test" pagesize="6"<br /> rowsize="2" width="100%" class="Mars"&gt;<br /> &lt;table width="100%"&gt;<br />  &lt;tr&gt;<br />   &lt;td&gt;{id}&lt;/td&gt;<br />  &lt;/tr&gt;<br />  &lt;tr&gt;<br />   &lt;td&gt;{naMe}&lt;/td&gt;<br />  &lt;/tr&gt;<br />  &lt;tr&gt;<br />   &lt;td&gt;&lt;a href="javascript:alert('{naMe}')"&gt;编辑&lt;/a&gt;&lt;/td&gt;<br />  &lt;/tr&gt;<br /> &lt;/table&gt;<br />&lt;/display:table&gt;<br />&lt;linktone:displaywrap uid="aa" name="test" pagesize="6"<br /> maxsize="&lt;%=maxsize%&gt;" append="age=34&amp;type=1" requestURI="displaytagdemo.jsp" /&gt;<br />&lt;/center&gt;<br />&lt;/body&gt;<br />&lt;/html&gt;<br /><font color="#ff3333">该文件源代码在:</font><a href="/Files/lyjjq/displaytagdemo.rar">http://www.blogjava.net/Files/lyjjq/displaytagdemo.rar</a><br /><font color="#ff3333">用到的包和配置文件在:</font><a href="/Files/lyjjq/lib.jar">http://www.blogjava.net/Files/lyjjq/lib.rar</a></p>
<img src ="http://www.blogjava.net/lyjjq/aggbug/38396.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lyjjq/" target="_blank">强强</a> 2006-03-31 10:03 <a href="http://www.blogjava.net/lyjjq/articles/38396.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>