遇到Datasource& amp;多URL应用程序中的会话交叉引用

时间:2013-11-27 05:28:08

标签: java servlets jdbc tomcat6 jndi

我有一个应用程序,它被配置为根据具有唯一凭据的URL连接到特定数据库 -

例如 -

  1. demo.mydomain.com(数据库名称 - 演示)
  2. client1.mydomain.com(DB Name - client1)
  3. client2.mydomain.com(数据库名称 - 客户端2)
  4. 我在web-inf目录中的context.xml中定义了数据源,如下所示 -

    <!-- demo Environment Configuration Starts  -->
    
    <Resource type="javax.sql.DataSource"
                name="jdbc/demo" 
                driverClassName="com.mysql.jdbc.Driver"
                url="jdbc:mysql://localhost:3306/demo"
                username="demo" 
                password="demo" 
                initialSize="10"
                maxActive="100" 
                maxIdle="30" 
                minIdle="0"
                suspectTimeout="60"
                timeBetweenEvictionRunsMillis="30000"
                minEvictableIdleTimeMillis="60000"
               />
    
    <!-- Client1 Environment Configuration Starts   -->
    
    <Resource type="javax.sql.DataSource"
                name="jdbc/client1" 
                driverClassName="com.mysql.jdbc.Driver"
                url="jdbc:mysql://localhost:3306/client1"
                username="client1" 
                password="client1" 
                initialSize="10"
                maxActive="100" 
                maxIdle="30" 
                minIdle="0"
                suspectTimeout="60"
                timeBetweenEvictionRunsMillis="30000"
                minEvictableIdleTimeMillis="60000"
                />
    

    所有可用客户的名单都在继续。

    SysServlet在web.xml中定义,带有URL映射 -

    <servlet>
        <servlet-name>SysInfo</servlet-name>
        <servlet-class>com.emsproject.action.common.SysServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>SysInfo</servlet-name>
        <url-pattern>/eapp/*</url-pattern>
    </servlet-mapping>
    

    public class SysServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet{
    static final long serialVersionUID = 1L;
    private static DataSource dataSource;
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        try {
            String clientName = request.getPathInfo();
            String esmPool = clientName.substring(1, clientName.length()).trim();
            /******************************************************
             * Below code prepares the datasource by JNDI lookup * 
             ******************************************************/
            dataSource = (DataSource) new InitialContext().lookup("java:/comp/env/jdbc/"+esmPool);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /*Returns a connection */
    public Connection getConnection() throws Exception {
        return dataSource.getConnection();
    }
    
    /*Closing connection when transaction is over*/
    public void freeConnection(Connection dbConn) {
        try { 
            if(null != dbConn){
                dbConn.close();
            }
        } catch (SQLException e){
            e.printStackTrace();
        }
    }
    

    }

    应用程序使用 -

    构建
    1. Struts 2
    2. MySql 5
    3. Tomcat 6
    4. 应用程序一次正常运行,但没有任何问题 我面临的问题如下 -

      1. 当client1执行某些插入/更新时,它会反映到client2&amp;等等,当他们同时访问应用程序时。

      2. 当Client1执行登录时(我会在会话中保留某些详细信息)&amp;稍后Client2登录系统,Client2信息被共享或对client1可见。

      3. 同时访问让我很烦恼 请建议我解决同样的问题....


        我在获取连接时对代码进行了一些更改 -

        public Connection getConnection(String clientName) throws Exception {
            DataSource dataSource = (DataSource) new InitialContext().lookup("java:/comp/env/jdbc/"+clientName);
            return dataSource.getConnection();
        } 
        

        但我对该声明有一个担忧 -

        DataSource dataSource = (DataSource) new InitialContext().lookup("java:/comp/env/jdbc/"+clientName);
        

        每次我需要连接时都可以初始化DataSource ......

        请建议......

4 个答案:

答案 0 :(得分:0)

每次需要连接时,您在技术上不会初始化DataSource。您每次都在JNDI上下文中查找DataSource。每个DataSource只会有一个实例。

查找非常快(基本上只是一个地图查找),所以我个人不会太担心。

创建InitialContext会慢得多。 InitialContext()的创建速度很慢,只能在您的应用程序中执行一次并缓存。

答案 1 :(得分:0)

@Pace

我正在添加它作为更好地格式化我修改的帖子中的代码的答案,

ctx抛出一个空指针........(我不知道缓存InitialContext)

public class SysServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet{
    static final long serialVersionUID = 1L;

    //Context ctx = null;
    InitialContext ctx = null;



    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        try {
            ctx = new InitialContext();
            String clientName = request.getPathInfo();
            String esmPool = clientName.substring(1, clientName.length()).trim();
            } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*Returns a connection */
    public Connection getConnection(String clientName) throws Exception {
        DataSource dataSource = (DataSource) ctx.lookup ("java:/comp/env/jdbc/"+clientName);
        return dataSource.getConnection();
    }     
    /*Closing connection when transaction is over*/
    public void freeConnection(Connection dbConn) {
        try { 
            if(null != dbConn){
                dbConn.close();
            }
        } catch (SQLException e){
            e.printStackTrace();
        }
    }

我需要sugestions以避免在每个getConnection();

上执行新的InitialContext()

答案 2 :(得分:0)

我做了一些更改,每次登录时只初始化一次Context&amp;这似乎工作正常.... 只需要改变

InitialContext ctx = null;

private static InitialContext ctx = null;

答案 3 :(得分:0)

在Servlet的对象构造期间构建InitialContext:

public class SysServlet ....{
    private InitialContext ctx = new InitialContext();
    ....
}

之后,您可以在getConnection()中进行查找,它应该可以正常工作。