本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用
内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系。
本人互联网技术爱好者,互联网技术发烧友
微博:伊直都在0221
QQ:951226918
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1.Action 类
1)action: 应用程序可以完成的每一个操作. 代表一个sturts2 的请求。例如: 显示一个登陆表单; 把产品信息保存起来
2)Action类: 普通的 Java 类,能够处理struts2 请求的java类, 可以有属性和方法, 同时必须遵守下面这些规则:
① 属性的名字必须遵守与 JavaBeans 属性名相同的命名规则. 属性的类型可以是任意类型. 从字符串到非字符串(基本数据库类型)之间的数据转换可以自动发生
② 必须有一个不带参的构造器:反射
③ 至少有一个供 struts 在执行这个 action 时调用的方法
④ 同一个 Action 类可以包含多个 action 方法.
⑤ Struts2 会为每一个 HTTP 请求创建一个新的 Action 实例。即,Action 不是单例的,是线程安全的。
2.在Action中如何访问web资源
1)什么是web 资源
HttpServletRequest, HttpSession,ServletContext 等原生的Servlet API
2)为什么访问web 资源?
B/S 应用的controller 中必然需要访问web资源:向域对象中读写属性,读写 cookie,获取realPath ....
3) 如何访问?
① 和servlet API 解耦的方式:只能访问有限的Servelt API 对象,且只能访问其有限的方法(读取请求参数,读写域对象的属性,是session 失效 ... )
> 使用 ActionContext
>实现 XxxAware 接口
注:为了避免与 Servlet API 耦合在一起, 方便 Action 做单元测试, Struts2 对 HttpServletRequest, HttpSession 和 ServletContext 进行了封装, 构造了 3 个 Map 对象来替代这 3 个对象,
在 Action 中可以直接使用 HttpServletRequest, HttpServletSession, ServletContext 对应的 Map 对象来保存和读取数据.
② 和servlet API 耦合的方式:可以访问更多的Servlet API对象,且可以调用其原生的方法。
> 使用 ServletContext
> 实现ServletXxxAware接口
3.1 和servlet API 解耦的方式
1)通过 ActionContext 访问 Web 资源:ActionContext 是 Action 执行的上下文对象, 在 ActionContext 中保存了 Action 执行所需要的所有对象, 包括 parameters, request, session, application 等.
> 获取 HttpSession 对应的 Map 对象: public Map getSession() , session 对应的Map 实际上是SessionMap 类型的,强转之后调用其invalidate() 方法,可以使其session 失效
> 获取 ServletContext 对应的 Map 对象: public Map getApplication()
> 获取请求参数对应的 Map 对象: public Map getParameters()
> 获取 HttpServletRequest 对应的 Map 对象: public Object get(Object key):ActionContext 类中没有提供类似 getRequest() 这样的方法来获取 HttpServletRequest 对应的 Map 对象. 要得到 HttpServletRequest 对应的 Map 对象, 可以通过为 get() 方法传递 “request” 参数实现
struts.xml
1 <package name="testAction" namespace="/" extends="struts-default">
2
3 <action name="TestActionContext" class="com.jason.struts.action.TestActionContextAction" method="execute">
4
5 <result>/test-actionContext.jsp</result>
6
7 </action>
8
9 </package>
10
TestActionContextAction.java
1 package com.jason.struts.action; 2
3 import java.util.Map; 4
5 import com.opensymphony.xwork2.ActionContext; 6
7 /**
8 * 9 * @ClassName:TestActionContextAction 10 * @Description:TODO 11 * @author: jason_zhangz@163.com 12 * @date:2016年8月2日下午6:01:48 13 * 14 * 15 */
16 public class TestActionContextAction { 17
18 public String execute(){ 19
20 //0.获取actionContext对象,是Action 的上下文对象。可以从中获取到Action获取所以信息
21
22 ActionContext actionContext = ActionContext.getContext(); 23
24 //1.获取application 对应的Map,并向其中添加一个属性 25 //通过application 对象的 getApplication() 方法来获取application 对象的map 对象
26 Map<String, Object> applicationMap = actionContext.getApplication(); 27 //设置属性
28 applicationMap.put("applicationKey", "applicationValue"); 29
30 //2.session
31 Map<String, Object> sessionMap = actionContext.getSession(); 32 sessionMap.put("sessionKey", "sessionValue"); 33
34
35 //3.request 36 //ActionContext 中并没有提供 getRequest 方法来获取 request 对应的 Map,需要手工调用get(),传入 requet 字符串来获取
37
38 Map<String, Object> requsetMap = (Map<String, Object>) actionContext.get("request"); 39 requsetMap.put("requestKey", "requestValue"); 40
41 //4.获取请求参数对应的Map,并且获取指定的参数值 42 //键:请求参数的名字;值:请求参数的值对应的字符串数组 43 //注意:1. getParameters 的返回值为Map<String, Object> ,而不是Map<String ,String[]> 44 // 2.parameters 这个Map 只能读,不能写入数据,如果写入,但不出错,同时也不起作用
45 Map<String, Object> paramters = actionContext.getParameters(); 46 System.out.println(((String [])paramters.get("name"))[0]); 47
48
49 paramters.put("age", 100); 50 return "success"; 51 } 52
53 }
index.jsp
1 <%@ page language="java" contentType="text/html; charset=UTF-8"
2 pageEncoding="UTF-8"%>
3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
4 <html>
5 <head>
6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
7 <title>testAction index page</title>
8 </head>
9 <body>
10
11 <a href="TestActionContext.action?name=jason"> Test ActionContext</a>
12 </body>
13 </html>
test-actionContest.jsp
1 <%@ page language="java" contentType="text/html; charset=UTF-8"
2 pageEncoding="UTF-8"%>
3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
4 <html>
5 <head>
6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
7 <title>test-actionContext page</title>
8 </head>
9 <body>
10
11 <h4>test-actionContext page</h4>
12
13 application: ${applicationScope.applicationKey } 14 <br><br>
15
16
17 application: ${sessionScope.sessionnKey } 18 <br><br>
19
20
21 request:${requestScope.requestKey } 22 <br><br>
23
24 age:${parameters.age } 25
26
27 </body>
28 </html>
3.2实现 XxxAware 接口
TestAwareAction.java
1 package com.jason.struts.action; 2
3 import java.util.Map; 4
5 import org.apache.struts2.interceptor.ApplicationAware; 6 import org.apache.struts2.interceptor.ParameterAware; 7 import org.apache.struts2.interceptor.RequestAware; 8 import org.apache.struts2.interceptor.SessionAware; 9
10 /**
11 * 12 * @ClassName:TestAwareAction 13 * @Description:测试 解耦 实现 XxxAware 接口 14 * @author: jason_zhangz@163.com 15 * @date:2016年8月5日下午5:28:42 16 * 17 * 18 */
19 public class TestAwareAction implements ApplicationAware ,SessionAware,RequestAware,ParameterAware{ 20 //通过实现不同的Aware 的接口,之后实现 setXX 方法,而struts2 用注入的方式,将对应的map 对象注入到自己所定义个私有变量中,之后调用execute方法
21
22 public String execute(){ 23 24 //1.向application 中加入一个属性:applicationKey - applicationValue 25 application.put("applicationKey2", "applicationValue2"); 26 //2.从application 中读取一个属性data,打印 27 System.out.println(application.get("date")); 28 29 return "success"; 30 } 31
32 private Map<String, Object> application; 33 private Map<String,String[]> parameters; 34 private Map<String, Object> request; 35 private Map<String, Object> session; 36
37 @Override 38 public void setApplication(Map<String, Object> application) { 39 40 this.application = application; 41 } 42 @Override 43 public void setParameters(Map<String, String[]> parameters) { 44 this.parameters = parameters; 45
46 } 47 @Override 48 public void setRequest(Map<String, Object> request) { 49 this.request = request; 50
51 } 52 @Override 53 public void setSession(Map<String, Object> session) { 54 this.session = session; 55
56 } 57
58
59 }
struts.xml
1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE struts PUBLIC 3 "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" 4 "http://struts.apache.org/dtds/struts-2.3.dtd">
5
6 <struts>
7 <!--
8 package: 包. Struts2 使用package 来组织模块 9 name属性:必须. 用于其他的包引用当前包。一般为当前模块的名字 10 extends:当前包继承哪个包,继承的,即可以继承其中的所有的配置。通常情况下,继承 struts-default 11 namespace:可选,如果没有给出,则 以 "/" 为默认值。若namespace有一个非默认值,则要想调用这个包里面的action,则必须把这个属性所定义的命名空间添加到先关的URI 字符串里。在servletPath 前面添加。 12 例如: http://localhost:8080/contextpath/namespace/servletPath 13
14
15 -->
16 <!-- <package name="helloword" extends="struts-default"> 17
18 配置一个action: 一个struts2 的请求就是一个action 19
20 name:对应一个Struts2 的请求的名字(或者对应一个servletPath,但是去除 / 和 扩展名),不含扩展名 21 class:的默认值为:com.opensymphony.xwork2.ActionSupport 22 method:的默认值为:execute 23
24
25 <action name="product-input" 26 class="com.opensymphony.xwork2.ActionSupport" 27 method="execute"> 28
29
30 result:结果。即,要访问的路径。表示action 方法执行后可能返回的一个结果。一个action节点可能有多个result 子节点。多个子节点使用name属性来区分, 31 name:标示一个一个result,和action 方法的返回值对应。默认值为 success 32 type:表示结果的类型,默认为dispatcher(转发到 结果) 33
34 <result name="success" type="dispatcher">/struts2/input.jsp</result> 35 </action> 36
37
38 <action name="product-save" class="com.jason.struts.helloword.Product" method="save"> 39 <result name="details">/struts2/details.jsp</result> 40
41 </action> 42
43
44
45 </package> 46
47 -->
48
49 <package name="testAction" namespace="/" extends="struts-default">
50
51 <action name="TestActionContext" class="com.jason.struts.action.TestActionContextAction" method="execute">
52
53 <result>/test-actionContext.jsp</result>
54
55 </action>
56
57
58 <action name="TestAware" class="com.jason.struts.action.TestAwareAction" method="execute">
59
60 <result>/test-aware.jsp</result>
61
62 </action>
63
64 </package>
65
66
67
68
69
70
71
72 </struts>
test-aware.jsp
1 <%@ page language="java" contentType="text/html; charset=UTF-8"
2 pageEncoding="UTF-8"%>
3 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
4 <html>
5 <head>
6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
7 <title>Test Aware Page<</title>
8 </head>
9 <body>
10
11 <h4>Test Aware Page</h4>
12
13 application:${applicationScope.applicationKey2 } 14 </body>
15 </html>
index.jsp
1 <%@page import="java.util.Date"%>
2 <%@ page language="java" contentType="text/html; charset=UTF-8"
3 pageEncoding="UTF-8"%>
4 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
5 <html>
6 <head>
7 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
8 <title>testAction index page</title>
9 </head>
10 <body>
11 <%
12 Date date = new Date(); 13 application.setAttribute("date", date); 14 %>
15 <a href="TestActionContext.action"> Test ActionContext</a>
16 <br>
17 <br>
18 <a href="TestAware.action"> TestAware</a>
19 </body>
20 </html>
3.3.两种解耦方式web资源的比较
1)若一个Action 类中有对个 Action 方法,且多个方法,使用域对象的 Map 或 parameters ,则建议使用实现了Aware 接口的方式。
3.4. 与Servlet 耦合的访问方式:需要用到原生的API
方式一:
1) 直接访问 Servlet API 将使 Action 与 Servlet 环境耦合在一起, 测试时需要有 Servlet 容器, 不便于对 Action 的单元测试;
2) 直接获取 HttpServletRequest 对象: ServletActionContext.getRequest();
3) 直接获取 HttpSession 对象:ServletActionContext.getRequest().getSession();
4) 直接获取 ServletContext 对象:ServletActionContext.getServletContext();
TestServletActionContextAction.java
1 package com.jason.struts.action; 2
3 import javax.servlet.ServletContext; 4 import javax.servlet.http.HttpServletRequest; 5 import javax.servlet.http.HttpSession; 6
7 import org.apache.struts2.ServletActionContext; 8
9 public class TestServletActionContextAction { 10
11
12 public String execute(){ 13 /**
14 * ServletActionContext:可以获取到当前Action 对象需要的一切的servlet API 相关对象 15 * 常用方法: 16 * 1.获取 HttpServletRequest :ServletActionContext.getRequest() 17 * 2.获取 HttpSession :ServletActionContext.getRequest().getSession() 18 * 3.获取ServletContext:ServletActionContext.getServletContext() 19 */
20
21 HttpServletRequest request = ServletActionContext.getRequest(); 22 HttpSession session = ServletActionContext.getRequest().getSession(); 23 ServletContext servletContext = ServletActionContext.getServletContext(); 24
25 System.out.println("execute ..."); 26
27
28 return "success"; 29 } 30 }
struts.xml
1 2 <action name="TestServletActionContext" class="com.jason.struts.action.TestServletActionContextAction"> 3 <result>/success.jsp</result> 4 </action>
index.jsp
1 <a href="TestServletActionContext.action"> TestServletActionContext</a>
方式二:
通过实现 ServletRequestAware, ServletContextAware 等接口的方式
TestSerlvetAwareAction.java
1 package com.jason.struts.action; 2
3 import javax.servlet.ServletContext; 4 import javax.servlet.http.HttpServlet; 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletResponse; 7
8 import org.apache.struts2.interceptor.ServletRequestAware; 9 import org.apache.struts2.interceptor.ServletResponseAware; 10 import org.apache.struts2.util.ServletContextAware; 11
12
13 /**
14 * 15 * @ClassName:TestSerlvetAwareAction 16 * @Description:通过实现ServletXxxAware 接口的方式可以有Struts2 注入需要的Servlet 相关对象 17 * 18 * ServletRequestAware: 注入HttpServletRequest 对象(常用) 19 * ServletContextAware: 注入 ServletContext 对象(常用) 20 * ServletResponseAware: 21 * 22 * @author: jason_zhangz@163.com 23 * @date:2016年8月18日下午4:35:21 24 * 25 * 26 */
27 public class TestSerlvetAwareAction implements ServletRequestAware, ServletContextAware,ServletResponseAware{ 28
29
30 public String execute(){ 31
32 System.out.println("execute ..."); 33
34 return "success"; 35 } 36
37 private ServletContext servletContext; 38 @Override 39 public void setServletContext(ServletContext context) { 40 System.out.println(context); 41 //org.apache.catalina.core.ApplicationContextFacade@47da4d19
42 this.servletContext = context; 43
44 } 45
46 private HttpServletRequest request; 47 @Override 48 public void setServletRequest(HttpServletRequest request) { 49 System.out.println(request); 50 //org.apache.struts2.dispatcher.StrutsRequestWrapper@b8519f4
51 this.request = request; 52
53 } 54
55 private HttpServletResponse response; 56 @Override 57 public void setServletResponse(HttpServletResponse response) { 58 System.out.println(response); 59 //org.apache.catalina.connector.ResponseFacade@4f6ae814
60 this.response = response; 61 } 62
63 }
Struts.xml
1 <action name="TestServletAwareAction" class="com.jason.struts.action.TestSerlvetAwareAction">
2
3 <result>/success.jsp</result>
4 </action>
index.jsp
1 <a href="TestServletAwareAction.action"> TestServletAwareAction</a>
