(三)、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表达式

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

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

问题:标签取值方式?

El 表达式语言

是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中数据流转:

用户每次访问Struts的action,struts2都会创建:

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/application的map

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取值 : 自动搜索request的Map、session的map、application的map,找到后立刻返回!-->

<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提供的文件上传,主要是简化传统的上传操作!

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

回顾文件上传:

客户端:

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);

}

}

}

(三)、Struts第三天的更多相关文章

  1. 程序员编程艺术第三十六~三十七章、搜索智能提示suggestion,附近点搜索

    第三十六~三十七章.搜索智能提示suggestion,附近地点搜索 作者:July.致谢:caopengcs.胡果果.时间:二零一三年九月七日. 题记 写博的近三年,整理了太多太多的笔试面试题,如微软 ...

  2. 自学 iOS – 三十天三十个 Swift 项目

    自学 iOS – 三十天三十个 Swift 项目 github源码地址:https://github.com/allenwong/30DaysofSwift

  3. 【Web探索之旅】第三部分第三课:协议

    内容简介 1.第三部分第三课:协议 2.第四部分预告:Web程序员 第三部分第三课:协议 之前的课,我们学习了Client-Server模型的客户端语言和服务器语言. 客户端语言有HTML,CSS和J ...

  4. 自学 iOS - 三十天三十个 Swift 项目 第一天

    最近公司项目不是很忙,偶然间看到编程语言排行榜,看到swift 已经排到前10了,然OC排名也越来越后了,感觉要上车了,虽然现在项目都是用OC写的,但是swift是一种趋势.在网上看到"自学 ...

  5. STC8H开发(七): I2C驱动MPU6050三轴加速度+三轴角速度检测模块

    目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...

  6. Struts 2三种方式实现Ajax

    Ajax本质上和普通的HTTP请求是一样的,只不过普通的HTTP请求是给人看的,而Ajax请求是给JS代码去用的. 所以Ajax请求的页面一般比普通的HTTP请求的响应内容还要简单,可能是一个页面的一 ...

  7. struts(三)——struts框架实现登录示例

    前两篇讲解了struts框架的基本实现,自己感觉讲的也有些枯燥,今天拿登录的例子来做一个实现. 1.新建一个javaweb项目,并将struts的jar包拷贝到WebRoot/WEB-INF/lib下 ...

  8. SSH—Struts(三)—跑步者(Action)

    如已经描述Struts其基本原理和控制器ActionServlet,根据一个请求通过流ActionServlet之后就要到达Action类中做详细的处理了.ActionServlet通过ActionM ...

  9. Struts第三天

    OgnlValueStack贯穿整个 Action 的生命周期. 它是ContextMap中的一部分,里面的结构是一个List,是我们可以快速访问数据一个容器.它的封装是由struts2框架完成的. ...

随机推荐

  1. Asynchronous JS: Callbacks, Listeners, Control Flow Libs and Promises

    非常好的文章,讲javascript 的异步编程的. ------------------------------------------------------------------------- ...

  2. mac中Eclipse的快捷键

    查看某个类:command + shift +T 快速查看源代码中方法: command + o 选中某个类,command + t:查看此类的父类和子类 如果要导入一个类所在的包名,可以选中这个类, ...

  3. TCP小结

    TCP/IP协议实现了不同主机,不同操作系统之间信息交流.由4层构成,从上往下依次为: 1.应用层,包括http,ftp等协议,用于实现某一项具体的功能. 2.传输层,包括TCP和UDP,一个可靠,一 ...

  4. CentOS的KVM实践(虚拟机创建、网桥配置、Spice)

    最近公司准备上一套基于openstack的虚拟桌面系统,作为该项目的负责人,觉得有必要自己实践一下,该系统的搭建.最基础的就是需要了解基于linux的kvm的实践. 一.基础软件包准备 系统是采用px ...

  5. runat="server" 是什么意思?

    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs& ...

  6. RESTful架构2--架构详解

    转自:RESTful架构详解 1. 什么是REST REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移. 它首次出现在200 ...

  7. nfs服务器的建立

    NFS服务器的配置 一.NFS服务器端的配置,即共享发布者 (一)需启动的服务和需安装的软件 1.NFS服务器必须启动两个daemons服务:rpc.nfsd和rpc.mountd   rpc.nfs ...

  8. <marquee>,视频和音频的插入,正则表达式

    1.marquee 页面的自动滚动效果,不仅可以移动文字,也可以移动图片表格. <marquee></marquee>之间加内容即可. marquee的属性 1.滚动方向dir ...

  9. .NET面试题目一

    简单介绍下ADO.NET和ADO主要有什么改进? 答:ADO以Recordset存储,而ADO.NET则以DataSet表示,ADO.NET提供了数据集和数据适配器,有利于实现分布式处理,降低了对数据 ...

  10. Java is Pass-by-Value!

    Java is strictly pass-by-value. which means, when you pass a variable to a method, the method will j ...