Struts2学习之3(文件的上传下载,OGNL表达式,常用标签,表单重复提交)

来源:互联网 发布:香港代购mac口红多少钱 编辑:程序博客网 时间:2024/04/30 23:29

  • 文件的上传和下载
    • 文件的上传
      • 上传页面
      • 配置信息
      • 动作类
      • 错误信息配置
    • 文件的下载结果类型的使用
      • 配置信息
      • 动作类
  • Struts中的数据中心与OGNL表达式
    • Stack ContextValue Stack ContentsrootValueStack和ActionContext之间的关系
    • OGNL表达式简介
      • 支持对象方法调用如xxxdoSomeSpecial
      • 支持类静态的方法调用和值访问
      • 访问OGNL上下文OGNL context和ActionContext
      • 操作集合对象
      • 字符串和OGNL表达式转换
      • 在配置文件中xml或properties也可以使用OGNL表达式请使用ognl
  • Struts2中的常用标签
  • 防止表单重复提交
    • 表单页面
    • 配置信息

文件的上传和下载

文件的上传

必要前提:
表单的method必须是post
表单的enctype必须是multipart/form-data
提供input type=”file”类型上传输入域
在Struts2中,文件上传是由一个叫做fileUpload拦截器完成的。

上传页面

<body>    <s:actionerror/><!-- 显示错误信息 -->    <s:form action="upload" namespace="/uploadFile" enctype="multipart/form-data" method="post">    <!-- name属性一定要和动作类中的属性名一致 -->    <s:file name="photo" label="文件1" ></s:file>    <s:file name="photo" label="文件2" ></s:file>    <s:submit value="上传"></s:submit>   </s:form></body>

配置信息

<!-- 限制上传文件的总大小 -->    <constant name="struts.multipart.maxSize" value="10485760"></constant>    <!-- 国际化加载资源信息,用来回显上传出错的错误信息,fileupload为信息配置文件的名字 -->    <constant name="struts.custom.i18n.resources" value="fileupload"></constant>    <!-- 文件上传 -->    <package name="uploadFile" extends="struts-default" namespace="/uploadFile">        <action name="upload" class="com.jyh.action.Upload1Action" method="upload">            <!-- 引用defaultStack默认的拦截器栈 -->            <interceptor-ref name="defaultStack">                <!-- 设置文件的MIME类型 -->                <param name="fileUpload.allowedTypesSet">image/jpeg,image/bmp</param>                <!-- 设置该栈中fileUpload拦截器的allowedExtensions属性值(允许上传文件的类型,即后缀名 )-->                <param name="fileUpload.allowedExtensions">.jpg,.bmp,.png</param>             </interceptor-ref>            <result name="success">/success.jsp</result>            <result name="input">/upload.jsp</result>            <result name="error">/error.jsp</result>        </action>    </package>

动作类

package com.jyh.action;import java.io.File;import java.io.IOException;import javax.servlet.ServletContext;import org.apache.commons.io.FileUtils;import org.apache.commons.lang3.StringUtils;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.ActionSupport;@SuppressWarnings("serial")public class Upload1Action extends ActionSupport {    private String name;    private File[] photo;//多文件上传,用数组或者集合    private String[] photoFileName;//上传文件的文件名,xxxFileName固定写法    private String[] photoContentType;//上传文件的MIME类型,xxxContentType固定写法    public String upload() {        ServletContext context = ServletActionContext.getServletContext();        String directory = context.getRealPath("/files");        if(StringUtils.isBlank(photoFileName[0])){            return INPUT;        }else{            for (int i = 0; i < photo.length; i++) {                File target = new File(directory, photoFileName[i]);                try {                    FileUtils.copyFile(photo[i], target);//将源文件复制到上传目录                } catch (IOException e) {                    return INPUT;                }            }        }        return SUCCESS;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public File[] getPhoto() {        return photo;    }    public void setPhoto(File[] photo) {        this.photo = photo;    }    public String[] getPhotoFileName() {        return photoFileName;    }    public void setPhotoFileName(String[] photoFileName) {        this.photoFileName = photoFileName;    }    public String[] getPhotoContentType() {        return photoContentType;    }    public void setPhotoContentType(String[] photoContentType) {        this.photoContentType = photoContentType;    }}

错误信息配置

这里写图片描述

文件的下载:结果类型的使用

配置信息

<package name="downloadFile" extends="struts-default" namespace="/downloadFile">    <action name="download" class="com.jyh.action.DownloadAction" method="download">        <!-- type结果类型为stream -->        <result name="success" type="stream">            <!-- 指定是动作类中的哪个属性 -->            <param name="inputName">inputStream</param>            <!-- 通知浏览器以下载的方式打开 -->            <param name="contentDisposition">attachment;filename=${fileName}</param>            <!-- MIME类型 -->            <param name="contentType">application/octet-stream</param>        </result>        <result name="error">/error.jsp</result>    </action></package>

动作类

package com.jyh.action;import java.io.FileInputStream;import java.io.InputStream;import java.net.URLEncoder;import org.apache.commons.io.FilenameUtils;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.ActionSupport;@SuppressWarnings("serial")public class DownloadAction extends ActionSupport {    private InputStream inputStream;    private String fileName;    public String download(){        try {            String realPath = ServletActionContext.getServletContext().getRealPath("/files/" + fileName);            inputStream = new FileInputStream(realPath);        } catch (Exception e) {            return ERROR;        }        return SUCCESS;    }    public InputStream getInputStream() {        return inputStream;    }    public void setInputStream(InputStream inputStream) {        this.inputStream = inputStream;    }    public String getFileName() {        return fileName;    }    public void setFileName(String fileName) {        this.fileName = fileName;    }}

Struts中的数据中心与OGNL表达式

Stack Context,Value Stack Contents(root),ValueStack和ActionContext之间的关系

这里写图片描述

key value 备注 request ServletRequest中的所有属性(Attributes) 相当于EL表达式中的requestScope session HttpSession中的所有Attributes 相当于EL表达式中的sessionScope application ServletContext中的所有Attributes 相当于EL表达式中的applicationScope action 动作类 value stack(根) 一个List栈 parameters request.getParameterMap(),请求中的参数 相当于EL表达式中的paramValues attr 按照request>session>application的顺序查找数据 ${}

OGNL表达式简介

前提:在struts2中要使用OGNL表达式,必须放到Struts2的标签中。
OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,
它是一个开源项目。webwork用它作为表达式语言。
功能:

.支持对象方法调用,如xxx.doSomeSpecial();

2.支持类静态的方法调用和值访问;

 <body>    <!-- s:property 就相当于JSTL中的 c:out -->   <!-- 调用任意对象的任意方法  -->   <s:property value="'abcdefg'.length()"/>   <hr/>   <!-- 访问静态变量 -->   <s:property value="@java.lang.Integer@MAX_VALUE"/>    <hr/>   <!-- 访问静态方法 配置参数:<constant name="struts.ognl.allowStaticMethodAccess" value="true"></constant>-->   <s:property value="@java.lang.Math@abs(-100)"/>    <hr/> </body>

3.访问OGNL上下文(OGNL context)和ActionContext;

java代码添加数据

package com.jyh.action;import java.util.Calendar;import java.util.Date;import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.ActionContext;import com.opensymphony.xwork2.ActionSupport;import com.opensymphony.xwork2.util.CompoundRoot;import com.opensymphony.xwork2.util.ValueStack;@SuppressWarnings("serial")public class Demo1Action extends ActionSupport {    private String userName = "哈哈哈";    public String getUserName() {        return userName;    }    public void setUserName(String userName) {        this.userName = userName;    }    public String m1(){        ActionContext actionContext = ActionContext.getContext();//action        ValueStack vs = actionContext.getValueStack();//根栈        Map<String, Object> contextMap = vs.getContext();//上下文Map        //验证        actionContext.put("p1", "pppp1");        String s1 = (String)contextMap.get("p1");        contextMap.put("p2", "pppp2");        String s2 = (String)actionContext.get("p2");        System.out.println("s1:" + s1 + ",s2:" + s2);        //得出结论:actionContextput进去的数据contextMap可以取出来,反之亦可,        //查看源码可知,actionContextput和get方法就是调用contextMap的put和get方法        vs.set("p3", "pp3");//检测栈顶中有没有map,没有就创建一个map,把本值塞入map中后再将map push进去        vs.set("p4", "p4");//检测到栈顶是一个map,直接将数据塞入到 map中去        vs.setValue("p4", "pp4");//从栈顶开始搜索p4,找到之后就调用setAbc方法设置值        vs.setValue("#p5", "p5");//添加进contextMap中去        Object obj = vs.findValue("p3");//查找栈中的值,如果栈中找不到,就将值当做key在Stack Context中找        System.out.println(obj.toString());        Object obj2 = vs.findValue("#p5");        System.out.println(obj2.toString());        //-----------------------------        CompoundRoot root =  vs.getRoot();//contextMap中的根        //System.out.println(root);        //压对象进栈        vs.push(new Date());        vs.push("d1");        System.out.println("d1:" + root.peek());        root.push("d2");        System.out.println("d2:" + vs.peek());        //压两个时间对象        Calendar c1 = Calendar.getInstance();        c1.set(2000, 0, 1);        vs.push(c1.getTime());//2000-1-1        Calendar c2 = Calendar.getInstance();        c2.set(2014, 10,2);        vs.push(c2.getTime());//2014-11-2        HttpServletRequest request = ServletActionContext.getRequest();        request.setAttribute("r1", "r1");//将值塞入request域中去        actionContext.put("r2", "r2");//将值塞入Stack Context中去        return SUCCESS;    }    public String regist(){        System.out.println(userName);        return null;    }    public String regist1(){        System.out.println(userName);        return SUCCESS;    }}

页面用OGNL表达式获取数据

<body>    <s:debug></s:debug>    <!-- 取根栈中对象的属性 -->    <s:property value="time"/><hr>    <s:property value="userName"/><hr>    <!-- 取第二个时间的月份 -->    <s:property value="[1].month"/><hr>    <!-- #表示获取Stack Context中的数据 -->    <s:property value="#p1"/><br>    <s:property value="p1"/><hr>    <s:property value="p3"/><br>    <s:property value="p4"/><hr>    <s:property value="#p5"/><br>    <s:property value="p5"/><hr>    <s:property value="#request.r1"/><br>    ${r1}<br>    <s:property value="r2"/><br>    ${r2}<hr></body>

4.操作集合对象。

<s:property value="{'a','b','c'}.getClass()"/><br/>    <s:property value="#{'1':'a','2':'b','3':'c'}.getClass()"/><br/>    <s:radio name="gender" list="#{'0':'男','1':'女'}"></s:radio><br/>    <s:checkboxlist name="hobbies" list="{'吃饭','睡觉','打逗逗'}"></s:checkboxlist><br/>

5.字符串和OGNL表达式转换

<!-- 字符串转OGNL表达式,%{}括起来 --><s:textfield name="姓名" label="%{姓名}"></s:textfield><br/><!-- OGNL表达式转字符串,引号 包含起来 (property标签的value属性都是OGNL表达式 )--><s:property value="'0'"/>

6.在配置文件中xml或properties也可以使用OGNL表达式,请使用${ognl}

<!-- 通知浏览器以下载的方式打开 --><param name="contentDisposition">attachment;filename=${fileName}</param>

Struts2中的常用标签

<body>    <!-- 输出标签 -->    <s:property value="{'a','b','c'}.getClass()"/><br/>    <s:property value="#{'1':'a','2':'b','3':'c'}.getClass()"/><br/>    <!-- radio标签 -->    <s:radio name="gender" list="#{'0':'男','1':'女'}"></s:radio><br/>    <!-- 相当于checkbox -->    <s:checkboxlist name="hobbies" list="{'吃饭','睡觉','打逗逗'}"></s:checkboxlist><br/>    <!-- 相当于input -->    <s:textfield name="姓名" label="%{姓名}"></s:textfield><br/>    <br/><hr><br/>    <!--         set标签,存数据,        范围有:application|request|session|action        默认范围是action,1.放到请求范围request和2.放到Stack Context中去     -->    <s:set value="'session'" var="ss" scope="session"></s:set><br/>    <s:property value="#session.ss"/>    <s:set value="'value'" var="key"></s:set><br/>    StackContext:<s:property value="#key"/><br/>    requestScope:<s:property value="#request.key"/><br/>    <!-- bean:new一个对象放入Stack Context中去 -->    <s:bean name="java.util.Date" var="now"></s:bean><!-- new一个名为now的时间对象放入StackContext中去 -->    <s:property value="#now.time"/><br>    <!-- 包含另一个动作 -->    <s:action name="demo2" executeResult="true"></s:action><br/>    <!-- 循环 -->    <table border="1">        <tr>            <td>key</td>            <td>value</td>        </tr>        <!-- 把当前遍历的元素压如StackContext中去,var的值就是所对应的key,var对应的value就是需要的键值对象 -->        <s:iterator value="#request" var="me">            <tr>                <td><s:property value="#me.key"/></td>                <td><s:property value="#me.value"/></td>            </tr>        </s:iterator>        <tr><td>---</td><td>---</td></tr>        <!-- 不指定var,将要遍历的数据压入根栈中去 -->        <s:iterator value="#request">            <tr>                <td><s:property value="key"/></td>                <td><s:property value="value"/></td>            </tr>        </s:iterator>    </table>    <br>    <!--         status存当前遍历的数据并放入StackContext,并提供以下方法        isOdd,isEven,isLast,isFirst,getIndex,getCount     -->    <table border="1">        <tr><td>key</td><td>value</td><td>index</td></tr>        <!-- 不指定var,将要遍历的数据压入根栈中去 -->        <s:iterator value="#request" status="s">            <tr>                <td><s:property value="key"/></td>                <td><s:property value="value"/></td>                <td><s:property value="#s.count"/></td>            </tr>        </s:iterator>    </table>    <!-- a标签链接 -->    <s:a action="stackDemo/demo1">戳这里<s:param name="userName" value="'不明'"></s:param></s:a>    <s:url action="stackDemo/demo1" var="url">        <s:param name="userName" value="'不明'"></s:param>    </s:url>    <a href="${url}">猛戳</a></body>

防止表单重复提交

表单页面

<body>    <s:form action="/form/formRegist1" method="post">        <s:textfield name="userName" label="姓名"></s:textfield>        <s:token></s:token><!-- 关键 -->        <s:submit value="注册"></s:submit>    </s:form></body>

配置信息

<!-- 防止表单重复提交 -->    <package name="form" extends="struts-default" namespace="/form">        <action name="formRegist" class="com.jyh.action.Demo1Action" method="regist">            <interceptor-ref name="defaultStack"></interceptor-ref>            <interceptor-ref name="token"></interceptor-ref>            <!-- 拦截器转向,在表单重复提交的时候 -->            <result name="invalid.token">/msg.jsp</result>        </action>        <action name="formRegist1" class="com.jyh.action.Demo1Action" method="regist1">            <interceptor-ref name="defaultStack"></interceptor-ref>            <!-- 与token不同的是,重复提交之后会返回提交的界面 -->            <interceptor-ref name="tokenSession"></interceptor-ref>            <result>/success.jsp</result>        </action></package>
0 0