首页 > 解决方案 > Servlet:init() 方法与内联字段初始化

问题描述

我想问一下以下两种初始化Servlet的实现之间的区别。(内联字段初始化和init方法)

public class MyServlet extends HttpServlet {

    private static String FILE_PATH = "/.../.../.../";
    private static String DATE = "date";
    private static DateTimeFormatter FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd");
    private static MyDao DAO = new MyDao();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
        ...   
    }
}

VS。

public class MyServlet extends HttpServlet {

    private static String FILE_PATH;
    private static String DATE;
    private static DateTimeFormatter FORMAT;
    private static MyDao DAO;

 
    @Override
    public void init(){
         FILE_PATH = "/.../.../.../";
         String DATE = "date";
         FORMAT = DateTimeFormatter.ofPattern("yyyyMMdd");
         DAO = new MyDao();
    }
    

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
        ...   
    }
}
  1. Servlet 以任何一种方式初始化时都能正常工作吗?
  2. 首选哪种初始化方法,原因是什么?

先感谢您!

标签: javaservlets

解决方案


我想问一下以下两种初始化Servlet的实现之间的区别。

不同之处在于执行初始化的时间。

在第一个示例中,它由(例如)另一个引用其中一个static字段的类或实例化来触发MyServlet。这种情况只发生一次……在该类的生命周期中。

在第二个示例中,它是由对init()方法的显式调用触发的。这通常也只会发生一次,但它是在框架的直接控制下发生的。

实际上,对于给定的 servlet 类,在某些情况下init()可能会被多次调用。该方法实际上是在创建每个MyServlet 实例后调用的。因此,如果您的 Web 配置为两个不同的 servlet 重用同一个MyServlet类,并且两者都使用同一个类加载器,那么init()将被调用两次。同样,如果 web 容器可以关闭(即销毁)所有 servlet 并使用与以前相同的类加载器重新创建它们,那么init()将被第二次调用。(但请注意,由不同类加载器加载的一个类是不同的运行时类,每个类都有自己的一组静态变量。)


Servlet 以任何一种方式初始化时都能正常工作吗?

这取决于:

  • 之前是否有其他东西可以访问这些静态变量之一init()
  • 实例的构造是否MyDao依赖于已经初始化/配置的其他东西,以及
  • init()多次调用是否有害。

首选哪种初始化方法,原因是什么?

第一个比较简单。越简单越好……如果它满足您的需求。

但是,这不是“二元选择”。您可以以一种方式初始化一些静态,而另一种。例如:

public class MyServlet extends HttpServlet {

    private static final String FILE_PATH = "/.../.../.../";
    private static final String DATE = "date";
    private static final DateTimeFormatter FORMAT = 
            DateTimeFormatter.ofPattern("yyyyMMdd");
    private static MyDao DAO;

 
    @Override
    public void init() {
         MyServlet.DAO = new MyDao();
    }

请注意,(有效)常量的静态变量应尽可能声明final以防止意外更新。即使他们是private

另外,考虑是否DAO真的应该是一个实例变量。


推荐阅读