今天开始第五章啦,本章主要内容:Struts 2拦截器、Struts 2文件操作、Struts 2国际化。
第一部分 Struts 2拦截器
5.1.1 拦 截 器 概 述
Struts 2框架绝大部分功能在其内部都是通过拦截器完成的,拦截器是Struts 2的核心所在。Struts 2框架内建了大量的拦截器,这些拦截器可以在struts-default.xml(位于Struts 2完整版srccoresrcmain esources目录下)中查看。
Struts 2框架给出了这么多的拦截器,下面简要介绍它们的作用:
5.1.2 拦 截 器 配 置
拦截器的配置是在struts.xml中完成的,定义一个拦截器使用<interceptor…/>标签,其格式如下:
这种情况的应用非常广。有的时候,如果需要在配置拦截器时就为其传入拦截器参数,只要在<interceptor..>与</interceptor>之间配置<param…/>标签即可。其格式如下:
在struts.xml中可以配置多个拦截器,它们被包在<interceptors></interceptors>之间,如下面的配置:
如果要应用这些拦截器,就需要在<action>配置中引用它们,一个<action>需要应用多个拦截器,这样就不免要有多条引用语句(引用拦截器用标签<interceptorref.../>),所以Struts 2给出了拦截器栈的使用,一个拦截器栈中可以包含多个拦截器,配置拦截器栈的格式为:
其实,在Struts 2框架中也配置有很多内置拦截器栈,在Struts 2的struts-default.xml中可以发现有如下拦截器栈的配置。
在struts-default.xml文件的最后还有这样一句代码:
该句是用来配置默认拦截器栈的,Struts 2框架自动配置了默认拦截器栈,这样每次当用户请求经过Struts 2框架处理时都会先由“defaultStack”这个默认拦截器栈来处理。
拦截器或拦截器栈配置完成后就可以在<action>中对其引用了,一个action引用拦截器或拦截器栈的格式如下:
在为Action配置拦截器的时候,要先显示的配置默认的拦截器栈,因为在Action中单独配置了拦截器了的话,全局配置的默认拦截器栈“defaultStack”会失效,这是因为局部优先级大于全局优先级。
5.1.3 自定义拦截器并做一个小项目
Struts 2框架还提供了AbstractInterceptor类,该类实现了Interceptor接口,并提供了init()方法和destroy()方法的空实现。在一般的拦截器实现中都会继承该类,因为一般实现的拦截器是不需要打开资源的,故无须实现这两个方法,继承该类会更简洁。该类的代码实现为:
1.创建Struts 2项目
建立项目,取项目名为“InterceptorTest”。加载Struts 2包及修改web.xml文件,配置Struts 2,操作同【实例2.1】的第1步、第2步,不再赘述。
2.自定义拦截器类
创建自定义拦截器类“MyInterceptor.java”,编写代码如下:
package org.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
public class MyInterceptor extends AbstractInterceptor{
public String intercept(ActionInvocation arg0) throws Exception {
System.out.println("我在Action前执行---->");
String result=arg0.invoke();
System.out.println("我在Action后执行---->");
return result;
}
}
3.编写测试用Action
创建Action类“TestAction.java”,编写代码如下:
package org.action;
import com.opensymphony.xwork2.ActionSupport;
public class TestAction extends ActionSupport{
public String execute() throws Exception {
System.out.println("我在Action中执行---->");
return NONE; //不做任何跳转
}
}
4.配置拦截器
在struts.xml中配置Action及拦截器,代码如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="default" extends="struts-default">
<interceptors>
<interceptor name="myInterceptor" class="org.interceptor.MyInterceptor"/>
</interceptors>
<action name="test" class="org.action.TestAction">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="myInterceptor"></interceptor-ref>
</action>
</package>
</struts>
5.运行测试
完这些简单的工作后,部署项目并启动服务器,在浏览器中输入“http://localhost:8080/InterceptorTest/test.action”请求,再查看控制台,出现如图所示的界面:
5.1.4 拦截器应用实例2——阻止表单重复提交
1.创建Struts 2项目
建立项目,取项目名为“InterceptorTest”。加载Struts 2包及修改web.xml文件,配置Struts 2,操作同【实例2.1】的第1步、第2步,不再赘述。
2.创建登录页
修改index.jsp作为登录页面:
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<html>
<head>
<title>登录界面</title>
</head>
<body>
<s:form action="login" method="post">
<!-- 每次提交一个token值,Struts2框架会检测是否是同一次表单提交-->
<s:token></s:token>
<s:textfield name="username" label="用户名"></s:textfield>
<s:password name="password" label="密码"></s:password>
<s:submit value="提交"></s:submit>
</s:form>
</body>
</html>
3.编写Action
编写Action类LoginAction.java,代码如下:
4.配置拦截器
5.编写JSP
成功返回界面welcome.jsp,代码如下:
5.编写JSP
重复提交的提示错误界面wrong.jsp,代码如下:
6.运行测试
部署运行该项目,输入用户名和密码进入成功界面,如图所示:
此时,刷新页面,或单击浏览器的返回再次提交,就会被拦截器拦截,跳转到如图所示的错误界面。
第二部分 Struts 2文件操作
5.2.1 文件上传实例
1.创建Struts 2项目
用Struts 2的Common-FileUpload框架上传多个文件。
建立项目,取项目名为“StrutsUpload”。加载Struts 2包及修改web.xml文件,配置Struts 2,操作同【实例2.1】的第1、2步,不再赘述。
2.修改index.jsp
在创建项目的时候,勾选自动生成index.jsp文件,读者可以应用该文件,将其中内容替换为自己编写的代码,注意:form的enctype一定要改为:“multipart/form-data”,以二进制流的方式来处理表单数据,如下:
3.编写Action类
在src下建立包action,在该包下建立自定义Action类UploadAction。该类的实现代码为:
package action;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
public class UploadAction extends ActionSupport{
private List<File> upload; //上传的文件内容,由于是多个,用List集合
private List<String> uploadFileName; //文件名
public String execute() throws Exception {
if(upload!=null){
for (int i = 0; i < upload.size(); i++) { //遍历,得到每个文件对它们进行读写操作
InputStream is=new FileInputStream(upload.get(i));
OutputStream os=
new FileOutputStream("d:upload"+getUploadFileName().get(i));
byte buffer[]=new byte[1024];
int count=0;
while((count=is.read(buffer))>0){
os.write(buffer,0,count);
}
os.close();
is.close();
}
}
return SUCCESS;
}
public List<File> getUpload() {
return upload;
}
public void setUpload(List<File> upload) {
this.upload = upload;
}
public List<String> getUploadFileName() {
return uploadFileName;
}
public void setUploadFileName(List<String> uploadFileName) {
this.uploadFileName = uploadFileName;
}
}
在struts.xml中配置该Action类,代码如下:
4.建立success.jsp
上传成功后,跳转到成功页面。代码如下:
5.部署运行
如图所示,然后单击【上传】按钮,成功后跳转到成功页面,这时可以打开D盘的upload文件夹查看上传的文件。
5.2.2 文件下载
如果是一个以西欧字符(英文名字)命名的文件,可以直接用一个超链接指向要下载的文件即可:
<a href="/image/pic.jpg">点击下载</a>
如果包含非西欧字符(如中文日文)等命名的文件,就不能用上述方法了,下面这个实例有解决方案:在页面实现一个超链接,指向一个Action请求,在Action类中进行处理,在struts.xml对Action进行配置的result中用param配置参数,完成文件的下载,下面介绍这些参数:
1.创建Struts 2项目
【实例5.5】用Struts 2框架的功能完成文件下载。
建立项目,取项目名为“StrutsDownload”。加载Struts 2包及修改web.xml文件,配置Struts 2,操作同【实例2.1】的第1、2步,不再赘述。在项目WebRoot下建立一个image文件夹,其中放入一个文件“用例.rar”,用于本例下载演示之用。
2.修改index.jsp
3.编写Action类
package org.action;
import java.io.InputStream;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class DownloadAction extends ActionSupport{
private String downloadFile; //需要下载的文件路径
//生成set方法,该值由配置文件传递过来
public void setDownloadFile(String downloadFile) {
this.downloadFile = downloadFile;
}
//根据上面给出的文件路径,生成它的输入流
public InputStream getTargetFile(){
return ServletActionContext.getServletContext().getResourceAsStream(downloadFile);
}
public String execute() throws Exception {
return SUCCESS;
}
}
4.配置struts.xml文件
文件下载最重要的工作就是在配置文件中进行配置,下面看其struts.xml文件:
<struts>
<package name="default" extends="struts-default">
<action name="download" class="org.action.DownloadAction">
<!-- 传递参数,指定要下载的文件的路径 -->
<param name="downloadFile">/image/用例.rar</param>
<result name="success" type="stream">
<!-- 输入流名称,对应Action类中的getTargetFile()方法 -->
<param name="inputName">targetFile</param>
<!-- 设置下载文件的文件名 -->
<param name="contentDisposition">
filename="example.rar"
</param>
<!-- 指定下载文件时缓冲区的大小 -->
<param name="bufferSize">4096</param>
</result>
</action>
</package>
</struts>
5.部署运行
部署项目,启动Tomcat,在浏览器中输入“http://localhost:8080/StrutsDownload/”,出现如图所示的界面,单击其上“下载”链接,就会弹出【新建下载任务】对话框,单击【浏览】按钮选择存盘路径,最后单击【下载】按钮开始下载进程。
第三部分 Struts 2国际化
5.3.1 国际化原理
国际化:是指在不修改程序代码的情况下,能根据不同的语言及地区显示不同的界面,就是语言转换。
实现原理:当用户选择了不同的语言后,程序会加载相对应的已经准备好的国际化资源文件来对程序进行赋值,来改变Web界面,其关键是提供不同国家语言的资源文件。简而言之:就是前端界面文字显示使用变量,根据用户选择的语言对变量进行赋值。
1.命名规则
Struts 2的国际化资源文件都是“*.properties”文件,而且该文件需要放在项目的classses文件夹下。就命名规则而言,国际化资源文件必须命名为“基本名称_语言代码_国家代码.properties”,例如,中文的国际化资源文件应命名为:
而英文国际化资源文件则命名为:
2.内容格式
资源文件内容的格式为“key=value”,其中key可以根据程序员自己的喜好来命名,但一般都会命名为容易理解或记忆的名称,而value值则是该key对应的值,不同国家语言对应的该值是不同的。例如,英文对应:
中文则对应:
看到这里,读者可能有点迷惑,按常理来说,中文对应的应该是:
因为中文是非西欧字符,要对其进行转码。目前MyEclipse可以自动进行中文转码。
5.3.2 资源文件的访问方式
1.使用<s:text>标签
2.使用标签属性key
3.使用getText()方法
getText()应用范围比较广泛,可以在页面使用,也可以在Action类或校验配置文件中使用。对于上面两个方法的应用都可以用该方法来代替:
3.使用getText()方法
5.3.3 国际化应用实例
【实例5.6】利用Struts 2的il8n拦截器以及国际化功能,开发左图所示的界面,刚开始为中文页面,如果单击下面的“英文”链接,就会出现如右图所示的英文页面。单击“chinese”链接,又回到左图的中文页面。
1.创建Struts 2项目
建立项目,取项目名为“SelectLanguageLogin”。加载Struts 2包及修改web.xml文件,配置Struts 2,操作同【实例2.1】的第1步、第2步,不再赘述。
2.创建资源文件
(1)创建英文资源文件。
建在src目录下,文件名为message_en_US.properties,代码如下:
language = please select language
chinese = chinese
english = english
loginView = Login View
XH = XH
KL = KL
login = login
(2)创建中文资源文件。
在src下创建文件message_zh_CN.properties,在其编辑区Properties选项页,单击【Add】按钮,添加并编辑各属性对应的中文名称,如图所示。
language=u8BF7u9009u62E9u8BEDu8A00
chinese=u4E2Du6587
english=u82F1u6587
loginView=u767Bu5F55u754Cu9762
XH=u5B66u53F7
KL=u53E3u4EE4
login=u767Bu5F55
4.编写Action
本例的目的是体现国际化的应用而非登录验证功能本身,故在Action中不进行任何处理,直接返回“SUCCESS”,Action类的代码如下:
5.自定义拦截器
采取配置拦截器的方法,在进入“login.action”之前先对其进行语言的处理,拦截器代码实现为:
package org.interceptor;
import java.util.Locale;
import java.util.Map;
import com.opensymphony.xwork2.*;
import com.opensymphony.xwork2.interceptor.*;
public class CheckInterceptor extends AbstractInterceptor {
public String intercept(ActionInvocation arg0) throws Exception {
// 获得Action上下文
ActionContext ctx = arg0.getInvocationContext();
// 获得Session
Map session = ctx.getSession();
//检查是否设置了Locale,如果未设定,则默认为简体中文
Locale currentLocale=(Locale)session.get("WW_TRANS_I18N_LOCALE");
if(currentLocale==null){
// 设置Locale实例
currentLocale = new Locale("zh", "CN");
session.put("WW_TRANS_I18N_LOCALE", currentLocale);
}
return arg0.invoke();
}
}
在struts.xml文件中配置拦截器,配置代码如下:
最后演示效果如开头所示。
本章实例代码GitEE地址:
https://gitee.com/jahero/bookManage.git
下章我们就开始一个Struts框架的实例综合应用啦,加油,共勉↖(^ω^)↗。