(三)、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. 【Machine Learning in Action --4】朴素贝叶斯过滤网站的恶意留言

    背景:以在线社区的留言板为例,为了不影响社区的发展,我们需要屏蔽侮辱性的言论,所以要构建一个快速过滤器,如果某条留言使用了负面或者侮辱性的语言,那么就将该留言标识为内容不当.过滤这类内容是一个很常见的 ...

  2. SQL函数学习(二):DATEADD() 函数

    DATEADD() 函数在日期中添加或减去指定的时间间隔. 语法 DATEADD(datepart,number,date) date 参数是合法的日期表达式.number 是您希望添加的间隔数:对于 ...

  3. go pkg

    fmt Scanln用来读取输入数据 示例: package main import ( "fmt" "os" "time" ) func ...

  4. iOS中的触摸事件,手势识别,摇晃事件等

    在iOS中,事件可以划分为以下几类: 1.触摸事件:通过触摸,手势进行触发(手指点击.缩放等) 2.运动事件:通过加速器触发(例如手机晃动) 3.远程控制事件:通过其他远程设备触发(例如耳机控制按钮) ...

  5. Day06 杂乱与4个对象

    1.杂乱 -- 数据库的分页操作 -- 分页使用的是rownum 例1: select rownum,empno,ename from emp ; 结果: 例2: select r,empno,ena ...

  6. 八、oracle 分页

    oracle的分页一共有三种方式 方法一 根据rowid来分 SELECT * FROM EMP WHERE ROWID IN (SELECT RID FROM (SELECT ROWNUM RN, ...

  7. CSS3的box-sizing属性

    盒模型的宽度,在 IE5.x 以及 Quirks 模式的 IE6/7 中,将 border 与 padding 都包含在 width 之内 W3C标准中的盒模型宽度为内容宽度,不包括内边距paddin ...

  8. codeforce Gym 101102A Coins (01背包变形)

    01背包变形,注意dp过程的时候就需要取膜,否则会出错. 代码如下: #include<iostream> #include<cstdio> #include<cstri ...

  9. javaWEB总结(2): load-on-startup节点

    在javaWEB总结(1)里面,我们创建了一个servlet以及它的映射,当我们访问那个映射地址的时候,就可以访问servlet,并且servlet容器调用了生命周期方法,销毁前调用destroy方法 ...

  10. QTP连接MYSQL数据库方法

    1.首先安装mysql数据驱动,qtp在windows系统下操作连接mysql,所以下载mysql-connector-odbc-   5.1.8-win32.msi 下载地址:http://mysq ...