﻿<?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>IT博客-D盘-随笔分类-Java</title><link>http://www.cnitblog.com/wufajiaru/category/6821.html</link><description>workspace</description><language>zh-cn</language><lastBuildDate>Tue, 27 Sep 2011 21:38:32 GMT</lastBuildDate><pubDate>Tue, 27 Sep 2011 21:38:32 GMT</pubDate><ttl>60</ttl><item><title>试用了一下liferay，很喜欢</title><link>http://www.cnitblog.com/wufajiaru/archive/2009/06/18/59470.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Thu, 18 Jun 2009 04:20:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2009/06/18/59470.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/59470.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2009/06/18/59470.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/59470.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/59470.html</trackback:ping><description><![CDATA[<div>可能会因此抛弃曾经叹服的roller，这个更适合。</div>
<div>官网：<a href="http://www.liferay.com/">http://www.liferay.com</a></div>
<div>下载：<a href="http://sourceforge.net/project/showfiles.php?group_id=49260">http://sourceforge.net/project/showfiles.php?group_id=49260</a></div>
<div>从JForum到rollerweblogger再到<span style="FONT-SIZE: 13px; FONT-FAMILY: 'lucida grande'; WHITE-SPACE: pre; webkit-border-horizontal-spacing: 2px; webkit-border-vertical-spacing: 2px">liferay，因为JAVA里最好的论坛是<span style="FONT-SIZE: 16px; FONT-FAMILY: Simsun; WHITE-SPACE: normal; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px">JForum，因此选了它，后来发现需要的并不是论坛，而是一个blog或wiki。寻寻觅觅，java阵营里没有好的wiki，而mediawiki默认试用wiki语言，让人用起来很不爽，增加了推广难度，后来发现了roller，一个很优秀的开源blog，有专门的主题网站，功能很强大，花了一点时间研究二次开发，发现他涉及了太多的技术，而我只是想把他变成我想要的富文本wiki系统，没有那么多时间，于是放下，有空欣赏一下而已。最近，认识了liferay，发现他不仅有bbs还有blog还有wiki，这都是我想要的，最重要的是，这些都是支持富文本的，他使用了fckeditor，这将极大增强它的用户体验。接下来，有空要好好研究一下这个据说是华人开发的东东了。</span></span></div>
<div>牛人知识库链接：<br><font face="'lucida grande'" size=3><span style="FONT-SIZE: 13px; WHITE-SPACE: pre; webkit-border-horizontal-spacing: 2px; webkit-border-vertical-spacing: 2px">《devilbaby的博客》，对liferay的开发有丰富的经验，尤其对liferay的性能有特别的研究： <a href="http://devilbaby.javaeye.com/">http://devilbaby.javaeye.com/</a><br></span></font></div>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/59470.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2009-06-18 12:20 <a href="http://www.cnitblog.com/wufajiaru/archive/2009/06/18/59470.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring入门[zz，实例讲解，容易懂]</title><link>http://www.cnitblog.com/wufajiaru/archive/2009/04/17/56438.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Fri, 17 Apr 2009 04:07:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2009/04/17/56438.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/56438.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2009/04/17/56438.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/56438.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/56438.html</trackback:ping><description><![CDATA[<p>Spring是一个非常优秀的轻量级框架，通过Spring的IoC容器，我们的关注点便放到了需要实现的业务逻辑上。对AOP的支持则能让我们动态增强业务方法。编写普通的业务逻辑Bean是非常容易而且易于测试的，因为它能脱离J2EE容器（如Servlet，jsp环境）单独进行单元测试。最后的一步便是在Spring框架中将这些业务Bean以XML配置文件的方式组织起来，它们就按照我们预定的目标正常工作了！非常容易！</p>
<p>本文将给出一个基本的Spring入门示例，并演示如何使用Spring的AOP将复杂的业务逻辑分离到每个方面中。</p>
<p>1．开发环境配置<br>2．编写Bean接口及其实现<br>3．在Spring中配置Bean并获得Bean的实例<br>4．编写Advisor以增强ServiceBean<br>5．总结</p>
<p>1．开发环境配置<br>首先，需要正确配置Java环境。推荐安装JDK1.4.2，并正确配置环境变量：</p>
<p>JAVA_HOME=&lt;JDK安装目录&gt;<br>CLASSPATH=.<br>Path=%JAVA_HOME%\bin;&#8230;&#8230;</p>
<p>我们将使用免费的Eclipse 3.1作为IDE。新建一个Java Project，将Spring的发布包spring.jar以及commons-logging-1.0.4.jar复制到Project目录下，并在Project &gt; Properties中配置好Java Build Path：</p>
<p>&nbsp;</p>
<p>点击查看大图</p>
<p>2．编写Bean接口及其实现<br>我们实现一个管理用户的业务Bean。首先定义一个ServiceBean接口，声明一些业务方法：</p>
<p>/** * Copyright_2006, Liao Xuefeng * Created on 2006-3-9 * For more information, please visit: <a href="http://www.crackj2ee.com/">http://www.crackj2ee.com</a> */package com.crackj2ee.example.spring;<br>/** * Interface of service facade. *&nbsp; * @author Xuefeng */public interface ServiceBean {&nbsp;&nbsp;&nbsp; void addUser(String username, String passWord);&nbsp;&nbsp;&nbsp; void deleteUser(String username);&nbsp;&nbsp;&nbsp; boolean findUser(String username);&nbsp;&nbsp;&nbsp; String getPassword(String username);}<br>然后在MyServiceBean中实现接口：</p>
<p>/** * Copyright_2006, Liao Xuefeng * Created on 2006-3-9 *&nbsp; * For more information, please visit: <a href="http://www.crackj2ee.com/">http://www.crackj2ee.com</a> */package com.crackj2ee.example.spring;<br>import java.util.*;<br>public class MyServiceBean implements ServiceBean {<br>&nbsp;&nbsp;&nbsp; private String dir;&nbsp;&nbsp;&nbsp; private Map map = new HashMap();<br>&nbsp;&nbsp;&nbsp; public void setUserDir(String dir) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.dir = dir;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Set user dir to: " + dir);&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; public void addUser(String username, String password) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!map.containsKey(username))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.put(username, password);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new RuntimeException("User already exist.");&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; public void deleteUser(String username) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(map.remove(username)==null)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new RuntimeException("User not exist.");&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; public boolean findUser(String username) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return map.containsKey(username);&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; public String getPassword(String username) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (String)map.get(username);&nbsp;&nbsp;&nbsp; }}</p>
<p>为了简化逻辑，我们使用一个Map保存用户名和口令。</p>
<p>现在，我们已经有了一个业务Bean。要测试它非常容易，因为到目前为止，我们还没有涉及到Spring容器，也没有涉及到任何Web容器（假定这是一个Web应用程序关于用户管理的业务Bean）。完全可以直接进行Unit测试，或者，简单地写个main方法测试：</p>
<p>/** * Copyright_2006, Liao Xuefeng * Created on 2006-3-9 * For more information, please visit: <a href="http://www.crackj2ee.com/">http://www.crackj2ee.com</a> */package com.crackj2ee.example.spring;<br>public class Main {<br>&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ServiceBean service = new MyServiceBean();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; service.addUser("bill", "hello");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; service.addUser("tom", "goodbye");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; service.addUser("tracy", "morning");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("tom's password is: " + service.getPassword("tom"));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(service.findUser("tom")) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; service.deleteUser("tom");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; }}<br>执行结果：</p>
<p><br>3．在Spring中配置Bean并获得Bean的实例<br>我们已经在一个main方法中实现了业务，不过，将对象的生命周期交给容器管理是更好的办法，我们就不必为初始化对象和销毁对象进行硬编码，从而获得更大的灵活性和可测试性。</p>
<p>想要把ServiceBean交给Spring来管理，我们需要一个XML配置文件。新建一个beans.xml，放到src目录下，确保在classpath中能找到此配置文件，输入以下内容：</p>
<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "<a href='http://www.springframework.org/dtd/spring-beans.dtd"><beans'>http://www.springframework.org/dtd/spring-beans.dtd"&gt;&lt;beans</a>&gt;&nbsp;&nbsp;&nbsp; &lt;bean id="service" class="com.crackj2ee.example.spring.MyServiceBean" /&gt;&lt;/beans&gt;<br>以上XML声明了一个id为service的Bean，默认地，Spring为每个声明的Bean仅创建一个实例，并通过id来引用这个Bean。下面，我们修改main方法，让Spring来管理业务Bean：</p>
<p>/** * Copyright_2006, Liao Xuefeng * Created on 2006-3-9 * For more information, please visit: <a href="http://www.crackj2ee.com/">http://www.crackj2ee.com</a> */package com.crackj2ee.example.spring;<br>import org.springframework.beans.factory.xml.XmlBeanFactory;import org.springframework.core.io.ClassPathResource;<br>public class Main {<br>&nbsp;&nbsp;&nbsp; public static void main(String[] args) throws Exception {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // init factory:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // use service bean:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ServiceBean service = (ServiceBean)factory.getBean("service");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; service.addUser("bill", "hello");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; service.addUser("tom", "goodbye");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; service.addUser("tracy", "morning");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("tom's password is \"" + service.getPassword("tom") + "\"");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(service.findUser("tom")) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; service.deleteUser("tom");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // close factory:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; factory.destroySingletons();&nbsp;&nbsp;&nbsp; }}</p>
<p>执行结果：<br>&nbsp;</p>
<p>由于我们要通过main方法启动Spring环境，因此，首先需要初始化一个BeanFactory。红色部分是初始化Spring的BeanFactory的典型代码，只需要保证beans.xml文件位于classpath中。</p>
<p>然后，在BeanFactory中通过id查找，即可获得相应的Bean的实例，并将其适当转型为合适的接口。</p>
<p>接着，实现一系列业务操作，在应用程序结束前，让Spring销毁所有的Bean实例。</p>
<p>对比上一个版本的Main，可以看出，最大的变化是不需要自己管理Bean的生命周期。另一个好处是在不更改实现类的前提下，动态地为应用程序增加功能。</p>
<p>4．编写Advisor以增强ServiceBean<br>所谓AOP即是将分散在各个方法处的公共代码提取到一处，并通过类似拦截器的机制实现代码的动态织入。可以简单地想象成，在某个方法的调用前、返回前、调用后和抛出异常时，动态插入自己的代码。在弄清楚Pointcut、Advice之类的术语前，不如编写一个最简单的AOP应用来体验一下。</p>
<p>考虑一下通常的Web应用程序都会有日志记录，我们来编写一个LogAdvisor，对每个业务方法调用前都作一个记录：</p>
<p>/** * Copyright_2006, Liao Xuefeng * Created on 2006-3-9 * For more information, please visit: <a href="http://www.crackj2ee.com/">http://www.crackj2ee.com</a> */package com.crackj2ee.example.spring;<br>import java.lang.reflect.Method;import org.springframework.aop.MethodBeforeAdvice;<br>public class LogAdvisor implements MethodBeforeAdvice {&nbsp;&nbsp;&nbsp; public void before(Method m, Object[] args, Object target) throws Throwable {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("[Log] " + target.getClass().getName() + "." + m.getName() + "()");&nbsp;&nbsp;&nbsp; }}<br>然后，修改beans.xml：</p>
<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "<a href="http://www.springframework.org/dtd/spring-beans.dtd">http://www.springframework.org/dtd/spring-beans.dtd</a>"&gt;<br>&lt;beans&gt;&nbsp;&nbsp;&nbsp; &lt;bean id="serviceTarget" class="com.crackj2ee.example.spring.MyServiceBean" /&gt;<br>&nbsp;&nbsp;&nbsp; &lt;bean id="logAdvisor" class="com.crackj2ee.example.spring.LogAdvisor" /&gt;<br>&nbsp;&nbsp;&nbsp; &lt;bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean"&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="proxyInterfaces"&gt;&lt;value&gt;com.crackj2ee.example.spring.ServiceBean&lt;/value&gt;&lt;/property&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="target"&gt;&lt;ref local="serviceTarget"/&gt;&lt;/property&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="interceptorNames"&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;list&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;logAdvisor&lt;/value&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/list&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;&nbsp;&nbsp;&nbsp; &lt;/bean&gt;&lt;/beans&gt;<br>注意观察修改后的配置文件，我们使用了一个ProxyFactoryBean作为service来与客户端打交道，而真正的业务Bean即MyServiceBean被声明为serviceTarget并作为参数对象传递给ProxyFactoryBean，proxyInterfaces指定了返回的接口类型。对于客户端而言，将感觉不出任何变化，但却动态加入了LogAdvisor，关系如下：<br>&nbsp;</p>
<p><br>运行结果如下，可以很容易看到调用了哪些方法：<br>&nbsp;</p>
<p>要截获指定的某些方法也是可以的。下面的例子将修改getPassword()方法的返回值：</p>
<p>/** * Copyright_2006, Liao Xuefeng * Created on 2006-3-9 * For more information, please visit: <a href="http://www.crackj2ee.com/">http://www.crackj2ee.com</a> */package com.crackj2ee.example.spring;<br>import org.aopalliance.intercept.MethodInterceptor;import org.aopalliance.intercept.MethodInvocation;<br>public class PasswordAdvisor implements MethodInterceptor {&nbsp;&nbsp;&nbsp; public Object invoke(MethodInvocation invocation) throws Throwable {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object ret = invocation.proceed();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(ret==null)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String password = (String)ret;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringBuffer encrypt = new StringBuffer(password.length());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=0; i&lt;password.length(); i++)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; encrypt.append('*');&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return encrypt.toString();&nbsp;&nbsp;&nbsp; }}<br>这个PasswordAdvisor将截获ServiceBean的getPassword()方法的返回值，并将其改为"***"。继续修改beans.xml：</p>
<p>&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "<a href='http://www.springframework.org/dtd/spring-beans.dtd"><beans'>http://www.springframework.org/dtd/spring-beans.dtd"&gt;&lt;beans</a>&gt;&nbsp;&nbsp;&nbsp; &lt;bean id="serviceTarget" class="com.crackj2ee.example.spring.MyServiceBean" /&gt;<br>&nbsp;&nbsp;&nbsp; &lt;bean id="logAdvisor" class="com.crackj2ee.example.spring.LogAdvisor" /&gt;<br>&nbsp;&nbsp;&nbsp; &lt;bean id="passwordAdvisorTarget" class="com.crackj2ee.example.spring.PasswordAdvisor" /&gt;<br>&nbsp;&nbsp;&nbsp; &lt;bean id="passwordAdvisor" class="org.springframework.aop.support.RegeXPMethodPointcutAdvisor"&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="advice"&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref local="passwordAdvisorTarget"/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="patterns"&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;list&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;.*getPassword&lt;/value&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/list&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br>&nbsp;&nbsp;&nbsp; &lt;bean id="service" class="org.springframework.aop.framework.ProxyFactoryBean"&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="proxyInterfaces"&gt;&lt;value&gt;com.crackj2ee.example.spring.ServiceBean&lt;/value&gt;&lt;/property&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="target"&gt;&lt;ref local="serviceTarget"/&gt;&lt;/property&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="interceptorNames"&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;list&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;logAdvisor&lt;/value&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;passwordAdvisor&lt;/value&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/list&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;&nbsp;&nbsp;&nbsp; &lt;/bean&gt;&lt;/beans&gt;</p>
<p>利用Spring提供的一个RegexMethodPointcutAdvisor可以非常容易地指定要截获的方法。运行结果如下，可以看到返回结果变为"******"：<br>&nbsp;</p>
<p>还需要继续增强ServiceBean？我们编写一个ExceptionAdvisor，在业务方法抛出异常时能做一些处理：</p>
<p>/** * Copyright_2006, Liao Xuefeng * Created on 2006-3-9 * For more information, please visit: <a href="http://www.crackj2ee.com/">http://www.crackj2ee.com</a> */package com.crackj2ee.example.spring;<br>import org.springframework.aop.ThrowsAdvice;<br>public class ExceptionAdvisor implements ThrowsAdvice {&nbsp;&nbsp;&nbsp; public void afterThrowing(RuntimeException re) throws Throwable {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("[Exception] " + re.getMessage());&nbsp;&nbsp;&nbsp; }}<br>将此Advice添加到beans.xml中，然后在业务Bean中删除一个不存在的用户，故意抛出异常：</p>
<p>service.deleteUser("not-exist");<br>再次运行，注意到ExceptionAdvisor记录下了异常：<br>&nbsp;</p>
<p>5．总结<br>利用Spring非常强大的IoC容器和AOP功能，我们能实现非常灵活的应用，让Spring容器管理业务对象的生命周期，利用AOP增强功能，却不影响业务接口，从而避免更改客户端代码。</p>
<p>为了实现这一目标，必须始终牢记：面向接口编程。而Spring默认的AOP代理也是通过Java的代理接口实现的。虽然Spring也可以用CGLIB实现对普通类的代理，但是，业务对象只要没有接口，就会变得难以扩展、维护和测试。</p>
<p>欢迎来信与作者交流：<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#97;&#115;&#107;&#108;&#120;&#102;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;">asklxf@163.com</a></p>
<p>完整的Eclipse工程：springbasic.rar</p>
<p>（出处：<a href="http://www.knowsky.com/">http://www.knowsky.com</a>）</p>
<p>&nbsp;</p>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/56438.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2009-04-17 12:07 <a href="http://www.cnitblog.com/wufajiaru/archive/2009/04/17/56438.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle的sys用户怎么通过jdbc连接[转]</title><link>http://www.cnitblog.com/wufajiaru/archive/2009/02/20/54770.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Fri, 20 Feb 2009 09:10:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2009/02/20/54770.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/54770.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2009/02/20/54770.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/54770.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/54770.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 早看到这篇文章好多问题都不是问题了http://jamesq.bokee.com/1263981.htmloracle的sys用户怎么通过jdbc连接经过GOOGLE 总算知道了如何在JDBC中使用SYSDBA角色连接ORACLE数据库在DriverManager.getConnection通过Properties 设置连接的defaultRowPrefetch，nternal_log...&nbsp;&nbsp;<a href='http://www.cnitblog.com/wufajiaru/archive/2009/02/20/54770.html'>阅读全文</a><img src ="http://www.cnitblog.com/wufajiaru/aggbug/54770.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2009-02-20 17:10 <a href="http://www.cnitblog.com/wufajiaru/archive/2009/02/20/54770.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Robust Java 中文版——Java异常处理、测试与调试 [转]</title><link>http://www.cnitblog.com/wufajiaru/archive/2009/02/13/54505.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Fri, 13 Feb 2009 03:06:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2009/02/13/54505.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/54505.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2009/02/13/54505.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/54505.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/54505.html</trackback:ping><description><![CDATA[<h3>来自：<a href="http://book.csdn.net/bookfiles/150/1001506504.shtml">http://book.csdn.net/bookfiles/150/1001506504.shtml</a><br><br>3.1&nbsp; <span>简介</span></h3>
<p><span>前两章介绍了使用异常的基本概念，重点讨论了处理方式和理由，阐述了工作原理，分析如何在代码中处理异常。本章介绍更高级的主题，具体内容如下：</span></p>
<p><span>●<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>如何创建和使用自定义异常。</span></p>
<p><span>●<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>异常支持链表和本地化。</span></p>
<p><span>●<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>抽象类和接口中的异常用法。</span></p>
<p><span>●<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>覆盖方法的异常要求。</span></p>
<p><span>●<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>如何用字节码表示异常处理代码。</span></p>
<p><span>●<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>应用程序中异常处理操作的效率。</span></p>
<p><span>在处理异常时，上述主题并不常用。简单项目根本不使用它们。但在编写较复杂的程序时，这些主题的作用便显示出来了。</span></p>
<h3><span lang=EN-US>3.2&nbsp; </span><span style="FONT-FAMILY: 楷体_GB2312">自定义异常</span></h3>
<p class=MsoNormal style="TEXT-INDENT: 21pt; LINE-HEIGHT: 18pt"><span style="FONT-FAMILY: 宋体">前面讨论了如何处理调用</span><span lang=EN-US>Java API</span><span style="FONT-FAMILY: 宋体">的方法时产生的异常。根据需要，还可创建和使用自定义异常<span style="LETTER-SPACING: -1pt">——</span>自我构建表示错误的类。可创建全新异常，并将它们用于应用程序。</span></p>
<p class=a style="MARGIN-BOTTOM: 0pt; LINE-HEIGHT: 18pt"><span style="FONT-FAMILY: 宋体">使用自定义异常有什么好处呢？为何要定义新异常类型？创建自定义异常是为了表示应用程序的一些错误类型，为代码可能发生的一个或多个问题提供新含义。可以显示代码多个位置之间的错误的相似性，也可区分代码运行时可能出现的相似问题的一个或多个错误，或给出应用程序中一组错误的特定含义。</span></p>
<p class=MsoNormal style="TEXT-INDENT: 20.6pt; LINE-HEIGHT: 18pt"><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -0.1pt">例如，考虑任何类型的服务器。服务器的基本作用是处理与客户机的通信。若使用标准</span><span lang=EN-US style="LETTER-SPACING: -0.1pt">Java API(</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -0.1pt">如</span><span lang=EN-US style="LETTER-SPACING: -0.1pt">java.io</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -0.1pt">和</span><span lang=EN-US style="LETTER-SPACING: -0.1pt">java.net</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -0.1pt">包中的类</span><span lang=EN-US style="LETTER-SPACING: -0.1pt">)</span><span style="FONT-FAMILY: 宋体; LETTER-SPACING: -0.1pt">来编写服务器，则可使编写的代码在多个位置抛</span><span lang=EN-US>IOException</span><span style="FONT-FAMILY: 宋体">。</span> <span style="FONT-FAMILY: 宋体">在设置服务器、等待客户机连接和获取通信流时，可抛出</span><span lang=EN-US>IOExceptions</span><span style="FONT-FAMILY: 宋体">；在通信期间及试图断开连接时，也可抛出</span><span lang=EN-US>IOExceptions</span><span style="FONT-FAMILY: 宋体">。简言之，服务器的各个部分都可能引发</span><span lang=EN-US>IOException</span><span style="FONT-FAMILY: 宋体">。</span></p>
<p class=MsoNormal style="TEXT-INDENT: 21pt; LINE-HEIGHT: 18pt"><span style="FONT-FAMILY: 宋体">对服务器而言，这些</span><span lang=EN-US>IOException</span><span style="FONT-FAMILY: 宋体">意义不尽相同。虽然由同一异常类型表示，但与各个异常相关的业务含义存在差异，报告和恢复操作亦有不同。可以将一个异常集与服务器配置和启动问题关联，将另一个异常集与客户机通信的实际行动关联，将第三个异常集与服务器关闭任务关联。使用自定义异常，可采用对应用程序有意义的方式来灵活地表示错误。</span></p>
<p class=MsoNormal style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体">创建和使用自定义异常并不难。遵循以下</span><span lang=EN-US>3</span><span style="FONT-FAMILY: 宋体">个步骤即可。</span></p>
<h3><span lang=EN-US>3.2.1</span><span lang=EN-US>&nbsp; </span><span style="FONT-FAMILY: 黑体">定义异常类</span></h3>
<p class=MsoNormal style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体">一般要定义新类来表示自定义异常</span><span style="FONT-FAMILY: 宋体">。多数情况下，只需创建已有异常类的子类。</span></p>
<p class=10 style="MARGIN: 7.8pt 0cm 0pt 21pt; TEXT-INDENT: 5.4pt"><span lang=EN-US>1 &nbsp;public class CustomerExistsException extends Exception{</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.4pt"><span lang=EN-US>2 &nbsp;&nbsp;&nbsp;public CustomerExistsException(){}</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.4pt"><span lang=EN-US>3 &nbsp;&nbsp;&nbsp;public CustomerExistsException(String message){</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.4pt"><span lang=EN-US>4 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(message);</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.4pt"><span lang=EN-US>5 &nbsp;&nbsp;&nbsp;}</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 7.8pt 21pt; TEXT-INDENT: 5.4pt"><span lang=EN-US>6 &nbsp;}</span></p>
<p class=MsoNormal style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体">至少要继承</span><span lang=EN-US>Throwable</span><span style="FONT-FAMILY: 宋体">或</span><span lang=EN-US>Throwable</span><span style="FONT-FAMILY: 宋体">的子类。经常需要定义一个或多个构造函数，以在对象中存储错误消息。如第</span><span lang=EN-US>2-4</span><span style="FONT-FAMILY: 宋体">行所示。在继承任何异常时，将自动继承</span><span lang=EN-US>Throwable</span><span style="FONT-FAMILY: 宋体">类的一些标准特性，如：</span></p>
<p class=1><span lang=EN-US>●<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">错误消息</span></p>
<p class=1><span lang=EN-US>●<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">栈跟踪</span></p>
<p class=1><span lang=EN-US>●<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">异常包装</span></p>
<p class=a style="MARGIN-BOTTOM: 0pt"><span style="FONT-FAMILY: 宋体">若要在异常中添加附加信息，则可以为类添加一些变量和方法：</span></p>
<p class=10 style="MARGIN: 7.8pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US>1 &nbsp;public class CustomerExistsException extends Exception{</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US>2&nbsp;&nbsp; &nbsp;private String customerName;</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US>3 &nbsp;&nbsp; public CustomerExistsException(){}</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US>4 &nbsp;&nbsp;&nbsp; public CustomerExistsException(String message){</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US>5 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(message);</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US>6 &nbsp;&nbsp;&nbsp; }</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US>7 &nbsp;&nbsp;&nbsp;&nbsp;public CustomerExistsException(String message, String customer){</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US>8 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super(message);</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US>9 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;customerName = customer;</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>10 &nbsp;&nbsp;&nbsp; }</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>11 &nbsp;&nbsp;&nbsp;&nbsp;public String getCustomerName(){</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>12 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return customerName;</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>13 &nbsp;&nbsp;&nbsp;&nbsp;}</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 7.8pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>14 &nbsp;}</span></p>
<p class=MsoNormal style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体">由本例可知，可修改</span><span lang=EN-US>CustomerExistsException</span><span style="FONT-FAMILY: 宋体">类，以支持其他属性。例如，可将</span><span lang=EN-US>customerName</span><span style="FONT-FAMILY: 宋体">字符串</span><span lang=EN-US>(</span><span style="FONT-FAMILY: 宋体">引发异常的记录的客户名</span><span lang=EN-US>)</span><span style="FONT-FAMILY: 宋体">与异常联系起来。</span></p>
<h3><span lang=EN-US>3.2.2</span><span lang=EN-US>&nbsp; </span><span style="FONT-FAMILY: 黑体">声明方法抛出自定义异常</span></h3>
<p class=MsoNormal style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体">这实际上是&#8220;处理或声明&#8221;规则的&#8220;声明&#8221;部分。为了使用自定义异常，必须通知调用代码的类：要准备处理这个异常类型。为此，声明一个或多个方法抛出异常：</span></p>
<p class=10 style="MARGIN: 7.8pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>public void insertCustomer(Customer c) </span><strong><span lang=EN-US style="FONT-FAMILY: Courier-Bold">throws </span><span lang=EN-US>CustomerExistsException{</span></strong></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 9pt"><span lang=EN-US>// The method stores customer information in the database.</span></p>
<p class=10 style="MARGIN-LEFT: 21pt; TEXT-INDENT: 9pt"><span lang=EN-US>// If the customer data already exists, the method creates</span></p>
<p class=10 style="MARGIN-LEFT: 21pt; TEXT-INDENT: 9pt"><span lang=EN-US>// and throws the CustomerExistsException.</span></p>
<p class=10 style="MARGIN-LEFT: 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>}</span></p>
<h3 style="MARGIN: 5.45pt 0cm"><span lang=EN-US>3.2.3</span><span lang=EN-US>&nbsp; </span><span style="FONT-FAMILY: 黑体">找到故障点，新建异常并加上关键字</span><span lang=EN-US>throw</span></h3>
<p class=MsoNormal style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体">最后一步实际上是创建对象，并通过系统传送该对象。为此，需要了解代码将在方法的哪个位置出现故障。根据情况，可能要使用以下部分或所有条件，来指示代码中的故障点。</span></p>
<p class=a0 style="MARGIN-TOP: 4.65pt"><span lang=EN-US>1. </span><span style="FONT-FAMILY: 黑体">外部问题</span></p>
<p class=1><span lang=EN-US>●<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">应用程序中产生的异常</span></p>
<p class=1><span lang=EN-US>●<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">其他方法返回的故障代码</span></p>
<p class=a0 style="MARGIN-TOP: 4.65pt"><span lang=EN-US>2. </span><span style="FONT-FAMILY: 黑体">内部问题</span></p>
<p class=1><span lang=EN-US>●<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">应用程序状态不一致</span></p>
<p class=1><span lang=EN-US>●<span style="FONT: 7pt 'Times New Roman'">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">应用程序中的处理问题</span></p>
<p class=MsoNormal style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体">在本例中，当不能新建一个客户时会遇到一个故障场景。结果，创建一个异常来表示问题并抛出该问题。如下面的示例方法所示：</span></p>
<p class=10 style="MARGIN: 4.65pt 0cm 0pt 21pt; TEXT-INDENT: 5.4pt"><span lang=EN-US>1 &nbsp;public void insertCustomer(Customer c)</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US style="FONT-FAMILY: Courier">2 &nbsp;&nbsp;&nbsp;</span><strong><span lang=EN-US>throws CustomerExistsException</span></strong><span lang=EN-US style="FONT-FAMILY: Courier">, SQLException {</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US>3 &nbsp;&nbsp;&nbsp;String selectSql =</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US>4 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"SELECT * FROM Customer WHERE first_name=? AND last_name=?";</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US>5 &nbsp;&nbsp;&nbsp;String insertSql = "INSERT INTO Customer VALUES(?, ?)";</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US>6 &nbsp;&nbsp;&nbsp;try{</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US>7 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Connection conn = dbmsConnectionFactory.getConnection();</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US>8 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PreparedStatement selStmt = conn.prepareStatement(selectSql);</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 5.25pt"><span lang=EN-US>9 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;selectStmt.setString(1, c.getFirstName());</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>10 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;selectStmt.setString(2, c.getLastName());</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>11 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ResultSet rs = selStmt.executeQuery();</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>12 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (rs.next()){</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>13 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// In this case, the failure condition is produced if you</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>14 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// &nbsp;can already locate a metching record in the database.</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>15 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw new CustomerExistsException("Customer exists:" + c, c);</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>16 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>17 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else{</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>18 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PreparedStatement insStmt = conn.prepareStatement(insertSql);</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>19 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insStmt.setString(1, c.getFirstName());</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>20 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insStmt.setString(2, c.getLastName());</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>21 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int status = insStmt.executeUpdate();</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>22 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 0pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>23 &nbsp;&nbsp;}</span></p>
<p class=10 style="MARGIN: 2.5pt 0cm 7.8pt 21pt; TEXT-INDENT: 0cm"><span lang=EN-US>24 &nbsp;&nbsp;catch (SQLException exc){</span></p>
<p class=MsoNormal style="TEXT-INDENT: 21pt; LINE-HEIGHT: 16.5pt"><span lang=EN-US>Java</span><span style="FONT-FAMILY: 宋体">关键字</span><span lang=EN-US>throw</span><span style="FONT-FAMILY: 宋体">将这个新异常对象传给该方法的调用者。在执行完这</span><span lang=EN-US>3</span><span style="FONT-FAMILY: 宋体">个步骤后，就创建了自定义异常。除非派生一个非检测异常类</span><span lang=EN-US>(</span><span style="FONT-FAMILY: 宋体">如</span><span lang=EN-US>RuntimeException</span><span style="FONT-FAMILY: 宋体">或</span><span lang=EN-US>Error)</span><span style="FONT-FAMILY: 宋体">，否则调用方法的任何对象随后将按照&#8220;处理或声明&#8221;规则解决该异常。</span></p>
<p class=MsoNormal style="TEXT-INDENT: 21pt; LINE-HEIGHT: 16.5pt"><span style="FONT-FAMILY: 宋体">这引出了一个有趣的问题：在自定义异常时，应如何派生？必须在</span><span lang=EN-US>Throwable</span><span style="FONT-FAMILY: 宋体">类层次结构中派生，否则将不能在应用程序中传播异常。另外，不能从</span><span lang=EN-US>Throwable</span><span style="FONT-FAMILY: 宋体">直接派生。</span><span lang=EN-US>Throwable</span><span style="FONT-FAMILY: 宋体">为两类主要问题</span><span lang=EN-US>(Exception</span><span style="FONT-FAMILY: 宋体">和</span><span lang=EN-US>Error)</span><span style="FONT-FAMILY: 宋体">提供行为基础，不能为这棵继承树定义新分支。一般也不要直接继承</span><span lang=EN-US>Error</span><span style="FONT-FAMILY: 宋体">或其任何子类，因为自定义异常通常不符合错误标准</span><span lang=EN-US>(</span><span style="FONT-FAMILY: 宋体">即适当应用程序不应试图捕获的严重问题</span><span lang=EN-US>)</span><span style="FONT-FAMILY: 宋体">。</span></p>
<p class=MsoNormal style="TEXT-INDENT: 21pt; LINE-HEIGHT: 16.5pt"><span style="FONT-FAMILY: 宋体">需要从</span><span lang=EN-US>Exception</span><span style="FONT-FAMILY: 宋体">类层次结构中派生。一般地，应将自定义异常定义为故障状态更一般的异常类型的子类。例如，</span><span lang=EN-US>ServerConnectionException</span><span style="FONT-FAMILY: 宋体">是</span><span lang=EN-US>java.io.IOException</span><span style="FONT-FAMILY: 宋体">的子类，因为</span><span lang=EN-US>Server- Connec tionException</span><span style="FONT-FAMILY: 宋体">是</span><span lang=EN-US>java.io.IOException</span><span style="FONT-FAMILY: 宋体">的更具体类型。</span></p>
<p class=MsoNormal style="TEXT-INDENT: 21pt; LINE-HEIGHT: 16.5pt"><span style="FONT-FAMILY: 宋体">如果定义的异常从</span><span lang=EN-US>RuntimeException</span><span style="FONT-FAMILY: 宋体">树继承，是否属于正确的编码实践？若如此，就回避了异常机制，即使声明了异常，类也不必显式处理异常</span><span style="FONT-FAMILY: 宋体">。</span></p>
<br><br><a href="http://luckaway.javaeye.com/blog/189385"><u><font color=#108ac6>自定义异常的原则（转）</font></u></a><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;本文是<span class=hilite3><font style="BACKGROUND-COLOR: #aaffaa">Exception</font></span>处理的一篇不错的文章，从<span class=hilite1><font style="BACKGROUND-COLOR: #ffff00">Java</font></span> <span class=hilite3><font style="BACKGROUND-COLOR: #aaffaa">Exception</font></span>的概念介绍起，依次讲解了<span class=hilite3><font style="BACKGROUND-COLOR: #aaffaa">Exception</font></span>的类型（Checked/Unchecked），<span class=hilite3><font style="BACKGROUND-COLOR: #aaffaa">Exception</font></span>处理的最佳实现： <br><br>1．&nbsp; 选择Checked还是Unchecked的几个经典依据 <br><br>2．&nbsp; <span class=hilite3><font style="BACKGROUND-COLOR: #aaffaa">Exception</font></span>的封装问题 <br><br>3．&nbsp; 如无必要不要创建自己得<span class=hilite3><font style="BACKGROUND-COLOR: #aaffaa">Exception</font></span> <br><br>4．&nbsp; 不要用<span class=hilite3><font style="BACKGROUND-COLOR: #aaffaa">Exception</font></span>来作流程控制 <br><br>5．&nbsp; 不要轻易的忽略捕获的<span class=hilite3><font style="BACKGROUND-COLOR: #aaffaa">Exception</font></span> <br><br>6．&nbsp; 不要简单地捕获顶层的<span class=hilite3><font style="BACKGROUND-COLOR: #aaffaa">Exception</font></span>&#8221; <br><br>——选自JAVADigest.Net对原文的介绍 <br><br>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/54505.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2009-02-13 11:06 <a href="http://www.cnitblog.com/wufajiaru/archive/2009/02/13/54505.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>log4j和jboss</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/12/22/52915.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Mon, 22 Dec 2008 10:28:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/12/22/52915.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/52915.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/12/22/52915.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/52915.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/52915.html</trackback:ping><description><![CDATA[<span style="COLOR: #008000"><strong style="FONT-SIZE: 12pt">首先认识一下log4j：</strong></span>&nbsp;
<div class=blog_content>一.Log4j的基本概念 <br>1.Logger: 日志记录器. <br>日志的级别 级别越低 日志记录将更详细 <br>级别有(由高到底)off,fatal,error,warn,info,debug,all 级别高的可覆盖级别低的日志输出 <br>2.Appender: 输出端 指定日志输出到那个地方.一个Logger可以有多个Appender输出端,每个Appender输出端也可以被多个Logger使用. <br>常用的输出端有: <br>ConsoleAppender 将日志输出到控制台 <br>org.apache.log4j.rolling.RollingFileAppender 可指定文件和日期的输出端 <br>WriterAppender 将日志以流格式发送到任何指定的地方 <br>JDBCAppender 通过JDBC把日志输出到数据库中 <br>3.Layout: 日志格式化 <br>log4j有三种Layout: <br>HTMLLayout 格式化日志输出为HTML表格; <br>PatternLayout 根据指定的格式(ConversionPattern)格式化日志输出(常用) <br>SimpleLayout 以非常简单的方式输出 <br><br>二.配置 <br>1. log4j的配置文件 log4j.xml&nbsp; <br></div>
<p class=xml style="DISPLAY: none" name="code"><br>&nbsp;</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #008080">&nbsp;1</span><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">&lt;?</span><span style="COLOR: #ff00ff">xml&nbsp;version="1.0"&nbsp;encoding="UTF-8"&nbsp;</span><span style="COLOR: #0000ff">?&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;2</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">&lt;!</span><span style="COLOR: #ff00ff">DOCTYPE&nbsp;configuration&nbsp;</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;3</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">configuration&nbsp;</span><span style="COLOR: #ff0000">xmlns</span><span style="COLOR: #0000ff">='http://logging.apache.org/'&nbsp;</span><span style="COLOR: #ff0000">debug</span><span style="COLOR: #0000ff">="true"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;4</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;5</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000">&nbsp;把日志输出到控制台中&nbsp;</span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;6</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">appender&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="console"</span><span style="COLOR: #ff0000">&nbsp;class</span><span style="COLOR: #0000ff">="org.apache.log4j.ConsoleAppender"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;7</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">layout&nbsp;</span><span style="COLOR: #ff0000">class</span><span style="COLOR: #0000ff">="org.apache.log4j.PatternLayout"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;8</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">param&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="ConversionPattern"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="%d&nbsp;%-5p&nbsp;[%t]&nbsp;%C{2}&nbsp;(%F:%L)&nbsp;&nbsp;%m%n"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">&nbsp;9</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">layout</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">10</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">appender</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">11</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">12</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000">&nbsp;把日志按日期输出到日期日志文件中&nbsp;</span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">13</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">appender&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="ROLL"</span><span style="COLOR: #ff0000">&nbsp;class</span><span style="COLOR: #0000ff">="org.apache.log4j.rolling.RollingFileAppender"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">14</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">rollingPolicy&nbsp;</span><span style="COLOR: #ff0000">class</span><span style="COLOR: #0000ff">="org.apache.log4j.rolling.TimeBasedRollingPolicy"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">15</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">param&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="FileNamePattern"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="${catalina.home}/log4jlogs/mywebsite.%d{yyyy-MM-dd}.log.zip"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">16</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">rollingPolicy</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">17</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">layout&nbsp;</span><span style="COLOR: #ff0000">class</span><span style="COLOR: #0000ff">="org.apache.log4j.PatternLayout"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">18</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">param&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="ConversionPattern"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="%d{MM-dd&nbsp;HH:mm:ss}&nbsp;%p&nbsp;[%t]&nbsp;%C{2}&nbsp;(%F:%L)&nbsp;-&nbsp;%m%n"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">19</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">layout</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">20</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">appender</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">21</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">22</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;<br></span><span style="COLOR: #008080">23</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000">&nbsp;终端日志文件&nbsp;</span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">24</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">appender&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="terminal-logger"</span><span style="COLOR: #ff0000">&nbsp;class</span><span style="COLOR: #0000ff">="org.apache.log4j.DailyRollingFileAppender"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">25</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">param&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="File"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="${catalina.home}/logs/kiosks/TerminalService.log"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">26</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">param&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="Append"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="true"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">27</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">layout&nbsp;</span><span style="COLOR: #ff0000">class</span><span style="COLOR: #0000ff">="org.apache.log4j.PatternLayout"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">28</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">param&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="ConversionPattern"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="%d{MM-dd&nbsp;HH:mm:ss}&nbsp;[%p]&nbsp;[%t]&nbsp;(%F:%L):&nbsp;%m%n"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">29</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">layout</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">30</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">filter&nbsp;</span><span style="COLOR: #ff0000">class</span><span style="COLOR: #0000ff">="org.apache.log4j.varia.LevelRangeFilter"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">31</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">param&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="levelMin"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="INFO"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">32</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">param&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="AcceptOnMatch"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="true"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">33</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">filter</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">34</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">appender</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">35</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">logger&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="com.macaufly.kiosks"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">36</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">level&nbsp;</span><span style="COLOR: #ff0000">value</span><span style="COLOR: #0000ff">="INFO"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">37</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">appender-ref&nbsp;</span><span style="COLOR: #ff0000">ref</span><span style="COLOR: #0000ff">="terminal-logger"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">38</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">logger</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">39</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;<br></span><span style="COLOR: #008080">40</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">41</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000">&nbsp;设置接收所有输出的通道(但在logger中定义的级别在这里不起作用)&nbsp;</span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">42</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">root</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">43</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">level&nbsp;</span><span style="COLOR: #ff0000">value</span><span style="COLOR: #0000ff">="debug"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000">&nbsp;设置级别&nbsp;</span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">44</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">appender-ref&nbsp;</span><span style="COLOR: #ff0000">ref</span><span style="COLOR: #0000ff">="console"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">45</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">root</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">46</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000">&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">47</span><span style="COLOR: #008000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;设置域名限制,即&nbsp;com.dchaoxiong.studentmanage.servlets&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">48</span><span style="COLOR: #008000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;包及以下的日志均输出到下面指定的通道(appender-ref)中&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #008080">49</span><span style="COLOR: #008000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">50</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">logger&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="com.dchaoxiong.studentmanage.servlets"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">51</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">level&nbsp;</span><span style="COLOR: #ff0000">value</span><span style="COLOR: #0000ff">="debug"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000">&nbsp;设置级别&nbsp;</span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">52</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">appender-ref&nbsp;</span><span style="COLOR: #ff0000">ref</span><span style="COLOR: #0000ff">="ROLL"</span><span style="COLOR: #ff0000">&nbsp;</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #008000">&lt;!--</span><span style="COLOR: #008000">&nbsp;与前面的通道id相对应&nbsp;</span><span style="COLOR: #008000">--&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">53</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">logger</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;<br></span><span style="COLOR: #008080">54</span><span style="COLOR: #000000"><img src="http://www.cnitblog.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">&lt;/</span><span style="COLOR: #800000">configuration</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;</span></div>
<p class=xml style="DISPLAY: none" name="code"></p>
<div class=blog_content>2. 把该配置文件放在工程的类路径下 <br>3.private Logger logger = Logger.getLogger(ClassName.class);取得loger类 </div>
<br><br><strong style="FONT-SIZE: 12pt; COLOR: #008000">在log4j中定义了5个级别的日志等级：</strong><br>
<li>ERROR - A definite problem （最少）
<li>WARN - Likely a problem, but can live with it
<li>INFO - Common notifications, lifecycle stuff
<li>DEBUG - Low volume debug
<li>TRACE - High volume debug （最多）
<p>&nbsp;</p>
<p><span style="COLOR: #008000"><strong style="FONT-SIZE: 12pt">今天解决的问题是如何不让jboss在后台打出过多的信息：</strong></span><br><br>开始还以为是自己的log4j打出来的，居然连hibernate连数据库的密码都打出来，狂汗；<br>后来改了一通自己的log4j.xml，一点作用都没起，一查，原来自己的log4j都没有启用，瀑布汗；<br>于是，把矛头指向jboss，搜索&#8220;log4j&#8221;，出来三个log4j.xml，其中有一个在defaul下面的应该是我用到的；<br>修改一通，把org.hibernate的设置为error，噢耶，小功告成。<br><br>总结一下：<br>1.jboss里面默认带了log4j的<br>2.据说，如果项目中也启用log4j，可能会和jboss的冲突；<br>3.jboss中的log4j也不知道是哪个版本的，我们平常使用的&lt;logger&gt;元素在那里是要用&lt;category&gt;的；<br>4.想把项目的log输出到file，而其他的都依然console&amp;file，还没成功，ps：只是现在还没成功，最终应该是没有问题的。</p>
<p>最后，Aramil提供了一个文档，也许能解决更多疑惑：<a href="http://www.javaeye.com/topics/download/af3cde8a-0f83-473f-8fbb-0457bac30c5c"><font color=#006699>JBossLog4j.zip</font></a> </p>
</li>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/52915.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-12-22 18:28 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/12/22/52915.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>stmt.setQueryTimeout(seconds); [最后还是没起作用]</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/12/17/52727.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Wed, 17 Dec 2008 10:25:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/12/17/52727.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/52727.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/12/17/52727.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/52727.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/52727.html</trackback:ping><description><![CDATA[<p>困扰了好几天的问题居然这么容易就解决了哈。<br><br>程序中需要调用一个存储过程，这个存储过程的执行时间很长，而程序也并不需要得到他的返回值，为了使程序等待的时间不致于太长，就需要在存储过程执行结束之前停止调用。<br><br>开始，想在存储过程中控制，没有实现；<br>后来，想专门起一个线程，让他自己靠边执行，因为时间原因没有顾得上实现，也太麻烦；<br>再后来，小林提醒说网上有人说可以让存储过程主动超时；<br>最后，居然看到statment有这么个方法：setQueryTimeout(seconds)<br><br>哈哈，没想到，设置个超时时间为1秒，一秒钟以后就立刻返回了。</p>
<br><br>＝＝＝＝＝＝＝＝＝＝＝＝<br>后记<br><br>第二天试验发现，其实根本就没有起作用，后来还是起了一个新的线程让他执行，唉，居然被欺骗了......<br><br>可是，为什么就不起作用呢？
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/52727.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-12-17 18:25 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/12/17/52727.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ecside二次笔摘</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/12/16/52668.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Tue, 16 Dec 2008 03:21:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/12/16/52668.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/52668.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/12/16/52668.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/52668.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/52668.html</trackback:ping><description><![CDATA[这几天偶尔会碰到ecside的问题，零零碎碎碰下来也对他有了一点了解，有些问题从网上搜到了答案，有些问题绕开了解决。不过，总的来说，ec还是一个不错的作品，虽然原作者已经改为开发一个新的替代产品。<br>下面是从网上转载的资料，可以用来参考：<br><a href="http://blog.sina.com.cn/s/blog_4b22130e010009b5.html~type=v5_one&amp;label=rela_prevarticle">http://blog.sina.com.cn/s/blog_4b22130e010009b5.html~type=v5_one&amp;label=rela_prevarticle</a><br><br>
<p>1.使用方法：<br>ec:table标签内 增加<br>listHeight="数字" 属性 （指定列表体的高度）<br>同时把要指定 width="数字" 不能省略 同时要使用绝对大小而不要使用百分比</p>
<p>&nbsp;<wbr></p>
<p>请教楼主，下了你的代码试了一下，如果把默认DEFAULT_PAGE_SIZE改为别的数字，比如每页显示5条，分页错误，点击下一页，显示还是10条，</p>
<p>你的jsp页面里的 ec:table的 rowsDisplayed 属性也要修改 改为5</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>bjwulin 写道</p>
<p>fins 写道</p>
<p><br>没太看明白　　:(</p>
<p>reload第一个表格　你是在怎么reload的？？</p>
<p>我描述不清楚，这样说吧，如果表格有21条数据，每页10条，现在在第三页，如果我在数据库里面手工删除1条数据，然后调用EcUtil.reload(...)的话，怎么让它显示第二页的数据。因为我在后台得到的还是pageNo=3</p>
<p>我不明白的就是<br>为什么"后台得到的还是pageNo=3"??</p>
<p>你后台是怎么计算页数的?<br>我怀疑可能是你没有调用EccnUtil.refresh(...)<br>如果数据数目发生变化了<br>建议 先<br>EccnUtil.refresh(...)<br>再<br>EccnUtil.reload(...)</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>1)&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> 实现了灵活的可定制的&#8220;可编辑列表&#8221;功能 （详见help.txt 200行左右的描述 以及示例）<br>支持多种编辑方式（文本框 下拉框将来还会支持更多），可自定义模版（使用自定义的文本框下拉框），还提供了：<br>对可编辑列进行标识，对编辑过的cell进行标识（默认为改变单元格背景色），<br>使用ajax技术提交后台，提交成功的cell将清除编辑标识等贴心设计。<br>2) 增加了 高亮显示选种行的功能，使用 ec:table属性: selectlightRow="true"<br>3) 去掉了 fullnavigation导航条，将其与navigation导航条合并<br>改为为ec:table增加属性 nearPageNum="数字" 用来设置导航条前后显示的邻近页数 等于0时 为不使用邻近页。<br>4) 为ec:table增加了 maxRowsExported="数字" 属性，用来限制导出大最大条数，如果数据超过这个数目，则不执行导出操作。<br>5) 为之前增加的ec:table的pageSizeList属性 增加了特性<br>pageSizeList="max:200,10,15,30,50,100,all" 如果 10--100以及all中，某一项大过了max的200则不在列表中显示。<br>也可以只使用pageSizeList="max:200" 此时将使用默认设置，并进行max控制。<br>6) 解决了pdf中文编码问题，终于支持pdf导出了。<br>7) 恢复了对sitemesh的支持，用法见原版ec文档（我没有亲自没有测试,因为我不会用sitemesh ）。<br>8) Ajax翻页优化，同时增加了 ECSide.findAjaxZoneAtClien 属性，可设置客户端 还是 服务端进行 html代码剪裁。<br>默认推荐使用 服务器端。<br>9) 再次对js和java代码进行了较大规模的重构,清理了一些无用代码，添加了必要的协议信息。<br>10) 还有一些细节的修改(例如对滚轮的支持更自然) 和对一些小bug的修正，但是由于变化较大，肯定还会带来一些新bug。<br>11) 整个示例的应用逐步发展为 ecside 的最佳实践，加入了hsqldb（hsqldb的使用参考了springside），全新的例子。<br>当然还不够好 会在以后的日子里继续完善。<br>12) 做了一个简单的logo 。</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>使用方法：<br>ec:table标签内 增加<br>listHeight="数字" 属性 （指定列表体的高度）<br>同时把要指定 width="数字" 不能省略 同时要使用绝对大小而不要使用百分比</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>smalldeer 写道</p>
<p>一直关注ecside，谢谢你们的无私奉献，真的增强好多。<br>有一个问题请教，我在一个页面中，要使用2个表格，<br>如果不写request.setAttribute("totalRows", new Integer(rowc));<br>就会报 You need to specify the totalRows (as an Integer) to use the org.extremecomponents.table.callback.LimitCallback.<br>如果写，但是有2个table，参数只有一个totalRows，我如何为2个表格分别指定它的totalRows呢</p>
<p>请教一下，十分感谢。</p>
<p>说来惭愧啊<br>我虽然一直在研究ec的代码 并做出改造<br>但是 有几个地方我一直没有深入的涉及<br>其中就包括 同一叶面显示多表格的设计</p>
<p>因为我一直认为这不是一个好的实现方式</p>
<p>其实代码是这样的<br>他先去找 tableId+"_totalRows"<br>找不到了 才去找 totalRows<br>我的那个例子对你有误导 我的错</p>
<p>&nbsp;<wbr></p>
<p>ecside介绍：</p>
<p>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</p>
<p>ecside是一个开源的列表组件。</p>
<p>他源自著名开源列表组件 eXtremeComponents （http://www.extremecomponents.org），</p>
<p>但现在已经脱离eXtremeComponents,独立发展（仍有大量代码来自 eXtremeComponents）。</p>
<p>由于各种协议和各种授权的问题，目前还不能独立成为一个开源项目，但&#8220;做最实用易用的列表组件&#8221;是ecside最终的目标。</p>
<p>作者： fins ( name: Wei Zijun&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> email:fins@163.com&nbsp;<wbr>&nbsp;<wbr> blog:http://fins.javaeye.com )</p>
<p>&nbsp;<wbr></p>
<p>(详见readme.txt)</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>基础功能的使用请参考 eXtremeComponents 官方网站(http://www.extremecomponents.org)的wiki（有中文版）</p>
<p>&nbsp;<wbr></p>
<p>增强的功能简介：</p>
<p>&nbsp;<wbr></p>
<p>1&nbsp;<wbr> ec:table属性增加&nbsp;<wbr> toolbarLocation</p>
<p>&nbsp;<wbr>用来控制工具条在上还是在下显示</p>
<p>&nbsp;<wbr>可选值 "bottom" "top" "none"（不显示）</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>2&nbsp;<wbr> ec:table属性增加&nbsp;<wbr> toolbarContent</p>
<p>&nbsp;<wbr>可自定义工具条显示那些内容，以及排列顺序</p>
<p>默认： toolbarContent="navigation|pagejump|pagesize|export|extend|status"</p>
<p>例子&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> toolbarContent="pagejump|navigation|export|extend|status"</p>
<p>此时 工具条将不显示"页面行数调整"框同时顺序也会和默认的发生变化</p>
<p>&nbsp;<wbr></p>
<p>navigation 导航条</p>
<p>pagejump 页面跳转</p>
<p>pagesize 页面行数设置</p>
<p>export 导出按钮区</p>
<p>extend 自定义扩展区</p>
<p>status 数据信息区</p>
<p>&nbsp;<wbr></p>
<p>同时 为ec:table增加属性 nearPageNum="数字",</p>
<p>用来设置导航条前后显示的邻近页数,不设置将使用默认值，设置为0则不显示邻近页</p>
<p>&nbsp;<wbr></p>
<p>3&nbsp;<wbr> ec:table属性增加&nbsp;<wbr> pageSizeList</p>
<p>可用来设置&#8220;页面行数选择列表&#8221;中的具体数值</p>
<p>默认：pageSizeList="10,20,50,100,1000,2000,all"</p>
<p>其中的all为增加全部显示功能。</p>
<p>例子 &nbsp;<wbr>&nbsp;<wbr>pageSizeList="10,20,50"</p>
<p>此时列表里将只显示 10 20 50供选择</p>
<p>max:数字 特性 :</p>
<p>pageSizeList="max:200,10,15,30,50,100,all"</p>
<p>如果 10--100以及all中，某一项大过了max的200则不在列表中显示。</p>
<p>也可以只使用pageSizeList="max:200" 此时将使用默认设置，并用max限制。</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>4 ec:table属性增加 xlsFileName&nbsp;<wbr> 和 pdfFileName</p>
<p>用来快捷的实现导出xls文件</p>
<p>如果你只是想使用默认的方式导出 xls 和 pdf文件 不用再使用 ec:exportXls&nbsp;<wbr> ec:exportPdf标签了</p>
<p>直接在ec:table里使用这个属性就ok.</p>
<p>使用方法 xlsFileName="文件名.xls"</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>5&nbsp;<wbr> ec:table属性增加&nbsp;<wbr> showPrint</p>
<p>显示打印按钮，该功能只能在ie 5.5以上浏览器中使用没有使用第三方组件 使用了ie内置组件</p>
<p>使用方法： showPrint="true"</p>
<p>打印按钮将作为导出的一种类型而存在</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>6 ec:table属性增加&nbsp;<wbr> resizeColWidth 和 minColWidth</p>
<p>默认：&nbsp;<wbr> resizeColWidth="false"&nbsp;<wbr> minColWidth="20"</p>
<p>用来实现手动调节列宽的功能 在ie 5.5+ 和ff 2.0下测试通过</p>
<p>resizeColWidth="true" 实现列宽调整</p>
<p>minColWidth="20" 调整时列的最小宽度</p>
<p>目前不能和过滤功能一同使用(当filterable="true"时候不可以用)</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>7 为ec:row 添加更多的html事件支持，现支持：onmouserover onmouserout onclick ondbclick</p>
<p>&nbsp;<wbr></p>
<p>8 为ec:column 添加更多的html事件支持，现支持：onmouserover onmouserout onclick ondbclick</p>
<p>&nbsp;<wbr></p>
<p>9 为ec:table ec:row ec:column 增加了 tagAttributes属性</p>
<p>该属性用来为元素增加一些自定义的html属性</p>
<p>例如&nbsp;<wbr> ec:column 现在并不支持&nbsp;<wbr> onmouseup事件</p>
<p>可以通过下面的方式实现</p>
<p>&nbsp;<wbr></p>
<p>&lt;ec:column tagAttributes="onmouseup=\"alert('test mouse up');\" " .......</p>
<p>&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>10 ec:column属性增加 ellipsis</p>
<p>实现单元格内数据过长的时候 自动截短并加"..."的功能 ie only</p>
<p>因为ff不支持 text-overflow: ellipsis;</p>
<p>使用 ellipsis="true"</p>
<p>使用时 还要为ec:table加上 style="table-layout:fixed;" (如果您已经使用了调整列宽功能 则不用添加)</p>
<p>&nbsp;</p>
<p><span XML:LANG="EN-US">11 ec:column属性增加<span>&nbsp;<wbr></span> headerSpan </span></p>
<p><span>实现表头的跨列显示 </span></p>
<p><span>使用</span></p>
<p><span XML:LANG="EN-US">&lt;ec:column<span>&nbsp;<wbr></span> headerSpan="2" ...</span></p>
<p><span XML:LANG="EN-US">&lt;ec:column<span>&nbsp;<wbr></span> headerSpan="0" ...</span></p>
<p><span>注意当把 一个<span XML:LANG="EN-US">column 的 headerSpan=设置为 n的时候</span></span></p>
<p><span>那么他下面的 <span XML:LANG="EN-US">n-1个 column 的 headerSpan 一定要为 0 (这个以后会想办法修正现在这么处理太麻烦了)</span></span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">12 ec:column属性增加<span>&nbsp;<wbr></span> calcSpan</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr></span>实现统计行的标题跨列显示</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr></span>使用<span>&nbsp;<wbr></span></span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr></span>&lt;ec:column<span>&nbsp;<wbr></span> calc="total" calcTitle= "合计" calcSpan="2" ....</span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr></span>13 增加 ec:extendrow 标签</span></p>
<p><span>在列表前<span XML:LANG="EN-US">/后加一行或多行 取决于你的html代码怎么写因为这个是绝对自由的 连tr标签都要自己写</span></span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr></span>before="true"<span>&nbsp;<wbr></span> (true top false(默认))</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr></span>当 before="top"的时候 所加行会出现在 列表表头的上面</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr></span>这样你可以做多行表头了<span>&nbsp;<wbr></span> （但这时候 不支持列宽调整 想支持需要自己做些动作详见示例文件demo2.jsp）</span></p>
<p><span>例如</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;ec:extendrow before="true"&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;tr&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;td style="background-color:#ffeedd" &gt;*列表前扩展行&lt;/td&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;td style="background-color:#ffeedd"&gt;可以在这里加一些自定内容&lt;/td&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;td style="background-color:#ffeedd" colspan="2"&gt;该行与ectable在同一table内&lt;/td&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;/tr&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;/ec:extendrow&gt;</span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;ec:extendrow&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;tr&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;td style="background-color:#eeddff"&gt;&#160;&lt;/td&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;td style="background-color:#eeddff"&gt;*列表后扩展行&lt;/td&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;td style="background-color:#eeddff"&gt;可以在这里加一些自定内容&lt;/td&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;td style="background-color:#eeddff"&gt;该行与ectable在同一table内&lt;/td&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;/tr&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;/ec:extendrow&gt;</span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr></span>14 增加 ec:extend 标签</span></p>
<p><span>用来在<span XML:LANG="EN-US">toolbar内增加一些自定义的html代码属性</span></span></p>
<p><span>例如 <span XML:LANG="EN-US">&lt;ec:extend&gt;&lt;a href="#"&gt;自定义扩展内容&lt;/a&gt;&lt;/ec:extend&gt;</span></span></p>
<p><span>这时该连接 将会出现在 <span XML:LANG="EN-US">toolbarContent 中的 extend所在位置</span></span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr></span>15 增加 ec:extendbar 标签</span></p>
<p><span>在列表前<span XML:LANG="EN-US">/后加些html代码<span>&nbsp;<wbr></span> 属性<span>&nbsp;<wbr></span> before="true"<span>&nbsp;<wbr></span> (true top false(默认))</span></span></p>
<p><span>如果要加的东西比较多<span XML:LANG="EN-US"><span>&nbsp;<wbr></span> 建议使用这个而不要使用ec:extend</span></span></p>
<p><span XML:LANG="EN-US">ec:extendbar 添加的内容不会和组件自带的tool放到一行</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr></span>当 before="top"的时候 所加内容会出现在 列表和列表标题之间</span></p>
<p><span>例如</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;ec:extendbar before="true" &gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;span style="color:#999999"&gt;*工具条 前扩展块:可以在工具条前加些你自己想加的东西，&lt;b&gt;所加内容和ectable在同一form内&lt;/b&gt;&lt;/span&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;/ec:extendbar&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;ec:extendbar&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;span style="color:#999999"&gt;*工具条 后扩展块:可以在工具条后加些你自己想加的东西，&lt;b&gt;所加内容和ectable在同一form内&lt;/b&gt;&lt;/span&gt;</span></p>
<p><span XML:LANG="EN-US"><span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> &lt;/ec:extendbar&gt;</span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">16 增加了cell类型</span></p>
<p><span>复选框 <span XML:LANG="EN-US">cell="checkbox"<span>&nbsp;<wbr></span> headerCell="checkbox"</span></span></p>
<p><span>单选框 <span XML:LANG="EN-US">cell="radiobox"<span>&nbsp;<wbr></span> headerCell="riadiobox"</span></span></p>
<p><span>例如</span></p>
<p><span XML:LANG="EN-US">&lt;ec:column cell="checkbox"<span>&nbsp;<wbr></span> headerCell="checkbox"</span></p>
<p><span XML:LANG="EN-US">alias="chkBoxNameXXX" value="chkValue${pre.nickname}"</span></p>
<p><span XML:LANG="EN-US">width="22" viewsAllowed="html" /&gt;</span></p>
<p><span>注意 <span XML:LANG="EN-US">value对应生成的 checkBox 的 value ,alias 对应生成的 checkBox 的name</span></span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">17 增加页面变量 ${TOTALROWCOUNT} 用来标示当前纪录在全部记录中的行数</span></p>
<p><span>（<span XML:LANG="EN-US">${ROWCOUNT}用来标示当前纪录在当前页中的行数）</span></span></p>
<p><span>例子</span></p>
<p><span XML:LANG="EN-US">&lt;ec:column property="name" title="姓名" width="160"&gt;${TOTALROWCOUNT},${pre.name}&lt;/ec:column&gt;</span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">18 增加了&#8220;固定列表头，滚动列表体&#8221;(&#8220;列表内部滚动条&#8221;)的功能</span></p>
<p><span>这个功能实现起来比我一开始想像的复杂</span></p>
<p><span>不是简单的使用一个 <span XML:LANG="EN-US">div overflow:scroll就可以搞定的</span></span></p>
<p><span>虽然功能是支持了但是代码肯定还有很多<span XML:LANG="EN-US">bug或者是可以改进的地方</span></span></p>
<p><span>欢迎大家积极的提出宝贵的意见谢谢了</span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span>使用方法：</span></p>
<p><span XML:LANG="EN-US">ec:table标签内增加</span></p>
<p><span XML:LANG="EN-US">listHeight="数字" 属性 （指定列表体的高度）</span></p>
<p><span>同时把要指定 <span XML:LANG="EN-US">width="数字" 不能省略同时要使用绝对大小 而不要使用百分比</span></span></p>
<p><span>详见例子<span XML:LANG="EN-US">:</span></span></p>
<p><span XML:LANG="EN-US">demo0.jsp</span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">19 增加shadowRow功能</span></p>
<p><span XML:LANG="EN-US">shadowRow我自己瞎起的名字解释如下：</span></p>
<p><span>每行下面可以再加一个子行这个行里显示什么可以由大家自己定义 </span></p>
<p><span>常见的应用是在有些论坛论坛主题列表里当你点击行开头的小加号的时候 会在这行下面展开一个区域那里面显示的是主帖的内容<span XML:LANG="EN-US">.</span></span></p>
<p><span>我们可以把这个扩展一下利用<span XML:LANG="EN-US">ajax从后台去读取我们想读取的信息,这样我们就可以做任何我们想做的事情了)</span></span></p>
<p><span>该功能是不通过标签或<span XML:LANG="EN-US">java代码实现 纯js实现。</span></span></p>
<p><span>详见例子 <span XML:LANG="EN-US">demo0.jsp （大家一定要注意看demo0.jsp里的注释啊 呵呵）</span></span></p>
<p><span>其实有了这个功能，大家已经可以自己比较容易的实现可编辑表格的功能了呵呵过一阵我会发一个例子上来</span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">20 ec:table 增加了 excludeParameters 和 includeParameters 属性</span></p>
<p><span>使用后，<span XML:LANG="EN-US">ecside将自动排除或保留属性中所指定的&#8220;表单属性&#8221;</span></span></p>
<p><span>这个如果你理解了 <span XML:LANG="EN-US">autoIncludeParameters 的用处就不难理解这两个属性的用处了</span></span></p>
<p><span>注意<span XML:LANG="EN-US">: excludeParameters 比 includeParameters 有更高的优先级</span></span></p>
<p><span>即 <span XML:LANG="EN-US">excludeParameters="a"<span>&nbsp;<wbr></span> includeParameters ="a" 时 a仍然将被排除</span></span></p>
<p><span>建议尽量使用 <span XML:LANG="EN-US">excludeParameters 不要使用 includeParameters ，除非你非常明确自己要包含的东西。</span></span></p>
<p><span XML:LANG="EN-US">includeParameters 使用不当会使你忘记包含一些必须包含的东西.</span></p>
<p><span XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span XML:LANG="EN-US">excludeParameters="表单属性名称1,表单属性名称2"<span>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> (表单属性名称不能含有半角的逗号)</span></p>
<p><span XML:LANG="EN-US">includeParameters="表单属性名称3,表单属性名称4"</span></p>
<p>&nbsp;</p>
<div class=articleContent id=articleBody>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US"><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">21 实现了灵活的可定制的&#8220;可编辑列表&#8221;： </span></span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">在<span lang=EN-US XML:LANG="EN-US">ec:column 中指定下列属性：</span></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">cellName="这个cell在数据库中真正对应的列名，省略时则自动使用 property对应的名称"</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">cellValue="这个cell在数据库中真正对应的值"</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">cellEdit="a1,a2,a3"<span style="mso-spacerun: yes">&nbsp;<wbr></span></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US"><span style="mso-tab-count: 1">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> a1编辑类型(目前可选input select 其他如radio等还不完善)，</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US"><span style="mso-tab-count: 1">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> a2对应的模版textarea的ID(默认是 "ec_edit_template_'+编辑类型 ),</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US"><span style="mso-tab-count: 1">&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></span> a3触发编辑的事件（默认是ondblclick）</span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">模版为一段写在<span lang=EN-US XML:LANG="EN-US">textarea内的表单域的html代码，书写是完全自由的但是一定要注意不要缺少必要的事件方法和属性。</span></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">22 增加了 高亮显示选种行的功能，使用 ec:table属性: selectlightRow="true"</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">23 为ec:table增加了 maxRowsExported="数字" 属性，用来限制导出大最大条数，</span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">如果数据超过这个数目，则不执行导出操作。</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">24 实现了cell的映射功能（详见示例的性别和 角色列）</span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">用法：</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&lt;ec:column mappingItem="用来映射的MAP在context内的key" mappingDefaultValue="当找不到映射值时要使用的默认值".../&gt;</span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">例如，在示例中，角色的信息以 &#8220;标识<span lang=EN-US XML:LANG="EN-US">--名称&#8221;的形式放到了一个 map内</span></span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">在<span lang=EN-US XML:LANG="EN-US">action中把这个map放到了 request.setAttribute("USERROLE_MAP", CommonDictionary.USERROLE);内</span></span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">在页面使用</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&lt;ec:column property="USERROLE" title="角色" mappingItem="USERROLE_MAP" mappingDefaultValue="[错误的角色]"/&gt;</span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">就会自动将名称显示出来。</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">25 做了一个简单的小标签用来从map生成 select的option列表</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&lt;ec:options items="MAP在context内的key" defaultKey="默认选中的option的value" tagAttributes="附加的html属性"/&gt;</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">还有很多细节的改动，暂略<span lang=EN-US XML:LANG="EN-US">...</span></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">内部变化：</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">1 提炼了ectable生成的js</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">ectable 原先的实现会在页面内生成大量的js代码非常不好</span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">现在翻页相关的<span lang=EN-US XML:LANG="EN-US">js代码全部提炼成了 js函数</span></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">2 翻页按钮的外观提炼成由css决定而不是图片决定。</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">ectable原版生成的是 &lt;img ... src="图片路径" /&gt;</span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">现在生成的是 <span lang=EN-US XML:LANG="EN-US">&lt;input type="button" class="样式" /&gt;</span></span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">这样要改变外观只要去修改&#8220;样式&#8221; 中的背景图片就<span lang=EN-US XML:LANG="EN-US">ok了</span></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">filter clear 按钮 暂时还没有这么处理</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">3 ！！！翻页机制全部使用ajax实现！！！</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">(没有使用任何的ajax后台框架(如dwr ajaxAnywhere)，纯js端实现)</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">filter 排序功能还没有使用ajax</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">4 支持 预查询功能（利用ajax实现）</span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">例如在用户察看第<span lang=EN-US XML:LANG="EN-US">5 页数据的时候，系统会偷偷的把 上一页和下一页的数据也查出来</span></span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">并放到隐藏的<span lang=EN-US XML:LANG="EN-US">textarea内 ，翻页的时候无需再查询</span></span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">当然这个功能有利弊，所以是可设置是否开启</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">5 将导出excel所使用的组件由poi切换成了 jxl</span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">原因有<span lang=EN-US XML:LANG="EN-US">2</span></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">1 jxl这个项目没有死仍然在继续发展</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">2 jxl似乎对内存要求更小</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">(poi在导出20000条纪录的时候outofmemery了,jxl则顺利完成任务)</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">jxl官方网址</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">http://www.andykhan.com/jexcelapi/index.html</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">6 xls导出方式修改如果了解代码的人一定知道 默认的导出xls时是导出的vo/map里的原始数值</span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">而不是页面实际显示的内容，这个问题现在解决了。</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">7 代码进行了较大规模的重构分离出了tool模块(但这个模块还不够灵活下一版本打算在这个基础上争强扩展性灵活性)</span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">你可以自己写<span lang=EN-US XML:LANG="EN-US">tool来取代组件内设的tool</span></span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">组件默认的 <span lang=EN-US XML:LANG="EN-US">tool 配制在 extremetable.properties 文件内</span></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">tool.navigation=org.ecside.tool.PageNavigationTool</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">tool.pagejump=org.ecside.tool.PageJumpTool</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">tool.pagesize=org.ecside.tool.PageSizeTool</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">tool.export=org.ecside.tool.ExportTool</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">tool.status=org.ecside.tool.StatusTool</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">tool.extend=org.ecside.tool.ExtendTool</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">tool.blank=org.ecside.tool.BlankTool</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">tool.|=org.ecside.tool.SeparatorTool</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">tool.,=org.ecside.tool.NewLineTool</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">&nbsp;<wbr></span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">如果你想实现 自己的导航 可以 继承抽象类<span lang=EN-US XML:LANG="EN-US">BaseTool</span></span></p>
<p><span style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt">然后修改配制例如</span></p>
<p><span lang=EN-US style="FONT-SIZE: 10.5pt; mso-bidi-font-size: 12.0pt" XML:LANG="EN-US">tool.navigation=com.mytest.MyNavigationTool</span></p>
</div>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/52668.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-12-16 11:21 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/12/16/52668.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>request 中Parameter(参数) 和Attribute(属性)区别</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/12/01/52119.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Mon, 01 Dec 2008 07:03:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/12/01/52119.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/52119.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/12/01/52119.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/52119.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/52119.html</trackback:ping><description><![CDATA[HttpServletRequest类既有getAttribute()方法，也由getParameter()方法，这两个方法有以下区别： &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr><br>&nbsp;<wbr> （1）HttpServletRequest类有setAttribute()方法，而没有setParameter()方法 &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr><br>&nbsp;<wbr> （2）当两个Web组件之间为链接关系时，被链接的组件通过getParameter()方法来获得请求参数，例如假定welcome.jsp和authenticate.jsp之间为链接关系，welcome.jsp中有以下代码： &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr><br>&nbsp;<wbr> &lt;a &nbsp;<wbr> href="authenticate.jsp?username=weiqin"&gt;authenticate.jsp &nbsp;<wbr> &lt;/a&gt; &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr><br>&nbsp;<wbr> 或者： &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr><br>&nbsp;<wbr> &lt;form &nbsp;<wbr> name="form1" &nbsp;<wbr> method="post" &nbsp;<wbr> action="authenticate.jsp"&gt; &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> 请输入用户姓名：&lt;input &nbsp;<wbr> type="text" &nbsp;<wbr> name="username"&gt; &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr> &nbsp;<wbr> &lt;input &nbsp;<wbr> type="submit" &nbsp;<wbr> name="Submit" &nbsp;<wbr> value="提交"&gt; &nbsp;<wbr><br>&nbsp;<wbr> &lt;/form&gt; &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr><br>&nbsp;<wbr> 在authenticate.jsp中通过request.getParameter("username")方法来获得请求参数username: &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr><br>&nbsp;<wbr> &lt;% &nbsp;<wbr> String &nbsp;<wbr> username=request.getParameter("username"); &nbsp;<wbr> %&gt; &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr><br>&nbsp;<wbr> （3）当两个Web组件之间为转发关系时，转发目标组件通过getAttribute()方法来和转发源组件共享request范围内的数据。假定authenticate.jsp和hello.jsp之间为转发关系。authenticate.jsp希望向hello.jsp传递当前的用户名字，如何传递这一数据呢？先在authenticate.jsp中调用setAttribute()方法： &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr><br>&nbsp;<wbr> &lt;% &nbsp;<wbr><br>&nbsp;<wbr> String &nbsp;<wbr> username=request.getParameter("username"); &nbsp;<wbr><br>&nbsp;<wbr> request.setAttribute("username"，username); &nbsp;<wbr><br>&nbsp;<wbr> %&gt; &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr><br>&nbsp;<wbr> &lt;jsp:forward &nbsp;<wbr> page="hello.jsp" &nbsp;<wbr> /&gt; &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr><br>&nbsp;<wbr> 在hello.jsp中通过getAttribute()方法获得用户名字: &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr><br>&nbsp;<wbr> &lt;% &nbsp;<wbr> String &nbsp;<wbr> username=(String)request.getAttribute("username"); &nbsp;<wbr> %&gt; &nbsp;<wbr><br>&nbsp;<wbr> Hello: &nbsp;<wbr> &lt;%=username &nbsp;<wbr> %&gt; &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr><br>&nbsp;<wbr> (4)从更深的层次考虑，request.getParameter()方法传递的数据，会从Web客户端传到Web服务器端，代表HTTP请求数据。request.getParameter()方法返回String类型的数据。 &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr><br>&nbsp;<wbr> request.setAttribute()和getAttribute()方法传递的数据只会存在于Web容器内部，在具有转发关系的Web组件之间共享。这两个方法能够设置Object类型的共享数据。 &nbsp;<wbr><br>&nbsp;<wbr> &nbsp;<wbr><br>&nbsp;<wbr> ——getParameter得到的都是String类型的。或者是http://a.jsp?id=123中的123，或者是某个表单提交过去的数据。 &nbsp;<wbr><br>&nbsp;<wbr> ——getAttribute则可以是对象。 &nbsp;<wbr><br>&nbsp;<wbr> ——getParameter()是获取POST/GET传递的参数值； &nbsp;<wbr><br>&nbsp;<wbr> ——getAttribute()是获取对象容器中的数据值； &nbsp;<wbr><br>&nbsp;<wbr> ——getParameter：用于客户端重定向时，即点击了链接或提交按扭时传值用，即用于在用表单或url重定向传值时接收数据用。 &nbsp;<wbr><br>&nbsp;<wbr> ——getAttribute：用于服务器端重定向时，即在sevlet中使用了forward函数,或struts中使用了mapping.findForward。getAttribute只能收到程序用setAttribute传过来的值。 &nbsp;<wbr><br>&nbsp;<wbr> 另外，可以用setAttribute,getAttribute发送接收对象.而getParameter显然只能传字符串。 &nbsp;<wbr><br>&nbsp;<wbr> setAttribute是应用服务器把这个对象放在该页面所对应的一块内存中去，当你的页面服务器重定向到另一个页面时，应用服务器会把这块内存拷贝另一个页面所对应的内存中。这样getAttribute就能取得你所设下的值，当然这种方法可以传对象。session也一样，只是对象在内存中的生命周期不一样而已。 &nbsp;<wbr><br>&nbsp;<wbr> getParameter只是应用服务器在分析你送上来的request页面的文本时，取得你设在表单或url重定向时的值。
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/52119.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-12-01 15:03 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/12/01/52119.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java日期转换SimpleDateFormat格式大全【转自www.bitsCN.com】</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/11/27/51946.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Thu, 27 Nov 2008 09:29:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/11/27/51946.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/51946.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/11/27/51946.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/51946.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/51946.html</trackback:ping><description><![CDATA[<p>24小时制时间显示:&nbsp;&nbsp; public class Datetime {</p>
<p>&nbsp;&nbsp;&nbsp; public static void main(String args[]){&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; java.util.Date current=new java.util.Date();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; java.text.SimpleDateFormat sdf=new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String c=sdf.format(current);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(c);<br>&nbsp;&nbsp;&nbsp; }<br>}&nbsp;<br>&nbsp;</p>
<p>12小时制时间显示: </p>
<p>&nbsp;</p>
<p>public class Datetime {</p>
<p>&nbsp;&nbsp;&nbsp; public static void main(String args[]){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; java.util.Date current=new java.util.Date();&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; java.text.SimpleDateFormat sdf=new java.text.SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String c=sdf.format(current);&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(c);<br>&nbsp;&nbsp;&nbsp; }<br>}</p>
<p><br>&nbsp;</p>
<p>&nbsp;</p>
<p>两者区别:yyyy-MM-dd HH:mm:ss ;&nbsp; yyyy-MM-dd hh:mm:ss </p>
<p><a href="http://www.bitscn.net/"></a>&nbsp;</p>
<p>如下: </p>
<p>字母&nbsp; 日期或时间元素&nbsp; 表示&nbsp; 示例&nbsp; <br>G&nbsp; Era 标志符&nbsp; Text&nbsp; AD&nbsp; <br>y&nbsp; 年&nbsp; Year&nbsp; 1996; 96&nbsp; <br>M&nbsp; 年中的月份&nbsp; Month&nbsp; July; Jul; 07&nbsp; <br>w&nbsp; 年中的周数&nbsp; Number&nbsp; 27&nbsp; <br>W&nbsp; 月份中的周数&nbsp; Number&nbsp; 2&nbsp; <br>D&nbsp; 年中的天数&nbsp; Number&nbsp; 189&nbsp; <br>d&nbsp; 月份中的天数&nbsp; Number&nbsp; 10&nbsp; <br>F&nbsp; 月份中的星期&nbsp; Number&nbsp; 2&nbsp; <br>E&nbsp; 星期中的天数&nbsp; Text&nbsp; Tuesday; Tue&nbsp; <br>a&nbsp; Am/pm 标记&nbsp; Text&nbsp; PM&nbsp; <br>H&nbsp; 一天中的小时数（0-23）&nbsp; Number&nbsp; 0&nbsp; <br>k&nbsp; 一天中的小时数（1-24）&nbsp; Number&nbsp; 24&nbsp; <br>K&nbsp; am/pm 中的小时数（0-11）&nbsp; Number&nbsp; 0&nbsp; <br>h&nbsp; am/pm 中的小时数（1-12）&nbsp; Number&nbsp; 12&nbsp; <br>m&nbsp; 小时中的分钟数&nbsp; Number&nbsp; 30&nbsp; <br>s&nbsp; 分钟中的秒数&nbsp; Number&nbsp; 55&nbsp; <br>S&nbsp; 毫秒数&nbsp; Number&nbsp; 978&nbsp; <br>z&nbsp; 时区&nbsp; General time zone&nbsp; Pacific Standard Time; PST; GMT-08:00&nbsp; <br>Z&nbsp; 时区&nbsp; RFC 822 time zone&nbsp; -0800&nbsp; </p>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/51946.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-11-27 17:29 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/11/27/51946.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>PO BO VO DTO POJO DAO概念及其作用（转）</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/11/19/51685.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Wed, 19 Nov 2008 07:52:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/11/19/51685.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/51685.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/11/19/51685.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/51685.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/51685.html</trackback:ping><description><![CDATA[虽然也不一定准确，但是很通俗易懂。<br>转自：<a href="http://hi.baidu.com/caocao808/blog/item/b92753d980368d2f10df9b84.html">http://hi.baidu.com/caocao808/blog/item/b92753d980368d2f10df9b84.html</a><br><br>
<div class=tit>PO BO VO DTO POJO DAO概念及其作用（附转换图）</div>
<div class=date>2007-12-05 16:40</div>
<table style="TABLE-LAYOUT: fixed">
    <tbody>
        <tr>
            <td>
            <div class=cnt id=blog_text>
            <p>PO：<br>persistant object持久对象<br><br>最形象的理解就是一个PO就是数据库中的一条记录。<br>好处是可以把一条记录作为一个对象处理，可以方便的转为其它对象。</p>
            <p>&#160;</p>
            <hr>
            <p><br>BO：<br><font size=4>business object</font><font size=4>业务对象<br><br>主要作用是把业务逻辑封装为一个对象。这个对象可以包括一个或多个其它的对象。<br>比如一个简历，有教育经历、工作经历、社会关系等等。<br>我们可以把教育经历对应一个PO，工作经历对应一个PO，社会关系对应一个PO。<br>建立一个对应简历的BO对象处理简历，每个BO包含这些PO。<br>这样处理业务逻辑时，我们就可以针对BO去处理。<br></font></p>
            <p>&#160;</p>
            <hr>
            <p><br>VO ：<br>value object值对象<br><font size=3>ViewObject表现层对象<br><br></font>主要对应界面显示的数据对象。对于一个WEB页面，或者SWT、SWING的一个界面，用一个VO对象对应整个界面的值。</p>
            <p>&#160;</p>
            <hr>
            <p><br>DTO ：<br>Data Transfer Object数据传输对象<br>主要用于远程调用等需要大量传输对象的地方。<br>比如我们一张表有100个字段，那么对应的PO就有100个属性。<br>但是我们界面上只要显示10个字段，<br>客户端用WEB service来获取数据，没有必要把整个PO对象传递到客户端，<br>这时我们就可以用只有这10个属性的DTO来传递结果到客户端，这样也不会暴露服务端表结构.到达客户端以后，如果用这个对象来对应界面显示，那此时它的身份就转为VO</p>
            <p>&#160;</p>
            <hr>
            <p><br>POJO ：<br><font color=#333333 size=3>plain ordinary java object 简单java对象<br></font>个人感觉POJO是最常见最多变的对象，是一个中间对象，也是我们最常打交道的对象。<br><br>一个POJO持久化以后就是PO<br>直接用它传递、传递过程中就是DTO<br>直接用来对应表示层就是VO</p>
            <p>&#160;</p>
            <hr>
            <p>DAO：<br>data access object数据访问对象<br>这个大家最熟悉，和上面几个O区别最大，基本没有互相转化的可能性和必要.<br>主要用来封装对数据库的访问。通过它可以把POJO持久化为PO，用PO组装出来VO、DTO<br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 总结下我认为一个对象究竟是什么O要看具体环境，在不同的层、不同的应用场合，对象的身份也不一样，而且对象身份的转化也是很自然的。就像你对老婆来说就是老公，对父母来说就是子女。设计这些概念的初衷不是为了唬人而是为了更好的理解和处理各种逻辑，让大家能更好的去用<font color=#ff0000>面向对象</font>的方式处理问题.<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 大家千万不要陷入过度设计，大可不必为了设计而设计一定要在代码中区分各个对象。一句话技术是为应用服务的。<br><br>欢迎指正。</p>
            <hr>
            <br>画了个图，感觉没有完全表达出自己的意思。。。。。谁帮忙完善下，最好能体现各个O在MVC中的位置<br><img height=480 alt=snap20070108.jpg src="http://www.blogjava.net/images/blogjava_net/vip01/snap20070108.jpg" width=557 border=0></div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/51685.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-11-19 15:52 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/11/19/51685.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JPA是什么 </title><link>http://www.cnitblog.com/wufajiaru/archive/2008/11/18/51651.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Tue, 18 Nov 2008 08:50:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/11/18/51651.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/51651.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/11/18/51651.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/51651.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/51651.html</trackback:ping><description><![CDATA[<div class=postTitle><a class=postTitle2 id=viewpost1_TitleUrl href="http://www.blogjava.net/wealupa/archive/2008/11/14/240548.html"><u><font color=#800080>JPA是什么</font></u></a> </div>
定义 Java Persistence API<br>JPA通过JDK 5.0注解或XML描述对象－关系表的映射关系，并将运行期的实体对象持久化到数据库中。
<h2>起源</h2>
Sun引入新的JPA ORM规范出于两个原因：其一，简化现有Java EE和Java SE应用的对象持久化的开发工作；其二，Sun希望整合对ORM技术，实现天下归一。<br>JPA由EJB 3.0软件专家组开发，作为JSR-220实现的一部分。但它不囿于EJB 3.0，你可以在Web应用、甚至桌面应用中使用。JPA的宗旨是为POJO提供持久化标准规范，由此可见，经过这几年的实践探索，能够脱离容器独立运 行，方便开发和测试的理念已经深入人心了。目前Hibernate 3.2、TopLink 10.1.3以及OpenJPA都提供了JPA的实现。<br>JPA的总体思想和现有Hibernate、TopLink，JDO等ORM框架大体一致。总的来说，JPA包括以下3方面的技术：<br><strong>ORM映射元数据</strong><br>JPA支持XML和JDK 5.0注解两种元数据的形式，元数据描述对象和表之间的映射关系，框架据此将实体对象持久化到数据库表中；<br><strong>JPA 的API</strong><br>用来操作实体对象，执行CRUD操作，框架在后台替我们完成所有的事情，开发者从繁琐的JDBC和SQL代码中解脱出来。<br><strong>查询语言</strong><br>这是持久化操作中很重要的一个方面，通过面向对象而非面向数据库的查询语言查询数据，避免程序的SQL语句紧密耦合。
<h2>JPA的优势</h2>
<strong>1 标准化</strong><br>JPA 是 JCP 组织发布的 Java EE 标准之一，因此任何声称符合 JPA 标准的框架都遵循同样的架构，提供相同的访问 API，这保证了基于JPA开发的企业应用能够经过少量的修改就能够在不同的JPA框架下运行。<br><strong>2 对容器级特性的支持</strong><br>JPA 框架中支持大数据集、事务、并发等容器级事务，这使得 JPA 超越了简单持久化框架的局限，在企业应用发挥更大的作用。<br><strong>3 简单易用，集成方便</strong><br>JPA的主要目标之一就是提供更加简单的编程模型：在JPA框架下创建实体和创建Java 类一样简单，没有任何的约束和限制，只需要使用 javax.persistence.Entity进行注释；JPA的框架和接口也都非常简单，没有太多特别的规则和设计模式的要求，开发者可以很容易的 掌握。JPA基于非侵入式原则设计，因此可以很容易的和其它框架或者容器集成。<br><strong>4 可媲美JDBC的查询能力</strong><br>JPA的查询语言是面向对象而非面向数据库的，它以面向对象的自然语法构造查询语句，可以看成 是Hibernate HQL的等价物。JPA定义了独特的JPQL（Java Persistence Query Language），JPQL是EJB QL的一种扩展，它是针对实体的一种查询语言，操作对象是实体，而不是关系数据库的表，而且能够支持批量更新和修改、JOIN、GROUP BY、HAVING 等通常只有 SQL 才能够提供的高级查询特性，甚至还能够支持子查询。<br><strong>5 支持面向对象的高级特性</strong><br>JPA 中能够支持面向对象的高级特性，如类之间的继承、多态和类之间的复杂关系，这样的支持能够让开发者最大限度的使用面向对象的模型设计企业应用，而不需要自行处理这些特性在关系数据库的持久化。
<h2>JPA的供应商</h2>
JPA 的目标之一是制定一个可以由很多供应商实现的API，并且开发人员可以编码来实现该API，而不是使用私有供应商特有的API。因此开发人员只需使用供应 商特有的API来获得JPA规范没有解决但应用程序中需要的功能。尽可能地使用JPA API，但是当需要供应商公开但是规范中没有提供的功能时，则使用供应商特有的API。<br><strong>1 Hibernate</strong><br>JPA是需要Provider来实现其功能的，Hibernate就是JPA Provider中很强的一个，目前来说应该无人能出其右。从功能上来说，JPA现在就是Hibernate功能的一个子集。Hibernate 从3.2开始，就开始兼容JPA。Hibernate3.2获得了Sun TCK的JPA(Java Persistence API) 兼容认证。<br>只要熟悉Hibernate或者其他ORM框架，在使用JPA时会发现其实非常容易上手。例如 实体对象的状态，在Hibernate有自由、持久、游离三种，JPA里有new，managed，detached，removed，明眼人一看就知 道，这些状态都是一一对应的。再如flush方法，都是对应的，而其他的再如说Query query = manager.createQuery(sql)，它在Hibernate里写法上是session，而在JPA中变成了manager，所以从 Hibernate到JPA的代价应该是非常小的<br>同样，JDO，也开始兼容JPA。在ORM的领域中，看来JPA已经是王道，规范就是规范。在各大厂商的支持下，JPA的使用开始变得广泛。<br><strong>2 Spring</strong><br>Spring + Hibernate 常常被称为 Java Web 应用人气最旺的框架组合。而在 JCP 通过的 Web Beans JSR ，却欲将JSF + EJB + JPA 、来自 JBoss Seam（Spring 除外）的一些组件和EJB 3（目前能够提供有基本拦截和依赖注入功能的简化 Session Bean 框架）的一个 Web 组合进行标准化。如今的 Spring 2.0 为 JPA 提供了完整的 EJB 容器契约，允许 JPA在任何环境内可以在 Spring 管理的服务层使用（包括 Spring 的所有 AOP 和 DI 增强）。同时，关于下一个Web应用组合会是 EJB、Spring + Hibernate 还是 Spring + JPA 的论战，早已充斥于耳。<br>在Spring 2.0.1中，正式提供对JPA的支持，这也促成了JPA的发展，要知道JPA的好处在于可以分离于容器运行，变得更加的简洁。<br><strong>3 OpenJPA</strong><br>OpenJPA 是 Apache 组织提供的开源项目，它实现了 EJB 3.0 中的 JPA 标准，为开发者提供功能强大、使用简单的持久化数据管理框架。OpenJPA 封装了和关系型数据库交互的操作，让开发者把注意力集中在编写业务逻辑上。OpenJPA 可以作为独立的持久层框架发挥作用，也可以轻松的与其它 Java EE 应用框架或者符合 EJB 3.0 标准的容器集成。<br><strong>4 其它</strong><br>目前支持的实现包括Toplink、Hibernate Entitymanager等。TopLink以前需要收费，如今开源了。OpenJPA虽然免费，但功能、性能、普及性等方面更加需要加大力度。<br>对于EJB来说，实体Bean一直是被批评的对象，由于其太复杂和庞大。JPA的出现，很大程度的分离了复杂性。这让EJB的推广也变得容易。<br>总而言之，JPA规范主要关注的仅是API的行为方面，而由各种实现完成大多数性能有关的调优。尽管如此，所有可靠的实现都应该拥有某种数据缓存，以作为选择。但愿不久的将来，JPA能成为真正的标准。<br><strong>小结</strong><br>EJB 3.0和JPA 毫无疑问将是Java EE 5的主要卖点。在某些领域中，它们给Java社区带来了竞争优势，并使Java 在其他领域与竞争对手不分伯仲（因为，不可否认，目前某些领域尚不存在基于标准的方法）。<br>过去数年来，Spring Framework一直是EJB在企业领域的主要竞争对手。EJB3.0规范解决了很多促进Spring兴起的问题。随着它的出现，EJB3.0毫无疑问比Spring提供了更好的开发体验——最引人注目的优势是它不需要配置文件。<br>JPA提供一种标准的OR映射解决方案，该解决方案完全集成到EJB3。0兼容的容器中。JPA的前辈将会继续稳定发展，但是业务应用程序中的 raw 使用将可能会减少。实现 JPA 兼容的实体管理器似乎很可能是此类技术的发展方向。<br>Java EE系列规范的较大问题与JPA没有任何关系。Java EE 系列规范的问题涉及到 Web和EJB容器之间的集成。Spring在此领域仍然具有主要竞争优势。JBoss的Seam项目尝试使用自定义的方法来解决这一问题。Caucho Resin应用服务器试图扩展容器边界并支持在Web容器中使用@EJB注释。我们希望Java EE 5.1将解决层集成的问题，为我们提供一个全面而标准的依赖性注入方法。<br>在不久的将来，Sun可能会将JPA作为一个单独的JSR对待，同时JPA还可能作为Java SE的一部分。不过这些都不太重要，重要的是，我们现在已经可以在脱离容器的情况下、在Java SE应用中使用JPA了。 <br>JPA已经作为一项对象持久化的标准，不但可以获得Java EE应用服务器的支持，还可以直接在Java SE中使用。开发者将无需在现有多种ORM框架中艰难地选择，按照Sun的预想，现有ORM框架头顶的光环将渐渐暗淡，不再具有以往的吸引力。 
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/51651.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-11-18 16:50 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/11/18/51651.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSTL(1.1)之Core tag Libray [转]</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/11/05/51119.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Wed, 05 Nov 2008 08:03:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/11/05/51119.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/51119.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/11/05/51119.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/51119.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/51119.html</trackback:ping><description><![CDATA[<div class="entry-body nerr" style="DISPLAY: block">
<p>JavaServer Pages Standard Tag Libray(1.1),其中文名字为JSP标准标签函数库。JSTL是一个标准的已<br>制定好的标签库，可以应用于各种领域，如:基本输入输出，流程控制，循环，XML文件剖析，数据库查<br>询以及国际化和文字格式标准化的应用等。JSTL所提供的标签库分为以下五大类:<br>&nbsp;核心标签库(Core tag Liabry)<br>&nbsp;I18N格式标签库(I18N-capable formatting tag libary)<br>&nbsp;SQL标签库(SQL tag Libary)<br>&nbsp;XML标签库(XML tag Libary)<br>&nbsp;函数标签库(Functions tag Libary)</p>
<p>核心标签库(Core tag Liabry)主要有:基本输入输出，流程控制，迭代操作和URL操作。<br>&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;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out<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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set<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; &nbsp;表达式操作&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; remove<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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch<br>&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp; Core&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;&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;&nbsp; if<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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; choose<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;&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;&nbsp;&nbsp; &nbsp;when<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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outherwise</p>
<p>&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; forEach<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;&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; forTokens </p>
<p>&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; import<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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;param<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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;url<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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; URL操作&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; param<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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; redirect<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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; param<br>------------------------------------------------------------------------------------------<br>在JSP中使用JSTL中的标签库时，必须使用&lt;<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#37;&#64;&#116;&#97;&#103;&#108;&#105;&#98;&#37;"><u><font color=#0000ff size=2>%@taglib%</font></u></a>&gt;指令，并且设定prefix和uri的值得，通常设定:<br>&lt;<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#37;&#64;&#116;&#97;&#103;&#108;&#105;&#98;"><u><font color=#0000ff size=2>%@taglib</font></u></a> prefix="c" uri="<a href='http://java.sun.com/jsp/jstl/core"%'><u><font color=#0000ff size=2>http://java.sun.com/jsp/jstl/core"%</font></u></a>&gt;<br>这样就可以使用核心标签库了。</p>
<p>.表达式操作<br>&nbsp;表达式操作分类中包含四个标签: &lt;c:out&gt;,&lt;c:set&gt;,&lt;c:remove&gt;和&lt;c:catch&gt;<br>&lt;c:out&gt;：重要用来显示数据的内容，类似与&lt;%=scripting-language%&gt;。它的语法如下:<br>语法1: 没有body内容<br>&lt;c:out value="value" [escapeXml="{true|false}"] [default="defaultValue"]/&gt;</p>
<p>语法2: 有body内容<br>&lt;c:out value="value"&nbsp; [escapeXml="{true|false}"]&gt;<br>&nbsp; default value<br>&lt;/c:out&gt;</p>
<p>Attribute<br>-----------------------------------------------------------------------------------------------------------------------<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;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EL&nbsp;&nbsp;&nbsp;&nbsp; 类型&nbsp;&nbsp;&nbsp;&nbsp; 必须&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 默认值<br>value&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object&nbsp;&nbsp;&nbsp; 是&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无<br>default&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果value值为null,则显示default的值&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无<br>escapeXml&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是否转换特殊字符，如: &lt;转换为&amp;It&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; true<br>----------------------------------------------------------------------------------------------------------------------<br>Null和错误说明<br>假若value为null,会显示default的值；假若没有设定default的值，则会显示一个空的字符串。</p>
<p>&lt;c:set&gt;:主要用来把变量存储至JSP范围或是JavaBean的属性中。<br>语法1: 没有body<br>将value的值存储至范围为scope的varName变量之中<br>&lt;c:set value="value" var="varName" [scope="{page|request|session|application}"]/&gt;</p>
<p>语法2: 有body<br>将body内容存储至范围为scope的varName变量之中<br>&lt;c:set value="value" [scope="{page|request|session|application}"]&gt;<br>&nbsp; body.....<br>&lt;/c:set&gt;</p>
<p>语法3: 将value的值存储至target对象属性中<br>&lt;c:set value="value" target="target" property="propertyNmae"/&gt;</p>
<p>语法4: 将body内容的数据存储至target对象属性中<br>&lt;c:set target="target" property="propertyNmae"&gt;<br>&nbsp;body....<br>&lt;/c:set&gt;</p>
<p>Attribute<br>----------------------------------------------------------------------------------------<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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EL&nbsp;&nbsp;&nbsp;&nbsp; 类型&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 必须&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;默认值<br>value&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无<br>var&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无<br>scope&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var变量的JSP范围&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; page<br>target&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;为一JavaBean或java.util.Map对象&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无<br>property&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;指定target对象属性&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;&nbsp;&nbsp;&nbsp;&nbsp;Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无<br>------------------------------------------------------------------------------------------<br>Null 和 错误处理:<br>语法3和语法4会产生异常错误,有以下两种情况:<br>&nbsp;.target 为null<br>&nbsp;.target 不是java.util.Map或JavaBean对象<br>假若value为null时:将由存储变量改为移除变量<br>&nbsp;.语法1: 由var和scope所定义的变量，将被移除<br>&nbsp;&nbsp;&nbsp; .若scope已指定时，则PageContext.removeAttribute(varName,scope);<br>&nbsp;&nbsp;&nbsp; .若scope未指定时，则PageContext.removeAttribute(varName);<br>&nbsp;.语法3: <br>&nbsp;&nbsp;&nbsp; .假若target为Map时，则Map.remove(property);<br>&nbsp;&nbsp;&nbsp; .假若target为JavaBean时，propertye指定的属性为null<br>注意: var和scope这两个属性不能使用表达式来表示，我们不能写成 scope="${ourScope}"或var="${a}"</p>
<p>&lt;c:remove&gt;:主要用来移除变量。<br>语法:<br>&lt;c:remove var="varName" [scope="{page|request|session|application}"]/&gt;</p>
<p>Attribute<br>----------------------------------------------------------------------------------------<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;&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;&nbsp;&nbsp;&nbsp; EL&nbsp;&nbsp;&nbsp;&nbsp; 类型&nbsp;&nbsp;&nbsp;&nbsp; 必须&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 默认值<br>&nbsp;var&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; N&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String&nbsp;&nbsp;&nbsp;&nbsp; 是&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 无<br>&nbsp;scope&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var变量的JSP范围&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; page<br>----------------------------------------------------------------------------------------<br>说明:<br>&lt;c:remove&gt;必须要有var属性，即要被移除的属性名称，scope则可有可无，如:<br>&lt;c:remove var="username" scope="session"/&gt;<br>将username变量从session范围移除。若我们不设定scope，则&lt;c:remove&gt;会移除所有范围名称为username<br>的数据。</p>
<p>&lt;c:catch&gt;:主要用来处理产生错误的异常情况，并且将信息保存起来。<br>语法:<br>&lt;c:catch [var="varName"]&gt;<br>&nbsp;...欲抓取错误的部分...<br>&lt;/c:catch&gt;</p>
<p>Attribute<br>----------------------------------------------------------------------------------------<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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EL&nbsp;&nbsp;&nbsp;&nbsp; 类型&nbsp;&nbsp;&nbsp;&nbsp; 必须&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 默认值<br>&nbsp;var&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; N&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无<br>-----------------------------------------------------------------------------------------<br>说明:<br>&lt;c:catch&gt;主要将可能发生错误的部分放在&lt;c:catch&gt;和&lt;/c:catch&gt;之间。如果真的发生错误，可将错误<br>信息保存至变量varName标量中，如:<br>&lt;c:catch var="message"&gt;<br>&nbsp;&nbsp;&nbsp; //可能发生错误的部分<br>&lt;/catch&gt;<br>另外，当错误发生&lt;c:catch&gt;和&lt;/c:catch&gt;之间时，只有&lt;c:catch&gt;和&lt;/c:catch&gt;之间的程序会被中止忽<br>略，但整个网页不会被中止。</p>
<p>流程控制<br>流程控制分类中包含四个标签:&lt;c:if&gt;,&lt;c:choose&gt;,&lt;c:when&gt;和&lt;c:otherwise&gt;。</p>
<p>&lt;c:if&gt;:的用途和我们在一般程序中写的if一样。<br>语法:<br>语法1：没有body<br>&lt;c:if test="testCondition" var="varName" [scope="{page|request|session|application}"]/&gt;</p>
<p>语法2: 有body<br>&lt;c:if test="testCondition" [var="varName"] [scope="{page|request|session|appliation}"]&gt;<br>&nbsp; ...body....<br>&lt;/c:if&gt;</p>
<p>Attribute<br>------------------------------------------------------------------------------------------------------------------------<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;&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;&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;&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; EL&nbsp;&nbsp;&nbsp;&nbsp; 类型&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;必须&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 默认值<br>test&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果表达式的结果为true则执行body,false则相反&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;是&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;无<br>var&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;用来存储test运算后的结果，即true或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; &nbsp;N&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 无<br>scope&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var变量的JSP范围&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; N&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; page<br>------------------------------------------------------------------------------------------------------------------------<br>说明:<br>&lt;c:if&gt;标签必须要有test属性，body里除了能是静态文本之外可以是任何JSP代码，标签或HTML代码。</p>
<p>&lt;c:choose&gt;:本身只当作&lt;c:when&gt;和&lt;c:otherwise&gt;的父标签。<br>语法:<br>&lt;c:choose&gt;<br>&nbsp; body(&lt;when&gt;和&lt;otherwise&gt;)<br>&lt;/c:choose&gt;<br>限制:<br>&lt;c:choose&gt;的本地内容只能有:<br>&nbsp;.空白<br>&nbsp;.1或多个&lt;c:when&gt;<br>&nbsp;.0或多个&lt;c:otherwise&gt;<br>如:<br>&lt;c:choose&gt;</p>
<p>&nbsp;&lt;c:when test="${condition1}"&gt;<br>&nbsp;&nbsp; condition1 为 true<br>&nbsp;&lt;/c:when&gt;</p>
<p>&nbsp;&lt;c:when test="${condition2}"&gt;<br>&nbsp;&nbsp; condition2 为 true<br>&nbsp;&lt;/c:when&gt;</p>
<p>&nbsp;&lt;c:otherwise&gt;<br>&nbsp;&nbsp; condition1和conditon2都为false<br>&nbsp;&lt;/&lt;c:otherwise &gt;<br>&nbsp;<br>&lt;/c:choose&gt;<br>说明:<br>在同一个&lt;c:choose&gt;中，假如所有的&lt;c:when&gt;的test都不为true时，则执行&lt;c:otherwise&gt;的本体内容。<br>在同一个&lt;c:choose&gt;中，假若有好几个&lt;c:when&gt;都会true时，只能有一个&lt;c:when&gt;成立。</p>
<p>迭代操作<br>迭代(Iterator)操作主要包含两个标签: &lt;c:forEach&gt;和&lt;c:forTokens&gt;。</p>
<p>&lt;c:forEach&gt;为循环控制，它可以将集合(Collection)中的成员循序浏览一遍。运做方式为当条件符合<br>时，就会持续重复执行&lt;c:forEach&gt;的body内容。<br>语法:<br>语法1: 迭代一集合对象之所有成员<br>&lt;c:forEach [var="varName"] items="collection" [varStatus="varStatusName"]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [begin="begin"] [end="end"] [step="step"]&gt;<br>&nbsp;...body内容.....<br>&lt;c:forEach&gt;</p>
<p>语法2: 迭代指定的次数<br>&lt;c:forEach [var="varName"] [varStatus="varStatusName"]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; begin="begin" end="end" [step="step"]&gt;<br>&nbsp;...body内容.....<br>&lt;c:forEach&gt;</p>
<p>Attribute<br>--------------------------------------------------------------------------------------------------------------------------<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;&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;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EL&nbsp;&nbsp;&nbsp;&nbsp; 类型&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp; 必须&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 默认值<br>&nbsp;var&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; N&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;无</p>
<p>&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;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Arrays<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;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Collection<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;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;无<br>items&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;Enumeration&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;&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;&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;&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; Map<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;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String</p>
<p>varStatus&nbsp;&nbsp;&nbsp;&nbsp; 用来存放到指到的相关成员信息&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无<br>begin&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;&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; &nbsp; Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;int&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;&nbsp; &nbsp;0<br>end&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;&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;&nbsp;&nbsp;&nbsp;&nbsp; Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;int&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;&nbsp; &nbsp;最后一个成员<br>setp&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;int&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;&nbsp; &nbsp;1<br>-------------------------------------------------------------------------------------------------------------------------<br>Null 和 错误处理<br>.假若items为null时，则表示为一空的集合对象<br>.假若begin大于或等于items时，则迭代不运算<br>注意:<br>varName的范围只存在&lt;c:forEach&gt;的本体中，如果超出了本题，则不能取得varName的值。如:<br>&lt;c:forEach items="${atts}" var="item"&gt;<br>&lt;/c:forEach&gt;<br>${item}&lt;/br&gt;<br>${item}则不会显示item的内容。&lt;c:forEach&gt;除了支持数组之外，还有标准的J2SE的结合类型，例如:<br>ArrayList,List,LinkedList,Vector,Stack和Set等等；另外包括java.util.Map类的对象，例如:<br>HashMap,Hashtable,Properties,Provider和Attributes。</p>
<p>另外&lt;c:forEach&gt;还提供了varStatus属性，主要用来存放现在指到成员的相关信息。例如：我们写成<br>varStatus="s",那么就会把信息存放到名称为s的属性当中。varStatus属性还提供另外四个属性:index,<br>count,fist和last，它们个自的意义如下:<br>------------------------------------------------------------------------------------------<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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 意义<br>&nbsp;&nbsp; index&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 现在指到成员的索引<br>&nbsp;&nbsp; count&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 总共指到成员的总和<br>&nbsp;&nbsp; first&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; boolean&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 现在指到成员是否为第一个<br>&nbsp;&nbsp; last&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;boolean&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 现在指到成员是否为最后一个<br>-------------------------------------------------------------------------------------------<br>如下例子:<br>&lt;<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#37;&#64;&#112;&#97;&#103;&#101;"><u><font color=#0000ff size=2>%@page</font></u></a> contentType="text/html;charset=gb2312"%&gt;<br>&lt;<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#37;&#64;&#116;&#97;&#103;&#108;&#105;&#98;"><u><font color=#0000ff size=2>%@taglib</font></u></a> prefix="c" uri="<a href='http://java.sun.com/jsp/jstl/core"%'><u><font color=#0000ff size=2>http://java.sun.com/jsp/jstl/core"%</font></u></a>&gt;<br>&lt;%<br>&nbsp;String atts[] = new String[5];<br>&nbsp;atts[0]="hello";<br>&nbsp;atts[1]="this";<br>&nbsp;atts[2]="is";<br>&nbsp;atts[3]="a";<br>&nbsp;atts[4]="girl";<br>&nbsp;request.setAttritue("atts",atts);<br>%&gt;<br>&lt;c:forEach items="${atts}" var="item" varStatus="s"&gt;<br>&lt;h2&gt;&lt;c:out value="${item}"/&gt;的四种属性&gt;&lt;/h2&gt;<br>&nbsp;index: ${s.index}&lt;/br&gt;<br>&nbsp;count: ${s.count}&lt;/br&gt;<br>&nbsp;first: ${s.first}&lt;/br&gt;<br>&nbsp;last:&nbsp; ${s.last}&lt;/br&gt; <br>&lt;/c:forEach&gt;</p>
<p>&lt;c:forTokens&gt;<br>&lt;c:forTokens&gt;:用来浏览一字符串中所有的成员，起成员是由定义符号(delimiters)所分隔的。<br>语法:<br>&lt;c:forTokens items="stringFoTokens" delims="delimmmmiters" [var="varName"]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [varStatus="varStatusName"] [begin="begin"] [end="end"] [step="step"]&gt;<br>&nbsp;...body内容....<br>&lt;/c:forTokens&gt;</p>
<p>Attribute<br>--------------------------------------------------------------------------------------------------------------------<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;&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;&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;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;EL&nbsp;&nbsp;&nbsp;&nbsp; 类型&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 必须&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 默认值<br>&nbsp;var&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无<br>&nbsp;items&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无<br>&nbsp;delims&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; N&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;是&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无<br>&nbsp;varStatus&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;用来存放现在指到的相关成员信息&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; N&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无<br>&nbsp;begin&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;0<br>&nbsp;end&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最后一个成员<br>&nbsp;step&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; Y&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1<br>---------------------------------------------------------------------------------------------------------------------<br>限制:<br>.假若有begin属性时，begin必须大于等于0<br>.假若有end属性时，必须大于begin<br>.假若有step属性时，step必须大于等于1</p>
<p>Null 和 错误处理<br>.假如itmes为null时,则表示为有空的集合对象<br>.假若begin大于等于items的大小时，则迭代不运算</p>
<p>例子:<br>&lt;c:forToken items="A,B,C,D,E,F,G" delims="," var="item&gt;<br>${item}<br>&lt;/c:forToken&gt;<br>items属性也可以用EL，例如:<br>&lt;%<br>&nbsp;String phonenumber="123-456-7899";<br>&nbsp;request.setAttribute("userPhone",phonenumber);<br>%&gt;<br>&lt;c:forTokens items="${userPhone}" delims="-" var="item"&gt;<br>${item}<br>&lt;/c:forTokens&gt;</p>
<p>URL操作<br>JSTL包含三个URL操作有关的标签,分别是: &lt;c:import&gt;,&lt;c:redirect&gt;和&lt;c:url&gt;。它们的主要功能是：<br>用来将其他文件的内容包含起来，网页的向导，还有url的产生。</p>
</div>
<p id=trackback>你可以通过这个链接引用该篇文章:http://shijian0916nunu.bokee.com/viewdiary.12079441.html </p>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/51119.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-11-05 16:03 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/11/05/51119.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP标签库介绍</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/09/27/49585.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Sat, 27 Sep 2008 07:52:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/09/27/49585.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/49585.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/09/27/49585.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/49585.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/49585.html</trackback:ping><description><![CDATA[什么是标签库？<br><br>JSP标签库（也被称作定制标签）是一种通过JavaBean生成基于XML的脚本的方法&nbsp;&nbsp;&nbsp;<br>。从概念上将，标签就是很简单而且可重用的代码结构。比方说，在我们最新发布的JSPKit（在JSP&nbsp;Insider内）中，我们就使用XML标签实现了对XML文档的轻松访问。请看以下的清单A。<br><br>清单A：执行XML/XSL&nbsp;转换的示例标签及其所在的HTML页面\r<br><br>&lt;%@&nbsp;taglib&nbsp;uri="http://www.jspinsider.com/jspkit/JAXP"&nbsp;prefix="JAXP"%&gt;<br>&nbsp;&nbsp;&lt;JAXP:TransformerTag&gt;<br>&nbsp;&nbsp;&lt;JAXP:XMLFile&gt;c:/xml/example.xml&lt;/JAXP:XMLFile&gt;<br>&nbsp;&nbsp;&lt;JAXP:XSLFile&gt;c:/xml/example.xsl&lt;/JAXP:XSLFile&gt;<br>&lt;/JAXP:TransformerTag&gt;&nbsp;&nbsp;<br><br>以上的示例使用了简单的标签来访问处在幕后的更强大代码。在以上的事例中首先装载了一个XML文件，然后应用了一个XSL文件来创建一个将被发送到客户端的结果——这一切不过仅仅只是用了一个很简单的标签。<br><br>定制标签使得JSP项目中很容易创建重用的开放源代码模块。而你的全部需要不过就是标签库及其文档。标签库的重要特性如下所示：<br><br>易于安装在多个项目上<br>标签很容易从一个JSP项目迁移到其他项目。一旦建立了一个标签库，你只需要把这个个标签库包装成一个JAR文件就可以在其他JSP项目中重新使用了。不能重用的是你作为程序员在建立标签时所加进标签的内容。因为标签可以重新使用，所以标签库可以轻松地用于你自己的项目。目前，最好的标签资源可以在JSPTags.com这个站点找到。.&nbsp;<br>扩展JSP<br>标签库可以具备JSP规范(JSP&nbsp;1.2)中的任何特性和功能。这也意味着你拥有了无限的能力可以扩展和增加JSP的强大功能却无需等待新版本JSP的发布。所以说，你完全可以取消页面上的JSP&nbsp;include调用了——只需用include标签建立自己的规范就可以了。&nbsp;<br>易于维护<br>标签库使得JSP&nbsp;Web应用程序变得很容易维护。主要有以下几个原因：&nbsp;<br><br><br>标签对任何人而言都很容易使用、易于理解。&nbsp;<br>你的所有逻辑都驻留在处于中心的标签处理器和JavaBean内。这样一来，如果你不得不更新你的代码，你只需要处理这些中心文件而无需修正使用这些代码的其他页面。&nbsp;<br>如果你需要增加新的功能，你不必改变任何已经存在的页面。你可以把额外的属性包含到你的标签内从而引进新的行为同时保留以前的属性，实现旧页面的正常运行。<br><br>比方说，你可能有如下的一个标签，它让你的文本都显示蓝色：<br><br>&lt;BlueText&gt;My&nbsp;Text&lt;/BlueText&gt;&nbsp;<br><br>但是随着项目的进行，你又想让蓝色变暗。于是你保留自己的标签但是为其增加了一个新的属性：shade&nbsp;<br><br>&lt;BlueText&nbsp;shade="teal"&gt;My&nbsp;Text&lt;/BlueText&gt;&nbsp;<br><br>所有的老标签继续显示蓝色，但现在你可以使用同一标签来产生变暗的蓝色文本了。<br><br><br>标签提升了代码的重用性。那些经过多次测试和使用的代码肯定具有更少的bug。所以，使用定制标签的JSP页面也同样具有更少的缺陷，维护起来自然方便多了。&nbsp;<br>更快的开发速度<br>标签库是一种重用代码的好办法。我们知道，服务器端语言标准的重用代码方式是使用模版。标签库和模版库这种方式相比则好得多。采用模版库，你就需要针对每个项目修改模版或者建立生硬的接口。标签库则没有这些限制，而其所具有的面向对象特性则让标签库不仅用法灵活而且扩展能力极为强大。还有，因为你重用代码，结果在项目开发上花费的时间就大大降低了，而更多的时间则可以用来设计自己的Web应用程序。标签库的简单接口使得这些代码用法简单、易于调试。&nbsp;<br>虽然标签库用起来特别简单，但是，建立其内部支持层次可比建立简单的JavaBean复杂多了。这种复杂性的主要原因在于标签库包含了好几个部分。而你所需要掌握的技能不过是理解、熟悉Java和JSP。<br><br><br>定制标签内幕<br>一个简单的定制标签包括了以下几个要素：<br><br><br>1、JavaBean：为了充分利用Java的面向对象特性，重用代码应当放置在独立的代码容器内&nbsp;&nbsp;&nbsp;<br>。这些JavaBean可不是标签库的一部分。他们是标签库用来执行所分配任务的基础代码模块。&nbsp;<br><br>2、标签处理器：这是标签库的真正核心。标签处理器（tag&nbsp;handler）引用它所需要的任何外部材料（JavaBean）并且负责访问JSP页面的信息（PageContext对象）。而JSP页面则把页面上设置的标签属性都传递给标签处理器，JSP页面上的标签标示的内容也是这样处理的。当标签处理器完成其处理过程，它就会把处理后的输出结果回送给JSP页面做进一步处理。&nbsp;<br><br>3、标签库描述符（TLD文件）：这是一种很简单的XML文件，TLD文件描述和说明了属性、信息和标签处理器文件位置等信息。JSP&nbsp;容器使用这一文件来映射被调用标签库的位置和用法。&nbsp;<br><br>4、Web站点的web.xml文件：其实这就是你的Web站点上的初始化文件。在这个文件内你可以定义Web应用程序中使用的定制标签，还可以定义用来描述每个定制标签的TLD文件。&nbsp;<br><br>5、发布文件（WAR或JAR文件）：如果你打算重用定制标签，那么你肯定需要想个简便的办法把标签从一个项目迁移到其他项目中去。把标签库打包成一个JAR文件就是这种既方便又高效的标签库发布方式。我们在以上的事例中没有建立JAR文件，但是如果你打算更进一步地了解JAR文件的细节，你不妨阅读&#8220;JSP&nbsp;WAR文件简介&#8221;。&nbsp;<br><br>6、JSP页面上的标签库声明：仅需使用标签库标示符即可方便地声明页面上存在的标签。标签库在页面上声明之后，你就可以随意使用它们了。&nbsp;<br><br>看起来会让你忙乎一阵子，实际上没那么糟糕。刚开始用的时候当然会有点棘手。其实真正关键的并不是编码而是把以上各个部分正确地组织起来。这种层次性的结构是很重要的，也正是如此才可以说标签库及灵活又易于使用。更重要的事，这些层次可以让整个建立标签库的过程都能通过JSP&nbsp;IDE自动完成。今后的JSP&nbsp;IDE更可以自动完成创建定制标签的大部分工作，而你自己则只需要负责建立代码和标签处理器。<br><br>（注意：一个标签处理器只定义一个定制标签；而一个标签库则是很多个标签处理器的集合，它们执行同一任务。）<br><br>建立你的第一个标签<br>以下的进阶指南将介绍如何把JSP扩展为具有自己的HTML编码功能&nbsp;&nbsp;&nbsp;<br>。这种编码方法用&lt;和&nbsp;&gt;符号代替HTML代码，而且很容易经过扩展以执行其他编码操作。整个示例虽然简单，但它确实向你说明了定制标签的最基础要素。<br><br>创建JavaBean<br>代码中的任何可重用部分都应该包含在JavaBean内。这一点是很重要的。这样你就可以在其他项目中重用这些代码了。由于任何放置在标签处理器内的代码都不会在标签以外被重用，所以代码的重用部分要与之分离。在我们的示例中，HTML编码逻辑很一般，所以我们直接把他们放在了JavaBean内，请参看清单B。<br><br>创建标签处理器\r<br>标签处理器使用了清单C的代码。<br><br>这些代码很简单，其中包括：<br><br>读取包含在打开和关闭标签内的文本。&nbsp;<br>调用HTML编码函数。&nbsp;<br>将结果返回给JSP页面。&nbsp;<br>创建标签描述符\r<br>我们需要描述自己的标签以便系统知道他们到底具有什么含义。TLD文件通常就以标签处理器命名并被存放在"/WEB-INF/"目录之下。该文件的文件扩展名是.tld。请参看清单D。<br><br>更新Web&nbsp;XML文件<br>现在你就可以告诉JSP容器使用标签库了。为此你需要修改web.xml文件：增加一个taglib项以注册标签库并为标签分配一个URI。URI是Web站点上唯一应用于这一特定标签的索引。由于标签今后还可能用在不同的Web站点上，所以你最好采用完整的URL和/或者包名字（package&nbsp;name）来保证这一唯一性。示例代码请参看清单E。<br><br>使用新标签<br>定制标签现在就可以用在你的JSP页面上了&nbsp;&nbsp;&nbsp;<br>。你只需要在页面上使用taglib指示符声明所要采用的标签即可。标签通过其唯一的URI被索引，然后被分配给一个前缀（prefix）。这一前缀并没有什么特别的意义，只要它不和指示符内的其他名称不冲突就可以了。请参看以下的清单F和G。<br><br>清单F：在JSP页面上使用HTML编码标签<br><br>&lt;%@&nbsp;taglib&nbsp;uri="HTMLEncode"&nbsp;prefix="Examples"&nbsp;%&gt;<br>&lt;html&gt;<br>&lt;head&gt;&lt;/head&gt;<br>&lt;body&gt;<br>&nbsp;&lt;pre&gt;<br>&nbsp;&lt;Examples:HTMLEncode&gt;<br>&nbsp;&nbsp;&lt;&nbsp;Hello&nbsp;,&nbsp;Simple&nbsp;sample&nbsp;&gt;<br>&nbsp;&lt;/Examples:HTMLEncode&gt;<br>&nbsp;&lt;/pre&gt;<br>&nbsp;&lt;/body&gt;<br>&lt;/html&gt;<br>&nbsp;<br><br>清单G：代码示例输出\r<br><br>&lt;&nbsp;Hello&nbsp;,&nbsp;Simple&nbsp;sample&nbsp;&gt;<br>which&nbsp;displays&nbsp;as:<br>&lt;&nbsp;Hello&nbsp;,&nbsp;Simple&nbsp;sample&nbsp;&gt;<br>&nbsp;<br><br>实际上，我就用这个标签对页面上的所有代码示例进行了编码。你可以注意到定制标签是在服务器上进行处理的。这就是说，你不会在输出页面上看到定制标签。<br><br>正如你所看到的那样，建立标签并非难事。最麻烦的是学习标签处理器的整个细节。我们不过是触及了皮毛。由于这一过程需要采取的步骤很多，所以刚入门的JSP程序员可能在建立标签的时候会觉得很困惑。<br><br>小结\r<br>标签库是JSP尚未得到广泛应用的重要特性之一&nbsp;&nbsp;&nbsp;<br>。它所提供的自己定制新标签等功能和以往的Web设计方式还是很不同的，适应起来自然有一段时间。不过，越来越多的开发人员已经在逐渐使用标签库完成自己的Web设计任务。到2001年末，估计标签库就会成为许多JSP项目中最常见的特性之一。<br><br>标签库的优点非本文所能全面阐述。标签库还具有其他很多优点。标签库促使JSP开发进入了前所未有的新天地。对JSP开发人员来说这确实是一种很令人振奋的新技术，从此我们就获得了建立任何类型Web应用程序的自由。标签库让JSP变成了最丰富、最具动态开发能力的Web编程环境。<br><br>&nbsp;<br><br>作者简介：<br><br>Casey&nbsp;Kochmer&nbsp;是Amberjack&nbsp;Software公司的总裁，该公司是JSP&nbsp;Insider的母公司。作为一位高级web应用程序设计师，Casey利用自己12年专业编程经验为JSP&nbsp;Kit做出了重要贡献。他还是JSP&nbsp;Buzz和其他许多站点文章的作者。闲暇之时，Casey喜欢徒步漫游华盛顿州的奥林匹克山。<img height=1 src="http://www.pcbookcn.com/down_info.asp?id=1952" width=1 border=0><br>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/49585.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-09-27 15:52 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/09/27/49585.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jsp标签的使用[转]</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/09/27/49584.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Sat, 27 Sep 2008 07:45:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/09/27/49584.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/49584.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/09/27/49584.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/49584.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/49584.html</trackback:ping><description><![CDATA[1. JSP标签库<br>JSP标签库（也称自定义库）可看成是一套产生基于XML脚本的方法，它经由JavaBeans来支持。在概念上说，标签库是非常简单和可以重用的代码构造。<br><br>2. JSP2.0标签使用方法 <br>JSP2.0中标签的使用由多个部分组成： <br><br>（1） WEB_INF/web.xml中添加标签引用 <br><br>（2） 标签的实现，可能是class也可能是web templet <br><br>（3） 在jsp文件中添加引用 <br><br>在实际使用中，分析jsp2.0标签可以先从jsp文件入手，然后再分析web.xml及相应的标签库文件。 <br><br>2.2 基本标签的使用方法 <br>2.2.1 jsp文件中的标签引用及使用方法 <br>以下是一个简单的jsp文件： <br><br>&lt;%@ taglib prefix="mytag" uri="/WEB-INF/jsp2/jsp2-example-taglib.tld" %&gt; <br><br>&lt;html&gt; &lt;body&gt; &lt;mytag:helloWorld/&gt; &lt;/body&gt;&lt;/html&gt; <br><br>说明： <br><br>（1） 首先以&lt;%@ taglib prefix="mytag" uri="&#8230;" %&gt;说明标签前缀及该前缀引用的标签所在路径，在这个例子中uri值是一个相对路径（本地路径），即当前项目根目录下WEB-INF/ jsp2/ jsp2-example-taglib.tld。如果使用的是本地路径就不需要在web.xml中配置路径映射了； <br><br>（2） 指定了标签前缀后，在jsp页面的body内就可以使用这个前缀来引用标签库中的指定标签了，如&lt;mytag:helloWorld/&gt;，就是引用mytag所指定的标签库中的helloWorld标签。 <br><br>2.2.2 web.xml中的配置 <br>如果在上述例子中使用的不是本地路径，那么就需要在web.xml中配置路径转换，如使用：&lt;%@ taglib prefix="mytag" uri=" http://mytaglib/myTestTags1 " %&gt;来引用标签库，那么就需要在web.xml文件的jsp-config节点中添加如下配置： <br><br>&lt;taglib&gt; <br><br>&lt;taglib-uri&gt;http://mytaglib/myTestTags1&lt;/taglib-uri&gt; <br><br>&lt;taglib-location&gt;/WEB-INF/jsp2/jsp2-example-taglib.tld &lt;/taglib-location&gt; <br><br>&lt;/taglib&gt; <br><br>JSP解释器会将http://mytaglib/myTestTags1根据web.xml中的配置转化为本地路径。当然&lt;taglib- uri&gt;中文本可以是任何值，但不能和其它的配置冲突，所以在规划时最好加上前缀，如：http://mytaglib等。 <br><br>2.2.3 标签库中的配置 <br>在标签库中的配置实际上就是配置对实现类的引用，JSP解释器会根据jsp文件中对标签的引用，在标签库中找到相应的标签，然后再根据标签中的定 义调用具体的实现类，本例中在jsp文件中对标签的引用：&lt;mytag:helloWorld/&gt;，即引用了helloWorld这个标签， 这个标签在标签库中的定义如下： <br><br>&lt;tag&gt; <br>&lt;description&gt;Outputs Hello, World&lt;/description&gt; <br>&lt;name&gt;helloWorld&lt;/name&gt; <br>&lt;tag-class&gt;jsp2.examples.simpletag.HelloWorldSimpleTag&lt;/tag-class&gt; <br>&lt;body-content&gt;empty&lt;/body-content&gt; <br>&lt;/tag&gt; <br>该标签由四个部分组成： <br><br>（1） description：描述该标签的作用 <br><br>（2） name：标签的名字，该名字在jsp文件使用，相当由类名； <br><br>（3） tag-class：标签的实现索引，相当于类的实现；本例索引指定 jsp2.examples.simpletag.HelloWorldSimpleTag，是一个java的类文件，应放在 WEB_INF/classes/jsp2/examples/simpletag目录下的HelloWorldSimpleTag.class文件； <br><br>（4） body-content：在jsp文件中使用标签时，标签中的内容类别，本例的值是empty，表示helloWorld这个标签中没有内容。如果在 jsp页面中在该标签中加入了内容，如&lt;mytag:helloWorld&gt;hell&lt;/mytag:helloWorld&gt;， 页面会报错，当然&lt;mytag:helloWorld&gt;&lt;/mytag:helloWorld&gt;是不会错的（注意不能有空格 式）。 <br><br>2.2.4 类的实现 <br>类HelloWorldSimpleTag实现如下： <br><br>package jsp2.examples.simpletag; <br><br>import javax.servlet.jsp.JspException; <br>import javax.servlet.jsp.tagext.SimpleTagSupport; <br>import java.io.IOException; <br><br>public class HelloWorldSimpleTag extends SimpleTagSupport { <br>public void doTag() throws JspException, IOException { <br>getJspContext().getOut().write( "Hello, world!" ); <br>}} <br>说明： <br><br>（1） jsp标签调用的类一般继承于SimpleTagSupport <br><br>（2） SimpleTagSupport中实现了getJspContext()这个方法，这个方法可以获取指向jsp页面的输出流。 <br><br>（3） getJspContext().getOut().write( "Hello, world!" )：输出Hellow,World! <br><br>2.3含有变量的tag配置 <br>2.3.1 jsp文件中的标签引用及使用方法 <br>以下是引用了带有变量标签的jsp页面： <br><br>&lt;%@ taglib prefix="mytag" uri="/WEB-INF/jsp2/my_taglib.tld" %&gt; <br>&lt;html&gt;&lt;body&gt; <br>&lt;mytag:repeat num1="15"&gt; <br>Invocation ${count} of 5&lt;br&gt; <br>&lt;/mytag:repeat&gt; <br>&lt;/body&gt; <br>&lt;/html&gt; <br>说明： <br><br>（1） &lt;mytag:repeat num="15"&gt;，输入参数的传入方法：即在标签中将要传入的参数做为标签的一个属性，并指定其属性值，本例中传入参数num1，它的值为15； <br><br>（2） ${count}，在页面中显示输出参数的值，count是输出参数的名字 <br><br>2.3.2 标签库中的配置 <br>标签库中的相应配置如下： <br><br>&lt;tag&gt; <br>&lt;description&gt;Repeats the body of the tag 'num' times&lt;/description&gt; <br>&lt;name&gt;repeat&lt;/name&gt; <br>&lt;tag-class&gt;jsp2.examples.simpletag.RepeatSimpleTag&lt;/tag-class&gt; <br>&lt;body-content&gt;scriptless&lt;/body-content&gt;--标签内容是脚本 <br>&lt;variable&gt; <br>&lt;description&gt;Current invocation count (1 to num)&lt;/description&gt; <br>&lt;name-given&gt;count&lt;/name-given&gt; --输出参数说明 <br>&lt;/variable&gt; <br>&lt;attribute&gt; <br>&lt;name&gt;num&lt;/name&gt; --输入参数说明 <br>&lt;required&gt;true&lt;/required&gt; <br>&lt;rtexprvalue&gt;true&lt;/rtexprvalue&gt; <br>&lt;/attribute&gt; <br>&lt;/tag&gt; <br>该标签由六个部分组成： <br><br>（1） description：见上文 <br><br>（2） name：见上文 <br><br>（3） tag-class：见上文 <br><br>（4） body-content：这个例子的值是scriptless，表示标签中的内容是脚本 <br><br>（5） variable：输出参数，在jsp中使用${count}来引用这个输出变量的值，输出参数名并不是强制性的，这里只是一个约定，即要求repeat实现类最后有count这个输出参数，以便在jsp页中方便引用，如果没有也不会报错； <br><br>（6） attribute：输入参数，在jsp中使用&lt; mytag:repeat num="5"&gt;来设置这个输入参数num，这个参数名是强制性的，即要在repeat实现类中有setNum这个方法，如果没有相应的方法jsp页面会报错； <br><br>2.3.3 类的实现 <br>package jsp2.examples.simpletag; <br><br>import javax.servlet.jsp.JspException; <br>import javax.servlet.jsp.tagext.SimpleTagSupport; <br>import java.util.HashMap; <br>import java.io.IOException; <br><br>public class RepeatSimpleTag1 extends SimpleTagSupport { <br>private int num; <br><br>public void doTag() throws JspException, IOException { <br>for (int i=0; i&lt;num; i++) { <br>getJspContext().setAttribute("count", String.valueOf( i + 1 ) ); <br>getJspBody().invoke(null); <br>} } <br><br>public void setNum(int num) { <br>this.num = num; }} <br>说明： <br><br>（1） getJspContext().setAttribute定义了输出到jsp页面的输出参数count，这里的count是一个字符串，它的值可以不与 标签库中variable定义相同，如，它可以是len，当然在jsp引用时应以这里为准，即使用${len}引用； <br><br>（2） setNum(int num)方法：接收输入参数，这个方法命名规则为set+输入参数名，该方法带一个参数，用于接收输入参数的值。 <br><br>2.4 函数标签的定义方法 <br>2.4.1 jsp文件中函数标签引用及使用方法 <br>&lt;%@ taglib prefix="my" uri="/WEB-INF/jsp2/jsp2-example-taglib.tld" %&gt; <br>&lt;html&gt; <br>&lt;body&gt;&lt;span&gt;${my:caps(&#8220;HELLO WORLD&#8221;)}&lt;/span&gt;&lt;/body&gt; <br><br>&lt;/html&gt; <br><br>说明： <br><br>（1） 函数标签的引用比其它标签的引用都要简单，它的引用与高级语言中的函数调用方法类似，直接在函数名后的括号后面输入相应的参数值即可，不需要另加用标签的其它属性来说明输入参数。 <br><br>2.4.2 函数标签在标签库中配置 <br>&lt;function&gt; <br>&lt;description&gt;Converts the string to all caps&lt;/description&gt; <br>&lt;name&gt;caps&lt;/name&gt; <br>&lt;function-class&gt;jsp2.examples.el.Functions&lt;/function-class&gt; <br>&lt;function-signature&gt;java.lang.String caps( java.lang.String )&lt;/function-signature&gt; <br>&lt;/function&gt; <br>说明如下： <br><br>（1） 这种方法的定义包含在function元素中； <br><br>（2） name：函数名 <br><br>（3） function-class：该函数真正的实现class，本例中，caps函数是由WEB_INF/classes/ jsp2/examples/el路径中的Functions类来实现的； <br><br>（4） function-signature：说明函数的输入及输出参数类型，不用指明参数名。 <br><br>2.4.3 类的实现 <br>package jsp2.examples.el; <br>import java.util.*; <br><br>public class Functions { <br>public static String caps( String text ) { <br>return text.toUpperCase(); <br>}} <br>说明： <br><br>（1） 函数标签实现类就是普通的类，它不需要从某个父类继承； <br><br>（2） 函数标签实现类中必须有相应的方法与标签库中相应的函数字义相同（包括函数名，输入参数个数及输入参数类型，函数的返回值）； <br><br>2.5 标签模板 <br>标签模板的特点： <br><br>（1） 没有tld文件在jsp中通过&lt;%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %&gt;引用，即使用tagdir代替了uri，这里的tags是一个文件夹，不是文件，在该文件夹中包含了所需的标签模板； <br><br>（2） 通过以下方式传入参数值： <br><br>&lt;tags:displayProducts&gt; <br>&lt;jsp:attribute name="normalPrice"&gt;....&lt;/jsp:attribute&gt; <br>&lt;jsp:attribute name="onSale"&gt;....&lt;/jsp:attribute&gt; <br>..... <br>&lt;/tags:displayProducts&gt; <br>（3） displayProducts是与/WEB-INF/tags目录中的某个文件名； <br><br>（4） 通过&lt;jsp:attribute name="&#8230;. "&gt;来赋值 <br><br>（5） 标签模板是一个纯文本文件，类似于html文件，而不需要通过java的类来实现标签的定义； <br><br>（6） 个人认为标签模板的主要作用重在排版，而其它标签的作用重在功能的实现；本人不打算在以后的开发使用标签模板，因此本文不再进一步分析标签模板。 
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/49584.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-09-27 15:45 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/09/27/49584.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JBoss3.0 下配置和部署EJB简介[转]</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/09/27/49582.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Sat, 27 Sep 2008 06:45:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/09/27/49582.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/49582.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/09/27/49582.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/49582.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/49582.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: JBoss3.0 下配置和部署EJB简介(by huihoo.org 赵晨希,zhaochenxi@vip.sina.com)1．JBoss简介JBoss是一个运行EJB的J2EE应用服务器。它是开放源代码的项目，遵循最新的J2EE规范。从JBoss项目开始至今，它已经从一个EJB容器发展成为一个基于的J2EE的一个web 操作系统（operating system for web），...&nbsp;&nbsp;<a href='http://www.cnitblog.com/wufajiaru/archive/2008/09/27/49582.html'>阅读全文</a><img src ="http://www.cnitblog.com/wufajiaru/aggbug/49582.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-09-27 14:45 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/09/27/49582.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]hibernate中getsession导致停止响应的问题</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/04/03/41910.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Thu, 03 Apr 2008 09:16:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/04/03/41910.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/41910.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/04/03/41910.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/41910.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/41910.html</trackback:ping><description><![CDATA[<p>我们的一个小程序总是在open session的时候停止响应，而且非常规律得在操作第四次时停止。查阅很多资料，发现下面这篇文章很有启发，摘录如下：<br><br><br>前几天用spring+hibernate+struts写了个增/删/改/查的例子。调试期间问题就来了，当查询结果<font face=Arial>翻页好几次就没N久没有响应了。最后控制报错。网上查了，它说数据库连接（池）问题。</font></p>
<p>出现错误如下:</p>
<p><font face=Arial><font face=Arial><font face=Arial><span lang=EN-US style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">&lt;<st1:chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="9" year="2007">2007-9-30</st1:chsdate> </span><span style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">下午</span><span lang=EN-US style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">12</span><span style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">时</span><span lang=EN-US style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">03</span><span style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">分</span><span lang=EN-US style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">03</span><span style="FONT-SIZE: 10.5pt; FONT-FAMILY: 宋体; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'">秒</span><span lang=EN-US style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"> CST&gt; &lt;Error&gt; &lt;WebLogicServer&gt; &lt;BEA-000337&gt; &lt;ExecuteThread: '13' for queue: 'weblogic.kernel.Default' has been busy for "901" seconds working on the request "Http Request: /admin/school.do", which is more than the configured time (StuckThreadMaxTime) of "600" seconds.&gt;<br><br></p>
<p>先说下我配置</p>
<p>1.环境：</p>
<p>spring 2.0.6，hibernate 3.2.3，struts 1.2.9，oracle 10.2，weblogic 8.1.4</p>
<p>jdbc是ojdbc14.jar</p>
<p>2.连接池用DBCP</p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">bean&nbsp;</span><span style="COLOR: #ff0000">id</span><span style="COLOR: #0000ff">="dataSource"</span><span style="COLOR: #ff0000">&nbsp;class</span><span style="COLOR: #0000ff">="org.apache.commons.dbcp.BasicDataSource"</span><span style="COLOR: #ff0000">&nbsp;destroy-method</span><span style="COLOR: #0000ff">="close"</span><span style="COLOR: #0000ff">&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">property&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="driverClassName"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="${jdbc.driverClassName}"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">property&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="url"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="${jdbc.url}"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">property&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="username"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="${jdbc.username}"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">&lt;</span><span style="COLOR: #800000">property&nbsp;</span><span style="COLOR: #ff0000">name</span><span style="COLOR: #0000ff">="password"</span><span style="COLOR: #ff0000">&nbsp;value</span><span style="COLOR: #0000ff">="${jdbc.password}"</span><span style="COLOR: #0000ff">/&gt;</span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;<br>bean&gt;&nbsp;&nbsp;&nbsp;<br></span></div>
<br>3.分页方法（参考springside的），此类继承HibernateDaoSupport<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Page&nbsp;listByPage(Class&nbsp;entityClass,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;pageNo,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;pageSize,&nbsp;List&nbsp;criterions,&nbsp;List&nbsp;orders)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;Criteria&nbsp;criteria&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;createCriteria(entityClass,&nbsp;criterions);&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;CriteriaImpl&nbsp;impl&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(CriteriaImpl)&nbsp;criteria;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;先把Projection和OrderBy条件取出来,清空两者来执行Count操作&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Projection&nbsp;projection&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;impl.getProjection();&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">获取总记录数&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;totalCount&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;((Integer)&nbsp;criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(totalCount&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Page();&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;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">加排序&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(orders&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;criteria.addOrder((Order)&nbsp;orders.get(i));&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;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">原来的投影&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;criteria.setProjection(projection);&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;startIndex&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;Page.getStartOfPage(pageNo,&nbsp;pageSize);&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">取得结果&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;criteria.setFirstResult(startIndex).setMaxResults(pageSize).list();&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Page(startIndex,&nbsp;totalCount,&nbsp;pageSize,&nbsp;list);&nbsp;&nbsp;&nbsp;&nbsp;<br>}&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Criteria&nbsp;createCriteria(Class&nbsp;entityClass,&nbsp;List&nbsp;criterions)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;Criteria&nbsp;criteria&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;getSession().createCriteria(entityClass);&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(criterions&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;criteria.add((Criterion)&nbsp;criterions.get(i));&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;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;criteria;&nbsp;&nbsp;&nbsp;&nbsp;<br>}&nbsp;&nbsp;&nbsp;<br></span></div>
<br>
<p><span>另外，没有用<font face=Arial>OpenSessionInViewFilter，struts与spring的整合：<font face=Arial>DelegatingRequestProcessor、action path与bean name同名。</font></font></span></p>
<p>&nbsp;</p>
<p><span><font face=Arial>翻页不过10次，服务器就没响应了，最后出现上面的错误的了。</font></span></p>
<p><span>刚用weblogic，也刚用ssh套餐。郁闷。<br><br>前天解决了。<br></p>
<p>问题解决，问题的原因是数据库连接耗尽，我用HiberanteDaoSupport的getSession()方法取得Session后没有释放Session。</p>
<p>出问题的代码处（红色部分）：<br><br></p>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Criteria&nbsp;createCriteria(Class&nbsp;entityClass,&nbsp;List&nbsp;criterions)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;Criteria&nbsp;criteria&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;<span style="COLOR: red">getSession().</span>createCriteria(entityClass);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(criterions&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;criteria.add((Criterion)&nbsp;criterions.get(i));&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;<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;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;criteria;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>}&nbsp;&nbsp;&nbsp;<br></span></div>
<br>
<p>用完Session释放后就没事了，调用HiberanteDaoSupport的<font face=Arial>releaseSession(session);方法后即可解决。</font></p>
<br>
<p>现在正确的代码：</p>
<br>
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Page&nbsp;listByPage(Class&nbsp;entityClass,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;pageNo,&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;pageSize,&nbsp;List&nbsp;criterions,&nbsp;List&nbsp;orders)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;Session&nbsp;session&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;getSession();&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">创建criteria&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Criteria&nbsp;criteria&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;session.createCriteria(entityClass);&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">为criteria添加criterions&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;createCriteria(entityClass,&nbsp;criteria,&nbsp;criterions);&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;CriteriaImpl&nbsp;impl&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;(CriteriaImpl)&nbsp;criteria;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;先把Projection和OrderBy条件取出来,清空两者来执行Count操作&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Projection&nbsp;projection&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;impl.getProjection();&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">获取总记录数&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;totalCount&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;((Integer)&nbsp;criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(totalCount&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Page();&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;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">加排序&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(orders&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;criteria.addOrder((Order)&nbsp;orders.get(i));&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;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">原来的投影&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;criteria.setProjection(projection);&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;startIndex&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;Page.getStartOfPage(pageNo,&nbsp;pageSize);&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">取得结果&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;List&nbsp;list&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;criteria.setFirstResult(startIndex).setMaxResults(pageSize).list();&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">释放hiberante资源,一定要释放,要不然就数据库连接耗尽.&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000"><br></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;releaseSession(session);&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Page(startIndex,&nbsp;totalCount,&nbsp;pageSize,&nbsp;list);&nbsp;&nbsp;&nbsp;&nbsp;<br>}&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;<br></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">&nbsp;Criteria&nbsp;createCriteria(Class&nbsp;entityClass,&nbsp;Criteria&nbsp;criteria,&nbsp;List&nbsp;criterions)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">(criterions&nbsp;</span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">&nbsp;i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;&nbsp;i&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;criteria.add((Criterion)&nbsp;criterions.get(i));&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;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;criteria;&nbsp;&nbsp;&nbsp;&nbsp;<br>}&nbsp;&nbsp;&nbsp;<br></span></div>
<br><br>^_^</span></span></font></font></font><font face="宋体, MS Song"> <br><br>chenlb.blogjava.net </font>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/41910.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-04-03 17:16 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/04/03/41910.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Yale CAS实现原理及其基础协议[转]</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/03/24/41396.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Mon, 24 Mar 2008 07:41:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/03/24/41396.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/41396.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/03/24/41396.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/41396.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/41396.html</trackback:ping><description><![CDATA[<span class=blue>更新时间:</span> <span class=date>2008-03-01 13:50:27</span> <span class=blue>作者：</span> JavaFeng<br><strong><span class=blue><img src="http://icon.zdnet.com.cn/techupdate/pic/images/information.gif" align=absMiddle>关键词：</span> <span><a class=red href="http://www.techupdate.com.cn/techupdate/list-0-95615-0-1.htm" target=_blank><u><font color=#0000ff>协议</font></u></a> <a class=red href="http://www.techupdate.com.cn/techupdate/list-0-77730-0-1.htm" target=_blank><u><font color=#0000ff>原理</font></u></a> <a class=red href="http://www.techupdate.com.cn/techupdate/list-0-82803-0-1.htm" target=_blank><u><font color=#0000ff>实现</font></u></a> <a class=red href="http://www.techupdate.com.cn/techupdate/list-0-74727-0-1.htm" target=_blank><u><font color=#0000ff>cas</font></u></a> </span></strong>
<ul>CAS(Central Authentication Service) 是 Yale 大学发起的一个开源项目，据统计，大概每 10 个采用开源构建 Web SSO 的 Java 项目，就有 8 个使用 CAS 。对这些统计，我虽然不以为然，但有一点可以肯定的是， CAS 是我认为最简单实效，而且足够安全的 SSO 选择。
    <div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>本节主要分析 CAS 的安全性，以及为什么 CAS 被这样设计，带着少许密码学的基础知识，我希望有助于读者对 CAS 的协议有更深层次的理解。 </div>
    <div></div>
    <div>
    <div style="TEXT-INDENT: 21pt">从结构体系看， CAS 包含两部分： </div>
    <div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><font color=#0000ff><span>l<span Times New Roman??>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>CAS Server </font></div>
    <div style="TEXT-INDENT: 21pt">CAS Server 负责完成对用户的认证工作， CAS Server 需要独立部署，有不止一种 CAS Server 的实现， Yale CAS Server 和 ESUP CAS Server 都是很不错的选择。 </div>
    <div style="TEXT-INDENT: 21pt">CAS Server 会处理用户名 / 密码等凭证 (Credentials) ，它可能会到数据库检索一条用户帐号信息，也可能在 XML 文件中检索用户密码，对这种方式， CAS 均提供一种灵活但同一的接口 / 实现分离的方式， CAS 究竟是用何种认证方式，跟 CAS 协议是分离的，也就是，这个认证的实现细节可以自己定制和扩展。 </div>
    <div style="MARGIN: 0cm 0cm 0pt 42pt; TEXT-INDENT: -21pt"><font color=#0000ff><span>l<span Times New Roman??>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>CAS Client </font></div>
    <div style="TEXT-INDENT: 21pt">CAS Client 负责部署在客户端（注意，我是指 Web 应用），原则上， CAS Client 的部署意味着，当有对本地 Web 应用的受保护资源的访问请求，并且需要对请求方进行身份认证， Web 应用不再接受任何的用户名密码等类似的 Credentials ，而是重定向到 CAS Server 进行认证。 </div>
    <div style="TEXT-INDENT: 21pt">目前， CAS Client 支持（某些在完善中）非常多的客户端，包括 Java 、 .Net 、 ISAPI 、 Php 、 Perl 、 uPortal 、 Acegi 、 Ruby 、 VBScript 等客户端，几乎可以这样说， CAS 协议能够适合任何语言编写的客户端应用。 </div>
    <div style="TEXT-INDENT: 21pt"></div>
    <div style="TEXT-INDENT: 21pt">&nbsp;剖析协议就像剖析设计模式，有些时候，协议让人摸不着头脑。 CAS 的代理模式要相对复杂一些，它引入了一些新的概念，我希望能够在这里描述一下其原理，有助于读者在配置和调试 CAS SSO 有更清晰的思路。
    <div style="TEXT-INDENT: 21pt">如果没记错， CAS 协议应该是由 <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#100;&#114;&#101;&#119;&#46;&#109;&#97;&#122;&#117;&#114;&#101;&#107;&#64;&#121;&#97;&#108;&#101;&#46;&#101;&#100;&#117;"><u><font color=#0000ff>Drew Mazurek</font></u></a> 负责可开发的，从 CAS v1 到现在的 CAS v3 ，整个协议的基础思想都是基于 Kerberos 的票据方式。 </div>
    <div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CAS v1</span> 非常原始，传送一个用户名居然是 &#8221;yes david.turing&#8221; 的方式， CAS v2 开始使用了 XML 规范，大大增强了可扩展性， CAS v3 开始使用 AOP 技术，让 Spring 爱好者可以轻松配置 CAS Server 到现有的应用环境中。 </div>
    <div style="TEXT-INDENT: 21pt">CAS 是通过 TGT(Ticket Granting Ticket) 来获取 ST(Service Ticket) ，通过 ST 来访问服务，而 CAS 也有对应 TGT ， ST 的实体，而且他们在保护 TGT 的方法上虽然有所区别，但是，最终都可以实现这样一个目的——免去多次登录的麻烦。 </div>
    <div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>下面，我们看看 CAS 的基本协议框架： </div>
    <div></div>
    <div>基础协议
    <div><span><img height=380 alt=cas_protocol-1.jpg src="http://www.blogjava.net/images/blogjava_net/security/cas_protocol-1.jpg" width=528 border=0> <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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CAS</span> 基础模式 </div>
    <div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>上图是一个最基础的 CAS 协议， CAS Client 以 Filter 方式保护 Web 应用的受保护资源，过滤从客户端过来的每一个 Web 请求，同时， CAS Client 会分析 HTTP 请求中是否包请求 Service Ticket( 上图中的 Ticket) ，如果没有，则说明该用户是没有经过认证的，于是， CAS Client 会重定向用户请求到 CAS Server （ Step 2 ）。 Step 3 是用户认证过程，如果用户提供了正确的 Credentials ， CAS Server 会产生一个随机的 Service Ticket ，然后，缓存该 Ticket ，并且重定向用户到 CAS Client （附带刚才产生的 Service Ticket ）， Service Ticket 是不可以伪造的，最后， Step 5 和 Step6 是 CAS Client 和 CAS Server 之间完成了一个对用户的身份核实，用 Ticket 查到 Username ，因为 Ticket 是 CAS Server 产生的，因此，所以 CAS Server 的判断是毋庸置疑的。 </div>
    <div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>该协议完成了一个很简单的任务，就是 User(david.turing) 打开 IE ，直接访问 helloservice 应用，它被立即重定向到 CAS Server 进行认证， User 可能感觉到浏览器在 helloservcie 和 casserver 之间重定向，但 User 是看不到， CAS Client 和 CAS Server 相互间的 Service Ticket 核实 (Validation) 过程。当 CAS Server 告知 CAS Client 用户 Service Ticket 对应确凿身份， CAS Client 才会对当前 Request 的用户进行服务。 </div>
    <div></div>
    <div>CAS 如何实现 SSO
    <div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>当我们的 Web 时代还处于初级阶段的时候， SSO 是通过共享 cookies 来实现，比如，下面三个域名要做 SSO ： </div>
    <div style="TEXT-INDENT: 21pt"><a href="http://www.blogjava.net/"><u><font color=#0000ff>http://www.blogjava.net</font></u></a> </div>
    <div style="TEXT-INDENT: 21pt"><a href="http://www.matrix.org.cn/"><u><font color=#0000ff>http://www.matrix.org.cn</font></u></a> </div>
    <div style="TEXT-INDENT: 21pt"><a href="http://www.csdn.net/"><u><font color=#0000ff>http://www.csdn.net</font></u></a> </div>
    <div style="TEXT-INDENT: 21pt">如果通过 CAS 来集成这三个应用，那么，这三个域名都要做一些域名映射， </div>
    <div style="TEXT-INDENT: 21pt"><a href="http://blogjava.cas.org/"><u><font color=#0000ff>http://blogjava.cas.org</font></u></a> </div>
    <div style="TEXT-INDENT: 21pt"><a href="http://matrix.cas.org/"><u><font color=#0000ff>http://matrix.cas.org</font></u></a> </div>
    <div style="TEXT-INDENT: 21pt"><a href="http://csdn.cas.org/"><u><font color=#0000ff>http://csdn.cas.org</font></u></a> </div>
    <div style="TEXT-INDENT: 21pt">因为是同一个域，所以每个站点都能够共享基于 cas.org 的 cookies 。这种方法原始，不灵活而且有不少安全隐患，已经被抛弃了。 </div>
    <div style="TEXT-INDENT: 21pt">CAS 可以很简单的实现跨域的 SSO ，因为，单点被控制在 CAS Server ，用户最有价值的 TGC-Cookie 只是跟 CAS Server 相关， CAS Server 就只有一个，因此，解决了 cookies 不能跨域的问题。 </div>
    <div style="TEXT-INDENT: 21pt">回到 CAS 的基础协议图，当 Step3 完成之后， CAS Server 会向 User 发送一个 Ticket granting cookie (TGC) 给 User 的浏览器，这个 Cookie 就类似 Kerberos 的 TGT ，下次当用户被 Helloservice2 重定向到 CAS Server 的时候， CAS Server 会主动 Get 到这个 TGC cookie ，然后做下面的事情： </div>
    <div style="MARGIN: 0cm 0cm 0pt 57.75pt; TEXT-INDENT: -36.75pt"><span>1，<span Times New Roman??>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>如果 User 的持有 TGC 且其还没失效，那么就走基础协议图的 Step4 ，达到了 SSO 的效果。 </div>
    <div style="MARGIN: 0cm 0cm 0pt 57.75pt; TEXT-INDENT: -36.75pt"><span>2，<span Times New Roman??>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span>如果 TGC 失效，那么用户还是要重新认证 ( 走基础协议图的 Step3) 。 </div>
    <div style="MARGIN: 14pt 0cm 14.5pt"><strong>&nbsp;CAS 的代理模式 </strong></div>
    <div style="MARGIN: 14pt 0cm 14.5pt">&nbsp;模式 1 已经能够满足大部分简单的 SSO 应用，现在，我们探讨一种更复杂的情况，即用户访问 helloservice ， helloservice 又依赖于 helloservice2 来获取一些信息，如同：
    <div style="TEXT-INDENT: 21pt">User <span>&#224; </span>helloservice <span>&#224; </span>helloservice2 </div>
    <div style="TEXT-INDENT: 21pt">这种情况下，假设 helloservice2 也是需要对 User 进行身份验证才能访问，那么，为了不影响用户体验（过多的重定向导致 User 的 IE 窗口不停地 闪动 ) ， CAS 引入了一种 Proxy 认证机制，即 CAS Client 可以代理用户去访问其它 Web 应用。 </div>
    <div style="TEXT-INDENT: 21pt">代理的前提是需要 CAS Client 拥有用户的身份信息 ( 类似凭据 ) 。 与其说之前我们提到的 TGC 是用户持有对自己身份信息的一种凭据，则这里的 PGT 就是 CAS Client 端持有的对用户身份信息的一种凭据。凭借 TGC ， User 可以免去输入密码以获取访问其它服务的 Service Ticket ，所以，这里，凭借 PGT ， Web 应用可以代理用户去实现后端的认证，而无需前端用户的参与。 </div>
    <div style="TEXT-INDENT: 21pt">如下面的 CAS Proxy 图所示， CAS Client 在基础协议之上，提供了一个额外的 PGT URL 给 CAS Server, 于是， CAS Server 可以通过 PGT URL 提供一个 PGT 给 CAS Client 。 <br></div>
    <div><span><img height=402 alt=cas_protocol-2.jpg src="http://www.blogjava.net/images/blogjava_net/security/cas_protocol-2.jpg" width=528 border=0> <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>初学者可能会对上图的 PGT URL 感到迷惑，或者会问，为什么要这么麻烦，要通过一个额外的 URL( 而且是 SSL 的入口 ) 去传递 PGT ？如果直接在 Step 6 返回，则连用来做对应关系的 PGTIOU 都可以省掉。 PGTIOU 设计是从安全性考虑的，非常必要， CAS 协议安全性问题我会在后面一节介绍。 </div>
    <div style="TEXT-INDENT: 21pt">于是， CAS Client 拿到了 PGT( <span style="FONT-SIZE: 10pt; COLOR: black">PGTIOU-85&#8230;..ti2td</span> ) ，这个 PGT 跟 TGC 同样地关键， CAS Client 可以通过 PGT 向后端 Web 应用进行认证。如下图所示， Proxy 认证与普通的认证其实差别不大， Step1, 2 与基础模式的 Step 1,2 几乎一样，唯一不同的是， Proxy 模式用的是 PGT 而不是 TGC ，是 Proxy Ticket （ PT ）而不是 Service Ticket 。 </div>
    <div style="TEXT-INDENT: 21pt">最终的结果是， helloservice2 明白 helloservice 所代理的客户是 David. Turing 同学，同时，根据本地策略， helloservice2 有义务为 PGTURL=http://helloservice/proxy 服务 (PGTURL 用于表示一个 Proxy 服务 ) ，于是它传递数据给 helloservice 。这样， helloservice 便完成一个代理者的角色，协助 User 返回他想要的数据。 </div>
    <div style="TEXT-INDENT: 21pt"><br><img height=378 alt=cas_protocol-3.jpg src="http://www.blogjava.net/images/blogjava_net/security/cas_protocol-3.jpg" width=543 border=0> <br>&nbsp;&nbsp;&nbsp;代理认证模式非常有用，它也是 CAS 协议 v2 的一个最大的变化，这种模式非常适合在复杂的业务领域中应用 SSO 。因为，以前我们实施 SSO 的时候，都是假定以 IE User 为 SSO 的访问者，忽视了业务系统作为 SSO 的访问者角色。 </div>
    </div>
    </div>
    </div>
    </div>
    </div>
</ul>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/41396.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-03-24 15:41 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/03/24/41396.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>将JBoss启动做成Windows的系统服务(遇到的问题已经修正，验证有效)</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/26/40178.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Tue, 26 Feb 2008 09:54:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/26/40178.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/40178.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/26/40178.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/40178.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/40178.html</trackback:ping><description><![CDATA[<div class=tit>将JBoss启动做成Windows的系统服务</div>
<div class=date>2007-08-30 11:03</div>
<table style="TABLE-LAYOUT: fixed">
    <tbody>
        <tr>
            <td>
            <div class=cnt>
            <div><font size=2>这里将用到JavaService.exe 这个程序将JBoss启动做成Windows的系统服务。</font></div>
            <div><font size=2></font></div>
            <div><font size=2>第一步： 复制 JavaService.exe 文件到%JBOSS_HOME%\bin目录下；</font></div>
            <div><font size=2><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>如果没有JavaService.exe 可以在</font><a href="http://javaservice.objectweb.org/"><font color=#0000ff size=2><u>http://javaservice.objectweb.org/</u></font></a><font size=2> 网站上下载；</font></div>
            <div><font size=2></font></div>
            <div><font size=2>第二步： 设置环境变量：</font></div>
            <div><font size=2><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>将JAVA_HOME设置成jdk的目录，例如：D:\develop\java\jdk1.6.0</font></div>
            <div><font size=2><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>将JBOSS_HOME设置成JBOSS的目录，例如：D:\Develop\jboss-4.2.0.GA</font></div>
            <div><font size=2></font></div>
            <div><span style="COLOR: red"><font size=2>注意：在环境变量中目录不能有空格，否则会造成服务无法启动。（我这里测试，jdk路径中的空格不影响服务启动）</font></span></div>
            <div><font size=2></font></div>
            <div><font size=2>第三步： 通过Windows的运行&#8220;cmd&#8221;或者&#8220;command&#8221;打开dos运行窗口；进入&#8220;%JBOSS_HOME%\bin&#8221;路径；</font></div>
            <div><font size=2></font></div>
            <div><font size=2>第四步： 在将下面表格中的命令复制到dos窗口下回车运行：</font></div>
            <table style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BACKGROUND: #b3b3b3; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellSpacing=0 cellPadding=0 border=1>
                <tbody>
                    <tr style="HEIGHT: 100.4pt">
                        <td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 426.1pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 100.4pt" vAlign=top width=568>
                        <div><span style="COLOR: black"><font size=2>JavaService.exe -install JBoss %Java_Home%\jre\bin\server\jvm.dll -Djava.class.path="%JBOSS_HOME%\bin\run.jar;%JAVA_HOME%\lib\tools.jar" -Xms64M -Xmx128M -start org.jboss.Main -stop org.jboss.Main -method systemExit -out "%JBOSS_HOME%\server\default\log\out.log" -err "%JBOSS_HOME%\server\default\log\err.log" -current "%JBOSS_HOME%\bin" <br><br><br>原来的示例中后面还有&#8220;-overwrite -startup &#8221;的参数，屡试不成，将这两个参数去掉后运行成功，不知为何，也不知原文作者为什么要加这个。</font></span></div>
                        </td>
                    </tr>
                </tbody>
            </table>
            <div><font size=2></font></div>
            <div><font size=2>运行后，将会提示：&#8220;The JBoss automatic service war successfully installed&#8221;，提示服务安装完成，可以在Windows的服务管理列表中找到名称为&#8220;JBoss&#8221;的服务。输入：&#8220;net start JBoss&#8221;启动服务，服务启动可能需要一定时间，打开新的IE浏览器在地址栏输入：</font><a href="http://localhost:8080/"><font color=#0000ff size=2><u>http://localhost:8080</u></font></a><font size=2> 会有提示页面，表示服务启动成功。</font></div>
            <div><font size=2></font></div>
            <div><font size=2>如何卸载服务：</font></div>
            <div><font size=2><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>在dos命令窗口输入：&#8220;JavaService.exe &#8211;uninstall 服务名称&#8221;</font></div>
            <div><font size=2></font></div>
            <div><font size=2></font></div>
            <div><font size=2>另外此方法也使用于其他的服务，需要在第四步时更改相应的参数。</font></div>
            </div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/40178.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-26 17:54 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/26/40178.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>高级：JDO技术及如何进入企业应用示例</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39931.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Tue, 19 Feb 2008 06:39:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39931.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/39931.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39931.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/39931.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/39931.html</trackback:ping><description><![CDATA[<table style="MARGIN-BOTTOM: 20px; WIDTH: 968px; HEIGHT: 25px" cellSpacing=0 cellPadding=0 width=968 border=0>
    <tbody>
        <tr>
            <td align=middle><span class=content01></span><span class=b>发布时间：2008.02.03 04:41</span>&nbsp;&nbsp;&nbsp;&nbsp;<span class=b> 来源：赛迪网</span>&nbsp;&nbsp;&nbsp;&nbsp;<span class=b>作者：xuyy_cn</span></td>
        </tr>
    </tbody>
</table>
<table class=p11 style="WIDTH: 970px; HEIGHT: 14034px" cellSpacing=0 cellPadding=0 width=970 border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" align=left>
            <p class=a14c style="TEXT-INDENT: 2em"><span class=a14c id=zoom>
            <p style="TEXT-INDENT: 2em">JDO（Java&nbsp;Data&nbsp;Object）是JCP中较早开发出来并形成规范的JSR12，该规范对数据的持久化存储进行了一系列规范，并已有众多的商业产品和开源项目是基于该规范。作为一种需要引起重视的技术，研究并探讨其企业应用可行性是十分重要的。&nbsp;<br><br>前言&nbsp;<br><br>在企业级的应用开发中，常需要有良好的持久化技术来支持数据存储。通过良好的规范或API，将企业的领域业务对象进行持久化存储，大多采用O/R映射技术来进行模式化的数据转换及自动映射工作。&nbsp;<br><br>JDO（Java&nbsp;Data&nbsp;Object）是JCP中较早开发出来并形成规范的JSR12，该规范对数据的持久化存储进行了一系列规范，并已有众多的商业产品和开源项目是基于该规范。作为一种需要引起重视的技术，研究并探讨其企业应用可行性是十分重要的。&nbsp;<br><br>以下主要对JDO（JDO&nbsp;1.0规范）的应用开发技术作扼要介绍，通过该文，可以由浅入深、并较为全面地了解JDO，掌握主要的技术细节及过程，理解其运行机制，并对企业级应用有个总体的把握，这将有助于企业应用软件的技术选型、体系架构及分析设计活动。&nbsp;<br><br>该文适合企业应用架构师、及关心数据持久层设计开发人员。&nbsp;<br><br>JDO基本思想及特点&nbsp;<br><br>企业信息系统的一个重要问题是解决数据的存储，即持久化。在软件开发过程中，分析员分析领域业务，提取出领域业务模型，并对应设计出数据库中需要进行存储业务数据的数据库表及相应字段。&nbsp;<br><br>并根据业务流程，设计业务处理逻辑单元，进行数据的加工、处理及存储、查询等业务。其中一个较为繁烦、枯燥的工作，就是处理大量的数据持久化代码。&nbsp;<br><br>为了解决数据从业务对象层向数据存储层之间的转换工作，JDO提供了相应的开发规范及API，解决了由Java对象直接存储为数据库相应表的底层处理过程，有助于设计人员更加专注于面向业务流程、面向业务对象等较高层次的应用。&nbsp;<br><br>由于采用JDO的映射机制，能降低了业务系统与数据存储系统的耦合，使得业务系统相对于关系数据库或对象型数据库，具有可移植性，同时，由于采用面向对象（而非传统的面向记录）的持久化技术，系统更为轻便、简洁，增强了可维护性。&nbsp;<br><br>JDO应用示例及分析&nbsp;<br><br>以下将通过一些示例，由浅及深地讲解JDO技术。&nbsp;<br><br>临时对象与持久对象&nbsp;<br><br>这是一个普通的业务对象的代码。&nbsp;<br><br><br><br><br><br><br><br><br><br><br>package&nbsp;business.model;&nbsp;<br>public&nbsp;class&nbsp;Book&nbsp;<br>{&nbsp;<br>private&nbsp;String&nbsp;isbn;&nbsp;<br>private&nbsp;String&nbsp;name;&nbsp;<br>private&nbsp;Date&nbsp;publishDate;&nbsp;<br>public&nbsp;void&nbsp;setISBN(String&nbsp;isbn)&nbsp;<br>{&nbsp;<br>this.isbn&nbsp;=&nbsp;isbn;&nbsp;<br>}&nbsp;<br>public&nbsp;String&nbsp;getISBN()&nbsp;<br>{&nbsp;<br>return&nbsp;this.isbn;&nbsp;<br>}&nbsp;<br>public&nbsp;void&nbsp;setName(String&nbsp;name)&nbsp;<br>{&nbsp;<br>this.name&nbsp;=&nbsp;name;&nbsp;<br>}&nbsp;<br>public&nbsp;String&nbsp;getName()&nbsp;<br>{&nbsp;<br>return&nbsp;this.name;&nbsp;<br>}&nbsp;<br>public&nbsp;void&nbsp;<br>setPublishDate(Date&nbsp;pubDate)&nbsp;<br>{&nbsp;<br>this.publishDate&nbsp;=&nbsp;pubDate;&nbsp;<br>}&nbsp;<br>public&nbsp;Date&nbsp;getPublishDate()&nbsp;<br>{&nbsp;<br>return&nbsp;this.publishDate;&nbsp;<br>}&nbsp;<br>}&nbsp;<br><br><br><br><br>现在将它作为一个JDO中对象保存到数据库中。代码如下：&nbsp;<br><br><br>Book&nbsp;book&nbsp;=&nbsp;new&nbsp;Book();&nbsp;<br>book.setISBN(&#8220;isbn-1234567&#8221;);&nbsp;<br>book.setName(&#8220;Java设计模式&#8221;);&nbsp;<br><br>PersistenceManager&nbsp;<br>manager&nbsp;=&nbsp;persistenceManagerFactory.&nbsp;<br>getPersistenceManager();&nbsp;<br>manager.currentTransaction().begin();&nbsp;<br>manager.makePersistence(book);&nbsp;<br>manager.currentTransaction().commit();&nbsp;<br><br><br><br><br>Book类的实例book对JDO的API而言，就是一个持久对象。类Book是可持久类。那任何一个普通java类都是JDO的可持久类吗？不是的。只有具备以下的条件，一个对象才可以被JDO持久到数据库中。&nbsp;<br><br>它所属类应标记为可持久的类，有以下两种方法：&nbsp;<br><br>显式：实现接口，javax.jdo.PersistenceCapable即可；&nbsp;<br><br>隐式：以Sun的JDO参考实现为例，Book.java类的相同路径下还须有Book.jdo文件。&nbsp;<br><br><br>encoding&nbsp;=&nbsp;&#8220;UTF-8&#8221;?&gt;&nbsp;<br><br><br><br><br><br><br><br><br><br><br>并通过字节码增强工具（本例采用Sun的字节码增强工具）处理:&nbsp;<br><br><br>javac&nbsp;Book.java&nbsp;<br>java&nbsp;com.sun.jdori.enhancer.Main&nbsp;<br>Book.class&nbsp;Book.jdo&nbsp;<br><br><br><br><br>通过上述两种方法，获得的Book.class才是一个可持久的类。&nbsp;<br><br>字节码增强的有如下功能：当应用程序通过set方法修改某个字段1时，由于通过增强过程，在其内部插入了某些代码，JDO会获得数据状态变化的信息，从而在持久过程中，进行有选择性的处理。&nbsp;<br><br>按照JDO规范，增强后的类可以在不同的JDO实现上使用，而无需重新编译或增强。&nbsp;<br><br>并不是所有Book对象都是持久对象，只有当makePersistence后，该对象才是持久对象，并会通过JDO实现存储到数据库中。通过JDO的供应商扩展标记符（vendor-extension），可详细描述Book类的存储特性，如为该可持久类指定数据库表和对应字段。&nbsp;<br><br>持久对象查询&nbsp;<br><br>JDO查询主要有以下两种方式。&nbsp;<br><br>使用Extend查询&nbsp;<br><br>Extend可以查询指定类及子类的持久对象。&nbsp;<br><br><br>PersistenceManager&nbsp;<br>manager&nbsp;=&nbsp;persistenceManagerFactory.&nbsp;<br>getPersistenceManager();&nbsp;<br>manager.currentTransaction().begin();&nbsp;<br>Extend&nbsp;extend&nbsp;=&nbsp;<br>manager.getExtend(Book.class,true);&nbsp;<br>//true表明同时查询子类&nbsp;<br>Iterator&nbsp;it&nbsp;=&nbsp;extend.iterator();&nbsp;<br>while(it.hasNext())&nbsp;<br>{&nbsp;<br>Book&nbsp;book&nbsp;=&nbsp;(Book)it.next();&nbsp;<br>System.out.println(book.getISBN());&nbsp;<br>}&nbsp;<br>extend.closeAll();&nbsp;<br>manager.currentTransaction().commit();&nbsp;<br><br><br><br><br>Extend查询方法，提供了一种基于类的查询途径，它可以与下面的Query构成更为强大的查询。&nbsp;<br><br>使用Query查询&nbsp;<br><br>Query可以指定过滤条件，是一种常用的查询方式。&nbsp;<br><br>下例是查找条件为&#8220;书名以&#8216;Java设计模式&#8217;开头且出版日期小于今天&#8221;的书籍。&nbsp;<br><br><br>String&nbsp;filter&nbsp;=&nbsp;<br>&#8220;((String)name).startsWith(\&#8221;Java设计模式\&#8221;)&nbsp;<br>&amp;&amp;&nbsp;publishDate&nbsp;&lt;&nbsp;today&#8221;;&nbsp;<br>Query&nbsp;query&nbsp;=&nbsp;<br>pm.getQuery(Book.class,filter);&nbsp;<br>query.declareImports(&#8220;import&nbsp;java.util.Date&#8221;);&nbsp;<br>query.declareParameters(&#8220;Date&nbsp;today);&nbsp;<br><br>Date&nbsp;today&nbsp;=&nbsp;new&nbsp;Date();&nbsp;<br>results&nbsp;=&nbsp;(Collection)&nbsp;<br>query.execute(today);&nbsp;<br>//传入参数值today&nbsp;<br>if&nbsp;(results.isEmpty())&nbsp;<br>{&nbsp;<br>System.out.println(&#8220;No&nbsp;data!&#8221;);&nbsp;<br>}else{&nbsp;<br>Iterator&nbsp;it&nbsp;=&nbsp;results.iterator();&nbsp;<br>while(it.hasNext())&nbsp;<br>{&nbsp;<br>Book&nbsp;book&nbsp;=&nbsp;(Book)it.next();&nbsp;<br>System.out.println&nbsp;<br>(&#8220;Book&nbsp;Name:&#8221;&nbsp;+&nbsp;book.getName()&nbsp;<br>+&nbsp;&#8220;,&nbsp;ISBN:&#8221;&nbsp;+&nbsp;book.getISBN());&nbsp;<br>}&nbsp;<br>}&nbsp;<br><br><br><br><br>注：该条件使用了一个变元&#8216;today&#8217;，通过&#8220;declareParameters&#8221;来声明该变量，并在&#8220;execute&#8221;方法中传入该变量的实例。这种带参数的查询，很类似于我们以前采用JDBC的带?的查询方式。&nbsp;<br><br>其中startsWith(String&nbsp;s)是JDO提供的标准字符方法，类似的方法还有endsWith(String&nbsp;s)。&nbsp;<br><br>JDOQL：上述使用的就是一个JDOQL样例，JDOQL是JDO规范一个组成部分。使用JDOQL可以使用应用在不同的JDO实现上运行。为了解决JDOQL的某些不足，JDO规范提供了支持特定JDO供应商查询语句接口。&nbsp;<br><br>查询排序&nbsp;<br><br>下例是将查询结果按&#8220;出版日期降序、书名升序&#8221;进行排序。&nbsp;<br><br><br>Query&nbsp;query&nbsp;=&nbsp;<br>pm.newQuery(Book.class,&nbsp;filter);&nbsp;<br><br>String&nbsp;orderStr&nbsp;=&nbsp;<br>&#8220;publishDate&nbsp;decending,&nbsp;name&nbsp;ascending&#8221;;&nbsp;<br>query.setOrdering(orderStr);&nbsp;<br><br>results&nbsp;=&nbsp;query.execute(today);&nbsp;<br><br><br>对象更新&nbsp;<br><br>当客户端对业务数据进行了更新后，需要通过业务过程将其更新到持久层中。这有两个过程，首先根据主键找到该实例，接着更新字段及提交。如下例，将指定书目编号的书本的出版日期进行更改。&nbsp;<br><br><br><br><br><br><br><br><br><br><br><br><br>public&nbsp;void&nbsp;updateBookPublishDate&nbsp;<br>(String&nbsp;isbn,&nbsp;Date&nbsp;newDate)&nbsp;<br>{&nbsp;<br>PersistenceManager&nbsp;pm&nbsp;=&nbsp;null;&nbsp;<br>try{&nbsp;<br>pm&nbsp;=&nbsp;pmf.getPersistenceManager();&nbsp;<br>Object&nbsp;obj&nbsp;=&nbsp;<br>pm.newObjectIdInstance(Book.class,isbn);&nbsp;<br>Book&nbsp;book&nbsp;=&nbsp;<br>(Book)pm.getObjectById(obj,true);&nbsp;<br>book.setPublishDate(newDate);&nbsp;<br>}catch(Exception&nbsp;e)&nbsp;<br>{&nbsp;<br>xxxContext.setRollbackOnly();&nbsp;<br>throw&nbsp;new&nbsp;Exception(e);&nbsp;<br>}finally{&nbsp;<br>try{&nbsp;<br>if&nbsp;(pm&nbsp;!=&nbsp;null&nbsp;&amp;&amp;&nbsp;!pm.isClosed())&nbsp;<br>{&nbsp;<br>pm.close();&nbsp;<br>}&nbsp;<br>}catch(Exception&nbsp;ex)&nbsp;<br>{&nbsp;<br>System.out.println(ex);&nbsp;<br>}&nbsp;<br>}&nbsp;<br><br><br><br><br>注，在PersistenceManager使用newObjectIdInstance（）方法时，JDO是如何知道通过书目编号ISBN来找到该对象呢？其实在本可持久类Book的jdo描述文件中，还需提供如下信息：&nbsp;<br><br><br>encoding&nbsp;=&nbsp;&#8220;UTF-8&#8221;?&gt;&nbsp;<br><br><br><br>identity-type=&#8220;application&#8221;&nbsp;<br>objectid-class=&#8220;BookKey&#8221;&nbsp;&gt;&nbsp;<br>primary-key=&#8220;true&#8221;/&gt;&nbsp;<br><br><br><br><br><br><br><br>其中&#8220;identity-type=&#8220;application&#8221;&#8221;声明可持久类Book采用程序标识方式，即应用程序传入ID（字段isbn为&#8220;primary-key&#8221;）信息，JDO实现构造出指定的&#8220;objectid-class&#8221;的实例（即newObjectIdInstance过程），并由JDO来检索出指定的持久化对象（即getObjectById）。&nbsp;<br><br>BookKey类源码如下：&nbsp;<br><br><br>package&nbsp;businesss.model;&nbsp;<br>public&nbsp;class&nbsp;BookKey&nbsp;implements&nbsp;<br>java.io.Serializable&nbsp;<br>{&nbsp;<br>public&nbsp;String&nbsp;isbn;&nbsp;<br>public&nbsp;BookKey()&nbsp;<br>{&nbsp;<br>}&nbsp;<br>public&nbsp;BookKey(String&nbsp;oid)&nbsp;<br>{&nbsp;<br>isbn&nbsp;=&nbsp;oid;&nbsp;<br>}&nbsp;<br>public&nbsp;String&nbsp;toString()&nbsp;<br>{&nbsp;<br>return&nbsp;isbn;&nbsp;<br>}&nbsp;<br>public&nbsp;Boolean&nbsp;equals(Object&nbsp;obj)&nbsp;<br>{&nbsp;<br>return&nbsp;isbn.equals&nbsp;<br>((BookKey)obj).isbn);&nbsp;<br>}&nbsp;<br>public&nbsp;int&nbsp;hashCode()&nbsp;<br>{&nbsp;<br>return&nbsp;isbn.hashCode();&nbsp;<br>}&nbsp;<br>}&nbsp;<br><br><br><br><br>符合&nbsp;JDO&nbsp;的&#8220;objectid-class&#8221;类，如&#8220;BookKey&#8221;，须具备以下条件：&nbsp;<br><br>类声明为&nbsp;public，并实现&nbsp;java.io.Serializable；&nbsp;<br><br>带有一个公有且不带参数的构造方法；&nbsp;<br><br>当字段作为主键时，须有公有的，且名称和类型与持久类的字段一致，如：public&nbsp;String&nbsp;isbn；&nbsp;<br><br>equals&nbsp;和&nbsp;hashCode&nbsp;须使用全部（特指多字段的联合主键）的主键字段值；&nbsp;<br><br>类必须有一个构造方法，与&nbsp;toString&nbsp;方法的处理过程是逆向过程；即将&nbsp;toString&nbsp;的输出值，作为该构造方法的输入值，又可以重新生成该实例（如构造方法&#8220;public&nbsp;BookKey(String&nbsp;oid)&#8221;）。&nbsp;<br><br>综上所述，如果Book由两个字段作为主键，如isbn和name，则可能的代码是pm.newObjectIdInstance(Book.class,isbn+&#8220;#&#8221;+name)，且BookKey的构造方法作相应更改，并有两个公有字段&#8220;isbn&#8221;和&#8220;name&#8221;。&nbsp;<br><br>对象删除&nbsp;<br><br>对象删除采用方法deletePersistence。示例如下：&nbsp;<br><br><br><br><br><br><br><br><br>pm.currentTransaction().begin();&nbsp;<br>Object&nbsp;obj&nbsp;=&nbsp;<br>pm.newObjectIdInstance&nbsp;<br>(Book.class,isbn);&nbsp;<br>Book&nbsp;book&nbsp;=&nbsp;<br>(Book)pm.getObjectById(obj,true);&nbsp;<br>pm.deletePersistence(book);&nbsp;<br>pm.currentTransaction().commit();&nbsp;<br><br><br><br><br>获得PersistenceManager实例&nbsp;<br><br>上述的所有操作与需要PersistenceManager实例，它可以在两种环境方法下获得：非受管环境和受管环境。&nbsp;<br><br>非受管环境&nbsp;<br><br>非受管环境是多指两层开发模式，应用程序直接获得资源对象，进行业务操作。一般事务管理、安全管理或资源管理都需要应用程序自行维护。&nbsp;<br><br><br>Properties&nbsp;properties&nbsp;=&nbsp;<br>new&nbsp;Properties();&nbsp;<br>properties.put(&#8220;javax.jdo.&nbsp;<br>PersistenceManagerFactoryClass&#8221;,&nbsp;<br>&#8220;com.xxx.jdo.xxxPMFClass&#8221;);&nbsp;<br>properties.put(&#8220;javax.jdo.&nbsp;<br>option.ConnectionURL&#8221;,&nbsp;&#8220;xxx&#8221;);&nbsp;<br>properties.put(&#8220;javax.jdo.&nbsp;<br>option.ConnectionUserName&#8221;,&nbsp;&#8220;xxx&#8221;);&nbsp;<br>properties.put(&#8220;javax.jdo.&nbsp;<br>option.ConnectionPassword&#8221;,&nbsp;&#8220;xxx&#8221;);&nbsp;<br>PersistenceManagerFactory&nbsp;pmf&nbsp;=&nbsp;<br>JDOHelper.getPersistence&nbsp;<br>ManagerFactory(properties);&nbsp;<br>PersistenceManager&nbsp;pm&nbsp;=&nbsp;<br>pmf.getPersistenceManager();&nbsp;<br><br><br><br><br>与JDBC获取类似。&nbsp;<br><br>受管环境&nbsp;<br><br>受管环境一般是多层开发模式，尤其是处于J2EE应用环境中，程序通过容器获得资源对象，进行业务操作，由于在容器环境下，事务、安全及资源管理都由容器进行统一集中管理，从而简化了代码结构。&nbsp;<br><br>以下是EJB（EntityBean、SessionBean、MessageDrivenBean）中的setXXXContext中的代码示例。&nbsp;<br><br><br>private&nbsp;PersistenceManagerFactory&nbsp;pmf;&nbsp;<br>public&nbsp;void&nbsp;setXXXContext&nbsp;<br>(XXXContext&nbsp;context)&nbsp;<br>{&nbsp;<br>try{&nbsp;<br>InitialContext&nbsp;ctx&nbsp;=&nbsp;<br>new&nbsp;InitialContext();&nbsp;<br>Object&nbsp;obj&nbsp;=&nbsp;ctx.lookup&nbsp;<br>(&#8220;java:compenvjdofactory&#8221;);&nbsp;<br>pmf&nbsp;=&nbsp;(PersistenceManagerFactory)&nbsp;<br>PortableRemoteObject.narrow&nbsp;<br>(o,PersistenceManagerFactory.class);&nbsp;<br>}catch(NamingException&nbsp;e)&nbsp;<br>{&nbsp;<br>throw&nbsp;new&nbsp;Exception(e);&nbsp;<br>}&nbsp;<br>}&nbsp;<br><br><br><br><br>PMF是如何绑定到J2EE环境下的JNDI上，有兴趣可参考JCA相关的技术文档。&nbsp;<br><br>事务管理&nbsp;<br><br>事务管理及使用，主要有以下三种情形。&nbsp;<br><br>使用JDO事务的Bean管理情形&nbsp;<br><br>一般在非J2EE环境下，使用该事务管理模式。&nbsp;<br><br><br>PersistenceManager&nbsp;pm&nbsp;=&nbsp;<br>pmf.getPersistenceManager();&nbsp;<br>pm.currentTransaction().begin();&nbsp;<br>//do&nbsp;some&nbsp;business&nbsp;with&nbsp;jdo&nbsp;<br>pm.currentTransaction().commit();&nbsp;<br>pm.close();&nbsp;<br><br><br><br><br>使用JTA事务的Bean管理情形&nbsp;<br><br>一般在J2EE环境下，采用Bean管理的事务情形下，使用以下方式。&nbsp;<br><br>该方式可用在EJB的事务环境下。&nbsp;<br><br><br>xxxContext.getUser&nbsp;<br>Transaction().begin();&nbsp;<br>PersistenceManager&nbsp;pm&nbsp;=&nbsp;<br>pmf.getPersistenceManager();&nbsp;<br>//do&nbsp;some&nbsp;business&nbsp;with&nbsp;jdo&nbsp;<br>xxxContext.getUserTransaction().commit();&nbsp;<br>pm.close();&nbsp;<br><br><br>使用JTA事务的容器管理情形&nbsp;<br><br>一般在J2EE环境下，采用容器管理的事务情形下，使用如下方式。&nbsp;<br><br>如下是某个会话Bean的业务方法。&nbsp;<br><br><br><br><br><br><br><br><br><br><br>public&nbsp;void&nbsp;doBusiness(){&nbsp;<br>PersistenceManager&nbsp;pm&nbsp;;&nbsp;<br>try{&nbsp;<br>pm&nbsp;=&nbsp;pmf.getPersistenceManager();&nbsp;<br>//do&nbsp;some&nbsp;business&nbsp;with&nbsp;jdo&nbsp;<br>}catch(Exception&nbsp;e){&nbsp;<br>xxxContext.setRollbackOnly();&nbsp;<br>System.out.println(e);&nbsp;<br>}finally{&nbsp;<br>try{&nbsp;<br>if&nbsp;(pm&nbsp;!=&nbsp;null&nbsp;&amp;&amp;&nbsp;!pm.isClosed())&nbsp;<br>pm.close();&nbsp;<br>}catch(Exception&nbsp;ex){&nbsp;<br>System.out.println(ex);&nbsp;<br>}&nbsp;<br>}&nbsp;<br>}&nbsp;<br><br><br><br><br>综上，可以得出结论，JDO的操作完全与JDBC的操作相差无几。&nbsp;<br><br>JDO高级应用&nbsp;<br><br>复杂对象的持久化&nbsp;<br><br>在实际的应用中，一个可持久化类要远比Book类复杂很多。它可能会引用其它的Java类型、类、集合或数组，及可能复杂的继承关系。当这些对象的状态发生变化时，JDO是如何感知及跟踪状态变化？&nbsp;<br><br>JDO提供了相应的API及规范来实现该功能。&nbsp;<br><br>基本类型及引用&nbsp;<br><br>可持久化类的字段能被JDO实现进行持久化的原则。原始类型、java.util.Date等被支持（其它较为复杂或可选特性，详见JDO规范）；如果引用是一个可持久类，则JDO进行持久化处理；通过元数据(如jdo文件)声明的字段，一般是非可持久化类的引用，JDO进行持久化；&nbsp;<br><br>前面两种情形，当状态发生变化时，JDO会自动感知，但如果引用是非可持久化类，则需要代码进行显式通知，否则JDO不会将变化进行存储。如下例：&nbsp;<br><br><br>public&nbsp;class&nbsp;Book&nbsp;<br>{&nbsp;<br>&#8230;&#8230;&nbsp;<br>private&nbsp;Object&nbsp;picture;&nbsp;<br>public&nbsp;void&nbsp;setPicture(Object&nbsp;pic)&nbsp;<br>{&nbsp;<br>picture&nbsp;=&nbsp;pic;&nbsp;<br>}&nbsp;<br>public&nbsp;Object&nbsp;getPicture()&nbsp;<br>{&nbsp;<br>Return&nbsp;picture;&nbsp;<br>}&nbsp;<br>}&nbsp;<br><br><br><br><br>该类字段picture需要持久化，但java.lang.Object不是一个可持久类，故声明如下：&nbsp;<br><br><br><br><br><br><br><br>persistence-modifier=&#8220;persistent&#8221;/&gt;&nbsp;<br><br><br><br><br><br><br><br>如果其它模块通过getPicture获得对象，并在JDO不可感知的外部，修改对象，则变化不会存储，较好的办法是修改setPicture方法，如下：&nbsp;<br><br><br>public&nbsp;void&nbsp;setPicture(Object&nbsp;pic)&nbsp;<br>{&nbsp;<br>JDOHelper.makeDirty(this,&nbsp;&#8220;picture&#8221;);&nbsp;<br>picture&nbsp;=&nbsp;pic;&nbsp;<br>}&nbsp;<br><br><br><br><br>并通过setPicture方法来更新数据。JDO的&#8220;makeDirty&#8221;方法，主要负责通知JDO实现，可持久化类Book某个实例（this）的&#8220;picture&#8221;字段发生了变化。&nbsp;<br><br>集合&nbsp;<br><br>可持久类的字段引用为集合时，按照JDO规范，强制支持java.util.HashSet，对HashMap、HashTable、TreeMap、TreeSet、LinkedList、ArrayList及Vector的支持对JDO实现而言是可选的，通过PersistenceManagerFactory的supportedOptions方法获得实现特性。&nbsp;<br><br>数组&nbsp;<br><br>如果可持久类的引用是数组类型，当数组单元发生变化时，需要调用&#8220;makeDirty&#8221;来通知JDO实现，该实例的数组引用内容发生了变化。与引用是非可持久类实例不同，不需要进行JDO的元数据声明。&nbsp;<br><br>继承&nbsp;<br><br>如果使用可持久性，一般继承的子类与父类都为可持久类，以减少系统复杂性，这时需要在子类的元数据中指出其可持久超类，如下：&nbsp;<br><br><br>&lt;&nbsp;<br>class&nbsp;name=&#8220;TechBook&#8221;&nbsp;<br>persistence-capable-superclass=&#8220;Book&#8221;/&gt;&nbsp;<br><br><br><br><br>可为非持久类扩展持久类，或可为持久类扩展非可持久类；这两种情形JDO实现都将忽略非&nbsp;<br><br>可持久类的字段部分，而不保存到数据库。&nbsp;<br><br>JDO的一些不足之处&nbsp;<br><br>JDO对数据的持久化技术相比于成熟的SQL，还有不足之处，这些不足在某些情况下将可能会影响数据处理部分的设计实现。以下列举了常用数据访问的必要功能&nbsp;<br><br>查询增强&nbsp;<br><br>如字符串不支持通配符、大小写比较；&nbsp;<br><br>不支持聚合操作，无法实现MIN、MAX、SUM和AVG；&nbsp;<br><br>不支持投影操作，JDO查询返回为对象，而不像SQL那样返回字段；&nbsp;<br><br>不支持联合、交叉（UNION/INTERSECT）；&nbsp;<br><br>不支持JOIN、IN和EXISTS；&nbsp;<br><br>企业应用探究&nbsp;<br><br>由于JDO采用面向对象的持久化处理技术，从而为解决企业业务系统的持久化问题提供了一个新技术解决方案。但是先进的未必就最适用。在某些应用场景下，需要结合各种因素，采取灵活的策略。&nbsp;<br><br>面向对象与面向记录&nbsp;<br><br>现在大多业务系统都采用面向对象分析设计，这就需要每个应用系统都自行实现将对象映射成记录，并存储到数据库中，而有JDO这样的面向对象的持久化技术，在某种程度上解放了这种转化设计的不规范性，进而获得相对更优的系统结构。&nbsp;<br><br>另一方面，一个业务系统的数据持久化，一般都有这样的过程：对象层－＞记录层－＞物理层，JDO无疑使分析设计人员从记录层的苦海中解脱出来，从而更加专注于对象层，这对开发人员无疑是一个令人欢欣鼓舞的技术。&nbsp;<br><br>JDO并不能完全代替JDBC。&nbsp;<br><br>根据经典的&#8220;8-2原理&#8221;，如果用JDO来解决80%的问题，余下的20%由JDBC来实现，这种相互补充，各取所长的策略，是一个很有效的办法。&nbsp;<br><br>这样一方面可以获得较好的结构及提升开发质量，另一方面解决了JDO的某些技术不足，并可根据以后的技术变化，再做适当转化。&nbsp;<br><br>性能问题&nbsp;<br><br>JDO与JDBC究竟谁的性能更优，目前还没有一个权威、且令人满意的答案。但对于一些JDO实现而言，通过采用缓存机制，使得性能有了较大提高。&nbsp;<br><br>跨数据库&nbsp;<br><br>使用JDO的系统能更好地进行数据库移植，甚至可以在对象数据库上运行；当然JDBC处理层如果完全遵循SQL-92标准，也同样具有很好的跨数据库能力。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font face="Times New Roman" size=3>(责任编辑：包春林) </font></p>
            </span></td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/39931.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-19 14:39 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39931.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA域对象持久化技术的比较</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39930.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Tue, 19 Feb 2008 06:38:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39930.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/39930.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39930.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/39930.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/39930.html</trackback:ping><description><![CDATA[<br>本文是对Java常用域对象持久化技术的比较。在本文中介绍了域对象的概念，讨论了为什么要引入持久化技术，并对目前5种Java常用的域对象持久化技术进行比较，评价它们各自的优缺点和适用范围。 <br><br>一.&nbsp;应用程序的分层体系结构&nbsp; <br>3层结构是目前典型的应用软件结构，3层即表述层、业务逻辑层和数据库层。其中表述层提供与用户的交互界面，GUI和Web页面是表述层的两个典型的例子；业务逻辑层实现各种业务逻辑；数据库层负责存放和管理应用的持久性数据。&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在上述的三层结构中，业务逻辑层不仅负责业务逻辑，而且直接访问数据库，提供对业务数据的保存、更新、删除和查询操作。如果数据库改变或数据库的表结构发生变化，对业务逻辑层的影响非常大。为了把数据访问细节与业务逻辑分开，可以把数据访问作为单独的持久化层。持久化层封装了数据访问细节，为业务逻辑层提供了面向对象的API。完善的持久化层应达到以下目标：&nbsp; <br>代码可重用性高，能够完成所有的数据库访问操作；&nbsp; <br>能够支持多种数据库平台；&nbsp; <br>具有相对独立性，当持久化层发生变化时，不会影响上层的实现。&nbsp; <br>二.&nbsp;软件的模型&nbsp; <br>在软件开发领域，模型用来表示真实世界的实体。在软件开发的不同阶段，需要为目标系统创建不同类型的模型。在分析阶段，需要创建概念模型。在设计阶段，需要创建域模型和数据模型。&nbsp; <br>构成域模型的基本元素就是域对象，即Domain&nbsp;Object，是对真实世界的实体的抽象。域对象可以代表业务领域中的人、地点、事务或概念。域对象包括3种：实体域对象、过程域对象和事件域对象。在三层应用结构中，以上3种域对象都位于业务逻辑层，实体域对象是应用的业务数据在内存中的表现形式，而过程域对象用于执行业务逻辑。&nbsp; <br>当实体域对象在内存中创建后，他们不可能永远存在，因此必须对域对象进行持久化。狭义的理解，&#8220;持久化&#8221;仅仅是把域对象永久保存到数据库中；广义的理解，&#8220;持久化&#8221;包括和数据库的各种相关操作，如：保存、更新、删除、加载、查询等。&nbsp; <br>三.&nbsp;Java中常用域对象持久化技术的比较&nbsp; <br>目前Java中共有5种常用的实现持久化的模式：&nbsp; <br>JDBC直接访问数据库&nbsp; <br>主动域对象模式&nbsp; <br>CMP模式&nbsp; <br>ORM模式&nbsp; <br>JDO模式&nbsp; <br>1、JDBC直接访问数据库&nbsp; <br>在这几种模式中JDBC的历史最为悠久，从Java诞生的那天起就有了JDBC，目前已经发展到JDBC3.0了。JDBC是一套规范，她规定了统一的标准接口，各个数据库厂商提供标准接口的实现。因此，只需要掌握标准的SQL语言就可以访问各种不同的数据库了。JDBC规范的出台，向世界宣告从此有了访问关系数据库的标准通用接口了。JDBC规范一经发布，获得了空前成功，很快成为java访问数据库的标准，JDBC获得了几乎所有数据库厂商的支持。这种数据库间的可移植性和Java一直高喊的口号Compile&nbsp;Once,　Run　everywhere遥相呼应。Java能有今天这么风光，JDBC可以说是功不可末。了。在没有JDBC的时候，各家数据库厂商都有自己的一套API，开发人员访问数据库非常困难，换个数据库，应用程序的修改量极大。JDBC今天还是java访问数据库的基石，本文中讨论的其他几种模式说到底只是更好的封装了JDBC,　提供了更为上层的更为强大的接口而已。&nbsp; <br>JDBC实现数据库访问的方式是在业务方法中直接嵌入SQL语句，SQL语句是面向关系的，依赖于关系模型。所以JDBC方式的优点是简单直接，特别是对于小型应用十分方便。&nbsp; <br>但是JDBC这种实现方式也给应用程序带来以下缺点：&nbsp; <br>(1)、实现业务逻辑的代码和数据库访问代码掺杂在一起，使程序结构不清晰，可读性差。&nbsp; <br>(2)、在程序代码中嵌入面向关系的SQL语句，使开发人员不能完全运用面向对象的思维来编写程序。&nbsp; <br>(3)、业务逻辑和关系数据模型绑定，如果关系数据发生变化，必须手工修改代码中所有相关的SQL语句，这曾经了维护软件的难度。&nbsp; <br>(4)、如果程序代码中SQL语句包含语法错误，在编译时不能检查这种错误，只有在运行时才能发现这种错误，这增加了调试程序的难度。&nbsp; <br>正是由于上述的缺点，为了使业务逻辑和数据访问细节分离，出现了下面的几种模式。&nbsp;
<p>&#160;</p>
<p>&#160;</p>
<p>2、主动域对象模式&nbsp; <br>主动域对象是实体域对象的一种形式，它在实现中封装了关系数据模型和数据访问的细节。在&nbsp;J2EE&nbsp;架构中，EJB组件分为会话EJB和实体EJB。会话EJB通常实现业务逻辑，而实体EJB表示业务实体。实体EJB又分为两种：由EJB本身管理持久化，即BMP（Bean-Managed&nbsp;Persistence）；由EJB容器管理持久化，即CMP（Container-Managed&nbsp;Persistence）。BM&nbsp;P就是主动域对象模式的一个例子，BMP&nbsp;表示由实体&nbsp;EJB&nbsp;自身管理数据访问细节。&nbsp; <br>主动域对象模式有以下优点：&nbsp; <br>(1)、在实体域对象中封装自身的数据访问细节，过程域对象完全负责业务逻辑，使程序结构更加清晰。&nbsp; <br>(2)、如果关系数据模式发生变化，只需要修改主动域对象的代码，不需要修改过程域对象的业务方法。&nbsp; <br>主动域对象模式有以下缺点：&nbsp; <br>(1)、在实体域对象的实现中仍然包含SQL语句。&nbsp; <br>(2)、每个实体域对象都负责自身的数据访问实现。把这一职责分散在多个对象中，这会导致实体域对象重复实现一些共同的数据访问操作，从而造成重复编码。&nbsp; <br>主动域对象本身位于业务逻辑层，因此采用主动域对象模式时，整个应用仍然是三层应用结构，并没有从业务逻辑层分离出独立的持久化层。&nbsp; <br>3．CMP模式&nbsp; <br>在J2EE架构中，CMP（Container-Managed&nbsp;Persistence）表示由EJB容器来管理实体EJB&nbsp;的持久化，EJB容器封装了对象-关系的映射及数据访问细节。CMP&nbsp;和ORM的相似之处在于，两者都提供对象-关系映射服务，都把对象持久化的任务从业务逻辑中分离出来。区别在于CMP负责持久化实体EJB组件，而ORM负责持久化&nbsp;POJO，它是普通的基于&nbsp;Java&nbsp;Bean&nbsp;形式的实体域对象。&nbsp; <br>CMP模式的优点在于：&nbsp; <br>(1)、他是基于EJB技术，是SUN&nbsp;J2EE体系的核心部分，获得了业界的普遍支持，包括各大厂商和开源组织等。如果选择它作企业级开发，技术支持会非常完备。&nbsp; <br>(2)、功能日趋完善，包括了完善的事务支持，EJBQL查询语言，透明的分布式访问等等&nbsp; <br>CMP模式的缺点在于：&nbsp; <br>(1)、开发人员开发的实体必须遵守复杂的J2EE规范，而多少ORM中间件没有类似要求。&nbsp; <br>(2)、实体域EJB只能运行在EJB容器中，而POJO可以运行在任何一种Java环境中。&nbsp; <br>(3)、尽管按照J2EE的规范，EJB应该是一种可移植组件，实际应用时确受到很大限制。而ORM中间件就不存在这样的问题。&nbsp; <br>4．ORM模式&nbsp; <br>ORM-Object/Relational&nbsp;Mapper，即&#8220;对象-关系型数据映射组件&#8221;。对于O/R，即&nbsp;Object（对象）和&nbsp;Relational（关系型数据），表示必须同时使用面向对象和关系型数据进行开发。建模领域中的&nbsp;ORM&nbsp;为&nbsp;Object/Role&nbsp;Modeling（对象角色建模）。另外这里是&#8220;O/R&nbsp;Mapper&#8221;而非&#8220;O/R&nbsp;Mapping&#8221;。相对来讲，O/R&nbsp;Mapping&nbsp;描述的是一种设计思想或者实现机制，而&nbsp;O/R&nbsp;Mapper指以O/R原理设计的持久化框架（Framework），包括&nbsp;O/R机制、SQL自生成、事务处理和Cache管理等。&nbsp; <br>一般把基于&nbsp;Java&nbsp;Bean&nbsp;形式的实体域对象称为&nbsp;POJO（Plain&nbsp;Old&nbsp;Java&nbsp;Object），意为又普通又古老的&nbsp;Java&nbsp;对象的意思。随着各种&nbsp;ORM&nbsp;映射工具的日趋成熟和流行，POJO有重现光彩，它和基于&nbsp;CMP&nbsp;的实体&nbsp;EJB&nbsp;相比，既简单又具有很高的可移植性，因此联合使用ORM&nbsp;映射工具和&nbsp;POJO，已经成为一种越来越受欢迎的且用来取代&nbsp;CMP&nbsp;的持久化方案。POJO的缺点就是无法做远程调用，不支持分布式计算。&nbsp; <br>常用的ORM中间件有：Hibernate、Apache&nbsp;OJB、Cayenne、Jaxor、TopLink等。其中&nbsp;Hibernate&nbsp;的轻量级&nbsp;ORM&nbsp;模型逐步确立了在&nbsp;Java&nbsp;ORM&nbsp;架构中领导地位，甚至取代复杂而又繁琐的&nbsp;EJB&nbsp;模型而成为事实上的&nbsp;Java&nbsp;ORM&nbsp;工业标准。而且其中的许多设计均被&nbsp;J2EE&nbsp;标准组织吸纳而成为最新&nbsp;EJB&nbsp;3.0&nbsp;规范的标准。&nbsp; <br>5．JDO模式&nbsp; <br>JDO是近几年新兴的数据持久性技术，Java&nbsp;Data&nbsp;Objects（JDO）是&nbsp;SUN&nbsp;公司制定的描述对象持久化语义的标准API。严格的说，JDO&nbsp;并不是对象-关系映射接口，因为它支持把对象持久化到任意一种存储系统中，包括关系数据库、面向对象的数据库、基于XML的数据库，以及其他专有存储系统。由于关系数据库是目前最流行的存储系统，许多JDO的实现都包含了对象-关系映射服务。&nbsp;JDO模式的优点是：&nbsp; <br>(1)、简单易用，不需要写大量无用的接口，不需要继承什么特殊的类，唯一所要做的就是对你的class文件做一下enhance。&nbsp; <br>(2)、真正面向对象。用了JDO的java程序是真正的面向对象，无需再理会数据库里面有什么表格，存取都是以java　object为对象，所有数据库表格都是自动生成的。&nbsp; <br>(3)、方便的数据库移植。应用程序换数据库时候除了换一个JDBC　driver,　换一下数据库URL,无需对程序做任何改动。&nbsp; <br>JDO模式的缺点是：&nbsp; <br>由于是新兴技术，一些IT巨头还没有给予足够的支持，其中包括IBM、Oracle、BEA。&nbsp; <br>四.&nbsp;总结&nbsp; <br>关于这些技术优劣之争从它们刚刚出生那天起从来就没有停止过，而各家各派也从来没有能够说服过对方。对于应用开发者而言，撇开应用纯粹来争论技术优劣并没有多大意义。没有最好的，只有最合适的。在做开发的时候能够选择一个最合适于自己应用的技术，那就足够了。总的来说，JDBC面向RDBMS,比较适合关系数据库模式驱动的应用，例如统计表格数据，生成报表之类的应用。EJB　技术以J2EE应用服务器为中心，如果应用确实需要灵活的可声明的事务边界，需要支持大容量的访问和不间断的服务，需要应用服务器的集群，那么选EJB吧。JDO则面向对象，对于以域对象为中心的应用，包含图，树模型的应用，JDO是首选。<br></p>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/39930.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-19 14:38 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39930.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入浅出JBoss Seam</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39929.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Tue, 19 Feb 2008 06:15:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39929.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/39929.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39929.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/39929.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/39929.html</trackback:ping><description><![CDATA[<div class=postTitle><a class=postTitle2 id=viewpost1_TitleUrl href="http://www.blogjava.net/zhouxing/archive/2007/11/06/158610.html"><font color=#4371a6>深入浅出JBoss Seam</font></a> </div>
<p class=info>作者 <strong>Michael Yuan</strong>译者 <strong>包亮</strong> 发布于 2007年11月2日 上午1时3分 </p>
<dl class=tags2>
<dt class=community>社区
<dd><a id=739 onclick="try {CategoryPopup.showPopup(this);} catch(e) {}; return false;" href="http://www.infoq.com/cn/java" name=java><u><font color=#4371a6>Java</font></u></a>
<dt class=topics>主题
<dd><a id=744 onclick="try {CategoryPopup.showPopup(this);} catch(e) {}; return false;" href="http://www.infoq.com/cn/webframework" name=webframework><u><font color=#4371a6>Web框架</font></u></a> </dd></dl>
<p>本文节选了Michael Yuan和Thomas Heute所著的即将出版<strong><a href="http://www.michaelyuan.com/blog/seam-next-gen-web-framework/"><u><font color=#4371a6>JBoss Seam: Power and Flexibility Beyond Java EE 5.0</font></u></a></strong>第一章和第二章，内容有所删减。</p>
<h2>什么是Seam？</h2>
<p>JBoss Seam是&#8220;Java EE 5.0的一个轻量级的框架&#8221;。这是什么意思？难道Java EE(Enterprise Edition) 5.0本身不是一套&#8220;框架吗&#8221;？为什么在官方规范之外，还需要另外一个框架？好吧，我们就将seam看作是本应该被包括在Java EE 5.0中的一个&#8220;遗漏的框架&#8221;吧。它在Java EE 5.0框架的上层，为所有的在企业Web应用中的组件提供了一个统一的、易于理解的编程模型。它同样使基于状态的应用和业务流程驱动的应用的开发易如反掌。换句话说，Seam致力于开发者生产力和应用扩展性。</p>
<h3>1. 整合和强化Java EE框架 </h3>
<p>Java EE5.0的核心框架是EJB(Enterprise JavaBeans)3.0和JSF(JavaServer Faces)1.2。EJB 3.0(以下简称EJB3)是基于一个POJO(Plain Old Java Objects)的业务服务和数据库持久化的轻型框架。JSF是一个基于MVC(Model-View-Controller)的Web应用框架。大多数的Web应用都将包含有业务逻辑的EJB3组件和Web应用前端显示的JSF组件。EJB3和JSF虽然互补，但是他们是根据各自的理念设计的独立的框架。例如，EJB3使用注解（annotation）来配置服务，而JSF使用的是XML文件。更进一步讲，EJB3和JSF组件在框架层面上是互不敏感的。要整合EJB3和JSF，开发者必须手动地构造facade对象（如：JSF支持bean），将业务组件与Web页面和样板代码（又称plumbing代码）联结起来，以便能跨框架调用方法。将这些技术粘合起来是Seam的职责之一。</p>
<p>Seam打破了EJB3和JSF之间的人工层，它为整合EJB3和JSF提供了一个一致的，基于注解的途径。只需要个别简单的注解，Seam中的EJB3业务组件就能直接被用来支持JSF Web表单或者处理Web UI事件。Seam允许开发者将&#8220;同一种东西&#8221;——有注解的POJOs——应用与所有的应用组件。与其他Web框架开发的应用相比，Seam应用概念简洁，同样的功能却需要较少的代码（在JAVA和XML中）。如果没有耐心，或者想要快速预览，一个Seam到底有多简单，你可以现看看本文描述的hello world一例。</p>
<p>在JSP来说困难的任务，Seam可以轻易的完成。例如，JSF头疼的一个问题就是过分依赖HTTP POST。这使得将一个添加到书签中的JSF网页，通过HTTP GET访问相当困难。但是有了Seam，生成一个REST网页是非常容易的。Seam提供了一系列JSF组件标签和注解，增加了&#8220;web友好&#8221;和JSF应用的网页效率。</p>
<p>同时，Seam拓展了EJB3到POJO的组件模式, 从web层到业务层都有了状态上下文。进一步说，Seam整合了一系列主要的其他开放源代码框架，例如jBPM、JBoss Rules(又名Drools)、JBoss Portal、JBoss Microcontainer等等。Seam不仅能将它们&#8220;有机结合&#8221;起来，而且可以像整合JSF和EJB3一样强化原有的框架。</p>
<p>Seam位于Java EE 5.0底层，但它的应用并不局限与Java EE 5.0服务器。一个Seam应用可以部署在J2EE 1.4应用服务器和Tomcat服务器上。这意味着现在能在Seam应用中得到产品化支持。</p>
<blockquote><strong>1 + 1 &gt; 2</strong><br>
<p>或许有这样一种误解，认为Seam仅仅是将各种不同框架串起来的另外一个集成框架。Seam提供了它自身管理的状态上下文，允许框架通过注解和EL（表达式语言）表达式与其他框架进行深度整合。整合的程序来自于Seam开发者对第三方框架的认知。</p>
</blockquote>
<h3>2. 一个为ORM设计的Web框架 </h3>
<p>对象关系映射(ORM)解决方案在当今企业应用中广为使用。但是，大多数当前的业务和web框架并不是为ORM设计的，它们并不在整个Web交互生命周期——从请求来临到响应完成——管理持久上下文。这就导致了包括可怕的<strong>LazyInitializationException</strong>在内的各种ORM异常，带来了如&#8220;数据传输对象（DTO）&#8221;等丑陋的伎俩（ugly hacks）。</p>
<p>Gavin King发明了Seam，同时他也发明了在世界上广为使用的ORM解决方案Hibernate。为了继承和发扬ORM的最佳实践，Seam进行了重新设计。有了Seam，就不必再写DTO，你所做的就是延迟加载。因为扩展后的持久上下文就如同一个自然的高速缓存，可以减少和数据库的交互，ORM的性能就会被极大地改进。</p>
<p>进一步讲，因为Seam整合了ORM层、业务层和表示层，开发者就能够在表示层直接展示ORM对象，也能把数据库验证注解用于输入表单，以及重新定向ORM例外到定制的错误页面。</p>
<h3>3.专为有状态Web应用而设计</h3>
<p>Seam是专为有状态Web应用而设计的。Web应用是天生的多用户应用，电子商务应用天生也是有状态的和有事务的。但是，大多数已有Web应用框架是面向无状态应用的。开发者必须操作HTTP会话（session）对象来管理用户状态，与核心业务逻辑无关的代码不仅会混乱你的应用，而且带来了一系列的性能问题。</p>
<p>在Seam中，所有的基础应用组件天生地有状态。它们使用起来要比HTTP session容易，因为它们的状态由Seam公开管理。没有必要在Seam应用中编写引起麻烦的状态管理代码——只需在其组件上注解其做用域、生命周期方法以及其他状态属性，Seam就会掌管其他[译者注：指这些组件的生命周期]。Seam状态组件要比HTTP会话（session）能更好的管理用户状态。例如，你能有多个&#8220;会话&#8221;进行，每个&#8220;会话&#8221;由在一个HTTP会话（session）中一系列的Web请求和业务方法调用组成。</p>
<p>进一步说，在Seam中，数据库缓存和事务能自动与应用的状态相连。Seam在内存中自动保存数据库更新，等到对话结束后提交到数据库。内存中的缓存能大大减轻复杂状态应用中数据库的负载。</p>
<p>除了以上这些，Seam支持整合开源JBoss jBPM业务程序引擎，大大提升了Web应用中的状态管理。你现在能为一个机构中不同工作人员（诸如客户、经理、技术支持人员等等）的指定工作流程，利用工作流程来驱动应用，而不是依赖用户界面事件处理和数据库。</p>
<h3>4. 支持Web 2.0 </h3>
<p>Seam为Web2.0应用进行了充分的优化。它给AJAX（异步JavaScript和XML，增加网页交互的一种技术）提供了多种支持——从内置&#8220;零Javascript&#8221;的AJAX组件到有AJAX支持的JSF组件，再到定制的JavaScript库，Seam为浏览器端的Javascript对象提供了直接访问Seam服务器组件的途径。Seam提供了一个先进的并发模型，有效的管理来自同一用户的多个AJAX请求。</p>
<p>对于AJAX应用，不断增长的数据库负载是一个巨大的挑战。与一个非AJAX应用相比，一个AJAX应用要向服务器发送的更频繁的请求。一但数据库必须响应这些AJAX请求，那么数据库就不堪重荷。Seam中的状态持久上下文正如一个内存中的缓存，它能在会话始末保存信息，最终帮助减少数据库交互。</p>
<p>Web2.0应用往往为其数据使用复杂关系模型（例如，一个网络交际站点所做的就是处理和显示&#8220;用户&#8221;之间的关系），对于这些站点，延迟加载对于ORM层至关重要。否则，一个简单的查询就能级联地加载整个数据库。正如我们前面所讨论过的，Seam是现今唯一一个正确支持Web应用延时加载的Web框架。</p>
<h3>5.依赖双向映射的Pojo服务 </h3>
<p>Seam是一个&#8220;轻量级&#8221;框架，因为它使用POJO（plain old Java objects）作为服务组件。在应用中，POJO没有使用接口或抽象类来"钩住"组件。当然，问题是如何使POJO交互来组成这个应用？它们如何与容器服务（例如，数据库持久化服务）交互？</p>
<p>Seam通过使用一个流行的、被称作依赖注入(DI)的设计模式联结所有POJO组件。在这个模式下，Seam框架管理着所有组件的生命周期。当一个组件需要使用另外一个时，它通过注解（annotation）向Seam声明此依赖。Seam依据应用当前状态得到这个依赖组件，并将它注入到所需求的组件中。</p>
<p>通过拓展依赖注入概念，一个Seam组件A不但可以构造另外一个组件B，而且把此组件B&#8220;抛还&#8221;给Seam以备其他组件（例如组件C）以后使用。</p>
<p>这类双向依赖管理甚至都广泛的应用于简单的Seam web应用中（例如第二章的hello world一例）。在Seam术语中，我们称这个为&#8220;依赖双向映射&#8221;。</p>
<h3>6.非常规的配置</h3>
[译者注：指以隐式映射为主题，以显式映射为例外的配置方式]
<p>使Seam易用的主要设计原则是&#8220;非常规的配置&#8221;。其思想是为这些组件提供一系列默认行为，开发者只需要在预期行为非默认的时候，显示地配置组件。例如, 当Seam将组件A作为属性注入到组件B时，默认地，组件A刚会以组件B被注入的属性的名称命名。Seam里还有很类似的细节。总的结果是Seam中配置元数据要比其他Java框架简单的多。因此，大多数的Seam应用能通过一系列简单的Java注解进行充分配置。开发者从减化的复杂度中受益匪浅，最后，与其他Java框架相比，用更少的代码实现同样的功能。</p>
<h3>7.避免滥用XML</h3>
<p>或许你已经注意到，Java注解在表述和处理Seam配置元数据时扮演着重要的角色。通过这样的设计使框架更易于操作。</p>
<p>在J2EE发展早期，XML曾经被看作配置管理的&#8220;圣杯&#8221;。框架设计者将所有的配置信息，包括Java类和方法名称都统统丢进XML文档，而不考虑对开发者所带来的后果。反省后，发现这是个严重的错误。XML配置文档太过重复。开发者必须重复代码中已有的信息，从而将配置和代码联结起来。这些重复使应用易于出错（例如，一个拼写错误的类名可能在运行时显示为一个难于调试错误）。缺少合理的默认配置进一步使这一问题复杂化。事实上，在一些框架中，相当数量的样板代码伪装为XML，可能相当于或者超过实际应用中JAVA代码的数量。对于J2EE开发者，XML的滥用通常被称为&#8220;XML地狱&#8221;。</p>
<p>Java社区认识到了XML的滥用问题，并且已经非常成功地用Java代码中的注解取代了XML。EJB3是Java官方标准化机构促进Java企业组件中注解使用的一项成果。EJB3完全可选择的使用XML文档，它向正确方向迈出了积极的一步。Seam加入了EJB3的注解，为整个web应用拓展了基于注解的编程模型。</p>
<p>当然，XML对于配置数据并非完全不利。Seam设计者认识到XML适用于指定页面流程或者定义业务流程的web应用。XML文档使开发者集中地管理整个web应用的工作流程成为可能，同时也反对将配置信息分散于java源文件中。工作流程很少能与源代码耦合，因此XML文档中并不需要重复键入已存在于代码中的信息。</p>
<h3>8.为测试而设计</h3>
<p>Seam为了易于测试而重新设计。因为所有的Seam组件都是注解过的POJO，它们易于进行单元测试。开发者仅仅通过利用常规的Java new关键词来构造实例，然后在测试框架（例如JUnit 或者TestNG）中运行任何方法。如果需要测试多个Seam组件的交互，开发者则逐个实例化这些组件，然后手动建立它们的相互关系（也就是显示地使用setter 方法，而不是依靠Seam依赖注入功能）。</p>
<p>集成测试整个Seam应用比较复杂，因为开发者必须在Seam容器中运行应用。Seam用嵌入的轻量级容器来帮助该类测试。在测试框架中，开发者能按步骤地加载Seam容器，然后运行测试。</p>
<h3>9. 卓越的工具支持</h3>
<p>对于一个聚焦于开发者生产力的应用框架，开发工具的支持至关重要。Seam发布了一个基于命令行的生成器，称作 SeamGen。SeamGen类似于Ruby-On-Rails中的生成器，它支持诸如从一个数据库生成完整CRUD应用的功能，聪明的开发者会通过诸如&#8220;编辑/保存/在浏览器重新载入&#8221;的步骤、有测试支持的特性，来改进web应用。</p>
<p>但更重要的是，SeamGen生成项目不依赖于主流的Java集成开发环境，如Eclipse和NetBeans。有了SeamGen，开发者可以随时入门。</p>
<h3>10. 让我们开始编码吧</h3>
<p>总而言之，Seam为JavaEE应用削减了开发费用，同时，增加了Java EE 5.0不具有的强大的新功能。在下节（节选自本书第二章），我们将给您展示一些实际代码例子来阐述Seam如何工作的。你能通过网站<a hrefhttp:="" seam="" com="" www.michaelyuan.>http://www.michaelyuan.com/seam/</a>下载到本书中所有的例子的源代码。</p>
<h2>Seam Hello World </h2>
<p>JBoss Seam是EJB3和JSF中间的粘合剂，这是Jboss Seam最基本的和最广泛的应用。通过被Seam管理的组件，Seam允许这两个框架之间无缝(不是有意双关的)的集成。它为整个web应用拓展了基于注解的EJB3 POJO编程模型。在层与层之间，没有了必需的手动JNDI查找，没有了冗长的JSF支持bean的声明，没有了过多facade方法，没有了艰辛的对象传递，快哉！</p>
<blockquote><strong>继续在Seam中使用JavaEE模式</strong><br>
<p>在传统的java EE应用中，一些设计模式，例如JNDI查找、XML声明组件、值对象、facade是被强制使用的。Seam用基于注解的POJO消除了这些人为的需求。但是，当Seam应用中真正需要它们的时候，仍然可以自由地使用这些模式。</p>
</blockquote>
<p>编写一个Seam web应用概念上很简单。你只需要编码出下列组件：</p>
<ul>
    <li>实体对象代表数据模型。实体对象可能是JPA或者Hibernate中的POJO对象。它们自动地映射到关系数据库表。
    <li>SF web页面展示了用户界面。页面通过表单捕获用户的输入，并且显示结果。表单域与其数据显示数据库表，这些表被映射到实体bean或者实体bean的集合上。
    <li>EJB3 会话bean或者注解过的Seam POJO可以作为JSF Web页面的UI事件处理器。它们处理封装在实体bean中的用户输入，为下一步（或者页面）生成显示的数据对象。 </li>
</ul>
<p>所有以上组件均由Seam自行管理，它们在运行时被自动注入到正确的页面或者对象。例如，当用户单击按钮提交一个JSF表单，Seam就会自动解析表单域并构造一个实体bean。然后，Seam将实体bean传入同样被Seam构造的事件处理器会话bean中来处理。开发者不需要在代码中管理组件的生命周期和组件之间的相互关系。依赖处理过程中，没有样板代码和XML文件。</p>
<p>本章中，我们使用hello world一例来明确展示Seam如何粘合一个web应用。该例子工作如下：用户能在web表单中输入其名字来&#8220;问候&#8221;Seam。一旦她提交了表单，应用则保存她的名字到一个关系数据库中，并且显示所有已经&#8220;问候&#8221;过Seam的用户。该项目示例在该书下载的源代码中的HelloWorld文件夹中。为了建立它，你必须安装Apache ANT 1.6版本以上 (http://ant.apache.org/)。进入HelloWorld目录，运行命令ant，则会生成build/jars/helloworld.ear文件，可以直接拷贝该文件到Jboss AS实例的server/default/deploy目录下。现在，启动JBoss AS并且打开网址http://localhost:8080/helloworld/。</p>
<p>为了运行本书中的例子，我们建议您使用JEMS GUI安装程序安装一个与Seam兼容的JBoss AS。您可以从<a href="http://labs.jboss.com/portal/jemsinstaller/downloads"><u><font color=#4371a6>http://labs.jboss.com/portal/jemsinstaller/downloads</font></u></a>下载JEMS安装程序。如果您需要更多安装JBoss AS和应用部署帮助，请参见附录A，&#8220;安装和部署JBoss AS&#8221;</p>
<p>欢迎使用示例作为模板，快速开始你自己Seam项目（参见附录B &#8220;使用应用示例作为模板&#8221;）。或者，你能使用命令行工具Seam Gen (参见第四章&#8220;快速应用开发工具&#8221;)自动生成项目模板，包括所有的配置文件。本章中，我将花少量的时间来阐释源代码项目中的目录结构。相反，我们将集中讨论代码和配置，这也是开发者建立一个Seam 应用必需的。如此，我们就能将知识应用到任何一个项目结构，而不需要受模板的限制。</p>
<blockquote><strong>源代码目录</strong><br>
<p>一个Seam应用由java类和XML或文本配置文件组成。本书的项目例子中，java源代码文件在src目录中，网页在view 目录中，所有的配置文件都在resources目录中。更多信息请看附件B,使用应用示例作为模板。</p>
</blockquote>
<h3>1. 创建一个数据模型</h3>
<p>Helloworld应用中的数据模型仅仅是一个有name和id属性的person 类。注解<strong>@Entity</strong>告诉容器映射该类到一个关系数据库表，每个属性对应表中一个字段，每个person实例相当于表中的一条记录。因为Seam采用非常规的配置方式，容器为表名和字段中仅仅使用类名和属性名。属性id上的<strong>@Id</strong>和<strong>@GeneratedValue</strong>注解暗示id字段是主键，它的值是应用服务器为每个保存到数据库的peron对象自动生成。</p>
<pre>@Entity<br>
@Name("person")<br>
public class Person implements Serializable {<br>
<br>
private long id;<br>
private String name;<br>
<br>
@Id @GeneratedValue<br>
public long getId() { return id;}<br>
public void setId(long id) { this.id = id; }<br>
<br>
public String getName() { return name; }<br>
public void setName(String name) {this.name = name;}<br>
}</pre>
<p>Person类中最重要的注解是@Name，它为这个将要注册于Seam中的Person bean指定了名称。在其他Seam组件中（例如，页面和会话bean）中，开发者能指直接使用&#8220;<strong>person</strong>&#8221;来引用被管理的<strong>Person bean</strong>。</p>
<h3>2. 将数据模型映射到web表单</h3>
<p>在JSF页面中，我们使用Person bean来支持表单输入文本域。<strong>#{person.name}</strong>符号指代名为&#8220;<strong>person</strong>&#8221;的Seam组件的name属性，名为&#8220;<strong>person</strong>&#8221;的Seam组件是<strong>Person</strong>实体bean的一个实例。</p>
<pre>&lt;h:form&gt;<br>
Please enter your name:&lt;br/&gt;<br>
&lt;h:inputText value="#{person.name}" size="15"/&gt;&lt;br/&gt;<br>
&lt;h:commandButton type="submit" value="Say Hello"<br>
action="#{manager.sayHello}"/&gt;<br>
&lt;/h:form&gt;</pre>
<p>通过以下的实体表单，JSF页面显示了数据库中所有已经向Seam说&#8220;hello&#8221;的用户。用户名单列表存储在一个名为&#8220;<strong>fans</strong>&#8221;的Seam组件中，它是一个<strong>List
<person></person>
</strong>对象。JSF<strong>dataTable</strong>通过遍历列表，每一行显示一个<strong>Person</strong>对象。<strong>Fan</strong>标记是<strong>fans</strong>列表的迭代子。</p>
<pre>&lt;h:dataTable value="#{fans}" var="fan"&gt;<br>
&lt;h:column&gt;<br>
&lt;h:outputText value="#{fan.name}"/&gt;<br>
&lt;/h:column&gt;<br>
&lt;/h:dataTable&gt;<br>
</pre>
<p><img alt="" src="http://www.infoq.com/resource/articles/jboss-seam/zh/resources/image1.png" _href="img://image1.png"></p>
<p>图2.1显示了Hello World网页</p>
<p>当用户点击&#8220;Say Hello&#8221;按钮提交表单，Seam用输入数据构造了该person组件。然后它调用了名为&#8220;<strong>manager</strong>&#8221;的Seam 组件的sayhello()的方法(像这样，<strong>#{manager.sayHello}</strong>是表单提交按钮的UI事件处理器)，这就在数据库中保存了<strong>person</strong>对象并且刷新了<strong>fans</strong>列表。名为<strong>manager</strong>的组件是一个EJB3的会话bean, 我们将在下节讨论该话题。</p>
<h3>2. 处理web事件 </h3>
<p>Seam 中的名为manager的组件是会话bean <strong>ManagerAction</strong>，正如该类中<strong>@Name</strong>注解指定的。<strong>ManagerAction类</strong>有<strong>person</strong>和<strong>fans</strong>两个属性，这两个属性被<strong>@In</strong>和<strong>@Out</strong>所注解。</p>
<pre>@Stateless<br>
@Name("manager")<br>
public class ManagerAction implements Manager {<br>
<br>
@In @Out<br>
private Person person;<br>
<br>
@Out<br>
private List &lt;Person&gt; fans; </pre>
<p>注解@In和@Out在Seam编程模型中处于核心。因此，让我们看看到底它们在这里是做什么的。</p>
<p>注解@In告诉Seam，在此会话bean中，执行任何一个方法之前，Seam就会把由JSF表单构造的名为person组件赋给该person字段（通过依赖注入）。开发者能为@In中的注入的组件指定一个任意的名称，但是如果没有指定，如这里所示，Seam会将同类型以及同名称的组件注入到该字段中。注解@Out告诉Seam，在执行任何方法后，Seam会将属性fans值和属性person的值都赋给被Seam管理的同名的组件。在Seam中，我们将这个操作称作 &#8220;依赖抛出&#8221;。以此，在ManagerAction.sayHello()方法中，我们仅仅需要更新属性fans和属性person的值，它们会自动显示在页面上。</p>
<blockquote><strong>什么是双向映射</strong><br>
<p>在Seam 文件中，有时你就会看到术语&#8220;双向映射&#8221;。它指的是被Seam管理的组件和Seam管理上下之间的注入和抛出。</p>
</blockquote>
<p>因为<strong>person</strong>属性已经通过注入持有了表单数据，<strong>sayHello()</strong>方法仅仅是通过JPA <strong>EntityManager</strong>将它保存到数据库中，JPA <strong>EntityManager</strong>也是通过<strong>@PersistenceContext</strong>注入的。当方法返回之后，它便更新了<strong>fans</strong>和<strong>person</strong>对象并且把这两个对象抛出。方法<strong>sayHello()</strong>一般会返回null，预示着在调用之后，更新的数据模型将在当前的JSF页面显示。</p>
<pre>  @PersistenceContext<br>
private EntityManager em;<br>
<br>
public String sayHello () {<br>
em.persist (person);<br>
person = new Person ();<br>
fans = em.createQuery("select p from Person p")<br>
.getResultList();<br>
<br>
return null;<br>
}</pre>
<p>除了一些细节，我们基本完成了。可能你已经注意到，ManagerAction bean类实现了Manager接口。为了符合EJB3会话bean 规范，我需要一个能列出bean中所有业务方法的方法。下面是接口Manager代码，幸运的是，用任何高级IDE工具都能轻松地自动生成这个接口。</p>
<pre>@Local<br>
public interface Manager {<br>
public String sayHello ();<br>
}</pre>
<p>这就是在Hello World例子中需要的所有代码。后面两章小节将涵盖Seam应用的其他方法和配置。如果开发者为了自己的小型数据库应用想立即编码和定制helloworld项目，那么现在就可以跳过本章的剩余部分。</p>
<h3>4. 更易于理解的seam编程模型</h3>
<p>现在我们已经大致了解了Hello World的应用。但是我们还有一些重要的话题继续，例如其他折中途径以及前面代码没有涉及到重要特性，我们将在本节讨论这些话题。它们能帮助开发者对seam更深刻的理解，但是如果你没有耐心，可以直接跳过本节，需要的时再来阅读。</p>
<h4>4.1 Seam POJO组件 </h4>
<p>上例中，我们用一个EJB3会话bean实现了应用逻辑，但是我们并不局限于EJB3组件。事实上，Seam中任何一个有<strong>@Name</strong>注解的POJO都能被转化为一个可管理的组件。</p>
<p>例如，我们能将<strong>ManagerAction</strong>转化为一个 POJO，而不是一个EJB3 session bean。</p>
<pre>@Name("manager")<br>
public class ManagerAction {<br>
<br>
@In (create=true)<br>
private EntityManager em;<br>
<br>
... ...<br>
} </pre>
<p>使用POJO取代EJB3 bean有正反两方面意见，使用POJO编程时很简单，因为它们不需要EJB3特有的注解和接口（参见上文）。如果你的所有业务组件都是Seam POJO, 那么你就能不依赖EJB3应用服务器，运行你的Seam 应用（参见23章，没有EJB3的Seam)。</p>
<p>但是，POJO比EJB3的功能少，因为POJO不能获得EJB3容器服务。在不依赖EJB3的Seam 中丧失的EJB3服务就包括以下几点：</p>
<ul>
    <li><strong>@PersistenceContext</strong>注入在POJO中不在管用。为了在一个Seam POJO中得到EntityManager，开发者不得不在Seam配种文件中初始化EntityManager，然后使用Seam注解@In将它注入到POJO中。
    <li>POJOs中将不在支持方法级别事务声明（declarative method-level transaction）。相反，你可以配置Seam来划分事务，可以从收到web请求开始直到响应页面产生结束。
    <li>Seam POJO不是消息驱动组件。
    <li>不支持注解为<strong>@Asynchronous</strong>的方法。
    <li>不支持容器安全管理。
    <li>没有事务或者组件级别的持久上下文。Seam POJO中的所有的持久上下文都是经过拓展的（更多细节请参见7.1 &#8220;默认的对话作用域&#8221;）。
    <li>没有集成容器管理的体系结构（例如，JMX控制台服务）。
    <li>Seam POJO方法中没有Java RMI。
    <li>Seam POJO不能是注解为<strong>@WebService</strong>组件。
    <li>没有JCA集成。 </li>
</ul>
<p>所以当在EJB3容器中进行部署时，为什么每个人都想使用POJO组件？答案就是，POJO组件对于纯&#8220;业务逻辑&#8221;组件非常有益。POJO为其他组件代理了数据访问、消息传递和其他基本功能。例如，我们能使用POJO组件操纵Seam数据访问对象，这对&#8220;业务逻辑&#8221;POJO是非常有用的，因为它们可以在需要的时候，在其他框架中被重用。但是总的来说，它们的应用要比EJB3组件少，特别是在中小型应用中。所以，本书的大多数例子我们都使用EJB3组件。</p>
<h4>4.2 易于测试</h4>
<p>我们已经在第一章中提到，Seam为了不依赖容器的方便的测试，进行了重新设计。在<strong>helloworld</strong>项目中，我们在测试文件夹中包括了单元测试和集成测试这两个测试用例。在纯Java SE环境下，Seam 测试体系模拟了数据库、JSF、Seam上下文以及其他应用服务器服务，只要运行ant test命令就能运行所有的测试。</p>
<h4>4.3 基于Getter和Setter的双向映射 </h4>
<p>在Hello World一例中，我们已经展示了通过成员变量对Seam组件进行的双向映射，你也能通过Getter和Setter方法对组件进行双向映射。例如，以下代码就工作的很好。</p>
<pre>private Person person;<br>
private List &lt;Person&gt; fans;<br>
<br>
@In<br>
public void setPerson (Person person) {<br>
this.person = person;<br>
}<br>
@Out<br>
public Person getPerson () {<br>
return person;<br>
}<br>
@Out<br>
public List &lt;Person&gt; getFans () {<br>
return fans;<br>
}</pre>
<p>虽然以上的getter和setter方法看似轻微，利用getter和setter方法的双向映射真正的价值在于能其加入定制逻辑来操纵双向映射的过程。例如，你可以验证被注入的对象或者快速地从数据库重新得到被抛出的对象。</p>
<h4>4.4避免过度的双向映射</h4>
<p>在Hello World一例中 ,通过将数据组件作为业务组件的属性，可以轻易的减少或者消除双向映射。在JSF页面中，通过这种方式，开发者只需要引用业务组件，而不需要在业务组件和数据组件之间的双向映射。例如，开发者可以修改 ManagerAction类为以下所述。</p>
<p>依赖双向映射是一个非常实用的设计模式。但是，正如其他设计模式，过度使用就会有害。过度的依赖双向映射让代码变得难以阅读，因为开发者必须理解每个注入的组件出自何处。过度的依赖双向映射也能增加性能消耗，因为双向映射是在运行时进行。</p>
<pre>@Stateless<br>
@Name("manager")<br>
public class ManagerAction implements Manager {<br>
<br>
private Person person;<br>
public Person getPerson () {return person;}<br>
public void setPerson (Person person) {<br>
this.person = person;<br>
}<br>
<br>
private List &lt;Person&gt; fans;<br>
public List&lt;Person&gt; getFans () {return fans;}<br>
<br>
...  ...<br>
}</pre>
<p>接下来，我们在页面上引用的属性如下：</p>
<pre>&lt;h:form&gt;<br>
<br>
Please enter your name:&lt;br/&gt;<br>
<br>
&lt;h:inputText value="#{manager.person.name}"/&gt;<br>
&lt;br/&gt;<br>
&lt;h:commandButton type="submit" value="Say Hello"<br>
action="#{manager.sayHello}"/&gt;<br>
&lt;/h:form&gt;</pre>
<pre>... ...</pre>
<pre>&lt;h:dataTable value="#{manager.fans}" var="fan"&gt;<br>
&lt;h:column&gt;<br>
&lt;h:outputText value="#{fan.name}"/&gt;<br>
&lt;/h:column&gt;<br>
&lt;/h:dataTable&gt;</pre>
<p>最后，具有了依赖管理的Seam是多用的。通常用数据访问业务组件封装数据是一项好的实践，特别是针对有状态业务组件。</p>
<h4>4.5 JSF中的页面导航</h4>
<p>本例中，只有一个页面。每次点击按钮后，JSF页面会重新显示更新过的数据模型。显然，大多数web应用多于一个页面。在JSF中，一个用户界面事件处理器能通过返回导航规则名称，决定下一步该显示哪个页面。例如，开发者可以在<strong>navigation.xml</strong>中定义以下导航规则。</p>
<pre>&lt;navigation-case&gt;<br>
&lt;from-outcome&gt;anotherPage&lt;/from-outcome&gt;<br>
&lt;to-view-id&gt;/anotherPage.jsp&lt;/to-view-id&gt;<br>
&lt;/navigation-case&gt;<br>
</pre>
<p>之后，如果sayHello()方法返回一个名为&#8220;another page&#8221;的字符串，JSF下一步就该展示anotherPage.jsp。UI事件处理器决定了接下来要显示哪个页面，从而为我们带来了有步骤的控制。</p>
<h4>4.6 通过EntityManager访问数据库</h4>
<p>JPA（Java Persistence API）<strong>EntityManager</strong>管理着关系数据库表与实体bean 之间的映射。<strong>EntityManager</strong> 在运行时由应用服务器创建。你能使用注解@PersistenceContext，注入一个EntityManager的实例。</p>
<p><strong>EntityManager.persist()</strong>方法将实体bean存为与之对应数据表的一条记录。EntityManager.query()方法运行SQL化的查询，并以实体bean集合形式从数据库返回数据。更多细节请参考JPA文件中关于如何使用EntityManager和查询语言。在本书中，我们只用最简单的查询语句。</p>
<p>默认地，EntityManager将数据存于嵌入的HSQL数据库中。如果在本机上运行Jboss AS，可以通过以下步骤，为HSQL数据库开启一个GUI控制台：访问<strong>http://localhost:8080/jmx-console/</strong>，点击<strong>database=localDB,service=Hypersonic </strong>MBean服务，之后，点击在startDatabaseManager方法下方的&#8220;invoke&#8221;按钮。你就可以从控制台执行任意SQL指令。</p>
<h3>5. 配置和打包</h3>
<p>下面，我们将转移话题，讨论配置文件和应用程序打包。实际上，你可以通过Seam Gen命令行工具，生成几乎所有的配置文档和构造脚本文件。或者你也可以简单的重用在示例中的源文件。所以，如果你想首先学习Seam编程技术，但又担心接下来的配置和部署，这个是很正常的。你可以完全放心地跳过本节，需要的时候可以再次阅读。</p>
<p>本节中，我们集中探讨Seam EJB3组件配置，JBoss AS外的Seam POJO配置和部署当然是可行的。</p>
<p>大多数Seam配置文件都是XML文档。但是等等！我们刚才不是承诺Seam能让我们摆脱J2EE和Spring中的XML地狱吗？为什么它又有了XML文档呢? 是的，XML文档确实有很多用处。XML文档非常适合部署阶段的配置（例如web应用的根URL和后台数据库的定位）。因为它允许我们在部署阶段改变配置而不需要改变和重新编译源代码。它也适合粘合应用服务器中的不同子系统（例如，配置如何让JSF组件与Seam EJB3组件交互）。XML文档也非常适合表示层相关内容（例如网页和页面导航流程）。</p>
<p>我们反对在XML文档中重复已经存在于Java源代码中的信息。开发者很快就会发现，这个简单的SeamEJB3 应用有多个XML配置文档，每个文档那个都非常简短，并且没有一个包含存在于Java代码中的信息。换句话说，Seam中没有&#8220;XML代码&#8221;。</p>
<p>进一步讲，XML文档中的大多数内容都是静态的。所以开发者能在自己的Seam应用中轻松地重用这些文档。如何使用示例作为自己的应用模板的介绍，请参见附录B——使用应用示例作为模板。</p>
<p>我们将用下面几页来详细讲解示例应用的配置文档和打包后的目录结构。如果你没有耐心看下去，而且很满意这个应用模板，你可以跳过以下内容。不管怎样，不再罗嗦, 我们一起来了解hello world示例是如何进行配置和打包的。为了构建一个JBoss AS的部署Seam 应用，我们必须将以上所有java 类和配置文档打包为企业应用程序归档(EAR)。该例中，EAR文件是<strong>helloworld.ear</strong>。它包含了三个JAR文件那个和两个XML配置文档。</p>
<pre>helloworld.ear<br>
|+ app.war        //包含Web页面等<br>
|+ app.jar        //包含Seam组件<br>
|+ jboss-seam.jar // Seam库<br>
|+ META-INF<br>
|+ application.xml<br>
|+ jboss-app.xml  </pre>
<blockquote><strong>源代码目录</strong><br>
<p>在此项目的源代码中，resources/WEB-INF目录包含属于app.war/WEB-INF目录的配置文档。resources/META-INF目录包含属于app.jar/META-INF和helloworld.ear/META-INF的文档。Resources根目录包含属于根目录app.jar的文档。</p>
</blockquote>
<p>application.xml文档列出了在EAR中的JAR文件，并为该应用指定了根URL。</p>
<pre>&lt;application&gt;<br>
&lt;display-name&gt;Seam Hello World&lt;/display-name&gt;<br>
<br>
&lt;module&gt;<br>
&lt;web&gt;<br>
&lt;web-uri&gt;app.war&lt;/web-uri&gt;<br>
&lt;context-root&gt;/helloworld&lt;/context-root&gt;<br>
&lt;/web&gt;<br>
&lt;/module&gt;<br>
<br>
&lt;module&gt;<br>
&lt;ejb&gt;app.jar&lt;/ejb&gt;<br>
&lt;/module&gt;<br>
<br>
&lt;module&gt;<br>
&lt;java&gt;jboss-seam.jar&lt;/java&gt;<br>
&lt;/module&gt;<br>
<br>
&lt;/application&gt;</pre>
<p><strong>jboss-app.xml</strong>文档为该应用指定了类加载器，每个EAR应用的类加载器应该有一个唯一的名称。这里我们使用应用程序名作为类加载器的名称，以避免重复。</p>
<pre>&lt;jboss-app&gt;<br>
&lt;loader-repository&gt;<br>
helloworld:archive=helloworld.ear<br>
&lt;/loader-repository&gt;<br>
&lt;/jboss-app&gt;<br>
</pre>
<p>jboss-seam.jar是Seam发布Seam类库。app.war和app.jar文档由我们来建构。所以，下面我们要研究app.war和app.jar。</p>
<h4>5.1. WAR文件 </h4>
<p><strong>app.war</strong>是按照Web应用程序归档规范打包的JAR文件，它包含页面和标准的JSF/Seam配置文档。你还可以将JSF特有的类库文件放入<strong>WEB-INF/lib</strong>目录 (例如<strong>jboss-seam-ui.jar</strong>)。 </p>
<pre>app.war<br>
|+ hello.jsp<br>
|+ index.html<br>
|+ WEB-INF<br>
|+ web.xml<br>
|+ faces-config.xml<br>
|+ components.xml<br>
|+ navigation.xml</pre>
<p><strong>web.xml</strong>文档是所有java EE web应用必需的。JSF用它来配置JSF servlet控制器，Seam用它来拦截所有的web请求。该配置文档的相当标准。</p>
<pre>&lt;web-app version="2.4"<br>
xmlns="http://java.sun.com/xml/ns/j2ee"<br>
xmlns:xsi="..."<br>
xsi:schemaLocation="..."&gt;<br>
<br>
&lt;!-- Seam --&gt;<br>
&lt;listener&gt;<br>
&lt;listener-class&gt;<br>
org.jboss.seam.servlet.SeamListener<br>
&lt;/listener-class&gt;<br>
&lt;/listener&gt;<br>
<br>
&lt;!-- MyFaces --&gt;<br>
&lt;listener&gt;<br>
&lt;listener-class&gt;<br>
org.apache.myfaces.webapp.StartupServletContextListener<br>
&lt;/listener-class&gt;<br>
&lt;/listener&gt;<br>
<br>
&lt;context-param&gt;<br>
&lt;param-name&gt;<br>
javax.faces.STATE_SAVING_METHOD<br>
&lt;/param-name&gt;<br>
&lt;param-value&gt;client&lt;/param-value&gt;<br>
&lt;/context-param&gt;<br>
<br>
&lt;servlet&gt;<br>
&lt;servlet-name&gt;Faces Servlet&lt;/servlet-name&gt;<br>
&lt;servlet-class&gt;<br>
javax.faces.webapp.FacesServlet<br>
&lt;/servlet-class&gt;<br>
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br>
&lt;/servlet&gt;<br>
<br>
&lt;!-- Faces Servlet Mapping --&gt;<br>
&lt;servlet-mapping&gt;<br>
&lt;servlet-name&gt;Faces Servlet&lt;/servlet-name&gt;<br>
&lt;url-pattern&gt;*.seam&lt;/url-pattern&gt;<br>
&lt;/servlet-mapping&gt;<br>
&lt;context-param&gt;<br>
&lt;param-name&gt;javax.faces.CONFIG_FILES&lt;/param-name&gt;<br>
&lt;param-value&gt;/WEB-INF/navigation.xml&lt;/param-value&gt;<br>
&lt;/context-param&gt;<br>
&lt;/web-app&gt;</pre>
<p><strong>faces-config.xml</strong>文档是JSF标准的配置文档，Seam用它来将其拦截器添加到JSF生命周期中。</p>
<pre>&lt;faces-config&gt;<br>
<br>
&lt;lifecycle&gt;<br>
&lt;phase-listener&gt;<br>
org.jboss.seam.jsf.SeamPhaseListener<br>
&lt;/phase-listener&gt;<br>
&lt;/lifecycle&gt;<br>
<br>
&lt;/faces-config&gt;</pre>
<p>navigation.xml文档为多页面应用包含JSF页面导航规则。因为hello world示例只有一个简单的页面，因此该文档是空的。</p>
<p><strong>components.xml</strong>文档包含Seam特有的配置选项，除<strong>jndi-pattern</strong>属性以外，其他都不依赖于应用。该属性必须包括EAR文档的名称，以便Seam通过其的JNDI全名访问EJB3 bean。</p>
<pre>&lt;components ...&gt;<br>
<br>
&lt;core:init<br>
jndi-pattern="helloworld/#{ejbName}/local"<br>
debug="false"/&gt;<br>
<br>
&lt;core:manager conversation-timeout="120000"/&gt;<br>
<br>
&lt;/components&gt;</pre>
<h4>5.2. Seam组件JAR包</h4>
<p><strong>app.jar</strong>文档包含所有的EJB3bean 类（实体bean和会话bean）以及EJB3相关的配置文档。</p>
<pre>app.jar<br>
|+ Person.class        // entity bean<br>
|+ Manager.class       // session bean interface<br>
|+ ManagerAction.class // session bean<br>
|+ seam.properties     // empty file but needed<br>
|+ META-INF<br>
|+ ejb-jar.xml<br>
|+ persistence.xml</pre>
<p><strong>seam.properties</strong>文档这儿是空但必需的，因为Jboss要通过它知道此JAR文件包含Seam EJB3 bean类，并且相应地处理注解。</p>
<p><strong>ejb-jar.xml</strong>文档包含额外的配置信息，这些信息能重载或者增补EJB3 bean上的注解。在一个Seam应用中，它能将所有的EJB3 类加入Seam拦截器。我们能在所有的Seam应用中重用该文档。</p>
<pre>&lt;ejb-jar&gt;<br>
&lt;assembly-descriptor&gt;<br>
&lt;interceptor-binding&gt;<br>
&lt;ejb-name&gt;*&lt;/ejb-name&gt;<br>
&lt;interceptor-class&gt;<br>
org.jboss.seam.ejb.SeamInterceptor<br>
&lt;/interceptor-class&gt;<br>
&lt;/interceptor-binding&gt;<br>
&lt;/assembly-descriptor&gt;<br>
&lt;/ejb-jar&gt;</pre>
<p><strong>persistence.xml</strong>文档为EJB3 实体bean配置了后台数据源。本例中，我们只是使用了被嵌入到JBoss AS中默认的HSQL数据库(也就是<strong>java:/DefaultDS</strong>数据源)。</p>
<pre>&lt;persistence&gt;<br>
&lt;persistence-unit name="helloworld"&gt;<br>
&lt;provider&gt;<br>
org.hibernate.ejb.HibernatePersistence<br>
&lt;/provider&gt;<br>
&lt;jta-data-source&gt;java:/DefaultDS&lt;/jta-data-source&gt;<br>
&lt;properties&gt;<br>
&lt;property name="hibernate.dialect"<br>
value="org.hibernate.dialect.HSQLDialect"/&gt;<br>
&lt;property name="hibernate.hbm2ddl.auto"<br>
value="create-drop"/&gt;<br>
&lt;property name="hibernate.show_sql" value="true"/&gt;<br>
&lt;/properties&gt;<br>
&lt;/persistence-unit&gt;<br>
&lt;/persistence&gt;<br>
</pre>
<p>这样，以上就是一个简单Seam应用所需的所有配置和打包。我们将在以后讨论到本书的更高级的主题时，涵盖更多的配置选项和类库。再次强调一下，Seam应用入门最简单的方法就是，不要担心这些配置文件，只需要从已有的应用模板做起。</p>
<h3>6. 为何这么简单？</h3>
<p>这就是hello world 应用，三个简单的Java类，一个JSF页面，一组静态配置文件。我们已经有了一个完整的数据库驱动的web应用。整个应用只需要的是少于30行的Java代码，没有一处&#8220;XML代码&#8221;。但是如果开发者有PHP背景，你可能仍然会问&#8220;何以这么简单？我能在php中使用更少的代码吗？&#8221;</p>
<p>好吧，答案就是Seam应用在理论上要比PHP（或者其他任何一种脚本语言）应用简单的多。Seam 组件模式允许我们，有所控制地，可维护地给应用增加更多的功能。我们很快就会发现，Seam组件使开发有状态的和有事务的web应用变得易如反掌。对象关系映射框架（例如：实体bean）允许我们将注意力放在抽象数据模型上，而不需要处理数据库特有的SQL语句。</p>
<p>本文是基于该书的第一章和第二章。后面的章节中，我们继续讨论如何使用Seam组件继续开发复杂的Seam 应用。参见<a href="http://www.infoq.com/resource/articles/jboss-seam/zh/resources/seam-book-toc.pdf" _href="http://www.infoq.com/resource/articles/jboss-seam/zh/resources/seam-book-toc.pdf"><u><font color=#4371a6>本书目录</font></u></a>来查看本书的所有主题。</p>
<p>请看Gavin King的两个访谈录来查看以往关于Seam的话题。</p>
<ul>
    <li>JBoss Seam 1.1 Indepth: An Interview with Gavin King
    <li>JBoss Seam 1.0: rethinking web application architecture </li>
</ul>
<h2>关于作者</h2>
<p>Dr. Michael Yuan是<a href="http://www.michaelyuan.com/seam/"><u><font color=#4371a6>JBoss Seam: Simplicity and Power Beyond Java EE 5.0</font></u></a>一书的作者。该书探讨了下一代web应用框架。他同时也是<a href="http://www.michaelyuan.com/blog/nokia-smartphone-hacks/"><u><font color=#4371a6>Nokia Smartphone Hacks</font></u></a>一书和其他三本技术读物的作者。Michael潜心研究轻量级企业web应用，终端对终端的移动应用开发。你可以通过他的博客联系他。</p>
<strong>查看英文原文：</strong><a href="http://www.infoq.com/articles/jboss-seam"><u><font color=#4371a6>Introduction to JBoss Seam</font></u></a>
<hr>
<strong>译者简介：</strong> 包亮，一名普通的程序员，喜欢敏捷实践，喜欢"懒惰"，减少重复，尽可能让工作变得简单。几年来，一直通过网络汲取知识，也希望通过网络将知识与人分享 。志愿参与InfoQ中文站内容建设，请邮件至<a onclick=createEmailAddress(this); href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#99;&#104;&#105;&#110;&#97;&#45;&#101;&#100;&#105;&#116;&#111;&#114;&#105;&#97;&#108;&#91;&#97;&#116;&#93;&#105;&#110;&#102;&#111;&#113;&#46;&#99;&#111;&#109;" name=china-editorial><u><font color=#4371a6>china-editorial@infoq.com</font></u></a>。
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/39929.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-19 14:15 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39929.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于jdbc和持久化访问数据库（摘录自《POJOs IN ACTION中文版：用轻量级框架开发企业应用》）</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39928.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Tue, 19 Feb 2008 06:13:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39928.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/39928.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39928.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/39928.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/39928.html</trackback:ping><description><![CDATA[<br><br>
<h3>2.4&nbsp; 决策3：访问数据库</h3>
<p class=POJO0 style="TEXT-INDENT: 19pt">无论怎样组织和封装业务逻辑，最终你必须从数据库存取数据。在标准J2EE应用程序里，你主要有两种选择：JDBC，这需要进行大量低层的编码；实体bean，难用而且缺少有分量的特性。相比之下，使用轻量级框架最令人兴奋的是，你可以选择新的更强大的方式访问数据库，能显著减少必须编写的数据库访问相关代码量。下面，让我们来具体分析一下。</p>
<h3 style="MARGIN-LEFT: 0cm">2.4.1&nbsp; 直接使用JDBC存在什么问题</h3>
<p class=POJO0 style="TEXT-INDENT: 19pt">近来，对象/关系型数据库映射框架（如JDO和Hibernate）和SQL映射框架（如iBATIS）的异军突起并非毫无根据。实际上，它们是Java社区反复受挫于JDBC的产物。为了理解新近框架产生的动因，让我们先探讨一下直接使用JDBC存在的问题。对多数应用程序来说，直接使用JDBC并非上佳选择，主要有如下3个原因。</p>
<p class=POJO4 style="MARGIN-TOP: 6pt">n&nbsp; 开发和维护SQL困难而且耗时——一些开发人员发现编写大型、复杂的SQL语句相当困难。为反映数据库模式的变化，及时更新SQL语句也可能相当耗时。你需要仔细权衡，为了使用JDBC，损失可维护性是否值得。</p>
<p class=POJO4 style="MARGIN-TOP: 6pt">n&nbsp; SQL缺少可移植性——由于常常需要使用数据库专有的SQL，应用程序如要处理多种数据库，你就必须编写多个版本的SQL语句，维护可能成为噩梦。即使实际应用中你</p>
<p class=POJO4 style="MARGIN-LEFT: 41.95pt; TEXT-INDENT: 0cm">的应用程序只用到一种数据库，但由于SQL缺少可移植性，有可能因此妨碍你使用更简单、更快捷的内存数据库，如对Hypersonic结构化查询语言数据库引擎（HSQLDB）进行测试。</p>
<p class=POJO4 style="MARGIN-TOP: 6pt">n&nbsp; 编写JDBC代码耗时而且容易出错——为获取连接、创建和初始化制备语句（Prepared Statement），并通过关闭连接和制备语句进行清理，你必须编写大量样板代码。你还必须编写代码实现Java对象和SQL语句之间的映射。JDBC代码编写起来枯燥无味，而且容易出错。</p>
<p class=POJO0 style="TEXT-INDENT: 19pt">如果你的应用程序必须直接执行SQL语句，那么前两个问题就不可避免。有时，为取得最佳性能，你必须用上SQL的十八般武艺，甚至包括厂商提供的专有特性。或者，出于各种业务上的原因，你的DBA可能要求完全控制应用程序执行的SQL语句，这样一来，你就无法使用那些即时（on the fly）生成SQL语句的持久层框架。通常，公司在其关系型数据库上的投入非常巨大，以致于与数据库协作的应用程序反倒显得不那么重要了。引用<em>i</em><em>BATIS in Action</em>作者的一段话，有时&#8220;数据库，甚至SQL本身的生命周期比应用程序源代码还长，甚至在应用程序经历了多个版本后，它们仍然健在。有些情况下，应用程序已经用另一种语言重新编写，而SQL和数据库却仍变化不大&#8221;。如果直接使用SQL把你搞得焦头烂额，算你走运，有个框架可以直接执行SQL，而且比JDBC更易使用。当然了，那就是iBATIS。</p>
<h3 style="MARGIN-LEFT: 0cm">2.4.2&nbsp; 使用iBATIS</h3>
<p class=POJO0 style="TEXT-INDENT: 19pt">我开发过的所有企业Java应用程序都直接执行SQL。早期的应用程序只使用SQL，后来则使用了持久层框架，并在一些组件里使用SQL。一开始，我使用普通的JDBC执行SQL语句，不过后来，我通常自己编写小型框架处理JDBC使用中比较枯燥的部分。Spring的JDBC类我也用过一段时间，它们可以消除大量样板代码。但是无论是我自己编写的框架还是Spring类，在将Java类映射成SQL语句时都存在问题，这正是我与iBATIS不期而遇时激动不已的原因。</p>
<p class=POJO0 style="TEXT-INDENT: 19pt">除了能让应用程序与连接和制备语句彻底隔绝外，iBATIS还能用XML描述符文件把JavaBean映射成SQL语句。它使用Java bean的内省机制将bean属性映射到制备语句占位符，并从ResultSet构建bean。iBATIS还支持数据库生成主键，自动加载相关对象，实现缓存及延迟加载。这样一来，</p>
<p class=POJO0 style="TEXT-INDENT: 0cm">iBATIS就消除了执行SQL语句带来的大量苦差事。在后面几章，包括第9章里，你会发现iBATIS可以显著简化执行SQL语句的那部分代码。你不必再编写大量低层JDBC代码，只需编写XML描述符文件，并调用一些iBATIS API即可。</p>
<h3 style="MARGIN-LEFT: 0cm">2.4.3&nbsp; 使用持久层框架</h3>
<p class=POJO0 style="TEXT-INDENT: 19pt">当然，iBATIS无法解决开发和维护SQL带来的开销，也不能弥补SQL缺少可移植性的不足。要避免这些问题，只有使用持久层框架，它可以将领域对象映射到数据库上。持久层框架提供创建、获取和删除对象的API。当应用程序游历对象之间的关系时，它能自动从数据库加载对象，并在事务结束时自动更新数据库。持久层框架通过对象/关系映射可以自动生成SQL，一般这种映射由XML文档指定，该文档定义怎样将类映射到表，属性映射到字段，以及怎样将关系映射成外键和连接表。</p>
<p class=POJO0 style="TEXT-INDENT: 19pt">EJB 2也有持久层框架的功能有限的形式：实体bean。不过，EJB 2实体bean的不足实在太多，并且开发和测试也极其枯燥乏味。因此，应该尽量少用EJB<sup> </sup>2实体bean。此外，正如我在第10章里描述的，目前还不确定EJB 3将解决多少不足。</p>
<p class=POJO0 style="TEXT-INDENT: 19pt">两种最流行轻量级持久层框架是Sun公司标准JDO[JSR12][JSR243]和开源项目Hibernate。两者都提供POJO类的透明持久化。你可以直接使用POJO类开发和测试自己的业务逻辑，不用担心持久化，然后把这些类映射到数据库模式。此外，这两种框架都可以在应用服务器里面和外面运行，从而进一步简化开发。用Hibernate和JDO进行开发比用旧式的EJB2的实体bean要舒服得多。</p>
<p class=POJO0 style="TEXT-INDENT: 19pt">本书有好几章描述怎样有效使用JDO和Hibernate。在第5章，你将学习如何使用JDO持久化领域模型。第6章则讨论如何使用Hibernate持久化领域模型。在第11章，你将学习如何使用JDO和Hibernate高效查询大型数据库及处理庞大的结果集。</p>
<p class=POJO0 style="TEXT-INDENT: 19pt">除了决定怎样访问数据库外，你还必须决定如何处理数据库并发。下面让我们分析一下并发处理为何重要，以及可用的选项。<br><br><br>原文：<a href="http://book.csdn.net/bookfiles/367/10036714013.shtml">http://book.csdn.net/bookfiles/367/10036714013.shtml</a></p>
<!-- page -->
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/39928.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-19 14:13 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39928.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring+Hibernate+Struts优势地位凸显</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39927.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Tue, 19 Feb 2008 05:35:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39927.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/39927.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39927.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/39927.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/39927.html</trackback:ping><description><![CDATA[<div class=searchhot>关键字： <a href="http://tech.ddvip.com/search.php?key=Struts+Spring+Hibernate" target=_blank><u><font color=#0000ff>Struts+Spring+Hibernate</font></u></a> <a href="http://tech.ddvip.com/search.php?key=Java对象持久化" target=_blank><u><font color=#0000ff>Java对象持久化</font></u></a> <a href="http://tech.ddvip.com/search.php?key=配置Hibernate" target=_blank><u><font color=#0000ff>配置Hibernate</font></u></a> <a href="http://tech.ddvip.com/search.php?key=" target=_blank></a><a href="http://tech.ddvip.com/search.php?key=MVC模式" target=_blank><u><font color=#0000ff>MVC模式</font></u></a> <a href="http://tech.ddvip.com/search.php?key=SAAJ" target=_blank><u><font color=#0000ff>SAAJ</font></u></a> </div>
<div class=article_z>
<h2>内容摘要：Java界的各种框架找到了自己应有的位置。Spring+Hibernate+Struts已成为Java开发的主流体系。在这个体系中，Spring+Hibernate的地位应该说短期内是难以撼动了。 </h2>
</div>
<div class=article_c id=fontsize>
<p>　　经过数年的&#8220;框架大战&#8221;，Java界的各种框架找到了自己应有的位置。Spring+Hibernate+Struts已成为Java开发的主流体系。在这个体系中，Spring+Hibernate的地位应该说短期内是难以撼动了。除了新兴的Jboss Seam作为挑战者之外，几乎难有劲敌。</p>
<p>　　Java B/S编程中历来战火最激烈的其实还在Web层，框架的数量最多，争议最大。一切由Struts而起，而Struts最终也坐稳了第一个时代的王座。在技术层面，Struts 1.x已经被无数人抱怨过、批评过，但终于还是稳坐王位，这充分说明了习惯的力量。&#8220;稳定压倒一切&#8221;，这句话在IT技术领域仍旧适用。</p>
<p>　　在2007年CSDN举办的调查中，我们详细的分析了Java开发框架的使用状况，发现主要使用的开发框架JSP占26%，Struts占21%，Hibernate占17%，Spring MVC占11%，EJB占7%，JSF占6%，Spring Web Flow和POJO各占4%，其它占4%。就这一调查数据，我们不难看出，Spring+Hibernate+Struts的优势地位还是相当的明显。</p>
<p>　　<img style="WIDTH: 550px" onclick=get_larger(this) alt=Spring+Hibernate+Struts优势地位凸显 src="http://img.ddvip.com/2007_08/1187942133_ddvip_9678.jpg"></p>
<p>　　Struts和Hibernate几乎已经成了JavaEE应用的常规配置，21%的开发者用到 Struts，用到Hibernate的开发者也有17%；在一个成熟的技术平台上，各个项目的技术方案会在很大程度上趋同——因为所有未知领域都已经被探明，各种问题都有对应的最佳实践，架构师们可以参考的成功案例越来越多。就拿 JavaEE来说，今天的架构师们需要考虑的问题比之三年前已经简单多了，这就是成熟的价值。</p>
<p>　　有专家评论：&#8220;其实IT应用技术，什么新鲜玩意并不难学，难的是标准化和规范化。每个程序员都有自己的思路和习惯，写出来的代码自然是五花八门。Java何以成为编程界的占重要地位，很重要的一点在于Java的规范化。这种规范化很高的语言适用于多人合作的大型项目，便于沟通和理解，也就便于集成和维护。</p>
<p>　　Java世界为什么会框架横飞，说到底还是规范化的需要。纯JSP和Struts写Web谁快，摆明了是JSP。那为什么用Struts？原因在于100个人写出来的 JSP，有100种写法；而100个人写出来的Struts，基本相似。Struts之成功，正缘于其在Java Web层的规范化方面所做出的贡献。</p>
<p>　　然而长江后浪推前浪，Struts 1.x的技术缺陷毕竟是隐患。Sun力推JSF，打算一雪Web层框架缺失之耻。JSF现在比较有优势的是对Ajax的集成，这一点走在了其他框架的前面。未来两年，JSF与Struts将展开Java Web框架的最终战争。&#8221;</p>
<p>　　JSP经过几年风雨洗礼依然把持头把交椅，看来所有的框架表示层都离不开JSP而存在，而作为JSP的手足兄弟JSF也是仅次Spring之后又一个后起之秀。JSF能否实现JSP的合理过渡我们还要侍目以待，JSF是否能够撼动Struts也是值得我们期待。</p>
</div>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/39927.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-19 13:35 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39927.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>