Struts2中ServletActionContext.getServletContext().getRealPath("/")空指針


准備工作:xwork源碼一份(我的版本是2.0.4)。

 

1.當時我是這么建立這個類的

 

Java代碼    收藏代碼
  1. public class StaticAction extends ActionSupport {  
  2.     static {  
  3.         logDir = ServletActionContext.getServletContext().getRealPath("/"); //在這里打個斷點  
  4.     }  
  5.   
  6. }  

 

2.在com.opensymphony.xwork2.DefaultActionInvocation 類下大約第362行

 

Java代碼    收藏代碼
  1. private void init() throws Exception {  
  2.         Map contextMap = createContextMap();  
  3.   
  4.         createAction(contextMap); //在這個方法打個斷點,該方法會去創建你所調用的Action。詳情可以看看它里面的objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap);這一句  
  5.   
  6.         if (pushAction) {  
  7.             stack.push(action);  
  8.         }  
  9.   
  10.         invocationContext = new ActionContext(contextMap); //注意你所調用的Action,它的ActionContext在這里才會創建。  
  11.         invocationContext.setName(proxy.getActionName());  
  12.   
  13.         // get a new List so we don't get problems with the iterator if someone changes the list  
  14.         List interceptorList = new ArrayList(proxy.getConfig().getInterceptors());  
  15.         interceptors = interceptorList.iterator();  
  16.     }  

 

 

好了。調試運行。因為StaticAction有靜態代碼塊,而objectFactory在創建action實例時,使用的是Class.forName(String cls)方式,它的具體實現如下:

 

Java代碼    收藏代碼
  1. java.lang.Class.java  
  2.   
  3.     public static Class<?> forName(String className)   
  4.                 throws ClassNotFoundException {  
  5.         return forName0(className, true, ClassLoader.getCallerClassLoader());  
  6.     }  

 

 

 

看到forName0的第二個參數設置為true了嗎?表示該類被JVM裝載后,要不要立即初始化,如果設置成false,表示在將初始化的工作推遲到了newInstance的時候進行.所以,當方法createAction(contextMap)被調用時,要執行的StaticAction的靜態代碼塊肯定會被調用的。


當運行到ServletActionContext.getServletContext().getRealPath("/")這一句時,繼續查看ServletActionContext.getServletContext()的來源:


org.apache.struts2.ServletActionContext.java 大概第137行

 

 

Java代碼    收藏代碼
  1. public static ServletContext getServletContext() {  
  2.     return (ServletContext) ActionContext.getContext().get(SERVLET_CONTEXT);  
  3. }  

 

可以看到其實調用的是ActionContext.getContext().get(SERVLET_CONTEXT);過來的,而咱們在最開始也看到了createAction(contextMap);方法在 invocationContext = new ActionContext(contextMap); 方法執行之前,是無法正常得到SERVLET_CONTEXT的,所以,就會出空指針異常了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM