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

Heroku部署JavaWeb WAR包报UnsupportedClassVersionError及404错误

问题修复方案

两个错误为独立原因导致,按优先级逐个修复即可:

1. 修复 java.lang.UnsupportedClassVersionError 错误

错误根因:本地编译WAR包使用的JDK版本高于Heroku运行环境的JRE版本,高版本编译生成的class文件无法在低版本JVM上加载运行。
修复方式二选一即可:

  • 对齐Heroku运行环境版本:在项目根目录新建system.properties配置文件,写入和本地一致的JDK版本,例如本地使用JDK11则写入java.runtime.version=11,使用JDK17则写入java.runtime.version=17,将该文件随WAR包一同提交部署,Heroku会自动安装匹配版本的JDK。
  • 降低本地编译版本:打开Eclipse,右键项目→Properties→Java Compiler,将Compiler compliance level调整为1.8(Heroku默认JDK版本为8),重新打包WAR部署。

2. 修复重复提交返回404错误

该错误由三类问题叠加触发,按以下步骤修复:

2.1 修正Servlet代码缺陷

现有代码存在三处会直接导致请求失败的问题:

  • SQL执行语句写法错误:creado = ps.execute;为非法语法,execute是方法不是属性,需改为ps.executeUpdate()判断插入结果
  • 资源关闭逻辑未做空判断:如果数据库连接初始化失败,ps/con为null时直接调用close()会抛出空指针,直接中断请求
  • 请求转发使用相对路径:未从应用根路径匹配JSP资源,路径拼接异常时会找不到文件
    修正后的完整Servlet核心代码如下:
@WebServlet("/Servlet")
public class Servlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    public Servlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        boolean crear = create(request.getParameter("correo"),request.getParameter("nombre_usuario"),request.getParameter("pass"));
        
        if(crear){
            // 路径前加/,从应用根目录匹配资源,避免相对路径拼接错误
            request.getRequestDispatcher("/correcto.jsp").forward(request, response);
        }else {
            request.getRequestDispatcher("/index.jsp").forward(request, response);
        }
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
    
    public boolean create(String correo, String nombre_usu, String password) {
        boolean creado = false;
        Connection con = null;
        PreparedStatement ps = null;
        try{                        
            Class.forName("com.mysql.cj.jdbc.Driver");
            con = DriverManager.getConnection("jdbc:mysql://XXXXXX","XXXXXXX","XXXXXXXXX");
            String sql = "INSERT INTO usuarios (correo,nombre_usuario,clave) VALUES (?,?,?)";
            ps = con.prepareStatement(sql);
            ps.setString(1, correo);
            ps.setString(2, nombre_usu);
            ps.setString(3, password);
            // 修正SQL执行逻辑,受影响行数大于0即判定插入成功
            creado = ps.executeUpdate() > 0;
        
        } catch (SQLException | ClassNotFoundException e) {
            e.printStackTrace();
        }finally {
            // 增加非空判断,避免空指针异常
            try {
                if(ps != null) ps.close();
                if(con != null) con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return creado;
    }
}

2.2 修正表单提交路径

不要在JSP中硬编码相对路径,通过EL表达式动态获取应用上下文路径,避免部署路径变化时提交地址失效。
将index.jsp中的form标签修改为:

<form action="${pageContext.request.contextPath}/Servlet" method="GET">

2.3 校验包结构与启动配置

  • 确认index.jsp、correcto.jsp放在WAR包根目录(与WEB-INF文件夹同级),不要放在WEB-INF目录内,否则无法被请求转发找到
  • 确认Heroku部署时使用的Tomcat/Webapp Runner版本支持Servlet 3.0+注解(Tomcat7及以上版本支持@WebServlet注解,建议使用Tomcat9及以上稳定版本)
  • 首次报类版本错误时应用实际未启动成功,必须先解决JDK版本匹配问题,保证应用正常启动后再测试业务逻辑,否则所有请求都会返回404

额外排查建议

  • 部署后通过Heroku日志命令查看实时启动日志,优先解决启动阶段抛出的异常,再验证业务逻辑
  • 确认你的MySQL服务对公网开放访问,Heroku平台无法访问内网/本地数据库,若使用云数据库需将Heroku出口IP加入数据库白名单,建议直接使用Heroku平台提供的MySQL插件降低配置成本

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 18:01:03