2015-12-28 75 views
0

當我在學習how to use JNDI resources in Tomcat 7時,已經建立了一個自定義的bean工廠,名爲MyBeanFactory。它爲我的Web應用程序提供外部資源。我們第一次假設它提供了當前的系統時間戳。爲什麼JNDI資源只能在Tomcat中調用一次?

但是,我意識到MyBeanFactory僅在第一次請求時才被調用一次。在第一次執行後,似乎javabean MyBean已經存儲在Tomcat中。然後MyBean被每個請求重用。無論何時我在瀏覽器中保存URL,響應總是顯示與第一個相同的時間戳。我這裏還有元素的列表,可以幫助:

  • 爲myBean:由MyBeanFactory
  • MyBeanFactory提供的豆:工廠實施javax.naming.spi.ObjectFactory
  • 的context.xml:上下文描述符資源,位於META-INF文件夾中
  • web.xml:部署描述符
  • MyAction:在HTTP Servlet中
  • 控制檯

有人能告訴我爲什麼MyBeanFactory只調用一次,如果它有可能改變這個功能嗎?因爲我需要修改工廠來建立與服務器中的另一個進程的套接字。見How to serve a socket from a Java EE application?


爲myBean

public class MyBean { 

    private String foo = "Default Foo"; 
    private long bar = 0; 

    public String getFoo() { return (this.foo); } 
    public void setFoo(String foo) { this.foo = foo; }  
    public long getBar() { return (this.bar); } 
    public void setBar(long bar) { this.bar = bar; } 

} 

MyBeanFactory

public class MyBeanFactory implements ObjectFactory { 

    @Override 
    public Object getObjectInstance(Object obj, Name name, Context nameCtx, 
      Hashtable<?, ?> environment) throws NamingException { 
     System.out.println("MyBeanFactory starts"); 
     MyBean bean = new MyBean(); 
     bean.setBar(System.currentTimeMillis()); 
     // Return the customized instance 
     return bean; 

    } 
} 

的context.xml

<?xml version="1.0" encoding="UTF-8"?> 
<Context 
    path="/jndi" 
    reloadable="true" 
    cachingAllowed="false" 
    antiResourceLocking="true"> 

    <Resource 
    name="bean/MyBeanFactory" 
    auth="Container" 
    type="com.mycompany.MyBean" 
    factory="com.mycompany.MyBeanFactory" 
    bar="23"/> 

</Context> 

的web.xml

<?xml version="1.0" encoding="UTF-8"?> 
<web-app 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 
    id="WebApp_ID" 
    version="3.1"> 

    <display-name>jndi</display-name> 
    <welcome-file-list> 
    <welcome-file>index.html</welcome-file> 
    </welcome-file-list> 
    <servlet> 
    <servlet-name>action</servlet-name> 
    <servlet-class>com.mycompany.MyAction</servlet-class> 
    <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
    <servlet-name>action</servlet-name> 
    <url-pattern>*.action</url-pattern> 
    </servlet-mapping> 
    <!-- 
     Apache Tomcat 7: JNDI Resources HOW-TO 
     https://tomcat.apache.org/tomcat-7.0-doc/jndi-resources-howto.html 
    --> 
    <resource-env-ref> 
    <description> 
     Object factory for MyBean instances. 
    </description> 
    <resource-env-ref-name> 
     bean/MyBeanFactory 
    </resource-env-ref-name> 
    <resource-env-ref-type> 
     com.mycompany.MyBean 
    </resource-env-ref-type> 
    </resource-env-ref> 
</web-app> 

MyAction

public class MyAction extends HttpServlet { 

    // ... 

    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException { 
     System.out.println("doGet"); 
     response.getWriter() 
      .append("Hello coming from ") 
      .append(request.getRequestURI()); 

     Context initCtx = null; 
     try { 
      System.out.println("initCtx"); 
      initCtx = new InitialContext(); 
     } catch (NamingException e) { 
      e.printStackTrace(); 
     } 

     Context envCtx = null; 
     try { 
      System.out.println("envCtx"); 
      envCtx = (Context) initCtx.lookup("java:comp/env"); 
     } catch (NamingException e) { 
      e.printStackTrace(); 
     } 

     MyBean bean; 
     try { 
      System.out.println("lookup"); 
      bean = (MyBean) envCtx.lookup("bean/MyBeanFactory"); 
      response.getWriter() 
       .append("foo = " + bean.getFoo() + ", ") 
       .append("bar = " + bean.getBar() + ";"); 
     } catch (NamingException e) { 
      e.printStackTrace(); 
     } 
     System.out.println("------"); 
    } 
} 

控制檯

Dec 28, 2015 7:41:03 PM org.apache.catalina.startup.Catalina start 
INFO: Server startup in 412 ms 
doGet 
initCtx 
envCtx 
lookup 
MyBeanFactory starts // called only once 
------ 
doGet 
initCtx 
envCtx 
lookup 
------ 
doGet 
initCtx 
envCtx 
lookup 
------ 
+0

由於您正在定義一個servlet上下文資源,因此期望給定的上下文將只有一個實例似乎是合理的。上下文資源的全部要點是要共享的。這就是說,通過引用Tomcat 7,您已經拋棄了我,但使用了該版本的Tomcat沒有記錄的配置屬性。你實際使用哪個版本? –

+0

@JohnBollinger我使用的是tomcat 8.0.21 –

回答

2

<Resource>元件你本具有超出documented by Tomcat 8的屬性,特別是「工廠」和「酒吧」。但是,也許從文檔中錯誤地忽略了前一個屬性,因爲一些示例使用它。

無論如何,我想提請您注意「單身」屬性。當該屬性的值爲true(默認值)時,該資源被視爲單例,其中單個實例由上下文維護並在所有用戶之間共享。這似乎是你描述的行爲。如果您將該屬性添加到您的聲明中,值爲false,那麼每次查找該資源都應該檢索一個新實例。

相關問題