1、OGNL从ActionContext获取数据
OGNL表达式在JSP页面获取的数据从何处来?
OGLN表达式获取的数据从ActionContext中来,而ValueStack是其中最重要的一个。
在Struts2 framework处理一次http request 请求时,ActionContext中包含了所有需要的数据:application data(应该是指业务数据)、session-scope data和application-scope data。所有的application specific data都存储在ValueStack上。
The ActionContext contains all of the data available to the framework’s processing of the request, including things ranging from application data to session- or application-scoped maps. All of your application specific data, such as properties exposed on your action, will be held in the ValueStack, one of the objects in the ActionContext. |
OGNL表达式是从ActionContext中取值。默认情况下,ValueStack是OGNL直接读取数据的目标,当然也可以从ActionContext中其它的对象中读取数据。
All OGNL expressions must resolve against one of the objects contained in the ActionContext. By default, the ValueStack will be the one chosen for OGNL resolution, but you can specifically name one of the others, such as the session map, if you like. |
ActionContext是Struts2 framework的一个幕后(behind-the-scenes)的重要角色,它表示当前执行的action的context。对于“context”而言,是指一个容器,包含重要数据和资源的容器,容器中的数据和资源用来支持当前action的运行。
The ActionContext is a key behind-the-scenes player in the Struts 2 framework. The ActionContext helps clean things up by providing the notion of a context for the execution of an action. By context we mean a simple container for all the important data and resources that surround the execution of a given action. |
OGNL表达式的target是properties on specific objects。解析OGNL表达式,需要一个root object。
As we’ve seen, OGNL expressions target properties on specific objects. The resolution of each OGNL expression requires a root object against which resolution of references will begin. |
由于OGNL表达式是从ActionContext上获取数据,而ActionContext中包含多个对象,所以在使用OGNL表达式时,应该指明从ActionContext上的哪个对象上去解析OGNL表达式。
Every time you use an OGNL expression, you need to indicate which object the expression should start its resolution against. In Struts 2, each OGNL expression must choose its initial object from those contained in the ActionContext. |
在ActionContext中,最重要的就是ValueStack。ValueStack当中持有application's domain-specific data for a given action invocation.
As you can see, the ActionContext is full of juicy(有魅力的) treasures. The most important of these is the ValueStack. As we’ve said, the ValueStack holds your application’s domain-specific data for a given action invocation. The other objects are all maps of important sets of data. Each of them has a name that indicates its purpose and should be familiar to seasoned Java web application developers, as they correspond to specific concepts from the Servlet API. |
The parameters object is a map of the request parameters associated with the request being processed—the parameters submitted by the form, in other words. The application object is a map of the application attributes. The request and session objects are also maps of request and session attributes. By attribute we mean the Servlet API concept of an attribute. Attributes allow you to store arbitrary objects, associated with a name, in these respective scopes. Objects stored in application scope are accessible to all requests coming to the application. Objects stored in session scope are accessible to all requests of a particular session, and so forth. The attr object is a special map that looks for attributes in the following locations, in sequence: page, request, session, and application scope. |
2、OGNL的root object
SELECTING THE ROOT OBJECT FOR OGNL
在使用OGNL表达式的时候,必须要在ActionContext当中选择一个root object。Struts2 framework将使用这个root object去解析ONGL expression。
Up until now, we’ve hidden the fact that an OGNL expression must choose one of the objects in the ActionContext to use as its root object. So how does the framework choose which object to resolve a given OGNL expression against? |
默认情况下,struts2 framework使用ValueStack作为ONGL的root object。
As with all Struts 2 mysteries, this comes down to a case of intelligent defaults. By default, the ValueStack will serve as the root object for resolving all OGNL expressions that don’t explicitly name an initial object. |
除了ValueStack之外,使用OGNL从ActionContext中获取其它object的property,需要使用#符号。
OGNL expressions can start with a special syntax that names the object from the context against which they should resolve. The following OGNL expression demonstrates this syntax: |
#session['user']
#符号是用来告诉OGNL将当前指定的object作为解析OGNL expresssion的root object。
This OGNL expression actively names the session map from the ActionContext via the # operator of the expression language. The # operator tells OGNL to use the named object, located in its context, as the initial object for resolving the rest of the expression. With Struts 2, the OGNL context is the ActionContext and, thankfully, there’s a session object in that context. This expression then points to whatever object has been stored under the key user in the session object, which happens to be the session scope from the Servlet API. |
3、ValueStack是一个virtual object
The ValueStack: a virtual object
ValueStack是ActionContext中默认的root object。理解ValueStack,是理解Struts2 framework中数据流的关键。
Back to that default root object of the ActionContext. Understanding the ValueStack is critical to understanding the way data moves through the Struts 2 framework. |
当Struts2 framework接收到一个request时,它会立即创建ActionContext、ValueStack和action对象。action对象,作为application data的持有者,会被放置到ValueStack上。
When Struts 2 receives a request, it immediately creates an ActionContext, a ValueStack, and an action object. As a carrier of application data, the action object is quickly placed on the ValueStack so that its properties will be accessible, via OGNL, to the far reaches of the framework. |
通过param interceptor,会将incoming request parameter转移到ValueStack上去。在ValueStack上的所有数据,有一个共同点,就是它们与业务相关。action对象之所以被放到ValueStack上去,是因为action对象是domain data的持有者,而并不是因为它执行了action logic。
First, these will receive the automatic data transfer from the incoming request parameters. As we saw in chapter 4, this occurs because the params interceptor sets those parameters on properties exposed on the ValueStack, upon which the action object sits. While other things, such as the model of the ModelDriven interface, may also be placed on the stack, what all data on the ValueStack has in common is that it’s all specific to the application’s domain. In MVC terms, the ValueStack is the request’s view of the application’s model data. There are no infrastructural objects, such as Servlet API or Struts 2 objects, on the ValueStack. The action is only there because of its role as domain data carrier; it’s not there because of its action logic. |
当解析OGNL expressioin的时候,ValueStack pretends to be a single object。
There’s only one tricky bit about the ValueStack. The ValueStack pretends to be a single object when OGNL expressions are resolved against it. This virtual object contains all the properties of all the objects that’ve been placed on the stack. If multiple occurrences of the same property exist, those lowest down in the stack are hidden by the uppermost occurrence of a similarly named property. |
ValueStack解析OGNL expression的原理。
At present, we just want to see how the ValueStack appears as a single virtual object to the OGNL expressions resolving against it. Behind the scenes, OGNL will resolve each OGNL expressions by asking the ValueStack if it has a property such as, for instance, name. The ValueStack will always return the highest-level occurrence of the name property in its stack of objects. |
With a clear view of where the data is and how to get to it, it’s time to get back to the Struts 2 tags, and they are the means of pulling data from the ActionContext and ValueStack into the dynamic rendering of your view layer pages.