ActionContext and ServletActionContext parsing

1.ActionContext
The ActionContext of the xwork framework is the context of Action execution and stores the objects needed for Action execution. When using webwork, there are Parameter, Session, ServletContext, Locale and other information in it. In this way, webwork is responsible for converting Servlet related data into Map objects (i.e. ActionContext) independent of Servlet API, so as to decouple the Action implementation of xwork from the web layer, logic layer and presentation layer.

2.ServletActionContext
Provides a way to interact directly with the Servlet container. Through it, you can obtain HttpServletRequest, HttpServletResponse, ServletConfig, ServletContext and PageContext objects. However, using ServletActionContext means that the Action is tightly coupled with the Servlet API.

3. Because WebWork encapsulates request, parameter, Session and Application, these implicit objects are encapsulated into corresponding maps, such as RequestMap, ParameterMap, SessionMap and ApplicationMap, which are composed of

ActionContext, so we usually don't need to deal with the underlying objects such as request and session. This is what I was confused at first because I couldn't find the session. In fact, the processing of SessionMap is the processing of session

Handled it. We can return an instance of ActionContext through the static method getContext of ActionContext, and then call its getSession method to obtain the SessionMap. Then we can use the put and get methods to read and write the session.

Map params = new HashMap();;   
params.put(String, String);;   
......   
Map extraContext = new HashMap();;   
extraContext.put(ActionContext.PARAMETERS,params); 

Map session = new HashMap();;   
session.put("foo", "bar");;   
extraContext.put(ActionContext.SESSION, session); 

ActionContext ctx = ActionContext.getContext(); 
Map session = ctx.getSession(); 
session.put("username",loginInfo.getUsername()); 

ActionContext ctx = ActionContext.getContext(); 
Map params = ctx.getParameters(); 
String username = ctx.getParameters("username"); 

OgnlValueStack stack = new OgnlValueStack(); 
stack.push(new User());//First, push the object to be assigned into the stack 
stack.setValue("name","erica");//Assign a value to the specified property name of the stack top object 

Explore ActionContext again
As we have learned earlier, ActionContext is the context of Action execution, which stores the objects that Action needs to use during execution. We also call it generalized value stack.

Struts 2 will create a new ActionContext before each Action is executed. In the same thread, the properties in the ActionContext are unique, so that the Action can be used in multiple threads.

1: Thread safety of ActionContext

So how does struts 2 ensure the thread safety of ActionContext?

Look at the code of ActionContext object. An example is as follows:

java code:

public class ActionContext implements Serializable {
static ThreadLocal actionContext = new ThreadLocal();
......
}

public class ActionContext implements Serializable {static ThreadLocal actionContext = new ThreadLocal();......}
ThreadLocal, also known as "thread local variable", provides a copy of the variable value for each thread using the variable, so that each thread can change its copy independently without conflict with the copies of other threads.

The data stored in ActionContext is stored in the ThreadLocal attribute, which will only be visible in the corresponding current request thread, so as to ensure that the data is thread safe.

2: Access is Map

Reviewing the previous programs that use ActionContext to access the data in the Session, you will find that in fact, a Map is accessed in the program, not an HttpSession object. Why?

Originally, the struts 2 framework repackages many objects related to the Web. For example, the HttpSession object is repackaged into a Map object, which stores the data in the Session and provides the Map for Action, instead of directly dealing with the underlying HttpSession without Action. It is precisely because of the packaging of the framework that Action can be completely decoupled from the Web layer.

However, it should be noted that ActionContext cannot be used in ordinary Java applications.

In previous studies, Action and Servlet API are decoupled, so execute can be invoked in Java applications to test. However, if ActionContext is used to obtain session data, it cannot run like this. Because ActionContext packages all Web data, there is no Web environment and response data when running in Java applications, so null pointer exceptions will be thrown.

Accessing the values of other Web objects is similar to this. What you access through ActionContext is the wrapped Map.

3: Using SessionAware interface

Struts 2 also provides another simple way to use the SessionAware interface to access the data stored in ActionContext. By using IoC/DI to inject the Session Map into the Action, the interface can directly use this Map to operate the data in the program.

(1) Instead of accessing ActionContext in Action, Action implements the SessionAware interface, which tells struts 2 to set the Session Map before the Action is executed. It is implemented through the servletConfig interceptor, which is in the defaultStack. The example code is as follows:

java code:

public class OgnlAction extends ActionSupportimplements SessionAware{
private Map<String, Object> session;
public void setSession(Map<String, Object> session) 
	{
		this.session = session;
	}
	public String execute(){
	session.put("sessionTestKey", "test SessionAware");
	return this.SUCCESS;
	}
}
public class OgnlAction extends ActionSupport implements SessionAware{ private Map<String, Object> session; public void setSession(Map<String, Object> session) { this.session = session; } public String execute(){ session.put("sessionTestKey", "test SessionAware"); return this.SUCCESS; }}

In the code above:

The Action class implements the SessionAware interface
This interface requires the Action class to implement a method setsession (map < string, Object > Session), and inject the data of the Session through this method
In the execute method, you can manipulate the data in the session through this private attribute. Note that the value in this Map is also linked with HttpSession.
(2) The result interface is also slightly modified to see the effect of Action operation session. An example is as follows:

java code:

<%@ taglib prefix="s" uri="/struts-tags"%>
Values in session:<s:property value="#session['sessionTestKey']"/>
<br>
adopt Servlet of Api Get value in session:<%=session.getAttribute("sessionTestKey") %>
<%@ taglib prefix="s" uri="/struts-tags"%>Values in session:<s:property value="#Session ['sessiontestkey '] "/ > < br > get the value in the session through the Api of the Servlet: <% = session. Getattribute (" sessiontestkey ")% >

There are two ways to view values in a session.

Run the test. The example of the result page is as follows:

In order to run and test Action in ordinary Java applications, it is recommended that you use SessionAware to access HttpSession. Because in this way, when running or testing through the main method, you can directly call the setSession method to pass in the simulated session data, and there will be no exception of throwing null pointer in the execute method.

Therefore, it is recommended that you use SessionAware to access HttpSession.

4: Use other packaging interfaces

Similar to SessionAware, you can use RequestAware to obtain the Map that wraps the value in the attribute of the request object; Use ApplicationAware to obtain the Map that wraps the value in the attribute of the ServletContext object; Use ParameterAware to obtain the Map that wraps the values in the parameters of the request object. Here, only these common and commonly used are listed. For more information, please refer to the API documentation of struts 2.

7.4.2 ServletActionContext
In practical application development, is it enough to obtain data alone? The answer is obviously No. sometimes, according to the functional needs, the Servlet related API must be available in the Action, such as operating cookies. At this time, you need to use ServletActionContext.

1: ServletActionContext overview

This class directly inherits ActionContext and, of course, many functions of its parent class, such as access to OgnlValueStack, Action name, etc. More importantly, it also provides the function of directly accessing the related objects of the Servlet. The objects it can obtain are:

HttpServletRequest: request object
HttpServletResponse: response object
ServletContext: Servlet context information
PageContext: Http page context

2: Basic use

Directly use the static method of ServletActionContext to obtain the corresponding object. Examples are as follows:

java code:

HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
ServletContext servletContext = ServletActionContext.getServletContext();
PageContext pageContext = ServletActionContext.getPageContext();
HttpSession session = ServletActionContext.getRequest().getSession();
HttpServletRequest request = ServletActionContext.getRequest();HttpServletResponse response = ServletActionContext.getResponse();ServletContext servletContext = ServletActionContext.getServletContext();PageContext pageContext = ServletActionContext.getPageContext();HttpSession session = ServletActionContext.getRequest().getSession();

It should be noted here that the acquisition of HttpSession object is to obtain the session object through the HttpRequest object after obtaining the HttpRequest object. Of course, after obtaining the corresponding objects, we can directly use the methods of these objects for development, which will not be repeated here.

3: Obtain the corresponding Servlet object through IoC/DI

You can also obtain the corresponding Servlet object through IoC/DI. The corresponding relationship is:

ServletRequestAware: get the HttpServletRequest object through this interface
ServletResponseAware: get the HttpServletResponse object through this interface
Use ServletRequestAware as an example.

(1) Modify the Action to implement the ServletRequestAware interface. The example code is as follows:

java code:

public class OgnlAction extends ActionSupportimplements ServletRequestAware{
	private HttpServletRequest request = null;
	public void setServletRequest(HttpServletRequest request) {
	this.request = request;
}
public String execute()
{
	request.setAttribute("request", "Request Attribute value of");
	request.getSession().setAttribute("sessionTestKey", "test SessionAware");
	return this.SUCCESS;
}
	


public class OgnlAction extends ActionSupport implements ServletRequestAware{ private HttpServletRequest request = null; public void setServletRequest(HttpServletRequest request) { this.request = request; } public String execute(){ request.setAttribute("request", "Request Attribute value of"); request.getSession().setAttribute("sessionTestKey", "test SessionAware"); return this.SUCCESS; } }

(2) The corresponding result page also needs to be slightly modified to display the value set in the Action. An example is as follows:

java code:

<%@ taglib prefix="s" uri="/struts-tags"%>
Request Attribute value of:<s:property value="#request['request']"/>
<br>
Property value of the session:<s:property value="#session['sessionTestKey']"/>
<%@ taglib prefix="s" uri="/struts-tags"%>Request Attribute value of:<s:property value="#request['request']"/><br>Property value of the session:<s:property value="#session['sessionTestKey']"/>

(3) Run the test, and the result page should be as follows:

Figure 7.7 result page using ServletRequestAware

Of course, you can also use ServletResponseAware in the same way, which will not be repeated here.

7.4.3 ActionContext and ServletActionContext
According to the previous description, you will find that ActionContext and ServletActionContext have some duplicate functions. They can obtain the data of Web objects, but they are somewhat different.

Generally, it can be considered as follows: ActionContext is mainly responsible for the operation of values; ServletActionContext is mainly responsible for obtaining Servlet objects.

So how to choose in Action? The proposed principles are:

ActionContext is preferred
ServletActionContext is used only when ActionContext cannot meet the functional requirements
In short, we should try to make Action irrelevant to the Web, which is extremely beneficial to the testing and reuse of Action.

Another point to note: when using ActionContext, do not use ActionContext in the constructor of Action Getcontext(), because some values in ActionContext may not be set at this time, and the value obtained through ActionContext may be null.

Keywords: Java J2EE

Added by salhzmzm on Tue, 01 Feb 2022 23:49:37 +0200