用文件上传了解struts2拦截器的使用
2016-07-04 18:28
525 查看
struts2中,拦截器是非常核心的内容,框架默认提供的拦截器,我们可以从struts2-core-**.jar/struts-default.xml中查询到,我们以struts2-core-2.3.15.3.jar为例,打开struts-default.xml,可以看到如下的默认拦截器:
在struts-default.xml中,除了定义了一些默认的拦截器以外,还有一些默认的拦截器堆。这也提示我们,不光可以在使用时引用一个个的拦截器,也可以使用拦截器堆的方式,一次引用多个拦截器。如:我们在struts.xml配置文件中,没有配置拦截器的情况下,会默认引用以下这个拦截器堆:
为何我如此肯定,因为在这个文件中,有以下代码,我们在struts.xml中定义一个package元素时,通过也会extends这个struts-default.xml,那么也表示我们引用这个拦截器堆:
好了,抄了一阵struts的源码,现在我们开始今天的事情:文件上传
先来进行单文件上传:
从上面的默认拦截器定义,可以看到,struts2给我们提供了一个现成的拦截器fileUpload,并且已经默认引用了。
我们先来做一些准备工作,做一个文件上传的页面,相信大家都还记得文件上传的页面必须满足以下三个条件:
表单的提交方式必须是post
表单的enctype必须为multipart/form-data
表单中必须提供一个type=file的input元素
以下就是这个表单提交的页面:
上面使用的是struts2的标签,当然也可以使用普通的html标签。
上面的表单提交,我们需要一个action动作在来支持,我们先来在struts.xml中配置一下这个action动作
那个成功的返回页面success.jsp,没有任何展示,大不了就提示一下成功了
现在,我们就只差一个动作类了,我们来写配置文件中配置的demo.action.SingleFileUploadAction这个动作类:
以上代码为了简洁,省略了导入的包和各个属性的getter和setter,大家可以自己添加上。
通过上面的代码可以看到,我们需要有一个文件夹来存放上传的文件,本例,我们是在工程的根目录下,用一个files文件夹来存放的,所以,我们在WebRoot下,建一个files文件夹
好了,最最粗糙的文件上传完成了,先来看看效果
部署到tomcat,访问这个上传页面:
随便选张图片,上传下,果然,上传成功了。我们到tomcat下去查看,在项目的根目录下,发现有一个files目录,打开这个目录,发现确实上传成功了
感觉是完成了。再来得瑟一下,这回我选择一个视频,大概有几十M吧,然后
我操,这一定不是真的,刚才玩得还好好的。关键是,控制台还没报错,这怎么办?仔细看看这个报错,发现报的是没有input对应的逻辑视图,可明明我们的action里只返回了success,哪来的input,除了这个action,就只有一个可能,就是那个fileUpload拦截器干的。
好吧,既然你说我没有input视图,那我给你一个,在struts.xml中,action的定义里,添加一个result元素
再次去尝试去上传一个那个几十M的视频文件,这回倒是不报错了,而是重新又回到了上传页面。
那么问题来了,为什么呢?再上传那张图片是可以成功的,为什么视频就不可以吗?是因为格式不对吗?也没有指定格式呀,按理说应该是可以支持所有格式的,毕竟只是一个上传,又不是解析。
那会不会是大小的问题呢,可能性很大。因为文件上传不成功,无非不是路径问题,文件格式问题,然后就是文件大小问题,前面已经成功过,那么路径是没有问题的,格式的问题可能性很小。那么我们来找找有没有设置文件默认上传大小的地方:
我们知道,struts2加载的时候,不单会加载struts-default.xml,还会加载一个叫default.properties的文件,我们在struts2-core-2.3.15.3.jar包中,找到这个文件,仔细一看,找到了:
原来这里的文件默认大小这么小,难怪上传不上去,好吧,我们可以在struts.xml中,通过constant元素,来修改这个默认值
再次部署,试一下,终于成功了。在tomcat中,也找到了这个文件
感觉像是应该没有问题了。然而如果把这样的上传页面交付给甲方,相信这项目一定就没希望了。我们想想,这个地方明明在页面上写的是要上传“靓照”的,那也就是说这里我们希望要上传的是一张图片。可用户可不管那么多,他什么都有可能上传,就像我刚才一样,居然会上传一个视频上来。而且,如果用户上传的文件不对,应该给出提示。
那么,下面我们就来限制一下用户上传文件的大小和后缀名,如果用户上传的东西不对,那么给用户一个提示。
文件大小的限制,上面已经介绍了,那么现在,就应该是要给出用户提示了。
为了方便测试,我先把上传大小的限制调小一些,这样基本上随便一个文件都会过大,这样好测试:
struts2提供了一些标签,可以用于展示这些提示信息,比如这次的错误提示,我们就可以在页面上用以下标签展示:
这样,我们再次上传一个超过大小的文件,则会在页面上出现以下提示:
至于要把这个提示展示成中文的,则是可以通过国际化的配置来做,就不再是这篇博客要表现的东西了。
<interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/> <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/> <interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/> <interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/> <interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/> <interceptor name="cookieProvider" class="org.apache.struts2.interceptor.CookieProviderInterceptor"/> <interceptor name="clearSession" class="org.apache.struts2.interceptor.ClearSessionInterceptor" /> <interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" /> <interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" /> <interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/> <interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/> <interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/> <interceptor name="i18n" class="com.opensymphony.xwork2.interceptor.I18nInterceptor"/> <interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/> <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/> <interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/> <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/> <interceptor name="actionMappingParams" class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/> <interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/> <interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/> <interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/> <interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/> <interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/> <interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/> <interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/> <interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/> <interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/> <interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" /> <interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" /> <interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" /> <interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" /> <interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" /> <interceptor name="multiselect" class="org.apache.struts2.interceptor.MultiselectInterceptor" />
在struts-default.xml中,除了定义了一些默认的拦截器以外,还有一些默认的拦截器堆。这也提示我们,不光可以在使用时引用一个个的拦截器,也可以使用拦截器堆的方式,一次引用多个拦截器。如:我们在struts.xml配置文件中,没有配置拦截器的情况下,会默认引用以下这个拦截器堆:
<interceptor-stack name="defaultStack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="i18n"/> <interceptor-ref name="prepare"/> <interceptor-ref name="chain"/> <interceptor-ref name="scopedM dcdb odelDriven"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="multiselect"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="actionMappingParams"/> <interceptor-ref name="params"> <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param> </interceptor-ref> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="debugging"/> </interceptor-stack>
为何我如此肯定,因为在这个文件中,有以下代码,我们在struts.xml中定义一个package元素时,通过也会extends这个struts-default.xml,那么也表示我们引用这个拦截器堆:
<default-interceptor-ref name="defaultStack"/>
好了,抄了一阵struts的源码,现在我们开始今天的事情:文件上传
先来进行单文件上传:
从上面的默认拦截器定义,可以看到,struts2给我们提供了一个现成的拦截器fileUpload,并且已经默认引用了。
我们先来做一些准备工作,做一个文件上传的页面,相信大家都还记得文件上传的页面必须满足以下三个条件:
表单的提交方式必须是post
表单的enctype必须为multipart/form-data
表单中必须提供一个type=file的input元素
以下就是这个表单提交的页面:
<fieldset> <legend>单文件上传</legend> <s:form action="single/upload.action" enctype="multipart/form-data" method="post"> <s:textfield name="name" label="姓名"></s:textfield> <s:file name="photo" label="靓照"></s:file> <s:submit value="上传"></s:submit> </s:form> </fieldset>
上面使用的是struts2的标签,当然也可以使用普通的html标签。
上面的表单提交,我们需要一个action动作在来支持,我们先来在struts.xml中配置一下这个action动作
<package name="upload" extends="struts-default" namespace="/single"> <action name="upload" class="demo.action.SingleFileUploadAction" method="upload"> <result>/success.jsp</result> </action> </package>
那个成功的返回页面success.jsp,没有任何展示,大不了就提示一下成功了
<body> 上传成功了 </body>
现在,我们就只差一个动作类了,我们来写配置文件中配置的demo.action.SingleFileUploadAction这个动作类:
package demo.action; //省略引入的包 /** * 这个测试类,简单起见,使用模型和动作为同一个类的方式 * @author Minhellic * */ public class SingleFileUploadAction extends ActionSupport { private String name; //对应页面上的name字段 private File photo; //对应页面上要上传的文件,必须使用File来接收 private String photoFileName; //上传的文件名,XXXFileName这样的固定写法 private String photoContentType; //上传文件的MIME类型, XXXContentType这样的固定写法 public String upload() throws IOException { //普通的属性,可以直接使用 System.out.println(name); /* * 完全文件上传 */ //1.得到文件上要传的真实路径 ServletContext sc = ServletActionContext.getServletContext(); String dirPath = sc.getRealPath("/files");//得到文件的真实保存路径,需要在WebRoot根目录下建一个files目录 //2.构建目标文件 File target = new File(dirPath, photoFileName); //3.复制文件 FileUtils.copyFile(photo, target); return SUCCESS; } //省略各个属性的getter和setter }
以上代码为了简洁,省略了导入的包和各个属性的getter和setter,大家可以自己添加上。
通过上面的代码可以看到,我们需要有一个文件夹来存放上传的文件,本例,我们是在工程的根目录下,用一个files文件夹来存放的,所以,我们在WebRoot下,建一个files文件夹
好了,最最粗糙的文件上传完成了,先来看看效果
部署到tomcat,访问这个上传页面:
随便选张图片,上传下,果然,上传成功了。我们到tomcat下去查看,在项目的根目录下,发现有一个files目录,打开这个目录,发现确实上传成功了
感觉是完成了。再来得瑟一下,这回我选择一个视频,大概有几十M吧,然后
我操,这一定不是真的,刚才玩得还好好的。关键是,控制台还没报错,这怎么办?仔细看看这个报错,发现报的是没有input对应的逻辑视图,可明明我们的action里只返回了success,哪来的input,除了这个action,就只有一个可能,就是那个fileUpload拦截器干的。
好吧,既然你说我没有input视图,那我给你一个,在struts.xml中,action的定义里,添加一个result元素
<result name="input">/index.jsp</result>
再次去尝试去上传一个那个几十M的视频文件,这回倒是不报错了,而是重新又回到了上传页面。
那么问题来了,为什么呢?再上传那张图片是可以成功的,为什么视频就不可以吗?是因为格式不对吗?也没有指定格式呀,按理说应该是可以支持所有格式的,毕竟只是一个上传,又不是解析。
那会不会是大小的问题呢,可能性很大。因为文件上传不成功,无非不是路径问题,文件格式问题,然后就是文件大小问题,前面已经成功过,那么路径是没有问题的,格式的问题可能性很小。那么我们来找找有没有设置文件默认上传大小的地方:
我们知道,struts2加载的时候,不单会加载struts-default.xml,还会加载一个叫default.properties的文件,我们在struts2-core-2.3.15.3.jar包中,找到这个文件,仔细一看,找到了:
struts.multipart.maxSize=2097152
原来这里的文件默认大小这么小,难怪上传不上去,好吧,我们可以在struts.xml中,通过constant元素,来修改这个默认值
<constant name="struts.multipart.maxSize" value="100000000"></constant>
再次部署,试一下,终于成功了。在tomcat中,也找到了这个文件
感觉像是应该没有问题了。然而如果把这样的上传页面交付给甲方,相信这项目一定就没希望了。我们想想,这个地方明明在页面上写的是要上传“靓照”的,那也就是说这里我们希望要上传的是一张图片。可用户可不管那么多,他什么都有可能上传,就像我刚才一样,居然会上传一个视频上来。而且,如果用户上传的文件不对,应该给出提示。
那么,下面我们就来限制一下用户上传文件的大小和后缀名,如果用户上传的东西不对,那么给用户一个提示。
文件大小的限制,上面已经介绍了,那么现在,就应该是要给出用户提示了。
为了方便测试,我先把上传大小的限制调小一些,这样基本上随便一个文件都会过大,这样好测试:
<constant name="struts.multipart.maxSize" value="1000"></constant>
struts2提供了一些标签,可以用于展示这些提示信息,比如这次的错误提示,我们就可以在页面上用以下标签展示:
<s:actionerror/>
这样,我们再次上传一个超过大小的文件,则会在页面上出现以下提示:
至于要把这个提示展示成中文的,则是可以通过国际化的配置来做,就不再是这篇博客要表现的东西了。
相关文章推荐
- 插件管理框架 for Delphi(一)
- 使用CSS框架布局的缺点和优点小结
- 一起动手编写Android图片加载框架
- 基于.NET平台常用的框架和开源程序整理
- 列举PHP的Yii 2框架的开发优势
- Windows窗体的.Net框架绘图技术实现方法
- 浅谈JavaScript 框架分类
- 轻量级javascript 框架Backbone使用指南
- javascript实现框架高度随内容改变的方法
- JS刷新框架外页面七种实现代码
- 超赞的动手创建JavaScript框架的详细教程
- 深入探讨前端框架react
- js验证框架实现代码分享
- jQuery的框架介绍
- 简单介绍不用库(框架)自己写ajax
- 利用ASP.NET MVC+EasyUI+SqlServer搭建企业开发框架
- asp.net4.0框架下验证机制失效的原因及处理办法
- 插件管理框架 for Delphi(二)
- 零基础学习AJAX之AJAX框架
- Ajax 框架学习笔记