[原创]java WEB学习笔记55:Struts2学习之路---详解struts2 中 Action,如何访问web 资源,解耦方式(使用 ActionContext,实现 XxxAware 接口),耦合方式(通过ServletActionContext,通过实现 ServletRequestAware, ServletContextAware 等接口的方式)

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用

内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系。

本人互联网技术爱好者,互联网技术发烧友

微博:伊直都在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>

 

  

 

 

posted @ 2016-08-18 16:44  jason_zhangz  阅读(2747)  评论(0编辑  收藏  举报