首页 > 解决方案 > 尝试在 Head First Servlets 和 JSP 中重现示例时出现 NullPointerException

问题描述

我正在重现 Head First Servlets 和 JSP Ch.5 中的示例,该示例展示了 Servlet 上下文侦听器的工作原理。实现书中的代码后,我得到了NullPonterException.

servlet [ListenerTester] 在路径 [/ServletContextListenerPractice] 的上下文中的 Servlet.service() 引发异常 java.lang.NullPointerException

查了好几遍,肯定和书上的代码是一样的,除了文件路径。我设置了文件路径,就像com.example.web本书使用com.example. 任何人都知道问题是什么?

ListenerTester.java

package com.example.web;

import java.io.*;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;

/**
 * Servlet implementation class ListenerTester
 */
@WebServlet("/ListenerTester")
public class ListenerTester extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    public ListenerTester() {
        super();
        // TODO Auto-generated constructor stub
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        response.setContentType("text/html");
        PrintWriter out = response.getWriter();

        out.println("test context attributes set by listener<br>");
        out.println("<br>");

        Dog dog = (Dog) getServletContext().getAttribute("dog");

        // render brand name to client
        out.println("The brand is " + dog.getBreed());
    }

}

狗.java

package com.example.web;

public class Dog {

    private String breed;

    public Dog(String breed) {
        this.breed = breed;
    }

    public String getBreed() {
        return breed;
    }
}

MyServletContextListener.java

package com.example.web;

import javax.servlet.*;

public class MyServletContextListener implements ServletContextListener {
    public void contextInitilized(ServletContextEvent event) {
        ServletContext sc = event.getServletContext();
        String dogBreed = sc.getInitParameter("breed");

        Dog d = new Dog(dogBreed);

        // set Dog reference, d, as attribute on Servlet Context
        sc.setAttribute("dog", d);
    }

    public void contextDestroyed(ServletContextEvent event) {
        // do nothing
    }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<servlet>
    <servlet-name>ListenerTester</servlet-name>
    <servlet-class>com.example.web.ListenerTester</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>ListenerTester</servlet-name>
    <url-pattern>/ListenTest.do</url-pattern>
</servlet-mapping>

<context-param>
    <param-name>breed</param-name>
    <param-value>Beta</param-value>
</context-param>

<listener>
    <listener-class>
        com.example.web.MyServletContextListener
    </listener-class>
</listener>

</web-app>

标签: javaservlets

解决方案


您拼写错误contextInitialized,但编译器并不介意,因为您没有告诉它您打算覆盖超类中的方法,ServletContextListener. 如果您添加@Override注释来告诉编译器您的意图,它将验证您实际上是在覆盖超类方法。

public class MyServletContextListener implements ServletContextListener {
    @Override    // this one gives a compiler error because it doesn't override anything
    public void contextInitilized(ServletContextEvent event) {
        // . . .
    }

    @Override    // this one doesn't complain because it does override a method
    public void contextInitialized(ServletContextEvent event) {
        // . . .
    }

    // this one compiles just fine, even though the name is spelled wrong
    public void contextInitilized(ServletContextEvent event) {
        // . . .
    }

    public void contextDestroyed(ServletContextEvent event) {
        // do nothing
    }
}

拥有一个名为contextInitilized;的新方法是完全合法的。它也是完全没用的,不会做你所期望的。


推荐阅读