为了避免与 Servlet API 耦合在一起, 方便 Action 做单元测试, Struts2 对 HttpServletRequest, HttpSession 和 ServletContext 进行了封装, 构造了 3 个 Map 对象来替代这 3 个对象, 在 Action 中可以直接使用 HttpServletRequest, HttpSession, ServletContext 对应的 Map 对象来保存和读取数据。这里大家注意,struts1是没有提供与Servlet的API解耦的。

1.Struts2如何获取request、response、session、ServletContext

  在Struts2开发中,除了将请求参数自动设置到Action的字段中,我们往往也需要在Action里直接获取请求(Request)或会话(Session)的一些信息,甚至需要直接对JavaServlet Http的请求(HttpServletRequest),响应(HttpServletResponse)操作.Struts2提供了三种用于获取这些对象的方法,下面来一一介绍一下;

非IOC方法:通过ActionContext,ServletActionContext类直接获取,实现与Servlet解耦

  • ActionContext是 Action 执行的上下文对象, 在 ActionContext 中保存了 Action 执行所需要的所有对象, 包括 parameters, request, session, application 等.
  1. static ThreadLocal actionContext = new ActionContextThreadLocal()
    (ActionContext) actionContext.get();来获取
  • l 获取 HttpServletRequest 对应的 Map 对象:public Object get(Object key): ActionContext 类中没有提供类似 getRequest() 这样的方法来获取 HttpServletRequest 对应的 Map 对象. 要得到 HttpServletRequest 对应的 Map 对象, 可以通过为 get() 方法传递 “request” 参数实现
  1. ActionContext.get(org.apache.struts2.StrutsStatics.HTTP_REQUEST);
  • 获取HTTPServletResponse,该获取同request相似;
  1. ActionContext.get(org.apache.struts2.StrutsStatics.HTTP_RESPONSE);
  • l 获取 HttpSession 对应的 Map 对象:
  1. public Map getSession()
  • l 获取 ServletContext 对应的 Map 对象:
  1. public Map getApplication()

测试代码:获取request、response、session、application对象

  1. @SuppressWarnings("serial")
  2. public class ContextAction extends ActionSupport{
  3.  
  4. @Override
  5. public String execute() throws Exception {
  6. System.out.println("欢迎访问ContextAction中的execute方法!");
  7. /**request对象(与servletAPI解耦的方式)*//*
  8. ActionContext.getContext().put("username", "request_username");
  9. *//**session对象(与servletAPI解耦的方式)*//*
  10. ActionContext.getContext().getSession().put("username", "session_username");
  11. *//**application对象(ServletContext对象)(与servletAPI解耦的方式)*//*
  12. ActionContext.getContext().getApplication().put("username", "application_username");
  13. */
  14. //使用与ServletActionContext的方式操作上述
            ServletActionContext.getRequest().setAttribute("username", "request_username");
            ServletActionContext.getServletContext().setAttribute("username", "application_username");
            ServletActionContext.getRequest().getSession().setAttribute("username", "session_username");
  15. System.out.println("request:"+ServletActionContext.getRequest());
  16. System.out.println("response:"+ServletActionContext.getResponse());
  17. System.out.println("session:"+ServletActionContext.getRequest().getSession());
  18. System.out.println("servletContext:"+ServletActionContext.getServletContext());
  19. //Action接口中常量 SUCCESS="success"
  20. return SUCCESS;
  21. }
  22. }

IOC方法:实现指定接口,由struts框架运行时注入,即使用Struts2 Aware拦截器

Action 类通过可以实现某些特定的接口, 让Struts2 框架在运行时向 Action 实例注入 parameters, request, session 和 application 对应的 Map 对象:

测试代码::获取request、response、session、application对象

  1. @SuppressWarnings("serial")
  2. public class ContextActionTwo extends ActionSupport implements ServletRequestAware,
  3. ServletContextAware,ServletResponseAware,SessionAware{
  4. private HttpServletRequest request;
  5. private HttpServletResponse response;
  6. private Map<String, Object> session;
  7. private ServletContext application;//注意可以实现接口ApplicationAware同样的功能
  8. //使用第二种方式
  9. @Override
  10. public String execute() throws Exception {
  11. System.out.println("欢迎访问ContextActionTwo中的execute()!");
  12. //向作用域中存值
  13. request.setAttribute("username", "request_username2");
  14. session.put("username", "session_username2");
  15. application.setAttribute("username", "application_username2");
  16. return SUCCESS;
  17. }
  18.  
  19. @Override
  20. public void setSession(Map<String, Object> session) {
  21. // TODO Auto-generated method stub
  22. this.session = session;
  23. }
  24.  
  25. @Override
  26. public void setServletResponse(HttpServletResponse response) {
  27. // TODO Auto-generated method stub
  28. this.response = response;
  29. }
  30.  
  31. @Override
  32. public void setServletContext(ServletContext context) {
  33. // TODO Auto-generated method stub
  34. this.application = context;
  35. }
  36.  
  37. @Override
  38. public void setServletRequest(HttpServletRequest request) {
  39. // TODO Auto-generated method stub
  40. this.request = request;
  41. }
  42. }
  1. attr.jsp
  2.  
  3. <body>123
  4. ${requestScope.username}<br>
  5. ${sessionScope.username}<br>
  6. ${applicationScope.username}<br>
  7. </body>

struts-context.xml文件的配置:

  1. <struts>
  2. <package name="context" namespace="/context" extends="struts-default">
  3. <default-action-ref name="contextAction_test"></default-action-ref>
  4.  
  5. <action name="contextAction_test" class="cn.youric.you.two_context.ContextAction">
  6. <result name="success">/context/success.jsp</result>
  7. </action>
  8. <action name="contextAction02_test" class="cn.youric.you.two_context.ContextActionTwo">
  9. <result name="success">/context/attr.jsp</result>
  10. </action>
  11. </package>
  12. </struts>

别忘了include;

2.聊聊ActionContext

  ActionContext(com.opensymphony.xwork.ActionContext)是Action执行时的上下文,上下文可以看作是一个容器(其实我们这里的容器就是一个Map而已),它存放的是Action在执行时需要用到的对象. 一般情况, 我们的ActionContext都是通过: ActionContext context = (ActionContext) actionContext.get();来获取的.我们再来看看这里的actionContext对象的创建:

  1. static ThreadLocal<ActionContext> actionContext = new ThreadLocal<>();

  ThreadLocal可以命名为"线程局部变量",它为每一个使用该变量的线程都提供一个变量值的副本,使每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突.这样,我们ActionContext里的属性只会在对应的当前请求线程中可见,从而保证它是线程安全的.

3. ServletActionContext和ActionContext联系

  ServletActionContext和ActionContext有着一些重复的功能,在我们的Action中,该如何去抉择呢?我们遵循的原则是:如果ActionContext能够实现我们的功能,那最好就不要使用ServletActionContext,让我们的Action尽量不要直接去访问Servlet的相关对象.

  注意:在使用ActionContext时有一点要注意: 不要在Action的构造函数里使用ActionContext.getContext(),因为这个时候ActionContext里的一些值也许没有设置,这时通过ActionContext取得的值也许是null;同样,HttpServletRequest req = ServletActionContext.getRequest()也不要放在构造函数中,也不要直接将req作为类变量给其赋值。至于原因,我想是因为前面讲到的static ThreadLocal actionContext = new ActionContextThreadLocal(),从这里我们可以看出ActionContext是线程安全的,而ServletActionContext继承自ActionContext,所以ServletActionContext也线程安全,线程安全要求每个线程都独立进行,所以req的创建也要求独立进行,所以ServletActionContext.getRequest()这句话不要放在构造函数中,也不要直接放在类中,而应该放在每个具体的方法体中(eg:login()、queryAll()、insert()等),这样才能保证每次产生对象时独立的建立了一个req。

Struts2 第五讲 -- Struts2与Servlet的API解耦的更多相关文章

  1. Struts2(七) Struts2访问Servlet的API

    当接受表单参数,向页面保持数据时.要用到Struts访问Servlet 的API .下面只做参考,有错误或不同意见可以发送邮箱2440867831@qq.com  .建议大家看struts文档,源代码 ...

  2. 关于Struts2自动装配和访问Servlet API

    自动装配 1.根据属性的getter和setter获取值  index.jsp <s:form action="hello" method="POST"& ...

  3. Struts2框架中使用Servlet的API示例

    1. 在Action类中也可以获取到Servlet一些常用的API * 需求:提供JSP的表单页面的数据,在Action中使用Servlet的API接收到,然后保存到三个域对象中,最后再显示到JSP的 ...

  4. 在Struts2框架中使用Servlet的API

    1. 在Action类中也可以获取到Servlet一些常用的API * 需求:提供JSP的表单页面的数据,在Action中使用Servlet的API接收到,然后保存到三个域对象中,最后再显示到JSP的 ...

  5. struts2:在Action中使用Servlet的API,设置、读取各种内置对象的属性

    有两种方式可以实现在Action中使用Servlet的API.一种是使用org.apache.struts2.ServletActionContext类,另一种是使用com.opensymphony. ...

  6. struts2訪问servlet的API

    1.struts作为控制器,正常非常多时候要訪问到servlet的API.经常使用功能:   (1).获取请求參数,控制界面跳转   (2).把共享数据存储于request,session,servl ...

  7. Struts2(二)— Result结果配置、Servlet的API的访问、模型驱动、属性驱动

    一.Result结果配置 1.全局和局部结果 ​ 平常我们设置跳转页面,是在action标签里面加上 result标签来控制,这种设置的页面跳转,称之为局部结果页面但是我们有时候在很多个action里 ...

  8. Struts2页面配置和访问servlet API

    一.Struts2页面配置 在struts2中页面可以分为两种,全局页面和局部页面. 1.全局页面: 在一个<package></package>标签内的多个action都要跳 ...

  9. Struts2获取Servlet的api的两种方式,解决ParameterAware过时的问题

    servlet API通过ActionContext进行获取 Struts2对HttpServletRequest,HttpSession和ServletContext进行了封装,构造了3个Map对象 ...

随机推荐

  1. 白话SpringCloud | 第四章:服务消费者(RestTemple+Ribbon+Feign)

    前言 上两章节,介绍了下关于注册中心-Eureka的使用及高可用的配置示例,本章节开始,来介绍下服务和服务之间如何进行服务调用的,同时会讲解下几种不同方式的服务调用. 一点知识 何为负载均衡 实现的方 ...

  2. .net和js 获取当前url各种属性

    转来 假设当前页完整地址是:http://www.test.com:80/aaa/bbb.aspx?id=5&name=kelli "http://"是协议名 " ...

  3. mc:Ignorable="d"什么意思?

    有两个命名空间我们要注意一下的:xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc=" ...

  4. 写一个安全的Java单例

    单例模式可能是我们平常工作中最常用的一种设计模式了.单例模式解决的问题也很常见,即如何创建一个唯一的对象.但想安全的创建它其实并不容易,还需要一些思考和对JVM的了解. 1.首先,课本上告诉我,单例这 ...

  5. main方法击破

    什么是main方法? 是类中的一段代码,可以让程序独立运行. public class HelloWord{ public static void main(String[] args) { for ...

  6. pv-err-watch

    # pv-err-watch 这是一个前端监控的小工具,提供了多种信息的查询 ## 快速开始 安装`npm install pv-err-watch -S` ```js import errorWat ...

  7. mac的svn

    http://xclient.info/s/cornerstone.html?t=c5242a66e53f1d866afe8c42aace2738c04ce9ee#versions 破解版的地址 打开 ...

  8. css 简单梯形

    通过css2D变形我们可以轻松得到平行四边形,那么通过此技巧可以得到梯形吗? no! 不过我们可以通过3D旋转得到类似这样的效果: transform:perspective(0.5em)  rota ...

  9. webstorm 配置Vue.js 语法提示

    标签属性 v-text v-html v-once v-if v-show v-else v-for v-on v-bind v-model v-ref v-el v-pre v-cloak v-on ...

  10. Apache Flume

    An Event is a unit of data that flows through a Flume agent. The Event flows from Source to Channel  ...