﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-花香蝶自来-随笔分类-Struts</title><link>http://www.blogjava.net/ltc603/category/14101.html</link><description>&lt;font size="3"&gt;学无止境&lt;/font&gt;
&lt;br&gt;

&lt;script type="text/javascript" src="http://wujunlove.googlepages.com/bigstaticeyes.js"&gt;&lt;/script&gt;</description><language>zh-cn</language><lastBuildDate>Tue, 10 Apr 2007 05:11:41 GMT</lastBuildDate><pubDate>Tue, 10 Apr 2007 05:11:41 GMT</pubDate><ttl>60</ttl><item><title>Web服务器开发环境下的线程安全问题</title><link>http://www.blogjava.net/ltc603/archive/2007/04/09/109490.html</link><dc:creator>阿成</dc:creator><author>阿成</author><pubDate>Mon, 09 Apr 2007 12:31:00 GMT</pubDate><guid>http://www.blogjava.net/ltc603/archive/2007/04/09/109490.html</guid><wfw:comment>http://www.blogjava.net/ltc603/comments/109490.html</wfw:comment><comments>http://www.blogjava.net/ltc603/archive/2007/04/09/109490.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ltc603/comments/commentRss/109490.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ltc603/services/trackbacks/109490.html</trackback:ping><description><![CDATA[<p>Servlet是在多线程环境下的。即可能有多个请求发给一个servelt实例，每个请求是一个线程。 <br>struts下的action也类似，同样在多线程环境下。可以参考struts user guide: http://struts.apache.org/struts-action/userGuide/building_controller.html 中的Action Class Design Guidelines一节: Write code for a multi-threaded environment - Our controller servlet creates only one instance of your Action class, and uses this one instance to service all requests. Thus, you need to write thread-safe Action classes. Follow the same guidelines you would use to write thread-safe Servlets. <br>译:为多线程环境编写代码。我们的controller servlet指挥创建你的Action 类的一个实例，用此实例来服务所有的请求。因此，你必须编写线程安全的Action类。遵循与写线程安全的servlet同样的方针。 <br><br>1.什么是线程安全的代码 <br>在多线程环境下能正确执行的代码就是线程安全的。 <br>安全的意思是能正确执行，否则后果是程序执行错误，可能出现各种异常情况。</p>
<p>2.如何编写线程安全的代码 <br>很多书籍里都详细讲解了如何这方面的问题，他们主要讲解的是如何同步线程对共享资源的使用的问题。主要是对synchronized关键字的各种用法，以及锁的概念。 <br>Java1.5中也提供了如读写锁这类的工具类。这些都需要较高的技巧，而且相对难于调试。 <br><br>但是，线程同步是不得以的方法,是比较复杂的,而且会带来性能的损失。等效的代码中，不需要同步在编写容易度和性能上会更好些。 <br>我这里强调的是什么代码是始终为线程安全的、是不需要同步的。如下: <br>1)常量始终是线程安全的，因为只存在读操作。 <br>2)对构造器的访问(new 操作)是线程安全的，因为每次都新建一个实例，不会访问共享的资源。 <br>3)最重要的是:局部变量是线程安全的。因为每执行一个方法，都会在独立的空间创建局部变量，它不是共享的资源。局部变量包括方法的参数变量。 <br>struts user guide里有： <br>Only Use Local Variables - The most important principle that aids in thread-safe coding is to use only local variables, not instance variables , in your Action class. <br>译:只使用用局部变量。--编写线程安全的代码最重要的原则就是，在Action类中只使用局部变量，不使用实例变量。</p>
<p><br>总结： <br>在Java的Web服务器环境下开发，要注意线程安全的问题。最简单的实现方式就是在Servlet和Struts Action里不要使用类变量、实例变量，但可以使用类常量和实例常量。 <br>如果有这些变量，可以将它们转换为方法的参数传入，以消除它们。 <br>注意一个容易混淆的地方：被Servlet或Action调用的类中(如值对象、领域模型类)中是否可以安全的使用实例变量？如果你在每次方法调用时 <br>新建一个对象，再调用它们的方法，则不存在同步问题---因为它们不是多个线程共享的资源，只有共享的资源才需要同步---而Servlet和Action的实例对于多个线程是共享的。 <br>换句话说，Servlet和Action的实例会被多个线程同时调用，而过了这一层,如果在你自己的代码中没有另外启动线程，且每次调用后续业务对象时都是先新建一个实例再调用，则都是线程安全的。 </p>
<img src ="http://www.blogjava.net/ltc603/aggbug/109490.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ltc603/" target="_blank">阿成</a> 2007-04-09 20:31 <a href="http://www.blogjava.net/ltc603/archive/2007/04/09/109490.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ActionServlet深入探讨</title><link>http://www.blogjava.net/ltc603/archive/2007/04/06/108859.html</link><dc:creator>阿成</dc:creator><author>阿成</author><pubDate>Fri, 06 Apr 2007 01:48:00 GMT</pubDate><guid>http://www.blogjava.net/ltc603/archive/2007/04/06/108859.html</guid><wfw:comment>http://www.blogjava.net/ltc603/comments/108859.html</wfw:comment><comments>http://www.blogjava.net/ltc603/archive/2007/04/06/108859.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ltc603/comments/commentRss/108859.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ltc603/services/trackbacks/108859.html</trackback:ping><description><![CDATA[<div>java.lang.Object<br>&nbsp;&nbsp;|<br>&nbsp;&nbsp;+--javax.servlet.GenericServlet<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+--javax.servlet.http.HttpServlet<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+--org.apache.struts.action.ActionServlet<br><br>Struts提供了一个缺省版本的ActionServlet类，你可以继承这个类，覆盖其中的一些方法来达到你的特殊处理的需要。ActionServlet继承与javax.servlet.http.HttpServlet，所以在本质上它和一个普通的servlet没有区别，你完全可以把它当做一个servlet来看待，只是在其中完成的功能不同罢了。ActionServlet主要完成如下功能：<br><br>将一个来自客户端的URI映射到一个相应的Action类<br>
<ul>
    <li>如果是这个Action类是第一次被调用，那么实例化一个并放入缓存<br>
    <li>如果在配置文件(struts-config.xml)中指定了相应的ActionForm，那么从Request中抓取数据填充FormBean<br>
    <li>调用这个Action类的perform()方法，传入ActionMapping的一个引用，对应的ActionForm、以及由容器传给ActionServlet的HttpServletRequest、HttpServletResponse对象。</li>
</ul>
<br><br>确省版本的ActionServlet会从配置文件web.xml中读取如下初始化参数：<br>
<ul>
    <li>application<br>应用使用的资源包(resources&nbsp;bundle)的基类<br>
    <li>factory<br>用于创建应用的MessageResources对象的MessageResourcesFactory的类名。确省是org.apache.struts.util.PropertyMessageResourcesFactory。<br>
    <li>config<br>Struts的配置文件，确省是/WEB-INF/struts-config.xml。注意这儿是与应用Context关联的相对路径。<br>
    <li>content<br>定义了确省的内容类型和编码格式，它会被自动地被设置到每个response中，如果JSP/Servlet中没有明确的设置。确省是text/html。<br>
    <li>debug<br>调试信息的级别。默认为0，比当前级别高的调试信息会被log到日志文件中。<br>
    <li>detail<br>与debug的作用类似，只是这个detail是initMapping()时专用的。调试信息会被打印到System.out，而不是日志文件。<br>
    <li>formBean<br>ActionFormBean的实现类，确省为org.apache.struts.action.ActionFormBean<br>
    <li>forward<br>应用中使用的ActionForward类，确省是org.apache.struts.action.ActionForward。<br>
    <li>locale<br>指定了确省使用的Locale对象。设为true，当得到一个session时，会自动在session中存储一个以Action.LOCALE_KEY标示的Locale对象，如果session中还没有与Action.LOCALE_KEY绑定的Locale对象。<br>
    <li>mapping<br>应用中使用的ActionMapping类，确省是org.apache.struts.action.ActionMapping。<br>
    <li>multipartClass<br>文件上传使用的MutipartRequestHandler的实现类。确省为org.apache.struts.upload.DiskMultipartRequestHandler<br>
    <li>nocache<br>如果设为true，那么ActionServlet会自动在每个到客户端的响应中添加nocache的HTML头，这样客户端就不会对应用中的页面进行缓存。确省为false<br>
    <li>null<br>如果设置为true，那么应用在得到一个未定义的message资源时，会返回null，而不是返回一个错误信息。确省是true。<br>
    <li>maxFileSize<br>文件上传的大小上限，确省为250M<br>
    <li>bufferSize<br>文件上传时的缓冲区的大小，确省为4M<br>
    <li>tempDir<br>设置用于上传时的临时目录。工作目录会作为一个Servlet环境（Context）的属性提供。<br>
    <li>validate<br>Are&nbsp;we&nbsp;using&nbsp;the&nbsp;new&nbsp;configuration&nbsp;file&nbsp;format?确省为true。<br>
    <li>validating</li>
</ul>
<br>在解析配置XML文件是是否进行有效性的验证。确省为true<br><br>ActionServlet中应用了命令设计模式。<br><br>一个Servlet在由容器生成时，首先会调用init()方法进行初始化，在接到一个HTTP请求时，调用相应的方法进行处理；比如GET请求调用doGet()方法，POST请求调用doPost()方法。所以首先看看ActionServlet的init()方法，你就会很清楚为什么ActionServlet可以完成这些功能了。<br>
<h3>init()</h3>
<br>在它的init()方法中，ActionServlet依次调用如下protected的方法完成初始化：<br>
<ul>
    <li>initActions()&nbsp;－&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;大家可能还曾有这个疑问：Struts为什么可以找到一个请求URI对应的action类呢？答案就在这儿，ActionServlet有一个actions属性，类型为org.apache.struts.util.FastHashMap，用于存储以类的全名为key的已实例化的Action类。在init()时首先调用的就是initActions()方法，在这个方法中只是简单的清除map中的所有的名值对，<br>
    <div class=codeStyle>
    <ol>
        <li>
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><font color=#0000ff>synchronized</font></strong>&nbsp;(actions)&nbsp;{
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;actions.setFast(<strong><font color=#0000ff>false</font></strong>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;actions.clear();
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;actions.setFast(<strong><font color=#0000ff>true</font></strong>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} </li>
    </ol>
    </div>
    <br>首先把actions设为slow模式，这时对FastHashMap的访问是线程同步的，然后清除actions中的所有的已存在的名/值对，最后再把actions的模式设为fast。由于FastHashMap是struts在java.util.HashMap的基础上的一个扩展类，是为了适应多线程、并且对HashMap的访问大部分是只读的特殊环境的需要。大家知道java.util.HashMap是非线程安全的，所以HashMap一般适用于单线程环境下。org.apache.struts.FastHashMap就是继承于java.util.HashMap，在其中添加多线程的支持产生的。在fast模式下的工作方式是这样的：读取是非线程同步的；写入时首先克隆当前map，然后在这个克隆上做写入操做，完成后用这个修改后的克隆版本替换原来的map。那么在什么时候会把Actions类添加到这个map中呢？我们已经提到了struts是动态的生成Action类的实例的，在每次ActionServlet接收到一个GET或POST的HTTP请求时，会在这个map中查找对应的Action类的实例，如果不存在，那么就实例化一个，并放入map中。可见这个actions属性起到了对Action类实例的缓存的作用。<br>
    <li>initInternal()&nbsp;－&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;初始化ActionServlet内部使用的资源包MessageResources，使用MessageResources.getMessageResources(internalName)得到&nbsp;&nbsp;&nbsp;&nbsp;internalName为"org.apache.struts.action.ActionResources"对应的ActionResources.properties文件。这个资源包主要用于ActionServlet处理过程中的用到的提示信息，这儿不展开讨论。<br>
    <li>initDebug()&nbsp;－&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;从web.xml中读取本应用的debug级别参数getServletConfig().getInitParameter("debug")，然后赋给debug属性。<br>
    <li>initApplication()－&nbsp;&nbsp;&nbsp;&nbsp;初始化应用资源包，并放置入ServletContext中。<br>
    <div class=codeStyle>
    <ol>
        <li>
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><a href="http://www.javaresearch.org/source/jdk142/java/lang/String.java.html" target=_blank><font class=classLink color=#0000ff><u>String</u></font></a></strong>&nbsp;factory&nbsp;=getServletConfig().getInitParameter(&#8220;factory&#8221;);&nbsp;&nbsp;&nbsp;&nbsp;
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><a href="http://www.javaresearch.org/source/jdk142/java/lang/String.java.html" target=_blank><font class=classLink color=#0000ff><u>String</u></font></a></strong>&nbsp;oldFacory&nbsp;=&nbsp;MessageResourcesFactory.getFactoryClass();
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><font color=#0000ff>if</font></strong>&nbsp;(factory&nbsp;!=<strong><font color=#0000ff>null</font></strong>)
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageResourcesFactory.setFactoryClass(factory);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><a href="http://www.javaresearch.org/source/jdk142/java/lang/String.java.html" target=_blank><font class=classLink color=#0000ff><u>String</u></font></a></strong>&nbsp;value&nbsp;=&nbsp;getServletConfig().getInitParameter(<font color=#ff33ff>"application"</font>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageResourcesFactory&nbsp;factoryObject&nbsp;=
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageResourcesFactory.createFactory();
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;application&nbsp;=&nbsp;factoryObject.createResources(value);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageResourcesFactory.setFactory(oldFactory);&nbsp;
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getServletContext().setAttribute(<font color=#ff0000>Action</font>.MESSAGES_KEY,&nbsp;application); </li>
    </ol>
    </div>
    <br>说明：文中引用的代码片断可能会省略了一些例外检查等非主线的内容，敬请注意。<br><br>首先从配置文件中读取factory参数，如果这个参数不为空，那么就在MessageResourcesFactory中使用这个指定的Factory类；否则，使用默认的工厂类org.apche.struts.util.PropertyMessageResourceFactory。然后调用MessageResourcesFactory的静态createFactory()方法，生成一个具体的MessageResourceFactory对象（注意：MessageResourcesFactory是抽象类）。这样就可以调用这个具体的MessageResourceFactory的createResource()方法得到配置文件(web.xml)中定义的资源文件了。<br>上面的application对象类型为MessageResources。在web.xml中在配置ActionServlet时可以指定一个特定的工厂类。不能直接MessageResourcesFactory的createResources()方法，因为这个方法是abstract的。创建factoryObject的过程如下：<br>
    <div class=codeStyle>
    <ol>
        <li>&nbsp;&nbsp;&nbsp;&nbsp;
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageResourceFactory&nbsp;factoryObject=
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageResourcesFactory.createFactory();
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;application&nbsp;=&nbsp;factoryObject.createResources(value); </li>
    </ol>
    </div>
    <br>&lt;li&gt;initMapping()&nbsp;－&nbsp;&nbsp;&nbsp;&nbsp;为应用初始化mapping信息ActionServlet有一个protected的属性：mapping，封装了一个ActionMapping的对象集合，以便于管理、查找ActionMapping。mappings是org.apache.struts.action.ActionMappings类的实例。主要有两个方法：addMapping(ActionMapping&nbsp;mapping)和findMapping(String&nbsp;path)。ActionMapping也是使用上面提到的org.apache.struts.util.FastHashMap类来存储所有的ActionMapping对象。<br>
    <div class=codeStyle>
    <ol>
        <li>
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mappings.setServlet(<strong><font color=#0000ff>this</font></strong>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8230;&#8230;
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em><font color=#339900>//&nbsp;Initialize&nbsp;the&nbsp;name&nbsp;of&nbsp;our&nbsp;ActionFormBean&nbsp;implementation&nbsp;class</font></em>
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;=&nbsp;getServletConfig().getInitParameter(<font color=#ff33ff>"formBean"</font>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><font color=#0000ff>if</font></strong>&nbsp;(value&nbsp;!=&nbsp;<strong><font color=#0000ff>null</font></strong>)
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;formBeanClass&nbsp;=&nbsp;value;
        <li>&nbsp;&nbsp;&nbsp;&nbsp;
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em><font color=#339900>//&nbsp;Initialize&nbsp;the&nbsp;name&nbsp;of&nbsp;our&nbsp;ActionForward&nbsp;implementation&nbsp;class</font></em>
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;=&nbsp;getServletConfig().getInitParameter(<font color=#ff33ff>"forward"</font>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><font color=#0000ff>if</font></strong>&nbsp;(value&nbsp;!=&nbsp;<strong><font color=#0000ff>null</font></strong>)
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;forwardClass&nbsp;=&nbsp;value;
        <li>
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em><font color=#339900>//&nbsp;Initialize&nbsp;the&nbsp;name&nbsp;of&nbsp;our&nbsp;ActionMapping&nbsp;implementation&nbsp;class</font></em>
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;=&nbsp;getServletConfig().getInitParameter(<font color=#ff33ff>"mapping"</font>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><font color=#0000ff>if</font></strong>&nbsp;(value&nbsp;!=&nbsp;<strong><font color=#0000ff>null</font></strong>)
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mappingClass&nbsp;=&nbsp;value; </li>
    </ol>
    </div>
    <br>在initMapping()中，首先链接mappings对象到本servlet实例。其实这句话的作用很简单，在ActionMappings中会有一个ActionServlet类型的属性，这个属性就界定了这个ActionMappings对象所属的ActionServlet。Struts的实现比较灵活，其中的ActionFormBean、ActionForward、ActionMapping类你完全可以使用自己实现的子类，来定制Struts的工作方式。上面的代码就从配置文件（web.xml）中读取formBean、forward、mapping参数，这些参数就是你定制的ActionFormBean、ActionForward、ActionMapping类名。<br>
    <div class=codeStyle>
    <ol>
        <li>
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em><font color=#339900>//&nbsp;Initialize&nbsp;the&nbsp;context-relative&nbsp;path&nbsp;to&nbsp;our&nbsp;configuration&nbsp;resources</font></em>
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value&nbsp;=&nbsp;getServletConfig().getInitParameter(<font color=#ff33ff>"config"</font>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><font color=#0000ff>if</font></strong>&nbsp;(value&nbsp;!=&nbsp;<strong><font color=#0000ff>null</font></strong>)
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;config&nbsp;=&nbsp;value;
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<em><font color=#339900>//&nbsp;Acquire&nbsp;an&nbsp;input&nbsp;stream&nbsp;to&nbsp;our&nbsp;configuration&nbsp;resource</font></em>
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color=#ff0000>InputStream</font>&nbsp;input&nbsp;=&nbsp;getServletContext().getResourceAsStream(config);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Digester&nbsp;digester&nbsp;=&nbsp;<strong><font color=#0000ff>null</font></strong>;
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digester&nbsp;=&nbsp;initDigester(detail);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><font color=#0000ff>try</font></strong>&nbsp;{
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;formBeans.setFast(<strong><font color=#0000ff>false</font></strong>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;forwards.setFast(<strong><font color=#0000ff>false</font></strong>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mappings.setFast(<strong><font color=#0000ff>false</font></strong>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digester.parse(input);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mappings.setFast(<strong><font color=#0000ff>true</font></strong>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;forwards.setFast(<strong><font color=#0000ff>true</font></strong>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;formBeans.setFast(<strong><font color=#0000ff>true</font></strong>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<strong><font color=#0000ff>catch</font></strong>&nbsp;(<font color=#ff0000>SAXException</font>&nbsp;e)&nbsp;{
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong><font color=#0000ff>throw</font></strong>&nbsp;<strong><font color=#0000ff>new</font></strong>&nbsp;ServletException
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(internal.getMessage(<font color=#ff33ff>"configParse"</font>,&nbsp;config),&nbsp;e);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<strong><font color=#0000ff>finally</font></strong>&nbsp;{
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;input.close();
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} </li>
    </ol>
    </div>
    <br>从web.xml读取Struts的配置文件的位置。使用org.apache.struts.digester.Digester解析config参数标示的配置文件，通常为&#8220;/WEB-INF/struts-config.xml&#8221;，解析出所有的data-source、form-bean、action-mapping、forward。从上面的程序片断看到，Digester仅仅调用了一个parse()方法，那么，Digester是怎样把解析struts-config.xml文件并把解析的结果form-bean等信息存储到属性变量formBeans等中的呢？你可以注意到在调用digester.parse(InputStream)之前，首先调用了initDigester()方法：<br>
    <div class=codeStyle>
    <ol>
        <li>
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Digester&nbsp;digester&nbsp;=&nbsp;<strong><font color=#0000ff>new</font></strong>&nbsp;Digester();
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digester.push(<strong><font color=#0000ff>this</font></strong>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digester.addObjectCreate(<font color=#ff33ff>"struts-config/action-mappings/action"</font>,
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mappingClass,&nbsp;<font color=#ff33ff>"className"</font>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digester.addSetProperties(<font color=#ff33ff>"struts-config/action-mappings/action"</font>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digester.addSetNext(<font color=#ff33ff>"struts-config/action-mappings/action"</font>,
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color=#ff33ff>"addMapping"</font>,
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color=#ff33ff>"org.apache.struts.action.ActionMapping"</font>);
        <li>
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digester.addSetProperty
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(<font color=#ff33ff>"struts-config/action-mappings/action/set-property"</font>,
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color=#ff33ff>"property"</font>,&nbsp;<font color=#ff33ff>"value"</font>); </li>
    </ol>
    </div>
    <br>在这个方法中首先生成一个Digester对象，然后设置解析的规则和回调，如果你对XML、SAX不是很熟，这儿不必纠缠太深。要注意的是addSetNext()方法，设置了每一个要解析元素的Set&nbsp;Next回调方法，而这个方法就是由digester解析器的父提供的。上面的片断中的&#8220;addMapping&#8221;就是ActionServlet本身定义的一个方法，将由Digester回调。Digester就是籍此把解析出的每一个FormBean、ActionForward、ActionMapping等存储到属性变量formBeans、forwards、mappings等中的。<br>
    <li>initUpload()&nbsp;－&nbsp;&nbsp;&nbsp;&nbsp;初始化有关Upload的一些参数，比如：bufferSize、tempDir。<br>
    <li>initDataSource()&nbsp;－取出在initMapping()中从配置文件中读取的每一个DataSource，设置LogWriter，如果为GenericDataSource的实例，则打开数据源。然后，把每个dataSource放入Context中。<br>dataSource.setLogWriter(scw)；<br>((GenericDataSource)dataSource).open();<br>getServletContext().setAttribute(key,dataSource);<br>
    <li>initOther()&nbsp;－&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;设置其它尚未初始化的的参数（content、locale、nocache），并发布formBeans、forwards、mappings到Context：<br>getServletContext().setAttribute(Action.FORM_BEANS_KEY,&nbsp;formBeans);<br>getServletContext().setAttribute(Action.FORWARDS_KEY,&nbsp;forwards);<br>getServletContext().setAttribute(Action.MAPPINGS_KEY,&nbsp;mappings);<br>
    <li>initServlet()&nbsp;－&nbsp;&nbsp;&nbsp;&nbsp;初始化Controller&nbsp;Servlet的Servlet&nbsp;Mapping。这儿也使用了Digester工具，扫描web.xml所有的&lt;web-app/servlet-mapping&gt;，寻找servlet-name与当前Servlet相同的mapping，置入Context。代码如下；<br>
    <div class=codeStyle>
    <ol>
        <li>
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Digester&nbsp;digester&nbsp;=&nbsp;<strong><font color=#0000ff>new</font></strong>&nbsp;Digester();
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digester.push(<strong><font color=#0000ff>this</font></strong>);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digester.setDebug(debug);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digester.setValidating(validating);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digester.addCallMethod(&#8220;web-appservlet-mapping&#8221;,&#8220;addServletMapping&#8221;,&nbsp;2);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digester.addCallParm(&#8220;web-appservlet-mappingservlet-name&#8221;,&nbsp;0);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digester.addCallParm(&#8220;web-appservlet-mappingurl-pattern&#8221;,&nbsp;1);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font color=#ff0000>InputStream</font>&nbsp;is&nbsp;=&nbsp;getServletContext().getResourceAsStream(&#8220;/WEB-INFweb.xml&#8221;);
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digester.parse(is);&nbsp;
        <li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getServletContext().setAttribute(<font color=#ff0000>Action</font>.SERVLET_KEY,servletMapping); </li>
    </ol>
    </div>
    </li>
</ul>
</div>
<img src ="http://www.blogjava.net/ltc603/aggbug/108859.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ltc603/" target="_blank">阿成</a> 2007-04-06 09:48 <a href="http://www.blogjava.net/ltc603/archive/2007/04/06/108859.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>request.getSession() </title><link>http://www.blogjava.net/ltc603/archive/2006/09/01/67089.html</link><dc:creator>阿成</dc:creator><author>阿成</author><pubDate>Fri, 01 Sep 2006 05:59:00 GMT</pubDate><guid>http://www.blogjava.net/ltc603/archive/2006/09/01/67089.html</guid><wfw:comment>http://www.blogjava.net/ltc603/comments/67089.html</wfw:comment><comments>http://www.blogjava.net/ltc603/archive/2006/09/01/67089.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ltc603/comments/commentRss/67089.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ltc603/services/trackbacks/67089.html</trackback:ping><description><![CDATA[request.getSession() will return the current session and if one does not exist, a new session will be cretaed.<br /><br />request.getSession(true) will return the current session if one exists, if one doesn't exits a new one will be created.<br /><br />So there is actually no difference between the two methods.<br /> <br />HOWEVER, if you use request.getSession(false), it will return the current session if one exists and if one DOES NOT exist a new one will NOT be cretaed. <img src ="http://www.blogjava.net/ltc603/aggbug/67089.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ltc603/" target="_blank">阿成</a> 2006-09-01 13:59 <a href="http://www.blogjava.net/ltc603/archive/2006/09/01/67089.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts加载spring的问题－zt</title><link>http://www.blogjava.net/ltc603/archive/2006/08/22/65104.html</link><dc:creator>阿成</dc:creator><author>阿成</author><pubDate>Tue, 22 Aug 2006 08:14:00 GMT</pubDate><guid>http://www.blogjava.net/ltc603/archive/2006/08/22/65104.html</guid><wfw:comment>http://www.blogjava.net/ltc603/comments/65104.html</wfw:comment><comments>http://www.blogjava.net/ltc603/archive/2006/08/22/65104.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ltc603/comments/commentRss/65104.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ltc603/services/trackbacks/65104.html</trackback:ping><description><![CDATA[
		<p>前几天不是一个同事使用OpenSessionInView pattern时,遇到Hibernate 3的mappinglazy="true"的问题,也不会想到它<br />struts启动spring的WebApplicationContext<br />spring有三种启动方式,使用ContextLoaderServlet,ContextLoaderListener和ContextLoaderPlugIn.<br />看一下ContextLoaderListener的源码,这是一个ServletContextListener<br />/**<br />  * Initialize the root web application context.<br />  */<br /> public void contextInitialized(ServletContextEvent event) {<br />  this.contextLoader = createContextLoader();<br />  this.contextLoader.initWebApplicationContext(event.getServletContext());<br /> }<br /> <br />  /**<br />  * Create the ContextLoader to use. Can be overridden in subclasses.<br />  * @return the new ContextLoader<br />  */<br /> protected ContextLoader createContextLoader() {<br />  return new ContextLoader();<br /> }<br /> contextLoader的源码<br /> public WebApplicationContext initWebApplicationContext(ServletContext servletContext)<br />   throws BeansException {</p>
		<p>  long startTime = System.currentTimeMillis();<br />  if (logger.isInfoEnabled()) {<br />   logger.info("Root WebApplicationContext: initialization started");<br />  }<br />  servletContext.log("Loading Spring root WebApplicationContext");</p>
		<p>  try {<br />   // Determine parent for root web application context, if any.<br />   ApplicationContext parent = loadParentContext(servletContext);</p>
		<p>   WebApplicationContext wac = createWebApplicationContext(servletContext, parent);<br />   servletContext.setAttribute(<br />     WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, wac);</p>
		<p>   if (logger.isInfoEnabled()) {<br />    logger.info("Using context class [" + wac.getClass().getName() +<br />      "] for root WebApplicationContext");<br />   }<br />   if (logger.isDebugEnabled()) {<br />    logger.debug("Published root WebApplicationContext [" + wac +<br />      "] as ServletContext attribute with name [" +<br />      WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]");<br />   }</p>
		<p>   if (logger.isInfoEnabled()) {<br />    long elapsedTime = System.currentTimeMillis() - startTime;<br />    logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms");<br />   }</p>
		<p>   return wac;<br />  }<br />  catch (RuntimeException ex) {<br />   logger.error("Context initialization failed", ex);<br />   servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);<br />   throw ex;<br />  }<br />  catch (Error err) {<br />   logger.error("Context initialization failed", err);<br />   servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err);<br />   throw err;<br />  }<br /> }<br /> 注意WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,这里面放了WebApplicationContext,需要使用时从ServletContext取出<br /> 可以使用WebApplicationContextUtils得到WebApplicationContext<br /> public static WebApplicationContext getWebApplicationContext(ServletContext sc) {<br />  Object attr = sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);<br />  if (attr == null) {<br />   return null;<br />  }<br />  if (attr instanceof RuntimeException) {<br />   throw (RuntimeException) attr;<br />  }<br />  if (attr instanceof Error) {<br />   throw (Error) attr;<br />  }<br />  if (!(attr instanceof WebApplicationContext)) {<br />   throw new IllegalStateException("Root context attribute is not of type WebApplicationContext: " + attr);<br />  }<br />  return (WebApplicationContext) attr;<br /> }<br /> 关键的问题在于struts如何启动的spring的,ContextLoaderPlugIn的源码<br /> <br /> // Publish the context as a servlet context attribute.<br />  String attrName = getServletContextAttributeName();<br />  getServletContext().setAttribute(attrName, wac);<br /> <br /> public String getServletContextAttributeName() {<br />  return SERVLET_CONTEXT_PREFIX + getModulePrefix();<br /> }<br /> 不同加载的Key竟然不同,原因就是WebApplicationContext放在那里的问题,可spring调用的时候会根据WebApplicationContext里面定义的那个名字去找的,问题出在这里</p>
		<p>
				<br /> 在struts-config.xml中配置<br />    &lt;plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"&gt;<br />      &lt;set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml" /&gt;<br />    &lt;/plug-in&gt;</p>
		<p>    &lt;controller&gt;<br />        &lt;set-property property="processorClass" value="org.springframework.web.struts.DelegatingRequestProcessor" /&gt;<br />    &lt;/controller&gt;<br /> 原理是这样的,Struts虽然只能有一个ActionServlet实例,但是对于不同的子应用分别能有自己的RequestProcessor实例每个RequestProcessor实例分别对应不同的struts配置文件。<br />   子应用的ProcessorClass类必须重写一般就是继承RequestProcessor类，然后再其配置文件的controller元素中的&lt;processorClass&gt;属性中作出修改。那么当<br />  getRequestProcessor(getModuleConfig(request)).process(request,response);就能根据request选择相应的moduleconfig,再根据其&lt;processorClass&gt;属性选择相应的RequestProcessor子类来处理相应的请求了。</p>
<img src ="http://www.blogjava.net/ltc603/aggbug/65104.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ltc603/" target="_blank">阿成</a> 2006-08-22 16:14 <a href="http://www.blogjava.net/ltc603/archive/2006/08/22/65104.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>让你的struts能处理日期类型</title><link>http://www.blogjava.net/ltc603/archive/2006/08/21/64812.html</link><dc:creator>阿成</dc:creator><author>阿成</author><pubDate>Mon, 21 Aug 2006 08:02:00 GMT</pubDate><guid>http://www.blogjava.net/ltc603/archive/2006/08/21/64812.html</guid><wfw:comment>http://www.blogjava.net/ltc603/comments/64812.html</wfw:comment><comments>http://www.blogjava.net/ltc603/archive/2006/08/21/64812.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ltc603/comments/commentRss/64812.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ltc603/services/trackbacks/64812.html</trackback:ping><description><![CDATA[
		<span id="ArticleContent1_ArticleContent1_lblContent">
				<font size="4">
						<font color="#a52a2a">struts使用日期包括将string自动转化为日期fill到form中，以及将form中的日期按照指定格式显示在html的textfield中。首先讲第一种情况的解决方法：<br /><br />创建如下类：<br /><br /><b>import</b> java.util.*;<br /><b>import</b> org.apache.commons.beanutils.*;<br /><b>import</b> java.text.SimpleDateFormat;<br /><br /><b>public</b> <b>class</b> DateConvert <b>implements</b> Converter<br />{<br />  <b>static</b> SimpleDateFormat df = <b>new</b> SimpleDateFormat("yyyy/MM/dd");<br />  <b>public</b> DateConvert()<br />  {<br /><br />  }<br />  <b>public</b> Object convert(Class type, Object value)<br />  {<br />    <br />    <b>if</b>(value==null)<b>return</b> null;<br />    <b>if</b>(((String)value).trim().length()==0) <b>return</b> null;<br /><br />    <b>if</b>(value <b>instanceof</b> String)<br />    {<br />      <b>try</b><br />      {<br />        <b>return</b> df.parse((String)value);<br />      }<br />      <b>catch</b> (Exception ex)<br />      {<br />        <b>throw</b> <b>new</b> ConversionException("输入的日期类型不合乎yyyy/MM/dd"<br />          + value.getClass());<br />      }<br /><br />    }<br />    <b>else</b><br />    {<br />      <b>throw</b> <b>new</b> ConversionException("输入的不是字符类型"+value.getClass());<br />    }<br /><br />  }<br />}<br /><br />然后在你的系统某出使用如下（如web的init方法）<br />ConvertUtils.register(new DateConvert(),java.util.Date.class);<br />参数用于表示DateConvert类负责处理java.util.Date类型的转化<br /><br />第二种情况是如何显示form中日期类型到html:text中，我用的办法是修改struts的代码，重新生成一个新的struts.jar<br />org.apache.struts.taglib.html.BaseFieldTag的doStartTag的方法<br />找到 if (value != null) {results.append(ResponseUtils.filter(value))代码行下面的内容，需要修改此处代码，以便输出日期类型<br />如下：<br /><b>if</b> (value != null) {<br />            results.append(ResponseUtils.filter(value));<br />        } <b>else</b> <b>if</b> (redisplay || !"password".equals(type)) {<br />            Object value = RequestUtils.lookup(pageContext, name, property, null);<br />            <i>//System.out.println("lijz "+value);</i></font>
						<br />
				</font>
				<font size="4">
						<font color="#a52a2a">            <b>if</b>(value <b>instanceof</b> java.util.Date)<br />            {<br />               <i>//System.out.println("date="+value);</i></font>
						<br />
				</font>
				<font size="4">
						<font color="#a52a2a">               <b>if</b> (value == null)<br />                   value = "";<br />        <b>else</b><br />        {<br />          java.util.Date d= (java.util.Date)value;<br />          <b>try</b><br />           {<br /><br />            results.append(ResponseUtils.filter(df.format(d)));<br />          }<br />          <b>catch</b>(Exception ex)<br />          {<br />            System.out.println("form error:"+ex.getMessage());<br />          }<br />          }<br />            }<br />           <b>else</b><br />           {<br />               <b>if</b> (value == null)<br />                value = "";<br />                results.append(ResponseUtils.filter(value.toString()));<br />           }<br />           <br />       }<br />        results.append("\"");<br />        results.append(prepareEventHandlers());<br />        results.append(prepareStyles());<br />        results.append(getElementClose());<br /><br />        <i>// Print this field to our output writer</i></font>
						<br />
				</font>
				<font size="4">
						<font color="#a52a2a">        ResponseUtils.write(pageContext, results.toString());<br /><br />        <i>// Continue processing this page</i></font>
						<br />
				</font>
				<font color="#a52a2a" size="4">        <b>return</b> (EVAL_BODY_TAG);      <br /> <br /> 重新编译struts成struts.jar.放到你需要的项目中 <br /><br /><strong><font color="#000000">作者Blog：</font></strong><a id="ArticleContent1_ArticleContent1_AuthorBlogLink" href="http://blog.csdn.net/chensheng913/" target="_blank">http://blog.csdn.net/chensheng913/</a></font>
		</span>
<img src ="http://www.blogjava.net/ltc603/aggbug/64812.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ltc603/" target="_blank">阿成</a> 2006-08-21 16:02 <a href="http://www.blogjava.net/ltc603/archive/2006/08/21/64812.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts 表单验证流程－孙卫琴</title><link>http://www.blogjava.net/ltc603/archive/2006/08/17/64202.html</link><dc:creator>阿成</dc:creator><author>阿成</author><pubDate>Thu, 17 Aug 2006 12:22:00 GMT</pubDate><guid>http://www.blogjava.net/ltc603/archive/2006/08/17/64202.html</guid><wfw:comment>http://www.blogjava.net/ltc603/comments/64202.html</wfw:comment><comments>http://www.blogjava.net/ltc603/archive/2006/08/17/64202.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ltc603/comments/commentRss/64202.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ltc603/services/trackbacks/64202.html</trackback:ping><description><![CDATA[
		<span style="FONT-FAMILY: 方正小标宋简体">
				<strong>一、表单验证的流程</strong>
		</span>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">在</span>
				<span lang="EN-US">hello.jsp</span>
				<span style="FONT-FAMILY: 宋体">网页上，不输入姓名，直接单击【</span>
				<span lang="EN-US">Submit</span>
				<span style="FONT-FAMILY: 宋体">】</span>
				<span style="FONT-FAMILY: 宋体">按钮，会看到如图</span>
				<span lang="EN-US">2-6</span>
				<span style="FONT-FAMILY: 宋体">所示的网页。</span>
		</p>
		<p class="a" align="center">
				<span lang="EN-US">
						<img height="160" src="http://act.it.sohu.com/book/data/book/78/278/02.files/image010.jpg" width="355" border="0" />
				</span>
		</p>
		<p class="a0" align="center">
				<span style="FONT-FAMILY: 宋体">图</span>
				<span lang="EN-US">2-6  </span>
				<span style="FONT-FAMILY: 宋体">表单验证失败的</span>
				<span lang="EN-US">hello.jsp</span>
				<span style="FONT-FAMILY: 宋体">网页</span>
		</p>
		<p class="a9">
				<span style="FONT-FAMILY: 宋体">当客户提交</span>
				<span lang="EN-US">HelloForm</span>
				<span style="FONT-FAMILY: 宋体">表单时，</span>
				<span style="FONT-FAMILY: 宋体">请求路径为</span>
				<span style="FONT-FAMILY: 宋体">“</span>
				<span lang="EN-US">/HelloWorld.do</span>
				<span style="FONT-FAMILY: 宋体">”：</span>
		</p>
		<p class="a5">
				<span lang="EN-US">&lt;html:form <b>action="/HelloWorld.do"</b> focus="userName" &gt;</span>
		</p>
		<p class="a6">
				<span style="FONT-FAMILY: 宋体">服务器端执行表单验证流程如下。</span>
		</p>
		<h4 style="TEXT-INDENT: 0cm">
				<span lang="EN-US">
						<img height="40" src="http://act.it.sohu.com/book/data/book/78/278/02.files/image008.jpg" width="76" border="0" />
				</span>
		</h4>
		<p class="a9">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">1</span>
				<span style="FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US">Servlet</span>
				<span style="FONT-FAMILY: 宋体">容器在</span>
				<span lang="EN-US">web.xml</span>
				<span style="FONT-FAMILY: 宋体">文件中寻找</span>
				<span lang="EN-US">&lt;url-pattern&gt;</span>
				<span style="FONT-FAMILY: 宋体">属性为“</span>
				<span lang="EN-US">*.do</span>
				<span style="FONT-FAMILY: 宋体">”的</span>
				<span lang="EN-US">&lt;servlet-mapping&gt;</span>
				<span style="FONT-FAMILY: 宋体">元素：</span>
		</p>
		<p class="a5">
				<span lang="EN-US">&lt;servlet-mapping&gt;</span>
		</p>
		<p class="a5" style="MARGIN-LEFT: 31.5pt">
				<span lang="EN-US">&lt;servlet-name&gt;action&lt;/servlet-name&gt;</span>
		</p>
		<p class="a5" style="MARGIN-LEFT: 31.5pt">
				<b>
						<span lang="EN-US">&lt;url-pattern&gt;*.do&lt;/url-pattern&gt;</span>
				</b>
		</p>
		<p class="a5">
				<span lang="EN-US">&lt;/servlet-mapping&gt;</span>
		</p>
		<p class="aa">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">2</span>
				<span style="FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US">Servlet</span>
				<span style="FONT-FAMILY: 宋体">容器依据以上</span>
				<span lang="EN-US">&lt;servlet-mapping&gt;</span>
				<span style="FONT-FAMILY: 宋体">元素的</span>
				<span lang="EN-US">&lt;servlet-name&gt;</span>
				<span style="FONT-FAMILY: 宋体">属性“</span>
				<span lang="EN-US">action</span>
				<span style="FONT-FAMILY: 宋体">”，在</span>
				<span lang="EN-US">web.xml</span>
				<span style="FONT-FAMILY: 宋体">文件中寻找匹配的</span>
				<span lang="EN-US">&lt;servlet&gt;</span>
				<span style="FONT-FAMILY: 宋体">元素：</span>
		</p>
		<p class="a5">
				<span lang="EN-US">&lt;servlet&gt;</span>
		</p>
		<p class="a5" style="MARGIN-LEFT: 31.5pt">
				<b>
						<span lang="EN-US">&lt;servlet-name&gt;action&lt;/servlet-name&gt;</span>
				</b>
		</p>
		<p class="a5" style="MARGIN-LEFT: 31.5pt">
				<span lang="EN-US">&lt;servlet-class&gt;org.apache.struts.action.ActionServlet&lt;/servlet-class&gt;</span>
		</p>
		<p class="a5">
				<span lang="EN-US">&lt;/servlet&gt;</span>
		</p>
		<p class="aa">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">3</span>
				<span style="FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US">Servlet</span>
				<span style="FONT-FAMILY: 宋体">容器把请求转发给以上</span>
				<span lang="EN-US">&lt;servlet&gt;</span>
				<span style="FONT-FAMILY: 宋体">元素指定的</span>
				<span lang="EN-US">ActionServlet</span>
				<span style="FONT-FAMILY: 宋体">，</span>
				<span lang="EN-US">ActionServlet</span>
				<span style="FONT-FAMILY: 宋体">依据用户请求路径</span>
				<span style="FONT-FAMILY: 宋体">“</span>
				<span lang="EN-US">/HelloWorld.do</span>
				<span style="FONT-FAMILY: 宋体">”，</span>
				<span style="FONT-FAMILY: 宋体">在</span>
				<span lang="EN-US">Struts</span>
				<span style="FONT-FAMILY: 宋体">配置文件中检索</span>
				<span lang="EN-US">path</span>
				<span style="FONT-FAMILY: 宋体">属性为</span>
				<span style="FONT-FAMILY: 宋体">“</span>
				<span lang="EN-US">/HelloWorld</span>
				<span style="FONT-FAMILY: 宋体">”</span>
				<span style="FONT-FAMILY: 宋体">的</span>
				<span lang="EN-US">&lt;action&gt;</span>
				<span style="FONT-FAMILY: 宋体">元素</span>
				<span style="FONT-FAMILY: 宋体">：</span>
		</p>
		<p class="a5">
				<span lang="EN-US">&lt;action    <b>path      = "/HelloWorld"</b></span>
		</p>
		<p class="a5">
				<span lang="EN-US">          type      = "hello.HelloAction"</span>
		</p>
		<p class="a5">
				<span lang="EN-US">          name      = "HelloForm"</span>
		</p>
		<p class="a5">
				<span lang="EN-US">          scope     = "request"</span>
		</p>
		<p class="a5">
				<span lang="EN-US">          validate  = "true"</span>
		</p>
		<p class="a5">
				<span lang="EN-US">          input     = "/hello.jsp"</span>
		</p>
		<p class="a5">
				<span lang="EN-US"> &gt;</span>
		</p>
		<p class="a5">
				<span lang="EN-US">        &lt;forward name="SayHello" path="/hello.jsp" /&gt;</span>
		</p>
		<p class="a5">
				<span lang="EN-US"> </span>&lt;/action&gt;</p>
		<p class="a5">
				<span lang="EN-US">
				</span> </p>
		<table class="MsoNormalTable" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; MARGIN-LEFT: 5.4pt; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellspacing="0" cellpadding="0" border="1">
				<tbody>
						<tr style="HEIGHT: 43.4pt">
								<td style="BORDER-RIGHT: medium none; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; WIDTH: 63pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 43.4pt" valign="top" width="84">
										<p class="MsoNormal" style="MARGIN-TOP: 6pt; TEXT-INDENT: 0cm">
												<span lang="EN-US">
														<img height="40" src="http://act.it.sohu.com/book/data/book/78/278/02.files/image003.jpg" width="57" border="0" />
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: medium none; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; WIDTH: 346.5pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 43.4pt" width="462">
										<p class="a7">
												<strong>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">更确切地说，</span>
														<span lang="EN-US" style="COLOR: black">ActionServlet</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">此时检索的是</span>
														<span lang="EN-US" style="COLOR: black">ActionMapping</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">对象，而不是直接访问</span>
														<span lang="EN-US" style="COLOR: black">Struts</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">配置文件中的</span>
														<span lang="EN-US" style="COLOR: black">&lt;action&gt;</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">元素。因为</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">在</span>
														<span lang="EN-US" style="COLOR: black">ActionServlet</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">初始化的时候，会加载</span>
														<span lang="EN-US" style="COLOR: black">Struts</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">配置文件，把各种配置信息保存在相应的配置类的实例中，例如</span>
														<span lang="EN-US" style="COLOR: black">&lt;action&gt;</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">元素的配置信息存放在</span>
														<span lang="EN-US" style="COLOR: black">ActionMapping</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">对象中。</span>
												</strong>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />
		<p class="a6">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">4</span>
				<span style="FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US">ActionServlet</span>
				<span style="FONT-FAMILY: 宋体">根据</span>
				<span lang="EN-US">&lt;action&gt;</span>
				<span style="FONT-FAMILY: 宋体">元素的</span>
				<span lang="EN-US">name</span>
				<span style="FONT-FAMILY: 宋体">属性，创建一个</span>
				<span lang="EN-US">HelloForm</span>
				<span style="FONT-FAMILY: 宋体">对象，把客户提交的表单数据传给</span>
				<span lang="EN-US">HelloForm</span>
				<span style="FONT-FAMILY: 宋体">对象，再把</span>
				<span lang="EN-US">HelloForm</span>
				<span style="FONT-FAMILY: 宋体">对象保存在</span>
				<span lang="EN-US">&lt;action&gt;</span>
				<span style="FONT-FAMILY: 宋体">元素的</span>
				<span lang="EN-US">scope</span>
				<span style="FONT-FAMILY: 宋体">属性指定的</span>
				<span lang="EN-US">request</span>
				<span style="FONT-FAMILY: 宋体">范围内。</span>
		</p>
		<p class="a9">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">5</span>
				<span style="FONT-FAMILY: 宋体">）由于</span>
				<span lang="EN-US">&lt;action&gt;</span>
				<span style="FONT-FAMILY: 宋体">元素的</span>
				<span lang="EN-US">validate</span>
				<span style="FONT-FAMILY: 宋体">属性为</span>
				<span lang="EN-US">true</span>
				<span style="FONT-FAMILY: 宋体">，</span>
				<span lang="EN-US">ActionServlet</span>
				<span style="FONT-FAMILY: 宋体">调用</span>
				<span lang="EN-US">HelloForm</span>
				<span style="FONT-FAMILY: 宋体">对象的</span>
				<span lang="EN-US">validate()</span>
				<span style="FONT-FAMILY: 宋体">方法执行表单验证：</span>
		</p>
		<p class="a5">
				<span lang="EN-US">public ActionErrors validate(ActionMapping mapping,</span>
		</p>
		<p class="a5">
				<span lang="EN-US">                                 HttpServletRequest request) {</span>
		</p>
		<p class="a5">
				<span lang="EN-US">            ActionErrors errors = new ActionErrors();</span>
		</p>
		<p class="a5">
				<span lang="EN-US">            if ((userName == null) || (userName.length() &lt; 1))</span>
		</p>
		<p class="a5">
				<span lang="EN-US">            errors.add("username", new ActionMessage("hello.no.username.error"));</span>
		</p>
		<p class="a5">
				<span lang="EN-US">            return errors;</span>
		</p>
		<p class="a5">
				<span lang="EN-US">}</span>
		</p>
		<p class="aa">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">6</span>
				<span style="FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US">HelloForm</span>
				<span style="FONT-FAMILY: 宋体">对象的</span>
				<span lang="EN-US">validate()</span>
				<span style="FONT-FAMILY: 宋体">方法返回一个</span>
				<span lang="EN-US">ActionErrors</span>
				<span style="FONT-FAMILY: 宋体">对象，里面包含一个</span>
				<span lang="EN-US">ActionMessage</span>
				<span style="FONT-FAMILY: 宋体">对象，这个</span>
				<span lang="EN-US">ActionMessage</span>
				<span style="FONT-FAMILY: 宋体">对象中封装了错误消息，消息</span>
				<span lang="EN-US">key</span>
				<span style="FONT-FAMILY: 宋体">为“</span>
				<span lang="EN-US">hello.no.username.error</span>
				<span style="FONT-FAMILY: 宋体">”</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体">，</span>
				<span style="FONT-FAMILY: 宋体">在</span>
				<span lang="EN-US">Resource Bundle</span>
				<span style="FONT-FAMILY: 宋体">中与值匹配的消息文本为：</span>
		</p>
		<p class="a5">
				<span lang="EN-US">hello.no.username.error=Please enter a &lt;i&gt;UserName&lt;/i&gt; to say hello to!</span>
		</p>
		<p class="a6">
				<span style="FONT-FAMILY: 宋体; LETTER-SPACING: 0.1pt">（</span>
				<span lang="EN-US" style="LETTER-SPACING: 0.1pt">7</span>
				<span style="FONT-FAMILY: 宋体; LETTER-SPACING: 0.1pt">）</span>
				<span lang="EN-US" style="LETTER-SPACING: 0.1pt">ActionServlet</span>
				<span style="FONT-FAMILY: 宋体; LETTER-SPACING: 0.1pt">把</span>
				<span lang="EN-US" style="LETTER-SPACING: 0.1pt">HelloForm</span>
				<span style="FONT-FAMILY: 宋体; LETTER-SPACING: 0.1pt">的</span>
				<span lang="EN-US" style="LETTER-SPACING: 0.1pt">validate()</span>
				<span style="FONT-FAMILY: 宋体; LETTER-SPACING: 0.1pt">方法返回的</span>
				<span lang="EN-US" style="LETTER-SPACING: 0.1pt">ActionErrors</span>
				<span style="FONT-FAMILY: 宋体; LETTER-SPACING: 0.1pt">对象保存在</span>
				<span lang="EN-US" style="LETTER-SPACING: 0.1pt">request</span>
				<span style="FONT-FAMILY: 宋体; LETTER-SPACING: 0.1pt">范围内，然后根据</span>
				<span lang="EN-US" style="LETTER-SPACING: 0.1pt">&lt;action&gt;</span>
				<span style="FONT-FAMILY: 宋体; LETTER-SPACING: 0.1pt">元素的</span>
				<span lang="EN-US" style="LETTER-SPACING: 0.1pt">input</span>
				<span style="FONT-FAMILY: 宋体; LETTER-SPACING: 0.1pt">属性，把客户请求转发给</span>
				<span lang="EN-US" style="LETTER-SPACING: 0.1pt">hello.jsp</span>
				<span style="FONT-FAMILY: 宋体; LETTER-SPACING: 0.1pt">。</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">8</span>
				<span style="FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US">hello.jsp</span>
				<span style="FONT-FAMILY: 宋体">的</span>
				<span lang="EN-US">&lt;html:errors&gt;</span>
				<span style="FONT-FAMILY: 宋体">标签从</span>
				<span lang="EN-US">request</span>
				<span style="FONT-FAMILY: 宋体">范围内读取</span>
				<span lang="EN-US">ActionErrors</span>
				<span style="FONT-FAMILY: 宋体">对象，再从</span>
				<span lang="EN-US">ActionErrors</span>
				<span style="FONT-FAMILY: 宋体">对象中读取</span>
				<span lang="EN-US">ActionMessage</span>
				<span style="FONT-FAMILY: 宋体">对象，把它包含的错误消息显示在网页上。</span>
		</p>
		<h3>
				<a name="_Toc73267708">
				</a>
				<a name="_Toc50722850">
						<span lang="EN-US">二、</span>
				</a>
				<span style="FONT-FAMILY: 方正小标宋简体">逻辑验证失败的流程</span>
		</h3>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">接下来在</span>
				<span lang="EN-US">hello.jsp</span>
				<span style="FONT-FAMILY: 宋体">的</span>
				<span lang="EN-US">HTML</span>
				<span style="FONT-FAMILY: 宋体">表单中输入姓名“</span>
				<span lang="EN-US">Monster</span>
				<span style="FONT-FAMILY: 宋体">”，然后单击【</span>
				<span lang="EN-US">Submit</span>
				<span style="FONT-FAMILY: 宋体">】</span>
				<span style="FONT-FAMILY: 宋体">按钮。当服务器端响应客户请求时，验证流程如下。</span>
		</p>
		<h4 style="TEXT-INDENT: 0cm">
				<span lang="EN-US">
						<img height="40" src="http://act.it.sohu.com/book/data/book/78/278/02.files/image008.jpg" width="76" border="0" />
				</span>
		</h4>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">1</span>
				<span style="FONT-FAMILY: 宋体">）表单验证</span>
				<span style="FONT-FAMILY: 宋体">的流程（</span>
				<span lang="EN-US">1</span>
				<span style="FONT-FAMILY: 宋体">）～（</span>
				<span lang="EN-US">4</span>
				<span style="FONT-FAMILY: 宋体">）。</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">2</span>
				<span style="FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US">ActionServlet</span>
				<span style="FONT-FAMILY: 宋体">调用</span>
				<span lang="EN-US">HelloForm</span>
				<span style="FONT-FAMILY: 宋体">对象的</span>
				<span lang="EN-US">validate()</span>
				<span style="FONT-FAMILY: 宋体">方法，这次</span>
				<span lang="EN-US">validate()</span>
				<span style="FONT-FAMILY: 宋体">方法返回的</span>
				<span lang="EN-US">ActionErrors</span>
				<span style="FONT-FAMILY: 宋体">对象中不包含任何</span>
				<span lang="EN-US">ActionMessage</span>
				<span style="FONT-FAMILY: 宋体">对象，表示表单验证成功。</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">3</span>
				<span style="FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US">ActionServlet</span>
				<span style="FONT-FAMILY: 宋体">查找</span>
				<span lang="EN-US">HelloAction</span>
				<span style="FONT-FAMILY: 宋体">实例是否存在，如果不存在就创建一个实例。然后调用</span>
				<span lang="EN-US">HelloAction</span>
				<span style="FONT-FAMILY: 宋体">的</span>
				<span lang="EN-US">execute()</span>
				<span style="FONT-FAMILY: 宋体">方法。</span>
		</p>
		<p class="a9">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">4</span>
				<span style="FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US">HelloAction</span>
				<span style="FONT-FAMILY: 宋体">的</span>
				<span lang="EN-US">execute()</span>
				<span style="FONT-FAMILY: 宋体">方法先进行逻辑验证，由于没有通过逻辑验证，就创建一个</span>
				<span lang="EN-US">ActionMessage</span>
				<span style="FONT-FAMILY: 宋体">对象，这个</span>
				<span lang="EN-US">ActionMessage</span>
				<span style="FONT-FAMILY: 宋体">对象封装了错误消息，消息</span>
				<span lang="EN-US">key</span>
				<span style="FONT-FAMILY: 宋体">为“</span>
				<span lang="EN-US">hello.dont.talk.to.monster</span>
				<span style="FONT-FAMILY: 宋体">”，在</span>
				<span lang="EN-US">Resource Bundle</span>
				<span style="FONT-FAMILY: 宋体">中与值匹配的消息文本为：</span>
		</p>
		<p class="a5">
				<span lang="EN-US">hello.dont.talk.to.monster=We don't want to say hello to Monster!!!</span>
		</p>
		<p class="a6">
				<span lang="EN-US">execute()</span>
				<span style="FONT-FAMILY: 宋体">方法把</span>
				<span lang="EN-US">ActionMessage</span>
				<span style="FONT-FAMILY: 宋体">对象保存在</span>
				<span lang="EN-US">ActionMessages</span>
				<span style="FONT-FAMILY: 宋体">对象中，再把</span>
				<span lang="EN-US">ActionMessages</span>
				<span style="FONT-FAMILY: 宋体">对象存放在</span>
				<span lang="EN-US">request</span>
				<span style="FONT-FAMILY: 宋体">范围内。最后返回一个</span>
				<span lang="EN-US">ActionForward</span>
				<span style="FONT-FAMILY: 宋体">对象，该对象包含的请求转发路径为</span>
				<span lang="EN-US">&lt;action&gt;</span>
				<span style="FONT-FAMILY: 宋体">元素的</span>
				<span lang="EN-US">input</span>
				<span style="FONT-FAMILY: 宋体">属性指定的</span>
				<span lang="EN-US">hello.jsp</span>
				<span style="FONT-FAMILY: 宋体">。</span>
		</p>
		<p class="a9">
				<span style="FONT-FAMILY: 宋体">以下是</span>
				<span lang="EN-US">execute()</span>
				<span style="FONT-FAMILY: 宋体">方法中进行逻辑验证的代码：</span>
		</p>
		<p class="a5">
				<span lang="EN-US">ActionMessages errors = new ActionMessages();</span>
		</p>
		<p class="a5">
				<span lang="EN-US">String userName = (String)((HelloForm) form).getUserName();</span>
		</p>
		<p class="a5">
				<span lang="EN-US">String badUserName = "Monster";</span>
		</p>
		<p class="a5">
				<span lang="EN-US">
				</span> </p>
		<p class="a5">
				<span lang="EN-US">if (userName.equalsIgnoreCase(badUserName)) {</span>
		</p>
		<p class="a5">
				<span lang="EN-US">     errors.add("username", new ActionMessage("hello.dont.talk.to.monster", badUserName ));</span>
		</p>
		<p class="a5">
				<span lang="EN-US">     saveErrors(request, errors);</span>
		</p>
		<p class="a5">
				<span lang="EN-US">     return (new ActionForward(mapping.getInput()));</span>
		</p>
		<p class="a5">
				<span lang="EN-US">}</span>
		</p>
		<p class="a6">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">5</span>
				<span style="FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US">ActionServlet</span>
				<span style="FONT-FAMILY: 宋体">依据</span>
				<span lang="EN-US">HelloAction</span>
				<span style="FONT-FAMILY: 宋体">返回的</span>
				<span lang="EN-US">ActionForward</span>
				<span style="FONT-FAMILY: 宋体">对象，再把请求转发给</span>
				<span lang="EN-US">hello.jsp</span>
				<span style="FONT-FAMILY: 宋体">。</span>
		</p>
		<p class="MsoNormalIndent">
				<span style="COLOR: black; FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US" style="COLOR: black">6</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US" style="COLOR: black">hello.jsp</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体">的</span>
				<span lang="EN-US" style="COLOR: black">&lt;html:errors&gt;</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体">标签从</span>
				<span lang="EN-US" style="COLOR: black">request</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体">范围内读取</span>
				<span lang="EN-US" style="COLOR: black">ActionMessages</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体">对象，再从</span>
				<span lang="EN-US" style="COLOR: black">ActionMessages</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体">对象中读取</span>
				<span lang="EN-US" style="COLOR: black">ActionMessage</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体">对象，把它包含的错误消息显示在网页上，</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体">如图</span>
				<span style="COLOR: black; FONT-FAMILY: 宋体">所示。</span>
		</p>
		<p class="a" align="center">
				<span lang="EN-US">
						<img height="172" src="http://act.it.sohu.com/book/data/book/78/278/02.files/image011.jpg" width="378" border="0" />
				</span>
		</p>
		<p class="a0" align="center">
				<span style="FONT-FAMILY: 宋体">逻辑验证失败时的</span>
				<span lang="EN-US">hello.jsp</span>
				<span style="FONT-FAMILY: 宋体">网页</span>
		</p>
		<h3>
				<a name="_Toc73267709">
				</a>
				<a name="_Toc50722851">
						<span lang="EN-US">三</span>
				</a>
				<span style="FONT-FAMILY: 方正小标宋简体">、逻辑验证成功的流程</span>
		</h3>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">接下来，在</span>
				<span lang="EN-US">hello.jsp</span>
				<span style="FONT-FAMILY: 宋体">的</span>
				<span lang="EN-US">HTML</span>
				<span style="FONT-FAMILY: 宋体">表单中输入姓名“</span>
				<span lang="EN-US">Weiqin</span>
				<span style="FONT-FAMILY: 宋体">”，然后单击【</span>
				<span lang="EN-US">Submit</span>
				<span style="FONT-FAMILY: 宋体">】</span>
				<span style="FONT-FAMILY: 宋体">按钮。当服务器端响应客户请求时，流程如下。</span>
		</p>
		<h4 style="TEXT-INDENT: 0cm">
				<span lang="EN-US">
						<img height="40" src="http://act.it.sohu.com/book/data/book/78/278/02.files/image008.jpg" width="76" border="0" />
				</span>
		</h4>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">1</span>
				<span style="FONT-FAMILY: 宋体">）重复</span>
				<span lang="EN-US">二</span>
				<span style="FONT-FAMILY: 宋体">的流程（</span>
				<span lang="EN-US">1</span>
				<span style="FONT-FAMILY: 宋体">）～（</span>
				<span lang="EN-US">3</span>
				<span style="FONT-FAMILY: 宋体">）。</span>
		</p>
		<p class="a9">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">2</span>
				<span style="FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US">HelloAction</span>
				<span style="FONT-FAMILY: 宋体">的</span>
				<span lang="EN-US">execute()</span>
				<span style="FONT-FAMILY: 宋体">方法先执行逻辑验证，这次通过了验证，然后执行相关的业务逻辑，最后调用</span>
				<span lang="EN-US">ActionMapping.findForward()</span>
				<span style="FONT-FAMILY: 宋体">方法，参数为</span>
				<span style="FONT-FAMILY: 宋体">“</span>
				<span lang="EN-US">SayHello</span>
				<span style="FONT-FAMILY: 宋体">”：</span>
		</p>
		<p class="a5">
				<span lang="EN-US">// Forward control to the specified success URI</span>
		</p>
		<p class="a5">
				<span lang="EN-US">return (mapping.findForward("SayHello"));</span>
		</p>
		<p class="aa">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">3</span>
				<span style="FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US">ActionMapping.findForward()</span>
				<span style="FONT-FAMILY: 宋体">方法从</span>
				<span lang="EN-US">&lt;action&gt;</span>
				<span style="FONT-FAMILY: 宋体">元素中寻找</span>
				<span lang="EN-US">name</span>
				<span style="FONT-FAMILY: 宋体">属性为</span>
				<span style="FONT-FAMILY: 宋体">“</span>
				<span lang="EN-US">SayHello</span>
				<span style="FONT-FAMILY: 宋体">”的</span>
				<span lang="EN-US">&lt;forward&gt;</span>
				<span style="FONT-FAMILY: 宋体">子元素，然后返回与之对应的</span>
				<span lang="EN-US">ActionForward</span>
				<span style="FONT-FAMILY: 宋体">对象，它代表的请求转发路径为“</span>
				<span lang="EN-US">/hello.jsp</span>
				<span style="FONT-FAMILY: 宋体">”。</span>
		</p>
		<table class="MsoNormalTable" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; MARGIN-LEFT: 5.4pt; BORDER-LEFT: medium none; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse" cellspacing="0" cellpadding="0" border="1">
				<tbody>
						<tr style="HEIGHT: 43.4pt">
								<td style="BORDER-RIGHT: medium none; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; WIDTH: 63pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 43.4pt" valign="top" width="84">
										<p class="MsoNormal" style="MARGIN-TOP: 6pt; TEXT-INDENT: 0cm">
												<span lang="EN-US">
														<img height="40" src="http://act.it.sohu.com/book/data/book/78/278/02.files/image003.jpg" width="57" border="0" />
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: medium none; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: medium none; WIDTH: 346.5pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; HEIGHT: 43.4pt" width="462">
										<p class="a7">
												<strong>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">更确切地说，</span>
														<span lang="EN-US" style="COLOR: black">ActionMapping</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">从本身包含的</span>
														<span lang="EN-US" style="COLOR: black">HashMap</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">中查找</span>
														<span lang="EN-US" style="COLOR: black">name</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">属性为</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">“</span>
														<span lang="EN-US" style="COLOR: black">SayHello</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">”</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">的</span>
														<span lang="EN-US" style="COLOR: black">ActionForward</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">对象。在</span>
														<span lang="EN-US" style="COLOR: black">ActionServlet</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">初始化时会加载</span>
														<span lang="EN-US" style="COLOR: black">Struts</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">配置文件，把</span>
														<span lang="EN-US" style="COLOR: black">&lt;action&gt;</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">元素的配置信息存放在</span>
														<span lang="EN-US" style="COLOR: black">ActionMapping</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">对象中。</span>
														<span lang="EN-US" style="COLOR: black">&lt;action&gt;</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">元素中可以包含多个</span>
														<span lang="EN-US" style="COLOR: black">&lt;forward&gt;</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">子元素，每个</span>
														<span lang="EN-US" style="COLOR: black">&lt;forward&gt;</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">子元素的配置信息存放在一个</span>
														<span lang="EN-US" style="COLOR: black">ActionForward</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">对象中，这些</span>
														<span lang="EN-US" style="COLOR: black">ActionForward</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">对象存放在</span>
														<span lang="EN-US" style="COLOR: black">ActionMapping</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">对象的</span>
														<span lang="EN-US" style="COLOR: black">HashMap</span>
														<span style="COLOR: black; FONT-FAMILY: 楷体_GB2312">中。</span>
												</strong>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p class="a6">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">4</span>
				<span style="FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US">HelloAction</span>
				<span style="FONT-FAMILY: 宋体">的</span>
				<span lang="EN-US">execute()</span>
				<span style="FONT-FAMILY: 宋体">方法</span>
				<span style="FONT-FAMILY: 宋体">然后把</span>
				<span lang="EN-US">ActionForward</span>
				<span style="FONT-FAMILY: 宋体">对象返回给</span>
				<span lang="EN-US">ActionServlet</span>
				<span style="FONT-FAMILY: 宋体">，</span>
				<span lang="EN-US">ActionServlet</span>
				<span style="FONT-FAMILY: 宋体">再把客户请求转发给</span>
				<span lang="EN-US">hello.jsp</span>
				<span style="FONT-FAMILY: 宋体">。</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">（</span>
				<span lang="EN-US">5</span>
				<span style="FONT-FAMILY: 宋体">）</span>
				<span lang="EN-US">hello.jsp</span>
				<span style="FONT-FAMILY: 宋体">的</span>
				<span lang="EN-US">&lt;bean:message&gt;</span>
				<span style="FONT-FAMILY: 宋体">标签从</span>
				<span lang="EN-US">Resource Bundle</span>
				<span style="FONT-FAMILY: 宋体">中读取文本，把它们输出到网页上，最后生成</span>
				<span style="FONT-FAMILY: 宋体">动态网页，如图</span>
				<span style="FONT-FAMILY: 宋体">所示。</span>
		</p>
		<p class="a" align="center">
				<span lang="EN-US">
						<img height="178" src="http://act.it.sohu.com/book/data/book/78/278/02.files/image002.jpg" width="378" border="0" />
				</span>
		</p>
		<p class="a0" align="center">
				<span lang="EN-US">  </span>
				<span style="FONT-FAMILY: 宋体">通过数据验证的</span>
				<span lang="EN-US">hello.jsp</span>
				<span style="FONT-FAMILY: 宋体">网页</span>
		</p>
<img src ="http://www.blogjava.net/ltc603/aggbug/64202.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ltc603/" target="_blank">阿成</a> 2006-08-17 20:22 <a href="http://www.blogjava.net/ltc603/archive/2006/08/17/64202.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用Validator检查你的表单 </title><link>http://www.blogjava.net/ltc603/archive/2006/05/11/45655.html</link><dc:creator>阿成</dc:creator><author>阿成</author><pubDate>Thu, 11 May 2006 06:52:00 GMT</pubDate><guid>http://www.blogjava.net/ltc603/archive/2006/05/11/45655.html</guid><wfw:comment>http://www.blogjava.net/ltc603/comments/45655.html</wfw:comment><comments>http://www.blogjava.net/ltc603/archive/2006/05/11/45655.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ltc603/comments/commentRss/45655.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ltc603/services/trackbacks/45655.html</trackback:ping><description><![CDATA[
		<p>
				<span class="italicbodycopy">
						<b>用Validator（验证器）提供的丰富的内置验证方法简化Struts的开发过程。</b>
				</span>
		</p>
		<p>
				<span class="bodycopy">Struts框架的一个主要好处是它提供了对接收到的表单数据进行验证的内置界面。如果有任何验证失败，则应用程序都会重新显示HTML表单，这样就可以改正无效的数据了。如果验证成功，则处理过程会继续进行。Struts框架的简单验证界面会减少与处理数据验证有关的令人头疼的事情，这样你就可以把精力集中到验证代码上，而不是放到捕获数据、重新显示不完整或无效数据的技巧上。</span>
		</p>
		<p class="bodycopy">但是，Struts内置的验证界面也有缺点。例如，在整个应用程序中验证代码常常会大量重复，因为许多域需要相同的验证逻辑。对一些相似字段的验证逻辑进行任何修改都要求在几个地方修改代码，还要重新编译受影响的代码。为了解决这个问题并增强Struts验证界面的功能，作为Struts的第三方附加件创建了Validator框架。后来，Validator被集成到核心Struts代码库中，并从Struts中分离出来，现在它是一个独立的Jakarta Commons项目。虽然Validator是一个独立的框架，但它仍能与其他程序封装在一起后提供，并与Struts无缝集成。</p>
		<p>
				<span class="parahead1">Validator概述</span>
		</p>
		<p>
				<span class="bodycopy">没有Validator，你就不得不编写验证表单数据所需的全部代码，并把它放入Form Bean对象的validate( )方法中。对于想在其上进行数据验证的每个Form Bean域来说，都需要编写逻辑代码来实现验证。此外，你还必须编写代码来存储验证失败时的出错消息。 </span>
		</p>
		<p class="bodycopy">有了Validator，你就不必在Form Bean中编写用于验证或存储错误消息的任何代码。相反，Form Bean提供了Validator的一个ActionForm子类，它提供验证或存储错误消息的功能。 </p>
		<p class="bodycopy">可把Validator框架作为一个可用于Form Bean验证的可插入的验证例行程序系统来进行安装。每个验证例行程序都只是一个Java方法，负责执行特定类型的验证任务，验证可能通过，也可能失败。 默认情况下，Validator与几个有用的验证例行程序封装在一起来提供，这些例行程序能满足大多数情况下的验证要求。但是，如果Validator框架没有提供你需要的验证例行程序，那么你可以自己创建定制的验证例行程序，并将它插入到该框架中。此外，Validator还支持服务器端和客户端（JavaScript）的验证，而Form Bean只提供服务器端验证界面。 </p>
		<p>
				<span class="bodycopy">Validator使用两个XML配置文件来分别确定安装哪个验证例行程序和如何将它们应用于给定的应用程序。第一个配置文件validator-rules.xml说明应该被插入到框架中的验证例行程序，并提供每个验证的逻辑的名称。validator-rules.xml文件还定义了每个验证例行程序的客户端JavaScript代码。可以配置Validator让它把这个JavaScript代码发送到浏览器上，这样验证就可以在客户端和服务器端进行了。 </span>
		</p>
		<p>
				<span class="bodycopy">第二个配置文件validation.xml确定哪个验证例行程序应用到哪个Form Bean。文件中的定义使用struts-config.xml文件给出的Form Bean的逻辑名称以及validator-rules.xml文件给出的验证例行程序的逻辑名称，以便把二者关联起来。</span>
		</p>
		<p class="bodycopy">使用Validator框架包括启用Validator插件、配置Validator的两个配置文件，以及创建提供Validator的ActionForm子类的Form Beans。下面详细解释如何配置和使用Validator。 </p>
		<p>
				<span class="parahead1">启用Validator插件</span>
		</p>
		<p>
				<span class="bodycopy">虽然Validator框架是与Struts封装在一起提供的，但在默认状况下Validator并不被启用。为了启用Validator，要向你的应用程序的struts-config.xml文件中添加下面的插件定义。 </span>
		</p>
		<p>
		</p>
		<pre>&lt;!-- Validator Configuration --&gt;
&lt;plug-in className="org.apache.struts
.validator.ValidatorPlugIn"&gt;
  &lt;set-property property="pathnames"
               value="/WEB-INF/
  validator-rules.xml, /WEB-INF/

  validation.xml"/&gt;
&lt;/plug-in&gt;
</pre>
		<p>
		</p>
		<p>
				<span class="bodycopy">该定义告诉Struts为你的应用程序加载并初始化Validator插件。在初始化时，该插件装入由路径名属性指定的、用逗号分隔的Validator配置文件清单。每个配置文件的路径应该用与Web应用程序的相关的路径来指定，如前面的例子所示。 </span>
		</p>
		<p class="bodycopy">请注意，你的应用程序的struts-config.xml文件必须与Struts Configuration Document Type Definition（Struts配置文档类型定义，DTD）一致，后者规定文件中元素出现的顺序。所以，你必须把Validator插件定义放到该文件的适当位置。确保文件中元素适当排列的最简便方法就是使用诸如Struts Console的工具，它自动格式化你的配置文件，以便与DTD保持一致。</p>
		<p>
				<span class="parahead1">配置validator-rules.xml </span>
		</p>
		<p class="bodycopy">Validator框架可以设置为可插入系统，其验证例行程序仅仅是插入到该系统中执行具体验证的Java方法。validator-rules.xml文件说明性地插入Validator用于执行验证的验证例行程序中。Struts示例应用程序带有这个文件的预配置拷贝。在大多数情况下，你不必修改这个预配置拷贝，除非你要向该框架中添加自己定制的验证。</p>
		<p>
				<span class="bodycopy">
						<a href="http://www.oracle.com/global/cn/oramag/oracle/04-jan/o14dev_struts_l1.html" target="_blank" s_oid="http://www.oracle.com/global/cn/oramag/oracle/04-jan/o14dev_struts_l1.html" s_oidt="0">
								<span class="bodylink">清单1</span>
						</a>是一个示例validator-rules.xml文件，说明如何将验证例行程序插入到Validator中。validator-rules.xml文件中的每个验证例行程序都有自己的定义，它用validator标记声明，利用name属性为该验证例行程序指定逻辑名，并指定该例行程序的类和方法。该例行程序的逻辑名称供该文件中的其他例行程序以及validation.xml文件中的验证定义用于引用该例行程序。</span>
		</p>
		<p class="bodycopy">请注意，validator标记放在javascript的标记中，javascript标记用于定义客户端JavaScript代码，以便在客户端执行与服务器端相同的验证。 </p>
		<p class="parahead1">提供的验证程序</p>
		<p class="bodycopy">默认情况下，Validator中包括几个基本验证例行程序，你可以用它们来处理大多数验证问题。这些例行程序具有逻辑名称，如required（用于输入要求的值）、CreditCard（用于输入信用卡号码值）、email（用于输入电子邮件地址值），等等。</p>
		<p class="parahead1">创建Form Bean</p>
		<p>
				<span class="bodycopy">为了使用Validator，你的应用程序的Form Bean必须归到Validator的ActionForm的某一子类，而不是ActionForm本身。Validator的ActionForm子类提供了ActionForm的validate( )方法（它嵌入到Validator框架中）的实施过程。你不必从头编写验证代码并把它投入validate( )方法中，相反，可以完全忽略该方法，因为Validator为你提供了验证代码。 </span>
		</p>
		<p class="bodycopy">与Struts提供的核心功能相类似，Validator提供给你两种可供选择的方法来创建Form Bean。 你可以选择的第一种方法就是像下面这样创建一个特定的Form Bean对象：</p>
		<p>
		</p>
		<pre>package com.jamesholmes.minihr;

import org.apache.struts.validator
.ValidatorForm;


public class LogonForm extends ValidatorForm {
  private String username;
  private String password;
  
  public String getUsername() {
    return username;
  }
  
  public void setUsername(String 
username) {
    this.username = username;
  }


  public String getPassword() {
    return password;
  }
public void setPassword(String 
password) {
    this.password = password;
  }
}
</pre>
		<span class="bodycopy">
				<p>
				</p>
		</span>
		<p class="bodycopy">这个类与你不是用Validator所创建的类相似，但它提供ValidatorForm而不是ActionForm。这个类也不提供ActionForm的空reset( )和validate( )方法的实施过程，因为ValidatorForm提供了相应过程。</p>
		<p class="bodycopy">在struts-config.xml文件中配置这个特定Form Bean的方法与配置正则Form Bean的方法相同：</p>
		<p>
		</p>
		<pre>&lt;form-beans&gt;
  &lt;form-bean name="logonForm"
            type="com.jamesholmes
  .minihr.LogonForm"/&gt;
&lt;/form-beans&gt;
</pre>
		<p>
		</p>
		<p>
				<span class="bodycopy">用表单标记的name属性给特定Form Bean指定的逻辑名是在定义validation.xml文件中的验证时所使用的名称，如下所示：</span>
		</p>
		<p>
		</p>
		<pre>&lt;!DOCTYPE form-validation 
PUBLIC "-//Apache Software Foundation//
       DTD Commons Validator Rules
       Configuration 1.0//EN"
       "http://jakarta.apache.org/
      commons/dtds/validator_1_0.dtd"&gt;


&lt;form-validation&gt;
  &lt;formset&gt;
    &lt;form name="logonForm"&gt;
      &lt;field property="username" 
            depends="required"&gt;
        &lt;arg0 key="prompt.username"/&gt;
      &lt;/field&gt;
    &lt;/form&gt;
  &lt;/formset&gt;
&lt;/form-validation&gt;
</pre>
		<p>
		</p>
		<p>
				<span class="bodycopy">Validator使用该表单标记的name属性的值将验证定义与要应用这些定义的Form Bean的名称相匹配。 </span>
		</p>
		<p class="bodycopy">创建Form Bean时可以选择的第二种方法是在struts-config.xml文件中定义一个动态Form Bean，如下所示：</p>
		<p>
		</p>
		<pre>&lt;form-beans&gt;
  &lt;form-bean name="logonForm"
            type="org.apache
.struts.validator.DynaValidatorForm"&gt;
    &lt;form-property name="username"
            type="java.lang.String"/&gt;
    &lt;form-property name="password"
            type="java.lang.String"/&gt;
  &lt;/form-bean&gt;
&lt;/form-beans&gt;
</pre>
		<p>
		</p>
		<p>
				<span class="bodycopy">动态Form Bean不要求创建特定的Form Bean对象；相反，要定义Form Bean应该具有的属性和类型，而Struts为你动态创建Form Bean。 Validator允许你使用这个概念，就像在核心Struts中使用这个概念一样。与使用Validator的惟一区别就是要指定Form Bean是org.apache.struts.validator.DynaValidatorForm类型，而不是org.apache.struts.action.DynaActionForm类型。</span>
		</p>
		<p class="bodycopy">分配给动态Form Bean的逻辑名是在定义validation.xml文件中的验证时使用的名称。Validator使用与之相匹配的名称将这些验证与Form Bean联系在一起。 </p>
		<p class="bodycopy">除了创建Form Bean的这两种标准方法之外，Validator还提供了一个高级特性，用于将多个验证定义与一个Form Bean定义联系起来。当你使用基于validatorForm或基于DynaValidatorForm的Form Bean时，Validator使用struts-config.xml文件中的Form Bean的逻辑名称，将Form Bean映射到validation.xml文件中的验证定义。这种机制在大多数情况下非常有用，但在某些时候，Form Bean要在多个操作中共享。 一个操作可能使用Form Bean的所有域（fields），而另一个操作可能只使用这些域的一个子集。因为验证定义被连接到Form Bean，所以只使用域的一个子集的操作就无法绕过对未使用域的验证。当验证Form Bean时，就会对未使用的域生成错误消息，因为Validator无从知道不去验证未使用的域，它只是简单地把它们看作缺失或无效。</p>
		<p class="bodycopy">为了解决这个问题，Validator提供了两个附加的ActionForm子类，它使你能够将验证与操作相关联，而不是与Form Bean相关联。这样你就可以根据哪个操作正在使用Form Bean来指定把哪些验证用于该Form Bean了。对于特定的Form Bean，你要像下面这样声明org.apache.struts.validator.ValidatorActionForm子类：</p>
		<p>
		</p>
		<pre>public class AddressForm extends ValidatorActionForm {
  ...
}
</pre>
		<p>
		</p>
		<p class="bodycopy">对于动态Form Bean，在struts-config.xml文件中为Form Bean定义指定org.apache.struts.validator.DynaValidatorActionForm的类型，如下所示： </p>
		<p>
		</p>
		<pre>&lt;form-bean name="addressForm"
          type="org.apache.struts
.validator.DynaValidatorActionForm"&gt;
  ...
&lt;/form-bean&gt;
</pre>
		<p>
		</p>
		<p class="bodycopy">在validation.xml文件中，把一组验证映射到一个操作路径，而不是映射到Form Bean名，因为如果你定义了Create Address和Edit Address两个操作（它们使用同一个Form Bean），那么每个操作都会有一个惟一的操作名，如下所示： </p>
		<p>
		</p>
		<pre>&lt;action-mappings&gt;
  &lt;action path="/createAddress"
         type="com.jamesholmes
  .minihr.CreateAddressAction"
         name="addressForm"/&gt;
  &lt;action path="/editAddress"
         type="com.jamesholmes
  .minihr.EditAddressAction"
         name="addressForm"/&gt;

&lt;/action-mappings&gt;
</pre>
		<p>
		</p>
		<p class="bodycopy">下面的validation.xml文件片断显示了两组验证，它们用于同一个Form Bean，但却有不同的操作路径：</p>
		<p>
		</p>
		<pre>&lt;formset&gt;
  &lt;form name="/createAddress"&gt;
    &lt;field property="city"
          depends="required"&gt;
      &lt;arg0 key="prompt.city"/&gt;
    &lt;/field&gt;
  &lt;/form&gt;
  &lt;form name="/editAddress"&gt;
    &lt;field property="state"
          depends="required"&gt;
      &lt;arg0 key="prompt.state"/&gt;
    &lt;/field&gt;
  &lt;/form&gt;
&lt;/formset&gt;
</pre>
		<p>
		</p>
		<p class="bodycopy">因为Form Bean要么属于ValidatorActionForm子类，要么属于DynaValidatorActionForm子类，所以Validator知道用一个操作路径代替Form Bean的逻辑名称来找出用于Form Bean的验证。</p>
		<p class="parahead1">配置validation.xml文件</p>
		<p class="bodycopy">validation.xml文件用于声明将应用到Form Beans的一组验证。要验证的每个Form Bean在这个文件中都有自己的定义。在这个定义中，指定要应用到该Form Bean的各域的验证。下面是一个validation.xml文件的例子，说明如何定义验证：</p>
		<p>
		</p>
		<pre>&lt;!DOCTYPE form-validation 
PUBLIC "-//Apache Software Foundation//
       DTD Commons Validator Rules
       Configuration 1.0//EN"
       "http://jakarta.apache.org/
      commons/dtds/validator_1_0.dtd"&gt;

&lt;form-validation&gt;
  &lt;formset&gt;
    &lt;form name="logonForm"&gt;
      &lt;field property="username"
            depends="required"&gt;
        &lt;arg0 key="prompt.username"/&gt;

      &lt;/field&gt;
      &lt;field property="password"
            depends="required"&gt;
        &lt;arg0 key="prompt.password"/&gt;
      &lt;/field&gt;
    &lt;/form&gt;
  &lt;/formset&gt;
&lt;/form-validation&gt;
</pre>
		<p>
		</p>
		<p>
				<span class="bodycopy">validation.xml文件的第一个元素是form-validation。这个元素是该文件的主元素，而且只定义一次。在form-validation元素内定义form-set元素，它包括多个表单元素。一般来说，在文件中只定义一个form-set元素，但是如果要将验证国际化，那就要在每个地方单独使用一个form-set元素。</span>
		</p>
		<p>
				<span class="bodycopy">每个表单元素使用name属性将名称与其所包含的域验证集关联起来。Validator使用这个逻辑名称将这些验证映射到在struts-config.xml文件中定义的一个Form Bean。根据要验证的Form Bean的类型，Validator力求将该名称与Form Bean的逻辑名称或操作路径相匹配。在表单元素内，field元素定义要应用到Form Bean的特定域的验证。field元素的property属性对应于特定Form Bean中的域名。depends属性利用validator-rules.xml文件指定验证例行程序的逻辑名称，这些例行程序将应用到域验证中。</span>
		</p>
		<p class="parahead1">配置ApplicationResources.properties </p>
		<p class="bodycopy">Validator使用Struts的资源绑定（Resource Bundle）机制将错误消息具体化。不用在框架中对错误消息进行硬编码，Validator使你能在ApplicationResources.properties文件中为一个消息指定一个键值，如果验证失败则将返回该键值。validator-rules.xml文件中的每个验证例行程序都用validator标记的msg属性指定错误消息的键值，如下所示： </p>
		<p>
		</p>
		<pre>&lt;validator name="required"
          classname="org.apache

.struts.validator.FieldChecks"
          method="validateRequired"
          methodParams="java.lang
.Object, org.apache.commons.validator
.ValidatorAction, org.apache.commons
.validator.Field, org.apache.struts
.action.ActionErrors, javax.servlet
.http.HttpServletRequest"
          msg="errors.required"&gt;
</pre>
		<p>
		</p>
		<p class="bodycopy">如果在验证例行程序运行时验证失败，则返回与msg属性指定的键值对应的消息。</p>
		<p>
				<span class="bodycopy">下面的片段显示来自ApplicationResources.properties文件的验证出错时的默认消息集，它们由Struts示例应用程序提供。每个消息的键值对应于每个由validator-rules.xml文件中的验证例行程序所指定的消息，它们由Struts示例应用程序提供。</span>
		</p>
		<p>
		</p>
		<pre># Error messages for Validator framework validations
errors.required={0} is required.
errors.minlength={0} cannot be less than {1} characters.
errors.maxlength={0} cannot be greater than {2} characters.
errors.invalid={0} is invalid.
errors.byte={0} must be a byte.
errors.short={0} must be a short.
errors.integer={0} must be an integer.
errors.long={0} must be a long.0.   errors.float={0} must be a float.

errors.double={0} must be a double.
errors.date={0} is not a date.
errors.range={0} is not in the range {1} through {2}.
errors.creditcard={0} is not a valid credit card number.
errors.email={0} is an invalid e-mail address.
</pre>
		<p>
		</p>
		<p>
				<span class="bodycopy">请注意，每条消息都有占位符，形式为{0}、{1}或{2}。在运行期间，占位符被另一个值代替，如所验证的域的名称。这一特性特别有用，它使你能够创建可被几个不同的域重复使用的通用验证错误消息。 </span>
		</p>
		<p class="bodycopy">例如，下面给出required验证的错误消息errors.required： </p>
		<p>
		</p>
		<pre>errors.required={0} is required.
</pre>
		<p>
		</p>
		<p class="bodycopy">当你使用validation.xml文件中的该required验证时，必须定义用于替换该错误消息中的{0}的值，如下所示：</p>
		<p>
		</p>
		<pre>&lt;form name="auctionForm"&gt;
  &lt;field property="bid" depends="required"&gt;
    &lt;arg0 key="prompt.bid"/&gt;
  &lt;/field&gt;
&lt;/form&gt;
</pre>
		<p>
		</p>
		<p class="bodycopy">错误消息最多可以有4个占位符：{0}和{3}。这些占位符分别称为arg0到arg3，你可以通过使用arg0~arg3标记来指定它们。在上面的例子中，arg0标记指定了用于替换{0}占位符的值。该标记的key属性指定来自ApplicationResources.properties文件的一个消息键值，它的值用于替换占位符，如下所示： </p>
		<table align="right" bgcolor="#cccccc" border="1" cellpadding="5" hspace="5" vspace="5" width="30%">
				<tbody>
						<tr>
								<td>
										<center>
												<span class="parahead1">
														<a name="NEXT">下一步</a>
												</span>
										</center>
										<p>
										</p>
										<p>
												<span class="boldbodycopy">阅读</span>
												<br />
												<span class="boldbodycopy">关于Validator的更多文章</span>
												<br />
												<a href="http://jakarta.apache.org/commons/validator" target="_top">
														<span class="bodylink">jakarta.apache.org/commons/validator</span>
												</a>
										</p>
										<p>
												<span class="boldbodycopy">关于Struts Console的更多文章</span>
												<br />
												<a href="http://www.jamesholmes.com/struts" target="_top">
														<span class="bodylink">www.jamesholmes.com/struts</span>
												</a>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p>
		</p>
		<pre>prompt.bid=Auction Bid
</pre>
		<p>
		</p>
		<p class="bodycopy">使用消息键值代替占位符的值，这一方法使你不必在validation.xml文件中对替换值反复硬编码。但是，如果你不想使用Resource Bundle的键值/值机制来指定占位符的值，则可以使用arg0标记的如下语法显式地指定占位符的值：</p>
		<p>
		</p>
		<pre>&lt;arg0 key="Auction Bid" resource="false"/&gt;
</pre>
		<p>
		</p>
		<p class="bodycopy">在这个例子中，resource属性的值设为false，以便通知Validator要把该key属性指定的值作为占位符的值，而不要作为ApplicationResources.properties文件中消息的一个键值。</p>
		<p class="parahead1">启用客户端验证 </p>
		<p>
				<span class="bodycopy">Validator除了提供了简化服务器端表单数据验证过程的框架外，它还提供了执行客户端验证时易于使用的方法。在validator-rules.xml文件中定义的每一个验证例行程序都可以随意指定JavaScript代码，这些代码可以在浏览器（客户端上的）中运行，从而执行与服务器端进行的验证相同的验证过程。在客户端进行验证时，除非所有表单都通过验证，否则这些表单不允许被提交。</span>
		</p>
		<p>
				<span class="bodycopy">为了启用客户端验证，必须在每个需要验证的JSP中放上Struts HTML Tag Library（标记库）的javascript标记，如下所示：</span>
		</p>
		<p>
		</p>
		<pre>&lt;html:javascript formName="logonForm"/&gt;
</pre>
		<p>
		</p>
		<p class="bodycopy">javascript标记要求使用formName属性来为想要对其执行验证的表单指定validation.xml文件中给出的表单定义名，如下所示： </p>
		<p>
		</p>
		<pre>&lt;form name="logonForm"&gt;
  &lt;field property="username"
        depends="required"&gt;
    &lt;arg0 key="prompt.username"/&gt;
  &lt;/field&gt;
  &lt;field property="password"
        depends="required"&gt;
    &lt;arg0 key="prompt.password"/&gt;
  &lt;/field&gt;
&lt;/form&gt;
</pre>
		<p>
		</p>
		<p class="bodycopy">为表单定义指定的服务器端的所有验证都将在客户端运行。由于客户端验证用JavaScript执行，所以可以有多种方法不去执行它。要确保验证过程总是能运行，不论你是否选择启用了客户端验证，Validator都在服务器端执行这些验证。</p>
		<p>
				<span class="parahead1">结论</span>
		</p>
		<p class="bodycopy">Validator框架针对表单数据的验证提供了可配置的系统，从而为核心Struts框架添加了很多有价值的功能。通过把Validator框架用于你的应用程序，你可以节约时间并简化Struts应用程序的开发过程。 </p>
<img src ="http://www.blogjava.net/ltc603/aggbug/45655.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ltc603/" target="_blank">阿成</a> 2006-05-11 14:52 <a href="http://www.blogjava.net/ltc603/archive/2006/05/11/45655.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用FileUpload组件实现文件上传</title><link>http://www.blogjava.net/ltc603/archive/2006/02/10/30168.html</link><dc:creator>阿成</dc:creator><author>阿成</author><pubDate>Fri, 10 Feb 2006 07:52:00 GMT</pubDate><guid>http://www.blogjava.net/ltc603/archive/2006/02/10/30168.html</guid><wfw:comment>http://www.blogjava.net/ltc603/comments/30168.html</wfw:comment><comments>http://www.blogjava.net/ltc603/archive/2006/02/10/30168.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/ltc603/comments/commentRss/30168.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/ltc603/services/trackbacks/30168.html</trackback:ping><description><![CDATA[
		<strong>
				<br />
		</strong>
		<p>使用FileUpload组件实现文件上传 <br />文件上传在web应用中非常普遍，要在servlet/jsp环境中实现文件上传功能非常容易，因为网上已经有许多用java开发的组件用于文件上传，本文以commons-fileupload组件为例，为servlet/jsp应用添加文件上传功能。</p>
		<p>common-fileupload组件是apache的一个开源项目之一，可以从<a href="http://jakarta.apache.org/commons/fileupload/" target="_blank"><font color="#000000">http://jakarta.apache.org/commons/fileupload/</font></a>下载。该组件简单易用，可实现一次上传一个或多个文件，并可限制文件大小。</p>
		<p>下载后解压zip包，将commons-fileupload-1.0.jar复制到tomcat的webapps\你的webapp\WEB-INF\lib\下，如果目录不存在请自建目录。</p>
		<p>新建一个servlet: Upload.java用于文件上传：</p>
		<p>import java.io.*;<br />import java.util.*;<br />import javax.servlet.*;<br />import javax.servlet.http.*;<br />import org.apache.commons.fileupload.*;</p>
		<p>public class Upload extends HttpServlet {</p>
		<p>    private String uploadPath = "C:\\upload\\"; // 用于存放上传文件的目录<br />    private String tempPath = "C:\\upload\\tmp\\"; // 用于存放临时文件的目录</p>
		<p>    public void doPost(HttpServletRequest request, HttpServletResponse response)<br />        throws IOException, ServletException<br />    {<br />    }<br />}</p>
		<p>当servlet收到浏览器发出的Post请求后，在doPost()方法中实现文件上传。以下是示例代码：</p>
		<p>public void doPost(HttpServletRequest request, HttpServletResponse response)<br />    throws IOException, ServletException<br />{<br />    try {<br />        DiskFileUpload fu = new DiskFileUpload();<br />        // 设置最大文件尺寸，这里是4MB<br />        fu.setSizeMax(4194304);<br />        // 设置缓冲区大小，这里是4kb<br />        fu.setSizeThreshold(4096);<br />        // 设置临时目录：<br />        fu.setRepositoryPath(tempPath);</p>
		<p>        // 得到所有的文件：<br />        List fileItems = fu.parseRequest(request);<br />        Iterator i = fileItems.iterator();<br />        // 依次处理每一个文件：<br />        while(i.hasNext()) {<br />            FileItem fi = (FileItem)i.next();<br />            // 获得文件名，这个文件名包括路径：<br />            String fileName = fi.getName();<br />            if(fileName!=null) {<br />                // 在这里可以记录用户和文件信息<br />                // ...<br />                // 写入文件a.txt，你也可以从fileName中提取文件名：<br />                fi.write(new File(uploadPath + "a.txt"));<br />            }<br />        }<br />        // 跳转到上传成功提示页面<br />    }<br />    catch(Exception e) {<br />        // 可以跳转出错页面<br />    }<br />}</p>
		<p>如果要在配置文件中读取指定的上传文件夹，可以在init()方法中执行：</p>
		<p>public void init() throws ServletException {<br />    uploadPath = ....<br />    tempPath = ....<br />    // 文件夹不存在就自动创建：<br />    if(!new File(uploadPath).isDirectory())<br />        new File(uploadPath).mkdirs();<br />    if(!new File(tempPath).isDirectory())<br />        new File(tempPath).mkdirs();<br />}</p>
		<p>编译该servlet，注意要指定classpath，确保包含commons-upload-1.0.jar和tomcat\common\lib\servlet-api.jar。</p>
		<p>配置servlet，用记事本打开tomcat\webapps\你的webapp\WEB-INF\web.xml，没有的话新建一个。典型配置如下：</p>
		<p>&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;<br />&lt;!DOCTYPE web-app<br />    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<br />    "<a href="http://java.sun.com/dtd/web-app_2_3.dtd" target="_blank"><font color="#000000">http://java.sun.com/dtd/web-app_2_3.dtd</font></a>"&gt;</p>
		<p>&lt;web-app&gt;<br />    &lt;servlet&gt;<br />        &lt;servlet-name&gt;Upload&lt;/servlet-name&gt;<br />        &lt;servlet-class&gt;Upload&lt;/servlet-class&gt;<br />    &lt;/servlet&gt;</p>
		<p>    &lt;servlet-mapping&gt;<br />        &lt;servlet-name&gt;Upload&lt;/servlet-name&gt;<br />        &lt;url-pattern&gt;/fileupload&lt;/url-pattern&gt;<br />    &lt;/servlet-mapping&gt;<br />&lt;/web-app&gt;</p>
		<p>
				<br />配置好servlet后，启动tomcat，写一个简单的html测试：</p>
		<p>&lt;form action="fileupload" method="post"<br />enctype="multipart/form-data" name="form1"&gt;<br />  &lt;input type="file" name="file"&gt;<br />  &lt;input type="submit" name="Submit" value="upload"&gt;<br />&lt;/form&gt;</p>
		<p>注意action="fileupload"其中fileupload是配置servlet时指定的url-pattern。<br /></p>
<img src ="http://www.blogjava.net/ltc603/aggbug/30168.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/ltc603/" target="_blank">阿成</a> 2006-02-10 15:52 <a href="http://www.blogjava.net/ltc603/archive/2006/02/10/30168.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>