zoukankan      html  css  js  c++  java
  • (三)、Struts第三天

    ()Struts第三天

    Struts核心业务:

    (Struts提供了哪些功能?)

    1.  请求数据自动封装(params拦截器)

    2.  struts数据处理方式

    * ActionContext

    实现RequestAware 等接口  (servletConfig拦截器)

    * ServletActionContext

    3.  拦截器功能

    4.  Ognl表达式语言与Struts标签   (今天)

    5.  文件上传 下载  (今天)

    6.  数据效验

    7.  类型转换、国际化

    8 .  其他技术

    模型驱动、数据回显等!

     

     

     

     

     

     

    1.  Ognl表达式语言与Struts标签 

    问题1

    Struts在运行时候,产生的数据,如果传递到页面,再jsp中取出显示的?

    问题2

    Ognl表达式语言与Struts标签关系?

     

     

    Ognl表达式概述:

    Struts2默认 必须引入Ognl.jar。这个jar包就是对Ognl 表达式语言的支持!

     

    OGNL表达式 

           OGNLObject Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。 Struts2框架使用OGNL作为默认的表达式语言。

    Strut2标签取值使用的表达式,就是Ognl表达式!

    问题:标签取值方式?

    E表达式语言

    jsp2.0以后官方默认支持标准!

    Struts2标签:

    struts2环境支持时候才可以用!

    (功能更加强大!)

     

    OGNL优势

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

           2、支持类静态的方法调用和值访问,表达式的格式:

                 @[类全名(包括包路径)]@[方法名 |  值名],例如:

                 @java.lang.String@format('foo %s', 'bar')

                 或@tutorial.MyConstant@APP_NAME; 

           3、支持赋值操作和表达式串联,如price=100, discount=0.8,

                 calculatePrice(),这个表达式会返回80; 

           4、访问OGNL上下文(OGNL context)和ActionContext; 

           5、操作集合对象。

    总结

            OGNL 有一个上下文(Context)概念,说白了上下文就是一个MAP结构,它实现  java.utils.Map 的接口。   这个Map就是值:OgnlContext!

     

    OgnlContext对象

    OgnlContext对象,是Ognl表达式语言的核心!

    注意:

    一般情况,很少直接用这个对象! Struts2标签取值时候使用!

     

    硬编码方式,来了解一下这个对象:

     

    /**

     * 硬编码,了解OgnlContext对象!

     * @author AdminTH

     *

     */

    public class OgnlContextDemo {

     

    // 1. OgnlContext实际上是一个Map!

    @Test

    public void testApp() throws Exception {

    // 创建OgnlContext对象是一个Map!

    OgnlContext context = new OgnlContext();

    // map中放数据

    context.put("cn""China");

    // 获取map中数据

    System.out.println(context.get("cn"));

    }

    // 2. OgnlContext对象,表达式取值:取根元素值

    @Test

    public void testApp2() throws Exception {

    OgnlContext context = new OgnlContext();

    // 往根元素设置值

    context.setRoot(new User(100,"Jack"new Address()));

    // 通过Ognl表达式取值

    // a. 构建一个表达式

    Object ognl = Ognl.parseExpression("address.city");

    // b. 解析表达式

    Object value = Ognl.getValue(ognl, context, context.getRoot());

    // 输出值

    System.out.println(value);

    }

    // 3. OgnlContext对象,表达式取值:取非根元素值

    // 总结: Ognl表达式语言取值,如果获取根元素值,直接写表达式; 非根元素值,在表达式前要加上#

    @Test

    public void testApp3() throws Exception {

    OgnlContext context = new OgnlContext();

    // map里面放数据(也叫往非根元素存放数据)

    context.put("user"new User(100,"Jack"new Address()));

    // 通过Ognl表达式获取值

    Object ognl = Ognl.parseExpression("#user.address.city");

    Object value = Ognl.getValue(ognl, context, context.getRoot());

    System.out.println(value);

    }

    //4. 其他功能,调用静态方法!

    @Test

    public void testApp4() throws Exception {

    OgnlContext context = new OgnlContext();

    // 如果是Math类的静态方法调用,可以省略类名称! 其他类,就必须写上类名!

    // Object ognl = Ognl.parseExpression("@Math@floor(10.1)");  // 得到表达式

    Object ognl = Ognl.parseExpression("@@floor(10.1)");  // 得到表达式

    Object value = Ognl.getValue(ognl, context, context.getRoot());// 解析表达式,获取值

    System.out.println(value);

    }

    }

     

    ValustStack值栈对象

    问题:

    OgnlContext对象与值栈对象的关系?

     

     

    ValueStack

           ValueStack实际是一个接口

        Struts2运行时候,时候的是接口的实现类:OgnlValueStack!

    ValueStack特点

            ValueStack贯穿整个 Action 的生命周期! 

    相当于一个数据的中转站在其中保存当前Action 对象和其他相关对象.

     

    Strut2运行时候,产生的数据都会保存值栈中!

    Struts中数据流转:

    用户每次访问Strutsactionstruts2都会创建:

    1.  ActionContext对象

    ActionContext.getContext.getSessionMap(key);

    这个数据就是从值栈获取的!

    2.  值栈对象

    3.  Action对象

    然后会把action对象放到值栈中,

    且通过ActionContext是可以获取值栈数据的!

     

    获取方式

             Struts2框架把 ValueStack 对象保存在名为 “struts.valueStack” 

     request请求属性中。

    方式1: 通过ActionContext可以获取

    方式2: 通过request对象获取!  

     

    值栈结构

    List栈:   存储Action对象!或其他根元素对象(Root)  【不用#

    Map栈:  存储映射数据!Map数据(非根元素数据)    【需要#符号】

     requestMap.put();

      Request.setAttribute(“”,””)

     

      

     

    Struts2标签取值 

     

     

    // 查看值栈结构

    public class VsAction extends ActionSupport{

    private User user;

    public User getUser() {

    return user;

    }

     

    @Override

    public String execute() throws Exception {

    // 模拟:调用Service查询!

    this.user = new User(1,"班长",new Address("骏景花园"));

    // 获取值栈,方式1

    // ValueStack vs2 = 

    // (ValueStack) ServletActionContext.getRequest().getAttribute("struts.valueStack");

    // 获取值栈,方式2  

    ActionContext ac = ActionContext.getContext();

    ValueStack vs1 = ac.getValueStack();

     

    /*

     * ValustStack:

     * 

     * 1. 往根据元素root, list,  节点存放数据  【root   CompoundRoot

     */

    vs1.set("cn""China");   // 存储以Map结构存储!

    vs1.set("usa""Ameraica");

    vs1.setValue("test""test");

    User user = new User(1,"杰克",new Address("广州"));

    vs1.push(user); // 入栈, 放入list栈中第一个元素

    /*

     * 2. 往非给元素存放数据,map栈!   【context  OgnlContext

     */

    // 获取request/session/applicationmap

    Map<String,Object> request = (Map<String, Object>) ac.get("request");

    Map<String, Object> session = ac.getSession();

    Map<String, Object> application = ac.getApplication();

    // 存数据

    ac.getContextMap().put("test_contextMap""test_contextMap");

    request.put("request_data""request_data");

    request.put("request_data2""request_data2");

    session.put("session_data""session_data");

    application.put("application_data""application_data");

    return SUCCESS;

    }

    }

     

    <body>

      <!-- 引入struts标签库 -->

      <%@taglib uri="/struts-tags" prefix="s" %>

         <!--  一、   通过el,  获取struts运行产生的数据 -->

         ${user.id }

         ${user.name }

         ${user.address.city }

         ${requestScope.test_contextMap }   

         ${requestScope.request_data }

         ${sessionScope.session_data }  <hr/>

         

     

         <!--  二、使用Ognl表达式语言取值! (必须要使用struts标签!)-->

         <!-- property标签取值,默认获取栈顶元素的值 -->

         <s:property/>

         <s:property value="user.id"/>

         <s:property value="user.name"/>

         <s:property value="user.address.city"/> <hr/>

         

         <!-- 非根元素取值 -->

         <s:property value="#test_contextMap"/>

         <s:property value="#request.test_contextMap"/>

         <s:property value="#request.request_data"/>   <hr/>

         

         <s:property value="#session.session_data"/>

         <s:property value="#application.application_data"/>   <hr/>

         

         <!-- 使用attr取值 自动搜索requestMapsessionmapapplicationmap,找到后立刻返回!-->

         <s:property value="#attr.request_data"/>

         <s:property value="#attr.session_data"/>

         <s:property value="#attr.application_data"/>   <hr/>

      

         <!-- 

          封装请求数据值的map:parameters

          访问:http://localhost:8080/day29/ognl.jsp?userName=Jack&pwd=888

          -->

          <s:property value="#parameters"/>

          <s:property value="#parameters.userName"/>   <!-- 输出:Jack -->

          <s:property value="#parameters.pwd"/>        <!-- 输出:888 -->

      

         <!-- 查看值栈数据 -->

         <s:debug></s:debug>

      </body>

     

     

     

     

     

     

     

     

    取值中几个符号用法 & Struts2常用标签

     

    Struts2中几个取值符号的用法:

    $   配置文件取值符号

    #   非根元素取域中值; 动态构建Map集合!

    %   提供一个Ognl表达式运行环境

     

     

     

     

     

     

    5.文件上传 下载

    文件上传

    Struts2提供的文件上传,主要是简化传统的上传操作!

    在引入struts2jar包中,默认必须引入文件上传的2jar包!

     

    回顾文件上传:

    客户端:

    1. 提交方式:post

    2. 表单类型: multipart/form-data

    3. 文件域

    服务器段:

    a. 自己解析内容

    b.  apache提供的fileUpload组件!

    c.  其他文件上传组件

     

    Struts2如何简化上传操作?

     

     

    ü 上传单个文件

    Jsp页面:

    <body>

       <form action="/day29/fileUpload.action" method="post" enctype="multipart/form-data">

       用户名:<input type="text" name="userName">   <br/>

       文件:   <input type="file" name="file1">   <br/>

       <input type="submit">

       </form>

      </body>

     

    Action:

    package cn.itcast.c_upload;

     

    import java.io.File;

    import java.io.IOException;

     

    import org.apache.commons.io.FileUtils;

    import org.apache.struts2.ServletActionContext;

     

    import com.opensymphony.xwork2.ActionContext;

    import com.opensymphony.xwork2.ActionSupport;

     

    // 上传一个处理

    public class UploadAction_上传一个 extends ActionSupport{

     

    // 封装普通表单数据

    private String userName;

    public void setUserName(String userName) {

    this.userName = userName;

    }

    // 封装文件上传数据

    private File file1;     // 上传的文件; 对象名称与表单元素名称一致

    private String file1FileName; // 上传的文件名 = 元素名称+ FileName(固定)

    private String file1ContentType;// 文件类型

    public void setFile1(File file1) {

    this.file1 = file1;

    }

    public void setFile1FileName(String file1FileName) {

    this.file1FileName = file1FileName;

    }

    public void setFile1ContentType(String file1ContentType) {

    this.file1ContentType = file1ContentType;

    }

    // 主要测试“上传”!

    @Override

    public String execute() {

    // 文件上传到服务器的: "/day27/upload目录"

    // 获取Actioncontext对象

    ActionContext ac = ActionContext.getContext();

    try {

    //1. 获取上传目录,路径

    String path = ServletActionContext.getServletContext().getRealPath("/upload");

    //2. 在目录下创建文件对象

    File dest = new File(path,file1FileName);

    //3. 上传

    // 参数1: 源文件

    // 参数2: 上传到的目标文件

    FileUtils.copyFile(file1, dest);

    // 提示

    ac.put("msg""上传" + file1FileName +"成功!");

    catch (Exception e) {

    ac.put("msg""上传" + file1FileName +"失败!!");

    e.printStackTrace();

    }

    return SUCCESS;

    }

    }

     

     

    ü 上传多个文件

    Jsp页面:

    <body>

       <form action="/day29/fileUpload.action" method="post" enctype="multipart/form-data">

       用户名:<input type="text" name="userName">   <br/>

       文件:   <input type="file" name="file1">   <br/>

       文件:   <input type="file" name="file1">   <br/>

      

       <input type="submit">

       </form>

      </body>

     

    package cn.itcast.c_upload;

     

    import java.io.File;

    import java.util.ArrayList;

    import java.util.List;

     

    import org.apache.commons.io.FileUtils;

    import org.apache.struts2.ServletActionContext;

     

    import com.opensymphony.xwork2.ActionContext;

    import com.opensymphony.xwork2.ActionSupport;

     

    // 上传多个

    public class UploadAction extends ActionSupport{

     

    // 封装普通表单数据

    private String userName;

    public void setUserName(String userName) {

    this.userName = userName;

    }

    // 封装文件上传数据

    private File[] file1;     // 上传的文件; 对象名称与表单元素名称一致

    private String[] file1FileName; // 上传的文件名 = 元素名称+ FileName(固定)

    private String[] file1ContentType;// 文件类型

    public void setFile1(File[] file1) {

    this.file1 = file1;

    }

    public void setFile1FileName(String[] file1FileName) {

    this.file1FileName = file1FileName;

    }

    public void setFile1ContentType(String[] file1ContentType) {

    this.file1ContentType = file1ContentType;

    }

    // 主要测试“上传”!

    @Override

    public String execute() {

    // 文件上传到服务器的: "/day27/upload目录"

    // 获取Actioncontext对象

    ActionContext ac = ActionContext.getContext();

    // 提示信息保存

    List<String> list = new ArrayList<String>();

    try {

    //1. 获取上传目录,路径

    String path = ServletActionContext.getServletContext().getRealPath("/upload");

    // 上传多个,增加遍历功能!

    for (int i=0; i<file1.length; i++){

    //2. 在目录下创建文件对象

    File dest = new File(path,file1FileName[i]);

    //3. 上传

    // 参数1: 源文件

    // 参数2: 上传到的目标文件

    FileUtils.copyFile(file1[i], dest);

    list.add("第"+(i+1)+"个文件:" +file1FileName[i] + ", 上传成功!");

    }

    // 保存提示

    ac.put("list", list);

    catch (Exception e) {

    ac.put("msg""上传失败!!");

    e.printStackTrace();

    }

    return SUCCESS;

    }

    }

     

     

    ü 错误处理、大小限制、类型限制

    错误处理:

     

    <global-results>

    <!-- struts在文件上传失败的时候,会自动返回input视图,即错误页面对应的视图 -->

    <result name="input">/c/error.jsp</result>

    </global-results>

    大小、类型限制:

    <!-- 下载返回处理:stream -->

    <result name="down" type="stream">

       <!-- 下载的文件的mime类型; 指定为二进制类型即可,支持所有文件类型;(tomcat/confg/web.xml搜索exe) -->

       <param name="contentType">application/octet-stream</param>

       

       <!-- 对应Action类中get属性名称!(即:action类返回流的方法!) -->

       <param name="inputName">fileStream</param>

       

       <!-- 指定下载的响应头; 以及下载显示的文件的文件名(中文,需要url编码后) -->

       <param name="contentDisposition">attachment;filename=${downFileName}</param>

       

       <!-- 每次读取文件的缓存大小 -->

       <param name="bufferSize">1024</param>

    </result>

     

    ü 完整的struts.xml

    <?xml version="1.0" encoding="UTF-8" ?>

    <!DOCTYPE struts PUBLIC

    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"

    "http://struts.apache.org/dtds/struts-2.3.dtd">

     

    <struts>

     

    <!-- 配置struts上传默认支持的大小限制是:20M, 默认是2M -->

    <constant name="struts.multipart.maxSize" value="20971520"></constant>

     

    <package name="upload" extends="struts-default">

    <global-results>

    <!-- struts在文件上传失败的时候,会自动返回input视图,即错误页面对应的视图 -->

    <result name="input">/c/error.jsp</result>

    </global-results>

    <action name="fileUpload" class="cn.itcast.c_upload.UploadAction">

    <!-- 指定执行默认的拦截器,给fileUpload拦截器设置参数值 -->

    <interceptor-ref name="defaultStack">

    <!-- 限制允许的文件扩展名称 -->

    <param name="fileUpload.allowedExtensions">txt,jar,zip,jpg</param>

    <!-- 限制允许的文件类型  (注意:如果与线面的扩展名名称限制一起使用,取交集!)

    <param name="fileUpload.allowedTypes">text/plain</param>

    -->

    </interceptor-ref>

    <result>/c/msg.jsp</result>

    </action>

    <!-- 下载的action -->

    <action name="down_*" class="cn.itcast.c_upload.DownAction" method="{1}">

    <!--下载 列表 -->

    <result name="list">/c/down.jsp</result>

    <!-- 下载返回处理:stream -->

    <result name="down" type="stream">

       <!-- 下载的文件的mime类型; 指定为二进制类型即可,支持所有文件类型;(tomcat/confg/web.xml搜索exe) -->

       <param name="contentType">application/octet-stream</param>

       

       <!-- 对应Action类中get属性名称!(即:action类返回流的方法!) -->

       <param name="inputName">fileStream</param>

       

       <!-- 指定下载的响应头; 以及下载显示的文件的文件名(中文,需要url编码后) -->

       <param name="contentDisposition">attachment;filename=${downFileName}</param>

       

       <!-- 每次读取文件的缓存大小 -->

       <param name="bufferSize">1024</param>

    </result>

    </action>

     

    </package>

     

    </struts>

     

     

     

    下载

    方式1:传统的servlet中下载!

    设置下载响应头!

    注意:

    Action的业务方法,返回null

     

    方式2: strtus2提供的下载方式!

     

     

     

    代码(补充)

    package cn.itcast.c_upload;

     

    import java.io.File;

    import java.io.InputStream;

    import java.io.UnsupportedEncodingException;

    import java.net.URLEncoder;

     

    import org.apache.struts2.ServletActionContext;

     

    import com.opensymphony.xwork2.ActionContext;

    import com.opensymphony.xwork2.ActionSupport;

     

    public class DownAction extends ActionSupport{

     

    /****************一、 下载列表显示********************/

    public String list() {

    // 获取上传目录路径

    String path = ServletActionContext.getServletContext().getRealPath("/upload");

    // 目录对象

    File file = new File(path);

    // 获取目录下的所有“文件名”

    String[] names = file.list();

    // 保存

    ActionContext.getContext().getContextMap().put("names", names);

    return "list";

    }

    /****************二、 下载, 处理********************/

    // 1. 封装数据 (下载的文件的文件名称) 

    private String fileName;

    public void setFileName(String fileName) {  // 传入的文件名(get提交,中文)

    // 中文处理

    try {

    fileName = new String(fileName.getBytes("ISO8859-1"),"UTF-8");

    } catch (UnsupportedEncodingException e) {

    e.printStackTrace();

    }

    this.fileName = fileName;

    }

    // 2. 处理下载请求

    public String down(){

    return "down";  // 字符换,对应的跳转类型“stream

    }

    // 3. 返回文件流

    public InputStream getFileStream(){

    // 返回文件为fileName的文件流

    return ServletActionContext.getServletContext().getResourceAsStream("/upload/"+ fileName);

    }

    // 4. 下载的文件名称(中文,需要url编码)

    public String getDownFileName(){

    // fileName进行URL编码!

    try {

    return URLEncoder.encode(fileName, "UTF-8");  // 确保浏览器显示的下载文件是正确的!

    } catch (UnsupportedEncodingException e) {

    throw new RuntimeException(e);

    }

    }

    }

     

     

     

     





  • 相关阅读:
    python自定义排序
    flex 布局
    display: table-cell; 元素上下左右居中,子元素无宽高
    transform 方法 上下左右元素居中 子元素无宽高
    flex 方法上下左右居中 子元素无宽高
    兼容-02
    兼容
    jS辨别访问浏览器判断是android还是ios系统
    选项卡
    返回顶部
  • 原文地址:https://www.cnblogs.com/dantefung/p/4834101.html
Copyright © 2011-2022 走看看