Struct2入门三

来源:互联网 发布:口袋妖怪能力数据 编辑:程序博客网 时间:2024/05/16 16:05

Struts2国际化
1、 国际化原理 ? 什么是国际化 ?
同一款软件 可以为不同用户,提供不同语言界面 —- 国际化软件
需要一个语言资源包(很多properties文件,每个properties文件 针对一个国家或者语言 ,通过java程序根据来访者国家语言,自动读取不同properties文件 )

2、 资源包编写
properties文件命名 : 基本名称语言(小写)国家(大写).properties
例如 :
messages_zh_CN.properties 中国中文
messages_en_US.properties 美国英文
3、 ResourceBundle 根据不同Locale(地域信息),读取不同国家 properties文件
ResourceBundle bundle = ResourceBundle.getBundle(“messages”, Locale.US);
国际化配置
第一种 全局国际化信息文件 (所有Action都可以使用 ) ——- 最常用
* properties文件可以在任何包中
* 需要在struts.xml 中配置全局信息文件位置

struts.xml

<constant name="struts.custom.i18n.resources" value="messages"></constant>   messages.properties 在src根目录    <constant name="struts.custom.i18n.resources" value="cn.itcast.resources.messages"></constant>   
messages.properties 在 cn.itcast.resources 包

国际化信息
在Action中使用 : this.getText(“msg”);
在jsp中使用 :
在配置文件中(校验xml) :

第二种 Action范围信息文件 (只能在某个Action中使用 )
数据只能在对应Action中使用,在Action类所在包 创建 Action类名.properties ——— 无需配置

第三种 package范围信息文件 (package中所有Action都可以使用 )
数据对包 (包括子包)中的所有Action 都有效 , 在包中创建 package.properties —– 无需配置

第四种 临时信息文件 (主要在jsp中 引入国际化信息 )
在jsp指定读取 哪个properties文件


* 向信息中传递参数 {0} {1} ———— MessageFormat 动态消息文本
this.getText(“required”, new String[] { “用户名” });

Struts2拦截器
拦截器介绍
拦截器 的使用 ,源自Spring AOP(面向切面编程)思想
拦截器 采用 责任链 模式
* 在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。
* 责任链每一个节点,都可以继续调用下一个节点,也可以阻止流程继续执行

在struts2 中可以定义很多个拦截器,将多个拦截器按照特定顺序 组成拦截器栈 (顺序调用 栈中的每一个拦截器 )

1、 struts2 所有拦截器 都必须实现 Interceptor 接口
2、 AbstractInterceptor 类实现了 Interceptor 接口. 并为 init, destroy 提供了一个空白的实现

所有实际开发中,自定义拦截器 只需要 继承 AbstractInterceptor类, 提供 intercept 方法实现

3、 常用struts2 拦截器

<interceptor-ref name="modelDriven"/> 模型驱动    <interceptor-ref name="fileUpload"/> 文件上传    <interceptor-ref name="params"> 参数解析封装     <interceptor-ref name="conversionError"/> 类型转换错误    <interceptor-ref name="validation"> 请求参数校验    <interceptor-ref name="workflow"> 拦截跳转 input 视图

自定义拦截器案例
案例 : 登陆,对其它Action访问 通过自定义拦截器 进行权限控制
导入jar包 (struts2 jar、c3p0、 dbutils、 mysql驱动)
web.xml
struts.xml
JDBCUtils 工具类

第一步 : 编写index.jsp 提供 图书增删改查 四个功能
编写BookAction ,提供四个业务方法

第二步: 完成登陆功能

第三步 :必须要登陆 才能进行图书管理
使用Filter 进行权限控制 —- 过滤所有web请求 (所有web资源访问)
使用拦截器 进行权限控制 —- 主要拦截对Action访问 (不能拦截JSP)

定义拦截器 继承AbstractInterceptor

配置拦截器
方式一

<!-- 注册拦截器 --><interceptors>            <interceptor name="privilege" class="cn.itcast.interceptor.PrivilegeInterceptor"></interceptor>        </interceptors>        <action name="book_*" class="cn.itcast.action.BookAction" method="{1}" >            <!-- 使用拦截器 -->            <!-- 当使用自定义拦截器 后,默认拦截器 就会失效  -->    <interceptor-ref name="defaultStack"></interceptor-ref>    nterceptor-ref name="privilege"></interceptor-ref>        </action>
方式二    <!-- 注册拦截器 -->
<interceptors>            <interceptor name="privilege" class="cn.itcast.interceptor.PrivilegeInterceptor"></interceptor>            <!-- 自定义拦截器栈 -->            <interceptor-stack name="privilegeStack">                <interceptor-ref name="defaultStack"></interceptor-ref>                <interceptor-ref name="privilege"></interceptor-ref>            </interceptor-stack>        </interceptors>        <!-- 设置当前包 所有Action 都使用 自定义拦截器栈 -->        <default-interceptor-ref name="privilegeStack"></default-interceptor-ref>

Struts2文件上传下载
Struts2文件上传
提供 FileUpload 拦截器,用于解析 multipart/form-data 编码格式请求,解析上传文件的内容
fileUpload拦截器 默认在 defaultStack 栈中, 默认会执行的

在Action需要对上传文件内容进行接收
页面:

<input type="file" name="upload" />    Action :        public class UploadAction extends ActionSupport {            // 接收上传内容            // <input type="file" name="upload" />            private File upload; // 这里变量名 和 页面表单元素 name 属性一致            private String uploadContentType;            private String uploadFileName;        } 
    * 格式 : 上传表单项name属性 + ContentType 、 上传表单项name属性 + FileName    * 为三个对象 提供 setter 方法

通过FileUtils 提供 copyFile 进行文件复制,将上传文件 保存到服务器端
Struts2文件上传问题解决
配置 input 视图 ,作为上传出错后 跳转页面
在文件上传时,如果发生错误 ,fileUpload拦截器 会设置错误信息,workflow拦截器 跳转到 input 视图

struts.multipart.parser=jakarta 定义文件上传,采用 commons-fileupload 技术
* 同时支持 cos 、pell 上传技术 (如果使用其它上传技术,单独下载jar包 )

通过 struts.multipart.maxSize 常量设置文件上传总大小限制
* struts.multipart.maxSize=2097152 默认上传文件总大小 2MB
* 超过文件总大小,跳转input 视图, 通过 回显错误信息
在struts.xml 设置上传总大小

设置上传文件总大小,对所有上传form有效,只想对当前form进行设置,可以设置fileUpload拦截器属性
FileUpload 拦截器有 3 个属性可以设置.
* maximumSize: 上传文件的最大长度(以字节为单位), 默认值为 2 MB
* allowedTypes: 允许上传文件的类型, 各类型之间以逗号分隔
* allowedExtensions: 允许上传文件扩展名, 各扩展名之间以逗号分隔
如果针对fileUpload 进行参数设置,当出错时,在页面通过 回显错误信息

struts-messages.properties 文件里预定义 上传错误信息,通过覆盖对应key 显示中文信息

struts.messages.error.uploading=Error uploading: {0}    struts.messages.error.file.too.large=The file is to large to be uploaded: {0} "{1}" "{2}" {3}    struts.messages.error.content.type.not.allowed=Content-Type not allowed: {0} "{1}" "{2}" {3}    struts.messages.error.file.extension.not.allowed=File extension not allowed: {0} "{1}" "{2}" {3}

修改为

struts.messages.error.uploading=上传错误: {0}    struts.messages.error.file.too.large=上传文件太大: {0} "{1}" "{2}" {3}    struts.messages.error.content.type.not.allowed=上传文件的类型不允许: {0} "{1}" "{2}" {3}    struts.messages.error.file.extension.not.allowed=上传文件的后缀名不允许: {0} "{1}" "{2}" {3}

多文件上传
第一步:在WEB-INF/lib下加入commons-fileupload-1.2.1.jar、commons-io-1.3.2.jar。这两个文件可以从http://commons.apache.org/下载。
第二步:把form表的enctype设置为:“multipart/form-data“,如下:

<form enctype="multipart/form-data" action="${pageContext.request.contextPath}/xxx.action" method="post">  <input  type="file" name="uploadImages">  <input  type="file" name="uploadImages"></form>

第三步:在Action类中添加以下属性,属性红色部分对应于表单中文件字段的名称:

public class uploadAction{  private File[] uploadImages;//得到上传的文件  private String[] uploadImagesContentType;//得到文件的类型  private String[] uploadImagesFileName;//得到文件的名称  //这里略省了属性的getter/setter方法  public String saveFiles() throws Exception{        ServletContext sc = ServletActionContext.getServletContext();        String realpath = sc.getRealPath("/uploadfile");        try {            if(uploadImages!=null&&uploadImages.length>0){                 for(int i=0;i<uploadImages.length;i++){                         File destFile = new File(realpath,uploadImageFileNames[i]);                         FileUtils.copyFile(uploadImages[i], destFile);                  }             }         } catch (IOException e) {              e.printStackTrace();}return "success";}}

Struts2文件下载
1) struts2 完成文件下载,通过 结果集类型 (Result Type) stream 来完成的
struts-default.xml 定义
2) 使用Stream结果集 完成文件下载
文件下载原理: 服务器读取下载文件内容,通过Response响应流写回, 设置 ContentType、 ContentDisposition 头信息

public class StreamResult extends StrutsResultSupport {    protected String contentType = "text/plain"; // contentType头信息  (下载文件对应 MIME协议规定类型 )        * html --- text/html . txt--- text/plain     protected String contentDisposition = "inline"; // ContentDisposition头信息 (下载文件打开方式 inline浏览器内部打开, attachment 以附件形式打开)    protected String inputName = "inputStream";  // 需要Action中 提供 getInputStream 方法 返回 InputStream 提供下载文件 内容 }   

Action 提供 InputStream 返回值 getInputStream 方法 ——- 指定下载文件流
配置 stream 结果集 参数 contentTypeActiongetContentTypeServletActionContext.getServletContext().getMimeType(filename);streamattachment;filename={filename} —- 在Action 提供 getFilename
* 下载附件名乱码问题 , IE和火狐 解决不同
* public String encodeDownloadFilename(String filename, String agent)
throws IOException {
if (agent.contains("Firefox")) { // 火狐浏览器
filename = "=?UTF-8?B?"
+ new BASE64Encoder().encode(filename.getBytes("utf-8"))
+ "?=";
} else { // IE及其他浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}

OGNL表示式使用 和 值栈

OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一个开源项目。 Struts2框架使用OGNL作为默认的表达式语言。
* xwork 提供 OGNL表达式
* ognl-3.0.5.jar
OGNL 是一种比EL 强大很多倍的语言

OGNL 提供五大类功能
1、支持对象方法调用,如xxx.doSomeSpecial();
2、支持类静态的方法调用和值访问
3、访问OGNL上下文(OGNL context)和ActionContext; (重点 操作ValueStack值栈 )
4、支持赋值操作和表达式串联
5、操作集合对象。

1、 使用OGNL访问 对象方法 和 静态方法
* OGNL 在jsp 结合 struts2 标签库 使用 , 执行 ognl表达式
调用 实例方法 : 对象.方法() —-
调用 静态方法 : @[类全名(包括包路径)]@[方法名] —
* 使用 静态方法调用 必须 设置 struts.ognl.allowStaticMethodAccess=true

2、 访问OGNL上下文(OGNL context)和ActionContext
OGNL上下文(OGNL context) 对象 —– 值栈 ValueStack

问题一 : 什么是值栈 ValueStack ?
ValueStack 是 struts2 提供一个接口,实现类 OgnlValueStack —- 值栈对象 (OGNL是从值栈中获取数据的 )
每个Action实例都有一个ValueStack对象 (一个请求 对应 一个ValueStack对象 )
在其中保存当前Action 对象和其他相关对象 (值栈中 是有Action 引用的 )
Struts 框架把 ValueStack 对象保存在名为 “struts.valueStack” 的请求属性中,request中 (值栈对象 是 request一个属性)

问题二 : 值栈的内部结构 ?
值栈由两部分组成
ObjectStack: Struts 把动作和相关对象压入 ObjectStack 中–List
ContextMap: Struts 把各种各样的映射关系(一些 Map 类型的对象) 压入 ContextMap 中
Struts 会把下面这些映射压入 ContextMap 中
parameters: 该 Map 中包含当前请求的请求参数
request: 该 Map 中包含当前 request 对象中的所有属性
session: 该 Map 中包含当前 session 对象中的所有属性
application:该 Map 中包含当前 application 对象中的所有属性
attr: 该 Map 按如下顺序来检索某个属性: request, session, application

ValueStack中 存在root属性 (CompoundRoot) 、 context 属性 (OgnlContext )
* CompoundRoot 就是ArrayList
* OgnlContext 就是 Map
context 对应Map 引入 root对象
* context中还存在 request、 session、application、 attr、 parameters 对象引用
* OGNL表达式,访问root中数据时 不需要 #, 访问 request、 session、application、 attr、 parameters 对象数据 必须写 #
* 操作值栈 默认指 操作 root 元素

问题三 : 值栈对象的创建 ,ValueStack 和 ActionContext 是什么关系 ?
值栈对象 是请求时 创建的
doFilter中 prepare.createActionContext(request, response);
* 创建ActionContext 对象过程中,创建 值栈对象ValueStack
* ActionContext对象 对 ValueStack对象 有引用的 (在程序中 通过 ActionContext 获得 值栈对象 )
Dispatcher类 serviceAction 方法中 将值栈对象保存到 request范围
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());

问题四 : 如何获得值栈对象
获得值栈对象 有两种方法

ValueStack valueStack = (ValueStack) ServletActionContext.getRequest().getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);    ValueStack valueStack2 = ActionContext.getContext().getValueStack();

问题五: 向值栈保存数据 (主要针对 root)
两种方式

// 将数据保存root的索引0位置,放置到第一个元素 ArrayList add(0,element);        valueStack.push("itcast");        // 在值栈创建参数map, 将数据保存到map中        valueStack.set("company", "传智播客");    在jsp中 通过 <s:debug /> 查看值栈的内容 

问题六: 在JSP中获取值栈的数据
访问root中数据 不需要#
访问 其它对象数据 加 #

通过下标获取root中对象
//取值栈顶对象
直接在root中查找对象属性 (自上而下自动查找)
valueStack:

在OgnlContext中获取数据

request:<s:property value="#request.username"/>session:<s:property value="#session.username"/>application:<s:property value="#application.username"/>attr:<s:property value="#attr.username"/>parameters:<s:property value="#parameters.cid[0]"/>
原创粉丝点击