在传统的web开发中,经常会用到Servelt API中的HttpServletRequest、HttpSession和Servletcontext。Struts2框架让我们可以直接访问和设置action及模型对象的数据,这降低了对HttpServletRequest对象的使用需求,但在某些应用中,我们可能会需要在action中去访问HttpServletRequest对象以及其他两个对象,例如,用户登录成功后,我们应该将用户信息保存到Session中。
Struts2提供了多种方式来访问上述的三种对象,归结起来,可以划分为两大类:
Ø 与Servlet api 解耦的访问方式
Ø 与Servlet api耦合的访问方式
为了避免与Servlet api耦合在一起,方便Action类做单元测试,Struts2对HttpServletRequest、HttpSession和ServletContext进行了封装,构造了三个Map对象来替代这三种对象,在Action中,直接使用HttpServletRequest、HttpSession和ServletContext对应的Map对象来保存和读取数据。
要获取这三个Map对象,可以使用com.opensymphony.xwork2.ActionContext类。
ActionContext是action执行的上下文,在ActionContext中保存了action执行所需要的一组对象,包括parameters,request, session, application和locale等。
ActionContext类定义了如下方法:
用于获取HttpServletRequest,HttpSession和ServletContext对应的Map对象。
Ø Public Object get(Object key)
ActionContext类没有提供类似getRequest()这样的方法来获取封装了HttpServletRequest的Map对象。要得到请求Map对象,你需要为get()方法传递参数”request”.
Ø Public Map getSession()
获取封装了HttpSession的Map对象
Ø Public Map getApplication()
获取封装了ServletContext的Map对象
Eg:通过ActionContext来获取request ,session和application对象。
http://localhost:8080/struts2/login/index!reg.action?user.username=kevin&user.password=123
LoginAction.java
public class LoginAction1 extends ActionSupport { private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String reg(){ ActionContext context = ActionContext.getContext(); Map request = (Map)context.get("request"); Map session = context.getSession(); Map application = context.getApplication(); request.put("greeting", "欢迎您来到程序员之家"); session.put("user", user); Integer count = (Integer)application.get("counter"); if(null==count) count=1; else count=count++; application.put("counter", count); return SUCCESS; } }
<h3>${sessionScope.user.username},${requestScope.greeting} . <br/> 本站的访问量是:${applicationScope.counter} </h3>
说明在Action中,对ActionContext返回的Map对象的操作,等价于对Servlet API中的HttpServletRequest,HttpSession,ServletContext对象的操作。
利用请求对象来传递数据还有一种方式,使用ActionContext类的put()方法将数据保存到ActionContext中,如下:
ActionContext.getContext().put(“greeting”,”welcome”);
然后在结果页面中,从请求对象中取出greeting属性:
${requestScope.greeting} 或者
<%=request.getAttribute(“greeting”)%>
除了利用ActionContext来获取request, session, application对象这种方式外,Action类还可以实现某些特定的接口,让struts2 框架在运行时向Action实例注入request, session 和application对象。
接口如下:
Ø Org.apache.struts2.interceptor.RequestAware
框架利用该接口,向Action实例注入request Map对象。该接口只有一个方法,如下
public void setRequest(Map request)
Ø Org.apache.struts2.interceptor.SessionAware
框架利用该接口,向Action实例注入sessionMap对象。该接口只有一个方法,如下:
void setSession(Map session)
Ø Org.apache.struts2.interceptor.ApplicationAware
框架利用该接口,向Action实例注入application Map对象。该接口只有一个方法,如下:
void setApplication(Map application)
Eg:通过接口注入来获取request,session,application对象
http://localhost:8080/struts2/login/login.action?user.username=kevin&user.password=123
Login2Action.java
public class LoginAction2 implements Action, RequestAware, SessionAware, ApplicationAware { private Map request; private Map session; private Map application; @Override public String execute() throws Exception { request.put("greeting", "欢迎您来到程序员之家"); session.put("user", user); Integer count = (Integer) application.get("counter"); if (null == count) count = 1; else count = count++; application.put("counter", count); return SUCCESS; } @Override public void setRequest(Map request) { this.request = request; } @Override public void setSession(Map session) { this.session = session; } @Override public void setApplication(Map application) { this.application = application; } private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
在LoginAction2类实现了RequestAware,SessionAware,ApplicationAware接口,框架在运行时会调用这三个接口中的方法,向LoginAction2注入request, session, application对象。在方法中不再需要访问ActionContext。
虽然利用struts2提供的request, session 和 application对象就可以对HttpServletRequest,HttpSession,ServletContext对象中的数据进行操作,但它们毕竟是Map类型,如果我们需要调用HttpServletRequest,HttpSession,ServletContext中的特定操作,例如获取请求方法的名字(调用HttpServletRequest中的getMethod()方法),那么可以使用下一节介绍的方式来获取servlet环境中的对象。
直接访问Servlet API 将使你的Action与Servlet环境耦合在一起,我们知道对于HttpServletRequest, HttpServletResponse 和ServletContext 这些对象,它们都是由Servlet容器来构造的,与这些对象绑定在一起,测试时就需要有Servlet容器,不便于Action的单元测试。但有时候,我们又确实需要直接访问这些对象,那么当然是以完成任务需求为主。
要直接获取HttpServletRequest 和 ServletContext对象,可以使用org.apache.strusts2.ServletActionContext类,该类是ActionContext的子类,在这个类中定义下面两个静态方法:
Ø Public static HttpServletRequest getRequest()
得到HttpServletRequest对象
Ø Public static ServletContext getServletContext()
得到ServletContext对象
此外,ServletActionContext类还给出了获取HttpServletResponse对象的方法,如下:
Ø Public static HttpServletResponse getResponse()
ServletActionContext类并没有给出直接得到HttpSession对象的方法,HttpSession对象可以通过HttpServletRequest对象来得到。
除了上述的方法调用得到HttpServletRequest 和 ServletContext对象外,还可以调用ActionContext 对象的 get() 方法,传递 ServletActionContext.HTTP_REQUEST 和ServletActionContext.SERVLET_CONTEXT键值来得到HttpServletRequest和ServletContext对象,如下所示:
Ø ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST)
得到与ServletActionContext.HTTP_REQUEST键值绑定的HttpServletRequest对象
Ø ActionContext.getContext().get(ServletActionContext.SERVLET_CONTEXT)
得到与ServletActionContext.SERVLET_CONTEXT键值绑定的ServletContext对象。
Ø ActionContext.getContext().get(ServletActionContext.HTTP_RESPONSE)
得到HttpServletResponse对象
建议采用第一种方式来获取HttpServletRequest和ServletContext对象,这样简单清晰。
Eg:通过ServletActionContext来获取HttpServletRequest和ServletContext对象
LoginAction3.java
public class LoginAction3 extends ActionSupport { private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String execute() throws Exception { HttpServletRequest request = ServletActionContext.getRequest(); HttpSession session = request.getSession(); ServletContext context = ServletActionContext.getServletContext(); /** ActionContext ctx = ActionContext.getContext(); HttpServletRequest request = (HttpServletRequest)ctx.get(ServletActionContext.HTTP_REQUEST); HttpSession session = request.getSession(); ServletContext context = (ServletContext)ctx.get(ServletActionContext.SERVLET_CONTEXT); */ //在请求中放置欢迎信息 request.setAttribute("greeting", "欢迎您来到程序员之家"); session.setAttribute("user", user); Integer count = (Integer) context.getAttribute("counter"); if (null == count) count = 1; else count = count++; context.setAttribute("counter", count); return SUCCESS; } }
除了利用ServletActionContext来获取HttpServletRequest对象和ServletContext对象这种方式外,Action类还可以实现ServletRequestAware 和 ServletContextAware接口,由struts2框架向Action实例注入HttpServletRequest 和 ServletContext对象。
Org.apache.struts2.interceptor.ServletRequestAware接口只有一个方法,如下:
Void setServletRequest(HttpServletRequest request)
Org.apache.struts2.util.ServletContextAware接口也只有一个方法:
Void setServletContext(ServletContext context)
ServletRequestAware接口和ServletContextAware接口不属于同一个包,前者在org.apache.struts2.interceptor包中,后者在org.apache.struts2.util包中。
Eg:通过接口注入来获取HttpServletRequest和 ServletContext对象:
public class LoginAction4 extends ActionSupport implements ServletRequestAware, ServletContextAware { private User user; private HttpServletRequest request; private ServletContext context; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String execute() throws Exception { HttpSession session = request.getSession(); // 在请求中放置欢迎信息 request.setAttribute("greeting", "欢迎您来到程序员之家"); session.setAttribute("user", user); Integer count = (Integer) context.getAttribute("counter"); if (null == count) count = 1; else count = count++; context.setAttribute("counter", count); return SUCCESS; } @Override public void setServletRequest(HttpServletRequest request) { this.request = request; } @Override public void setServletContext(ServletContext context) { this.context = context; } }