白话MVC(四)为Struts2编写文件上传插件
Struts2中,在Dispatcher.java里,把一个multipart/form-data类型的HttpServletRequest对象包装成JakartaMultiPartRequest的过程中,已经读完了HttpServletRequest对象输入流数据,基于此对象输入流的特点--不可再读取第二次,因此Action中已经不可能使用fastupload API解析multipart/form-data请求了。
?
纵览struts2框架里Model Bean的自动装配过程,发现拦截器其实共享了一个ActionContext的“值栈”,“值栈”里存储了必要的数据,以便让拦截器、ActionProxy、ActionInvocation对象和HttpServletRequest隔离,最后在ParametersInterceptor.java中,从“值栈”取得相关的数据,装配到Model Bean中,因此,任何数据在装配之前,都需要在合适的时机放入“值栈”之中。Struts2虽然在包装HttpServletRequest阶段已经完成了文件解析的工作,但是直到FileUploadInterceptor被调用时,把解析的文件放入了“值栈”。
?
fastupload基于这个约定,编写了struts2文件上传的“插件”,之所以打上引号,其功能实质上算不了一个正真的插件,只是实现了MultiPartRequest这个接口过程中调用了fastupload相关的API。具体的用法请参考《Fastupload 0.4.7发布,支持struts2》一文。这种解决办法只能说是凑合,好处是----不需要修改struts2的源码。
?
但是struts2在使用apache commons fileupload的过程中,写的MultiPartRequestWrapper.java的构造函数是多了一个saveDir,用来指定apache commons fileupload解析时产生临时文件的存储目录,并且在ActionProxy对象执行结束后,要清除这些临时文件,不止于此,在Action中,用来操作上传的文件的类用了java.io.File,也就是一定要和文件系统相关联。不能不说,apache commons fileupload使用临时文件这种方式,拖累了struts2,spring mvc以及其他一些mvc框架。
?
假如解析multipart/form-data请求后,这些解析的数据都作为内存中的一个对象存在,在需要的时候才保存到文件系统中,mvc框架处理起来要简单的多,是不是这样?正因如此,要发挥fastupload的威力,一定要用内存的解析方式!
?
首先看一下使用内存解析方式,Action类有何变化!
?
4, 使用fastupload预先的过滤机制(可选),在FastUploadMultiPartRequest类中,找到下面的代码,把@Inject那两行反注释掉,
??
5, 运行并测试那个Action -:)
采用侵入源码的方式,也是逼迫不已呀。就目前来说,也达到让fastupload支持struts2的目标,但是,如果能让struts2的发行包中,直接集成了fastupload组建高效解析API,才能让struts2框架使用者更容易的使用,需要与struts的开发小组讨论了... ...这个阶段刚结束,一个新的阶段接着开始。
?
fastupload支持struts2框架的开发过程比较仓促,加之本人水平有限,可能会有一些疏漏及不正确的地方,如果您发现了,请告诉我,我及时改正,同时也欢迎网友对fastupload提出建设性意见。
?
[原创文章,如转载,请注明出去!@仪山湖]
?
?
?
?
?
?
?