您的位置:首页 > 编程语言 > Java开发

Struts2学习之文件上传/下载&ValueStack(三)

2015-03-06 01:07 274 查看

简介

今天是学习Struts2第三天,也算struts2准备前奏告一段落,提升部分只能在后期深入了解,多看源码,多参阅资料。今天所学的知识点文件上传、下载/ValueStack&OGNL/Struts2标签

文件上传/下载

文件上传简介 a).企业常用文件上传技术:jspSmartUpload(主要应用JSPmodel1时代)、fileupload(Apachecommons项目中一个组件)、Servlet3.0集成文件上传Part类 b).Struts2对文件上传的支持 提供FileUpload拦截器,用于解析multipart/form-data编码格式请求,解析上传文件的内容 fileUpload拦截器默认在defaultStack栈中,默认会执行的 1.单文件上传 a).页面编写: 存在<inputtype="file"name="upload"/>上传项,必须提供name属性 表单提交方式必须post提交 表单编码类型enctype="multipart/form-data" b).编写Action类,按照约定定义接收表单属性 privateFileupload;//这里变量名和页面表单元素name属性一致 privateStringuploadContentType; privateStringuploadFileName; *为三个对象提供setter方法 通过FileUtils提供copyFile进行文件复制,将上传文件保存到服务器端 c).Struts2上传文件过程中错误处理 1).配置input视图,作为上传出错后跳转页面 在文件上传时,如果发生错误,fileUpload拦截器会设置错误信息,workflow拦截器跳转到input视图 2).通过: jsp:<s:actionError/><s:feildError/>显示错误消息的提示 错误消息提示改为中文版:借助国际化的消息资源文件 如果是通过配置全局默认参数引起的错误,最好用全局的消息资源文件 **struts2默认的提示资源文件:struts2-core-**.jar的org.apache.struts2的struts-message.properties文件中。比着key值覆盖对应的value即可 2.多文件上传 表单上传字段名设置一样,Action类中可以定义属性为数组或者为集合进行接收,然后在下载操作时进行遍历处理 3.文件下载 第一种方式:在配置文件中进行处理(原理:使用结果类型进行处理。Stream) a).在Action类中中定义InputStream和文件名 b).关联资源文件,截取文件名进行URLEncode编码 c).返回结果逻辑视图 d).配置struts.xml文件 inputName/contentType/ <paramname="contentDisposition">attachment;filename=${@java.net.URLEncoder@encode(filename,'UTF-8')}</param> <paramname="contentLength">${filesize}</param> 第二种方式: 文件下载原理:服务器读取下载文件内容,通过Response响应流写回,设置ContentType、ContentDisposition头信息 a).在Action中定义contentType/contentDisposition/filename进行编码,添加相应的get方法 getInputStream() ServletActionContext.getServletContext().getMimeType(filename); encodeDownloadFilename(Stringfilename,Stringagent)文件名编码问题 b).struts中配置结果参数OGNL表达式进行获取


自定义的结果类型

1.开发一个直接或间接实现com.opensymphony.xwork2.Result接口 publicclassCaptchaResultimplementsResult{ publicvoidexecute(ActionInvocationarg0)throwsException{ //实现结果视图的输出代码 } } 2.在struts.xml中进行定义 <packagename="default"namespace="/"extends="struts-default"> <result-types> <result-typename="captcha"class="com.itheima.results.CaptchaResult"/> </result-types> </package> 3.在配置Action时,引入该结果类型 <actionname="genCaptcha"> <resulttype="captcha"> <!--<paramname="width">240</param> <paramname="height">50</param>--> </result> </action> 4.在页面中,访问第三步配置好的Action <imgsrc="${pageContext.request.contextPath}/genCaptcha.action"/>

ValueStack(值栈)

问题一:什么是值栈ValueStack? ValueStack是struts2提供一个接口,实现类OgnlValueStack----值栈对象(OGNL是从值栈中获取数据的) 每个Action实例都有一个ValueStack对象(一个请求对应一个ValueStack对象) 在其中保存当前Action对象和其他相关对象(值栈中是有Action引用的) Struts框架把ValueStack对象保存在名为“struts.valueStack”的请求属性中,request中(值栈对象是request一个属性) valueStackvs=request.getAttribute("struts.valueStack"); 问题二:值栈的内部结构? 值栈由两部分组成 ObjectStack(root):Struts把动作和相关对象压入ObjectStack中--List ContextMap(context):Struts把各种各样的映射关系(一些Map类型的对象)压入ContextMap中 Struts会把下面这些映射压入ContextMap中 parameters:该Map中包含当前请求的请求参数?name=xxx request:该Map中包含当前request对象中的所有属性 session:该Map中包含当前session对象中的所有属性 application:该Map中包含当前application对象中的所有属性 attr:该Map按如下顺序来检索某个属性:request,session,application ValueStack和ContextMap ValueStack中存在root属性(CompoundRoot)、context属性(OgnlContext) *CompoundRoot就是ArrayList *OgnlContext就是Map context对应Map引入root对象 *context中还存在request、session、application、attr、parameters对象引用 *OGNL表达式,访问root中数据时不需要#,访问request、session、application、attr、parameters对象数据必须写# *操作值栈默认指操作root元素 问题三:值栈对象的创建,ValueStack和ActionContext是什么关系? 值栈对象是请求时创建的 doFilter中prepare.createActionContext(request,response); *创建ActionContext对象过程中,创建值栈对象ValueStack *ActionContext对象对ValueStack对象有引用的(在程序中通过ActionContext获得值栈对象) Dispatcher类serviceAction方法中将值栈对象保存到request范围 request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY,proxy.getInvocation().getStack()); 问题四:如何获得值栈对象 获得值栈对象有两种方法 ValueStackvalueStack=(ValueStack)ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY); ValueStackvalueStack2=ActionContext.getContext().getValueStack(); 问题五:向值栈保存数据(主要针对root) 两种方式 //将数据保存root的索引0位置,放置到第一个元素ArrayListadd(0,element); valueStack.push("itcast"); //在值栈创建参数map,将数据保存到map中 valueStack.set("company","传智播客"); 在jsp中通过<s:debug/>查看值栈的内容 问题六:在JSP中获取值栈的数据 访问root中数据不需要# 访问其它对象数据加# 通过下标获取root中对象 <s:propertyvalue="[0].top"/>//取值栈顶对象 直接在root中查找对象属性(自上而下自动查找) valueStack:<s:propertyvalue="username"/> 哪些数据默认会放入到值栈? 1)每次请求,访问Action对象会被压入值栈-------DefaultActionInvocation的init方法stack.push(action); *Action如果想传递数据给JSP,只有将数据保存到成员变量,并且提供get方法就可以了 2)ModelDriven接口有一个单独拦截器 <interceptorname="modelDriven"class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/> 在拦截器中,将model对象压入了值栈stack.push(model); *如果Action实现ModelDriven接口,值栈默认栈顶对象就是model对象 问题七:为什么EL也能访问值栈中的数据 StrutsPreparedAndExecuteFilter的doFilter代码中request=prepare.wrapRequest(request); *对Request对象进行了包装,StrutsRequestWrapper *重写request的getAttribute Objectattribute=super.getAttribute(s); if(attribute==null){ attribute=stack.findValue(s); } 访问request范围的数据时,如果数据找不到,去值栈中找 *request对象具备访问值栈数据的能力(查找root的数据)

OGNL

OGNL是ObjectGraphicNavigationLanguage(对象图导航语言)的缩写,它是一个开源项目。Struts2框架使用OGNL作为默认的表达式语言。 *xwork提供OGNL表达式 *ognl-3.0.5.jar OGNL是一种比EL强大很多倍的语言 OGNL提供五大类功能 1、支持对象方法调用,如xxx.doSomeSpecial(); 2、支持类静态的方法调用和值访问 3、访问OGNL上下文(OGNLcontext)和ActionContext;(重点操作ValueStack值栈) 4、支持赋值操作和表达式串联 5、操作集合对象 使用OGNL访问对象方法和静态方法 *OGNL在jsp结合struts2标签库使用,<s:propertyvalue="ognl表达式"/>执行ognl表达式 调用实例方法:对象.方法()----<s:propertyvalue="'hello,world'.length()"/> 调用静态方法:@[类全名(包括包路径)]@[方法名]---<s:propertyvalue="@java.lang.String@format('您好,%s','小明')"/> *使用静态方法调用必须设置struts.ognl.allowStaticMethodAccess=true 访问OGNL上下文(OGNLcontext)和ActionContext OGNL上下文(OGNLcontext)对象-----值栈ValueStack 在OgnlContext中获取数据 request:<s:propertyvalue="#request.username"/> session:<s:propertyvalue="#session.username"/> application:<s:propertyvalue="#application.username"/> attr:<s:propertyvalue="#attr.username"/> parameters:<s:propertyvalue="#parameters.cid[0]"/> OGNL表达式常见使用 #、%、$符号使用 1)#的使用 用法一#代表ActionContext.getContext()上下文 <s:propertyvalue="#request.name"/>------------>ActionContext().getContext().getRequest().get("name"); #request #session #application #attr #parameters 用法二:不写#默认在值栈中root中进行查找 <s:propertyvalue="name"/>在root中查找name属性 *查询元素时,从root的栈顶元素开始查找,如果访问指定栈中元素<s:propertyvalue="[1].name"/>访问栈中第二个元素name属性 *访问第二个元素对象<s:propertyvalue="[1].top"/> 用法三:进行投影映射(结合复杂对象遍历) 1)集合的投影(只输出部分属性 <h1>遍历集合只要name属性</h1> <s:iteratorvalue="products.{name}"var="pname"> <s:propertyvalue="#pname"/> </s:iterator> 2)遍历时,对数据设置条件 <h1>遍历集合只要price大于1500商品</h1> <s:iteratorvalue="products.{?#this.price>1500}"var="product"> <s:propertyvalue="#product.name"/>---<s:propertyvalue="#product.price"/> </s:iterator> 3)综合 <h1>只显示价格大于1500商品名称</h1> <s:iteratorvalue="products.{?#this.price>1500}.{name}"var="pname"> <s:propertyvalue="#pname"/> </s:iterator> 用法四:使用#构造map集合 经常结合struts2标签用来生成select、checkbox、radio <h1>使用#构造map集合遍历</h1> <s:iteratorvalue="#{'name':'aaa','age':'20','hobby':'sport'}"var="entry"> key:<s:propertyvalue="#entry.key"/>,value:<s:propertyvalue="#entry.value"/><br/> </s:iterator> 2)%的使用 用法一:结合struts2表单表单使用,通过%通知struts,%{}中内容是一个OGNL表达式,进行解析 <s:textfieldname="username"value="%{#request.username}"/> 用法二:设置ognl表达式不解析%{'ognl表达式'} <s:propertyvalue="%{'#request.username'}"/> 3)$的使用 用法一:用于在国际化资源文件中,引用OGNL表达式 在properties文件msg=欢迎您,${#request.username} 在页面 <s:i18nname="messages"> <s:textname="msg"></s:text> </s:i18n> *自动将值栈的username结合国际化配置信息显示 用法二:在Struts2配置文件中,引用OGNL表达式 <!--在Action提供getContentType方法--> <paramname="contentType">${contentType}</param> *${contentType}读取值栈中contentType数据,在Action提供getContentType因为Action对象会被压入值栈, contentType是Action属性,从值栈获得 结论:#用于写ognl表达式获取数据,%控制ognl表达式是否解析,$用于配置文件获取值栈的数据


Struts2标签库

tag-reference.html就是struts2标签规范 1、通用标签库的学习 <s:property>解析ognl表达式,设置默认值,设置内容是否HTML转义 <s:set>向四个数据范围保存数据 <s:iterator>遍历值栈中数据 <s:if><s:elseif><s:else>进行条件判断--------elseif可以有多个 <s:url>进行URL重写(追踪Session),结合s:param进行参数编码 *<s:urlaction="download"namespace="/"var="myurl"> <s:paramname="filename"value="%{'MIME协议简介.txt'}"></s:param> </s:url> <s:propertyvalue="#myurl"/> <s:a>对一个链接进行参数编码 *<s:aaction="download"namespace="/">下载MIME协议简介.txt <s:paramname="filename"value="%{'MIME协议简介.txt'}"></s:param> </s:a> OGNL了解部分:支持赋值操作和表达式串联、操作集合对象 1)在值栈中保存一个对象 <s:propertyvalue="price=1000,name='冰箱',getPrice()"/>自动查找值栈中price和name属性为其赋值 2)ognl操作集合 <s:propertyvalue="products[0].name"/>访问集合第一个元素name属性 <s:propertyvalue="map['name']"/>访问map中key为name的值 {}直接构造List元素、#{}直接构造Map元素 <s:iteratorvalue="{'aaa','bbb'}"var="s"> <s:propertyvalue="#s"/> </s:iterator> <s:iteratorvalue="#{'ccc':'111','ddd':'222'}"var="entry"> <s:propertyvalue="#entry.key"/> </s:iterator> 2、UI标签库的学习(Form标签) 使用struts2form标签好处:支持数据回显,布局排班(基于Freemarker模板定义) struts2表单标签value属性。必须写%{}进行设值 *******使用struts2表单标签前,必须配置StrutsPrepareAndExecuteFilter TheStrutsdispatchercannotbefound.ThisisusuallycausedbyusingStrutstagswithouttheassociatedfilter.Strutstagsareonlyusablewhentherequesthaspassedthroughitsservletfilter,whichinitializestheStrutsdispatcherneededforthistag <s:form>表单标签 <s:formaction="regist"namespace="/"method="post"theme="xhtml">---theme="xhtml"默认布局样式 <s:textfield>生成<inputtype="text"> <s:password>生成<inputtype="password"> <s:submittype="submit"value="注册"/>生成<inputtype="submit"> <s:resettype="reset"value="重置"/> 生成<inputtype="reset"> *struts2除了支持JSP之外,支持两种模板技术Velocity(扩展名.vm)、Freemarker(扩展名.ftl) <s:textarea>生成<textarea>多行文本框 <s:checkboxlist>生成一组checkbox *使用ognl构造Map(看到值和提交值不同时) *<s:checkboxlistlist="#{'sport':'体育','read':'读书','music':'音乐'}"name="hobby"></s:checkboxlist> <s:radio>生成一组radio *使用ognl构造List(看到内容和提交值相同时) *<s:radiolist="{'男','女'}"name="gender"></s:radio> <s:select>生成一个<select> *<s:selectlist="{'北京','上海','南京','广州'}"name="city"></s:select> =============struts2开发密码框默认不回显 <s:passwordname="password"id="password"showPassword="true"/> 3、页面元素主题设置 default.properties----struts.ui.theme=xhtml设置struts2页面元素使用默认主题 struts.ui.templateSuffix=ftl默认模板引擎Freemarker 修改主题 方式一:<s:textfieldname="username"label="用户名“theme="simple"></s:textfield>只对当前元素有效 方式二:<s:formaction=""method="post"namespace="/ui“theme="simple">对form中所有元素有效 方式三:struts.xml <constantname="struts.ui.theme"value="simple"></constant>修改默认主题样式,页面所有元素都有效 优先级:方式一>方式二>方式三

小结

1、文件上传(完成上传、设置上传参数【限制上传大小、扩展名】) 2、文件下载一个流两个头(不同浏览器附件名乱码解决),自定义结果类型 3、OGNL表达式 值栈原理和OGNL对值栈数据访问 *valueStack何时创建(生命周期) *valueStack内部结构,和ActionContext关系 *在Action获取valueStack对象 *如何向valueStack保存数据 *在JSP如何通过struts2标签显示值栈的内容 *Action元素何时加入值栈,Model对象何时加入值栈 *Request对象装饰类StrutsRequestWrapper作用?(重写getAttribute访问request范围数据时,可以查找值栈) #、%、$的使用 *#解析ognl表达式,访问值栈内容 *#投影 *#{}构造Map----{}构造list *%控制OGNL表达式是否解析 *$配置文件中使用xml配置、properties国际化配置 4、通用标签 <s:property><s:iterator><s:set><s:if>[s:elseif、s:else]、<s:url>、<s:a> 5、form标签 *使用struts2标签编写注册页面regist.jsp
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: