在servlet的init参数中查找JNDI是一个好主意吗?

时间:2013-04-14 01:29:15

标签: java performance java-ee jdbc jndi

我目前正在构建一个Java EE Web应用程序,并找到了this文章,它给了我一些关于如何构建更好的应用程序的重要指示。第一个提示是“使用HttpServlet init()方法缓存数据”。这听起来像是一个天才的想法,但现在我已经实现了我自己的版本,我害怕线程安全,并保持连接打开。

  1. 这个想法,以及我实现它的方式线程安全,以确保每个线程都有自己的数据库连接?
  2. 我知道这需要servlet重新启动,我想改变JNDI查找,我很好,但是还有任何其他缺点,不仅仅是在JDBC方法中进行JNDI查找吗?
  3. 我使用destroy方法关闭上下文变量的方式是一个聪明的想法,还是不适用于丰富的线程或任何其他障碍?
  4. 这里有一些代码可以让您了解我是如何实现这个想法的。在我对其他40个servlet实现这个之前,我只想对我的第一个实现提供一些指导。非常感谢您的阅读。哦,我也可以添加dao方法,如果这会有所帮助。

    Servlet注释:在init中,我只需调用一个执行所有JNDI漏洞的bean,以便更容易添加到多个servlet中。然后在servelt中我将数据源发送到要使用的dao方法。我还认为在启动时添加负载是明智的,这样我就可以看到JNDI在启动服务器时是否正常工作。

    @WebServlet(name="GetBoardPostCommenters", urlPatterns={"/getBoardPostCommenters"}, loadOnStartup = 1)
    public class GetBoardPostCommenters extends HttpServlet
    {
        private InstrideJndi jndi = null;
        private static final long serialVersionUID = 1L;
    
        public void init(ServletConfig servletConfig) throws ServletException
        {
            super.init(servletConfig);
            jndi = new InstrideJndi("GetBoardPostCommenters");
        }
    
        public void destroy()
        {
            jndi.closeConnection();
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
        {
            BoardPost boardPost;
    
            boardPost = new BoardPost();
            boardPost.setId(Long.parseLong(request.getParameter("boardPostId")));
            boardPost = BoardPostCommentLikeDAO.getBoardPostCommenters(boardPost, jndi.getDataSource());
    
            request.setAttribute("likerCommenterList", boardPost.getCommenterList());
            request.getRequestDispatcher("WEB-INF/util/likerCommenterList.jsp").forward(request, response);
        }
    }
    

    Bean注意:控制器获取调用此方法的servlet的名称以帮助调试。紧密连接完成了我通常在dao方法的最后做的事情。

    public class InstrideJndi
    {
        private DataSource dataSource = null;
        private Context initialContext = null;
        private Context environmentContext = null;
    
        public InstrideJndi(String className)
        {
            try
            {
                this.initialContext = new InitialContext();
                this.environmentContext = (Context) initialContext.lookup("java:/comp/env");
                this.dataSource = (DataSource) environmentContext.lookup("jdbc/instride");
            }
            catch(NamingException error)
            {
                System.out.println("Error With JNDI Lookup -  " + className + " - " + error.getMessage());
                error.printStackTrace();
            }
        }
    
        public DataSource getDataSource()
        {
            return this.dataSource;
        }
    
        public void closeConnection()
        {
            if (initialContext != null) try{initialContext.close();} catch(NamingException ignore) {}
            if (environmentContext != null) try{environmentContext.close();} catch(NamingException ignore) {}
        }
    }
    

1 个答案:

答案 0 :(得分:2)

每个帖子 在这里拥有自己的DataSource引用。您的servlet将是每个调用doGet()的许多请求线程中的一个实例。相反,init()仅在servlet实例处理请求之前在Web模块启动时被调用。

另一个提示 - 在一次查找中检索容器管理的资源是相当常见的。

this.dataSource = new InitialContext().lookup("java:/comp/env/jdbc/instride");

我可能错了,但我通常不会close()这些类型的InitialContext实例,除非我特别期望它是网络操作(ldap,从远程应用程序服务器查找资源等)。