(三)、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 表达式语言的支持!
l OGNL表达式
OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。 Struts2框架使用OGNL作为默认的表达式语言。
Strut2标签取值使用的表达式,就是Ognl表达式!
问题:标签取值方式?
El 表达式语言
是jsp2.0以后官方默认支持标准!
Struts2标签:
在struts2环境支持时候才可以用!
(功能更加强大!)
l 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、操作集合对象。
l 总结
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对象与值栈对象的关系?
l ValueStack
ValueStack实际是一个接口
Struts2在运行时候,时候的是接口的实现类:OgnlValueStack!
l ValueStack特点
ValueStack贯穿整个 Action 的生命周期!
相当于一个数据的中转站. 在其中保存当前Action 对象和其他相关对象.
Strut2运行时候,产生的数据都会保存值栈中!
Struts中数据流转:
用户每次访问Struts的action,struts2都会创建:
1. ActionContext对象
ActionContext.getContext.getSessionMap(“key”);
这个数据就是从值栈获取的!
2. 值栈对象
3. Action对象
然后会把action对象放到值栈中,
且通过ActionContext是可以获取值栈数据的!
l 获取方式
Struts2框架把 ValueStack 对象保存在名为 “struts.valueStack” 的
request请求属性中。
方式1: 通过ActionContext可以获取
方式2: 通过request对象获取!
l 值栈结构
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第三天的更多相关文章
- 程序员编程艺术第三十六~三十七章、搜索智能提示suggestion,附近点搜索
第三十六~三十七章.搜索智能提示suggestion,附近地点搜索 作者:July.致谢:caopengcs.胡果果.时间:二零一三年九月七日. 题记 写博的近三年,整理了太多太多的笔试面试题,如微软 ...
- 自学 iOS – 三十天三十个 Swift 项目
自学 iOS – 三十天三十个 Swift 项目 github源码地址:https://github.com/allenwong/30DaysofSwift
- 【Web探索之旅】第三部分第三课:协议
内容简介 1.第三部分第三课:协议 2.第四部分预告:Web程序员 第三部分第三课:协议 之前的课,我们学习了Client-Server模型的客户端语言和服务器语言. 客户端语言有HTML,CSS和J ...
- 自学 iOS - 三十天三十个 Swift 项目 第一天
最近公司项目不是很忙,偶然间看到编程语言排行榜,看到swift 已经排到前10了,然OC排名也越来越后了,感觉要上车了,虽然现在项目都是用OC写的,但是swift是一种趋势.在网上看到"自学 ...
- STC8H开发(七): I2C驱动MPU6050三轴加速度+三轴角速度检测模块
目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...
- Struts 2三种方式实现Ajax
Ajax本质上和普通的HTTP请求是一样的,只不过普通的HTTP请求是给人看的,而Ajax请求是给JS代码去用的. 所以Ajax请求的页面一般比普通的HTTP请求的响应内容还要简单,可能是一个页面的一 ...
- struts(三)——struts框架实现登录示例
前两篇讲解了struts框架的基本实现,自己感觉讲的也有些枯燥,今天拿登录的例子来做一个实现. 1.新建一个javaweb项目,并将struts的jar包拷贝到WebRoot/WEB-INF/lib下 ...
- SSH—Struts(三)—跑步者(Action)
如已经描述Struts其基本原理和控制器ActionServlet,根据一个请求通过流ActionServlet之后就要到达Action类中做详细的处理了.ActionServlet通过ActionM ...
- Struts第三天
OgnlValueStack贯穿整个 Action 的生命周期. 它是ContextMap中的一部分,里面的结构是一个List,是我们可以快速访问数据一个容器.它的封装是由struts2框架完成的. ...
随机推荐
- Asynchronous JS: Callbacks, Listeners, Control Flow Libs and Promises
非常好的文章,讲javascript 的异步编程的. ------------------------------------------------------------------------- ...
- mac中Eclipse的快捷键
查看某个类:command + shift +T 快速查看源代码中方法: command + o 选中某个类,command + t:查看此类的父类和子类 如果要导入一个类所在的包名,可以选中这个类, ...
- TCP小结
TCP/IP协议实现了不同主机,不同操作系统之间信息交流.由4层构成,从上往下依次为: 1.应用层,包括http,ftp等协议,用于实现某一项具体的功能. 2.传输层,包括TCP和UDP,一个可靠,一 ...
- CentOS的KVM实践(虚拟机创建、网桥配置、Spice)
最近公司准备上一套基于openstack的虚拟桌面系统,作为该项目的负责人,觉得有必要自己实践一下,该系统的搭建.最基础的就是需要了解基于linux的kvm的实践. 一.基础软件包准备 系统是采用px ...
- runat="server" 是什么意思?
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs& ...
- RESTful架构2--架构详解
转自:RESTful架构详解 1. 什么是REST REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移. 它首次出现在200 ...
- nfs服务器的建立
NFS服务器的配置 一.NFS服务器端的配置,即共享发布者 (一)需启动的服务和需安装的软件 1.NFS服务器必须启动两个daemons服务:rpc.nfsd和rpc.mountd rpc.nfs ...
- <marquee>,视频和音频的插入,正则表达式
1.marquee 页面的自动滚动效果,不仅可以移动文字,也可以移动图片表格. <marquee></marquee>之间加内容即可. marquee的属性 1.滚动方向dir ...
- .NET面试题目一
简单介绍下ADO.NET和ADO主要有什么改进? 答:ADO以Recordset存储,而ADO.NET则以DataSet表示,ADO.NET提供了数据集和数据适配器,有利于实现分布式处理,降低了对数据 ...
- 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 ...