﻿<?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-像一颗晨土-文章分类-learn more</title><link>http://www.blogjava.net/aichan/category/8882.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 05:01:50 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 05:01:50 GMT</pubDate><ttl>60</ttl><item><title> Hibernate二级缓存攻略（转载）</title><link>http://www.blogjava.net/aichan/articles/63483.html</link><dc:creator>艾尘</dc:creator><author>艾尘</author><pubDate>Mon, 14 Aug 2006 07:11:00 GMT</pubDate><guid>http://www.blogjava.net/aichan/articles/63483.html</guid><wfw:comment>http://www.blogjava.net/aichan/comments/63483.html</wfw:comment><comments>http://www.blogjava.net/aichan/articles/63483.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/aichan/comments/commentRss/63483.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/aichan/services/trackbacks/63483.html</trackback:ping><description><![CDATA[
		<span class="postbody">作者：AreYouOk<br />文档来自：<a href="http://forum.javaeye.com/viewtopic.php?t=18904">http://forum.javaeye.com/viewtopic.php?t=18904</a><br />很多人对二级缓存都不太了解，或者是有错误的认识，我一直想写一篇文章介绍一下hibernate的二级缓存的，今天终于忍不住了。<br />我的经验主要来自hibernate2.1版本，基本原理和3.0、3.1是一样的，请原谅我的顽固不化。<br /><br />hibernate的session提供了一级缓存，每个session，对同一个id进行两次load，不会发送两条sql给数据库，但是session关闭的时候，一级缓存就失效了。<br /><br />二级缓存是SessionFactory级别的全局缓存，它底下可以使用不同的缓存类库，比如ehcache、oscache等，需要设置hibernate.cache.provider_class，我们这里用ehcache，在2.1中就是<br />hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider<br />如果使用查询缓存，加上<br />hibernate.cache.use_query_cache=true<br /><br /><br />缓存可以简单的看成一个Map，通过key在缓存里面找value。<br /><br /><span style="font-weight: bold;">Class的缓存</span><br />对
于一条记录，也就是一个PO来说，是根据ID来找的，缓存的key就是ID，value是POJO。无论list，load还是iterate，只要读出
一个对象，都会填充缓存。但是list不会使用缓存，而iterate会先取数据库select
id出来，然后一个id一个id的load，如果在缓存里面有，就从缓存取，没有的话就去数据库load。假设是读写缓存，需要设置：<br /><cache usage="read-write"><br />如果你使用的二级缓存实现是ehcache的话，需要配置ehcache.xml<br /><cache name="com.xxx.pojo.Foo" maxelementsinmemory="500" eternal="false" timetoliveseconds="7200" timetoidleseconds="3600" overflowtodisk="true"><br />其
中eternal表示缓存是不是永远不超时，timeToLiveSeconds是缓存中每个元素（这里也就是一个POJO）的
超时时间，如果eternal="false"，超过指定的时间，这个元素就被移走了。timeToIdleSeconds是发呆时间，是可选的。当往缓
存里面put的元素超过500个时，如果overflowToDisk="true"，就会把缓存中的部分数据保存在硬盘上的临时文件里面。<br />每个需要缓存的class都要这样配置。如果你没有配置，hibernate会在启动的时候警告你，然后使用defaultCache的配置，这样多个class会共享一个配置。<br />当某个ID通过hibernate修改时，hibernate会知道，于是移除缓存。<br />这
样大家可能会想，同样的查询条件，第一次先list，第二次再iterate，就可以使用到缓存了。实际上这是很难的，因为你无法判断什么时候是第一次，
而且每次查询的条件通常是不一样的，假如数据库里面有100条记录，id从1到100，第一次list的时候出了前50个id，第二次iterate的时
候却查询到30至70号id，那么30-50是从缓存里面取的，51到70是从数据库取的，共发送1+20条sql。所以我一直认为iterate没有什
么用，总是会有1+N的问题。<br />（题外话：有说法说大型查询用list会把整个结果集装入内存，很慢，而iterate只select
id比较好，但是大型查询总是要分页查的，谁也不会真的把整个结果集装进来，假如一页20条的话，iterate共需要执行21条语句，list虽然选择
若干字段，比iterate第一条select
id语句慢一些，但只有一条语句，不装入整个结果集hibernate还会根据数据库方言做优化，比如使用mysql的limit，整体看来应该还是
list快。）<br />如果想要对list或者iterate查询的结果缓存，就要用到查询缓存了<br /><br /><span style="font-weight: bold;">查询缓存</span><br />首先需要配置hibernate.cache.use_query_cache=true<br />如果用ehcache，配置ehcache.xml，注意hibernate3.0以后不是net.sf的包名了<br /><cache name="net.sf.hibernate.cache.StandardQueryCache"><br />maxElementsInMemory="50" eternal="false" timeToIdleSeconds="3600"<br />timeToLiveSeconds="7200" overflowToDisk="true"/&gt;<br /><cache name="net.sf.hibernate.cache.UpdateTimestampsCache"><br />maxElementsInMemory="5000" eternal="true" overflowToDisk="true"/&gt;<br />然后<br />query.setCacheable(true);//激活查询缓存<br />query.setCacheRegion("myCacheRegion");//指定要使用的cacheRegion，可选<br />第二行指定要使用的cacheRegion是myCacheRegion，即你可以给每个查询缓存做一个单独的配置，使用setCacheRegion来做这个指定，需要在ehcache.xml里面配置它：<br /><cache name="myCacheRegion" maxelementsinmemory="10" eternal="false" timetoidleseconds="3600" timetoliveseconds="7200" overflowtodisk="true"><br />如果省略第二行，不设置cacheRegion的话，那么会使用上面提到的标准查询缓存的配置，也就是net.sf.hibernate.cache.StandardQueryCache<br /><br />对于查询缓存来说，缓存的key是根据hql生成的sql，再加上参数，分页等信息（可以通过日志输出看到，不过它的输出不是很可读，最好改一下它的代码）。<br />比如hql：<br />from Cat c where c.name like ?<br />生成大致如下的sql：<br />select * from cat c where c.name like ?<br />参数是"tiger%"，那么查询缓存的key*大约*是这样的字符串（我是凭记忆写的，并不精确，不过看了也该明白了）：<br />select * from cat c where c.name like ? , parameter:tiger%<br />这样，保证了同样的查询、同样的参数等条件下具有一样的key。<br />现
在说说缓存的value，如果是list方式的话，value在这里并不是整个结果集，而是查询出来的这一串ID。也就是说，不管是list方法还是
iterate方法，第一次查询的时候，它们的查询方式很它们平时的方式是一样的，list执行一条sql，iterate执行1+N条，多出来的行为是
它们填充了缓存。但是到同样条件第二次查询的时候，就都和iterate的行为一样了，根据缓存的key去缓存里面查到了value，value是一串
id，然后在到class的缓存里面去一个一个的load出来。这样做是为了节约内存。<br />可以看出来，查询缓存需要打开相关类的class缓存。list和iterate方法第一次执行的时候，都是既填充查询缓存又填充class缓存的。<br /><span style="font-weight: bold;">这里还有一个很容易被忽视的重要问题，即打开查询缓存以后，即使是list方法也可能遇到1+N的问题！</span>相
同条件第一次list的时候，因为查询缓存中找不到，不管class缓存是否存在数据，总是发送一条sql语句到数据库获取全部数据，然后填充查询缓存和
class缓存。但是第二次执行的时候，问题就来了，如果你的class缓存的超时时间比较短，现在class缓存都超时了，但是查询缓存还在，那么
list方法在获取id串以后，将会一个一个去数据库load！因此，class缓存的超时时间一定不能短于查询缓存设置的超时时间！如果还设置了发呆时
间的话，保证class缓存的发呆时间也大于查询的缓存的生存时间。这里还有其他情况，比如class缓存被程序强制evict了，这种情况就请自己注意
了。<br /><br />另外，如果hql查询包含select字句，那么查询缓存里面的value就是整个结果集了。<br /><br />当hibernate更新数据库的时候，它怎么知道更新哪些查询缓存呢？<br />hibernate在一个地方维护每个表的最后更新时间，其实也就是放在上面net.sf.hibernate.cache.UpdateTimestampsCache所指定的缓存配置里面。<br />当
通过hibernate更新的时候，hibernate会知道这次更新影响了哪些表。然后它更新这些表的最后更新时间。每个缓存都有一个生成时间和这个缓
存所查询的表，当hibernate查询一个缓存是否存在的时候，如果缓存存在，它还要取出缓存的生成时间和这个缓存所查询的表，然后去查找这些表的最后
更新时间，如果有一个表在生成时间后更新过了，那么这个缓存是无效的。<br />可以看出，只要更新过一个表，那么凡是涉及到这个表的查询缓存就失效了，因此查询缓存的命中率可能会比较低。<br /><br /><span style="font-weight: bold;">Collection缓存</span><br />需要在hbm的collection里面设置<br /><cache usage="read-write"><br />假如class是Cat，collection叫children，那么ehcache里面配置<br /><cache name="com.xxx.pojo.Cat.children"><br />maxElementsInMemory="20" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200"<br />overflowToDisk="true" /&gt;<br />Collection的缓存和前面查询缓存的list一样，也是只保持一串id，但它不会因为这个表更新过就失效，一个collection缓存仅在这个collection里面的元素有增删时才失效。<br />这样有一个问题，如果你的collection是根据某个字段排序的，当其中一个元素更新了该字段时，导致顺序改变时，collection缓存里面的顺序没有做更新。<br /><br /><span style="font-weight: bold;">缓存策略</span><br />只读缓存（read-only）：没有什么好说的<br />读/写缓存（read-write）:程序可能要的更新数据<br />不严格的读/写缓存（nonstrict-read-write）：需要更新数据，但是两个事务更新同一条记录的可能性很小，性能比读写缓存好<br />事务缓存（transactional）：缓存支持事务，发生异常的时候，缓存也能够回滚，只支持jta环境，这个我没有怎么研究过<br /><br />读写缓存和不严格读写缓存在实现上的区别在于，读写缓存更新缓存的时候会把缓存里面的数据换成一个锁，其他事务如果去取相应的缓存数据，发现被锁住了，然后就直接取数据库查询。<br />在hibernate2.1的ehcache实现中，如果锁住部分缓存的事务发生了异常，那么缓存会一直被锁住，直到60秒后超时。<br />不严格读写缓存不锁定缓存中的数据。<br /><br /><br /><span style="font-weight: bold;">使用二级缓存的前置条件</span><br />你
的hibernate程序对数据库有独占的写访问权，其他的进程更新了数据库，hibernate是不可能知道的。你操作数据库必需直接通过
hibernate，如果你调用存储过程，或者自己使用jdbc更新数据库，hibernate也是不知道的。hibernate3.0的大批量更新和删
除是不更新二级缓存的，但是据说3.1已经解决了这个问题。<br />这个限制相当的棘手，有时候hibernate做批量更新、删除很慢，但是你却不能自己写jdbc来优化，很郁闷吧。<br />SessionFactory也提供了移除缓存的方法，你一定要自己写一些JDBC的话，可以调用这些方法移除缓存，这些方法是：<br />void evict(Class persistentClass)<br />Evict all entries from the second-level cache.<br />void evict(Class persistentClass, Serializable id)<br />Evict an entry from the second-level cache.<br />void evictCollection(String roleName)<br />Evict all entries from the second-level cache.<br />void evictCollection(String roleName, Serializable id)<br />Evict an entry from the second-level cache.<br />void evictQueries()<br />Evict any query result sets cached in the default query cache region.<br />void evictQueries(String cacheRegion)<br />Evict any query result sets cached in the named query cache region.<br />不
过我不建议这样做，因为这样很难维护。比如你现在用JDBC批量更新了某个表，有3个查询缓存会用到这个表，用evictQueries(String
cacheRegion)移除了3个查询缓存，然后用evict(Class
persistentClass)移除了class缓存，看上去好像完整了。不过哪天你添加了一个相关查询缓存，可能会忘记更新这里的移除代码。如果你的
jdbc代码到处都是，在你添加一个查询缓存的时候，还知道其他什么地方也要做相应的改动吗？<br /><br />----------------------------------------------------<br /><br /><span style="font-weight: bold;">总结：</span><br />不要想当然的以为缓存一定能提高性能，仅仅在你能够驾驭它并且条件合适的情况下才是这样的。hibernate的二级缓存限制还是比较多的，不方便用jdbc可能会大大的降低更新性能。在不了解原理的情况下乱用，可能会有1+N的问题。不当的使用还可能导致读出脏数据。<br />如果受不了hibernate的诸多限制，那么还是自己在应用程序的层面上做缓存吧。<br />在
越高的层面上做缓存，效果就会越好。就好像尽管磁盘有缓存，数据库还是要实现自己的缓存，尽管数据库有缓存，咱们的应用程序还是要做缓存。因为底层的缓存
它并不知道高层要用这些数据干什么，只能做的比较通用，而高层可以有针对性的实现缓存，所以在更高的级别上做缓存，效果也要好些吧。<br /><br /><br />终于写完了，好累……</cache></cache></cache></cache></cache></cache></cache></span>
<img src ="http://www.blogjava.net/aichan/aggbug/63483.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/aichan/" target="_blank">艾尘</a> 2006-08-14 15:11 <a href="http://www.blogjava.net/aichan/articles/63483.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>收藏一篇extremeComponents使用AJAX 指南</title><link>http://www.blogjava.net/aichan/articles/38314.html</link><dc:creator>艾尘</dc:creator><author>艾尘</author><pubDate>Thu, 30 Mar 2006 10:43:00 GMT</pubDate><guid>http://www.blogjava.net/aichan/articles/38314.html</guid><wfw:comment>http://www.blogjava.net/aichan/comments/38314.html</wfw:comment><comments>http://www.blogjava.net/aichan/articles/38314.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/aichan/comments/commentRss/38314.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/aichan/services/trackbacks/38314.html</trackback:ping><description><![CDATA[<table width="750" cellspacing="0" cellpadding="0" border="0" style="border: 1px dashed rgb(0, 0, 0);">
    <tbody>
        <tr>
            <td>
            <table width="98%" cellspacing="0" cellpadding="0" border="0" align="center">
                <tbody>
                    <tr>
                        <td><a class="style9" target="_blank" href="../../../lucky/archive/2006/03/27/37623.html">extremeComponents使用AJAX 指南</a> </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
        <tr>
            <td>
            <table width="98%" cellspacing="0" cellpadding="0" border="0" align="center">
                <tbody>
                    <tr>
                        <td><span class="style8">Mon, 27 Mar 2006 08:09:00 GMT</span> </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
        <tr>
            <td>
            <div class="style6">
            <table width="98%" cellspacing="0" cellpadding="0" border="0" align="center">
                <tbody>
                    <tr>
                        <td class="style6">
                        <h2>AJAX 指南</h2>
                        <p> 				<em>进行中...</em> 		</p>
                        <p> 				<br /> 在eXtremeTable中使用AJAX非常简单，对现有功能的扩展也非常方便。 AJAX整合一个最强大的地方是它不需要整合。你可以自由地使用任何你想要使用的AJAX工具包。所有你要做的就是：当表的action被调用时，告诉 eXtremeTable使用什么javascript。表的actions包括：过滤、排序、分页、显示的行数和导出。 </p>
                        <p>在我自己的示例中我将使用非常酷的<a rel="nofollow" title="http://getahead.ltd.uk/dwr/" class="external text" href="http://getahead.ltd.uk/dwr/">DWR</a>工具包。DWR 需要的粘合代码非常少，这样我们只需要关注如何构建表。你可以通过本站<a rel="nofollow" title="http://extremecomponents.org/extremesite/assembler.run" class="external text" href="http://extremecomponents.org/extremesite/assembler.run">示例</a>看到效果! </p>
                        <div style="float: right; margin-left: 5px;" class="editsection">[<a title="Simplified Chinese Tutorials AJAX" href="http://extremecomponents.org/wiki/index.php?title=Simplified_Chinese_Tutorials_AJAX&amp;action=edit&amp;section=3">edit</a>]</div>
                        <a name="Assembler_Example"> 		</a>
                        <h3> Assembler Example </h3>
                        <p>本示例中将需要安装DWR工具包，创建POJO来构造表并创建包含eXtremeTable的JSP页面。 </p>
                        <div style="float: right; margin-left: 5px;" class="editsection">[<a title="Simplified Chinese Tutorials AJAX" href="http://extremecomponents.org/wiki/index.php?title=Simplified_Chinese_Tutorials_AJAX&amp;action=edit&amp;section=4">edit</a>]</div>
                        <a name=".E5.AE.89.E8.A3.85DWR"> 		</a>
                        <h3> 安装DWR </h3>
                        <p>首先要做的就是<a rel="nofollow" title="http://getahead.ltd.uk/dwr/download" class="external text" href="http://getahead.ltd.uk/dwr/download">下载</a>DWR工具包。你应该浏览网站的使用说明，不过下面是我让它符合我的需要来工作所进行的操作: </p>
                        <ul>
                            <li> 将dwr-1.1.jar拷贝到WEB-INF/lib目录 </li>
                            <li> 在WEB-INF目录下创建一个dwr.xml文件 </li>
                        </ul>
                        <pre>&lt;!DOCTYPE dwr PUBLIC<br />    &quot;-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN&quot;<br />    &quot;http://www.getahead.ltd.uk/dwr/dwr10.dtd&quot;&gt;<br /><br />&lt;dwr&gt;<br />  &lt;allow&gt;<br />    &lt;create creator=&quot;new&quot; javascript=&quot;Assembler&quot;&gt;<br />      &lt;param name=&quot;class&quot; value=&quot;org.extremesite.controller.Assembler&quot;/&gt;<br />      &lt;include method=&quot;getTable&quot;/&gt;<br />    &lt;/create&gt;<br />  &lt;/allow&gt;<br />  &lt;signatures&gt;<br />    &lt;![CDATA[<br />       import java.util.Map;<br />       import java.util.List;<br />       import org.extremesite.controller.Assembler;<br />       import javax.servlet.http.HttpServletRequest;<br />       Assembler.getTable(Map&lt;String, List&gt; parameterMap, HttpServletRequest request);<br />       ]]&gt;<br />  &lt;/signatures&gt;<br />&lt;/dwr&gt;<br /></pre>
                        <p>简而言之（In a nutshell）创建（create）标签允许当方法被调用时，参照构建表需要的POJO。签名（signature）标签声明了被调用方法使用的实际 类型。 本示例的Assembler类的getTable方法将通过传入一个Map（包含form参数）和HttpServletRequest。 </p>
                        <ul>
                            <li> 在WEB-INF/web.xml中对DWR servlet进行声明 </li>
                        </ul>
                        <pre>  &lt;servlet&gt;<br />    &lt;servlet-name&gt;dwr-invoker&lt;/servlet-name&gt;<br />    &lt;display-name&gt;DWR Servlet&lt;/display-name&gt;<br />    &lt;servlet-class&gt;uk.ltd.getahead.dwr.DWRServlet&lt;/servlet-class&gt;<br />    &lt;init-param&gt;<br />       &lt;param-name&gt;debug&lt;/param-name&gt;<br />       &lt;param-value&gt;true&lt;/param-value&gt;<br />    &lt;/init-param&gt;<br />  &lt;/servlet&gt;<br />  &lt;servlet-mapping&gt;<br />    &lt;servlet-name&gt;dwr-invoker&lt;/servlet-name&gt;<br />      &lt;url-pattern&gt;/dwr/*&lt;/url-pattern&gt;<br />  &lt;/servlet-mapping&gt;<br /></pre>
                        <p>以上就完成了DWR servlet的设置，它被用来调用你的POJO。除了设置它，你不需要对这个servlet有更多的了解。 </p>
                        <div style="float: right; margin-left: 5px;" class="editsection">[<a title="Simplified Chinese Tutorials AJAX" href="http://extremecomponents.org/wiki/index.php?title=Simplified_Chinese_Tutorials_AJAX&amp;action=edit&amp;section=5">edit</a>]</div>
                        <a name=".E5.88.9B.E5.BB.BAPOJO"> 		</a>
                        <h3> 创建POJO </h3>
                        <p>DWR使用（works with）POJOs。这个非常符合我们的需要，因为eXtremeTable有足够的API使用Jsp标签来构造表。实际上，JSP标签只不过是eXtremeTable Java API的前端。首先，我将展示构造表的方法： </p>
                        <pre>public class Assembler {<br />  private Object build(TableModel model, Collection presidents) throws Exception {<br />    Table table = model.getTableInstance();<br />    table.setTableId(&quot;assembler&quot;);<br />    table.setItems(presidents);<br />    table.setAction(model.getContext().getContextPath() + &quot;/assembler.run&quot;);<br />    table.setTitle(&quot;Presidents&quot;);<br />    table.setOnInvokeAction(&quot;buildTable('assembler')&quot;);<br />    model.addTable(table);<br /><br />    Export export = model.getExportInstance();<br />    export.setView(TableConstants.VIEW_XLS);<br />    export.setViewResolver(TableConstants.VIEW_XLS);<br />    export.setImageName(TableConstants.VIEW_XLS);<br />    export.setText(TableConstants.VIEW_XLS);<br />    export.setFileName(&quot;output.xls&quot;);<br />    model.addExport(export);<br /><br />    Row row = model.getRowInstance();<br />    row.setHighlightRow(Boolean.FALSE);<br />    model.addRow(row);<br /><br />    Column columnName = model.getColumnInstance();<br />    columnName.setProperty(&quot;fullName&quot;);<br />    columnName.setIntercept((AssemblerIntercept.class).getName());<br />    model.addColumn(columnName);<br /><br />    Column columnNickName = model.getColumnInstance();<br />    columnNickName.setProperty(&quot;nickName&quot;);<br />    model.addColumn(columnNickName);<br /><br />    Column columnTerm = model.getColumnInstance();<br />    columnTerm.setProperty(&quot;term&quot;);<br />    model.addColumn(columnTerm);<br /><br />    Column columnBorn = model.getColumnInstance();<br />    columnBorn.setProperty(&quot;born&quot;);<br />    columnBorn.setCell(TableConstants.DATE);<br />    model.addColumn(columnBorn);<br /><br />    Column columnDied = model.getColumnInstance();<br />    columnDied.setProperty(&quot;died&quot;);<br />    columnDied.setCell(TableConstants.DATE);<br />    model.addColumn(columnDied);<br /><br />    Column columnCareer = model.getColumnInstance();<br />    columnCareer.setProperty(&quot;career&quot;);<br />    model.addColumn(columnCareer);<br /><br />    return model.assemble();<br />  }<br />}<br /></pre>
                        <p>上面的大部分代码是自解释性的，你将在下面看到如何构造一个TableModel，但是首先你应该注意到TableModel是构造表时需要交互的 唯一对象。构造表的第一步就是使用TableModel来创建Table、Row、Column和Export。 一旦你创建了一个model对象，你只需要将它添加到model中。除非你将它添加到TableModel，否则的话model将不会是用它。所有东西已 经构建好后，你只需要调用model.assemble()方法来构造表了。 </p>
                        <p>可能<strong>table.setOnInvokeAction(&quot;buildTable('assembler')&quot;);</strong>是最有趣的调用。当你使用表的actions(翻页、过滤、排序......)，这个javascript方法将被调用。如果表的onInvokeAction空白，则默认的javascript方法将被提交（submit） ，正如你所期望的那样。 </p>
                        <p>Assembler类的另一个方法---getTable()： </p>
                        <pre>public class Assembler {<br />  public String getTable(Map parameterMap, HttpServletRequest request) {<br />    WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());<br /><br />    PresidentsDao presidentsDao = (PresidentsDao) webApplicationContext.getBean(&quot;presidentsDao&quot;);<br />    Collection presidents = presidentsDao.getPresidents();<br /><br />    Context context = null;<br />    if (parameterMap == null) {<br />      context = new HttpServletRequestContext(request);<br />    } else {<br />      context = new HttpServletRequestContext(request, parameterMap);<br />    }<br /><br />    TableModel model = new TableModelImpl(context);<br />    try {<br />      return build(model, presidents).toString();<br />    } catch (Exception e) {<br />      e.printStackTrace();<br />    }<br /><br />    return &quot;&quot;;<br />  }<br />}<br /></pre>
                        <p>这个方法调用比较频繁，它执行双重职责。它需要被Controller（如果使用Spring的话）在第一次调用，<em>如果使用Struts就等同于Action类。</em> 随后， 当使用AJAX时，这个方法也需要被调用，但是这次将传入一个定制的parameterMap。parameterMap将包含eXtremeTable使用AJAX需要的所有参数。当你看了 Controller和JSP后，这点将更加清晰。 </p>
                        <div style="float: right; margin-left: 5px;" class="editsection">[<a title="Simplified Chinese Tutorials AJAX" href="http://extremecomponents.org/wiki/index.php?title=Simplified_Chinese_Tutorials_AJAX&amp;action=edit&amp;section=6">edit</a>]</div>
                        <a name="Controller"> 		</a>
                        <h3> Controller </h3>
                        <pre>public class AssemblerController extends AbstractController {<br />  public String successView;<br /><br />  public void setSuccessView(String successView) {<br />    this.successView = successView;<br />  }<br /><br />  protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {<br />    ModelAndView mv = new ModelAndView(successView);<br />    Assembler assembler = new Assembler();<br />    Object viewData = assembler.getTable(null, request);<br />    request.setAttribute(&quot;assembler&quot;, viewData);<br />    return mv;<br />  }<br />}<br /></pre>
                        <p>controller在被第一次调用时来构建表。它调用POJO并将表传给request。注意空值（null）如何使用parameterMap传输。这是因为第一次表被构造时，没有对应表需要知道的actions。 </p>
                        <div style="float: right; margin-left: 5px;" class="editsection">[<a title="Simplified Chinese Tutorials AJAX" href="http://extremecomponents.org/wiki/index.php?title=Simplified_Chinese_Tutorials_AJAX&amp;action=edit&amp;section=7">edit</a>]</div>
                        <a name="JSP"> 		</a>
                        <h3> JSP </h3>
                        <p>通过引入(importing)合适的javascript文件来开始构建JSP页面。唯一需要包含进工程的javascript文件是extremecomponents.js，其它的javascript文件申明都是DWR使用的。 </p>
                        <pre>  &lt;script type=&quot;text/javascript&quot; src=&quot;&lt;c:url value=&quot;/dwr/interface/Assembler.js&quot;/&gt;&quot;&gt;&lt;/script&gt;<br />  &lt;script type=&quot;text/javascript&quot; src=&quot;&lt;c:url value=&quot;/dwr/engine.js&quot;/&gt;&quot;&gt;&lt;/script&gt;<br />  &lt;script type=&quot;text/javascript&quot; src=&quot;&lt;c:url value=&quot;/dwr/util.js&quot;/&gt;&quot;&gt;&lt;/script&gt;<br />  &lt;script type=&quot;text/javascript&quot; src=&quot;&lt;c:url value=&quot;/js/extremecomponents.js&quot;/&gt;&quot;&gt;&lt;/script&gt;<br /></pre>
                        <p>接着，插入钩子（hook)来显示表，div被用来调用innerHtml并构建新的标签。 </p>
                        <pre>  &lt;div id=&quot;tableDiv&quot;&gt;<br />    &lt;c:out value=&quot;$&quot; escapeXml=&quot;false&quot;/&gt; <br />  &lt;/div&gt;<br /></pre>
                        <p>最后，添加javascript来调用DWR的钩子（hooks）。  </p>
                        <pre>&lt;script type=&quot;text/javascript&quot;&gt;<br />  function buildTable(form) {<br />    var parameterMap = getParameterMap(form);   <br />    Assembler.getTable(parameterMap, showTable);<br />  }<br /><br />  function showTable(table) {<br />    document.getElementById('tableDiv').innerHTML=table;<br />  }<br />&lt;/script&gt;<br /></pre>
                        <p>getParameterMap()方法包含在extremecomponents.js文件中，将的到所有的form参数。你需要传入一个 form id的参照。记住，eXtremeTable本质上是一个form组建，tableid作为form id使用。默认的tableId为ec，但是你通常想要设置tableId，以示大家能更容易阅读你的代码。你将使用parameterMap调用 POJO的getTable方法。showTable是一个callback告诉DWR当从getTable()方法返回时将调用什么操作。 </p>
                        <div style="float: right; margin-left: 5px;" class="editsection">[<a title="Simplified Chinese Tutorials AJAX" href="http://extremecomponents.org/wiki/index.php?title=Simplified_Chinese_Tutorials_AJAX&amp;action=edit&amp;section=8">edit</a>]</div>
                        <a name=".E7.BB.93.E8.AE.BA"> 		</a>
                        <h3> 结论 </h3>
                        <p>本指南描述了在eXtremeTable中使用AJAX所需要的步骤。需要留心的一个主要事情是没有和AJAX发生实际整合。当表的actions 被使用是，你只需要简单地告诉eXtremeTable什么javascript将被调yong。另一个事情是，通过本示例我们可以知道DWR工具包使用 POJOs并能够简单地被任何框架使用。 </p>
                        <img width="1" height="1" src="../../../lucky/aggbug/37623.html" alt="" /><br /><br /></td>
                    </tr>
                </tbody>
            </table>
            </div>
            </td>
        </tr>
    </tbody>
</table><img src ="http://www.blogjava.net/aichan/aggbug/38314.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/aichan/" target="_blank">艾尘</a> 2006-03-30 18:43 <a href="http://www.blogjava.net/aichan/articles/38314.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Javascript callback and function pointer</title><link>http://www.blogjava.net/aichan/articles/37200.html</link><dc:creator>艾尘</dc:creator><author>艾尘</author><pubDate>Fri, 24 Mar 2006 05:41:00 GMT</pubDate><guid>http://www.blogjava.net/aichan/articles/37200.html</guid><wfw:comment>http://www.blogjava.net/aichan/comments/37200.html</wfw:comment><comments>http://www.blogjava.net/aichan/articles/37200.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/aichan/comments/commentRss/37200.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/aichan/services/trackbacks/37200.html</trackback:ping><description><![CDATA[<span style="color: rgb(51, 102, 255);"><span style="color: rgb(0, 0, 128);">简单的代码示例：<br />&lt;!--<br /></span>function </span><span style="color: rgb(153, 51, 0);">show(cbfunction,name){</span><br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(51, 102, 255);">return function</span><span style="color: rgb(153, 51, 0);">(sex){<span style="color: rgb(51, 153, 102);">//这里返回一个有参数的Function</span></span><br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: rgb(153, 51, 0);">cbfunction(name);<span style="color: rgb(51, 153, 102);">//调用参数传入的函数</span></span><br style="color: rgb(153, 51, 0);" /><span style="color: rgb(153, 51, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; alert(sex);</span><br style="color: rgb(153, 51, 0);" /><span style="color: rgb(153, 51, 0);">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }</span><br style="color: rgb(153, 51, 0);" /><span style="color: rgb(153, 51, 0);">&nbsp;&nbsp;&nbsp; }</span><br /><span style="color: rgb(51, 102, 255);">function </span><span style="color: rgb(153, 51, 0);">hello(name){</span><br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; <span style="color: rgb(153, 51, 0);">alert(<span style="color: rgb(255, 0, 255);">&quot;hello &quot;</span> + name);</span><br style="color: rgb(153, 51, 0);" /><span style="color: rgb(153, 51, 0);">}</span><br /><span style="color: rgb(153, 51, 0);">var fn = show(hello,<span style="color: rgb(255, 0, 255);">&quot;aichen&quot;</span>);</span><span style="color: rgb(51, 153, 102);">//返回的是一个函数,fn 为函数指针</span><br /><span style="color: rgb(153, 51, 0);">fn(<span style="color: rgb(255, 0, 255);">&quot;boy&quot;</span>);<br />--//&gt;<br />have fun!^_^</span><img src ="http://www.blogjava.net/aichan/aggbug/37200.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/aichan/" target="_blank">艾尘</a> 2006-03-24 13:41 <a href="http://www.blogjava.net/aichan/articles/37200.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>