2010年8月16日 星期一

[Struts2]-OGNL存取ActionContext內非Value Stack內之物件

參考前一篇[Struts2]-實作Interceptor
result頁面可以利用OGNL語法從ActionContext的ValueStack中取得欄位物件
<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>

<html>
<head>
<title>Hello World</title>
</head>
<body>
<h2><s:property value="message"/></h2>
</body>
</html>
此時property tag中的value屬性就是利用OGNL語法從hello action中取得message field。
因為當action處理完後欄位資料後會將欄位物件置於ActionContext的ValueStack中,
此時的前端頁面就是利用OGNL從ValueStack中取出相對應的欄位值。

在ActionContext中,除了ValueStack內的物件外還有其它的scope物件可以存取,
如下圖:


 名称作用例子
parameters包含當前HTTP請求參數的Map#parameters.id[0]作用相當於request.getParameter("id")
request包含當前HttpServletRequest的屬性(attribute)的Map#request.userName相當於request.getAttribute("object name")
session包含當前HttpSession的屬性(attribute)的Map#session.userName相當於session.getAttribute("object name")
application包含當前應用的ServletContext的屬性(attribute)的Map#application.userName相當於application.getAttribute("object name")
attr用於按request > session > application順序訪問其屬性(attribute)#attr.userName相當於按顺序在以上三個範圍(scope)内讀取object name屬性,直到找到為止

接下來我們實際編寫一個action(OgnlAction.java)來存取這些scope物件。
package example;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsStatics;

public class OgnlAction extends ActionSupport {

  private ActionContext actionContext;
  private Map application;
  private Map session;
  private Map parameters;
  private HttpServletRequest request;
  private HttpServletResponse response;

  @Override
  public String execute() {
    actionContext = ActionContext.getContext();
    application = actionContext.getApplication();
    session = actionContext.getSession();
    parameters = actionContext.getParameters();

    request = (HttpServletRequest) actionContext.get(StrutsStatics.HTTP_REQUEST);
    //private HttpServletRequest request = ServletActionContext.getRequest();
    response = (HttpServletResponse) actionContext.get(StrutsStatics.HTTP_RESPONSE);

    application.put("message", "message from application");
    session.put("message", "message from session");
    parameters.put("message", "message from parameters");
    request.setAttribute("message", "message from request");
    return SUCCESS;
  }
}

我們可以利用ActionContext類別來取得這些scope物件,
另外也能使用ServletActionContext這個輔助類別來取得
HttpServletRequest、HttpServletResponse 。
這裡要注意的是,ActionContext物件必須要在execute method內取得,
如果在method外初始的話,此時內部的application等scope物件都還是null。

接下來編寫一個Ognl.jsp來當做前端頁面。
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Struts OGNL Demo</title>
</head>
<body>
<h3>訪問ActionContext物件</h3>
<p>parameters: <s:property value="#parameters.message" /></p>
<p>request.message: <s:property value="#request.message" /></p>
<p>session.message: <s:property value="#session.message" /></p>
<p>application.message: <s:property value="#application.message" /></p>
<p>attr.message: <s:property value="#attr.message" /></p>
<hr/>
</body>
</html>
這裡可以發現,OGNL預設就是取得ValueStack內的物件,如果要取得其它的scope物件,
前面則要加上#符號。

最後是struts.xml的設定
<struts>
<package name="example" namespace="/example" extends="struts-default">
<action name="Ognl" class="example.OgnlAction">
<result name="success">/example/Ognl.jsp</result>
</action>
</package>
</struts>
輸入連結後/example/Ognl.actiont可以看到下面的結果:
除了parameters外其餘的結果都如我們預料,
筆者猜測也許parameters是取得當前http request的參值,
無法事後更動。

當我們直接在請求頁面的連結後加入參數時,就正常了。

沒有留言:

張貼留言