You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Servlet调用prepareStatement报错conn为null且init()未执行问题

问题根因

this.conn空指针、init()方法未执行的核心原因有两个:

  1. Servlet未被Tomcat正确注册,或重写init方法时违反Servlet生命周期规范,导致初始化逻辑根本没有触发
  2. 初始化阶段的异常被捕获后仅打印栈日志,没有向外抛出,Tomcat无法感知到Servlet初始化失败,仍正常把请求分发到未完成初始化的Servlet实例,最终在执行prepareStatement时触发空指针。
修复步骤
  • 先确认Servlet已完成注册,未注册的类不会被Tomcat识别为Servlet,自然不会执行init、service等生命周期方法。两种注册方式选一个就行:
    • 注解方式(Servlet 3.0及以上支持,配置简单):在RegisterUser类定义上方加@WebServlet注解,指定访问路径:
      @WebServlet("/registerUser")
      public class RegisterUser extends GenericServlet {
          // 类内原有代码保持不变
      }
      
    • web.xml配置方式:在项目的WEB-INF/web.xml文件中添加如下配置:
      <servlet>
          <servlet-name>RegisterUser</servlet-name>
          <servlet-class>login_registration.RegisterUser</servlet-class>
          <!-- 加load-on-startup配置后,Tomcat启动时就会初始化Servlet,不用等第一次请求才触发init -->
          <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
          <servlet-name>RegisterUser</servlet-name>
          <url-pattern>/registerUser</url-pattern>
      </servlet-mapping>
      
  • 修正init方法的写法,严格遵循Servlet规范。GenericServlet的init方法有两个重载,重写时不要破坏父类的初始化逻辑:
    优先选无参init重写方案,不需要手动调用super,GenericServlet内部的带参init方法会自动调用这个无参方法,不会出现初始化流程断裂的问题:
    @Override
    public void init() throws ServletException {
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "c##jdbc_practice",
                    "Oracle123");
        } catch (ClassNotFoundException | SQLException e) {
            // 初始化失败直接抛出ServletException,让Tomcat感知初始化异常,禁止吞掉异常只打日志
            throw new ServletException("数据库连接初始化失败", e);
        }
    }
    
    如果要重写带ServletConfig参数的init方法,必须在方法第一行调用父类的初始化方法,否则会导致Servlet配置加载失败:
    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config); // 这行必须保留,否则初始化流程断裂
        // 后续数据库连接初始化逻辑和上述无参init中的代码一致
    }
    
  • 修复service方法里的HTML语法错误,把写错的闭合标签</hi改成</h1>,避免返回的页面渲染异常。
  • 长期优化建议:不要把Connection定义为Servlet的实例变量长期持有。Servlet是单例多线程模型,所有并发请求会共用同一个数据库连接,很容易出现请求数据错乱、连接意外断开后无法自动恢复的问题。后续请使用数据库连接池(如HikariCP、Druid)管理连接,每次请求处理时从连接池获取连接,用完立刻归还。
验证方式

改完代码后重新打包部署到Tomcat,第一次访问对应注册路径时,Tomcat会自动触发init方法完成数据库连接初始化,可以在init方法里临时加一行打印System.out.println("init执行完成,连接状态:" + (conn != null));,确认控制台打印连接为true后,再测试注册数据写入逻辑。

内容的提问来源于stack exchange,提问作者Sai Siddanth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 12:24:23