﻿<?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/hummer008/category/28088.html</link><description>不走寻常路,要走就走无间道</description><language>zh-cn</language><lastBuildDate>Sat, 30 Jul 2016 20:45:23 GMT</lastBuildDate><pubDate>Sat, 30 Jul 2016 20:45:23 GMT</pubDate><ttl>60</ttl><item><title>根据不同参数加载不同的配置文件 Spring ContextLoaderListener</title><link>http://www.blogjava.net/hummer008/articles/348683.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Thu, 21 Apr 2011 02:25:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/348683.html</guid><description><![CDATA[1. 重构 ContextLoaderListener ；<br />
2. 继承ContextLoader ，重写 protected WebApplicationContext createWebApplicationContext(<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ServletContext servletContext, ApplicationContext parent)<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throws BeansException {}；方法；<br />
<br />
code：<br />
<br />
public class ContextLoaderListener implements ServletContextListener {<br />
<br />
&nbsp;&nbsp;&nbsp; private ContextLoader contextLoader;<br />
<br />
<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp; &nbsp;* Initialize the root web application context.<br />
&nbsp;&nbsp;&nbsp; &nbsp;*/<br />
&nbsp;&nbsp;&nbsp; public void contextInitialized(ServletContextEvent event) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.contextLoader = createContextLoader();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.contextLoader.initWebApplicationContext(event.getServletContext());<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp; &nbsp;* Create the ContextLoader to use. Can be overridden in subclasses.<br />
&nbsp;&nbsp;&nbsp; &nbsp;* @return the new ContextLoader<br />
&nbsp;&nbsp;&nbsp; &nbsp;*/<br />
&nbsp;&nbsp;&nbsp; protected ContextLoader createContextLoader() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return new CasContextLoader();<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp; &nbsp;* Return the ContextLoader used by this listener.<br />
&nbsp;&nbsp;&nbsp; &nbsp;* @return the current ContextLoader<br />
&nbsp;&nbsp;&nbsp; &nbsp;*/<br />
&nbsp;&nbsp;&nbsp; public ContextLoader getContextLoader() {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return this.contextLoader;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
<br />
&nbsp;&nbsp;&nbsp; /**<br />
&nbsp;&nbsp;&nbsp; &nbsp;* Close the root web application context.<br />
&nbsp;&nbsp;&nbsp; &nbsp;*/<br />
&nbsp;&nbsp;&nbsp; public void contextDestroyed(ServletContextEvent event) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (this.contextLoader != null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; this.contextLoader.closeWebApplicationContext(event.getServletContext());<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
}<br />
<br />
<br />
public class CasContextLoader extends ContextLoader {<br />
<br />
&nbsp;&nbsp;&nbsp; protected WebApplicationContext createWebApplicationContext(<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ServletContext servletContext, ApplicationContext parent)<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throws BeansException {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
//&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return super.createWebApplicationContext(servletContext, parent);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Class contextClass = determineContextClass(servletContext);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; throw new ApplicationContextException("Custom context class [" + contextClass.getName() +<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ConfigurableWebApplicationContext wac =<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; wac.setParent(parent);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; wac.setServletContext(servletContext);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String configLocation = servletContext.getInitParameter(CONFIG_LOCATION_PARAM);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String flag=CasConstants.IS_USE_MEMCACHED;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (configLocation != null) {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String[] xml=StringUtils.tokenizeToStringArray(configLocation,ConfigurableWebApplicationContext.CONFIG_LOCATION_DELIMITERS);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if(flag!=null &amp;&amp; flag.equalsIgnoreCase("true")){<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String[] new_xml=StringUtils.addStringToArray(xml, "/WEB-INF/cas_memcached.xml");<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; wac.setConfigLocations(new_xml);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }else{<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; wac.setConfigLocations(xml);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; wac.refresh();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return wac;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
}<br />
<br />
<br />
<img src ="http://www.blogjava.net/hummer008/aggbug/348683.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2011-04-21 10:25 <a href="http://www.blogjava.net/hummer008/articles/348683.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>eclipse 快捷键使用总结</title><link>http://www.blogjava.net/hummer008/articles/271707.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Wed, 20 May 2009 06:06:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/271707.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/271707.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/271707.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/271707.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/271707.html</trackback:ping><description><![CDATA[1、查看打开文件 Ctr + e <br />
<br />
2、查找选中的下一个:Ctr+k，反查:Ctr+Shift+k<br />
<br />
3、大小写转化：Ctr+Shift+X Ctr+Shift+Y<br />
<br />
4、ctrl+t（ctrl+t+t） 查看类或方法的继承结构 <br />
<br />
5、ctrl+shift+u 查看变量在哪里被引用了 <br />
<br />
6、ctrl+shift+g（alt+shift+h） 查看方法在哪里被调用了 <br />
<br />
7、ctrl+l 定位行号 <br />
<br />
8、选中类名 点击Edit 选择 Copy qualified Name 可以把类的完整路径copy下来 同样对方法名也适用<br />
<br />
9、Go to Next/Last Member&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Ctrl+Shift+Down/Up<br />
<br />
10、Copy Lines&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Ctrl+Alt+Down/Up<br />
<br />
11、ctrl+r,查找资源文件<br />
<br />
12、ctrl+t 查看类实现<br />
<br />
13、ctrl+shift+f 代码格式化
<img src ="http://www.blogjava.net/hummer008/aggbug/271707.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2009-05-20 14:06 <a href="http://www.blogjava.net/hummer008/articles/271707.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>采用p6spy完整显示hibernate的SQL语句 (OK)</title><link>http://www.blogjava.net/hummer008/articles/236432.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Fri, 24 Oct 2008 08:22:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/236432.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/236432.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/236432.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/236432.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/236432.html</trackback:ping><description><![CDATA[虽然在hibernate中有show_sql选项，但是显示出来的语句大多类似<br />
&nbsp;&nbsp;&nbsp; select * from xxx where value=?<br />
&nbsp;&nbsp;&nbsp; 但是有时候我们需要得到完整的SQL语句，怎么办呢？使用P6SPY就可以完成这个任务
<p>&nbsp;&nbsp;&nbsp; p6spy是一个开源软件，它可以跟踪任何使用jdbc的应用产生的数据库操作。特别适合于监控ejb服务器产生的 sql statements。<br />
&nbsp;&nbsp;&nbsp; 官方网址：<a href="http://www.p6spy.com/">http://www.p6spy.com/</a><br />
&nbsp;&nbsp;&nbsp; 目前p6spy 适用的应用服务器包括jboss, atg, orion, jonas, iplanet, weblogic, websphere, resin and tomcat.</p>
<p>下面我介绍一下p6spy在tomcat应用程序上安装的步骤：<br />
（1）<a href="http://www.p6spy.com/download.html">http://www.p6spy.com/download.html</a>，下载zip包<br />
（2）解压出p6spy.jar spy.properties两个文件<br />
（3）将p6spy.jar 放入应用程序的WEB-INF/lib目录，将spy.properties放入WEB-INF/classes目录<br />
（4）修改spy.properties</p>
<p>&nbsp;&nbsp;&nbsp; realdriver&nbsp; =com.mysql.jdbc.Driver&nbsp; 将这行前面的#去掉<br />
&nbsp;&nbsp;&nbsp; logfile&nbsp;&nbsp;&nbsp;&nbsp; = c:/spy.log&nbsp; 修改一个你需要的日志文件名<br />
&nbsp;&nbsp;&nbsp; <br />
（5）修改hibernate.xml，修改connection.driver_class的值为com.p6spy.engine.spy.P6SpyDriver<br />
（6）重启tomcat<br />
（7）这样在c:/下的spy.log记录了数据库的访问情况。</p>
<img src ="http://www.blogjava.net/hummer008/aggbug/236432.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-10-24 16:22 <a href="http://www.blogjava.net/hummer008/articles/236432.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>查询性能问题 </title><link>http://www.blogjava.net/hummer008/articles/235651.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Tue, 21 Oct 2008 05:54:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/235651.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/235651.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/235651.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/235651.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/235651.html</trackback:ping><description><![CDATA[<p>1.传递一组agent_id 提高SQL性能，不要一次传递一个agent_id</p>
<p>select agent_id agentId ,count(service_type) counts, sum(time_to_sec(end_time)-time_to_sec</p>
<p>(start_time)) seconds from et_service_log where service_type=? and site_id=? and agent_id in (?, ?, </p>
<p>?, ?, ?, ?, ?, ?, ?, ?)&nbsp; group by agent_id </p>
<p>SQLQuery sqlQuery = this.getSession().createSQLQuery(conditionSql);<br />
sqlQuery.setParameterList("agentId", agentIdList);</p>
<p>2.主从明细表关系查询优化<br />
&nbsp;<br />
普遍方法是 先查询主表IDLIST,再通过每个ID,获取一组明细表中的数据<br />
优化方法是 主从表 LEFT JOIN 一次执行就可以把相关数据RESRARCH</p>
<p>CODE ：<br />
&nbsp;Criteria criteria = createCriteria(MessageCategory.class)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add(Restrictions.eq("entityPk.siteId", siteId))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .add(Restrictions.eq("deleted", false));<br />
&nbsp;&nbsp; criteria.createAlias("messageContentSet", </p>
<p>"messageContentSet",JoinFragment.LEFT_OUTER_JOIN).setFetchMode("messageContentSet", </p>
<p>FetchMode.JOIN).add(<br />
&nbsp;&nbsp;&nbsp;&nbsp; Restrictions.eq("messageContentSet.deleted", false)).addOrder</p>
<p>(Order.desc("entityPk.id"));<br />
&nbsp;&nbsp; List listData=criteria.list();&nbsp;&nbsp; <br />
&nbsp;&nbsp; Set set =new HashSet(listData); (* 过滤重复数据)<br />
</p>
<img src ="http://www.blogjava.net/hummer008/aggbug/235651.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-10-21 13:54 <a href="http://www.blogjava.net/hummer008/articles/235651.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hashMap 便捷遍历</title><link>http://www.blogjava.net/hummer008/articles/234387.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Wed, 15 Oct 2008 02:43:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/234387.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/234387.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/234387.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/234387.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/234387.html</trackback:ping><description><![CDATA[<br />
<br />
@SuppressWarnings("unchecked")<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; public static void listHashMap() {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Map hashmap = new java.util.HashMap();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; for (int i = 0; i &lt; 10; i++ ) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; hashmap.put(""+i, "thanks"+i);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; java.util.Iterator it = hashmap.entrySet().iterator();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; while (it.hasNext()) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; java.util.Map.Entry entry = (java.util.Map.Entry) it.next();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println(entry.getValue());<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @SuppressWarnings("unchecked")<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; public static void newlistHashMap() {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Map hashmap = new java.util.HashMap();<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; for (int i = 0; i &lt; 10; i++ ) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; hashmap.put(""+i, "thanks"+i);<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; }<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Set set = hashmap.entrySet();&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; for (Object obj : set) {<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Map.Entry e =(Map.Entry)obj;<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; System.out.println(e.getKey()+":"+e.getValue());<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />
<br />
<img src ="http://www.blogjava.net/hummer008/aggbug/234387.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-10-15 10:43 <a href="http://www.blogjava.net/hummer008/articles/234387.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>dwr session error问题解决</title><link>http://www.blogjava.net/hummer008/articles/226013.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Mon, 01 Sep 2008 02:01:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/226013.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/226013.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/226013.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/226013.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/226013.html</trackback:ping><description><![CDATA[&nbsp;前台页面跳出session error的对话框<br />
而控制台则输出:<br />
2007-5-29 11:58:53 org.directwebremoting.util.CommonsLoggingOutput error<br />
严重: A request has been denied as a potential CSRF attack.<br />
的错误信息.<br />
请求被拒绝因为可能存在csrf(cross-site request forgeries,跨站请求伪造)攻击.<br />
也就是说页面URL可能被跨站了的服务所调用.<br />
<br />
------解决方法:<br />
<br />
<p>在web.xml配置文件中..<br />
dwr的配置<br />
</p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">servlet</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">servlet-name</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">dwr-invoker</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">servlet-name</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">servlet-class</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">org.directwebremoting.servlet.DwrServlet</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">servlet-class</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">init-param</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">param-name</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">debug</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">param-name</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">param-value</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">true</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">param-value</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">init-param</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">init-param</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">param-name</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">crossDomainSessionSecurity</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">param-name</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">param-value</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">false</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">param-value</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">init-param</span><span style="color: rgb(0,0,255)">&gt;</span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;</span><span style="color: rgb(0,0,255)">&lt;/</span><span style="color: rgb(128,0,0)">servlet</span><span style="color: rgb(0,0,255)">&gt;</span></div>
</div>
<p><br />
加入corssDomainSessionSecurity这个配置选项..这个参数是在dwr版本2.0才有的.默认值为true,也就是</p>
禁止其他域发送请求.<br />
corssDomainSessionSecurity:设置成false能够从其他域进行请求.注意这样做会在安全性上有一些冒险.
<img src ="http://www.blogjava.net/hummer008/aggbug/226013.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-09-01 10:01 <a href="http://www.blogjava.net/hummer008/articles/226013.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>业务层中使用拦截器</title><link>http://www.blogjava.net/hummer008/articles/222271.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Fri, 15 Aug 2008 07:38:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/222271.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/222271.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/222271.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/222271.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/222271.html</trackback:ping><description><![CDATA[第一部分 拦截器实现:<br />
&nbsp; <br />
<p>package com.infowarelab.cem.easytouch.web.interceptor;</p>
<p>import java.lang.reflect.Method;</p>
<p>import org.aopalliance.intercept.MethodInterceptor;<br />
import org.aopalliance.intercept.MethodInvocation;<br />
import org.springframework.beans.factory.InitializingBean;</p>
<p>import com.infowarelab.cem.easytouch.service.cache.JbossCache;<br />
import com.infowarelab.common.log.Log;<br />
import com.infowarelab.common.log.LogFactory;</p>
<p>public class FlushGroupCacheInterceptor implements MethodInterceptor,</p>
<p>InitializingBean {</p>
<p>&nbsp;protected Log log = LogFactory.getLog(FlushGroupCacheInterceptor.class);</p>
<p>&nbsp;private static final long serialVersionUID = 2366041803410037545L;</p>
<p>&nbsp;private JbossCache cache;</p>
<p>&nbsp;private Integer siteId;</p>
<p>&nbsp;public void setCache(JbossCache cache) {</p>
<p>&nbsp;&nbsp;this.cache = cache;<br />
&nbsp;}</p>
<p>&nbsp;public Object invoke(MethodInvocation invocation) throws Throwable {</p>
<p>&nbsp;&nbsp;Object result = invocation.proceed();</p>
<p>&nbsp;&nbsp;flushGroupCache(invocation);</p>
<p>&nbsp;&nbsp;return result;</p>
<p>&nbsp;}</p>
<p>&nbsp;private void flushGroupCache(MethodInvocation invocation)<br />
&nbsp;&nbsp;&nbsp;throws NoSuchMethodException {</p>
<p>&nbsp;&nbsp;// extends ActionSupport<br />
&nbsp;&nbsp;// HttpSession session = ServletActionContext.getRequest().getSession();<br />
&nbsp;&nbsp;// String<br />
&nbsp;&nbsp;// siteId=(String)session.getAttribute(CEMConstants.SESSION_KEY_SITE_ID);</p>
<p>&nbsp;&nbsp;siteId = Context.getCurrentSiteId();</p>
<p>&nbsp;&nbsp;if (siteId == null) {<br />
&nbsp;&nbsp;&nbsp;return;<br />
&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;String methodName = invocation.getMethod().getName();</p>
<p>&nbsp;&nbsp;log.info("--------------------");<br />
&nbsp;&nbsp;log.info("methodName:" + methodName);<br />
&nbsp;&nbsp;log.info("--------------------");</p>
<p>&nbsp;&nbsp;Class[] paramsType = invocation.getMethod().getParameterTypes();</p>
<p>&nbsp;&nbsp;Class methodNameClass = invocation.getThis().getClass();</p>
<p>&nbsp;&nbsp;Method m = methodNameClass.getMethod(methodName, paramsType);</p>
<p>&nbsp;&nbsp;boolean flag = m.isAnnotationPresent(OsCacheFlushGroupName.class);<br />
&nbsp;&nbsp;if (flag) {<br />
&nbsp;&nbsp;&nbsp;OsCacheFlushGroupName groupName = m<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getAnnotation(OsCacheFlushGroupName.class);<br />
&nbsp;&nbsp;&nbsp;log.info("--------------------");<br />
&nbsp;&nbsp;&nbsp;log.info("groupName:" + "" + siteId + groupName.value());<br />
&nbsp;&nbsp;&nbsp;log.info("--------------------");<br />
&nbsp;&nbsp;&nbsp;cache.flushGroup("" + siteId + groupName.value());<br />
&nbsp;&nbsp;}<br />
&nbsp;}</p>
<p>&nbsp;public void afterPropertiesSet() throws Exception {</p>
<p>&nbsp;&nbsp;// TODO Auto-generated method stub</p>
<p>&nbsp;}<br />
}<br />
<br />
第2部分:web层数据传递<br />
</p>
<p>package com.infowarelab.cem.easytouch.web.interceptor;</p>
<p>public class Context {</p>
<p>&nbsp; private static ThreadLocal&lt;Integer&gt; currentSiteId = new ThreadLocal&lt;Integer&gt;();&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Context(){}&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //这个方法由Filter在请求达到时根据会话(e.g HttpSession，但不限于HttpSession)情况调用设置&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void setCurrentSiteId(Integer siteId) {&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; currentSiteId.set(siteId);&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //这个方法，可被同一JVM中的任何其他方法调用。&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //返回当前请求者的Id，没有登录，则返回null&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static Integer getCurrentSiteId() {&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return currentSiteId.get();&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
}<br />
</p>
<p><br />
第3部分:web层数据传递通过filter,或web层Interceptor实现<br />
</p>
<p>package com.infowarelab.cem.easytouch.filter;</p>
<p>import java.io.IOException;</p>
<p>import javax.servlet.Filter;<br />
import javax.servlet.FilterChain;<br />
import javax.servlet.FilterConfig;<br />
import javax.servlet.ServletException;<br />
import javax.servlet.ServletRequest;<br />
import javax.servlet.ServletResponse;<br />
import javax.servlet.http.HttpServletRequest;<br />
import javax.servlet.http.HttpSession;</p>
<p>import com.infowarelab.cem.common.util.CEMConstants;<br />
import com.infowarelab.cem.easytouch.web.interceptor.Context;</p>
<p>public class SiteIdFilter implements Filter {</p>
<p>&nbsp;public void destroy() {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub</p>
<p>&nbsp;}</p>
<p>&nbsp;public void doFilter(ServletRequest request, ServletResponse response,<br />
&nbsp;&nbsp;&nbsp;FilterChain filterChain) throws IOException, ServletException {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub</p>
<p>&nbsp;&nbsp;setSiteIdToContext(request);<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;filterChain.doFilter(request, response);<br />
&nbsp;}</p>
<p>&nbsp;private void setSiteIdToContext(ServletRequest request) {<br />
&nbsp;&nbsp;String siteId = "";<br />
&nbsp;&nbsp;HttpServletRequest req = (HttpServletRequest) request;</p>
<p>&nbsp;<br />
&nbsp;&nbsp;HttpSession session = req.getSession();<br />
&nbsp;&nbsp;if (session.getAttribute(CEMConstants.SESSION_KEY_SITE_ID) != null) {<br />
&nbsp;&nbsp;&nbsp;siteId = (String) session<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getAttribute(CEMConstants.SESSION_KEY_SITE_ID);<br />
&nbsp;&nbsp;&nbsp;Context.setCurrentSiteId(new Integer(siteId));<br />
&nbsp;&nbsp;&nbsp;return;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;siteId = req.getParameter("siteId");<br />
&nbsp;&nbsp;if (siteId != null &amp;&amp; siteId.trim().length() &gt; 0) {<br />
&nbsp;&nbsp;&nbsp;Context.setCurrentSiteId(new Integer(siteId));<br />
&nbsp;&nbsp;&nbsp;return;<br />
&nbsp;&nbsp;}</p>
<p>&nbsp;}</p>
<p>&nbsp;public void init(FilterConfig config) throws ServletException {<br />
&nbsp;&nbsp;// TODO Auto-generated method stub</p>
<p>&nbsp;}</p>
<p>}<br />
</p>
<img src ="http://www.blogjava.net/hummer008/aggbug/222271.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-08-15 15:38 <a href="http://www.blogjava.net/hummer008/articles/222271.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java IP 解析</title><link>http://www.blogjava.net/hummer008/articles/219354.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Fri, 01 Aug 2008 07:28:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/219354.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/219354.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/219354.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/219354.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/219354.html</trackback:ping><description><![CDATA[******* 关注数值溢出问题 <br />
public class IPUtil {<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public static long IPToLong(String ipAddress)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String[]&nbsp;&nbsp; ipqi_ary=ipAddress.split("\\."); &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; long ip0= new Long(ipqi_ary[0]).longValue();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; long ip1= new Long(ipqi_ary[1]).longValue();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; long ip2= new Long(ipqi_ary[2]).longValue();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; long ip3= new Long(ipqi_ary[3]).longValue();<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return (ip0 &lt;&lt; 24) + (ip1 &lt;&lt; 16) + (ip2 &lt;&lt; 8) + ip3;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public static String LongToIP(long ipAddress)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; long ui1 = ipAddress &amp; 0xFF000000;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ui1 = ui1 &gt;&gt; 24;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; long ui2 = ipAddress &amp; 0x00FF0000;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ui2 = ui2 &gt;&gt; 16;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; long ui3 = ipAddress &amp; 0x0000FF00;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ui3 = ui3 &gt;&gt; 8;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; long ui4 = ipAddress &amp; 0x000000FF;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String IPstr = "";<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; IPstr = String.valueOf(ui1) + "." + String.valueOf(ui2) + "."<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; + String.valueOf(ui3) + "." + String.valueOf(ui4);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return IPstr;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; public static void&nbsp; main(String args[]){<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; String ipAddress="255.255.255.255";<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; long ipInt=IPUtil.IPToLong(ipAddress);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("String to int :"+ipInt);<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("int to String :"+IPUtil.LongToIP(ipInt));<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
}<br />
<br />
<img src ="http://www.blogjava.net/hummer008/aggbug/219354.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-08-01 15:28 <a href="http://www.blogjava.net/hummer008/articles/219354.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>相对路径 绝对路径(转)</title><link>http://www.blogjava.net/hummer008/articles/218735.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Wed, 30 Jul 2008 07:17:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/218735.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/218735.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/218735.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/218735.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/218735.html</trackback:ping><description><![CDATA[<span style="font-size: small"><strong>1.基本概念的理解</strong><br />
<br />
<span style="font-family: courier new,courier">绝对路径：绝对路径就是你的主页上的文件或目录在硬盘上真正的路径，(URL和物理路径)例如：<br />
C:xyz est.txt 代表了test.txt文件的绝对路径。http://www.sun.com/index.htm也代表了一个URL绝对路径。<br />
<br />
相对路径：相对与某个基准目录的路径。包含Web的相对路径（HTML中的相对目录），例如：在<br />
Servlet中，"/"代表Web应用的跟目录。和物理路径的相对表示。例如："./" 代表当前目录,"../"代表上级目录。这种类似的表示，也是属于相对路径。<br />
另外关于URI，URL,URN等内容，请参考RFC相关文档标准。<br />
<br />
RFC 2396: Uniform Resource Identifiers (URI): Generic Syntax,<br />
(http://www.ietf.org/rfc/rfc2396.txt)<br />
<br />
<br />
<strong>2.关于JSP/Servlet中的相对路径和绝对路径。</strong><br />
<br />
2.1服务器端的地址<br />
<br />
服务器端的相对地址指的是相对于你的web应用的地址，这个地址是在服务器端解析的（不同于html和javascript中的相对地址，他们是由客户端浏览器解析的）也就是说这时候在jsp和servlet中的相对地址应该是相对于你的web应用，即相对于http: //192.168.0.1/webapp/的。<br />
<br />
其用到的地方有：<br />
forward：servlet中的request.getRequestDispatcher(address);这个address是在服务器端解析的，所以，你要forward到a.jsp应该这么写：request.getRequestDispatcher(&#8220;/user/a.jsp&#8221;)这个/ 相对于当前的web应用webapp，其绝对地址就是：http://192.168.0.1/webapp/user/a.jsp。 sendRedirect：在jsp中&lt;%response.sendRedirect("/rtccp/user/a.jsp");%&gt;<br />
<br />
2.22、客户端的地址<br />
<br />
所有的html页面中的相对地址都是相对于服务器根目录(http://192.168.0.1/)的，而不是(跟目录下的该Web应用的目录) http://192.168.0.1/webapp/的。 Html中的form表单的action属性的地址应该是相对于服务器根目录(http://192.168.0.1/)的，所以，如果提交到a.jsp 为：action＝"/webapp/user/a.jsp"或action="&lt;%=request.getContextPath()% &gt;"/user/a.jsp；<br />
提交到servlet为actiom＝"/webapp/handleservlet" Javascript也是在客户端解析的，所以其相对路径和form表单一样。<br />
<br />
<br />
因此，一般情况下，在JSP/HTML页面等引用的CSS,Javascript.Action等属性前面最好都加上<br />
&lt;%=request.getContextPath()%&gt;,以确保所引用的文件都属于Web应用中的目录。另外，应该尽量避免使用类似".","./","../../"等类似的相对该文件位置的相对路径，这样当文件移动时，很容易出问题。<br />
<br />
<br />
<strong>3. JSP/Servlet中获得当前应用的相对路径和绝对路径<br />
<br />
</strong>3.1 JSP中获得当前应用的相对路径和绝对路径<br />
根目录所对应的绝对路径:request.getRequestURI()<br />
文件的绝对路径 　:application.getRealPath(request.getRequestURI());<br />
当前web应用的绝对路径 :application.getRealPath("/");<br />
取得请求文件的上层目录:new File(application.getRealPath(request.getRequestURI())).getParent()<br />
<br />
3.2 Servlet中获得当前应用的相对路径和绝对路径<br />
根目录所对应的绝对路径:request.getServletPath();<br />
文件的绝对路径 :request.getSession().getServletContext().getRealPath<br />
(request.getRequestURI())<br />
当前web应用的绝对路径 :servletConfig.getServletContext().getRealPath("/");<br />
(ServletContext对象获得几种方式：<br />
javax.servlet.http.HttpSession.getServletContext()<br />
javax.servlet.jsp.PageContext.getServletContext()<br />
javax.servlet.ServletConfig.getServletContext()<br />
)<br />
<br />
<strong>4.java 的Class中获得相对路径，绝对路径的方法<br />
<br />
</strong>4.1单独的Java类中获得绝对路径<br />
根据java.io.File的Doc文挡，可知:<br />
默认情况下new File("/")代表的目录为：System.getProperty("user.dir")。<br />
一下程序获得执行类的当前路径</span> <br />
</span>
<div class="dp-highlighter">
<div class="bar"><span style="font-size: small">&nbsp;</span></div>
<ol class="dp-j">
    <li class="alt"><span style="font-size: small; font-family: courier new,courier"><span><span class="keyword">package</span><span>&nbsp;org.cheng.file;&nbsp;&nbsp;</span></span></span></li>
    <li><span style="font-size: small; font-family: courier new,courier"><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span style="font-size: small; font-family: courier new,courier"><span><span class="keyword">import</span><span>&nbsp;java.io.File;&nbsp;&nbsp;</span></span></span></li>
    <li><span style="font-size: small; font-family: courier new,courier"><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span style="font-size: small; font-family: courier new,courier"><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;FileTest&nbsp;{&nbsp;&nbsp;</span></span></span></li>
    <li><span style="font-size: small; font-family: courier new,courier"><span>&nbsp;&nbsp;&nbsp;&nbsp;<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;Exception&nbsp;{&nbsp;&nbsp;</span></span></span></li>
    <li class="alt"><span style="font-size: small; font-family: courier new,courier"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(Thread.currentThread().<span class="hilite1"><span class="hilite1">getContextClassLoader</span></span>().getResource(<span class="string">""</span><span>));&nbsp;&nbsp;</span></span></span></li>
    <li><span style="font-size: small; font-family: courier new,courier"><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span style="font-size: small; font-family: courier new,courier"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(FileTest.<span class="keyword">class</span><span>.getClassLoader().getResource(</span><span class="string">""</span><span>));&nbsp;&nbsp;</span></span></span></li>
    <li><span style="font-size: small; font-family: courier new,courier"><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span style="font-size: small; font-family: courier new,courier"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(ClassLoader.getSystemResource(<span class="string">""</span><span>));&nbsp;&nbsp;</span></span></span></li>
    <li><span style="font-size: small; font-family: courier new,courier"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(FileTest.<span class="keyword">class</span><span>.getResource(</span><span class="string">""</span><span>));&nbsp;&nbsp;</span></span></span></li>
    <li class="alt"><span style="font-size: small; font-family: courier new,courier"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(FileTest.<span class="keyword">class</span><span>.getResource(</span><span class="string">"/"</span><span>));</span></span></span></li>
    <li class="alt"><span style="font-size: small; font-family: courier new,courier"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //</span></span></span><span style="font-family: courier new,courier">Class</span><span style="font-size: small; font-family: courier new,courier"><span><span class="comment">文件所在路径</span></span></span></li>
    <li><span style="font-size: small; font-family: courier new,courier"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(<span class="keyword">new</span><span>&nbsp;File(</span><span class="string">"/"</span><span>).getAbsolutePath());&nbsp;&nbsp;</span></span></span></li>
    <li class="alt"><span style="font-size: small; font-family: courier new,courier"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(System.getProperty(<span class="string">"user.dir"</span><span>));&nbsp;&nbsp;</span></span></span></li>
    <li><span style="font-size: small; font-family: courier new,courier"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span style="font-size: small"><span><span style="font-family: courier new,courier">}&nbsp; </span><br />
    </span></span></li>
</ol>
</div>
<span style="font-size: small"><br />
<span style="font-family: courier new,courier">4.2服务器中的Java类获得当前路径（来自网络）<strong><br />
<br />
</strong>(1).Weblogic<br />
<br />
WebApplication的系统文件根目录是你的weblogic安装所在根目录。<br />
例如：如果你的weblogic安装在c:eaweblogic700.....<br />
那么，你的文件根路径就是c:.<br />
所以，有两种方式能够让你访问你的服务器端的文件：<br />
a.使用绝对路径：<br />
比如将你的参数文件放在c:yourconfigyourconf.properties，<br />
直接使用 new FileInputStream("yourconfig/yourconf.properties");<br />
b.使用相对路径：<br />
相对路径的根目录就是你的webapplication的根路径，即WEB-INF的上一级目录，将你的参数文件放<br />
<br />
在yourwebappyourconfigyourconf.properties，<br />
这样使用：<br />
new FileInputStream("./yourconfig/yourconf.properties");<br />
这两种方式均可，自己选择。<br />
<br />
(2).Tomcat<br />
<br />
在类中输出System.getProperty("user.dir");显示的是%Tomcat_Home%/bin<br />
<br />
(3).Resin<br />
<br />
不是你的JSP放的相对路径,是JSP引擎执行这个JSP编译成SERVLET<br />
的路径为根.比如用新建文件法测试File f = new File("a.htm");<br />
这个a.htm在resin的安装目录下<br />
<br />
(4).如何读相对路径哪？<br />
<br />
在Java文件中getResource或getResourceAsStream均可<br />
<br />
例：getClass().getResourceAsStream(filePath);//filePath可以是"/filename",这里的/代表web<br />
<br />
发布根路径下WEB-INF/classes<br />
<br />
默认使用该方法的路径是：WEB-INF/classes。已经在Tomcat中测试。<br />
<br />
5.读取文件时的相对路径，避免硬编码和绝对路径的使用。（来自网络）<br />
5.1 采用Spring的DI机制获得文件，避免硬编码。<br />
参考下面的连接内容：<br />
<a href="http://www.javajia.net/viewtopic.php?p=90213&amp;" target="_blank">http://www.javajia.net/viewtopic.php?p=90213&amp;</a><br />
5.2 配置文件的读取<br />
参考下面的连接内容：<br />
<a href="http://dev.csdn.net/develop/article/39/39681.shtm" target="_blank">http://dev.csdn.net/develop/article/39/39681.shtm</a><br />
<br />
<strong>5.3 通过虚拟路径或相对路径读取一个xml文件，避免硬编码<br />
<br />
</strong>参考下面的连接内容：<br />
<a href="http://club.gamvan.com/club/clubPage.jsp?iPage=1&amp;tID=10708&amp;ccID=8" target="_blank">http://club.gamvan.com/club/clubPage.jsp?iPage=1&amp;tID=10708&amp;ccID=8</a><br />
<br />
6.Java中文件的常用操作（复制，移动，删除，创建等）（来自网络）<br />
常用 java File 操作类<br />
<a href="http://www.easydone.cn/014/200604022353065155.htm" target="_blank">http://www.easydone.cn/014/200604022353065155.htm</a><br />
<br />
Java文件操作大全（JSP中）<br />
<a href="http://www.pconline.com.cn/pcedu/empolder/gj/java/0502/559401.html" target="_blank">http://www.pconline.com.cn/pcedu/empolder/gj/java/0502/559401.html</a><br />
<br />
java文件操作详解（Java中文网）<br />
<a href="http://www.51cto.com/html/2005/1108/10947.htm" target="_blank">http://www.51cto.com/html/2005/1108/10947.htm</a><br />
<br />
JAVA 如何创建删除修改复制目录及文件<br />
<a href="http://www.gamvan.com/developer/java/2005/2/264.html" target="_blank">http://www.gamvan.com/developer/java/2005/2/264.html</a><br />
<br />
总结：<br />
通过上面内容的使用，可以解决在Web应用服务器端，移动文件，查找文件，复制<br />
删除文件等操作，同时对服务器的相对地址，绝对地址概念更加清晰。<br />
建议参考URI,的RFC标准文挡。同时对Java.io.File. Java.net.URI.等内容了解透彻<br />
对其他方面的理解可以更加深入和透彻。</span> </span>
<img src ="http://www.blogjava.net/hummer008/aggbug/218735.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-07-30 15:17 <a href="http://www.blogjava.net/hummer008/articles/218735.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java路径的最终解决方案(转)</title><link>http://www.blogjava.net/hummer008/articles/218725.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Wed, 30 Jul 2008 06:41:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/218725.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/218725.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/218725.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/218725.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/218725.html</trackback:ping><description><![CDATA[<table cellspacing="1" cellpadding="4" width="100%" border="0">
    <tbody>
        <tr>
            <td valign="top">
            <div class="subhead"><strong>ava路径的最终解决方案：相对路径寻址(1)</strong></div>
            </td>
        </tr>
        <tr>
            <td valign="top">
            <div class="content"></div>
            <p>　　Java中使用的路径，分为两种：绝对路径和相对路径。具体而言，又分为四种：</p>
            <p>　　一、URI形式的绝对资源路径</p>
            <p>　　如：file:/D:/java/eclipse32/workspace/jbpmtest3/bin/aaa.b</p>
            <p>　　URL是URI的特例。URL的前缀/协议，必须是Java认识的。URL可以打开资源，而URI则不行。</p>
            <p>　　URL和URI对象可以互相转换，使用各自的toURI(),toURL()方法即可！</p>
            <p>　　二、本地系统的绝对路径</p>
            <p>　　D:/java/eclipse32/workspace/jbpmtest3/bin/aaa.b</p>
            <p>　　Java.io包中的类，需要使用这种形式的参数。</p>
            <p>　　但是，它们一般也提供了URI类型的参数，而URI类型的参数，接受的是URI样式的String。因此，通过URI转换，还是可以把URI样式的绝对路径用在java.io包中的类中。</p>
            <p>　　三、相对于classpath的相对路径</p>
            <p>　　如：相对于</p>
            <p>　　file:/D:/java/eclipse32/workspace/jbpmtest3/bin/这个路径的相对路径。其中，bin是本项目的classpath。所有的Java源文件编译后的.class文件复制到这个目录中。</p>
            <p>　　四、相对于当前用户目录的相对路径</p>
            <p>　　就是相对于System.getProperty("user.dir")返回的路径。</p>
            <p>　　对于一般项目，这是项目的根路径。对于JavaEE服务器，这可能是服务器的某个路径。这个并没有统一的规范！</p>
            <p>　　所以，绝对不要使用&#8220;相对于当前用户目录的相对路径&#8221;。然而：</p>
            <p>　　默认情况下，java.io 包中的类总是根据当前用户目录来分析相对路径名。此目录由系统属性 user.dir 指定，通常是 Java 虚拟机的调用目录。</p>
            <p>　　这就是说，在使用java.io包中的类时，最好不要使用相对路径。否则，虽然在J2SE应用程序中可能还算正常，但是到了J2EE程序中，一定会出问题！而且这个路径，在不同的服务器中都是不同的！</p>
            </td>
        </tr>
    </tbody>
</table>
<!-- END TEMPLATE: print_content --><!-- BEGIN TEMPLATE: print_content -->
<table cellspacing="1" cellpadding="4" width="100%" border="0">
    <tbody>
        <tr>
            <td valign="top">
            <div class="subhead"><strong>Java路径的最终解决方案：相对路径寻址(2)</strong></div>
            </td>
        </tr>
        <tr>
            <td valign="top">
            <div class="content"></div>
            <p>　　相对路径最佳实践</p>
            <p>　　推荐使用相对于当前classpath的相对路径</p>
            <p>　　因此，我们在使用相对路径时，应当使用相对于当前classpath的相对路径。</p>
            <p>　　ClassLoader类的getResource(String name),getResourceAsStream(String name)等方法，使用相对于当前项目的classpath的相对路径来查找资源。</p>
            <p>　　读取属性文件常用到的ResourceBundle类的getBundle(String path)也是如此。</p>
            <p>　　通过查看ClassLoader类及其相关类的源代码，我发现，它实际上还是使用了URI形式的绝对路径。通过得到当前classpath的URI形式的绝对路径，构建了相对路径的URI形式的绝对路径。（这个实际上是猜想，因为JDK内部调用了SUN的源代码，而这些代码不属于JDK，不是开源的。）</p>
            <p>　　相对路径本质上还是绝对路径</p>
            <p>　　因此，归根结底，Java本质上只能使用绝对路径来寻找资源。所有的相对路径寻找资源的方法，都不过是一些便利方法。不过是API在底层帮助我们构建了绝对路径，从而找到资源的！</p>
            <p>　　得到classpath和当前类的绝对路径的一些方法</p>
            <p>　　下面是一些得到classpath和当前类的绝对路径的一些方法。你可能需要使用其中的一些方法来得到你需要的资源的绝对路径。</p>
            <p>　　1，FileTest.class.getResource("")</p>
            <p>　　得到的是当前类FileTest.class文件的URI目录。不包括自己！</p>
            <p>　　如：file:/D:/java/eclipse32/workspace/jbpmtest3/bin/com/test/</p>
            <p>　　2，FileTest.class.getResource("/")</p>
            <p>　　得到的是当前的classpath的绝对URI路径。</p>
            <p>　　如：file:/D:/java/eclipse32/workspace/jbpmtest3/bin/</p>
            <p>　　3，Thread.currentThread().getContextClassLoader().getResource("")</p>
            <p>　　得到的也是当前ClassPath的绝对URI路径。</p>
            </td>
        </tr>
    </tbody>
</table>
<!-- END TEMPLATE: print_content --><!-- BEGIN TEMPLATE: print_content -->
<table cellspacing="1" cellpadding="4" width="100%" border="0">
    <tbody>
        <tr>
            <td valign="top">
            <div class="subhead"><strong>Java路径的最终解决方案：相对路径寻址(3)</strong></div>
            </td>
        </tr>
        <tr>
            <td valign="top">
            <div class="content"></div>
            <p>　　如：file:/D:/java/eclipse32/workspace/jbpmtest3/bin/</p>
            <p>　　4，FileTest.class.getClassLoader().getResource("")</p>
            <p>　　得到的也是当前ClassPath的绝对URI路径。</p>
            <p>　　如：file:/D:/java/eclipse32/workspace/jbpmtest3/bin/</p>
            <p>　　5，ClassLoader.getSystemResource("")</p>
            <p>　　得到的也是当前ClassPath的绝对URI路径。</p>
            <p>　　如：file:/D:/java/eclipse32/workspace/jbpmtest3/bin/</p>
            <p>　　推荐使用Thread.currentThread().getContextClassLoader().getResource("")来得到当前的classpath的绝对路径的URI表示法。</p>
            <p>　　Web应用程序中资源的寻址</p>
            <p>　　上文中说过，当前用户目录，即相对于System.getProperty("user.dir")返回的路径。</p>
            <p>　　对于JavaEE服务器，这可能是服务器的某个路径，这个并没有统一的规范！</p>
            <p>　　而不是我们发布的Web应用程序的根目录！</p>
            <p>　　这样，在Web应用程序中，我们绝对不能使用相对于当前用户目录的相对路径。</p>
            <p>　　在Web应用程序中，我们一般通过ServletContext.getRealPath("/")方法得到Web应用程序的根目录的绝对路径。</p>
            <p>　　这样，我们只需要提供相对于Web应用程序根目录的路径，就可以构建出定位资源的绝对路径。</p>
            <p>　　这是我们开发Web应用程序时一般所采取的策略。</p>
            <p>　　通用的相对路径解决办法</p>
            <p>　　Java中各种相对路径非常多，不容易使用，非常容易出错。因此，我编写了一个便利方法，帮助更容易的解决相对路径问题。</p>
            <p>　　Web应用程序中使用JavaSE运行的资源寻址问题</p>
            <p>　　在JavaSE程序中，我们一般使用classpath来作为存放资源的目的地。但是，在Web应用程序中，我们一般使用classpath外面的WEB-INF及其子目录作为资源文件的存放地。</p>
            </td>
        </tr>
    </tbody>
</table>
<!-- END TEMPLATE: print_content --><!-- BEGIN TEMPLATE: print_content -->
<table cellspacing="1" cellpadding="4" width="100%" border="0">
    <tbody>
        <tr>
            <td valign="top">
            <div class="subhead"><strong>Java路径的最终解决方案：相对路径寻址(4)</strong></div>
            </td>
        </tr>
        <tr>
            <td valign="top">
            <div class="content"></div>
            <p>　　在Web应用程序中，我们一般通过ServletContext.getRealPath("/")方法得到Web应用程序的根目录的绝对路径。这样，我们只需要提供相对于Web应用程序根目录的路径，就可以构建出定位资源的绝对路径。</p>
            <p>　　Web应用程序，可以作为Web应用程序进行发布和运行。但是，我们也常常会以JavaSE的方式来运行Web应用程序的某个类的main方法。或者，使用JUnit测试。这都需要使用JavaSE的方式来运行。</p>
            <p>　　这样，我们就无法使用ServletContext.getRealPath("/")方法得到Web应用程序的根目录的绝对路径。</p>
            <p>　　而JDK提供的ClassLoader类，</p>
            <p>　　它的getResource(String name),getResourceAsStream(String name)等方法，使用相对于当前项目的classpath的相对路径来查找资源。</p>
            <p>　　读取属性文件常用到的ResourceBundle类的getBundle(String path)也是如此。</p>
            <p>　　它们都只能使用相对路径来读取classpath下的资源，无法定位到classpath外面的资源。</p>
            <p>　　Classpath外配置文件读取问题</p>
            <p>　　如，我们使用测试驱动开发的方法，开发Spring、Hibernate、iBatis等使用配置文件的Web应用程序，就会遇到问题。</p>
            <p>　　尽管Spring自己提供了FileSystem（也就是相对于user,dir目录）来读取Web配置文件的方法，但是终究不是很方便。而且与Web程序中的代码使用方式不一致！</p>
            <p>　　至于Hibernate，iBatis就更麻烦了！只有把配置文件移到classpath下，否则根本不可能使用测试驱动开发！</p>
            <p>　　怎么办？</p>
            <p>　　通用的相对路径解决办法</p>
            <p>　　面对这个问题，我决定编写一个助手类ClassLoaderUtil，提供一个便利方法[public static URL getExtendResource(String relativePath)]。在Web应用程序等一切Java程序中，需要定位classpath外的资源时，都使用这个助手类的便利方法，而不使用 Web应用程序特有的ServletContext.getRealPath("/")方法来定位资源。</p>
            </td>
        </tr>
    </tbody>
</table>
<!-- END TEMPLATE: print_content --><!-- BEGIN TEMPLATE: print_content -->
<table cellspacing="1" cellpadding="4" width="100%" border="0">
    <tbody>
        <tr>
            <td valign="top">
            <div class="subhead"><strong>Java路径的最终解决方案：相对路径寻址(5)</strong></div>
            </td>
        </tr>
        <tr>
            <td valign="top">
            <div class="content"></div>
            <p>　　利用classpath的绝对路径，定位所有资源</p>
            <p>　　这个便利方法的实现原理，就是&#8220;利用classpath的绝对路径，定位所有资源&#8221;。</p>
            <p>　　ClassLoader类的getResource("")方法能够得到当前classpath的绝对路径，这是所有Java程序都拥有的能力，具有最大的适应性！</p>
            <p>　　而目前的JDK提供的ClassLoader类的getResource(String 相对路径)方法，只能接受一般的相对路径。这样，使用ClassLoader类的getResource(String 相对路径)方法就只能定位到classpath下的资源。</p>
            <p>　　如果，它能够接受&#8220;../&#8221;这样的参数，允许我们用相对路径来定位classpath外面的资源，那么我们就可以定位位置的资源！</p>
            <p>　　当然，我无法修改ClassLoader类的这个方法，于是，我编写了一个助手类ClassLoaderUtil类，提供了[public static URL getExtendResource(String relativePath)]这个方法。它能够接受带有&#8220;../&#8221;符号的相对路径，实现了自由寻找资源的功能。</p>
            <p>　　通过相对classpath路径实现自由寻找资源的助手类的源代码：</p>
            <code>import java.io.IOException;<br />
            import java.io.InputStream;<br />
            import java.net.MalformedURLException;<br />
            import java.net.URL;<br />
            import java.util.Properties;<br />
            import org.apache.commons.logging.Log;<br />
            import org.apache.commons.logging.LogFactory;<br />
            /**<br />
            *@author沈东良shendl_s@hotmail.com<br />
            *Nov29,2006 10:34:34AM<br />
            *用来加载类，classpath下的资源文件，属性文件等。<br />
            *getExtendResource(StringrelativePath)方法，<br />
            *可以使用../符号来加载classpath外部的资源。<br />
            */<br />
            publicclass ClassLoaderUtil {<br />
            　　privatestatic Log log=LogFactory.getLog(ClassLoaderUtil.class);<br />
            　　/**<br />
            　　 *Thread.currentThread().getContextClassLoader().getResource("")<br />
            　　 */<br />
            　　<br />
            　　/**<br />
            　　 *加载Java类。 使用全限定类名<br />
            　　 *@paramclassName<br />
            　　 *@return<br />
            　　 */<br />
            　　publicstatic Class loadClass(String className) {<br />
            　　　　try {<br />
            　　　　　return getClassLoader().loadClass(className);<br />
            　　　　} catch (ClassNotFoundException e) {<br />
            　　　　　thrownew RuntimeException("class not found '"+className+"'", e);<br />
            　　　　}<br />
            　　 }<br />
            　　 /**<br />
            　　　 *得到类加载器<br />
            　　　 *@return<br />
            　　　 */<br />
            　　 publicstatic ClassLoader getClassLoader() {<br />
            　　<br />
            　　　　return ClassLoaderUtil.class.getClassLoader();<br />
            　　 }<br />
            　　 /**<br />
            　　　 *提供相对于classpath的资源路径，返回文件的输入流<br />
            　　　 *@paramrelativePath必须传递资源的相对路径。<br />
            　　　 *@是相对于classpath的路径。<br />
            　　　 *@如果需要查找classpath外部的资源，需要使用../来查找<br />
            　　　 *@return 文件输入流<br />
            　　 *@throwsIOException<br />
            　　 *@throwsMalformedURLException<br />
            　　　 */<br />
            　　 publicstatic InputStream getStream(String relativePath)<br />
            throws MalformedURLException, IOException {<br />
            　　　　 if(!relativePath.contains("../")){<br />
            　　　　　return getClassLoader().getResourceAsStream(relativePath);<br />
            　　　　　　<br />
            　　　　 }else{<br />
            　　　　　return ClassLoaderUtil.getStreamByExtendResource(relativePath);<br />
            　　　　 }<br />
            　　　　<br />
            　　 }<br />
            　　 /**<br />
            　　　 *<br />
            　　　 *@paramurl<br />
            　　　 *@return<br />
            　　　 *@throwsIOException<br />
            　　　 */<br />
            　　 publicstatic InputStream getStream(URL url) throws IOException{<br />
            　　　　 if(url!=null){<br />
            　　　　　　<br />
            　　　　　　　　return url.openStream();<br />
            　　　　　　<br />
            　　　　　　<br />
            　　　　 }else{<br />
            　　　　　　 returnnull;<br />
            　　　　 }<br />
            　　 }<br />
            　　 /**<br />
            　　　 *<br />
            　　　 *@paramrelativePath必须传递资源的相对路径。是相对于classpath的路径。<br />
            　　　 *@如果需要查找classpath外部的资源，需要使用../来查找<br />
            　　　 *@return<br />
            　　　 *@throwsMalformedURLException<br />
            　　　 *@throwsIOException<br />
            　　　 */<br />
            　　 publicstatic InputStream getStreamByExtendResource(String relativePath)<br />
            throws MalformedURLException, IOException{<br />
            　　　　return ClassLoaderUtil.getStream(<br />
            ClassLoaderUtil.getExtendResource(relativePath));<br />
            　　　　<br />
            　　　　<br />
            　　 }<br />
            　　<br />
            　　　/**<br />
            　　　 *提供相对于classpath的资源路径，返回属性对象，它是一个散列表<br />
            　　　 *@paramresource<br />
            　　　 *@return<br />
            　　　 */<br />
            　　 publicstatic Properties getProperties(String resource) {<br />
            　　　　Properties properties = new Properties();<br />
            　　　　try {<br />
            　　　　properties.load(getStream(resource));<br />
            　　　　} catch (IOException e) {<br />
            　　　　thrownew RuntimeException("couldn't load properties file'"+resource+"'",e);<br />
            　　　　}<br />
            　　　　return properties;<br />
            　　 }<br />
            　　 /**<br />
            　　　 *得到本Class所在的ClassLoader的Classpat的绝对路径。<br />
            　　　 *URL形式的<br />
            　　　 *@return<br />
            　　　 */<br />
            　　 publicstatic String getAbsolutePathOfClassLoaderClassPath(){<br />
            　　　　<br />
            　　　　<br />
            　　　　 ClassLoaderUtil.log.info(<br />
            ClassLoaderUtil.getClassLoader().getResource("").toString());<br />
            　　　　 return ClassLoaderUtil.getClassLoader().getResource("").toString();<br />
            　　　　<br />
            　　 }<br />
            　　 /**<br />
            　　　 *<br />
            　　　 *@paramrelativePath 必须传递资源的相对路径。是相对于classpath的路径。<br />
            　　　 *@如果需要查找classpath外部的资源，需要使用../来查找<br />
            　　　 *@return资源的绝对URL<br />
            　　 *@throwsMalformedURLException<br />
            　　　 */<br />
            　　 publicstatic URL getExtendResource(String relativePath)<br />
            throws MalformedURLException{<br />
            　　<br />
            　　　　 ClassLoaderUtil.log.info("传入的相对路径："+relativePath) ;<br />
            　　　　 //ClassLoaderUtil.log.info(Integer.valueOf(relativePath.indexOf("../"))) ;<br />
            　　　　 if(!relativePath.contains("../")){<br />
            　　　　　　 return ClassLoaderUtil.getResource(relativePath);<br />
            　　　　　　<br />
            　　　　 }<br />
            　　　　 String classPathAbsolutePath=ClassLoaderUtil.getAbsolutePathOfClassLoaderClassPath();<br />
            　　　　 if(relativePath.substring(0, 1).equals("/")){<br />
            　　　　　　 relativePath=relativePath.substring(1);<br />
            　　　　 }<br />
            　　　　 ClassLoaderUtil.log.info(Integer.valueOf(relativePath.lastIndexOf("../"))) ;<br />
            　　　　<br />
            　　　　 String wildcardString=relativePath.substring(<br />
            0,relativePath.lastIndexOf("../")+3);<br />
            　　　　relativePath=relativePath.substring(relativePath.lastIndexOf("../")+3);<br />
            　　　　 int containSum=ClassLoaderUtil.containSum(wildcardString, "../");<br />
            　　　　 classPathAbsolutePath= ClassLoaderUtil.cutLastString(<br />
            classPathAbsolutePath, "/", containSum);<br />
            　　　　 String resourceAbsolutePath=classPathAbsolutePath+relativePath;<br />
            　　　　 ClassLoaderUtil.log.info("绝对路径："+resourceAbsolutePath) ;<br />
            　　　　 URL resourceAbsoluteURL=new URL(resourceAbsolutePath);<br />
            　　　　 return resourceAbsoluteURL;<br />
            　　 }<br />
            　　 /**<br />
            　　　*<br />
            　　　 *@paramsource<br />
            　　　 *@paramdest<br />
            　　　 *@return<br />
            　　　 */<br />
            　　 privatestaticint containSum(String source,String dest){<br />
            　　　　 int containSum=0;<br />
            　　　　 int destLength=dest.length();<br />
            　　　　 while(source.contains(dest)){<br />
            　　　　　　 containSum=containSum+1;<br />
            　　　　　　 source=source.substring(destLength);<br />
            　　　　　　<br />
            　　　　 }<br />
            　　　　<br />
            　　　　<br />
            　　　　 return containSum;<br />
            　　 }<br />
            　　 /**<br />
            　　　 *<br />
            　　　 *@paramsource<br />
            　　　 *@paramdest<br />
            　　　 *@paramnum<br />
            　　　 *@return<br />
            　　　 */<br />
            　　 privatestatic String cutLastString(String source,String dest,int num){<br />
            　　　　 // String cutSource=null;<br />
            　　　　 for(int i=0;i&lt;num;i++){<br />
            　　　　　　 source=source.substring(0, source.lastIndexOf(dest, source.length()-2)+1);<br />
            　　　　　　<br />
            　　　　　　<br />
            　　　　 }<br />
            　　　　　　　　<br />
            　　　　 return source;<br />
            　　 }<br />
            　　 /**<br />
            　　　 *<br />
            　　　 *@paramresource<br />
            　　　 *@return<br />
            　　　 */<br />
            　　　publicstatic URL getResource(String resource){<br />
            　　　ClassLoaderUtil.log.info("传入的相对于classpath的路径："+resource) ;<br />
            　　　　 return ClassLoaderUtil.getClassLoader().getResource(resource);<br />
            　　 }<br />
            　　　<br />
            　　/**<br />
            　　 *@paramargs<br />
            　　 *@throwsMalformedURLException<br />
            　　 */<br />
            　　publicstaticvoid main(String[] args)<br />
            throws MalformedURLException {<br />
            　　　　<br />
            　　　　　　//ClassLoaderUtil.getExtendResource("../spring/dao.xml");<br />
            　　　　//ClassLoaderUtil.getExtendResource("../../../src/log4j.properties");<br />
            　　　　ClassLoaderUtil.getExtendResource("log4j.properties");<br />
            　　　　<br />
            　　　　System.out.println(<br />
            ClassLoaderUtil.getClassLoader().getResource("log4j.properties").toString());<br />
            　　}<br />
            }</code>
            <p>&nbsp;</p>
            <p>&nbsp;</p>
            <p>　　后记</p>
            <p>　　ClassLoaderUtil类的public static URL getExtendResource(String relativePath)，虽然很简单，但是确实可以解决大问题。</p>
            <p>　　不过这个方法还是比较简陋的。我还想在未来有空时，进一步增强它的能力。比如，增加Ant风格的匹配符。用**代表多个目录，*代表多个字符，？代表一个字符。达到Spring那样的能力，一次返回多个资源的URL，进一步方便大家开发。</p>
            <p>　　总结：</p>
            <p>　　1.尽量不要使用相对于System.getProperty("user.dir")当前用户目录的相对路径。这是一颗定时炸弹，随时可能要你的命。</p>
            <p>　　2.尽量使用URI形式的绝对路径资源。它可以很容易的转变为URI,URL，File对象。</p>
            <p>　　3.尽量使用相对classpath的相对路径。不要使用绝对路径。使用上面ClassLoaderUtil类的public static URL getExtendResource(String relativePath)方法已经能够使用相对于classpath的相对路径定位所有位置的资源。</p>
            <p>　　4.绝对不要使用硬编码的绝对路径。因为，我们完全可以使用ClassLoader类的getResource("")方法得到当前classpath的绝对路径。</p>
            <p>　　使用硬编码的绝对路径是完全没有必要的！它一定会让你死的很难看！程序将无法移植！</p>
            <p>　　如果你一定要指定一个绝对路径，那么使用配置文件，也比硬编码要好得多！</p>
            <p>　　当然，我还是推荐你使用程序得到classpath的绝对路径来拼资源的绝对路径！</p>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/hummer008/aggbug/218725.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-07-30 14:41 <a href="http://www.blogjava.net/hummer008/articles/218725.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>滚动条位置设置</title><link>http://www.blogjava.net/hummer008/articles/216777.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Wed, 23 Jul 2008 01:29:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/216777.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/216777.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/216777.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/216777.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/216777.html</trackback:ping><description><![CDATA[1.设置窗口滚动条的位置：<br />
window.scroll(0,document.body.scrollHeight)<br />
<br />
例，在打开网页时让页面处于页面底端<br />
&lt;body &nbsp; onload="window.scroll(0,document.body.scrollHeight)"&gt;<br />
<br />
2.设置组件的滚动条的位置：<br />
<br />
假设有个输入框，id为TextArea1<br />
方法一：<br />
TextArea1.scrollTop=100;//滚动到输入框的100位置<br />
&nbsp;方法二：<br />
document.getElementById("TextArea1").scrollTop=document.getElementById("TextArea1").scrollHeight; //滚动到输入框的底端<br />
<br />
支持 IE 和 FF<br />
onmouseover="this.style.cursor='pointer'"
<img src ="http://www.blogjava.net/hummer008/aggbug/216777.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-07-23 09:29 <a href="http://www.blogjava.net/hummer008/articles/216777.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>js 实用总结</title><link>http://www.blogjava.net/hummer008/articles/214231.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Fri, 11 Jul 2008 05:03:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/214231.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/214231.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/214231.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/214231.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/214231.html</trackback:ping><description><![CDATA[1.动态创建DIV<br />
<br />
function appendImageDIV(){<br />
&nbsp;&nbsp;&nbsp; if ((etIE || etDOM)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var obody = document.getElementsByTagName('BODY').item(0);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var imageDIV = document.createElement("DIV");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; imageDIV.id = WEBTOUCH_IMAGE_DIV_ID;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; imageDIV.style.display = "none";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; imageDIV.style.position = "absolute";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; imageDIV.style.zIndex = 999999999;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obody.appendChild(imageDIV);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var content = '&lt;img src="'+DYNAMIC_AGENT_CHAT_URL+CHAT_OFF_IMAGE+'"&nbsp; id="'+TAG_FOR_IMAGE+'" /&gt;';<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; imageDIV.innerHTML = content;<br />
&nbsp;&nbsp;&nbsp; }<br />
}<br />
<br />
2.DIV 屏幕位置不变<br />
<br />
<p>&lt;div id="Float21789" style="position: absolute; z-index: 9; width: 190px; top: 200px;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; right: 3px;"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;center&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;div id="AD21789" style="width: 190px; height: 90px; text-align: center; float: none;"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;a href="http://forum.csdn.net/PointForum/Forum/PostTopic.aspx" target="_blank"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;img src="http://community.csdn.net/ui/homepage/images/questions.gif" alt="提问" style="width: 180px;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; height: 50px; padding-right: 3px;" /&gt;&lt;/a&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/div&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/center&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/div&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;script type="text/javascript" language="JavaScript"&gt;<br />
&nbsp;&nbsp;&nbsp; var csdnScrollTop=function(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return document.documentElement.scrollTop?document.documentElement.scrollTop:document.body.scrollTop;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; function mymove21789(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.getElementById("Float21789").style.top=csdnScrollTop()+300+'px';document.getElementById("Float21789").style.right=3+'px';setTimeout("mymove21789();",50);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mymove21789();<br />
&nbsp;&nbsp;&nbsp; &lt;/script&gt;</p>
3.为事件添加方法<br />
<br />
if (window.addEventListener) {<br />
&nbsp;&nbsp;&nbsp; window.addEventListener('scroll', playImgFloatPosition, false);<br />
&nbsp;&nbsp;&nbsp; window.addEventListener('resize', playImgFloatPosition, false);<br />
}<br />
&nbsp;if (window.attachEvent) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; window.attachEvent('onscroll', playImgFloatPosition);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; window.attachEvent('onresize', playImgFloatPosition);<br />
}<br />
<img src ="http://www.blogjava.net/hummer008/aggbug/214231.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-07-11 13:03 <a href="http://www.blogjava.net/hummer008/articles/214231.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>js编码处理(转)</title><link>http://www.blogjava.net/hummer008/articles/213910.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Thu, 10 Jul 2008 03:44:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/213910.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/213910.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/213910.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/213910.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/213910.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用 JS 中的 encodeURIComponent 或 encodeURI 方法。 说明： &nbsp; encodeURIComponent(String) 对传递参数进行设置。不编码字符有 71 个： ! ， ' ， ( ， ) ， * ， - ， . ， _ ， ~ ， 0-9 ， a-z ， ...&nbsp;&nbsp;<a href='http://www.blogjava.net/hummer008/articles/213910.html'>阅读全文</a><img src ="http://www.blogjava.net/hummer008/aggbug/213910.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-07-10 11:44 <a href="http://www.blogjava.net/hummer008/articles/213910.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>webwork资源访问方式</title><link>http://www.blogjava.net/hummer008/articles/211865.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Tue, 01 Jul 2008 05:12:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/211865.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/211865.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/211865.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/211865.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/211865.html</trackback:ping><description><![CDATA[先Action必须继承ActionSupport，因为ActionSupport实现了资源访问接口TextProvider，如果你不希望Action继承ActionSupport，那么必须自己实现TextProvider接口，以获得资源访问能力。
<p>webwork的JSP Tag提供了访问资源的方式，例如：</p>
<div class="code">
<div class="codeContent">
<div class="code-java">&lt;ww:text name=<span class="code-quote">"title"</span>/&gt;</div>
</div>
</div>
<p>对于资源文件中包含参数，可以嵌套参数Tag：</p>
<div class="code">
<div class="codeContent">
<div class="code-java">&lt;ww:text name=<span class="code-quote">"title"</span>&gt; &lt;ww:param&gt;Webwork&lt;/ww:param&gt; &lt;ww:param&gt;JSP Tag&lt;/ww:param&gt;&lt;/ww:text&gt;</div>
</div>
</div>
<p>由于webwork的view访问资源的方式，实际上是通过调用ognlStack堆栈栈顶的action对象的getText(...)方法实现的，所以我们可以直接运用这种方式，例如：</p>
<div class="code">
<div class="codeContent">
<div class="code-java">&lt;ww:textfield label=<span class="code-quote">"%{getText('title')}"</span> name=<span class="code-quote">"username"</span>/&gt;</div>
</div>
</div>
<p>由于JSP Tag不能嵌套，因此当遇到上面这种情况，需要在Tag里面访问资源的时候，我们就必须采用这种直接通过ognlStack访问action的方式</p>
<p>当我们使用FreeMakrer作为view的时候，两种方式都可以采用<br />
采用Tag方式：</p>
<div class="code">
<div class="codeContent">
<div class="code-java">&lt;@ww.text name=<span class="code-quote">"title"</span>/&gt;</div>
</div>
</div>
<div class="code">
<div class="codeContent">
<div class="code-java">&lt;@ww.text name=<span class="code-quote">"title"</span>&gt; &lt;@ww.param&gt;webwork&lt;/@ww.param&gt; &lt;@ww.param&gt;jsp tag&lt;/@ww.param&gt;&lt;/@ww.text&gt;</div>
</div>
</div>
<p>采用ognlStack方式：</p>
<div class="code">
<div class="codeContent">
<div class="code-java">${action.getText(<span class="code-quote">"title"</span>)}</div>
</div>
</div>
<p>对比两种方式：</p>
<div class="code">
<div class="codeContent">
<div class="code-java">&lt;@ww.textfield label=<span class="code-quote">"%{getText('title')}"</span> name=<span class="code-quote">"username"</span> /&gt;&lt;@ww.textfield label=<span class="code-quote">"${action.getText('title')}"</span> name=<span class="code-quote">"username"</span> /&gt;</div>
</div>
</div>
&nbsp;<br />
<img src ="http://www.blogjava.net/hummer008/aggbug/211865.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-07-01 13:12 <a href="http://www.blogjava.net/hummer008/articles/211865.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>maven2使用(一)</title><link>http://www.blogjava.net/hummer008/articles/210371.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Tue, 24 Jun 2008 11:26:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/210371.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/210371.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/210371.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/210371.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/210371.html</trackback:ping><description><![CDATA[<p>1.maven2使用(一)</p>
<p>(1) 下载开源项目(POM.XML) d:\untils<br />
(2) 进入 d:\untils 然后 mvn eclipse:eclipse<br />
(3) 导入工程 (建立包依赖关系)<br />
(4) 如果部分插件下载不了,可以直接靠到相应目录(m2仓库),POM.XML添加相应的插件项目<br />
(5)添加CLASSPATH 变量</p>
<img src ="http://www.blogjava.net/hummer008/aggbug/210371.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-06-24 19:26 <a href="http://www.blogjava.net/hummer008/articles/210371.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>代理机制学习</title><link>http://www.blogjava.net/hummer008/articles/209059.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Thu, 19 Jun 2008 01:06:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/209059.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/209059.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/209059.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/209059.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/209059.html</trackback:ping><description><![CDATA[<p>&nbsp;<a title="代理机制" href="/Files/hummer008/proxy.pdf">代理机制</a> </p>
<img src ="http://www.blogjava.net/hummer008/aggbug/209059.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-06-19 09:06 <a href="http://www.blogjava.net/hummer008/articles/209059.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA代理机制</title><link>http://www.blogjava.net/hummer008/articles/208855.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Wed, 18 Jun 2008 06:02:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/208855.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/208855.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/208855.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/208855.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/208855.html</trackback:ping><description><![CDATA[按照代理类的创建时期，代理类可分为两种。<br />
l 静态代理类：由程序员创建或由特定工具自动生成<br />
源代码，再对其编译。在程序运行前，代理类的.class文件就已经存在了。<br />
l 动态代理类：在程序运行时，运用反射机制动态创建而成。 <br />
<br />
<p>可以看出静态<span class="hilite1">代理</span>类有一个很不爽的缺点：当如果接口加一个方法（把上面所有的代码的注释给去掉），所有的实现类和<span class="hilite1">代理</span>类里都需要做个实现。这就增加了代码的复杂度。动态<span class="hilite1">代理</span>就可以避免这个缺点。</p>
<p>3 。动态<span class="hilite1">代理</span></p>
<p><font face="Arial">动态<span class="hilite1">代理</span>与普通的<span class="hilite1">代理</span>相比较，最大的好处是接口中声明的所有方法都被转移到一个集中的方法中处理（invoke），这样，在接口方法数量比较多的时候，我们可以进行灵活处理，而不需要像静态<span class="hilite1">代理</span>那样每一个方法进行中转。</font></p>
<p><font face="Arial">动态<span class="hilite1">代理</span>类<font color="#ff0000">只能<span class="hilite1">代理</span>接口</font>，<span class="hilite1">代理</span>类都需要实现InvocationHandler类，实现invoke方法。该invoke方法就是调用<font color="#ff0000">被<span class="hilite1">代理</span>接口</font>的所有方法时需要调用的，该invoke方法返回的值是<font color="#ff0000">被<span class="hilite1">代理</span>接口</font>的一个实现类</font></p>
代码实例:<br />
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">package</span><span>&nbsp;ttitfly.proxy;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span class="keyword">import</span><span>&nbsp;java.lang.reflect.InvocationHandler;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span class="keyword">import</span><span>&nbsp;java.lang.reflect.Method;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span class="keyword">import</span><span>&nbsp;java.lang.reflect.Proxy;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span class="comment">//动态<span class="hilite1">代理</span>类只能<span class="hilite1">代理</span>接口，<span class="hilite1">代理</span>类都需要实现InvocationHandler类，实现invoke方法。该invoke方法就是调用被<span class="hilite1">代理</span>接口的所有方法时需要调用的，该invoke方法返回的值是被<span class="hilite1">代理</span>接口的一个实现类&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;DynamicProxy&nbsp;</span><span class="keyword">implements</span><span>&nbsp;InvocationHandler{&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;Object&nbsp;object;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//绑定关系，也就是关联到哪个接口（与具体的实现类绑定）的哪些方法将被调用时，执行invoke方法。 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//Proxy.newProxyInstance的第三个参数是表明这些被拦截的方法执行时需要执行哪个InvocationHandler的invoke方法 </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;Object&nbsp;bindRelation(Object&nbsp;object){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.object&nbsp;=&nbsp;object;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;Proxy.newProxyInstance(object.getClass().getClassLoader(),&nbsp;object.getClass().getInterfaces(),</span><span class="keyword">this</span><span>);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//拦截关联的这个实现类的方法被调用时将被执行&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;Object&nbsp;invoke(Object&nbsp;proxy,&nbsp;Method&nbsp;method,&nbsp;Object[]&nbsp;args)&nbsp;</span><span class="keyword">throws</span><span>&nbsp;Throwable&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(</span><span class="string">"Welcome"</span><span>);&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;result&nbsp;=&nbsp;method.invoke(object,&nbsp;args);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;result;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>}&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span> </li>
</ol>
<p class="alt"><br />
&nbsp;</p>
<p>测试类：</p>
<div class="code_title">
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">package</span><span>&nbsp;ttitfly.proxy;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span>
    <li class=""><span>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;TestDynamicProxy&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</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;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HelloWorld&nbsp;helloWorld&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;HelloWorldImpl();&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DynamicProxy&nbsp;dp&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;DynamicProxy();&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//在这里绑定的是HelloWorld,也就是HelloWorld是被<span class="hilite1">代理</span>接口。所以绑定关系时，需要传递一个HelloWorld的实现类的实例化对象。&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HelloWorld&nbsp;helloWorld1&nbsp;=&nbsp;(HelloWorld)dp.bindRelation(helloWorld);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;helloWorld1.print();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;helloWorld1.say();&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//helloWorld2将不被拦截 </span><span>&nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HelloWorld&nbsp;helloWorld2&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;HelloWorldImpl(); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;helloWorld2.print();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;helloWorld2.say(); &nbsp;&nbsp;</span>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span>
    <li class=""><span>}&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span> </li>
</ol>
</div>
</div>
<img src ="http://www.blogjava.net/hummer008/aggbug/208855.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-06-18 14:02 <a href="http://www.blogjava.net/hummer008/articles/208855.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java annotation高级应用</title><link>http://www.blogjava.net/hummer008/articles/207702.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Fri, 13 Jun 2008 08:17:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/207702.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/207702.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/207702.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/207702.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/207702.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 原文:http://www.matrix.org.cn/resource/article/44/44062_Java+Annotation+Apt.html关键字:java,annotation,apt前言：前不久在matrix上先后发表了《java annotation 入门》、《java annotation 手册》两篇文章，比较全面的对java annotation的语法、原...&nbsp;&nbsp;<a href='http://www.blogjava.net/hummer008/articles/207702.html'>阅读全文</a><img src ="http://www.blogjava.net/hummer008/aggbug/207702.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-06-13 16:17 <a href="http://www.blogjava.net/hummer008/articles/207702.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Annotation入门(转)</title><link>http://www.blogjava.net/hummer008/articles/207699.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Fri, 13 Jun 2008 08:07:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/207699.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/207699.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/207699.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/207699.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/207699.html</trackback:ping><description><![CDATA[原文:[http://www.matrix.org.cn/resource/article/44/44048_Java+Annotation.html]http://www.matrix.org.cn/resource/article/44/44048_Java+Annotation.html[/url]<br />
关键字:Java,annotation,标注<br />
<br />
<br />
<span style="color: blue">摘要：</span><br />
本文针对java初学者或者annotation初次使用者全面地说明了annotation的使用方法、定义方式、分类。初学者可以通过以上的说明制作简单的annotation程序，但是对于一些高级的annotation应用（例如使用自定义annotation生成javabean映射xml文件）还需要进一步的研究和探讨。涉及到深入annotation的内容，作者将在后文《Java Annotation高级应用》中谈到。<br />
<br />
同时，annotation运行存在两种方式：运行时、编译时。上文中讨论的都是在运行时的annotation应用，但在编译时的annotation应用还没有涉及，<br />
<br />
<span style="color: blue">一、为什么使用Annotation：</span><br />
<br />
在JAVA应用中，我们常遇到一些需要使用模版代码。例如，为了编写一个JAX-RPC web service，我们必须提供一对接口和实现作为模版代码。如果使用annotation对远程访问的方法代码进行修饰的话，这个模版就能够使用工具自动生成。<br />
另外，一些API需要使用与程序代码同时维护的附属文件。例如，JavaBeans需要一个BeanInfo Class与一个Bean同时使用/维护，而EJB则同样需要一个部署描述符。此时在程序中使用annotation来维护这些附属文件的信息将十分便利而且减少了错误。<br />
<br />
<span style="color: blue">二、Annotation工作方式：</span><br />
<br />
在5.0 版之前的Java平台已经具有了一些ad hoc annotation机制。比如，使用transient修饰符来标识一个成员变量在序列化子系统中应被忽略。而@deprecated这个 javadoc tag也是一个ad hoc annotation用来说明一个方法已过时。从Java5.0版发布以来，5.0平台提供了一个正式的annotation功能：允许开发者定义、使用自己的annoatation类型。此功能由一个定义annotation类型的语法和一个描述annotation声明的语法，读取annotaion 的API，一个使用annotation修饰的class文件，一个annotation处理工具（apt）组成。<br />
annotation并不直接影响代码语义，但是它能够工作的方式被看作类似程序的工具或者类库，它会反过来对正在运行的程序语义有所影响。annotation可以从源文件、class文件或者以在运行时反射的多种方式被读取。<br />
当然annotation在某种程度上使javadoc tag更加完整。一般情况下，如果这个标记对java文档产生影响或者用于生成java文档的话，它应该作为一个javadoc tag；否则将作为一个annotation。<br />
<br />
<span style="color: blue">三、Annotation使用方法：</span><br />
<br />
<strong>1。类型声明方式：</strong><br />
通常，应用程序并不是必须定义annotation类型，但是定义annotation类型并非难事。Annotation类型声明于一般的接口声明极为类似，区别只在于它在interface关键字前面使用&#8220;@&#8221;符号。<br />
annotation 类型的每个方法声明定义了一个annotation类型成员，但方法声明不必有参数或者异常声明；方法返回值的类型被限制在以下的范围： primitives、String、Class、enums、annotation和前面类型的数组；方法可以有默认值。<br />
<br />
下面是一个简单的annotation类型声明：<br />
<strong>清单1:</strong><br />
<pre class="overflow" title="pre code"><br />
&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * Describes the Request-For-Enhancement(RFE) that led<br />
&nbsp;&nbsp;&nbsp;&nbsp; * to the presence of the annotated API element.<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;public @interface RequestForEnhancement {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;&nbsp;&nbsp;&nbsp;id();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String synopsis();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String engineer() default "[unassigned]"; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String date();&nbsp;&nbsp;&nbsp;&nbsp;default "[unimplemented]"; <br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</pre>
<br />
代码中只定义了一个annotation类型RequestForEnhancement。<br />
<br />
<strong>2。修饰方法的annotation声明方式：</strong><br />
annotation 是一种修饰符，能够如其它修饰符（如public、static、final）一般使用。习惯用法是annotaions用在其它的修饰符前面。 annotations由&#8220;@+annotation类型+带有括号的成员-值列表&#8221;组成。这些成员的值必须是编译时常量（即在运行时不变）。<br />
<br />
A：下面是一个使用了RequestForEnhancement annotation的方法声明：<br />
<strong>清单2:</strong><br />
<pre class="overflow" title="pre code"><br />
&nbsp;&nbsp;&nbsp;&nbsp;@RequestForEnhancement(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 2868724,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;synopsis = "Enable time-travel",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;engineer = "Mr. Peabody",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;date&nbsp;&nbsp;&nbsp;&nbsp; = "4/1/3007"<br />
&nbsp;&nbsp;&nbsp;&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;public static void travelThroughTime(Date destination) { ... }<br />
</pre>
<br />
<br />
B：当声明一个没有成员的annotation类型声明时，可使用以下方式：<br />
<strong>清单3:</strong><br />
<pre class="overflow" title="pre code"><br />
&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * Indicates that the specification of the annotated API element<br />
&nbsp;&nbsp;&nbsp;&nbsp; * is preliminary and subject to change.<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;public @interface Preliminary { }<br />
</pre>
<br />
<br />
作为上面没有成员的annotation类型声明的简写方式：<br />
<strong>清单4:</strong><br />
<pre class="overflow" title="pre code"><br />
&nbsp;&nbsp;&nbsp;&nbsp;@Preliminary public class TimeTravel { ... }<br />
</pre>
<br />
<br />
C：如果在annotations中只有唯一一个成员，则该成员应命名为value：<br />
<strong>清单5:</strong><br />
<pre class="overflow" title="pre code"><br />
&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * Associates a copyright notice with the annotated API element.<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;public @interface Copyright {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String value();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</pre>
<br />
<br />
更为方便的是对于具有唯一成员且成员名为value的annotation（如上文），在其使用时可以忽略掉成员名和赋值号（=）：<br />
<strong>清单6:</strong><br />
<pre class="overflow" title="pre code"><br />
&nbsp;&nbsp;&nbsp;&nbsp;@Copyright("2002 Yoyodyne Propulsion Systems")<br />
&nbsp;&nbsp;&nbsp;&nbsp;public class OscillationOverthruster { ... }<br />
</pre>
<br />
<br />
<strong>3。一个使用实例：</strong><br />
结合上面所讲的，我们在这里建立一个简单的基于annotation测试框架。首先我们需要一个annotation类型来表示某个方法是一个应该被测试工具运行的测试方法。<br />
<strong>清单7:</strong><br />
<pre class="overflow" title="pre code"><br />
&nbsp;&nbsp;&nbsp;&nbsp;import java.lang.annotation.*;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * Indicates that the annotated method is a test method.<br />
&nbsp;&nbsp;&nbsp;&nbsp; * This annotation should be used only on parameterless static methods.<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Retention(RetentionPolicy.RUNTIME)<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Target(ElementType.METHOD)<br />
&nbsp;&nbsp;&nbsp;&nbsp;public @interface Test { }<br />
</pre>
<br />
<br />
值得注意的是annotaion类型声明是可以标注自己的，这样的annotation被称为&#8220;meta-annotations&#8221;。<br />
<br />
在上面的代码中，@Retention(RetentionPolicy.RUNTIME)这个meta-annotation表示了此类型的 annotation将被虚拟机保留使其能够在运行时通过反射被读取。而@Target(ElementType.METHOD)表示此类型的 annotation只能用于修饰方法声明。<br />
<br />
下面是一个简单的程序，其中部分方法被上面的annotation所标注：<br />
<strong>清单8:</strong><br />
<pre class="overflow" title="pre code"><br />
&nbsp;&nbsp;&nbsp;&nbsp;public class Foo {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Test public static void m1() { }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public static void m2() { }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Test public static void m3() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new RuntimeException("Boom");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public static void m4() { }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Test public static void m5() { }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public static void m6() { }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Test public static void m7() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new RuntimeException("Crash");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public static void m8() { }<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
Here is the testing tool:<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;import java.lang.reflect.*;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;public class RunTests {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int passed = 0, failed = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (Method m : Class.forName(args[0]).getMethods()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (m.isAnnotationPresent(Test.class)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m.invoke(null);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; passed++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch (Throwable ex) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.printf("Test %s failed: %s %n", m, ex.getCause());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; failed++;<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;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.printf("Passed: %d, Failed %d%n", passed, failed);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</pre>
<br />
<br />
这个程序从命令行参数中取出类名，并且遍历此类的所有方法，尝试调用其中被上面的测试annotation类型标注过的方法。在此过程中为了找出哪些方法被 annotation类型标注过，需要使用反射的方式执行此查询。如果在调用方法时抛出异常，此方法被认为已经失败，并打印一个失败报告。最后，打印运行通过/失败的方法数量。<br />
下面文字表示了如何运行这个基于annotation的测试工具：<br />
<br />
<strong>清单9:</strong><br />
<pre class="overflow" title="pre code"><br />
&nbsp;&nbsp;&nbsp;&nbsp;$ java RunTests Foo<br />
&nbsp;&nbsp;&nbsp;&nbsp;Test public static void Foo.m3() failed: java.lang.RuntimeException: Boom <br />
&nbsp;&nbsp;&nbsp;&nbsp;Test public static void Foo.m7() failed: java.lang.RuntimeException: Crash <br />
&nbsp;&nbsp;&nbsp;&nbsp;Passed: 2, Failed 2<br />
</pre>
<br />
<br />
<span style="color: blue">四、Annotation分类：</span><br />
<br />
根据annotation的使用方法和用途主要分为以下几类：<br />
<br />
<strong>1。内建Annotation——Java5.0版在java语法中经常用到的内建Annotation：</strong><br />
@Deprecated用于修饰已经过时的方法；<br />
@Override用于修饰此方法覆盖了父类的方法（而非重载）；<br />
@SuppressWarnings用于通知java编译器禁止特定的编译警告。<br />
<br />
下面代码展示了内建Annotation类型的用法：<br />
<strong>清单10:</strong><br />
<pre class="overflow" title="pre code"><br />
package com.bjinfotech.practice.annotation;<br />
<br />
/**<br />
* 演示如何使用java5内建的annotation<br />
* 参考资料：<br />
* http://java.sun.com/docs/books/tutorial/java/javaOO/annotations.html<br />
* http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html<br />
* http://mindprod.com/jgloss/annotations.html<br />
* @author cleverpig<br />
*<br />
*/<br />
import java.util.List;<br />
<br />
public class UsingBuiltInAnnotation {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//食物类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class Food{}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//干草类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class Hay extends Food{}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//动物类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class Animal{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Food getFood(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return null;<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;&nbsp;&nbsp;&nbsp;&nbsp;//使用Annotation声明Deprecated方法<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Deprecated<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void deprecatedMethod(){<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;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//马类-继承动物类<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class Horse extends Animal{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//使用Annotation声明覆盖方法<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Hay getFood(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new Hay();<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;&nbsp;&nbsp;&nbsp;&nbsp;//使用Annotation声明禁止警告<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@SuppressWarnings({"deprecation","unchecked"})<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void callDeprecatedMethod(List horseGroup){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Animal an=new Animal();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;an.deprecatedMethod();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;horseGroup.add(an);<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;}<br />
}<br />
</pre>
<br />
<br />
<strong>2。开发者自定义Annotation：由开发者自定义Annotation类型。</strong><br />
下面是一个使用annotation进行方法测试的sample：<br />
<br />
AnnotationDefineForTestFunction类型定义如下：<br />
<strong>清单11:</strong><br />
<pre class="overflow" title="pre code"><br />
package com.bjinfotech.practice.annotation;<br />
<br />
import java.lang.annotation.*;<br />
/**<br />
* 定义annotation<br />
* @author cleverpig<br />
*<br />
*/<br />
//加载在VM中，在运行时进行映射<br />
@Retention(RetentionPolicy.RUNTIME)<br />
//限定此annotation只能标示方法<br />
@Target(ElementType.METHOD)<br />
public @interface AnnotationDefineForTestFunction{}<br />
</pre>
<br />
<br />
测试annotation的代码如下：<br />
<br />
<strong>清单12:</strong><br />
<pre class="overflow" title="pre code"><br />
package com.bjinfotech.practice.annotation;<br />
<br />
import java.lang.reflect.*;<br />
<br />
/**<br />
* 一个实例程序应用前面定义的Annotation：AnnotationDefineForTestFunction<br />
* @author cleverpig<br />
*<br />
*/<br />
public class UsingAnnotation {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@AnnotationDefineForTestFunction public static void method01(){}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public static void method02(){}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@AnnotationDefineForTestFunction public static void method03(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new RuntimeException("method03");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public static void method04(){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new RuntimeException("method04");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public static void main(String[] argv) throws Exception{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int passed = 0, failed = 0;<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;&nbsp;&nbsp;&nbsp;&nbsp;String className="com.bjinfotech.practice.annotation.UsingAnnotation";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//逐个检查此类的方法，当其方法使用annotation声明时调用此方法<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (Method m : Class.forName(className).getMethods()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (m.isAnnotationPresent(AnnotationDefineForTestFunction.class)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m.invoke(null);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; passed++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch (Throwable ex) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.printf("测试 %s 失败: %s %n", m, ex.getCause());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; failed++;<br />
&nbsp;&nbsp;&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;&nbsp;&nbsp; }<br />
&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;System.out.printf("测试结果： 通过: %d, 失败： %d%n", passed, failed);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
</pre>
<br />
<br />
<strong>3。使用第三方开发的Annotation类型</strong><br />
这也是开发人员所常常用到的一种方式。比如我们在使用Hibernate3.0时就可以利用Annotation生成数据表映射配置文件，而不必使用Xdoclet。<br />
<br />
<span style="color: blue">五、总结：</span><br />
<br />
1。前面的文字说明了annotation的使用方法、定义方式、分类。初学者可以通过以上的说明制作简单的annotation程序，但是对于一些高级的 annotation应用（例如使用自定义annotation生成javabean映射xml文件）还需要进一步的研究和探讨。<br />
<br />
2。同时，annotation运行存在两种方式：运行时、编译时。上文中讨论的都是在运行时的annotation应用，但在编译时的annotation应用还没有涉及，因为编译时的annotation要使用annotation processing tool。<br />
<br />
<img src ="http://www.blogjava.net/hummer008/aggbug/207699.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-06-13 16:07 <a href="http://www.blogjava.net/hummer008/articles/207699.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>annotation知识(转)</title><link>http://www.blogjava.net/hummer008/articles/207695.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Fri, 13 Jun 2008 08:00:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/207695.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/207695.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/207695.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/207695.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/207695.html</trackback:ping><description><![CDATA[<span style="color: red">版权声明：本文可以自由转载，转载时请务必以超链接形式标明文章原始出处和作者信息及本声明</span> <br />
作者:cleverpig(作者的Blog:<a href="http://blog.matrix.org.cn/page/cleverpig" target="_new">http://blog.matrix.org.cn/page/cleverpig</a>)<br />
原文:<a href="http://www.matrix.org.cn/resource/article/44/44055_Java+Annotation+Reflect.html" target="_new">http://www.matrix.org.cn/resource/article/44/44055_Java+Annotation+Reflect.html</a><br />
关键字:java,annotation,reflect<br />
<br />
<span style="color: blue">前言：</span><br />
在上篇文章<a href="http://www.matrix.org.cn/resource/article/44/44048_Java+Annotation.html" target="_new">《Java Annotation入门》</a>中概要性的介绍了Annotation的定义、使用，范围涵盖较广，但是深度不够。所以作者在《Java Annotation入门》后，继续整理了Annotation的概念和知识点，与喜欢research的朋友们共享。<br />
<br />
<span style="color: red">阅读提示：文中提到的程序成员或者程序元素是一个概念，指组成程序代码的单元：如类、方法、成员变量。</span><br />
<br />
<span style="color: blue">一、Annotation究竟是什么？</span><br />
<br />
Annotation提供了一条与程序元素关联任何信息或者任何元数据（metadata）的途径。从某些方面看，annotation就像修饰符一样被使用，并应用于包、类型、构造方法、方法、成员变量、参数、本地变量的声明中。这些信息被存储在annotation的&#8220;name=value&#8221;结构对中。annotation类型是一种接口，能够通过java反射API的方式提供对其信息的访问。<br />
<br />
annotation能被用来为某个程序元素（类、方法、成员变量等）关联任何的信息。需要注意的是，这里存在着一个基本的潜规则：annotaion不能影响程序代码的执行，无论增加、删除annotation，代码都始终如一的执行。另外，尽管一些annotation通过java的反射api方法在运行时被访问，而java语言解释器在工作时忽略了这些annotation。正是由于java虚拟机忽略了annotation，导致了annotation类型在代码中是&#8220;不起作用&#8221;的；只有通过某种配套的工具才会对annotation类型中的信息进行访问和处理。本文中将涵盖标准的annotation和meta-annotation类型，陪伴这些annotation类型的工具是java编译器（当然要以某种特殊的方式处理它们）。<br />
<br />
由于上述原因，annotation在使用时十分简便。一个本地变量可以被一个以NonNull命名的annotation类型所标注，来作为对这个本地变量不能被赋予null值的断言。而我们可以编写与之配套的一个annotation代码分析工具，使用它来对具有前面变量的代码进行解析，并且尝试验证这个断言。当然这些代码并不必自己编写。在JDK安装后，在JDK/bin目录中可以找到名为&#8220;apt&#8221;的工具，它提供了处理annotation的框架：它启动后扫描源代码中的annotation，并调用我们定义好的annotation处理器完成我们所要完成的工作（比如验证前面例子中的断言）。说到这里，annotation的强大功能似乎可以替代XDoclet这类的工具了，随着我们的深入，大家会更加坚信这一点。<br />
注：详细描述请参看jsr250规范：<br />
<a href="http://www.jcp.org/aboutJava/communityprocess/pfd/jsr250/" target="_new">http://www.jcp.org/aboutJava/communityprocess/pfd/jsr250/</a><br />
<br />
<span style="color: blue">二、Annotation的定义：</span><br />
<br />
这段文字开始介绍annotation相关技术。在此大家将看到java5.0的标准annotation类型，这种标准类型就是前文中所说的&#8220;内建&#8221;类型，它们可以直接被javac支持。可喜的是，在java6.0beta版中的javac已经加入了对自定义annotation的支持。<br />
<br />
<span style="color: blue">1。Annotation的概念和语法：</span><br />
<br />
首先，关键的概念是理解annotation是与一个程序元素相关联信息或者元数据的标注。它从不影响java程序的执行，但是对例如编译器警告或者像文档生成器等辅助工具产生影响。<br />
<br />
下面是常用的annotation列表，我们应该注意在annotation和annotation类型之间的不同：<br />
<br />
<span style="color: green">A.annotation：</span><br />
annotation使用了在java5.0所带来的新语法，它的行为十分类似public、final这样的修饰符。每个annotation具有一个名字和成员个数&gt;=0。每个annotation的成员具有被称为name=value对的名字和值（就像javabean一样），name=value装载了annotation的信息。<br />
<br />
<span style="color: green">B.annotation类型：</span><br />
annotation类型定义了annotation的名字、类型、成员默认值。一个annotation类型可以说是一个特殊的java接口，它的成员变量是受限制的，而声明annotation类型时需要使用新语法。当我们通过java反射api访问annotation时，返回值将是一个实现了该annotation类型接口的对象，通过访问这个对象我们能方便的访问到其annotation成员。后面的章节将提到在java5.0的java.lang包里包含的3个标准annotation类型。<br />
<br />
<span style="color: green">C.annotation成员：</span><br />
annotation的成员在annotation类型中以无参数的方法的形式被声明。其方法名和返回值定义了该成员的名字和类型。在此有一个特定的默认语法：允许声明任何annotation成员的默认值：一个annotation可以将name=value对作为没有定义默认值的annotation成员的值，当然也可以使用name=value对来覆盖其它成员默认值。这一点有些近似类的继承特性，父类的构造函数可以作为子类的默认构造函数，但是也可以被子类覆盖。<br />
<br />
<span style="color: green">D.marker annotation类型：</span><br />
一个没有成员定义的annotation类型被称为marker annotation。这种annotation类型仅使用自身的存在与否来为我们提供信息。如后面要说的Override。<br />
<br />
<span style="color: green">E.meta-annotation：</span><br />
meta-annotation也称为元annotation，它是被用来声明annotation类型的annotation。Java5.0提供了一些标准的元-annotation类型。下面介绍的target、retention就是meta-annotation。<br />
<br />
<span style="color: green">F.target：</span><br />
annotation的target是一个被标注的程序元素。target说明了annotation所修饰的对象范围：annotation可被用于packages、types（类、接口、枚举、annotation类型）、类型成员（方法、构造方法、成员变量、枚举值）、方法参数和本地变量（如循环变量、catch参数）。在annotation类型的声明中使用了target可更加明晰其修饰的目标。<br />
<br />
<span style="color: green">G.retention：</span><br />
annotation的retention定义了该annotation被保留的时间长短：某些annotation仅出现在源代码中，而被编译器丢弃；而另一些却被编译在class文件中；编译在class文件中的annotation可能会被虚拟机忽略，而另一些在class被装载时将被读取（请注意并不影响class的执行，因为annotation与class在使用上是被分离的）。使用这个meta-annotation可以对annotation的&#8220;生命周期&#8221;限制。<br />
<br />
<span style="color: green">H.metadata：</span><br />
由于metadata被广泛使用于各种计算机开发过程中，所以当我们在这里谈论的metadata即元数据通常指被annotation装载的信息或者annotation本身。<br />
<br />
<span style="color: blue">2。使用标准Annotation：</span><br />
java5.0在java.lang包中定义了3种标准的annotation类型：<br />
<br />
<span style="color: green">A.Override：</span><br />
java.lang.Override是一个marker annotation类型，它被用作标注方法。它说明了被标注的方法重载了父类的方法，起到了断言的作用。如果我们使用了这种annotation在一个没有覆盖父类方法的方法时，java编译器将以一个编译错误来警示。<br />
这个annotaton常常在我们试图覆盖父类方法而确又写错了方法名时发挥威力。<br />
<br />
使用方法极其简单：在使用此annotation时只要在被修饰的方法前面加上@Override。<br />
下面的代码是一个使用@Override修饰一个企图重载父类的toString方法，而又存在拼写错误的sample：<br />
<strong>清单1：</strong><br />
<pre class="overflow"><br />
@Override<br />
public String toSting() {&nbsp;&nbsp; // 注意方法名拼写错了<br />
&nbsp;&nbsp;&nbsp;&nbsp;return "[" + super.toString() + "]";<br />
}<br />
</pre>
<br />
<br />
<span style="color: green">B.Deprecated：</span><br />
同样Deprecated也是一个marker annotation。当一个类型或者类型成员使用@Deprecated修饰的话，编译器将不鼓励使用这个被标注的程序元素。而且这种修饰具有一定的&#8220;延续性&#8221;：如果我们在代码中通过继承或者覆盖的方式使用了这个过时的类型或者成员，虽然继承或者覆盖后的类型或者成员并不是被声明为@Deprecated，但编译器仍然要报警。<br />
值得注意，@Deprecated这个annotation类型和javadoc中的@deprecated这个tag是有区别的：前者是java编译器识别的，而后者是被javadoc工具所识别用来生成文档（包含程序成员为什么已经过时、它应当如何被禁止或者替代的描述）。<br />
在java5.0，java编译器仍然象其从前版本那样寻找@deprecated这个javadoc tag，并使用它们产生警告信息。但是这种状况将在后续版本中改变，我们应在现在就开始使用@Deprecated来修饰过时的方法而不是@deprecated javadoc tag。<br />
<strong>清单2：</strong><br />
<pre class="overflow"><br />
下面是一段使用@Deprecated的代码：<br />
/**<br />
* 这里是javadoc的@deprecated声明.<br />
* @deprecated No one has players for this format any more.&nbsp;&nbsp;Use VHS instead.<br />
*/<br />
@Deprecated public class Betamax { ... }<br />
</pre>
<br />
<br />
<span style="color: green">C.SuppressWarnings：</span><br />
@SuppressWarnings被用于有选择的关闭编译器对类、方法、成员变量、变量初始化的警告。在java5.0，sun提供的javac编译器为我们提供了-Xlint选项来使编译器对合法的程序代码提出警告，此种警告从某种程度上代表了程序错误。例如当我们使用一个generic collection类而又没有提供它的类型时，编译器将提示出"unchecked warning"的警告。<br />
<br />
通常当这种情况发生时，我们就需要查找引起警告的代码。如果它真的表示错误，我们就需要纠正它。例如如果警告信息表明我们代码中的switch语句没有覆盖所有可能的case，那么我们就应增加一个默认的case来避免这种警告。<br />
相仿，有时我们无法避免这种警告，例如，我们使用必须和非generic的旧代码交互的generic collection类时，我们不能避免这个unchecked warning。此时@SuppressWarning就要派上用场了，在调用的方法前增加@SuppressWarnings修饰，告诉编译器停止对此方法的警告。<br />
SuppressWarning不是一个marker annotation。它有一个类型为String[]的成员，这个成员的值为被禁止的警告名。对于javac编译器来讲，被-Xlint选项有效的警告名也同样对@SuppressWarings有效，同时编译器忽略掉无法识别的警告名。<br />
<br />
annotation语法允许在annotation名后跟括号，括号中是使用逗号分割的name=value对用于为annotation的成员赋值：<br />
<strong>清单3：</strong><br />
<pre class="overflow"><br />
@SuppressWarnings(value={"unchecked","fallthrough"})<br />
public void lintTrap() { /* sloppy method body omitted */ }<br />
</pre>
<br />
<br />
在这个例子中SuppressWarnings annotation类型只定义了一个单一的成员，所以只有一个简单的value={...}作为name=value对。又由于成员值是一个数组，故使用大括号来声明数组值。<br />
<br />
注意：我们可以在下面的情况中缩写annotation：当annotation只有单一成员，并成员命名为"value="。这时可以省去"value="。比如将上面的SuppressWarnings annotation进行缩写：<br />
<strong>清单4：</strong><br />
<pre class="overflow"><br />
@SuppressWarnings({"unchecked","fallthrough"})<br />
</pre>
<br />
如果SuppressWarnings所声明的被禁止警告个数为一个时，可以省去大括号：<br />
<pre class="overflow"><br />
@SuppressWarnings("unchecked")<br />
</pre>
<br />
<br />
<span style="color: blue">3。Annotation语法：</span><br />
<br />
在上一个章节中，我们看到书写marker annotation和单一成员annotation的语法。下面本人来介绍一下完整的语法：<br />
<br />
annotation由&#8220;@+annotation类型名称+(..逗号分割的name-value对...)&#8221;组成。其中成员可以按照任何的顺序。如果annotation类型定义了某个成员的默认值，则这个成员可以被省略。成员值必须为编译时常量、内嵌的annotation或者数组。<br />
<br />
下面我们将定义一个annotation类型名为Reviews，它有一个由@Review annotation数组构成的成员。这个@Review annotation类型有三个成员："reviewer"是一个字符串，"comment" 是一个具有默认值的可选的字符串，"grade"是一个Review.Grade枚举类型值。<br />
<strong>清单5：</strong><br />
<pre class="overflow"><br />
@Reviews({&nbsp;&nbsp;// Single-value annotation, so "value=" is omitted here<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Review(grade=Review.Grade.EXCELLENT,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reviewer="df"),<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Review(grade=Review.Grade.UNSATISFACTORY,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reviewer="eg",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;comment="This method needs an @Override annotation")<br />
})<br />
</pre>
<br />
annotation语法的另一个重要规则是没有程序成员可以有多于一个的同一annotation实例。例如在一个类中简单的放置多个@Review annotation。这也是在上面代码中定义@Reviews annotation类型数组的原因。<br />
<br />
<span style="color: blue">4。Annotation成员类型和值：</span><br />
<br />
annotation成员必须是非空的编译时常量表达式。可用的成员类型为：primitive类型、, String, Class, enumerated类型, annotation类型, 和前面类型的数组。<br />
<br />
下面我们定义了一个名为UncheckedExceptions 的annotation类型，它的成员是一个扩展了RuntimeException类的类数组。<br />
<strong>清单6：</strong><br />
<pre class="overflow"><br />
@UncheckedExceptions({<br />
&nbsp;&nbsp;&nbsp;&nbsp;IllegalArgumentException.class, StringIndexOutOfBoundsException.class<br />
})<br />
</pre>
<br />
<br />
<span style="color: blue">5。Annotation的目标：</span><br />
<br />
annotation通常被放在类型定义和成员定义的前面。然而它也出现在package、方法参数、本地变量的前面。下面，我们来讨论一下这些不大常用的写法：<br />
<br />
package annotation出现在package声明的前面。<br />
下面的例子package-info.java中不包含任何的公共类型定义，却包含一个可选的javadoc注释。<br />
<strong>清单7：</strong><br />
<pre class="overflow"><br />
/**<br />
* This package holds my custom annotation types.<br />
*/<br />
@com.davidflanagan.annotations.Author("David Flanagan")<br />
package com.davidflanagan.annotations;<br />
</pre>
<br />
当package-info.java文件被编译时，它将产生名为包含annotation（特殊的接口）声明的package-info.class的类。这个接口没有成员，它的名字package-info不是一个合法的java标识，所以它不能用在java源代码中。这个接口的存在只是简单的被看作一个为package annotation准备的占位符。<br />
<br />
用于修饰方法参数、catch参数、本地变量的annotation只是简单的出现在这些程序成员的修饰符位置。java类文件格式没有为本地变量或者catch参数存储annotation作准备，所以这些annotation总是保留在源代码级别（source retention）；方法参数annotation能够保存在类文件中，也可以在保留到运行时。<br />
<br />
最后，请注意，枚举类型定义中不允许任何的修饰符修饰其枚举值。<br />
<br />
<span style="color: blue">6。Annotation和默认值：</span><br />
在Annotation中，没有默认值的成员必须有一个成员值。而如何理解默认值是如何被处理就是一个很重要的细节：annotation类型所定义的成员默认值被存储在class文件中，不被编译到annotation里面。如果我们修改一个annotation类型使其成员的默认值发生了改变，这个改变对于所有此类型的annotation中没有明确提供成员值的成员产生影响（即修改了该成员的成员值）。即使在annotation类型使其成员的默认值被改变后annotation从没被重新编译过，该类型的annotation(改变前已经被编译的)也受到影响。<br />
<br />
<span style="color: blue">三、Annotation工作原理：</span><br />
<br />
<span style="color: blue">Annotation与反射</span><br />
在java5.0中Java.lang.reflect提供的反射API被扩充了读取运行时annotation的能力。让我们回顾一下前面所讲的：一个annotation类型被定义为runtime retention后，它才是在运行时可见，当class文件被装载时被保存在class文件中的annotation才会被虚拟机读取。那么reflect是如何帮助我们访问class中的annotation呢？<br />
<br />
下文将在java.lang.reflect用于annotation的新特性，其中java.lang.reflect.AnnotatedElement是重要的接口，它代表了提供查询annotation能力的程序成员。这个接口被java.lang.Package、java.lang.Class实现，并间接地被Method类、Constructor类、java.lang.reflect的Field类实现。而annotation中的方法参数可以通过Method类、Constructor类的getParameterAnnotations()方法获得。<br />
<br />
下面的代码使用了AnnotatedElement类的isAnnotationPresent()方法判断某个方法是否具有@Unstable annotation，从而断言此方法是否稳定：<br />
<strong>清单8：</strong><br />
<pre class="overflow"><br />
import java.lang.reflect.*;<br />
<br />
Class c = WhizzBangClass.class;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
Method m = c.getMethod("whizzy", int.class, int.class);&nbsp;&nbsp;<br />
boolean unstable = m.isAnnotationPresent(Unstable.class);<br />
</pre>
<br />
isAnnotationPresent()方法对于检查marker annotation是十分有用的，因为marker annotation没有成员变量，所以我们只要知道class的方法是否使用了annotation修饰就可以了。而当处理具有成员的annotation时，我们通过使用getAnnotation()方法来获得annotation的成员信息（成员名称、成员值）。这里我们看到了一套优美的java annotation系统：如果annotation存在，那么实现了相应的annotation类型接口的对象将被getAnnotation()方法返回，接着调用定义在annotation类型中的成员方法可以方便地获得任何成员值。<br />
<br />
回想一下，前面介绍的@Reviews annotation，如果这个annotation类型被声明为runtime retention的话，我们通过下面的代码来访问@Reviews annotation的成员值：<br />
<strong>清单9：</strong><br />
<pre class="overflow"><br />
AnnotatedElement target = WhizzBangClass.class; //获得被查询的AnnotatedElement<br />
// 查询AnnotatedElement的@Reviews annotation信息<br />
Reviews annotation = target.getAnnotation(Reviews.class);<br />
// 因为@Reviews annotation类型的成员为@Review annotation类型的数组，<br />
// 所以下面声明了Review[] reviews保存@Reviews annotation类型的value成员值。<br />
Review[] reviews = annotation.value();<br />
// 查询每个@Review annotation的成员信息<br />
for(Review r : reviews) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;Review.Grade grade = r.grade();<br />
&nbsp;&nbsp;&nbsp;&nbsp;String reviewer = r.reviewer();<br />
&nbsp;&nbsp;&nbsp;&nbsp;String comment = r.comment();<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.printf("%s assigned a grade of %s and comment '%s'%n",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reviewer, grade, comment);<br />
}<br />
</pre>
<br />
<br />
<span style="color: blue">四、如何自定义Annotation？</span><br />
<br />
<span style="color: blue">1．详解annotation与接口的异同：</span><br />
因为annotation类型是一个非凡的接口，所以两者之间存在着某些差异：<br />
<br />
<span style="color: green">A.Annotation类型使用关键字@interface而不是interface。</span><br />
这个关键字声明隐含了一个信息：它是继承了java.lang.annotation.Annotation接口，并非声明了一个interface。<br />
<br />
<span style="color: green">B.Annotation类型、方法定义是独特的、受限制的。</span><br />
Annotation类型的方法必须声明为无参数、无异常抛出的。这些方法定义了annotation的成员：方法名成为了成员名，而方法返回值成为了成员的类型。而方法返回值类型必须为primitive类型、Class类型、枚举类型、annotation类型或者由前面类型之一作为元素的一维数组。方法的后面可以使用default和一个默认数值来声明成员的默认值，null不能作为成员默认值，这与我们在非annotation类型中定义方法有很大不同。<br />
Annotation类型和它的方法不能使用annotation类型的参数、成员不能是generic。只有返回值类型是Class的方法可以在annotation类型中使用generic，因为此方法能够用类转换将各种类型转换为Class。<br />
<br />
<span style="color: green">C.Annotation类型又与接口有着近似之处。</span><br />
它们可以定义常量、静态成员类型（比如枚举类型定义）。Annotation类型也可以如接口一般被实现或者继承。<br />
<br />
<span style="color: blue">2．实例：</span><br />
下面，我们将看到如何定义annotation类型的example。它展示了annotation类型声明以及@interface与interface之间的不同：<br />
<strong>清单10：</strong><br />
<pre class="overflow"><br />
package com.davidflanagan.annotations;<br />
import java.lang.annotation.*;<br />
<br />
/**<br />
* 使用annotation来描述那些被标注的成员是不稳定的，需要更改<br />
*/<br />
@Retention(RetentionPolicy.RUNTIME)<br />
public @interface Unstable {}<br />
</pre>
<br />
<br />
下面的另一个example只定义了一个成员。并通过将这个成员命名为value，使我们可以方便的使用这种annotation的快捷声明方式：<br />
<strong>清单11：</strong><br />
<pre class="overflow"><br />
/**<br />
* 使用Author这个annotation定义在程序中指出代码的作者<br />
*/<br />
public @interface Author {<br />
&nbsp;&nbsp;&nbsp;&nbsp;/** 返回作者名 */<br />
&nbsp;&nbsp;&nbsp;&nbsp;String value();<br />
}<br />
</pre>
<br />
<br />
以下的example更加复杂。Reviews annotation类型只有一个成员，但是这个成员的类型是复杂的：由Review annotation组成的数组。Review annotation类型有3个成员：枚举类型成员grade、表示Review名称的字符串类型成员Reviewer、具有默认值的字符串类型成员Comment。<br />
<strong>清单12：</strong><br />
<pre class="overflow"><br />
import java.lang.annotation.*;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
/**<br />
* Reviews annotation类型只有一个成员，<br />
* 但是这个成员的类型是复杂的：由Review annotation组成的数组<br />
*/<br />
@Retention(RetentionPolicy.RUNTIME)<br />
public @interface Reviews {<br />
&nbsp;&nbsp;&nbsp;&nbsp;Review[] value();<br />
}<br />
<br />
/**<br />
* Review annotation类型有3个成员： <br />
* 枚举类型成员grade、<br />
&nbsp;&nbsp;* 表示Review名称的字符串类型成员Reviewer、<br />
&nbsp;&nbsp;* 具有默认值的字符串类型成员Comment。<br />
*/<br />
public @interface Review {<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 内嵌的枚举类型<br />
&nbsp;&nbsp;&nbsp;&nbsp;public static enum Grade { EXCELLENT, SATISFACTORY, UNSATISFACTORY };<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;// 下面的方法定义了annotation的成员<br />
&nbsp;&nbsp;&nbsp;&nbsp;Grade grade();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;String reviewer();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;String comment() default "";&nbsp;&nbsp;<br />
}<br />
</pre>
<br />
<br />
最后，我们来定义一个annotation方法用于罗列出类运行中所有的unchecked异常（上文已经提到这种情况不一定是错误）。这个annotation类型将一个数组作为了唯一的成员。数组中的每个元素都是异常类。为了加强对未检查的异常（此类异常都是在运行时抛出）进行报告，我们可以在代码中对异常的类型进行限制：<br />
<strong>清单13：</strong><br />
<pre class="overflow"><br />
public @interface UncheckedExceptions {<br />
&nbsp;&nbsp;&nbsp;&nbsp;Class&lt;? extends RuntimeException&gt;[] value();<br />
}<br />
</pre>
<br />
<br />
<span style="color: blue">五、Meta-Annotation</span><br />
<br />
Annotation类型可以被它们自己所标注。Java5.0定义了4个标准的meta-annotation类型，它们被用来提供对其它annotation类型作说明。这些类型和它们所支持的类在java.lang.annotation包中可以找到。如果需要更详细的信息可以参考jdk5.0手册。<br />
<br />
<span style="color: blue">1．再谈Target</span><br />
作为meta-annotation类型的Target,它描述了annotation所修饰的程序成员的类型。当一个annotation类型没有Target时，它将被作为普通的annotation看待。当将它修饰一个特定的程序成员时，它将发挥其应用的作用，例如：Override用于修饰方法时，增加了@Target这个meta-annotation就使编译器对annotation作检查，从而去掉修饰错误类型的Override。<br />
<br />
Target meta-annotation类型有唯一的value作为成员。这个成员的类型是java.lang.annotation.ElementType[]类型的，ElementType类型是可以被标注的程序成员的枚举类型。<br />
<br />
<span style="color: blue">2．Retention的用法</span><br />
我们在文章的开头曾经提到过Retention，但是没有详细讲解。Retention描述了annotation是否被编译器丢弃或者保留在class文件；如果保留在class文件中，是否在class文件被装载时被虚拟机读取。默认情况下，annotation被保存在class文件中，但在运行时并不能被反射访问。Retention具有三个取值：source、class、runtime，这些取值来自java.lang.annotation.RetentionPolicy的枚举类型值。<br />
<br />
Retention meta-annotation类型有唯一的value作为成员，它的取值来自java.lang.annotation.RetentionPolicy的枚举类型值。<br />
<br />
<span style="color: blue">3．Documented</span><br />
Documented是一个meta-annotation类型，用于描述其它类型的annotation应该被作为被标注的程序成员的公共API，因此可以被例如javadoc此类的工具文档化。<br />
<br />
Documented是一个marker annotation，没有成员。<br />
<br />
<span style="color: blue">4．Inherited</span><br />
@Inherited meta-annotation也是一个marker annotation，它阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class，则这个annotation将被用于该class的子类。<br />
<br />
注意：@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation，方法并不从它所重载的方法继承annotation。<br />
<br />
值得思考的是，当@Inherited annotation类型标注的annotation的Retention是RetentionPolicy.RUNTIME，则反射API增强了这种继承性。如果我们使用java.lang.reflect去查询一个@Inherited annotation类型的annotation时，反射代码检查将展开工作：检查class和其父类，直到发现指定的annotation类型被发现，或者到达类继承结构的顶层。<br />
<br />
<span style="color: blue">六、总结：</span><br />
<br />
本文几乎覆盖了所有的Annotation的概念和知识点，从annotation的定义、语法到工作原理、如何自定义annotation，直至meta-annotation。其中也具有一些配套的代码片断可参考，虽然不是很多，但是可谓言简意赅、着其重点，本人认为用好annotation的关键还在于使用。希望本手册能够帮助大家用好annotation，这也是本人的最大快乐。<br />
<img src ="http://www.blogjava.net/hummer008/aggbug/207695.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-06-13 16:00 <a href="http://www.blogjava.net/hummer008/articles/207695.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用AOP实现CACHE机制转(二)</title><link>http://www.blogjava.net/hummer008/articles/205756.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Wed, 04 Jun 2008 03:37:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/205756.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/205756.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/205756.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/205756.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/205756.html</trackback:ping><description><![CDATA[<br />
<br />
cache.put(new Element(key,(Serializable)value));<br />
<br />
放入缓存中的value必须序列化，Java原生类型 char、int ，原生类型的包装类String、Character、Integer、Number...和集合List的实现类ArrayList都已经实现了Serializable接口，它们都可以直接放到缓存中。这里要注意的是，在方法返回值中经常用到的Iterator，并没有实现Serializable接口，所以Cache 不能缓存返回值类型为Iterator的方法。<br />
<br />
<br />
&nbsp;还有一点要注意的是，如果我们要做缓存的方法是在bean的生命周期的初始化阶段调用的（例如setter，init），此时方法缓存拦截器还没被调用执行，那么缓存将不起作用，如做了下面的配置：<br />
<br />
&lt;bean id="OrganizationManagerMethodCache" class="org.springframework.aop.framework.ProxyFactoryBean"&gt;<br />
　　 &lt;property name="target"&gt;<br />
　　 &lt;bean class="com.wzj.rbac.ServiceFacade.OrganizationManager" init-method="init" autowire="byName"/&gt; <br />
　　 &lt;/property&gt;<br />
　　 &lt;property name="interceptorNames"&gt;<br />
　　 &lt;list&gt;<br />
　　 &lt;value&gt;methodCachePointCut&lt;/value&gt;<br />
　　 &lt;/list&gt;<br />
　　 &lt;/property&gt;<br />
　　 &lt;/bean&gt;<br />
　　 在init初始方法里面调用的缓存方法将失效。
<img src ="http://www.blogjava.net/hummer008/aggbug/205756.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-06-04 11:37 <a href="http://www.blogjava.net/hummer008/articles/205756.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用AOP实现CACHE机制</title><link>http://www.blogjava.net/hummer008/articles/205589.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Tue, 03 Jun 2008 08:43:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/205589.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/205589.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/205589.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/205589.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/205589.html</trackback:ping><description><![CDATA[<br />
1.<span style="font-family: 宋体"><font size="2">首先配置<span lang="EN-US">ehcache.xml</span></font></span><br />
<br />
<p>&lt;ehcache&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;diskStore path="java.io.tmpdir"/&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;defaultCache&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxElementsInMemory="10000"&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eternal="false"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToIdleSeconds="120"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToLiveSeconds="120"&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overflowToDisk="true"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; /&gt;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; &lt;cache name="org.taha.cache.METHOD_CACHE"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxElementsInMemory="300"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eternal="false"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToIdleSeconds="60"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToLiveSeconds="60"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overflowToDisk="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /&gt;</p>
<p>&lt;/ehcache&gt;</p>
<p>&nbsp;//defaultCache&nbsp; 一定要有不然解析报错</p>
<p>2. spring-ehcache.xml<br />
<br />
</p>
<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br />
&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"&gt;</p>
<p>&lt;beans default-autowire="byName"&gt;</p>
<p>&nbsp;&lt;bean id="cacheManager"<br />
&nbsp;&nbsp;class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"&gt;</p>
<p>&nbsp;&nbsp;&lt;property name="configLocation"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;classpath:ehcache.xml&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;<br />
&nbsp;&lt;/bean&gt;</p>
<p><br />
&nbsp;&lt;bean id="methodCache"<br />
&nbsp;&nbsp;class="org.springframework.cache.ehcache.EhCacheFactoryBean"&gt;</p>
<p>&nbsp;&nbsp;&lt;property name="cacheManager"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;ref local="cacheManager" /&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;</p>
<p>&nbsp;&nbsp;&lt;property name="cacheName"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;value&gt;org.taha.cache.METHOD_CACHE&lt;/value&gt;<br />
&nbsp;&nbsp;&lt;/property&gt;</p>
<p>&nbsp;&lt;/bean&gt;</p>
<p><br />
&nbsp;&lt;bean id="methodCacheInterceptor"<br />
&nbsp;&nbsp;class="com.infowarelab.cem.easytouch.web.interceptor.MethodCacheInterceptor"&gt;</p>
<p>&nbsp;&nbsp;&lt;property name="cache"&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;ref local="methodCache" /&gt;</p>
<p>&nbsp;&nbsp;&lt;/property&gt;</p>
<p>&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;</p>
<p>&nbsp;&lt;bean id="methodCachePointCut"<br />
&nbsp;&nbsp;class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"&gt;</p>
<p>&nbsp;&nbsp;&lt;property name="advice"&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;ref local="methodCacheInterceptor" /&gt;</p>
<p>&nbsp;&nbsp;&lt;/property&gt;</p>
<p>&nbsp;&nbsp;&lt;property name="patterns"&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;list&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;.*methodOne&lt;/value&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;.*methodTwo&lt;/value&gt;&nbsp;&nbsp;&nbsp;//匹配methodTwo的方法&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;.*cache.*&lt;/value&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //匹配以 cache开头的方法</p>
<p>&nbsp;&nbsp;&nbsp;&lt;/list&gt;</p>
<p>&nbsp;&nbsp;&lt;/property&gt;</p>
<p>&nbsp;&lt;/bean&gt;</p>
<p>&nbsp;</p>
<p>&nbsp;&lt;bean id="myBean"<br />
&nbsp;&nbsp;class="org.springframework.aop.framework.ProxyFactoryBean"&gt;</p>
<p>&nbsp;&nbsp;&lt;property name="target"&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;bean class="com.infowarelab.cem.easytouch.web.interceptor.MyBean" /&gt;</p>
<p>&nbsp;&nbsp;&lt;/property&gt;</p>
<p>&nbsp;&nbsp;&lt;property name="interceptorNames"&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;list&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&lt;value&gt;methodCachePointCut&lt;/value&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&lt;/list&gt;</p>
<p>&nbsp;&nbsp;&lt;/property&gt;</p>
<p>&nbsp;&lt;/bean&gt;<br />
&nbsp;<br />
&nbsp;<br />
&nbsp;</p>
<p>&lt;/beans&gt;<br />
</p>
<p><br />
&nbsp;3 <a name="CachingtheresultofmethodsusingSpringandE"><span lang="EN-US" style="color: black; font-family: Verdana"><font size="2">MethodCacheInterceptor</font></span></a>&nbsp;代码<br />
<br />
</p>
<p>package com.infowarelab.cem.easytouch.web.interceptor;</p>
<p>import java.io.Serializable;</p>
<p>import net.sf.ehcache.Cache;<br />
import net.sf.ehcache.Element;</p>
<p>import org.aopalliance.intercept.MethodInterceptor;<br />
import org.aopalliance.intercept.MethodInvocation;<br />
import org.springframework.beans.factory.InitializingBean;</p>
<p>public class MethodCacheInterceptor implements MethodInterceptor,</p>
<p>InitializingBean {</p>
<p>&nbsp;private Cache cache;</p>
<p>&nbsp;/**<br />
&nbsp; * <br />
&nbsp; * sets cache name to be used<br />
&nbsp; * <br />
&nbsp; */</p>
<p>&nbsp;public void setCache(Cache cache) {</p>
<p>&nbsp;&nbsp;this.cache = cache;</p>
<p>&nbsp;}</p>
<p>&nbsp;/*<br />
&nbsp; * <br />
&nbsp; * (non-Javadoc)<br />
&nbsp; * <br />
&nbsp; * <br />
&nbsp; * <br />
&nbsp; * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)<br />
&nbsp; * <br />
&nbsp; */</p>
<p>&nbsp;public Object invoke(MethodInvocation invocation) throws Throwable {</p>
<p>&nbsp;&nbsp;String targetName = invocation.getThis().getClass().getName();</p>
<p>&nbsp;&nbsp;String methodName = invocation.getMethod().getName();</p>
<p>&nbsp;&nbsp;Object[] arguments = invocation.getArguments();</p>
<p>&nbsp;&nbsp;Object result;</p>
<p>&nbsp;&nbsp;String cacheKey = getCacheKey(targetName, methodName, arguments);</p>
<p>&nbsp;&nbsp;Element element = cache.get(cacheKey);</p>
<p>&nbsp;&nbsp;if (element == null) {</p>
<p>&nbsp;&nbsp;&nbsp;// call target/sub-interceptor</p>
<p>&nbsp;&nbsp;&nbsp;result = invocation.proceed();</p>
<p>&nbsp;&nbsp;&nbsp;// cache method result</p>
<p>&nbsp;&nbsp;&nbsp;element = new Element(cacheKey, (Serializable) result);</p>
<p>&nbsp;&nbsp;&nbsp;cache.put(element);</p>
<p>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;return element.getValue();</p>
<p>&nbsp;}</p>
<p>&nbsp;/**<br />
&nbsp; * <br />
&nbsp; * creates cache key: targetName.methodName.argument0.argument1...<br />
&nbsp; * <br />
&nbsp; */</p>
<p>&nbsp;private String getCacheKey(String targetName, String methodName,</p>
<p>&nbsp;Object[] arguments) {</p>
<p>&nbsp;&nbsp;StringBuffer sb = new StringBuffer();</p>
<p>&nbsp;&nbsp;sb.append(targetName).append(".").append(methodName);</p>
<p>&nbsp;&nbsp;if ((arguments != null) &amp;&amp; (arguments.length != 0)) {</p>
<p>&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; arguments.length; i++) {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;sb.append(".").append(arguments[i]);</p>
<p>&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;return sb.toString();</p>
<p>&nbsp;}</p>
<p>&nbsp;/*<br />
&nbsp; * <br />
&nbsp; * (non-Javadoc)<br />
&nbsp; * <br />
&nbsp; * <br />
&nbsp; * <br />
&nbsp; * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()<br />
&nbsp; * <br />
&nbsp; */</p>
<p>&nbsp;public void afterPropertiesSet() throws Exception {</p>
<p>&nbsp;&nbsp;// TODO Auto-generated method stub</p>
<p>&nbsp;}</p>
<p>}<br />
</p>
<br />
4 MyBean 代码部分 <br />
<br />
<p>package com.infowarelab.cem.easytouch.web.interceptor;</p>
<p>import com.infowarelab.cem.easytouch.service.ConfigdbInfoService;</p>
<p>public class MyBean {<br />
&nbsp;<br />
&nbsp;<br />
&nbsp;private ConfigdbInfoService configdbInfoService;<br />
&nbsp;</p>
<p>&nbsp;public String&nbsp; methodOne(String siteId,String name){<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; String cityName=configdbInfoService.getCityNameByIp("192.168.1.92");<br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;return ""+siteId+name+cityName;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;public String&nbsp; methodTwo(String siteId,String name,String pwd){<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;String cityName=configdbInfoService.getCountryNameByIp("192.168.1.92");<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;return ""+siteId+name+cityName;<br />
&nbsp;}</p>
<p>&nbsp;public void setConfigdbInfoService(ConfigdbInfoService configdbInfoService) {<br />
&nbsp;&nbsp;this.configdbInfoService = configdbInfoService;<br />
&nbsp;}<br />
&nbsp;<br />
&nbsp;<br />
&nbsp;<br />
}<br />
</p>
<br />
5.CopyOfLogin 代码 测试 AOP 代码<br />
<br />
<br />
<p>package com.infowarelab.cem.easytouch.web.action.api;</p>
<p>import com.infowarelab.cem.easytouch.web.interceptor.MyBean;</p>
<p>/**<br />
&nbsp;* <br />
&nbsp;* @author hummer.hu<br />
&nbsp;* @date:2008-4-24<br />
&nbsp;* <br />
&nbsp;*/<br />
public class CopyOfLogin extends ApiBaseAction {</p>
<p>&nbsp;<br />
&nbsp;<br />
&nbsp;private MyBean myBean;<br />
&nbsp;</p>
<p>&nbsp;public String execute() {</p>
<p>&nbsp;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;myBean.methodOne("5555555", "aaaa");<br />
&nbsp;&nbsp;myBean.methodTwo("6666666", "aaaa", "bbbb");<br />
&nbsp;&nbsp;return "login";<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;<br />
&nbsp;}<br />
&nbsp;public void setMyBean(MyBean myBean) {<br />
&nbsp;&nbsp;this.myBean = myBean;<br />
&nbsp;}</p>
<p>&nbsp;<br />
&nbsp;<br />
}<br />
</p>
<img src ="http://www.blogjava.net/hummer008/aggbug/205589.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-06-03 16:43 <a href="http://www.blogjava.net/hummer008/articles/205589.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IP地址相互转化</title><link>http://www.blogjava.net/hummer008/articles/205357.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Mon, 02 Jun 2008 08:27:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/205357.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/205357.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/205357.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/205357.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/205357.html</trackback:ping><description><![CDATA[<p>public class IPUtil {<br />
&nbsp;<br />
&nbsp;<br />
&nbsp;public static int IPToInt(String ipAddress)<br />
&nbsp;{<br />
&nbsp;&nbsp;String[]&nbsp;&nbsp; ipqi_ary=ipAddress.split("\\."); &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;int ip0= new Integer(ipqi_ary[0]).intValue();<br />
&nbsp;&nbsp;int ip1= new Integer(ipqi_ary[1]).intValue();<br />
&nbsp;&nbsp;int ip2= new Integer(ipqi_ary[2]).intValue();<br />
&nbsp;&nbsp;int ip3= new Integer(ipqi_ary[3]).intValue();<br />
&nbsp;&nbsp;&nbsp;&nbsp; return ip0*256*256*256+ip1*256*256+ip2*256+ip3;<br />
&nbsp;}</p>
<p>&nbsp;public static String IntToIP(int ipAddress)<br />
&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp; long ui1 = ipAddress &amp; 0xFF000000;<br />
&nbsp;&nbsp;ui1 = ui1 &gt;&gt; 24;<br />
&nbsp;&nbsp;long ui2 = ipAddress &amp; 0x00FF0000;<br />
&nbsp;&nbsp;ui2 = ui2 &gt;&gt; 16;<br />
&nbsp;&nbsp;long ui3 = ipAddress &amp; 0x0000FF00;<br />
&nbsp;&nbsp;ui3 = ui3 &gt;&gt; 8;<br />
&nbsp;&nbsp;long ui4 = ipAddress &amp; 0x000000FF;<br />
&nbsp;&nbsp;String IPstr = "";<br />
&nbsp;&nbsp;IPstr = String.valueOf(ui1) + "." + String.valueOf(ui2) + "."<br />
&nbsp;&nbsp;&nbsp;&nbsp;+ String.valueOf(ui3) + "." + String.valueOf(ui4);<br />
&nbsp;&nbsp;return IPstr;<br />
&nbsp;}</p>
<p>&nbsp;public static void&nbsp; main(String args[]){<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;String ipAddress="58.17.128.0";<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;int ipInt=IPUtil.IPToInt(ipAddress);<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;System.out.println("String to int :"+ipInt);<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;System.out.println("int to String :"+IPUtil.IntToIP(ipInt));<br />
&nbsp;}<br />
&nbsp;<br />
}<br />
</p>
<img src ="http://www.blogjava.net/hummer008/aggbug/205357.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-06-02 16:27 <a href="http://www.blogjava.net/hummer008/articles/205357.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>post方法调用java接口 </title><link>http://www.blogjava.net/hummer008/articles/205341.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Mon, 02 Jun 2008 07:13:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/205341.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/205341.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/205341.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/205341.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/205341.html</trackback:ping><description><![CDATA[<br />
// urlParam=<a href="http://192.168.1.92/easycall/cmd?funcName=check">http://192.168.1.92/easycall/cmd?funcName=check</a>;
<p>private String getBillingForEasytouch(String urlParam){<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;String result="";<br />
&nbsp;&nbsp;try{<br />
&nbsp;&nbsp;URL url = new URL(urlParam);&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;URLConnection connection = url.openConnection(); <br />
&nbsp;&nbsp;connection.setDoOutput(true);<br />
&nbsp;&nbsp;OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream(), "utf-8");&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;Integer easytouchServiceId = easyTouchConfig<br />
&nbsp;&nbsp;.getInteger(Constants.CEM_EASYTOUCH_SERVICE_ID);</p>
<p>&nbsp;&nbsp;String pwd = easyTouchConfig<br />
&nbsp;&nbsp;.getString(Constants.BILLING_FOR_EASYTOUCH_PWD);&nbsp;&nbsp;<br />
&nbsp;&nbsp;out.write("c=siteId:"+siteId+",pwd:"+pwd+",serviceId:"+easytouchServiceId+"&amp;s=0");&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;out.flush();<br />
&nbsp;&nbsp;out.close();</p>
<p>&nbsp;&nbsp;&nbsp;BufferedReader in = new BufferedReader(new InputStreamReader(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connection.getInputStream()));<br />
&nbsp;&nbsp;&nbsp;String line;<br />
&nbsp;&nbsp;&nbsp;while ((line = in.readLine()) != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;result += line;<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;in.close();<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;catch(Exception e){<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;return result;<br />
&nbsp;}<br />
</p>
<img src ="http://www.blogjava.net/hummer008/aggbug/205341.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-06-02 15:13 <a href="http://www.blogjava.net/hummer008/articles/205341.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>性能问题排查</title><link>http://www.blogjava.net/hummer008/articles/201824.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Wed, 21 May 2008 01:32:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/201824.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/201824.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/201824.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/201824.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/201824.html</trackback:ping><description><![CDATA[<p>一 总结概要:<br />
1.首先解决问题的方向不对,没有证实靠猜测就盲目优化SQL语句.(其实SQL语句性能不慢的,猜测 in(11,22,33,...) 语句的性能问题)<br />
2.对早已经发现的问题熟视无睹,明明知道页面展现有性能问题(IT性能慢,FIREFOX正常没有引起足够的重视)<br />
3.在自己写纯SQL语句优化无结果的情况下,重新审视过去走过的弯路<br />
4.不要放过每个细节,自己思路一定要清晰,坚持就是胜利了</p>
<p>&nbsp;</p>
<p>二 实际操作过程:<br />
1.数据库环境 192.168.0.70&nbsp; cem_vcc<br />
2.需要优化的SQL语句</p>
<p>&nbsp; 基本SQL&nbsp; A:&nbsp;&nbsp;&nbsp; select vl.*&nbsp; from vccrawlog vl, <br />
&nbsp;&nbsp;&nbsp;cem_cc_operator op,<br />
&nbsp;&nbsp;&nbsp;cem_cc_operator_acd_group ag <br />
&nbsp;&nbsp;&nbsp;where op.user_id=ag.user_id and ag.site_id=op.site_id<br />
&nbsp;&nbsp;&nbsp;and ag.site_id=2010010&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;and auto_rec_name is not null and is_rec_deleted=0&nbsp; and endtime is not null <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and&nbsp; vl.site_id=2010010<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and acd_group_id in <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (542,632,622,862,752,692,702,822,552,722,532,662,812,562,642,782,832,732,872,802,792,742,712,652) and ( (callee_id =op.site_extension and call_type=0 ) or( caller_id =op.site_extension and call_type=1&nbsp; )) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; order by sequence&nbsp;&nbsp; desc;</p>
<p>要求 1.A语句需要进行 COUNT(*) 操作<br />
&nbsp;&nbsp;&nbsp;&nbsp; 2.A语句需要进行 分页 </p>
<p><br />
业务简要说明: 查询VCCRAWLOG满足所有acd_group_id in <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (542,632,622,862,752,692,702,822,552,722,532,662,812,562,642,782,832,732,872,802,792,742,712,652) 里面座席数据.</p>
<p><br />
http://localhost:8080/vcc10/page/listRecords.action?&amp;site=8ins</p>
<p><br />
mysql 命令 </p>
<p>show create table vccrawlog;<br />
show index from vccrawlog;</p>
<p>SQL_NO_CACHE 不用缓存</p>
<p>select DISTINCT</p>
<p><br />
*************************************************<br />
&nbsp;1.COUNT语句</p>
<p>select sum(cnt) from <br />
(<br />
select count(*) cnt from vccrawlog vl, cem_cc_operator op, cem_cc_operator_acd_group ag <br />
where op.user_id=ag.user_id and ag.site_id=op.site_id<br />
&nbsp; and vl.site_id=op.site_id and vl.caller_id =op.site_extension and vl.call_type=1<br />
&nbsp; and ag.site_id=2010010 and vl.auto_rec_name is not null and vl.is_rec_deleted=0&nbsp; and vl.endtime is not null <br />
&nbsp; and ag.acd_group_id in (542,632,622,862,752,692,702,822,552,722,532,662,812,562,642,782,832,732,872,802,792,742,712,652)<br />
union all<br />
select count(*) cnt from vccrawlog vl, cem_cc_operator op, cem_cc_operator_acd_group ag <br />
where op.user_id=ag.user_id and ag.site_id=op.site_id<br />
&nbsp; and vl.site_id=op.site_id and vl.callee_id =op.site_extension and vl.call_type=0<br />
&nbsp; and ag.site_id=2010010 and vl.auto_rec_name is not null and vl.is_rec_deleted=0&nbsp; and vl.endtime is not null <br />
&nbsp; and ag.acd_group_id in (542,632,622,862,752,692,702,822,552,722,532,662,812,562,642,782,832,732,872,802,792,742,712,652)<br />
) a;</p>
<p>说明 通过union all 可以分别利用 caller_id 和 callee_id索引</p>
<p><br />
****************************************************</p>
<p><br />
2 .countSql:</p>
<p>select sum(cnt) from <br />
(<br />
select count(*) cnt from vccrawlog vl, ( select op.site_id,op.site_extension from cem_cc_operator op, cem_cc_operator_acd_group ag <br />
where op.user_id=ag.user_id and ag.site_id=op.site_id<br />
&nbsp; and ag.site_id=2010010<br />
&nbsp; and ag.acd_group_id in (542,632,622,862,752,692,702,822,552,722,532,662,812,562,642,782,832,732,872,802,792,742,712,652)<br />
&nbsp; union select 2010010,20100108888 ) operators <br />
&nbsp; where vl.site_id=operators.site_id and vl.caller_id =operators.site_extension and vl.call_type=1<br />
&nbsp; and vl.auto_rec_name is not null and vl.is_rec_deleted=0&nbsp; and vl.endtime is not null <br />
&nbsp; <br />
union all<br />
select count(*) cnt from vccrawlog vl, ( select op.site_id,op.site_extension from cem_cc_operator op, cem_cc_operator_acd_group ag <br />
where op.user_id=ag.user_id and ag.site_id=op.site_id<br />
&nbsp; and ag.site_id=2010010<br />
&nbsp; and ag.acd_group_id in (542,632,622,862,752,692,702,822,552,722,532,662,812,562,642,782,832,732,872,802,792,742,712,652)<br />
&nbsp; union select 2010010,20100108888 ) operators <br />
&nbsp; where vl.site_id=operators.site_id and vl.callee_id =operators.site_extension and vl.call_type=0<br />
&nbsp; and vl.auto_rec_name is not null and vl.is_rec_deleted=0&nbsp; and vl.endtime is not null <br />
) a;</p>
<p>说明:<br />
select op.site_id,op.site_extension from cem_cc_operator op, cem_cc_operator_acd_group ag <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; where op.user_id=ag.user_id and ag.site_id=op.site_id&nbsp;&nbsp;&nbsp; and ag.site_id=2010010<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; and ag.acd_group_id in (542,632,622,862,752,692,702,822,552,722,532,662,812,562,642,782,832,732,872,802,792,742,712,652)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; union select 2010010,20100108888 </p>
<p>可以去掉大量的重复数据</p>
<p>******************************************************************************</p>
<p><br />
页面性能排查:</p>
<p>&nbsp; 1.逐步执行 <br />
&nbsp;&nbsp;&nbsp; &lt;script language="javascript"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert('aaaaaaa');<br />
&nbsp;&nbsp;&nbsp; &lt;/script&gt;</p>
<p>&nbsp;&nbsp; 2.暂时删除觉得没有问题的部分</p>
<p><br />
&nbsp;</p>
<img src ="http://www.blogjava.net/hummer008/aggbug/201824.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-05-21 09:32 <a href="http://www.blogjava.net/hummer008/articles/201824.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mysql explain 分析说明</title><link>http://www.blogjava.net/hummer008/articles/200045.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Mon, 12 May 2008 08:36:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/200045.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/200045.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/200045.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/200045.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/200045.html</trackback:ping><description><![CDATA[EXPLAIN列的解释： <br />
<br />
table <br />
显示这一行的数据是关于哪张表的 <br />
<br />
type <br />
这是重要的列，显示连接使用了何种类型。从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和ALL <br />
<br />
possible_keys <br />
显示可能应用在这张表中的索引。如果为空，没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句 <br />
<br />
key <br />
实际使用的索引。如果为NULL，则没有使用索引。很少的情况下，MYSQL会选择优化不足的索引。这种情况下，可以在SELECT语句中使用USE INDEX（indexname）来强制使用一个索引或者用IGNORE INDEX（indexname）来强制MYSQL忽略索引 <br />
<br />
key_len <br />
使用的索引的长度。在不损失精确性的情况下，长度越短越好 <br />
<br />
ref <br />
显示索引的哪一列被使用了，如果可能的话，是一个常数 <br />
<br />
rows <br />
MYSQL认为必须检查的用来返回请求数据的行数 <br />
<br />
Extra <br />
关于MYSQL如何解析查询的额外信息。将在表4.3中讨论，但这里可以看到的坏的例子是Using temporary和Using filesort，意思MYSQL根本不能使用索引，结果是检索会很慢 <br />
<br />
<br />
<br />
<br />
extra列返回的描述的意义 <br />
<br />
Distinct <br />
一旦MYSQL找到了与行相联合匹配的行，就不再搜索了 <br />
<br />
Not exists <br />
MYSQL优化了LEFT JOIN，一旦它找到了匹配LEFT JOIN标准的行， <br />
<br />
就不再搜索了 <br />
<br />
Range checked for each <br />
<br />
Record（index map:#） <br />
没有找到理想的索引，因此对于从前面表中来的每一个行组合，MYSQL检查使用哪个索引，并用它来从表中返回行。这是使用索引的最慢的连接之一 <br />
<br />
Using filesort <br />
看到这个的时候，查询就需要优化了。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行 <br />
<br />
Using index <br />
列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的，这发生在对表的全部的请求列都是同一个索引的部分的时候 <br />
<br />
Using temporary <br />
看到这个的时候，查询需要优化了。这里，MYSQL需要创建一个临时表来存储结果，这通常发生在对不同的列集进行ORDER BY上，而不是GROUP BY上 <br />
<br />
Where used <br />
使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行，并且连接类型ALL或index，这就会发生，或者是查询有问题 <br />
<br />
<br />
<br />
<br />
不同连接类型的解释（按照效率高低的顺序排序） <br />
<br />
system <br />
表只有一行：system表。这是const连接类型的特殊情况 <br />
<br />
const <br />
表中的一个记录的最大值能够匹配这个查询（索引可以是主键或惟一索引）。因为只有一行，这个值实际就是常数，因为MYSQL先读这个值然后把它当做常数来对待 <br />
<br />
eq_ref <br />
在连接中，MYSQL在查询时，从前面的表中，对每一个记录的联合都从表中读取一个记录，它在查询使用了索引为主键或惟一键的全部时使用 <br />
<br />
ref <br />
这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分（比如，利用最左边前缀）时发生。对于之前的表的每一个行联合，全部记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好 <br />
<br />
range <br />
这个连接类型使用索引返回一个范围中的行，比如使用&gt;或&lt;查找东西时发生的情况 <br />
<br />
index <br />
这个连接类型对前面的表中的每一个记录联合进行完全扫描（比ALL更好，因为索引一般小于表数据） <br />
<br />
ALL <br />
这个连接类型对于前面的每一个记录联合进行完全扫描，这一般比较糟糕，应该尽量避免 <br />
<img src ="http://www.blogjava.net/hummer008/aggbug/200045.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-05-12 16:36 <a href="http://www.blogjava.net/hummer008/articles/200045.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate缓存管理(二) </title><link>http://www.blogjava.net/hummer008/articles/192118.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Fri, 11 Apr 2008 03:27:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/192118.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/192118.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/192118.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/192118.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/192118.html</trackback:ping><description><![CDATA[&nbsp;
<p style="text-indent: 12pt; text-align: left" align="left"><span style="font-size: 12pt; font-family: 宋体">hibernate</span><span style="font-size: 12pt; font-family: 宋体">可以用两种不同的对象缓存：first-level cache 和 second-level cache。first-level cache和Session对象关联，而second-level cache是和Session Factory对象关联。</span></p>
<p style="text-align: left" align="left"><span style="font-size: 12pt; font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><strong><span style="font-size: 12pt; font-family: 宋体">缺省地，</span></strong><strong><span style="font-size: 12pt; font-family: Arial">hibernate</span></strong><strong><span style="font-size: 12pt; font-family: 宋体">已经使用基于每个事务的</span></strong><strong><span style="font-size: 12pt; font-family: Arial">first-level cache</span></strong><span style="font-size: 12pt; font-family: 宋体">。</span><span style="font-size: 12pt; font-family: Arial"> Hibernate</span><span style="font-size: 12pt; font-family: 宋体">用</span><span style="font-size: 12pt; font-family: Arial">first-level cache</span><span style="font-size: 12pt; font-family: 宋体">主要是减少在一个事务内的</span><span style="font-size: 12pt; font-family: Arial">sql</span><span style="font-size: 12pt; font-family: 宋体">查询数量。例如，如果一个对象在同一个事务内被修改多次，</span><span style="font-size: 12pt; font-family: Arial">hibernate</span><span style="font-size: 12pt; font-family: 宋体">将只生成一个包括所有修改的</span><span style="font-size: 12pt; font-family: Arial"> UPDATE SQL</span><span style="font-size: 12pt; font-family: 宋体">语句。为了减少数据流动，</span><span style="font-size: 12pt; font-family: Arial">second-level cache</span><span style="font-size: 12pt; font-family: 宋体">在</span><span style="font-size: 12pt; font-family: Arial">Session Factory</span><span style="font-size: 12pt; font-family: 宋体">级的不同事务之间保持</span><span style="font-size: 12pt; font-family: Arial">load</span><span style="font-size: 12pt; font-family: 宋体">的对象，这些对象对整个应用可用，不只是对当前用户正在运行的查询。这样，每次查询将返回已经</span><span style="font-size: 12pt; font-family: Arial">load</span><span style="font-size: 12pt; font-family: 宋体">在缓存</span><span style="font-size: 12pt; font-family: 宋体">里的对象，避免一个或更多潜在的数据库事务。</span></p>
<p style="text-align: left" align="left"><span style="font-size: 12pt; font-family: 宋体">下载<a href="http://ehcache.sourceforge.net/"><strong><span style="color: #4169aa">ehcache</strong></a></span>，hibernate3.2必须要ehcache1.2以上才能支持。可以修改log4j配置文件log4j.logger.net.sf.hibernate.cache=debug查看日志</span></p>
<p>1.在类路径上<span style="font-family: Arial">ehcache.xml</span>：</p>
<p><span style="font-family: Arial">&lt;ehcache&gt;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;diskStore path="java.io.tmpdir"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;defaultCache<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxElementsInMemory="10000"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eternal="false"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overflowToDisk="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToIdleSeconds="120"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToLiveSeconds="120"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; diskPersistent="false"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; diskExpiryThreadIntervalSeconds="120"/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;<br />
&lt;/ehcache&gt;</span></p>
<p style="text-align: left" align="left"><span style="font-size: 12pt; font-family: 宋体">2.</span><span style="font-size: 12pt; font-family: Arial">applicationContext-hibernate.xml</span><span style="font-size: 12pt; font-family: 宋体">里</span><span style="font-size: 12pt; font-family: Arial">Hibernate SessionFactory</span><span style="font-size: 12pt; font-family: 宋体">配置：</span></p>
<p style="text-align: left" align="left"><span style="font-size: 12pt; font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="hibernateProperties"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;props&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="hibernate.dialect"&gt;@HIBERNATE-DIALECT@&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!--&lt;prop key="hibernate.show_sql"&gt;true&lt;/prop&gt;--&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="hibernate.max_fetch_depth"&gt;3&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="hibernate.hibernate.use_outer_join"&gt;true&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="hibernate.jdbc.batch_size"&gt;10&lt;/prop&gt;<br />
<strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="hibernate.cache.use_query_cache"&gt;true&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key="hibernate.cache.use_second_level_cache"&gt;true&lt;/prop&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="hibernate.cache.provider_class"&gt;org.hibernate.cache.EhCacheProvider&lt;/prop&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p>
<p style="text-align: left" align="left"><span style="font-size: 12pt; font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/props&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br />
</span><span style="font-size: 12pt; font-family: 宋体">说明：如果不设置</span><span style="font-size: 12pt; font-family: Arial">&#8220;</span><span style="font-size: 12pt; font-family: 宋体">查询缓存</span><span style="font-size: 12pt; font-family: Arial">&#8221;</span><span style="font-size: 12pt; font-family: 宋体">，那么</span><span style="font-size: 12pt; font-family: Arial">hibernate</span><span style="font-size: 12pt; font-family: 宋体">只会缓存使用</span><span style="font-size: 12pt; font-family: Arial">load()</span><span style="font-size: 12pt; font-family: 宋体">方法获得的单个持久化对象，如果想缓存使用</span><span style="font-size: 12pt; font-family: Arial">findall()</span><span style="font-size: 12pt; font-family: 宋体">、</span><span style="font-size: 12pt; font-family: Arial"> list()</span><span style="font-size: 12pt; font-family: 宋体">、</span><span style="font-size: 12pt; font-family: Arial">Iterator()</span><span style="font-size: 12pt; font-family: 宋体">、</span><span style="font-size: 12pt; font-family: Arial">createCriteria()</span><span style="font-size: 12pt; font-family: 宋体">、</span><span style="font-size: 12pt; font-family: Arial">createQuery()</span><span style="font-size: 12pt; font-family: 宋体">等方法获得的数据结果集的话，就需要设置</span><span style="font-size: 12pt; font-family: Arial"> hibernate.cache.use_query_cache true </span><span style="font-size: 12pt; font-family: 宋体">才行</span></p>
<p style="text-align: left" align="left"><span style="font-size: 12pt; font-family: Arial">.</span><span style="font-size: 12pt; font-family: 宋体">对于</span><span style="font-size: 12pt; font-family: Arial">"query cache"</span><span style="font-size: 12pt; font-family: 宋体">，需要在程序里编码：</span></p>
<p><span style="font-size: 12pt; font-family: Arial">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getHibernateTemplate().setCacheQueries(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return getHibernateTemplate().find(hql);</span></p>
</strong>
<img src ="http://www.blogjava.net/hummer008/aggbug/192118.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-04-11 11:27 <a href="http://www.blogjava.net/hummer008/articles/192118.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate缓存管理(一)</title><link>http://www.blogjava.net/hummer008/articles/192109.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Fri, 11 Apr 2008 03:14:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/192109.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/192109.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/192109.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/192109.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/192109.html</trackback:ping><description><![CDATA[&nbsp; ehcache.xml文件：<br />
&nbsp;
<p style="text-align: left" align="left"><span style="font-size: 12pt; font-family: 宋体">下载<a href="http://ehcache.sourceforge.net/"><strong><span style="color: #4169aa">ehcache</strong></a></span>，hibernate3.2必须要ehcache1.2以上才能支持。可以修改log4j配置文件log4j.logger.net.sf.hibernate.cache=debug查看日志</span></p>
<br />
&lt; ehcache&gt;<br />
&nbsp;&nbsp;&nbsp; &lt; diskStore path="c:\\ehcache\"/&gt; <br />
&nbsp;&nbsp;&nbsp; &lt; defaultCache <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxElementsInMemory="10000" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eternal="false" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToIdleSeconds="120" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToLiveSeconds="120" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overflowToDisk="true"&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt; !-- 设置Category类的缓存的数据过期策略 --&gt;<br />
&nbsp;&nbsp;&nbsp; &lt; cache name="org.qiujy.domain.cachedemo.Category"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxElementsInMemory="100"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eternal="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToIdleSeconds="0"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToLiveSeconds="0"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overflowToDisk="false"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt; !-- 设置Category类的products集合的缓存的数据过期策略 --&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt; cache name="org.qiujy.domain.cachedemo.Category.products"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxElementsInMemory="500"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eternal="false"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToIdleSeconds="300"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToLiveSeconds="600"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overflowToDisk="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt; cache name="org.qiujy.domain.cachedemo.Product"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxElementsInMemory="500"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eternal="false"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToIdleSeconds="300"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeToLiveSeconds="600"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; overflowToDisk="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /&gt;<br />
&nbsp;&nbsp;&nbsp; <br />
&lt; /ehcache&gt;
<p><font face="Times New Roman" size="3">配置的元素说明：<br />
元素或属性 描述 <br />
&lt; diskStore&gt; 设置缓存数据文件的存放目录 <br />
&lt; defaultCache&gt; 设置缓存的默认数据过期策略 <br />
&lt; cache&gt; 设定具体的命名缓存的数据过期策略<br />
每个命名缓存代表一个缓存区域，每个缓存区域有各自的数据过期策略。命名缓存机制使得用户能够在每个类以及类的每个集合的粒度上设置数据过期策略。 <br />
cache元素的属性&nbsp;&nbsp; <br />
name 设置缓存的名字,它的取值为类的全限定名或类的集合的名字 <br />
maxInMemory 设置基于内存的缓存中可存放的对象最大数目 <br />
eternal 设置对象是否为永久的,true表示永不过期,此时将忽略timeToIdleSeconds和timeToLiveSeconds属性;<br />
默认值是false <br />
timeToIdleSeconds 设置对象空闲最长时间,超过这个时间,对象过期。当对象过期时,EHCache会把它从缓存中清除。<br />
如果此值为0,表示对象可以无限期地处于空闲状态。 <br />
timeToLiveSeconds 设置对象生存最长时间,超过这个时间,对象过期。<br />
如果此值为0,表示对象可以无限期地存在于缓存中。 <br />
overflowToDisk 设置基于内在的缓存中的对象数目达到上限后,是否把溢出的对象写到基于硬盘的缓存中 </font></p>
<img src ="http://www.blogjava.net/hummer008/aggbug/192109.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-04-11 11:14 <a href="http://www.blogjava.net/hummer008/articles/192109.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>构建WEBTEST工程</title><link>http://www.blogjava.net/hummer008/articles/191521.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Tue, 08 Apr 2008 08:03:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/191521.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/191521.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/191521.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/191521.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/191521.html</trackback:ping><description><![CDATA[&nbsp;
<p style="text-align: center" align="center"><strong><span style="font-size: 16pt; font-family: 楷体_GB2312">构建WEBTEST工程</span></strong></p>
<p style="margin-left: 27pt; text-indent: -18pt; tab-stops: list 27.0pt">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><a href="http://webtest.canoo.com/webtest/manual/Downloads.html">http://webtest.canoo.com/webtest/manual/Downloads.html</a> <span style="font-family: 宋体">下载</span>webTest<span style="font-family: 宋体">相关的</span> <span style="font-size: 8.5pt; font-family: Arial"><a href="http://webtest.canoo.com/webtest/build.zip">build.zip</a></span></p>
<p style="margin-left: 9.05pt; text-indent: 21pt"><span style="font-family: 宋体">并</span>unzip<span style="font-family: 宋体">到</span> d:"dev"webtest<span style="font-family: 宋体">目录</span></p>
<p style="margin-left: 27pt; text-indent: -18pt; tab-stops: list 27.0pt">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">安装</span> ant <span style="font-size: 10pt; color: #313063; font-family: 宋体">下载</span><span style="font-size: 10pt; color: #313063; font-family: Verdana">ant</span><span style="font-size: 10pt; color: #313063; font-family: 宋体">的网址：</span><span style="font-size: 10pt; color: #313063; font-family: Verdana"><a href="http://ant.apache.org/">http://ant.apache.org/</a> (version 1.7.0) </span></p>
<p style="margin-left: 9pt; text-indent: 21pt"><span style="font-size: 10pt; color: #313063; font-family: Verdana">ANT_HOME=d:"dev"ant</span></p>
<p style="margin-left: 9pt; text-indent: 21pt"><span style="font-size: 10pt; color: #313063; font-family: Verdana">PATH=&#8230;%ANT_HOME%"bin</span></p>
<p style="margin-left: 27pt; text-indent: -18pt; tab-stops: list 27.0pt"><span style="color: #313063">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 10pt; color: #313063; font-family: 宋体">使用</span><span style="font-size: 10pt; color: #313063; font-family: Verdana"> ANT </span><span style="font-size: 10pt; color: #313063; font-family: 宋体">创建</span><span style="font-size: 10pt; color: #313063; font-family: Verdana">webtest</span><span style="font-size: 10pt; color: #313063; font-family: 宋体">工程</span><span style="font-size: 10pt; color: #313063; font-family: 宋体">先进入</span><span style="font-size: 10pt; color: #313063; font-family: 宋体">命令窗口</span></p>
<p style="margin-left: 27pt"><span style="font-size: 10pt; color: #313063; font-family: Verdana">d:"dev&gt;ant &#8211;f webtest"webtest.xml wt.createProject</span></p>
<p style="margin-left: 27pt"><span style="font-size: 10pt; color: #313063; font-family: 宋体">创建成功默认</span><span style="font-size: 10pt; color: #313063; font-family: Verdana">myWebTestProject </span><span style="font-size: 10pt; color: #313063; font-family: 宋体">工程</span></p>
<p style="margin-left: 27pt; text-indent: -18pt; tab-stops: list 27.0pt"><span style="color: #313063">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 10pt; color: #313063; font-family: Verdana">RUN demo tests</span></p>
<p style="margin-left: 27pt"><span style="font-size: 10pt; color: #313063; font-family: Verdana">d:"dev"myWebTestProject&gt;ant </span></p>
<p style="margin-left: 27pt; text-indent: -18pt; tab-stops: list 27.0pt"><span style="color: #313063">5.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 10pt; color: #313063; font-family: Verdana">test report </span><span style="font-size: 10pt; color: #313063; font-family: Wingdings">&#224;</span><span style="font-size: 10pt; color: #313063; font-family: 宋体">浏览器自动会打开测试报告</span></p>
<p style="margin-left: 27pt; text-indent: -18pt; tab-stops: list 27.0pt"><span style="color: #313063">6.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-size: 10pt; color: #313063; font-family: 宋体">把工程导入</span><span style="font-size: 10pt; color: #313063; font-family: Verdana">eclipse</span></p>
<p style="margin-left: 9pt">googleWebTest.xml <span style="font-family: 宋体">文件如下</span></p>
<p style="margin-left: 9pt"><span style="font-family: 宋体">具体的资料</span> <a href="http://webtest.canoo.com/webtest/manual/stepIndex.html">http://webtest.canoo.com/webtest/manual/stepIndex.html</a></p>
<p style="margin-left: 9pt">Webtest<span style="font-family: 宋体">特性总结如下</span>:</p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">1.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>webtest<span style="font-family: 宋体">模拟</span>Firefox<span style="font-family: 宋体">和</span> Internet Explorer<span style="font-family: 宋体">方式执行</span>JavaScript.</p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">2.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">不接收格式不正确的</span>HTML</p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">3.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">容易扩展和整合</span></p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">4.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>webtest<span style="font-family: 宋体">是纯</span>java<span style="font-family: 宋体">编写的</span>,<span style="font-family: 宋体">可以运行在有</span>JDK<span style="font-family: 宋体">的任何机器上</span>.</p>
<p style="margin-left: 18pt; text-indent: -18pt; tab-stops: list 18.0pt">5.<span style="font: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体">完美的结果报告</span>,<span style="font-family: 宋体">特别列出出错</span>case<span style="font-family: 宋体">的原因</span></p>
<img src ="http://www.blogjava.net/hummer008/aggbug/191521.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-04-08 16:03 <a href="http://www.blogjava.net/hummer008/articles/191521.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>selenium亲自RUN的实例（转载）</title><link>http://www.blogjava.net/hummer008/articles/185725.html</link><dc:creator>hummer</dc:creator><author>hummer</author><pubDate>Wed, 12 Mar 2008 08:14:00 GMT</pubDate><guid>http://www.blogjava.net/hummer008/articles/185725.html</guid><wfw:comment>http://www.blogjava.net/hummer008/comments/185725.html</wfw:comment><comments>http://www.blogjava.net/hummer008/articles/185725.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hummer008/comments/commentRss/185725.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hummer008/services/trackbacks/185725.html</trackback:ping><description><![CDATA[<p><br />
一些准备：JRE1.5+ 和 浏览器要求</p>
<p><br />
Windows<br />
如果你用的是Windows XP 或者是Windows2003，你可以使用IE 浏览器，或者安装Mozilla Firefox 或者Opera浏览器。 <br />
如果你是用的是Windows2000，如果想使用IE浏览器，你就需要安装reg.exe，但是如果使用Firefox不需要。我们建议（但不是必须）将你的浏览器执行路径加到你的PATH环境变量中（如果你不知道如何将你的浏览器安装目录加到PATH中，那么你就必须将你的浏览器安装到标准路径下：Firefox的标准路径："c:\Program Files\Mozilla Firefox\firefox.exe"；IE浏览器的标准路径："c:\Program Files\Internet Explorer\iexplore.exe"）</p>
<p>&nbsp;</p>
<p>1. 先去 http://selenium-rc.openqa.org/download.jsp 下载selenium包。解压。 </p>
<p>2. 用命令行来到解压的文件夹下： \selenium-remote-control-0.9.2\selenium-server-0.9.2</p>
<p>3. 运行： java -jar selenium-server.jar 启动selenium server</p>
<p>4. 在Eclipse创建一个项目，在项目的build path里面加上junit.jar和selenium-java-client-driver.jar（这个在刚解压的包里面）</p>
<p>5. 然后在Eclipse里运行 &#8220;Run As -&gt; unit Test&#8221;即可看到自动化的范例</p>
<p>&nbsp;</p>
<p>最后粘贴一下那个测试程序</p>
<p>&nbsp;</p>
<p>import com.thoughtworks.selenium.DefaultSelenium;<br />
import com.thoughtworks.selenium.Selenium;</p>
<p>import junit.framework.TestCase;</p>
<p>public class GoogleTest extends TestCase {<br />
&nbsp;&nbsp;&nbsp; private Selenium selenium;</p>
<p>&nbsp;&nbsp;&nbsp; public void setUp() throws Exception {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String url = "http://www.google.com";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; selenium = new DefaultSelenium("localhost", 4444, "*firefox", url);&nbsp; //4444 is default server port </p>
<p>&nbsp;&nbsp; selenium.start();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; protected void tearDown() throws Exception {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; selenium.stop();<br />
&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public void testGoogle() throws Throwable {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; selenium.open("http://www.google.com/webhp?hl=en");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assertEquals("Google", selenium.getTitle());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; selenium.type("q", "Selenium OpenQA");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assertEquals("Selenium OpenQA", selenium.getValue("q"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; selenium.click("btnG");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; selenium.waitForPageToLoad("5000");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assertEquals("Selenium OpenQA - Google Search", selenium.getTitle());<br />
&nbsp;&nbsp;&nbsp; }<br />
} </p>
<p><br />
相关资料：&nbsp;<br />
</p>
<p><a href="http://www.blogjava.net/becky/archive/2008/03/06/184267.html">http://www.blogjava.net/becky/archive/2008/03/06/184267.html</a><br />
</p>
<p>http://www.javaeye.com/topic/160592&nbsp;</p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/hummer008/aggbug/185725.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hummer008/" target="_blank">hummer</a> 2008-03-12 16:14 <a href="http://www.blogjava.net/hummer008/articles/185725.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>