Java servlet中的JNDI查找';s init参数是个好主意吗?

Java servlet中的JNDI查找';s init参数是个好主意吗?,java,performance,jakarta-ee,jdbc,jndi,Java,Performance,Jakarta Ee,Jdbc,Jndi,我目前正在构建一个JavaEEWeb应用程序,并找到了一篇文章,它为我提供了一些关于如何构建更好的应用程序的很好的指导。第一个技巧是“使用HttpServlet init()方法缓存数据”。这听起来像一个天才的想法,但现在我已经实现了自己的版本,我担心线程安全和保持连接打开 这个想法和我实现它的方式是线程安全的,以确保每个线程都有自己的db连接吗 我知道,每当我想要改变JNDI查找时,这需要重新启动servlet,我对此没有意见,但是不只是在JDBC方法中执行JNDI查找还有其他缺点吗 我使用d

我目前正在构建一个JavaEEWeb应用程序,并找到了一篇文章,它为我提供了一些关于如何构建更好的应用程序的很好的指导。第一个技巧是“使用HttpServlet init()方法缓存数据”。这听起来像一个天才的想法,但现在我已经实现了自己的版本,我担心线程安全和保持连接打开

  • 这个想法和我实现它的方式是线程安全的,以确保每个线程都有自己的db连接吗
  • 我知道,每当我想要改变JNDI查找时,这需要重新启动servlet,我对此没有意见,但是不只是在JDBC方法中执行JNDI查找还有其他缺点吗
  • 我使用destroy方法来关闭上下文变量的方式是一个聪明的想法吗?或者,如果有大量线程或任何其他障碍,这会不会不起作用
  • 下面是一些代码,让您了解我是如何实现这个想法的。在我在我的40个其他servlet上实现之前,我只想获得一些关于我的第一个实现的指导。非常感谢你的阅读。哦,如果有帮助的话,我也可以添加dao方法

    Servlet注释:在init中,我只调用一个bean,该bean执行所有JNDI工作,使之更容易添加到多个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) {}
        }
    }
    
    每个线程都有自己的数据源引用。您的servlet将是多个请求线程中的一个实例,每个线程调用
    doGet()
    。相反,
    init()
    只在web模块启动时,在servlet实例服务请求之前被调用

    另一个技巧-在一次查找中检索容器管理的资源是很常见的

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

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

    感谢您查看我的问题。要明确的是,我所做的很好(线程安全),我可以用您给出的示例来缩短代码,使其更加清晰。但是我所做的不应该导致问题,对吗?在我的web应用程序的整个生命周期(直到下一次重新启动)中都打开这些查找也可以吗?我没有预见到任何问题。如果您查看使用注入(通过@Resource)获取容器管理的资源(如数据源实例)的教程,它们通常是成员或类级别(静态)变量,因此可以在请求之间共享。只需确保始终从共享数据源获得.close()连接。