ClassLoader.getSystemClassLoader().getResourceAsStream() возвращает null в сервлете?

#tomcat8 #servlet-3.0

#tomcat8 #Сервлет-3.0

Вопрос:

Мой вопрос может быть очень расплывчатым. Позвольте мне подробнее остановиться на этом. Структура каталогов моего проекта (в IntelliJ IDEA):

 Server/--------------------------Module
      src/
          java/-----------------------------------classpath directory
              com.example.demo/
                               HelloServlet.java   ------a servlet respons
                               TestCode.java       ------a servlet that responds to network requests
                               Utils.java          ------a class to test by junit
          resources/------------------------------classpath directory
                    hello.txt------------------------------------------ "hello word" writed in this file
 

В Utils.java , у меня есть следующий код:

 public class Utils {
    private static BufferedReader reader = null;
    static{
        try {
            InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("hello.txt");
            reader = new BufferedReader(new InputStreamReader(is));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static String getString() throws IOException {
        return reader.readLine();
    }
}
 

В TestCode.java :

 public class TestCode {
    @Test
    public void test() throws IOException {
        System.out.println(Utils.getString());
    }
}
 

Когда я запускаю метод test(), я получаю следующий вывод на консоль:

 Hello World
 

Таким образом, все в порядке, но что-то не так в сервлете.
У HelloServlet.java меня есть следующий код:

 @WebServlet(name = "helloServlet", value = "/hello-servlet")
public class HelloServlet extends HttpServlet {
    private String message;

    public void init() {
        message = "init() has invoked.";
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        response.setContentType("text/html");
        //NullPointerException throws
        message = Utils.getString();
        PrintWriter out = response.getWriter();
        out.println("<html><body>");
        out.println("<h1>"   message   "</h1>");
        out.println("</body></html>");
    }

    public void destroy() {
    }
}
 

Когда я вызываю Utils.getString() в методе doGet() и отправляю запрос GET с помощью chrome.Тогда сервлет выдаст исключение NullPointerException.

 java.lang.NullPointerException
    at java.io.Reader.<init>(Reader.java:78)
    at java.io.InputStreamReader.<init>(InputStreamReader.java:72)
    at com.example.demo.Utils.<clinit>(Utils.java:17)
    at com.example.demo.HelloServlet.doGet(HelloServlet.java:20)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
 

НО когда я делаю некоторые изменения, Utils.java как показано ниже:

  private static BufferedReader reader = null;
    static{
        try {
            //use getClassLoader() instead of getSystemClassLoader()
            InputStream is = Utils.class.getClassLoader().getResourceAsStream("hello.txt");
            reader = new BufferedReader(new InputStreamReader(is));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static String getString() throws IOException {
        return reader.readLine();
    }
 

Затем я отправляю запрос GET с помощью Chrome. «Привет, мир» будет напечатано в браузере.
Когда я обновляю веб-сайт (или снова запрашиваю сервлет), возникает второй вопрос о том, что будет напечатано значение null.
Почему? Может кто-нибудь ответить на мой вопрос? Спасибо

Комментарии:

1. вы можете попробовать с помощью : this.getClass().getClassLoader().getResourceAsStream()

Ответ №1:

Apache Tomcat 8 использует несколько загрузчиков классов: https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html .

Если вы хотите сделать реализацию вашего кода независимой, используйте следующий фрагмент:

ClassLoader = request.getSession().getServletContext().getClassLoader()

Вы получите надежный способ получить «загрузчик классов веб-приложения, представленного этим ServletContext», в соответствии с документами JavaEE.