天天看點

幾個 Context 上下文的差別

在 java 中, 常見的 Context 有很多, 

 像: ServletContext, ActionContext, ServletActionContext, ApplicationContext, PageContext, SessionContext ...

 那麼, Context 究竟是什麼東西呢? 直譯是上下文、環境的意思。比如像: "今天我收到了一束花, 男朋友送的!" 又或者 "今天我收到了一束花, 送花的人送錯了的!"

 同樣是收到一束花, 在不同的上下文環境中表達的意義是不一樣的。

 同樣的, Context 其實也是一樣, 它離不開所在的上下文環境, 否則就是斷章取義了。

 另外, 在網絡上也有些人把 Context 看成是一些公用資訊或者把它看做是一個容器的, 個人覺得這種解釋稍好。

 接下來說說 ServletContext, ActionContext, ServletActionContext。

 1> ServletContext

 一個 WEB 運用程式隻有一個 ServletContext 執行個體, 它是在容器(包括 JBoss, Tomcat 等)完全啟動 WEB 項目之前被建立, 生命周期伴随整個 WEB 運用。

 當在編寫一個 Servlet 類的時候, 首先是要去繼承一個抽象類 HttpServlet, 然後可以直接通過 getServletContext() 方法來獲得 ServletContext 對象。

 這是因為 HttpServlet 類中實作了 ServletConfig 接口, 而 ServletConfig 接口中維護了一個 ServletContext 的對象的引用。

 利用 ServletContext 能夠獲得 WEB 運用的配置資訊, 實作在多個 Servlet 之間共享資料等。

 eg:

<?
 xml version="1.0" encoding="UTF-8"
 ?>
 

   
 <
 context-param
 >
 
     
 <
 param-name
 >
 url
 </
 param-name
 >
 
     
 <
 param-value
 >
 jdbc:oracle:thin:@localhost:1521:ORC
 </
 param-value
 >
 
   
 </
 context-param
 >
 
   
 <
 context-param
 >
 
     
 <
 param-name
 >
 username
 </
 param-name
 >
 
     
 <
 param-value
 >
 scott
 </
 param-value
 >
 
   
 </
 context-param
 >
 
   
 <
 context-param
 >
 
     
 <
 param-name
 >
 password
 </
 param-name
 >
 
     
 <
 param-value
 >
 tigger
 </
 param-value
 >
 
   
 </
 context-param
 >
 
   
   
 <
 servlet
 >
 
     
 <
 servlet-name
 >
 ConnectionServlet
 </
 servlet-name
 >
 
     
 <
 servlet-class
 >
 net.yeah.fancydeepin.servlet.ConnectionServlet
 </
 servlet-class
 >
 
   
 </
 servlet
 >
 
   
 <
 servlet-mapping
 >
 
     
 <
 servlet-name
 >
 ConnectionServlet
 </
 servlet-name
 >
 
     
 <
 url-pattern
 >
 /ConnectionServlet.action
 </
 url-pattern
 >
 
   
 </
 servlet-mapping
 >
 
   
   
 <
 servlet
 >
 
     
 <
 servlet-name
 >
 PrepareConnectionServlet
 </
 servlet-name
 >
 
     
 <
 servlet-class
 >
 net.yeah.fancydeepin.servlet.PrepareConnectionServlet
 </
 servlet-class
 >
 
   
 </
 servlet
 >
 
   
 <
 servlet-mapping
 >
 
     
 <
 servlet-name
 >
 PrepareConnectionServlet
 </
 servlet-name
 >
 
     
 <
 url-pattern
 >
 /PrepareConnectionServlet.action
 </
 url-pattern
 >
 
   
 </
 servlet-mapping
 >
 


 </
 web-app
 >      

package

 net.yeah.fancydeepin.servlet;

import

 java.io.IOException;

import

 javax.servlet.ServletContext;

import

 javax.servlet.ServletException;

import

 javax.servlet.http.HttpServlet;

import

 javax.servlet.http.HttpServletRequest;

import

 javax.servlet.http.HttpServletResponse;

public
  
 class
  PrepareConnectionServlet 
 extends
  HttpServlet {

     
 private
  
 static
  
 final
  
 long
  serialVersionUID 
 =
  
 1L
 ;

     
 public
  
 void
  init() 
 throws
  ServletException {
         
         ServletContext context 
 =
  getServletContext();
         String url 
 =
  context.getInitParameter(
 "
 url
 "
 );
         String username 
 =
  context.getInitParameter(
 "
 username
 "
 );
         String password 
 =
  context.getInitParameter(
 "
 password
 "
 );
         context.setAttribute(
 "
 url
 "
 , url);
         context.setAttribute(
 "
 username
 "
 , username);
         context.setAttribute(
 "
 password
 "
 , password);
     }

     
 protected
  
 void
  doGet(HttpServletRequest request,HttpServletResponse response)
 throws
  ServletException,IOException{
         
         doPost(request, response);
     }

     
 protected
  
 void
  doPost(HttpServletRequest request, HttpServletResponse response) 
 throws
  ServletException, IOException {
         
         response.sendRedirect(
 "
 ConnectionServlet.action
 "
 );
     }
 }

    
  
 
  

 package
  net.yeah.fancydeepin.servlet;


 import
  java.io.IOException;

 import
  javax.servlet.ServletContext;

 import
  javax.servlet.ServletException;

 import
  javax.servlet.ServletRequest;

 import
  javax.servlet.ServletResponse;

 import
  javax.servlet.http.HttpServlet;


 public
  
 class
  ConnectionServlet 
 extends
  HttpServlet {

     
 private
  
 static
  
 final
  
 long
  serialVersionUID 
 =
  
 1L
 ;

     
 public
  
 void
  service(ServletRequest request, ServletResponse response) 
 throws
  ServletException, IOException {
         
         ServletContext context 
 =
  getServletContext();
         System.out.println(
 "
 ***************************************
 "
 );
         System.out.println(
 "
 URL: 
 "
  
 +
  context.getAttribute(
 "
 url
 "
 ));
         System.out.println(
 "
 Username: 
 "
  
 +
  context.getAttribute(
 "
 username
 "
 ));
         System.out.println(
 "
 Password: 
 "
  
 +
  context.getAttribute(
 "
 password
 "
 ));
         System.out.println(
 "
 ***************************************
 "
 );
         
 super
 .service(request, response);
     }
 }
    
  
  當通路 PrepareConnectionServlet.action 時, 背景列印輸出:
   
  
 ***********************************************
 URL:  jdbc:oracle:thin:@localhost:1521:ORC
 Username:  scott
 Password:  tigger
 ***********************************************      

 2> ActionContext

 ActionContext 是目前 Action 執行時的上下文環境, ActionContext 中維護了一些與目前 Action 相關的對象的引用, 

 如: Parameters (參數), Session (會話), ValueStack (值棧), Locale (本地化資訊) 等。

 在 Struts1 時期, Struts1 的 Action 與 Servlet API 和 JSP 技術的耦合度都很緊密, 屬于一個侵入式架構:

public
  ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response){
     
 //
  TODO Auto-generated method stub
 

     
 return
  
 null
 ;
 }      

 到了 Struts2 時期, Struts2 的體系結構與 Struts1 之間存在很大的不同。Struts2 在 Struts1 的基礎上與 WebWork 進行了整合, 成為了一個全新的架構。

 在 Struts2 裡面, 則是通過 WebWork 來将與 Servlet 相關的資料資訊轉換成了與 Servlet API 無關的對象, 即 ActionContext 對象。

 這樣就使得了業務邏輯控制器能夠與 Servlet API 分離開來。另外, 由于 Struts2 的 Action 是每一次使用者請求都産生一個新的執行個體, 是以, 

 ActionContext 不存線上程安全問題, 可以放心使用。

package

 net.yeah.fancydeepin.action;

import

 java.util.Map;

import

 com.opensymphony.xwork2.ActionContext;

import

 com.opensymphony.xwork2.ActionSupport;

import

 com.opensymphony.xwork2.util.ValueStack;

public
  
 class
  ContextAction 
 extends
  ActionSupport {

     
 private
  
 static
  
 final
  
 long
  serialVersionUID 
 =
  
 1L
 ;
     
 private
  String username;
     
 private
  String password;

     
 public
  String execute(){
         
         ActionContext context 
 =
  ActionContext.getContext();
         ValueStack value 
 =
  context.getValueStack();
         value.set(
 "
 username
 "
 , username);
         value.set(
 "
 password
 "
 , password);
         Map
 <
 String, Object
 >
  session 
 =
  context.getSession();
         session.put(
 "
 url
 "
 , 
 "
 http://www.blogjava.net/fancydeepin
 "
 );
         
 return
  SUCCESS;
     }

     
 public
  
 void
  setUsername(String username) {
         
 this
 .username 
 =
  username;
     }

     
 public
  
 void
  setPassword(String password) {
         
 this
 .password 
 =
  password;
     }
 }      

<

s:property 

value

="username"

/><

BR

>

<

s:property 

value

="password"

/><

BR

>

<

s:property 

value

="#session.url"

/><

BR

>

 當通路 context.action 并傳給相應的參數的時候, 在浏覽器中會輸出相應的資訊。

 留意到上面 Struts2 的 Action 中并有沒添加屬性的 getting 方法, 而是手動的将參數值放到值棧(ValueStack)中的, 否則頁面是得不到參數來輸出的。

 3> ServletActionContext

 首先, ServletActionContext 是 ActionContext 的一個子類。ServletActionContext 從名字上來看, 意味着它與 Servlet API 緊密耦合。

 ServletActionContext 的構造子是私有的, 主要是提供了一些靜态的方法, 可以用來擷取: ActionContext, ActionMapping, PageContext, 

 HttpServletRequest, HttpServletResponse, ServletContext, ValueStack, HttpSession 對象的引用。

//
 或 implements ServletRequestAware
 

     HttpServletRequest request 
 =
  ServletActionContext.getRequest();
     
 //
 或 implements ServletResponseAware
 

     HttpServletResponse response 
 =
  ServletActionContext.getResponse();
     
 //
 或 implements SessionAware
 

     HttpSession session 
 =
  request.getSession();
     
 //
 或 implements ServletContextAware
 

     ServletContext context 
 =
  ServletActionContext.getServletContext();
         
     
 return
  SUCCESS;
 }