Spring / 休眠 - NullPointerException

Spring / Hibernate - NullPointerException

我对 Spring (MVC) 和 Hibernate 完全陌生,我正在努力学习它。

我编造了以下身份验证场景来练习,但我运气不太好。

场景:

我有一个 HTML 表单 (homepageForm.jsp),可以将用户名和密码发送到 HomeController。 HomeController 获取表单参数 (username/password) 并将表单参数与从数据库中检索到的用户名和密码进行比较。

如果匹配,将向用户显示 dashboard.jsp。如果不匹配,将加载 error.jsp。

数据库中的信息由 "UserRetrievalService" 检索。

我收到以下错误:

::::: 错误

    type Exception report

    message Request processing failed; nested exception is java.lang.NullPointerException

    description The server encountered an internal error that prevented it from fulfilling this request.

    exception
    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
        org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)


    root cause
    java.lang.NullPointerException
        com.springdemo.mvc.HomeController.processLoginForm(HomeController.java:91)
        sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

我怀疑这与引用 servlet.xml 的方式有关。 HomeController 中的第 91 行是这一行:

User user = userRetrievalService.getUser();

或者我没有正确使用@Autowired。

任何人都可以给我一些解决此问题的提示吗?

谢谢!

这里有一些关于该项目的附加信息。

**** servlet.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc.xsd">

        <context:component-scan base-package="com.springdemo.mvc" />
        <context:component-scan base-package="com.springdemo.model" />

        <mvc:annotation-driven/>

        <bean
            class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/view/" />
            <property name="suffix" value=".jsp" />
        </bean>

    </beans>

**** 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_3_1.xsd" id="WebApp_ID" version="3.1">
      <display-name>spring-mvc-demo</display-name>
      <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
    </web-app>

**** homepageForm.jsp

    <html>
    <head>
    <title>Homepage Form</title>
    </head>

    <body>
        <form action="processLogin" method="POST">
            <div>
                <label>Username</label> <input type="text" name="username" placeholder="username" />
            </div>
            <div>
                <label>Password</label> <input type="text" name="password" placeholder="password" />
            </div>
            <input type="submit" value="Login" />
        </form>
    </body>

    </html>

**** User.java

    package com.springdemo.model;

    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;

    @Entity
    @Table(name = "user")
    public class User implements AbstractUser {

        @Id
        @Column(name = "id")
        private int id;

        @Column(name = "username")
        private String username;

        @Column(name = "password")
        private String password;

        @Column(name = "first_name")
        private String firstname;

        @Column(name = "last_name")
        private String lastname;

        @Column(name = "email")
        private String email;

        public User() {

        }

        public User(int id, String username, String password, String firstname, String lastname, String email) {
            super();
            this.id = id;
            this.username = username;
            this.password = password;
            this.firstname = firstname;
            this.lastname = lastname;
            this.email = email;
        }

        + getters & setters

    }

**** 用户服务

    public interface UserService {

        public User getUser();
    }

**** 用户检索服务

    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    import org.springframework.stereotype.Component;

    @Component
    public class UserRetrievalService implements UserService {

        @Override
        public User getUser() {

            System.out.println("UserRetrievalService called...");

            Configuration config = new Configuration().configure("hibernate.cfg.xml");
            config.addAnnotatedClass(User.class);

            SessionFactory sessionFactory = config.buildSessionFactory();

            // create a session
            Session session = sessionFactory.getCurrentSession();

            try {

                // start trans
                session.beginTransaction();

                // get & create user
                User user = session.get(User.class, 1);

                // commit trans
                session.getTransaction().commit();

                System.out.println("UserRetrievalService : commit successful...");

                System.out.println(" >>>> USER: " + user.getId() + " " + user.getUsername() + " " + user.getPassword() + " " + user.getFirstname() + " " + user.getLastname());

                return user;

            } finally {
                sessionFactory.close();
            }

        }

    }

**** HomeController.java

    import javax.servlet.http.HttpServletRequest;

    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.servlet.ModelAndView;

    import com.springdemo.model.User;
    import com.springdemo.model.UserRetrievalService;

    @Controller
    public class HomeController { 

    ...
    private UserRetrievalService userRetrievalService;

    @Autowired
    public UserRetrievalService getUserRetrievalService() {
        return userRetrievalService;
    }

    @RequestMapping("/processLogin")
    public ModelAndView processLoginForm(HttpServletRequest request) {

        String username = request.getParameter("username");
        String password = request.getParameter("password");

        System.out.println("username : " + username);
        System.out.println("password : " + password);

        User user = userRetrievalService.getUser();

        ModelAndView modelAndView;

        if (username.equalsIgnoreCase(user.getUsername()) && (password.equalsIgnoreCase(user.getPassword()))) {
            modelAndView = new ModelAndView("dashboard"); // page to be returned
        } else {
            modelAndView = new ModelAndView("error"); // page to be returned
        }

        // System.out.println("success: user id = " + user.getId());

        modelAndView.addObject("myUser", user);

        return modelAndView;
    }
    ...
    }

::::: hibernate.cfg.xml

    <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

    <hibernate-configuration>

        <session-factory>

            <!-- JDBC Database connection settings -->
            <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="connection.url">jdbc:mysql://localhost:3306/springtestdb?useSSL=false</property>
            <property name="connection.username">*****</property>
            <property name="connection.password">*****</property>

            <!-- JDBC connection pool settings ... using built-in test pool -->
            <property name="connection.pool_size">1</property>

            <!-- Select our SQL dialect -->
            <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

            <!-- Echo the SQL to stdout -->
            <property name="show_sql">true</property>

            <!-- Set the current session context -->
            <property name="current_session_context_class">thread</property>

        </session-factory>

    </hibernate-configuration>

根据 Autowired 的 Javadoc,注释可用于 "a constructor, field, setter method or config method"。在 HomeController 中,在服务字段中放置 Autowired 注释。

@Autowired 
private UserRetrievalService userRetrievalService;

您的 UserRetrievalService 未正确注入。

您可以使用@Autowired 或Constructor/Setter 注入。在你的情况下,你使用了 setter 注入但不是以正确的方式

应该是

私有 UserRetrievalService userRetrievalService;

@Autowired
public UserRetrievalService setUserRetrievalService(UserRetrievalService userRetrievalService) {
    this.userRetrievalService = userRetrievalService;
}

关于休眠配置的建议。

您需要将 hibernate.cfg.xml 保留在类路径下

因为你的是maven项目,理想的地方是/src/main/resources/

请参阅 以了解更多信息。