package cn.itcast.action;
import com.opensymphony.xwork2.ActionSupport;
public class I18nDemo1Action extends ActionSupport {
@Override
public String execute() throws Exception {
// 得到properties文件中的信息
System.out.println(this.getText("msg"));
// 动态文本
System.out.println(this.getText("msg", new String[] { "tom" }));
return NONE;
}
}
I18nDemo2Action(测试validation.xml中获取资源文件内容)
package cn.itcast.action;
import com.opensymphony.xwork2.ActionSupport;
public class I18nDemo2Action extends ActionSupport {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String execute() throws Exception {
return NONE;
}
}
I18nDemo1Action.properties (action范围的资源文件 针对I18nDemo1Action)msg=hello world {0}
I18nDemo2Action-validation.xml(I18nDemo2Action的配置校验文件)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="name">
<field-validator type="requiredstring">
<message key="nameerror"></message>
</field-validator>
</field>
</validators>
package_en_US.properties(指定美国英语格式 当前包内范围内使用)
nameerror=name required
package_zh_CN.properties (指定中国英文格式 当前包范围内使用)
nameerror=name required
name=tom
message_en_US.properties
name=tom
message_zh_CN.properties
<?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>
<!-- 声明一个全局的国际化文件 -->
<constant name="struts.custom.i18n.resources" value="cn.itcast.i18n.resource.message"></constant>
<package name="default" namespace="/" extends="struts-default">
<action name="i18ndemo1" class="cn.itcast.action.I18nDemo1Action"></action>
<action name="i18ndemo2" class="cn.itcast.action.I18nDemo2Action">
<result name="input">/input.jsp</result>
</action>
</package>
</struts>
i18n.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
</head>
<body>
<s:i18n name="cn.itcast.action.package">
<s:text name="nameerror"></s:text>
</s:i18n>
<br>
<s:i18n name="cn.itcast.action.I18nDemo1Action">
<s:text name="msg">
<s:param>张三</s:param>
</s:text>
</s:i18n>
<br>
<s:text name="name" />
</body>
</html>
input.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
</head>
<body>
<s:fielderror />
</body>
</html>
Struts2的工作机制:
public interface Interceptor extends Serializable {
void destroy();
void init();
String intercept(ActionInvocation invocation) throws Exception;
}
init:该方法将在拦截器被创建后立即被调用,它在拦截器的生命周期内只被调用一次,可以在该方法中对相关资源进行必要的初始化。
public class PermissionInterceptor implements Interceptor {
private static final long serialVersionUID = -5178310397732210602L;
public void destroy() {
}
public void init() {
}
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("进入拦截器");
if(session里存在用户){
String result = invocation.invoke();
}else{
return “logon”;
}
//System.out.println("返回值:"+ result);
//return result;
}
}
<package name="itcast" namespace="/test" extends="struts-default">
<interceptors>
<interceptor name=“permission" class="cn.itcast.aop.PermissionInterceptor" />
<interceptor-stack name="permissionStack">
<interceptor-ref name="defaultStack" />
<interceptor-ref name=" permission " />
</interceptor-stack>
</interceptors>
<action name="helloworld_*" class="cn.itcast.action.HelloWorldAction" method="{1}">
<result name="success">/WEB-INF/page/hello.jsp</result>
<interceptor-ref name="permissionStack"/>
</action>
</package>
package cn.itcast.action;
import com.opensymphony.xwork2.ActionSupport;
public class Demo1Action extends ActionSupport {
@Override
public String execute() throws Exception {
System.out.println("Demo1Action ......");
return SUCCESS;
}
}
package cn.itcast.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class MyInterceptor implements Interceptor {
@Override
public void destroy() {
}
@Override
public void init() {
System.out.println("my interceptor init");
}
@Override
public String intercept(ActionInvocation action) throws Exception {
System.out.println("my interceptor 拦截......");
// 放行
return action.invoke();
}
}
package cn.itcast.interceptor;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class MyInterceptor2 implements Interceptor {
@Override
public void destroy() {
}
@Override
public void init() {
System.out.println("my interceptor init");
}
@Override
public String intercept(ActionInvocation action) throws Exception {
System.out.println("my interceptor2 拦截......");
// 放行
// return action.invoke();
return Action.LOGIN;
}
}
在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>
<package name="default" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="interceptor1" class="cn.itcast.interceptor.MyInterceptor" />
<interceptor name="interceptor2" class="cn.itcast.interceptor.MyInterceptor2" />
<interceptor-stack name="customStack">
<interceptor-ref name="interceptor2" />
<interceptor-ref name="defaultStack" />
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="interceptor1"/>
<action name="demo1" class="cn.itcast.action.Demo1Action">
<result>/success.jsp</result>
<result name="login">/input.jsp</result>
</action>
<action name="demo2" class="cn.itcast.action.Demo1Action">
<result>/success.jsp</result>
<result name="login">/input.jsp</result>
<interceptor-ref name="customStack" />
</action>
</package>
</struts>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
</head>
<body>
<h1>被拦截</h1>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
</head>
<body>
<h1>成功访问</h1>
</body>
</html>
部署到服务器 并测试结果如下:
package cn.itcast.domain;
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package cn.itcast.action;
import org.apache.struts2.ServletActionContext;
import cn.itcast.domain.User;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
public class LoginAction extends ActionSupport implements ModelDriven<User> {
private User user = new User();
@Override
public User getModel() {
return user;
}
@Override
public String execute() throws Exception {
if ("tom".equals(user.getUsername())
&& "123".equals(user.getPassword())) {
ServletActionContext.getRequest().getSession()
.setAttribute("user", user);
return SUCCESS;
} else {
this.addActionError("用户名或密码错误");
return INPUT;
}
}
}
新建BookAction
package cn.itcast.action;
import com.opensymphony.xwork2.ActionSupport;
public class BookAction extends ActionSupport {
public String add() throws Exception {
System.out.println("book action add");
return null;
}
public String update() throws Exception {
System.out.println("book action update");
return null;
}
public String delete() throws Exception {
System.out.println("book action delete");
return null;
}
public String search() throws Exception {
System.out.println("book action search");
return null;
}
}
新建自定义拦截器类MethodFilterInterceptor
package cn.itcast.interceptor;
import org.apache.struts2.ServletActionContext;
import cn.itcast.action.BookAction;
import cn.itcast.domain.User;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
public class BookInterceptor extends MethodFilterInterceptor {
@Override
protected String doIntercept(ActionInvocation invocation) throws Exception {
// 1.得到session中的user
User user = (User) ServletActionContext.getRequest().getSession()
.getAttribute("user");
if (user == null) {
Object obj = invocation.getAction(); // 得到当前拦截器对象
if (obj instanceof BookAction) {
BookAction action = (BookAction) obj;
action.addActionError("权限不足,请先登录"); // 存储错误信息
return Action.LOGIN;
} else {
return invocation.invoke();
}
}
return invocation.invoke();
}
}
配置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>
<package name="default" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="bookInterceptor" class="cn.itcast.interceptor.BookInterceptor">
<param name="includeMethods">add,update,delete</param>
</interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="bookInterceptor" />
<interceptor-ref name="defaultStack" />
</interceptor-stack>
</interceptors>
<action name="login" class="cn.itcast.action.LoginAction">
<result name="input">/login.jsp</result>
<result>/book.jsp</result>
</action>
<action name="book_*" class="cn.itcast.action.BookAction"
method="{1}">
<result name="login">/login.jsp</result>
<interceptor-ref name="myStack" />
</action>
</package>
</struts>
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
</head>
<body>
<s:fielderror />
<s:actionerror />
<form action="${pageContext.request.contextPath}/login" method="POST">
username:<input type="text" name="username"><br>
password:<input type="password" name="password"><br> <input
type="submit" value="login">
</form>
</body>
</html>
book.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
</head>
<body>
<a href="${pageContext.request.contextPath}/book_add">book add</a><br>
<a href="${pageContext.request.contextPath}/book_update">book update</a><br>
<a href="${pageContext.request.contextPath}/book_delete">book delete</a><br>
<a href="${pageContext.request.contextPath}/book_search">book search</a><br>
</body>
</html>
运行结果如下:
if (interceptors.hasNext()) {//判断是否有下一个拦截器. final InterceptorMapping interceptor = interceptors.next(); //得到一个拦截器 String interceptorMsg = "interceptor: " + interceptor.getName(); UtilTimerStack.push(interceptorMsg); try { resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this); //调用得到的拦截器的拦截方法.将本类对象传递到了拦截器中。 } finally { UtilTimerStack.pop(interceptorMsg); } }通过源代码分析,发现在DefaultActionInvocation中就是通过递归完成所有的拦截调用操作.如下图所示
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}{0}:<input type="file" name="uploadImage"> 中name属性的值
protected boolean acceptFile(Object action, File file, String filename, String contentType, String inputName, ValidationAware validation) { boolean fileIsAcceptable = false; // If it's null the upload failed if (file == null) { String errMsg = getTextMessage(action, "struts.messages.error.uploading", new String[]{inputName}); if (validation != null) { validation.addFieldError(inputName, errMsg); } if (LOG.isWarnEnabled()) { LOG.warn(errMsg); } } else if (maximumSize != null && maximumSize < file.length()) { String errMsg = getTextMessage(action, "struts.messages.error.file.too.large", new String[]{inputName, filename, file.getName(), "" + file.length()}); if (validation != null) { validation.addFieldError(inputName, errMsg); } if (LOG.isWarnEnabled()) { LOG.warn(errMsg); } } else if ((!allowedTypesSet.isEmpty()) && (!containsItem(allowedTypesSet, contentType))) { String errMsg = getTextMessage(action, "struts.messages.error.content.type.not.allowed", new String[]{inputName, filename, file.getName(), contentType}); if (validation != null) { validation.addFieldError(inputName, errMsg); } if (LOG.isWarnEnabled()) { LOG.warn(errMsg); } } else if ((!allowedExtensionsSet.isEmpty()) && (!hasAllowedExtension(allowedExtensionsSet, filename))) { String errMsg = getTextMessage(action, "struts.messages.error.file.extension.not.allowed", new String[]{inputName, filename, file.getName(), contentType}); if (validation != null) { validation.addFieldError(inputName, errMsg); } if (LOG.isWarnEnabled()) { LOG.warn(errMsg); } } else { fileIsAcceptable = true; } return fileIsAcceptable; }但是发现默认的错误信息提示是英文的,要想展示中文的,实现国际化 步骤如下:
<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"; } }
package cn.itcast.action; import java.io.File; import java.util.List; import org.apache.commons.io.FileUtils; import com.opensymphony.xwork2.ActionSupport; public class UploadAction extends ActionSupport { // 在action类中需要声明三个属性 private List<File> upload; private List<String> uploadContentType; private List<String> uploadFileName; public List<File> getUpload() { return upload; } public void setUpload(List<File> upload) { this.upload = upload; } public List<String> getUploadContentType() { return uploadContentType; } public void setUploadContentType(List<String> uploadContentType) { this.uploadContentType = uploadContentType; } public List<String> getUploadFileName() { return uploadFileName; } public void setUploadFileName(List<String> uploadFileName) { this.uploadFileName = uploadFileName; } @Override public String execute() throws Exception { for (int i = 0; i < upload.size(); i++) { System.out.println("上传文件的类型:" + uploadContentType.get(i)); System.out.println("上传文件的名称:" + uploadFileName.get(i)); FileUtils.copyFile(upload.get(i), new File("d:/upload", uploadFileName.get(i))); } return null; } }DownloadAction
package cn.itcast.action; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import org.apache.struts2.ServletActionContext; import cn.itcast.utils.DownloadUtils; import com.opensymphony.xwork2.ActionSupport; public class DownloadAction extends ActionSupport { private String filename; // 要下载文件的名称 public String getFilename() { return filename; } public void setFilename(String filename) { this.filename = filename; } // 设置下载文件mimeType类型 public String getContentType() { String mimeType = ServletActionContext.getServletContext().getMimeType( filename); return mimeType; } // 获取下载文件名称 public String getDownloadFileName() throws UnsupportedEncodingException { return DownloadUtils.getDownloadFileName(ServletActionContext .getRequest().getHeader("user-agent"), filename); } public InputStream getInputStream() throws UnsupportedEncodingException, FileNotFoundException { filename = new String(filename.getBytes("iso8859-1"), "utf-8"); // 解决中文名乱码 FileInputStream fis = new FileInputStream("d:/upload/" + filename); return fis; } @Override public String execute() throws Exception { System.out.println("进行下载......"); return super.execute(); } }配置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> <constant name="struts.custom.i18n.resources" value="message"></constant> <package name="default" namespace="/" extends="struts-default"> <action name="upload" class="cn.itcast.action.UploadAction"> <result name="input">/upload.jsp</result> <interceptor-ref name="defaultStack"> <param name="fileUpload.maximumSize">2097152</param> <param name="fileUpload.allowedExtensions">txt,mp3,docx</param> </interceptor-ref> </action> <action name="download" class="cn.itcast.action.DownloadAction"> <result type="stream"> <param name="contentType">${contentType}</param> <!-- 调用当前action中的getContentType()方法 --> <param name="contentDisposition">attachment;filename=${downloadFileName}</param><!-- 会调用Action中getFileName方法 --> <param name="inputStream">${inputStream}</param> <!-- 调用当前action中的getInputStream()方法 --> </result> </action> </package> </struts>message.properties
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Insert title here</title> </head> <body> <s:fielderror /> <form action="${pageContext.request.contextPath}/upload" method="POST" enctype="multipart/form-data"> <input type="file" name="upload"><br> <input type="file" name="upload"><br> <input type="file" name="upload"><br> <input type="submit" value="上传"> </form> </body> </html>download.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>Insert title here</title> </head> <body> <a href="${pageContext.request.contextPath}/download?filename=a.txt">a.txt</a><br> <a href="${pageContext.request.contextPath}/download?filename=测试下载.docx">测试下载.docx</a> </body> </html>