目录:
在web项目中我们经常需要访问Servlet Api : HttpServletRequest、HttpSession、ServletContext这三个接口。分别对应request,session,contex域对象来共享数据。(给jsp等)
struts2提供给开发者使用域对象来共享数据的方法一共有三种:
- ServletActionContext对象,在struts的action方法中使用域对象
- 会依赖servlet原生api。如果用到了request,session,servletcontext对象中的除了存储数据的方法以外的方法就必须使用这种方法了。如果是单纯使用域对象存储数据,则不推荐使用这种方式。
1 package action; 2 import java.util.ArrayList; 3 import java.util.List; 4 import javax.servlet.ServletContext; 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpSession; 7 import org.apache.struts2.ServletActionContext; 8 import com.opensymphony.xwork2.ActionSupport; 9 10 public class UserAction extends ActionSupport{ 11 public String showList() throws Exception{ 12 //模拟从数据库中得到数据 13 List<String> list = new ArrayList<String>(); 14 list.add("eric"); 15 list.add("rose"); 16 17 //获取request 18 HttpServletRequest request = ServletActionContext.getRequest(); 19 request.setAttribute("request_list", list); 20 21 //获取session 22 HttpSession session = request.getSession(true); 23 session.setAttribute("session_list", list); 24 25 //获取context 26 ServletContext context = ServletActionContext.getServletContext(); 27 context.setAttribute("context_list", list); 28 29 return SUCCESS; 30 31 } 32 }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <package name="default" namespace="/scope" extends="struts-default"> <global-allowed-methods>showList</global-allowed-methods> <action name="user_*" class="action.UserAction" method="{1}"> <result>/listUser.jsp</result> </action> </package> </struts>
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'listUser.jsp' starting page</title> </head> <body> <h3>request</h3> <table border="1"> <c:forEach items="${requestScope.request_list}" var="user"> <tr> <td>${user}</td> </tr> </c:forEach> </table> <h3>session</h3> <table border="1"> <c:forEach items="${sessionScope.session_list}" var="user"> <tr> <td>${user}</td> </tr> </c:forEach> </table> <h3>context</h3> <table border="1"> <c:forEach items="${applicationScope.context_list}" var="user"> <tr> <td>${user}</td> </tr> </c:forEach> </table> </body> </html>
- 会依赖servlet原生api。如果用到了request,session,servletcontext对象中的除了存储数据的方法以外的方法就必须使用这种方法了。如果是单纯使用域对象存储数据,则不推荐使用这种方式。
- ActionContext对象:每次创建action对象时都会创建它的上下文对象,提供了用来操作不同域对象的map集合。
- 脱离了servlet的api,运行这个方法不依赖于tomcat服务器。
- ActionContext对象是由拦截器来构建的, 而拦截器是在UserAction的构造方法之后执行。业务方法是在拦截器值后执行,故此ActionContext要在业务方法内才能正确获取,而不能所有方法使用一个ActionContext。(不推荐使用)
-
package action; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; public class UserAction extends ActionSupport{ public String showList() throws Exception{ //从数据库中得到数据 List<String> list = new ArrayList<String>(); list.add("eric"); list.add("rose"); ActionContext context = ActionContext.getContext(); //操作这个map集合就等同于操作了request域的数据 Map<String, Object> requestMap = context.getContextMap(); requestMap.put("request_list", list); //session Map<String, Object> session = context.getSession(); session.put("session_list", list); //context Map<String, Object> application = context.getApplication(); application.put("context_list", list); return SUCCESS; } }
- 自动调用struts2的接口方法把操作request域的map集合传入。与第二种方法不同,这种方法的map对象可以给整个action使用,一次性获取后可在所有方法内使用。(在action对象方法比较多的时候推荐使用)
-
package action; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.struts2.interceptor.ApplicationAware; import org.apache.struts2.interceptor.RequestAware; import org.apache.struts2.interceptor.SessionAware; import com.opensymphony.xwork2.ActionSupport; public class UserAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware{ private Map<String,Object> requestMap; private Map<String,Object> sessionMap; private Map<String,Object> contextMap; public String showList() throws Exception{ //从数据库中得到数据 List<String> list = new ArrayList<String>(); list.add("eric"); list.add("rose"); requestMap.put("request_list", list); sessionMap.put("session_list", list); contextMap.put("context_list", list); return SUCCESS; } @Override public void setRequest(Map<String, Object> request) { // TODO Auto-generated method stub this.requestMap = request; } @Override public void setApplication(Map<String, Object> context) { // TODO Auto-generated method stub this.contextMap = context; } @Override public void setSession(Map<String, Object> session) { // TODO Auto-generated method stub this.sessionMap = session; } }
- *一般如果有多个action需要注入,则在提取公共基类:BaseAction
-
package action; import java.util.ArrayList; import java.util.List; public class UserAction extends BaseAction{ public String showList() throws Exception{ //从数据库中得到数据 List<String> list = new ArrayList<String>(); list.add("eric"); list.add("rose"); requestMap.put("request_list", list); sessionMap.put("session_list", list); contextMap.put("context_list", list); return SUCCESS; } }
package action; import java.util.Map; import org.apache.struts2.interceptor.ApplicationAware; import org.apache.struts2.interceptor.RequestAware; import org.apache.struts2.interceptor.SessionAware; import com.opensymphony.xwork2.ActionSupport; /** * 基础action类, 把这个基础的action来注入。 * @author claire * */ public class BaseAction extends ActionSupport implements RequestAware,SessionAware,ApplicationAware { protected Map<String,Object> requestMap; protected Map<String,Object> sessionMap; protected Map<String,Object> contextMap; @Override public void setRequest(Map<String, Object> request) { // TODO Auto-generated method stub this.requestMap = request; } @Override public void setApplication(Map<String, Object> context) { // TODO Auto-generated method stub this.contextMap = context; } @Override public void setSession(Map<String, Object> session) { // TODO Auto-generated method stub this.sessionMap = session; } }
-
从表单传值到action的两种方式:
- 在action中直接定义变量,设置setter方法即可,struts2的拦截器可以自动获取。直接把参数赋值给属性。(字段驱动方式)
1 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> 2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 3 <html> 4 <head> 5 <title>My JSP 'register.jsp' starting page</title> 6 </head> 7 8 <body> 9 <form action="${pageContext.request.contextPath}/data/user_register.action" method="post"> 10 用户名: <input type="text" name="name" /> 11 密码:<input type="text" name="pwd" /> 12 性别:<input type="radio" name="gender" value="男">男 13 <input type="radio" name="gender" value="女">女<br> 14 爱好: 15 <input type="checkbox" name="hobit" value="篮球">篮球 16 <input type="checkbox" name="hobit" value="足球">足球 17 <input type="checkbox" name="hobit" value="网球">网球<br> 18 <input type="submit" value="注册"> 19 </form> 20 </body> 21 </html>
1 package action; 2 3 import com.opensymphony.xwork2.ActionSupport; 4 5 public class UserAction extends ActionSupport { 6 7 private String name; 8 private String password; 9 private String gender; 10 private String[] hobit; 11 12 /** 13 * 通过set方法将参数注入到action中 14 * @param name 15 */ 16 public void setName(String name) { 17 this.name = name; 18 } 19 public void setPassword(String password) { 20 this.password = password; 21 } 22 23 public void setGender(String gender) { 24 this.gender = gender; 25 } 26 27 public void setHobit(String[] hobit) { 28 this.hobit = hobit; 29 } 30 31 32 public String register() throws Exception{ 33 //使用表单数据 34 System.out.println("-----------------------------------------"); 35 System.out.println(name+"--"+password+"--"+gender+"--"+hobit); 36 return SUCCESS; 37 38 } 39 40 41 42 43 }
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <package name="data" namespace="/data" extends="struts-default"> <global-allowed-methods>register</global-allowed-methods> <action name="user_*" class="action.UserAction" method="{1}"> <result>/success.jsp</result> </action> </package> </struts>
- 直接把参数赋值给一个javabean对象。(域对象字段驱动方式)
- 将属性和相应的getter/setter从Action中提取出来,单独作为一个实体域对象,之后在action中直接使用这个对象。jsp页面表单与1)不同,标签的name属性应与UserAction中定义的javabean对象对应变量名相同(user.name)。 如:<input type="text" name="user.name" />
package action; public class User { private String name; private String password; private String gender; private String[] hobit; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public String[] getHobit() { return hobit; } public void setHobit(String[] hobit) { this.hobit = hobit; } @Override public String toString() { // TODO Auto-generated method stub return this.name+"--"+this.gender+"--"+this.password+"--"+this.hobit.toString(); } }
package action; import com.opensymphony.xwork2.ActionSupport; public class UserAction extends ActionSupport { //使用javabean对象 private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String register() throws Exception{ //使用表单数据 System.out.println("-----------------------------------------"); System.out.println(user); return SUCCESS; } }
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'register.jsp' starting page</title> </head> <body> <form action="${pageContext.request.contextPath}/data/user_register.action" method="post"> 用户名: <input type="text" name="user.name" /> 密码:<input type="text" name="user.password" /> 性别:<input type="radio" name="user.gender" value="男">男 <input type="radio" name="user.gender" value="女">女<br> 爱好: <input type="checkbox" name="user.hobit" value="篮球">篮球 <input type="checkbox" name="user.hobit" value="足球">足球 <input type="checkbox" name="user.hobit" value="网球">网球<br> <input type="submit" value="注册"> </form> </body> </html>
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <package name="data" namespace="/data" extends="struts-default"> <global-allowed-methods>register</global-allowed-methods> <action name="user_*" class="action.UserAction" method="{1}"> <result>/success.jsp</result> </action> </package> </struts>
* struts2可以将请求参数自动从String类型转换成需要类型。无需自己动手转换
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'register.jsp' starting page</title> </head> <body> <form action="${pageContext.request.contextPath}/data/user_register.action" method="post"> 用户名: <input type="text" name="user.name" /> 年龄:<input type="text" name="user.age"> 成绩:<input type="text" name="user.score"> 出生日期:<input type="text" name="user.birth"> <input type="submit"> </form> </body> </html>
package action; import java.util.Date; public class User { private String name; private int age; private double score; private Date birth; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public double getScore() { return score; } public void setScore(double score) { this.score = score; } public Date getBirth() { return birth; } public void setBirth(Date birth) { this.birth = birth; } @Override public String toString() { // TODO Auto-generated method stub return this.name+"--"+this.age+"--"+this.score+"--"+this.birth; } }
- 模型驱动:Action实现ModelDriven接口,同样把表单数据封装起来,action类必须实例化该对象(User user = new User()),并要重写getModel方法,这个方法返回的即为Action所使用的数据模型对象(user)。
- 当类型自动转换失败时,会自动交给input视图。返回“input"可在action配置时给他配置一个error页面(日期转化错误)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <package name="data" namespace="/data" extends="struts-default"> <global-allowed-methods>register</global-allowed-methods> <action name="user_*" class="action.UserAction" method="{1}"> <result>/success.jsp</result> <result name="input">/error.jsp</result> </action> </package> </struts>
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>错误信息页面</title> </head> <body> <%--打印错误信息 --%> <s:fielderror></s:fielderror> </body> </html>
- 自定义类型转换:
-
- 定义类型转换器,继承这个类:
package action; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import org.apache.struts2.util.StrutsTypeConverter; public class MyDateConvert extends StrutsTypeConverter { SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/MM/dd"); /** * 从页面到服务器 参数一:context,值栈上下文对象 参数二:values, 从页面传过来的参数值 参数三:toClass,要转换的目标参数类型 */ @Override public Object convertFromString(Map context, String[] values, Class toClass) { System.out.println("-----进入转换器---------------"); try { // 判断value是否为空 if (values == null || values.length == 0) return null; // 取出数据进行转换 if (values.length > 1) { Date[] dates = new Date[values.length]; for (int i = 0; i < dates.length; i++) { Date date = sdf1.parse(values[i]); dates[i] = date; } return dates; } else { // 一个值 Date date = sdf1.parse(values[0]); return date; } } catch (Exception e) { e.printStackTrace(); } return null; } @Override public String convertToString(Map context, Object o) { // 从服务器到页面的转换 return null; } }
-
- 绑定自定义转换器:
- 局部绑定:只绑定一个action
- 建立一个“action文件名-conversion.properties”文件,将其与被绑定action放在同一目录下
- 局部绑定:只绑定一个action
- 绑定自定义转换器:
-
-
- 全局绑定:绑定整个项目多个action (常用)
- 建立一个xwork-conversion.properties放在src目录下
- 所有Date类型的数据都走这个转换器
- 全局绑定:绑定整个项目多个action (常用)
-
文件上传:
- 三要素:
-
- 表单有file
- post提交
- enctype="multipart/form-data":multipart/form-data设置以二进制流的方式处理表单数据,这种编码方式会将文件域指定的文件的内容也封装进请求参数中。
- 如果涉及到中文的文件名称,需要在配置文件中加入<constant name="struts.il8n.encoding" value="gbk"/>
- 在Action中接收文件内容
- File attach: attach是file表单中的name属性
- 接收文件类型,固定模式拼接:file名+ContentType
- 接收文件名字,也是固定的拼接:file名+FileName
private String attachFileName;
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <include file="upload_down/struts-upload.xml"></include> </struts>
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <package name="upload" namespace="/upload" extends="struts-default"> <action name="upload" class="upload_down.UploadAction"> <!-- 往FileUploadInterceptor拦截器的属性注入值(调用setter方法) --> <interceptor-ref name="defaultStack"> <!-- 改变当前文件上传拦截器的允许文件类型 --> <param name="fileUpload.allowedTypes">image/jpeg,image/jpg</param> <!-- 允许后缀 --> <!-- 如果两个配置都写了,取交集 --> <param name="fileUpload.allowedExtensions">jpg,jpeg,gif</param> </interceptor-ref> <param name="savePath">D:/ajava/test/</param> <result>/success.jsp</result> <result name="input">/error.jsp</result> </action> <action name="down_*" class="upload_down.DownAction" method="{1}"> <param name="serverPath">D:/ajava/test</param> <result name="list">/listFile.jsp</result> </action> </package> </struts>
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'upload.jsp' starting page</title> </head> <body> <form action="${pageContext.request.contextPath}/upload/upload.action" method="post" enctype="multipart/form-data"> 文件:<input type="file" name="attach"><br> 描述:<input type="text" name="info"><br> <input type="submit" value="上传"> </form> </body> </html>
package upload_down; import java.io.File; import org.apache.commons.io.FileUtils; import com.opensymphony.xwork2.ActionSupport; /** * 文件上传 * @author claire * */ public class UploadAction extends ActionSupport{ //接收上传文件,名字与表单中相同 private File attach; //接收文件类型,固定模式拼接:file名+ContentType private String attachContentType; //接收文件名字,也是固定的拼接:file名+FileName private String attachFileName; //接收描述 private String info; //注入服务器地址 private String savePath; public String getSavePath() { return savePath; } public void setSavePath(String savePath) { this.savePath = savePath; } public File getAttach() { return attach; } public void setAttach(File attach) { this.attach = attach; } public String getAttachContentType() { return attachContentType; } public void setAttachContentType(String attachContentType) { this.attachContentType = attachContentType; } public String getAttachFileName() { return attachFileName; } public void setAttachFileName(String attachFileName) { this.attachFileName = attachFileName; } public String getInfo() { return info; } public void setInfo(String info) { this.info = info; } @Override public String execute() throws Exception { System.out.println(attach); System.out.println(attachFileName); System.out.println(info); System.out.println(savePath+attachFileName); /* * 保存到服务器硬盘中 */ FileUtils.copyFile(attach, new File(savePath+attachFileName)); return super.execute(); } }
文件下载:
- <result name="down" type="stream">一定要是stream
- action中一定要有获得输入流的方法:public InputStream getInputStream()对应struts.xml中的
<param name="inputName">inputStream</param>
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <global-allowed-methods>list,down</global-allowed-methods> <action name="down_*" class="upload_down.DownAction" method="{1}"> <param name="serverPath">D:/ajava/test/</param> <result name="fileList">/listFile.jsp</result> <!-- 文件下载的关键,视图类型要是stream --> <result name="down" type="stream"> <!-- 往StreamResult中注入属性 --> <!-- 文件类型image/jpg 通用类型:application/octet-stream(在tomcat里的conf中的web.xml中查exe)--> <param name="contentType">application/octet-stream</param> <param name="inputName">inputStream</param> <!-- filename=${name}获取action中的name --> <param name="contentDisposition">attachment;filename=${name}</param> <param name="bufferSize">1024</param> </result> </action> </package> </struts>
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'listUser.jsp' starting page</title> </head> <body> <table border="1" width="300"> <tr> <th>编号</th> <th>文件名称</th> <th>操作</th> </tr> <c:forEach items="${fileList}" var="file" varStatus="varSta"> <tr> <td>${varSta.count}</td> <td>${file}</td> <td><a href="${pageContext.request.contextPath}/upload/down_down?name=${file}">下载</a></td> </tr> </c:forEach> </table> </body> </html>
package upload_down; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.sql.Savepoint; import java.util.Map; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; public class DownAction extends ActionSupport{ private String serverPath; private String name; /** * 显示文件列表 * @return * @throws Exception */ public String list() throws Exception{ File file = new File(serverPath); String[] list = file.list(); //把文件列表转到listFile.jsp ActionContext context = ActionContext.getContext(); Map<String, Object> contextMap = context.getContextMap(); contextMap.put("fileList", list); return "fileList"; } /** * 下载文件 * @return * @throws Exception */ public String down() throws Exception{ return "down"; } /** * 提供struts写出数据的输入流 * @return */ public InputStream getInputStream(){ FileInputStream fis = null; try { fis = new FileInputStream(new File(serverPath+name)); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } return fis; } public String getServerPath() { return serverPath; } public void setServerPath(String serverPath) { this.serverPath = serverPath; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
- 除了struts基础包外,还要另外导入:
- web.xml:
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class> <!-- 配置action所在的包 --> <init-param> <param-name>actinoPackage</param-name> <param-value>claire.actionClass</param-value> </init-param> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
- 在web.xml配置的包下新疆Action类,在类中使用注解。