﻿<?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-lanxin1020-随笔分类-struts2</title><link>http://www.blogjava.net/lanxin1020/category/38971.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 15 Apr 2009 09:47:43 GMT</lastBuildDate><pubDate>Wed, 15 Apr 2009 09:47:43 GMT</pubDate><ttl>60</ttl><item><title>struts2原理(转)</title><link>http://www.blogjava.net/lanxin1020/archive/2009/04/15/265744.html</link><dc:creator>lanxin1020</dc:creator><author>lanxin1020</author><pubDate>Wed, 15 Apr 2009 06:03:00 GMT</pubDate><guid>http://www.blogjava.net/lanxin1020/archive/2009/04/15/265744.html</guid><wfw:comment>http://www.blogjava.net/lanxin1020/comments/265744.html</wfw:comment><comments>http://www.blogjava.net/lanxin1020/archive/2009/04/15/265744.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lanxin1020/comments/commentRss/265744.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lanxin1020/services/trackbacks/265744.html</trackback:ping><description><![CDATA[1.Struts 2的基本流程 <br />
&nbsp; Struts 2框架由3个部分组成：核心控制器FilterDispatcher、业务控制器和用户实现的业务逻辑组件。在这3个部分里，Struts 2框架提供了核心控制器FilterDispatcher，而用户需要实现业务控制器和业务逻辑组件。 <br />
2.核心控制器：FilterDispatcher <br />
&nbsp; FilterDispatcher是Struts 2框架的核心控制器，该控制器作为一个Filter运行在Web应用中，它负责拦截所有的用户请求，当用户请求到达时，该Filter会过滤用户请求。如果用户请求以action结尾，该请求将被转入Struts 2框架处理。 <br />
<br />
Struts 2框架获得了*.action请求后，将根据*.action请求的前面部分决定调用哪个业务逻辑组件，例如，对于login.action请求，Struts 2调用名为login的Action来处理该请求。 <br />
<br />
Struts 2应用中的Action都被定义在struts.xml文件中，在该文件中定义Action时，定义了该Action的name属性和class属性，其中name属性决定了该Action处理哪个用户请求，而class属性决定了该Action的实现类。 <br />
<br />
Struts 2用于处理用户请求的Action实例，并不是用户实现的业务控制器，而是Action代理——因为用户实现的业务控制器并没有与Servlet API耦合，显然无法处理用户请求。而Struts 2框架提供了系列拦截器，该系列拦截器负责将HttpServletRequest请求中的请求参数解析出来，传入到Action中，并回调Action 的execute方法来处理用户请求。 <br />
<br />
显然，上面的处理过程是典型的AOP（面向切面编程）处理方式。图3.19显示了这种处理模型。 <br />
<br />
<br />
<br />
图3.19&nbsp; Struts 2的拦截器和Action <br />
<br />
从图3.19中可以看出，用户实现的Action类仅仅是Struts 2的Action代理的代理目标。用户实现的业务控制器（Action）则包含了对用户请求的处理。用户的请求数据包含在 HttpServletRequest对象里，而用户的Action类无需访问HttpServletRequest对象。拦截器负责将 HttpServletRequest里的请求数据解析出来，并传给业务逻辑组件Action实例。 <br />
3.业务控制器 <br />
&nbsp; 正如从图3.19所看到的，业务控制器组件就是用户实现Action类的实例，Action类里通常包含了一个execute方法，该方法返回一个字符串——该字符串就是一个逻辑视图名，当业务控制器处理完用户请求后，根据处理结果不同，execute方法返回不同字符串&nbsp;&nbsp; ——每个字符串对应一个视图名。 <br />
<br />
程序员开发出系统所需要的业务控制器后，还需要配置Struts 2的Action，即需要配置Action的如下三个部分定义： <br />
<br />
—&nbsp; Action所处理的URL。 <br />
<br />
—&nbsp; Action组件所对应的实现类。 <br />
<br />
—&nbsp; Action里包含的逻辑视图和物理资源之间的对应关系。 <br />
<br />
每个Action都要处理一个用户请求，而用户请求总是包含了指定URL。当Filter Dispatcher拦截到用户请求后，根据请求的URL和Action处理URL之间的对应关系来处理转发。 <br />
4.Struts 2的模型组件 <br />
&nbsp; 实际上，模型组件已经超出了MVC框架的覆盖范围。对于Struts 2框架而言，通常没有为模型组件的实现提供太多的帮助。 <br />
<br />
文本框: 图3.20 控制器调用模型组件Java EE应用里的模型组件，通常指系统的业务逻辑组件。而隐藏在系统的业务逻辑组件下面的，可能还包含了DAO、领域对象等组件。 <br />
<br />
通常，MVC框架里的业务控制器会调用模型组件的方法来处理用户请求。也就是说，业务逻辑控制器不会对用户请求进行任何实际处理，用户请求最终由模型组件负责处理。业务控制器只是中间负责调度的调度器，这也是称Action为控制器的原因。 <br />
<br />
<br />
图3.20显示了这种处理流程。 <br />
<br />
提示&nbsp; 在图3.20中看到Action调用业务逻辑组件的方法。当控制器需要获得业务逻辑组件实例时，通常并不会直接获取业务逻辑组件实例，而是通过工厂模式来获得业务逻辑组件的实例；或者利用其他IoC容器（如Spring容器）来管理业务逻辑组件的实例。 <br />
5.Struts 2的视图组件 <br />
&nbsp; Struts 2已经改变了Struts 1只能使用JSP作为视图技术的现状，Struts 2允许使用其他的模板技术，如FreeMarker、Velocity作为视图技术。 <br />
<br />
当Struts 2的控制器返回逻辑视图名时，逻辑视图并未与任何的视图技术关联，仅仅是返回一个字符串，该字符串作为逻辑视图名。 <br />
<br />
当我们在struts.xml文件中配置 Action时，不仅需要指定Action的name属性和class属性，还要为Action元素指定系列result子元素，每个result子元素定义一个逻辑视图和物理视图之间的映射。前面所介绍的应用都使用了JSP技术作为视图，故配置result子元素时没有指定type属性，默认使用JSP 作为视图资源。 <br />
<br />
如果需要在Struts 2中使用其他视图技术，则可以在配置result子元素时，指定相应的type属性即可。例如，如果需要使用FreeMarker，则为result指定值为freemarker的type属性；如果想使用Velocity模板技术作为视图资源，则为result指定值为velocity的type属性&#8230;&#8230; <br />
6.Struts 2的运行流程 <br />
&nbsp; 经过上面介绍，我们发现Struts 2框架的运行流程非常类似于<span class="hilite1">WebWork</span>框架的流程。 <br />
<br />
提示&nbsp; 在Struts 2的官方站点，我们可以找到如下说法：Essentially，Struts 2.0 is the technical equivalent of <span class="hilite1">WebWork</span> 2.3。Aside from the package and property renaming，it isn't much different than，say，migrating from <span class="hilite1">WebWork</span> 2.1 to 2.2——意思是说：Struts 2.0技术等同于<span class="hilite1">WebWork</span> 2.3框架，除了包和属性被改名外。从<span class="hilite1">WebWork</span> 2.2迁移到Struts 2不会比从<span class="hilite1">WebWork</span> 2.1迁移到<span class="hilite1">WebWork</span> 2.2更复杂。 <br />
<br />
这里我们可以看到，Struts 2其实就是<span class="hilite1">WebWork</span> 2.2的升级版，这也就不难理解：为什么<span class="hilite1">WebWork</span>和Struts 2如此相似！ <br />
<br />
因此，Struts 2的运行流程与<span class="hilite1">WebWork</span>的运行流程完全相同，读者可以参看图1.8来了解Struts 2的运行流程。 <br />
<img src ="http://www.blogjava.net/lanxin1020/aggbug/265744.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lanxin1020/" target="_blank">lanxin1020</a> 2009-04-15 14:03 <a href="http://www.blogjava.net/lanxin1020/archive/2009/04/15/265744.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>struts2 使用 jakarta 上传文件时commons fileupload的异常捕捉（转自alfred.w）</title><link>http://www.blogjava.net/lanxin1020/archive/2009/04/14/265476.html</link><dc:creator>lanxin1020</dc:creator><author>lanxin1020</author><pubDate>Tue, 14 Apr 2009 04:50:00 GMT</pubDate><guid>http://www.blogjava.net/lanxin1020/archive/2009/04/14/265476.html</guid><wfw:comment>http://www.blogjava.net/lanxin1020/comments/265476.html</wfw:comment><comments>http://www.blogjava.net/lanxin1020/archive/2009/04/14/265476.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lanxin1020/comments/commentRss/265476.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lanxin1020/services/trackbacks/265476.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 问题：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struts2 使用jakarta 上传文件时，如果上传文件的大小超出commons fileupload(jakarta上传文件还是依赖commons-fileupload)设置的大小就会在进入action以前抛出异常.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb...&nbsp;&nbsp;<a href='http://www.blogjava.net/lanxin1020/archive/2009/04/14/265476.html'>阅读全文</a><img src ="http://www.blogjava.net/lanxin1020/aggbug/265476.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lanxin1020/" target="_blank">lanxin1020</a> 2009-04-14 12:50 <a href="http://www.blogjava.net/lanxin1020/archive/2009/04/14/265476.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>主题：谈谈我对Struts2文件上传的理解(转自 netfork)</title><link>http://www.blogjava.net/lanxin1020/archive/2009/04/14/265473.html</link><dc:creator>lanxin1020</dc:creator><author>lanxin1020</author><pubDate>Tue, 14 Apr 2009 04:46:00 GMT</pubDate><guid>http://www.blogjava.net/lanxin1020/archive/2009/04/14/265473.html</guid><wfw:comment>http://www.blogjava.net/lanxin1020/comments/265473.html</wfw:comment><comments>http://www.blogjava.net/lanxin1020/archive/2009/04/14/265473.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lanxin1020/comments/commentRss/265473.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lanxin1020/services/trackbacks/265473.html</trackback:ping><description><![CDATA[<p><a href="/topic/287800"></a>&nbsp;</p>
下文书中包的版本：commons-fileupload-1.2.1.jar、struts2-core-2.1.2.jar <br />
<br />
孙鑫的书《Struts2 深入详解》509页是关于限制上传文件的最大长度的内容。 <br />
其中谈到fileUpload拦截器只是当文件上传到服务器上之后，才进行的文件类型和大小判断。 <br />
Struts2框架底层默认用的是apache的commons-fileupload组件对上传文件进行接受处理。 <br />
通过struts.multipart.maxSize属性来对文件大小进行限定时，将直接影响到commons-fileupload组件的文件大小设定，默认是2M。当上传文件超过了这个尺寸时，将从commons-fileupload组件中抛出SizeLimitExceededException异常。上传文件拦截器捕获到这个异常后，将直接把该异常信息设置为Action级别的错误信息。 <br />
<br />
经过我的测试和对源代码的Debug，发现确实如孙鑫书中所言，如果上传文件大于2M时，在页面上就出现了一堆英文的错误信息，大致是：the request was rejected because its size....exceeds the configured maximum...并且在fieUpload中将来自MultiPartRequestWrapper型request对象的错误信息给加到了Action的错误中。 <br />
<br />
这时候，你在ApplicationResources.properties中自定义的上传文件过大的错误信息根本不起作用。原因就如书上所言，在底层commons-fileupload组件中就把异常给抛出来了文件根本没被上传，所以到了fileUpload拦截器时，根据取不到文件，当然也就没法对文件的类型和大小进行判断了。 <br />
<span style="color: red"><br />
<strong>然而，这个异常直接带来两个问题：</strong></span> <br />
<strong>1、在页面上显示了英文的错误信息。这样的信息显然不是我们想要的。 <br />
2、由于错误的产生，原来页面上输入的其他文本内容也都不见了，也就是说params注入失败。</strong> <br />
<br />
带着这两个问题，我们来探寻一下Struts2对于请求的处理过程。 <br />
注：这并不是一篇关于Struts2请求过程的介绍，主要是为了解决以上两个问题，才引起的简单分析。 <br />
<br />
<strong>首先当然我们要拿FilterDispatcher开刀。</strong> <br />
<br />
在doFilter方法中调用了prepareDispatcherAndWrapRequest方法，为了包装出Struts2自己的request对象，在prepareDispatcherAndWrapRequest方法中调用Dispatcher类的wrapRequest方法，在这个方法里，会根据请求内容的类型(提交的是文本的，还是multipart/form-data格式)，决定是使用tomcat的HttpServletRequestWrapper类分离出请求中的数据，还是使用Struts2的MultiPartRequestWrapper来分离请求中的数据。 <br />
注：向服务器请求时，数据是以流的形式向服务器提交，内容是一些有规则东东，我们平时在jsp中用request内置对象取parameter时，实际上是由tomcat的HttpServletRequestWrapper类分解好了的，无需我们再分解这些东西了。 <br />
<br />
当然，在这里，我们研究的是上传文件的情况，所以，由于form中设定的提交内容是媒体格式的，所以，Dispatcher类的wrapRequest方法会将请求交由MultiPartRequestWrapper类来处理。 <br />
<br />
MultiPartRequestWrapper这个类是Struts2的类，并且继承了tomcat的HttpServletRequestWrapper类，也是我们将用来代替HttpServletRequest这个类的类，看名字也知道，是对多媒体请求的包装类。 <br />
Struts2本身当然不会再造个轮子，来解析请求，而是交由Apache的commons-fileupload组件来解析了。 <br />
在MultiPartRequestWrapper的构造方法中，会调用MultiPartRequest（默认为JakartaMultiPartRequest类）的parse方法来解析请求。 <br />
<br />
在Struts2的JakartaMultiPartRequest类的parse方法中才会真正来调用commons-fileupload组件的ServletFileUpload类对请求进行解析，至此，Struts2已经实现了将请求转交commons-fileupload组件对请求解析的全过程。剩下的就是等commons-fileupload组件对请求解析完毕后，拿到分解后的数据，根据field名，依次将分解后的field名和值放到params（HashMap类型）里，同时JakartaMultiPartRequest类重置了HttpServletRequest的好多方法，比如熟知的getParameter、getParameterNames、getParameterValues，实际上都是从解析后得到的那个params对象里拿数据，在这个过程，commons-fileupload组件也乖乖的把上传的文件分析好了，JakartaMultiPartRequest也毫不客气的把分解后的文件一个一个的放到了files（HashMap类型）中，实际上此时，commons-fileupload组件已经所有要上传的文件上传完了。至此，Struts2实现了对HttpServletRequest类的包装，当回到MultiPartRequestWrapper类后，再取一下上述解析过程中发生的错误，然后把错误加到了自己的errors列表中了。同样我们会发现在MultiPartRequestWrapper类中，也把HttpServletRequest类的好多方法重载了，毕竟是个包装类嘛，实际上对于上传文件的请求，在Struts2后期的处理中用到的request都是MultiPartRequestWrapper类对象，比如我们调用getParameter时，直接调用的是MultiPartRequestWrapper的getParameter方法，间接调的是JakartaMultiPartRequest类对象的getParameter方法。 <br />
注：从这里，我们就可以看出，JakartaMultiPartRequest是完全设计成可以替换的类了。 <br />
<br />
然后继续向回返，到了Dispatcher类的wrapRequest方法，直接把MultiPartRequestWrapper对象返回了，我们就终于回到了FilterDispatcher类的prepareDispatcherAndWrapRequest方法，此时，我们拿到了完全解析好了的request对象（MultiPartRequestWrapper类），该对象又进一步被返回到了FilterDispatcher类的doFilter方法，也就是回到了出发点，至此，doFilter中拿到的request对象就是一个将请求中的数据分解好的了HttpServletRequest对象，我们完全可以用getParameter方法取其中的数据了，同时，我们也可以用getFiles得到文件数组了。 <br />
doFilter方法中，会进一步调用actionMapper的getMapping方法对url进行解析，找出命名空间和action名等，以备后面根据配置文件调用相应的拦截器和action使用。 <br />
<br />
关于doFilter方法中下一步对Dispatcher类的serviceAction方法的调用，不再描述，总之在action被调用之前，会首先走到fileUpload拦截器（对应的是FileUploadInterceptor类），在这个拦截器中，会先看一下request是不是 MultiPartRequestWrapper,如果不是，就说明不是上传文件用的request，fildUpload拦截器会直接将控制权交给下一个拦截器；如果是，就会把request对象强转为MultiPartRequestWrapper对象，然后调用hasErrors方法，看看有没有上传时候产生的错误，有的话，就直接加到了Action的错误（Action级别的）中了。另外，在fileUpload拦截器中会将MultiPartRequestWrapper对象中放置的文件全取出来，把文件、文件名、文件类型取出来，放到request的parameters中，这样到了params拦截器时，就可以轻松的将这些内容注入到Action中了，这也就是为什么fileUpload拦截器需要放在params拦截器前面的理由。在文件都放到request的parameters对象里之后，fileUpload拦截器会继续调用其他拦截器直到Action等执行完毕，他还要做一个扫尾的工作：把临时文件夹中的文件删除（这些文件是由commons-fileupload组件上传的，供你在自己的Action中将文件copy到指定的目录下，当action执行完了后，这些临时文件当然就没用了）。 <br />
<br />
<strong>你好，你还在看吗？</strong>呵呵，是不是太多了，也太乱了，没办法，Struts2就是这样的调用的。也不知道Struts2有没有公开其Sequence图，我是想画一个，不过，太懒，还是看着代码说说吧。 <br />
<br />
<span style="color: red"><strong>如果上面看烦了，也完全可以不看了，直接看下面的。</strong></span> <br />
<br />
在上面一番分析之后，文件上传的全过程就结束了。 <br />
我们回到我们的问题上来。 <br />
<br />
先看第一个： <br />
<strong>1、在页面上显示了英文的错误信息。这显然不是我们想要的。</strong> <br />
<br />
没办法了，commons-fileupload组件没想到国际化，在FileUploadInterceptor拦载器中，也没想着国际化，直接放到Action的错误中了，就没他事了，三种做法： <br />
　　(1)在错误显示之前，把这条错误给换掉，应该难度不大，我没做留给你做了。 <br />
　　(2)或者重写一下JakartaMultiPartRequest这个类，把捕捉到的异常信息换成自己的，然后，通过Struts2的配置文件，把我们重写的这个parser换上去用。 <br />
　　(3)直接改commons-fileupload组件的类，换成中文的。 <br />
我具体说一下第(3)种做法：找到FileUploadBase类，把902行～908行改一下。 <br />
FileUploadException ex = <br />
&nbsp;&nbsp;&nbsp; new SizeLimitExceededException( <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "the request was rejected because" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + " its size (" + pCount <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + ") exceeds the configured maximum" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + " (" + pSizeMax + ")", <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pCount, pSizeMax); <br />
=&gt; <br />
FileUploadException ex = new SizeLimitExceededException( <br />
"服务器拒绝了您的请求，原因可能是向服务器提交的数据发生了丢失。", pCount, pSizeMax); <br />
<br />
把914行～918行改一下。 <br />
throw new SizeLimitExceededException( <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "the request was rejected because its size (" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + requestSize <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + ") exceeds the configured maximum (" <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + sizeMax + ")", <br />
=&gt; <br />
throw new SizeLimitExceededException("服务器拒绝了您的请求，原因是提交数据量过大(通常是由于上传文件过大)，请返回上页重试。" <br />
+ " (最大字节数：" + sizeMax / 1024 <br />
+ "K)", requestSize, sizeMax); <br />
<br />
<br />
再看一下第二个问题。 <br />
<strong>2、由于错误的产生，原来页面上输入的内容也全部不见了，也就是说params注入失败。</strong> <br />
关于这个问题我在javaeye上搜索到一篇文章（使用的commons-fileupload组件的jar包似乎比较老）。 <br />
<a href="http://www.javaeye.com/topic/197345" target="_blank">http://www.javaeye.com/topic/197345</a> <br />
<br />
虽然按照此文，当上传失败时，能够将其他输入内容显示出来，但是这样做的结果是全部的文件肯定会上传到服务器上，也就是说，虽然是页面上报了文件因为太大，请求被拒绝的错，但是文件依然会被上传到服务器上，commons-fileupload组件根本没会去拦文件的上传。 <br />
在这里要说明一下，如果你不抛出这个异常，请求的流会继续向服务器上传，只有当整个流上传完了之后，commons-fileupload组件才能正确的分析出文件部分、文本部分。所以，在这里抛出异常是不得已的作法，如果不抛异常，后果是虽然页面报错，但文件还是会被传到服务器的上，这一步根本没挡住输入流的上传，如果没挡住的话，大家想想会有什么后果？ <br />
所以，综上所述，对于第二个问题，如果出现了这个异常，我们根本无法让原来输入的内容还显示出来的，因为commons-fileupload组件并没有解析全部的输入内容，直接给出异常了，到了params拦截器中，request里就是空的，根本取不到parameter，所以也就无法注入到Action中了。这种情况下，只能显示一个告知用户由于提交数据量过大，服务器拒绝了请求的错误信息，比较好的方法是，直接跳到一个专门的页面，提示用户，然后让用户点返回来再次输入，否则用户会感觉上传文件大就大吧，怎么连我输入的其他一些内容也没给保存住。当然，如果能用Ajax来上传文件，对客户的操作体验可能是最好的，但是，这样可能会导致服务器上有些挂空的文件（上传后从来没被用过），需要想法清除的。 <br />
<br />
整个分析下来，我们说第二个问题基本上是无法避免的。 <br />
 <img src ="http://www.blogjava.net/lanxin1020/aggbug/265473.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lanxin1020/" target="_blank">lanxin1020</a> 2009-04-14 12:46 <a href="http://www.blogjava.net/lanxin1020/archive/2009/04/14/265473.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>webservice 概述(转自linliangyi2007)</title><link>http://www.blogjava.net/lanxin1020/archive/2009/04/13/265351.html</link><dc:creator>lanxin1020</dc:creator><author>lanxin1020</author><pubDate>Mon, 13 Apr 2009 10:37:00 GMT</pubDate><guid>http://www.blogjava.net/lanxin1020/archive/2009/04/13/265351.html</guid><wfw:comment>http://www.blogjava.net/lanxin1020/comments/265351.html</wfw:comment><comments>http://www.blogjava.net/lanxin1020/archive/2009/04/13/265351.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lanxin1020/comments/commentRss/265351.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lanxin1020/services/trackbacks/265351.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Web Service概述 Web Service的定义 W3C组织对其的定义如下，它是一个软件系统，为了支持跨网络的机器间相互操作交互而设计。Web Service服务通常被定义为一组模块化的API，它们可以通过网络进行调用，来执行远程系统的请求服务。 这里我们从一个程序员的视角来观察web service。在传统的程序编码中，存在这各种的函数方法调用。通常，我们知道一个程序...&nbsp;&nbsp;<a href='http://www.blogjava.net/lanxin1020/archive/2009/04/13/265351.html'>阅读全文</a><img src ="http://www.blogjava.net/lanxin1020/aggbug/265351.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lanxin1020/" target="_blank">lanxin1020</a> 2009-04-13 18:37 <a href="http://www.blogjava.net/lanxin1020/archive/2009/04/13/265351.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>10Struts2文件上传功能开发（转自黑暗浪子）</title><link>http://www.blogjava.net/lanxin1020/archive/2009/04/13/265297.html</link><dc:creator>lanxin1020</dc:creator><author>lanxin1020</author><pubDate>Mon, 13 Apr 2009 07:33:00 GMT</pubDate><guid>http://www.blogjava.net/lanxin1020/archive/2009/04/13/265297.html</guid><wfw:comment>http://www.blogjava.net/lanxin1020/comments/265297.html</wfw:comment><comments>http://www.blogjava.net/lanxin1020/archive/2009/04/13/265297.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lanxin1020/comments/commentRss/265297.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lanxin1020/services/trackbacks/265297.html</trackback:ping><description><![CDATA[技术要点 <br />
本节代码详细说明文件上传功能的开发流程，介绍知识点如下： <br />
<div style="text-align: left"> 文件上传页面和显示上传成功页面代码内容。 <br />
 UploadAction类中实现上传功能方法和上传文件属性介绍。 <br />
 struts.xml中UploadAction配置，以及字符编码、文件临时存放路径配置。 <br />
 上传后所处路径和最终上传成功后效果展示。</div>
<br />
演示代码 <br />
上传文件页面，这里笔者定义的是多个文件上传。 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 </div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;!---------------------文件名：upload.jsp-----------------&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;%</span><span class="annotation">@taglib</span><span>&nbsp;prefix=</span><span class="string">"s"</span><span>&nbsp;uri=</span><span class="string">"/struts-tags"</span><span>%&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;html&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;head&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;meta&nbsp;http-equiv=</span><span class="string">"Content-Type"</span><span>&nbsp;content=</span><span class="string">"text/html;&nbsp;charset=gb2312"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;上传文件&lt;/title&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/head&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;body&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;上传文件表单定义&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;s:form&nbsp;action=</span><span class="string">"upload"</span><span>&nbsp;method=</span><span class="string">"post"</span><span>&nbsp;enctype=</span><span class="string">"multipart/form-data"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;上传文件标签定义&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&gt;上传文件:&lt;s:file&nbsp;name=</span><span class="string">"file"</span><span>&gt;&lt;/s:file&gt;&lt;/td&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&gt;再次上传文件:&lt;s:file&nbsp;name=</span><span class="string">"file"</span><span>&gt;&lt;/s:file&gt;&lt;/td&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&nbsp;align=</span><span class="string">"left"</span><span>&gt;&lt;s:submit&nbsp;name=</span><span class="string">"submit"</span><span>&nbsp;value=</span><span class="string">"提交"</span><span>&gt;&lt;/s:submit&gt;&lt;/td&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/s:form&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/body&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/html&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none" class="java" name="code">&lt;!---------------------文件名：upload.jsp-----------------&gt;
&lt;%@taglib prefix="s" uri="/struts-tags"%&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;
&lt;title&gt;上传文件&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;!-- 上传文件表单定义 --&gt;
&lt;s:form action="upload" method="post" enctype="multipart/form-data"&gt;
&lt;tr&gt;
&lt;!-- 上传文件标签定义 --&gt;
&lt;td&gt;上传文件:&lt;s:file name="file"&gt;&lt;/s:file&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;再次上传文件:&lt;s:file name="file"&gt;&lt;/s:file&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align="left"&gt;&lt;s:submit name="submit" value="提交"&gt;&lt;/s:submit&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/s:form&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<br />
上传文件成功后结果页面 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 </div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;!-------------------文件名：result.jsp&nbsp;-----------------&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;%</span><span class="annotation">@taglib</span><span>&nbsp;prefix=</span><span class="string">"s"</span><span>&nbsp;uri=</span><span class="string">"/struts-tags"</span><span>%&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;html&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;head&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;meta&nbsp;http-equiv=</span><span class="string">"Content-Type"</span><span>&nbsp;content=</span><span class="string">"text/html;&nbsp;charset=gb2312"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;title&gt;上传结果&lt;/title&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/head&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;body&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;上传文件： &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;显示上传成功文件名&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;s:property&nbsp;value=</span><span class="string">"fileFileName"</span><span>&nbsp;/&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/body&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/html&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none" class="java" name="code">&lt;!-------------------文件名：result.jsp -----------------&gt;
&lt;%@taglib prefix="s" uri="/struts-tags"%&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=gb2312"&gt;
&lt;title&gt;上传结果&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
上传文件：
&lt;!-- 显示上传成功文件名 --&gt;
&lt;s:property value="fileFileName" /&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<br />
UploadAction类代码 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 </div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;!------------------文件名：UploadAction.java&nbsp;------------------&gt; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;java.io.File; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;java.io.FileInputStream; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;java.io.FileNotFoundException; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;java.io.FileOutputStream; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;java.io.IOException; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;java.io.InputStream; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;java.io.OutputStream; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;java.util.List; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span class="keyword">import</span><span>&nbsp;org.apache.struts2.ServletActionContext; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;com.opensymphony.xwork2.ActionSupport; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span class="comment">//文件上传Action </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;UploadAction&nbsp;</span><span class="keyword">extends</span><span>&nbsp;ActionSupport&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//上传文件存放路径 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;String&nbsp;UPLOADDIR&nbsp;=&nbsp;</span><span class="string">"/upload"</span><span>; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//上传文件集合 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;List&lt;File&gt;&nbsp;file; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//上传文件名集合 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;List&lt;String&gt;&nbsp;fileFileName; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//上传文件内容类型集合 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;List&lt;String&gt;&nbsp;fileContentType; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;List&lt;File&gt;&nbsp;getFile()&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;file; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setFile(List&lt;File&gt;&nbsp;file)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.file&nbsp;=&nbsp;file; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;List&lt;String&gt;&nbsp;getFileFileName()&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;fileFileName; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setFileFileName(List&lt;String&gt;&nbsp;fileFileName)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.fileFileName&nbsp;=&nbsp;fileFileName; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;List&lt;String&gt;&nbsp;getFileContentType()&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;fileContentType; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setFileContentType(List&lt;String&gt;&nbsp;fileContentType)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.fileContentType&nbsp;=&nbsp;fileContentType; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;String&nbsp;execute()&nbsp;</span><span class="keyword">throws</span><span>&nbsp;Exception&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">int</span><span>&nbsp;i&nbsp;=&nbsp;</span><span class="number">0</span><span>;&nbsp;i&nbsp;&lt;&nbsp;file.size();&nbsp;i++)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//循环上传每个文件 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;uploadFile(i); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;</span><span class="string">"success"</span><span>; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//执行上传功能 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;uploadFile(</span><span class="keyword">int</span><span>&nbsp;i)&nbsp;</span><span class="keyword">throws</span><span>&nbsp;FileNotFoundException,&nbsp;IOException&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputStream&nbsp;in&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;FileInputStream(file.get(i)); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;dir&nbsp;=&nbsp;ServletActionContext.getRequest().getRealPath(UPLOADDIR); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File&nbsp;uploadFile&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;File(dir,&nbsp;</span><span class="keyword">this</span><span>.getFileFileName().get(i)); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OutputStream&nbsp;out&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;FileOutputStream(uploadFile); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">byte</span><span>[]&nbsp;buffer&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;</span><span class="keyword">byte</span><span>[</span><span class="number">1024</span><span>&nbsp;*&nbsp;</span><span class="number">1024</span><span>]; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">int</span><span>&nbsp;length; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">while</span><span>&nbsp;((length&nbsp;=&nbsp;in.read(buffer))&nbsp;&gt;&nbsp;</span><span class="number">0</span><span>)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.write(buffer,&nbsp;</span><span class="number">0</span><span>,&nbsp;length); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;in.close(); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;out.close(); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span class="keyword">catch</span><span>&nbsp;(FileNotFoundException&nbsp;ex)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ex.printStackTrace(); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span class="keyword">catch</span><span>&nbsp;(IOException&nbsp;ex)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ex.printStackTrace(); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none" class="java" name="code">&lt;!------------------文件名：UploadAction.java ------------------&gt;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
//文件上传Action
public class UploadAction extends ActionSupport {
//上传文件存放路径
private final static String UPLOADDIR = "/upload";
//上传文件集合
private List&lt;File&gt; file;
//上传文件名集合
private List&lt;String&gt; fileFileName;
//上传文件内容类型集合
private List&lt;String&gt; fileContentType;
public List&lt;File&gt; getFile() {
return file;
}
public void setFile(List&lt;File&gt; file) {
this.file = file;
}
public List&lt;String&gt; getFileFileName() {
return fileFileName;
}
public void setFileFileName(List&lt;String&gt; fileFileName) {
this.fileFileName = fileFileName;
}
public List&lt;String&gt; getFileContentType() {
return fileContentType;
}
public void setFileContentType(List&lt;String&gt; fileContentType) {
this.fileContentType = fileContentType;
}
public String execute() throws Exception {
for (int i = 0; i &lt; file.size(); i++) {
//循环上传每个文件
uploadFile(i);
}
return "success";
}
//执行上传功能
private void uploadFile(int i) throws FileNotFoundException, IOException {
try {
InputStream in = new FileInputStream(file.get(i));
String dir = ServletActionContext.getRequest().getRealPath(UPLOADDIR);
File uploadFile = new File(dir, this.getFileFileName().get(i));
OutputStream out = new FileOutputStream(uploadFile);
byte[] buffer = new byte[1024 * 1024];
int length;
while ((length = in.read(buffer)) &gt; 0) {
out.write(buffer, 0, length);
}
in.close();
out.close();
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}</pre>
<br />
struts.xml配置文件中有关文件上传的配置： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 </div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;!--------------------文件名：struts.xml-------------------&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;struts&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;系统常量定义，定义上传文件字符集编码&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;constant&nbsp;name=</span><span class="string">"struts.i18n.encoding"</span><span>&nbsp;value=</span><span class="string">"gb2312"</span><span>&gt;&lt;/constant&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;系统常量定义，定义上传文件临时存放路径&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;constant&nbsp;name=</span><span class="string">"struts.multipart.saveDir"</span><span>&nbsp;value=</span><span class="string">"c:\"</span><span>&gt;&lt;/constant&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;Action所在包定义&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span class="keyword">package</span><span>&nbsp;name=</span><span class="string">"C04.4"</span><span>&nbsp;</span><span class="keyword">extends</span><span>=</span><span class="string">"struts-default"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;Action名字，类以及导航页面定义&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;通过Action类处理才导航的的Action定义&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;action&nbsp;name=</span><span class="string">"upload"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"action.UploadAction"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;result&nbsp;name=</span><span class="string">"input"</span><span>&gt;/jsp/upload.jsp&lt;/result&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;result&nbsp;name=</span><span class="string">"success"</span><span>&gt;/jsp/result.jsp&lt;/result&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/action&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span class="keyword">package</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;/struts&gt;&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none" class="java" name="code">&lt;!--------------------文件名：struts.xml-------------------&gt;
&lt;struts&gt;
&lt;!-- 系统常量定义，定义上传文件字符集编码 --&gt;
&lt;constant name="struts.i18n.encoding" value="gb2312"&gt;&lt;/constant&gt;
&lt;!-- 系统常量定义，定义上传文件临时存放路径 --&gt;
&lt;constant name="struts.multipart.saveDir" value="c:\"&gt;&lt;/constant&gt;
&lt;!-- Action所在包定义 --&gt;
&lt;package name="C04.4" extends="struts-default"&gt;
&lt;!-- Action名字，类以及导航页面定义 --&gt;
&lt;!-- 通过Action类处理才导航的的Action定义 --&gt;
&lt;action name="upload" class="action.UploadAction"&gt;
&lt;result name="input"&gt;/jsp/upload.jsp&lt;/result&gt;
&lt;result name="success"&gt;/jsp/result.jsp&lt;/result&gt;
&lt;/action&gt;
&lt;/package&gt;
&lt;/struts&gt; </pre>
<br />
（1）：文件上传页面如图4.8所示。 <br />
<br />
图4.8&nbsp; 文件上传 <br />
（2）：选择文件如图4.9所示。 <br />
<br />
图4.9&nbsp; 选择上传的文件 <br />
（3）：单击&#8220;提交&#8221;按钮后文件上传成功页面，并显示上传文件名，如图4.10所示。 <br />
<br />
图4.10&nbsp; 上传文件成功后效果 <br />
（4）：两个被上传文件最终在服务器上存放路径效果如图4.11所示。 <br />
<br />
图4.11&nbsp; 上传文件存放路径图 <br />
代码解释 <br />
（1）在upload.jsp中通过Form标签和File标签定义了两个上传文件。Struts2标签笔者会在之后章节里具体介绍，这里只是让读者知道是如何使用标签显示图4.8显示的内容。如果上传成功，笔者在result.jsp中&#8220;[&#8221;和&#8220;]&#8221;之间显示上传文件的文件名，如果是多个文件，以&#8220;，&#8221;相隔。这些显示格式都是用Property标签定义的。 <br />
注意：如果上传文件，在JSP的Form中一定要定义如upload.jsp文件中黑体表示的部分。method和enctype属性都必须要如代码中所示。这样Form中上传文件才会起作用。 <br />
（2）UploadAction文件中先定义了常量UPLOADDIR，它是上传文件上传后存放的文件夹名字。比如笔者使用的是JBoss（附录中有安装和在MyEclipse中部署的操作说明），则在它的已部署Web项目下的upload文件夹中，会有所有上传成功的文件。如图4.11读者也可以看见它的上传文件最终存放路径。 <br />
注意：在MyEclipse中开发的&#8220;WebRoot&#8221;目录下也要新建一个upload文件夹，否则部署后在JBoss的已部署Web项目下将没有upload文件夹。因为部署的时候会将所有&#8220;WebRoot&#8221;目录下的文件夹和文件都部署到JBoss的已部署Web项目下。 <br />
定义好UPLOADDIR后，在定义上传文件的属性变量。也许其中的&#8220;fileFileName&#8221;和&#8220;fileContentType&#8221;读者看了有点别扭，尤其是&#8220;fileFileName&#8221;感觉不符合Java命名规范，但是这两个属性变量是4.1小节中介绍的&#8220;fileUpload&#8221;拦截器类中的类公有变量名字，只有这样定义，UploadAction执行时候会把在页面上选择的上传文件的属性值放在这两个变量里面，否则调试UploadAction时候会发现这两个变量都会是&#8220;null&#8221;即空值。不相信的读者可以自行改变这两个变量名再执行上传文件功能进行调试看一下这两个变量得到的值。 <br />
注意：因为这里笔者是进行多个文件上传功能开发，因此&#8220;file&#8221;、&#8220;fileFileName&#8221;、&#8220;fileFileName&#8221;属性变量都设定为List类型，其实还可以设定为数组类型。个人觉得没有啥大区别。完全凭个人喜好而定。还有如果读者自己开发单个文件上传，就没必要把它们设定为List类型或数组类型。直接把&#8220;file&#8221;定义为Java的IO包中的File类型，&#8220;fileFileName&#8221;、&#8220;fileFileName&#8221;定义为普通的String类型即字符串类型。 <br />
之后在execute方法中，写一个循环，对所有页面中选择的上传文件一个个进行上传。这里笔者运用了重构中的&#8220;抽取方法&#8221;的方式，将上传文件的功能封装成一个私有方法，名字为&#8220;uploadFile&#8221;。其中运用了Java的IO包中很多API方法。有对重构和Java的IO功能不了解的读者可以去查阅相关资料去理解掌握，这里不是本书以及本节重点，因此不再具体记述。 <br />
（3）struts.xml中定义了&lt;constant&gt;标签，主要定义了文件名和文件内容显示的字符编码集以及这些被上传文件临时存放路径。 <br />
先说明一下&lt;constant&gt;标签，顾名思义这是定义整个Web项目的一些常量属性值，如果不定义则在Struts2自带的default.properties（读者们可到自己安装Struts2的文件路径src\core\src\main\resources\org\apache\struts2\下找到）文件中有这些常量的定义，比如在本节struts.xml文件中的&#8220;struts.i18n.encoding&#8221;和&#8220;struts.multipart.saveDir&#8221;在default.properties定义代码如下： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 </div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;!--------------------文件名：</span><span class="keyword">default</span><span>.properties----------------&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>###&nbsp;This&nbsp;can&nbsp;be&nbsp;used&nbsp;to&nbsp;set&nbsp;your&nbsp;</span><span class="keyword">default</span><span>&nbsp;locale&nbsp;and&nbsp;encoding&nbsp;scheme &nbsp;&nbsp;</span></span></li>
    <li><span>#&nbsp;struts.locale=en_US &nbsp;&nbsp;</span></li>
    <li><span>struts.i18n.encoding=UTF-</span><span class="number">8</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>###&nbsp;Parser&nbsp;to&nbsp;handle&nbsp;HTTP&nbsp;POST&nbsp;requests,&nbsp;encoded&nbsp;using&nbsp;the&nbsp;MIME-type&nbsp;multipart/form-data &nbsp;&nbsp;</span></li>
    <li><span>#&nbsp;struts.multipart.parser=cos &nbsp;&nbsp;</span></li>
    <li><span>#&nbsp;struts.multipart.parser=pell &nbsp;&nbsp;</span></li>
    <li><span>struts.multipart.parser=jakarta &nbsp;&nbsp;</span></li>
    <li><span>#&nbsp;uses&nbsp;javax.servlet.context.tempdir&nbsp;by&nbsp;</span><span class="keyword">default</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>struts.multipart.saveDir=&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none" class="java" name="code">&lt;!--------------------文件名：default.properties----------------&gt;
### This can be used to set your default locale and encoding scheme
# struts.locale=en_US
struts.i18n.encoding=UTF-8
### Parser to handle HTTP POST requests, encoded using the MIME-type multipart/form-data
# struts.multipart.parser=cos
# struts.multipart.parser=pell
struts.multipart.parser=jakarta
# uses javax.servlet.context.tempdir by default
struts.multipart.saveDir=</pre>
<br />
如果不在struts.xml文件中定义，则Web项目会缺省使用default.properties文件中这两个常量属性的定义。一个将使字符编码集变为&#8220;UTF-8&#8221;，另一个干脆没有任何文件路径指定。而笔者开发的该Web项目缺省支持的字符编码集是&#8220;gb2312&#8221;，而且需要指定临时上传文件存放路径。（当然如果读者开发的Web项目缺省编码集就是&#8220;UTF-8&#8221;，而且也并不需要指定临时路径时候，就没必要在struts.xml中定义这两个&lt;constant&gt;），因此有必要定义这两个属性符合项目开发要求。 <br />
注意：也可以如第3章那样，把这两个属性定义在自定义的struts.properties文件中，具体代码可以如下： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 </div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;!------------------------文件名：struts.properties------------------&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>struts.i18n.encoding&nbsp;=gb2312 &nbsp;&nbsp;</span></li>
    <li><span>struts.multipart.saveDir=&nbsp;c:\&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none" class="java" name="code">&lt;!------------------------文件名：struts.properties------------------&gt;
struts.i18n.encoding =gb2312
struts.multipart.saveDir= c:\</pre>
<br />
笔者个人认为比在struts.xml中定义更加好，毕竟Struts2自己也是定义在properties属性文件中，而不是定义在自己的xml配置文件中。（Struts2自带的xml配置文件为struts-default.xml，在4.1小节中已记述）。这里是为了让读者知道struts.xml配置文件也可以配置这些属性，因此写在struts.xml配置文件中。从3.2小节笔者说明struts.xml配置文件时并没有介绍&lt;constant&gt;标签这点也可以知道笔者个人其实是不赞同这样的配置手段即在struts.xml中配置&lt;constant&gt;标签。 <br />
在&lt;Action&gt;标签中配置&#8220;result&#8221;，和第3章类似，将这两个JSP文件的导航流程配置好即可。 <br />
（4）开始进行文件上传功能展示，按照如上记述的步骤执行即可。笔者在桌面上新建了两个文本文件，将它们上传到JBoss已部署的Web项目中展示文件上传的upload文件夹下。如图4.11所示。 <br />
其实还可以指定上传文件的格式，让它只上传特定类型的文件。比如只能上传文本和xml文件，则在struts.xml需要显示配置&#8220;uploadFile&#8221;拦截器。如下代码： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 </div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;!-----------------------文件名：struts.xml------------------&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;struts&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;Action所在包定义&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;</span><span class="keyword">package</span><span>&nbsp;name=</span><span class="string">"C04.4"</span><span>&nbsp;</span><span class="keyword">extends</span><span>=</span><span class="string">"struts-default"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;Action名字，类以及导航页面定义&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;通过Action类处理才导航的的Action定义&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;action&nbsp;name=</span><span class="string">"upload"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"action.UploadAction"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;result&nbsp;name=</span><span class="string">"input"</span><span>&gt;/jsp/upload.jsp&lt;/result&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;result&nbsp;name=</span><span class="string">"success"</span><span>&gt;/jsp/result.jsp&lt;/result&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/action&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;!—显示配置文件上传拦截器&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;interceptor-ref&nbsp;name=&#8221;fileUpload&#8221;&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;!—指定特定类型的上传文件&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;param&nbsp;name&nbsp;=&#8221;allowedTypes&#8221;&gt;text/plain,application/xml&lt;/param&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/&nbsp;interceptor-ref&nbsp;&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;interceptor-ref&nbsp;name=&#8221;defaultStack&#8221;&gt;&lt;/&nbsp;interceptor-ref&nbsp;&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/</span><span class="keyword">package</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;/struts&gt;&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none" class="java" name="code">&lt;!-----------------------文件名：struts.xml------------------&gt;
&lt;struts&gt;
&lt;!-- Action所在包定义 --&gt;
&lt;package name="C04.4" extends="struts-default"&gt;
&lt;!-- Action名字，类以及导航页面定义 --&gt;
&lt;!-- 通过Action类处理才导航的的Action定义 --&gt;
&lt;action name="upload" class="action.UploadAction"&gt;
&lt;result name="input"&gt;/jsp/upload.jsp&lt;/result&gt;
&lt;result name="success"&gt;/jsp/result.jsp&lt;/result&gt;
&lt;/action&gt;
&lt;!—显示配置文件上传拦截器 --&gt;
&lt;interceptor-ref name=&#8221;fileUpload&#8221;&gt;
&lt;!—指定特定类型的上传文件 --&gt;
&lt;param name =&#8221;allowedTypes&#8221;&gt;text/plain,application/xml&lt;/param&gt;
&lt;/ interceptor-ref &gt;
&lt;interceptor-ref name=&#8221;defaultStack&#8221;&gt;&lt;/ interceptor-ref &gt;
&lt;/package&gt;
&lt;/struts&gt; </pre>
<br />
定义了一个名为&#8220;allowedTypes&#8221;的参数，其中在&lt;param&gt;&lt;/param&gt;之间的是文件类型，也可以用&#8220;，&#8221;间隔，表示允许上传多个文件类型。这里允许上传文件类型为txt、xml格式的文件。如果读者不知道各个文件类型的定义，可在自己的JBoss安装目录中的server\default\deploy\jboss-web.deployer\conf\下的web.xml文件中找到（搜索&lt;mime-mapping&gt;即可）。 <br />
注意：如果显示配置Struts2自己的缺省拦截器一定要写在&#8220;defaultStack&#8221;前，否则&#8220;fileUpload&#8221;拦截器不会执行拦截。因为Struts2中如果某个拦截器执行拦截时候发现自己已经执行过，第二个乃至之后同名的拦截器都不会执行。这里因为&#8220;defaultStack&#8221;拦截器栈中包含了&#8220;fileUpload&#8221;拦截器，而&#8220;fileUpload&#8221;拦截器已经执行拦截了，则不会再执行拦截。如果把&#8220;defaultStack&#8221;拦截器栈放在&#8220;fileUpload&#8221;拦截器前配置，则只执行&#8220;defaultStack&#8221;拦截器栈中的&#8220;fileUpload&#8221;拦截器，这里是没有定义&#8220;allowedTypes&#8221;的，Struts2缺省默认的是支持所有文件类型。因此它会支持所有文件类型的文件上传。因此再设定&#8220;allowedTypes&#8221;就没有任何意义了。 <br />
<img src ="http://www.blogjava.net/lanxin1020/aggbug/265297.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lanxin1020/" target="_blank">lanxin1020</a> 2009-04-13 15:33 <a href="http://www.blogjava.net/lanxin1020/archive/2009/04/13/265297.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>11 Struts2文件下载功能开发（转自黑暗浪子）</title><link>http://www.blogjava.net/lanxin1020/archive/2009/04/13/265295.html</link><dc:creator>lanxin1020</dc:creator><author>lanxin1020</author><pubDate>Mon, 13 Apr 2009 07:30:00 GMT</pubDate><guid>http://www.blogjava.net/lanxin1020/archive/2009/04/13/265295.html</guid><wfw:comment>http://www.blogjava.net/lanxin1020/comments/265295.html</wfw:comment><comments>http://www.blogjava.net/lanxin1020/archive/2009/04/13/265295.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lanxin1020/comments/commentRss/265295.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lanxin1020/services/trackbacks/265295.html</trackback:ping><description><![CDATA[<span style="font-size: xx-large">Struts2文件下载功能开发</span> <br />
技术要点 <br />
本节代码详细说明文件下载功能的开发流程，介绍知识点如下： <br />
<div style="text-align: left"> 上传成功页面重修改后支持文件下载代码内容。 <br />
 DownloadAction文件下载功能开发。 <br />
 struts.xml中DownloadAction配置，以及支持文件名为中文字符的文件下载。 <br />
 下载文件流程展示。</div>
<br />
演示代码 <br />
上传成功页面，这里笔者让其在每个上传文件后提供&#8220;下载&#8221;链接。 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 </div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;!------------------------文件名：result.jsp-------------------&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;%</span><span class="annotation">@taglib</span><span>&nbsp;prefix=</span><span class="string">"s"</span><span>&nbsp;uri=</span><span class="string">"/struts-tags"</span><span>%&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;body&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;上传文件： &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;table&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;循环显示上传成功文件名&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;s:iterator&nbsp;value=</span><span class="string">"fileFileName"</span><span>&nbsp;status=</span><span class="string">"fn"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;tr&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;上传成功文件名&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;s:property&nbsp;/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;td&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;下载文件链接内容为定义的下载Action&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;下载文件名作为链接参数fileName值，用OGNL表达式表达&nbsp;--&gt;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;a&nbsp;href="&lt;s:url&nbsp;value=</span><span class="string">'download.action'</span><span>&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;s:param&nbsp;name=</span><span class="string">'fileName'</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;value=</span><span class="string">'fileFileName[#fn.getIndex()]'</span><span>/&gt;&nbsp;&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/s:url&gt;"&gt;下载&lt;/a&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/td&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/tr&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/s:iterator&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/table&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/body&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none" class="java" name="code">&lt;!------------------------文件名：result.jsp-------------------&gt;
&lt;%@taglib prefix="s" uri="/struts-tags"%&gt;
&lt;body&gt;
上传文件：
&lt;table&gt;
&lt;!-- 循环显示上传成功文件名 --&gt;
&lt;s:iterator value="fileFileName" status="fn"&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;!-- 上传成功文件名 --&gt;
&lt;s:property /&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;!-- 下载文件链接内容为定义的下载Action --&gt;
&lt;!-- 下载文件名作为链接参数fileName值，用OGNL表达式表达 --&gt;
&lt;a href="&lt;s:url value='download.action'&gt;
&lt;s:param name='fileName'
value='fileFileName[#fn.getIndex()]'/&gt;
&lt;/s:url&gt;"&gt;下载&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/s:iterator&gt;
&lt;/table&gt;
&lt;/body&gt;</pre>
<br />
DownLoadAction类代码 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 </div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;!------------文件名：DownLoadAction.java&nbsp;------------------&gt; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;java.io.InputStream; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;java.io.UnsupportedEncodingException; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span class="keyword">import</span><span>&nbsp;org.apache.struts2.ServletActionContext; &nbsp;&nbsp;</span></span></li>
    <li><span class="keyword">import</span><span>&nbsp;com.opensymphony.xwork2.ActionSupport; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;DownLoadAction&nbsp;</span><span class="keyword">extends</span><span>&nbsp;ActionSupport&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//下载文件原始存放路径 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;String&nbsp;DOWNLOADFILEPATH=</span><span class="string">"/upload/"</span><span>; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//文件名参数变量 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;String&nbsp;fileName; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;String&nbsp;getFileName()&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;fileName; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;setFileName(String&nbsp;fileName)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.fileName&nbsp;=&nbsp;fileName; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//从下载文件原始存放路径读取得到文件输出流 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;InputStream&nbsp;getDownloadFile()&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp; &nbsp;&nbsp;</span></span></li>
    <li><span>ServletActionContext.getServletContext().getResourceAsStream(DOWNLOADFILEPATH+fileName); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//如果下载文件名为中文，进行字符编码转换 </span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;String&nbsp;getDownloadChineseFileName()&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;downloadChineseFileName&nbsp;=&nbsp;fileName; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">try</span><span>&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;downloadChineseFileName&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;String(downloadChineseFileName.getBytes(),&nbsp;</span><span class="string">"ISO8859-1"</span><span>); &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span class="keyword">catch</span><span>&nbsp;(UnsupportedEncodingException&nbsp;e)&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace(); &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;downloadChineseFileName; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;String&nbsp;execute()&nbsp;{ &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;SUCCESS; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li>
    <li><span>}&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none" class="java" name="code">&lt;!------------文件名：DownLoadAction.java ------------------&gt;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class DownLoadAction extends ActionSupport {
//下载文件原始存放路径
private final static String DOWNLOADFILEPATH="/upload/";
//文件名参数变量
private String fileName;
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
//从下载文件原始存放路径读取得到文件输出流
public InputStream getDownloadFile() {
return
ServletActionContext.getServletContext().getResourceAsStream(DOWNLOADFILEPATH+fileName);
}
//如果下载文件名为中文，进行字符编码转换
public String getDownloadChineseFileName() {
String downloadChineseFileName = fileName;
try {
downloadChineseFileName = new String(downloadChineseFileName.getBytes(), "ISO8859-1");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return downloadChineseFileName;
}
public String execute() {
return SUCCESS;
}
}</pre>
<br />
struts.xml配置文件中有关文件下载的配置： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 </div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;!------------------文件名：struts.xml-----------------&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;struts&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;下载文件的Action定义&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;action&nbsp;name=</span><span class="string">"download"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"action.DownLoadAction"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;设置文件名参数，由页面上传入&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param&nbsp;name=</span><span class="string">"fileName"</span><span>&gt;&lt;/param&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;result&nbsp;name=</span><span class="string">"success"</span><span>&nbsp;type=</span><span class="string">"stream"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;下载文件类型定义&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param&nbsp;name=</span><span class="string">"contentType"</span><span>&gt;text/plain&lt;/param&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;下载文件处理方法&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param&nbsp;name=</span><span class="string">"contentDisposition"</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;attachment;filename=</span><span class="string">"${downloadChineseFileName}"</span><span>&nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/param&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--&nbsp;下载文件输出流定义&nbsp;--&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;param&nbsp;name=</span><span class="string">"inputName"</span><span>&gt;downloadFile&lt;/param&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/result&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/action&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/struts&gt;&nbsp;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none" class="java" name="code">&lt;!------------------文件名：struts.xml-----------------&gt;
&lt;struts&gt;
&lt;!-- 下载文件的Action定义 --&gt;
&lt;action name="download" class="action.DownLoadAction"&gt;
&lt;!-- 设置文件名参数，由页面上传入 --&gt;
&lt;param name="fileName"&gt;&lt;/param&gt;
&lt;result name="success" type="stream"&gt;
&lt;!-- 下载文件类型定义 --&gt;
&lt;param name="contentType"&gt;text/plain&lt;/param&gt;
&lt;!-- 下载文件处理方法 --&gt;
&lt;param name="contentDisposition"&gt;
attachment;filename="${downloadChineseFileName}"
&lt;/param&gt;
&lt;!-- 下载文件输出流定义 --&gt;
&lt;param name="inputName"&gt;downloadFile&lt;/param&gt;
&lt;/result&gt;
&lt;/action&gt;
&lt;/struts&gt; </pre>
<br />
（1）：文件开始下载页面如图4.12所示。 <br />
<br />
图4.12&nbsp; 文件下载 <br />
（2）：单击&#8220;下载&#8221;链接，比如点&#8220;下载文件1.txt&#8221;文件右边&#8220;下载&#8221;链接，出现对话框如图4.13所示。 <br />
<br />
图4.13&nbsp; 下载文件处理方式 <br />
（3）：单击&#8220;保存&#8221;按钮后选择下载文件存放路径，如图4.14所示。 <br />
<br />
图4.14&nbsp; 下载文件选择存放路径 <br />
代码解释 <br />
（1）在result.jsp中通过iterator标签和url标签定义了&#8220;fileFileName&#8221;的循环显示以及链接。其中有关&#8220;status&#8221;和OGNL表达式笔者会在之后章节里具体介绍，这里只是让读者知道是如何使用标签显示图4.12显示的内容。特别指出&lt;param&gt;标签为downloadAction定义了一个参数，该参数名为&#8220;fileName&#8221;，因为在4.4.1小节中笔者定义的&#8220;fileFileName&#8221;是个List类型的数据集合，因此利用OGNL表达式将文件名作为&#8220;fileName&#8221;参数值传入downloadAction中。 <br />
（2）DownLoadAction文件中先定义了常量DOWNLOADFILEPATH，它是下载文件在服务器存放的路径名，也就是4.4.1小节中上传文件在服务器存放的路径名。 <br />
定义好DOWNLOADFILEPATH后，在定义DownLoadAction的属性变量。因为在result.jsp中定义了参数&#8220;fileName&#8221;，则它作为DownLoadAction的属性变量，需要定义相应的getter、setter方法。 <br />
然后定义了getDownloadFile方法，它返回的是一个文件流，表明将被下载文件转换为输出流，方便下载。利用Struts2自带的&#8220;ServletActionContext&#8221;类的API把下载文件存放路径作为方法参数，读取下载文件，将其转换为文件流。 <br />
还有一个getDownloadChineseFileName方法，该方法主要作用是将文件名为中文字符的文件进行文件名的字符编码集合转换。因为在Web系统中由JSP等视图页面传入的变量值，特别是中文字符的变量。缺省的字符编码集合都是&#8220;ISO8859-1&#8221;，因此利用Java的字符串类的API，将字符编码转成开发需要的字符编码集。防止中文字符乱码问题发生。 <br />
（3）struts.xml中定义了名为&#8220;download&#8221;的Action。其中它自己的参数&#8220;fileName&#8221;因为在这里它的值会从JSP页面上传入，所以这里只是定义，没有具体给它赋任何值 <br />
在&lt;result&gt;标签中定义了type属性，值为&#8220;stream&#8221;。如果是下载文件功能开发，DownLoadAction一定要设置type属性，而且值为&#8220;stream&#8221;。这是因为在Struts2自带的xml配置文件为struts-default.xml中有关于&#8220;stream&#8221;的result返回类型的定义，代码如下： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 </div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;!-------------------文件名：struts-</span><span class="keyword">default</span><span>.xml--------------&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;result-type&nbsp;name=</span><span class="string">"stream"</span><span>&nbsp;</span><span class="keyword">class</span><span>=</span><span class="string">"org.apache.struts2.dispatcher.StreamResult"</span><span>/&gt;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre style="display: none" class="java" name="code">&lt;!-------------------文件名：struts-default.xml--------------&gt;
&lt;result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/&gt;</pre>
<br />
这里Struts2定义了result返回类型为&#8220;stream&#8221;，这个result类型主要是处理文件的输入和输出流时候需要使用的。因为下载文件就是把文件转换成输入输出流，将其从一个文件路径放到另外一个文件路径中去。所以肯定要设置这个result类型的。 <br />
&#8220;contentType&#8221;、&#8220;contentDisposition&#8221;、&#8220;inputName&#8221;都是这个result的属性。&#8220;contentType&#8221;就是文件类型。这里因为下载的文件是文本文件，因此设定的值为文本文件类型，具体各个文件类型如何定义，4.4.1小节已经介绍过，这里不再做说明。&#8220;contentDisposition&#8221;是指定下载文件处理方式，如图4.13就是处理方式的效果。特别指出如果&#8220;contentDisposition&#8221;定义的值把前面的&#8220;attachment&#8221;去掉，则下载方式不是以附件方式下载，如果单击&#8220;下载&#8221;链接，则会把下载文件的内容显示在浏览器中。读者可以去试验一下。这里有个&#8220;${downloadChineseFileName}&#8221;，这就是在DownLoadAction中定义getDownloadChineseFileName方法的目的，${downloadChineseFileName}是OGNL的表达式，它显示了&#8220;downloadChineseFileName&#8221;变量的具体值，因为在DownLoadAction中定义getDownloadChineseFileName方法，则把已经转换成符合需要字符编码集的下载文件名作为下载文件方式对话框中显示的名称，不会造成任何乱码问题。&#8220;inputName&#8221;是最关键的一个属性，也是一定要定义的属性，&#8220;inputName&#8221;参数中定义的值&#8220;downloadFile&#8221;就是DownLoadAction中getDownloadFile方法返回的文件流名字。在Struts2中Acion用前缀名为get的方法得到各种属性的值，这些属性有些是在Action中定义，有些就像本示例在配置文件中利用OGNL表达式或直接定义。 <br />
（4）开始进行文件下载功能展示，按照如上记述的步骤执行即可。笔者将两个文本文件上传上去，然后在上传成功页面对具体的文件进行下载。在图4.13中单击&#8220;保存&#8221;按钮就显示图4.14，选择在本机上存放下载文件的路径即可完成下载文件功能。 <br />
<img src ="http://www.blogjava.net/lanxin1020/aggbug/265295.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lanxin1020/" target="_blank">lanxin1020</a> 2009-04-13 15:30 <a href="http://www.blogjava.net/lanxin1020/archive/2009/04/13/265295.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>12Struts2标签使用原理（转自黑暗浪子）</title><link>http://www.blogjava.net/lanxin1020/archive/2009/04/13/265294.html</link><dc:creator>lanxin1020</dc:creator><author>lanxin1020</author><pubDate>Mon, 13 Apr 2009 07:28:00 GMT</pubDate><guid>http://www.blogjava.net/lanxin1020/archive/2009/04/13/265294.html</guid><wfw:comment>http://www.blogjava.net/lanxin1020/comments/265294.html</wfw:comment><comments>http://www.blogjava.net/lanxin1020/archive/2009/04/13/265294.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/lanxin1020/comments/commentRss/265294.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/lanxin1020/services/trackbacks/265294.html</trackback:ping><description><![CDATA[<span style="font-size: xx-large">Struts2标签使用原理解疑</span> <br />
在笔者下载的Struts2的包中，读者可以在/lib下找到struts2-core-2.0.11.1.jar包，解压该包在其根目录下的/META-INF文件夹下可以看到一个名字为&#8220;struts-tags.tld&#8221;文件。该文件就是Struts2中所有自带的标签库定义。本节通过对该文件代码的介绍来让读者知晓Struts2内部是如何使用这些标签来进行工作。并简单说明JSP中是如何用其来书写标签代码。 <br />
技术要点 <br />
本节代码说明Struts2内部定义标签的格式和在JSP中使用方式。 <br />
<div style="text-align: left"> struts-tags.tld文件定标签定义配置格式。 <br />
 JSP中使用标签功能介绍。</div>
<br />
演示代码 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 </div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;!------------------文件名：&nbsp;struts-tags.tld-----------------&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;taglib&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&lt;tlib-version&gt;</span><span class="number">2.2</span><span>.</span><span class="number">3</span><span>&lt;/tlib-version&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&lt;jsp-version&gt;</span><span class="number">1.2</span><span>&lt;/jsp-version&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&lt;</span><span class="keyword">short</span><span>-name&gt;s&lt;/</span><span class="keyword">short</span><span>-name&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&lt;uri&gt;/struts-tags&lt;/uri&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&lt;display-name&gt;</span><span class="string">"Struts&nbsp;Tags"</span><span>&lt;/display-name&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&lt;description&gt;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&lt;/description&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&lt;tag&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;name&gt;action&lt;/name&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;tag-</span><span class="keyword">class</span><span>&gt;org.apache.struts2.views.jsp.ActionTag&lt;/tag-</span><span class="keyword">class</span><span>&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;body-content&gt;JSP&lt;/body-content&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;description&gt;&lt;![CDATA[Execute&nbsp;an&nbsp;action&nbsp;from&nbsp;within&nbsp;a&nbsp;view]]&gt;&lt;/description&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;attribute&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;name&gt;executeResult&lt;/name&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;required&gt;</span><span class="keyword">false</span><span>&lt;/required&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;rtexprvalue&gt;</span><span class="keyword">false</span><span>&lt;/rtexprvalue&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;description&gt;&lt;![CDATA[Whether&nbsp;the&nbsp;result&nbsp;of&nbsp;</span><span class="keyword">this</span><span>&nbsp;action&nbsp;(probably&nbsp;a&nbsp;view)&nbsp;should&nbsp;be&nbsp;executed/rendered]]&gt;&lt;/description&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/attribute&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;attribute&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;name&gt;namespace&lt;/name&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;required&gt;</span><span class="keyword">false</span><span>&lt;/required&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;rtexprvalue&gt;</span><span class="keyword">false</span><span>&lt;/rtexprvalue&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;description&gt;&lt;![CDATA[Namespace&nbsp;</span><span class="keyword">for</span><span>&nbsp;action&nbsp;to&nbsp;call]]&gt;&lt;/description&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/attribute&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&lt;/tag&gt; &nbsp;&nbsp;</span></li>
    <li><span>&lt;/taglib&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none" class="java" name="code">&lt;!------------------文件名： struts-tags.tld-----------------&gt;
&lt;taglib&gt;
&lt;tlib-version&gt;2.2.3&lt;/tlib-version&gt;
&lt;jsp-version&gt;1.2&lt;/jsp-version&gt;
&lt;short-name&gt;s&lt;/short-name&gt;
&lt;uri&gt;/struts-tags&lt;/uri&gt;
&lt;display-name&gt;"Struts Tags"&lt;/display-name&gt;
&lt;description&gt;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&lt;/description&gt;
&lt;tag&gt;
&lt;name&gt;action&lt;/name&gt;
&lt;tag-class&gt;org.apache.struts2.views.jsp.ActionTag&lt;/tag-class&gt;
&lt;body-content&gt;JSP&lt;/body-content&gt;
&lt;description&gt;&lt;![CDATA[Execute an action from within a view]]&gt;&lt;/description&gt;
&lt;attribute&gt;
&lt;name&gt;executeResult&lt;/name&gt;
&lt;required&gt;false&lt;/required&gt;
&lt;rtexprvalue&gt;false&lt;/rtexprvalue&gt;
&lt;description&gt;&lt;![CDATA[Whether the result of this action (probably a view) should be executed/rendered]]&gt;&lt;/description&gt;
&lt;/attribute&gt;
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;
&lt;attribute&gt;
&lt;name&gt;namespace&lt;/name&gt;
&lt;required&gt;false&lt;/required&gt;
&lt;rtexprvalue&gt;false&lt;/rtexprvalue&gt;
&lt;description&gt;&lt;![CDATA[Namespace for action to call]]&gt;&lt;/description&gt;
&lt;/attribute&gt;
&lt;/tag&gt;
&lt;/taglib&gt;</pre>
<br />
代码解释 <br />
（1）struts-tags.tld是Struts2自标签定义文件。所有标签定义都是在&lt;tablib&gt;和&lt;/taglib&gt;之间定义。以&lt;tag&gt;&lt;/tag&gt;用来定义一个具体标签。每个标签因为都可以有很多自己的属性。这些属性定义都是以&lt;attribute&gt;&lt;/attribute&gt;来定义。 <br />
（2）&lt;tlib-version&gt;&lt;/tlib-version&gt;之间定义的是标签库的版本。&lt;jsp-version&gt;&lt;/jsp-version&gt;定义的是标签库这些标签是支持JSP的哪个版本。&lt;short-name&gt; &lt;/short-name&gt;其实是标签库的默认名，也可以认为是其昵称。&lt;uri&gt; &lt;/uri&gt;定义的是标签库的URI，在JSP中会使用到。&lt;display-name&gt;&lt;/display-name&gt;是显示名。&lt;description&gt;&lt;/description&gt;是标签库的记述，记述标签库的使用用途等等。 <br />
（3）&lt;attribute&gt;中&lt;name&gt;&lt;/name&gt;是属性名称定义。&lt;required&gt;&lt;/required&gt;表示的该属性是否是必须的属性，如果是必须的则&lt;required&gt;&lt;/required&gt;之间为true，否则为false。&lt;rtexprvalue&gt;&lt;/rtexprvalue&gt;表示的是可否使用表达式，大多数标签都是为false。这里不是不能使用表达式，而是恰恰相反表示可以使用表达式。&lt;description&gt;&lt;/description&gt;定义和前面介绍相同。 <br />
（4）在JSP中，如之前章节的演示代码所示，都是在文件头有个使用标签的声明，代码如下。 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 </div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;!---------------------文件名：&nbsp;*.jsp-------------------------&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;%</span><span class="annotation">@taglib</span><span>&nbsp;prefix=</span><span class="string">"s"</span><span>&nbsp;uri=</span><span class="string">"/struts-tags"</span><span>%&gt;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre style="display: none" class="java" name="code">&lt;!---------------------文件名： *.jsp-------------------------&gt;
&lt;%@taglib prefix="s" uri="/struts-tags"%&gt;</pre>
<br />
有了这个声明，在JSP文件中就可以使用Struts2的标签。比如form标签定义要像如下代码所示。 <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 </div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;s:form&nbsp;action=</span><span class="string">"upload"</span><span>&nbsp;&#8230;&#8230;&#8230;&gt;&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<pre style="display: none" class="java" name="code">&lt;s:form action="upload" &#8230;&#8230;&#8230;&gt;</pre>
<br />
记住一定要用&#8220;s&#8221;，它是Struts2中标签的默认名也是相当于一个昵称，当然读者也可以把它改为自己想取的名字，不过在标签声明中的&#8220;prefix&#8221;中就要改成那个自己取的名字。 <br />
注意：因为笔者使用的Servlet版本是2.3之上的版本，因此没必要在web.xml中定义标签库。如果读者使用的Servlet版本比较低，则在web.xml文件中需要定义如下的代码： <br />
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 </div>
</div>
<ol class="dp-j">
    <li><span><span>&lt;!----------------------文件名：web.xml-----------------------&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;taglib&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;!-&nbsp;定义URI&nbsp;-&nbsp;-&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;taglib-uri&gt;/Struts&nbsp;</span><span class="number">2</span><span>-tags&lt;/taglib-uri&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;!-&nbsp;定义标签库支持的jar包位置-&nbsp;-&gt; &nbsp;&nbsp;</span></li>
    <li><span>&nbsp;&nbsp;&nbsp;&nbsp;&lt;taglib-location&gt;/WEB-INF/lib/struts2-core-</span><span class="number">2.0</span><span>.</span><span class="number">11.1</span><span>.jar&lt;/taglib-location&gt; &nbsp;&nbsp;</span></span></li>
    <li><span>&lt;/taglib&gt;&nbsp;&nbsp;</span></li>
</ol>
</div>
<pre style="display: none" class="java" name="code">&lt;!----------------------文件名：web.xml-----------------------&gt;
&lt;taglib&gt;
&lt;!- 定义URI - -&gt;
&lt;taglib-uri&gt;/Struts 2-tags&lt;/taglib-uri&gt;
&lt;!- 定义标签库支持的jar包位置- -&gt;
&lt;taglib-location&gt;/WEB-INF/lib/struts2-core-2.0.11.1.jar&lt;/taglib-location&gt;
&lt;/taglib&gt;</pre>
<br />
只有这样标签库才会在Servlet版本比较低的情况下使用有效果。 <br />
 <img src ="http://www.blogjava.net/lanxin1020/aggbug/265294.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/lanxin1020/" target="_blank">lanxin1020</a> 2009-04-13 15:28 <a href="http://www.blogjava.net/lanxin1020/archive/2009/04/13/265294.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>