Struts 2 Action classes doesn’t provide any methods to get Servlet API Request, Response, Session and attributes. But sometimes we need to access these in action classes, for example checking HTTP method or to work with session attributes or to set cookies or headers in response.
Struts 2 Action类不提供任何获取Servlet API请求,响应,会话和属性的方法。 但是有时我们需要在操作类中访问它们,例如检查HTTP方法或使用会话属性或设置cookie或标头作为响应。
That’s why Struts 2 API provides a bunch of interfaces that we can implement in action classes to inject these objects in Action classes. All of these interfaces end with “Aware” and defined in org.apache.struts2.interceptor
package.
这就是为什么Struts 2 API提供了许多接口的原因,我们可以在操作类中实现这些接口,以将这些对象注入到操作类中。 所有这些接口均以“ Aware”结尾,并在org.apache.struts2.interceptor
程序包中定义。
All of these interfaces declares setter methods through which Struts 2 API injects Servlet API components in action classes. It’s a great example of Dependency Injection in Java EE frameworks.
所有这些接口都声明了setter方法,Struts 2 API通过这些方法将Action类中的Servlet API组件注入。 这是Java EE框架中依赖注入的一个很好的例子。
These *Aware interfaces are:
这些* Aware接口为:
- SessionAware: This interface provides access to session attributes in action classes and declare a single method
setSession(Map<String, Object> sessionAttributes)
. Note that we can’t get HttpSession by implementing this interface, this is just to get access to the session attributes. SessionAware :此接口提供对操作类中的会话属性的访问,并声明单个方法setSession(Map<String, Object> sessionAttributes)
。 请注意,我们无法通过实现此接口来获取HttpSession,这仅仅是为了访问会话属性。 - ApplicationAware: This interface provides access to context attributes in action classes as Map. We can add attributes to application context by putting values in the context map. This interface declares single method
setApplication(Map<String, Object> applicationAttributes)
. ApplicationAware :此接口提供对操作类中的上下文属性(如Map)的访问。 我们可以通过将值放在上下文映射中来向应用程序上下文添加属性。 此接口声明单个方法setApplication(Map<String, Object> applicationAttributes)
。 - RequestAware: This interface provides access to request attributes in action classes, it contains single method
setRequest(Map<String, Object> requestAttr)
. This interface is only applicable if Action classes are used in Servlet environment. Since this interface makes the Action tied to a servlet environment, so it should be avoided if possible since things like unit testing will become more difficult. RequestAware :此接口提供对操作类中的请求属性的访问,它包含单个方法setRequest(Map<String, Object> requestAttr)
。 仅当在Servlet环境中使用Action类时,此接口才适用。 由于此接口将Action绑定到Servlet环境,因此应尽可能避免这样做,因为单元测试之类的事情将变得更加困难。 - ServletRequestAware: We can implement this interface in action classes to get access to HttpServletRequest object. This interface is only relevant if the Action is used in a servlet environment. It defines a single method as
setServletRequest(HttpServletRequest request)
. ServletRequestAware :我们可以在操作类中实现此接口,以访问HttpServletRequest对象。 仅当在Servlet环境中使用Action时,此接口才有意义。 它定义了一个方法作为setServletRequest(HttpServletRequest request)
。 - ServletResponseAware: Struts 2 action classes can implement this interface to get access to the HttpServletResponse object. We can then use response object to add headers or cookies. It defines a single method as
setServletResponse(HttpServletResponse response)
. ServletResponseAware :Struts 2动作类可以实现此接口来访问HttpServletResponse对象。 然后,我们可以使用响应对象添加标题或cookie。 它定义了一个方法作为setServletResponse(HttpServletResponse response)
。 - CookiesAware: This interface is intended to provide access to cookies in request in the form of Map. It contains single method
setCookiesMap(Map<String,String> cookies)
. To work with this interface, there are two interceptors defined in struts-default package as:<interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/> <interceptor name="cookieProvider" class="org.apache.struts2.interceptor.CookieProviderInterceptor"/>
But they are not part of defaultStack interceptors stack, so we need to include them for action class like below.
However these interceptors are very new and in my testing with Struts 2 version 2.3.15.1, I didn’t find it to be working. I looked into Struts 2 API docs but didn’t find any help on this. I will update the post if I find anything or if you know what is missing, please let us know through comments. The workaround is to use ServletRequestAware and ServletResponseAware interface to get the request cookies or to set cookies in response.
CookiesAware :此接口旨在以请求的形式提供对Map形式的cookie的访问。 它包含单个方法setCookiesMap(Map<String,String> cookies)
。 要使用此接口,在struts-default包中定义了两个拦截器:<interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/> <interceptor name="cookieProvider" class="org.apache.struts2.interceptor.CookieProviderInterceptor"/>
但是它们不是defaultStack拦截器堆栈的一部分,因此我们需要将它们包括在动作类中,如下所示。
但是这些拦截器是非常新的,在我对Struts 2版本2.3.15.1的测试中,我发现它没有起作用。 我查看了Struts 2 API文档,但没有找到任何帮助。 如果我发现任何问题,或者如果您知道缺少什么,我将更新该帖子,请通过评论告知我们。 解决方法是使用ServletRequestAware和ServletResponseAware接口获取请求cookie或设置cookie作为响应。
- PrincipalAware: We can implement this interface in action class to get Principal information from HttpServletRequest object. This interface works with
PrincipalProxy
to provide user id, principal details. PrincipalAware :我们可以在操作类中实现此接口,以从HttpServletRequest对象获取Principal信息。 此接口与PrincipalProxy
一起使用以提供用户ID和主体详细信息。
Let’s see all these interfaces in action with a simple Struts 2 project. Our final project structure looks like below image.
让我们通过一个简单的Struts 2项目查看所有这些接口。 我们的最终项目结构如下图所示。
Struts2配置文件 (Struts2 Configuration Files)
web.xml
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns="https://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>Struts2Example</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
pom.xml
pom.xml
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>Struts2Example</groupId>
<artifactId>Struts2Example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.15.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
<finalName>${project.artifactId}</finalName>
</build>
</project>
struts.xml
struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"https://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.convention.result.path" value="/"></constant>
<package name="user" namespace="/" extends="struts-default">
<action name="login">
<result>/login.jsp</result>
</action>
<action name="home" class="com.journaldev.struts2.actions.HomeAction">
<interceptor-ref name="cookie"></interceptor-ref>
<interceptor-ref name="cookieProvider"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
<result name="success">/home.jsp</result>
</action>
</package>
</struts>
The configuration files are self explanatory and easy to understand.
配置文件不言自明,易于理解。
Struts2 JSP页面 (Struts2 JSP Pages)
login.jsp
login.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII"
pageEncoding="US-ASCII"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Login Page</title>
</head>
<body>
<s:form action="home" method="post">
<s:textfield label="User Name" name="user"></s:textfield>
<s:textfield label="Password" name="password"></s:textfield>
<s:submit label="Login"></s:submit>
</s:form>
</body>
</html>
home.jsp
home.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII"
pageEncoding="US-ASCII"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Home Page</title>
</head>
<body>
<h3>Welcome <s:property value="user"/></h3>
</body>
</html>
JSP pages are also very simple and just used to send some data in request and then use them in result page.
JSP页面也非常简单,仅用于在请求中发送一些数据,然后在结果页面中使用它们。
Struts2动作类 (Struts2 Action Class)
HomeAction.java
HomeAction.java
package com.journaldev.struts2.actions;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.struts2.interceptor.ApplicationAware;
import org.apache.struts2.interceptor.CookiesAware;
import org.apache.struts2.interceptor.PrincipalAware;
import org.apache.struts2.interceptor.PrincipalProxy;
import org.apache.struts2.interceptor.RequestAware;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionSupport;
public class HomeAction extends ActionSupport implements SessionAware,
ApplicationAware, CookiesAware, RequestAware, ServletRequestAware,
ServletResponseAware, PrincipalAware {
private static final long serialVersionUID = 1L;
@Override
public String execute() {
System.out.println("Request Method: " + request.getMethod());
System.out.println("Using HTTPS?: " + principalProxy.isRequestSecure());
System.out.println("Request Cookies:" + requestCookies);
// add a cookie to response
response.addCookie(new Cookie("user", "Pankaj"));
if (requestCookies == null)
requestCookies = new HashMap<String, String>();
requestCookies.put("test", "test");
System.out.println("Session Attributes: " + sessionAttributes);
// add session attribute
HttpSession mySession = request.getSession();
mySession.setAttribute("user", "Pankaj");
//OR
sessionAttributes.put("test", "Test");
System.out.println("Context Attributes: "
+ contextAttributes.get("user"));
// add context attribute
contextAttributes.put("user", "Pankaj");
System.out.println("Request Attributes: " + requestAttributes);
return SUCCESS;
}
// variables for *Aware interfaces
private PrincipalProxy principalProxy = null;
private HttpServletRequest request = null;
private HttpServletResponse response = null;
private Map<String, Object> requestAttributes = null;
private Map<String, Object> sessionAttributes = null;
private Map<String, Object> contextAttributes = null;
private Map<String, String> requestCookies = null;
@Override
public void setPrincipalProxy(PrincipalProxy principalProxy) {
this.principalProxy = principalProxy;
}
@Override
public void setServletResponse(HttpServletResponse httpServletResponse) {
this.response = httpServletResponse;
}
@Override
public void setServletRequest(HttpServletRequest httpServletRequest) {
this.request = httpServletRequest;
}
@Override
public void setRequest(Map<String, Object> requestAttr) {
this.requestAttributes = requestAttr;
}
@Override
public void setCookiesMap(Map<String, String> cookies) {
this.requestCookies = cookies;
}
@Override
public void setApplication(Map<String, Object> applicationAttributes) {
this.contextAttributes = applicationAttributes;
}
@Override
public void setSession(Map<String, Object> sessionAttr) {
this.sessionAttributes = sessionAttr;
}
// java bean properties to hold request attributes
private String user;
private String password;
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
A single action class implementing all the *Aware interfaces and using them to log some data in server log files.
一个实现所有* Aware接口并使用它们将某些数据记录在服务器日志文件中的动作类。
Once we execute the login action and then hit home action multiple times, we get following logs.
一旦执行了登录操作,然后多次击中主页操作,我们就会获得以下日志。
Request Method: POST
Using HTTPS?: false
Request Cookies:{}
Session Attributes: {}
Context Attributes: null
Request Attributes: {struts.valueStack=com.opensymphony.xwork2.ognl.OgnlValueStack@662fe032, __cleanup_recursion_counter=1, struts.actionMapping=ActionMapping{name='home', namespace='/', method='null', extension='action', params=null, result=null}}
Request Method: POST
Using HTTPS?: false
Request Cookies:{}
Session Attributes: {test=Test, user=Pankaj}
Context Attributes: Pankaj
Request Attributes: {__cleanup_recursion_counter=1, struts.valueStack=com.opensymphony.xwork2.ognl.OgnlValueStack@749cd006, struts.actionMapping=ActionMapping{name='home', namespace='/', method='null', extension='action', params=null, result=null}}
Notice that request cookies are NULL, however I checked request and response in browser and it’s sending cookies in request.
请注意,请求cookie为NULL,但是我在浏览器中检查了请求和响应,并在请求中发送了cookie。
That’s all for accessing Servlet API core components in Struts 2 Action classes. It’s simple and elegant to use.
这就是访问Struts 2 Action类中的Servlet API核心组件的全部。 使用起来简单而优雅。