As we have learned earlier, Actioncontext is the context of action execution, which contains objects that the action needs to use when executing, and we call it the generalized value stack.
Struts2 creates a new actioncontext each time the action is executed, and the properties within the same line thread actioncontext are unique so that the action can be used in multiple threads.
1 : Actioncontext the thread safety
So how does Struts2 ensure thread safety for Actioncontext?
Look at the code for the Actioncontext object, for example:
?
| 1234 |
publicclass ActionContext implements Serializable { static ThreadLocal actionContext = newThreadLocal(); …… } |
Threadlocal, also known as a thread-local variable, provides a copy of the value of a variable for each thread that uses the variable, so that each thread can independently change its own copy without conflicting with the other thread's copy.
The data stored in the actioncontext is stored in this threadlocal attribute, which is only visible in the corresponding current request thread, ensuring that the data is thread-safe.
2 : The map is accessed
Looking back at the program that used Actioncontext to access the data in the session, you will find that the program is actually accessing a map, not a HttpSession object, which is why?
It turns out that the STRUTS2 framework wraps a lot of objects related to the web, such as repackaging the HttpSession object into a map object that holds the data from the session, providing this map to the action, Instead of dealing directly with the underlying httpsession. It is also because of the framework wrapper that the action can be fully decoupled from the Web layer.
Note, however, that Actioncontext cannot be used in normal Java applications.
In previous studies, it was explained that the action and Servlet APIs are decoupled, so you can call the Execute method of the action in a Java application to test it. But if you use Actioncontext to get session data, you can't run this way. Because Actioncontext wraps the data in the Web, when running in a Java application , there is no web environment and no response data, and thus throws a null pointer exception.
The value of accessing other Web objects is similar to this, and all you have to access through Actioncontext is the post-packaged map.
3 : Using Sessionaware Interface
STRUTS2 also provides an easy way to use the Sessionaware interface to access data stored in Actioncontext, which uses Ioc/di to inject a session Map into the action. You can use this map directly in the program to manipulate the data.
(1) In action, you no longer need to access actioncontext, instead, the action implements the Sessionaware interface, which tells Struts2 to set the session MAP before the action executes. is achieved through the ServletConfig interceptor, which is found in the Defaultstack. The sample code is as follows:
?
| 123456789101112 |
public class OgnlAction extends ActionSupport implements SessionAware{ private Map<String, Object> session; @Resource public void setSession(Map<String, Object> session) { this.session = session; } public String execute(){ session.put("sessionTestKey", "测试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), which injects the session data through this method
- In the Execute method, the data in the session can be manipulated through this private attribute, noting that the values in this map are also linked to HttpSession.
To be able to run and test the action in a common Java application, it is recommended that you use Sessionaware to access httpsession. Because of this, when running or testing through the main method, you can call the Setsession method directly, passing in the simulated session data, there is no exception that throws a null pointer in the Execute method.
Therefore, we recommend that you use Sessionaware to access the httpsession.
4 : Use other packaging interface
similar to Sessionaware, you can use Requestaware to get a map of the values in the attribute of the wrapper request object. Use Applicationaware to get a map of the values in the attribute that wraps the ServletContext object, use Parameteraware to get a map of the values in the parameters of the wrapper request object, and so on, Here are just a few of the common and common ones, and more see the API documentation for STRUTS2.
In real-world application development, is it enough to get the data alone? The answer is obviously no, and sometimes, depending on the function, you must be able to get the servlet-related APIs in action, such as manipulating cookies. This time, you need to use the servletactioncontext.
1 : Servletactioncontext Overview
This class directly inherits the Actioncontext, and of course inherits many of the functions of its parent class, such as: Access to Ognlvaluestack, action name, and so on. More importantly, it also provides the ability to directly access the relevant objects of the servlet, which can be obtained by:
- HttpServletRequest: Request Object
- HttpServletResponse: Response Object
- Servletcontext:servlet Contextual Information
- Pagecontext:http Page Context
2 : Basic Use
The corresponding object can be obtained by using the static method of Servletactioncontext directly. Examples are as follows:
Java code:?
| 12345 |
HttpServletRequest request = ServletActionContext.getRequest(); HttpServletResponse response = ServletActionContext.getResponse(); ServletContext servletContext = ServletActionContext.getServletContext(); PageContext pageContext = ServletActionContext.getPageContext(); HttpSession session = ServletActionContext.getRequest().getSession(); |
It is important to note that the HttpSession object gets the Session object by HttpRequest object after acquiring the HttpRequest object. Of course, after obtaining the corresponding object, the method of directly using these objects to develop, here is not to repeat.
3 : by Ioc/di the way to get the appropriate servlet Object
The corresponding Servlet object can also be obtained by Ioc/di, and the corresponding relationship is:
- Servletrequestaware: Use this interface to get the HttpServletRequest object
- Servletresponseaware: Use this interface to get the HttpServletResponse object
Use Servletrequestaware to sample.
(1) Modify the action to implement the Servletrequestaware interface, the sample code is as follows:
Java code:
?
| 12345678910111213 |
public class OgnlAction extends ActionSupport implements ServletRequestAware{ private HttpServletRequest request = null; @Resource public void setServletRequest(HttpServletRequest request) { this.request = request; } public String execute(){ request.setAttribute("request", "Request的属性值"); request.getSession().setAttribute("sessionTestKey", "测试SessionAware"); return this.SUCCESS; } } |
Actioncontext and servletactioncontext
According to the previous narration, you will find that Actioncontext and servletactioncontext have some repetitive functions that can get the data of the Web object, but there are some differences.
Generally, it is assumed that Actioncontext is primarily responsible for the operation of values; Servletactioncontext is primarily responsible for obtaining servlet objects.
So how do you decide what to do in action? The Recommended principles are:
- Preferential use of Actioncontext
- Use Servletactioncontext only if Actioncontext is unable to meet functional requirements
In short, try to make the action as web-independent as possible, which is extremely useful for testing and reusing action.
Another point to note: When using Actioncontext, do not use Actioncontext in the action constructor. GetContext (), because some of the values in Actioncontext may not have been set at this time, the value obtained through Actioncontext may be null.
Go Actioncontext and Servletactioncontext