首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java Web 常見異常處理避坑指南:EL 表達式失效、Hibernate 保留字衝突

     編輯:Java 綜合教學

Java Web 常見異常處理避坑指南:EL 表達式失效、Hibernate 保留字衝突

開發過程中,有些「詭異」問題實則是配置缺失或命名規範不當導致。本文匯總兩個高頻坑點及解決方案,助你快速定位、避免踩坑。

一、JSP 中 EL 表達式 `${errorMsg}` 不解析,原樣輸出

現象

JSP 頁面寫入 `${errorMsg}`,瀏覽器顯示為字面文本 `${errorMsg}`,而非後台傳遞的值。

根本原因

  • JSP 2.0+ (Servlet 2.4+) 預設啟用 EL 表達式。
  • 但若專案 `web.xml` 宣告的 Servlet 版本較低 (如 2.3),或頁面頂部缺少關鍵指令,容器會以舊版規則處理,**忽略 EL 表達式**。

解決方案

在 JSP 頁面最頂部添加指令,強制啟用 EL:

<%@ page isELIgnored="false" %>

或在 `web.xml` 中升級 Servlet 版本宣告 (推薦 4.0+):

<web-app xmlns="https://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://xmlns.jcp.org/xml/ns/javaee 
                             https://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    ...
</web-app>

補充:EL 表達式啟用/禁用優先級

層級配置優先級
頁面級`<%@ page isELIgnored="true/false" %>`最高
應用級`web.xml` 中 `true/false` (JSP 2.0)中
容器預設Servlet 版本 ≥ 2.4 啟用,≤ 2.3 禁用最低

二、Hibernate 實體類命名為 `Member` 導致查詢/更新/刪除異常

現象

實體類命名為 `Member`,執行 HQL 查詢、更新、刪除操作時拋出異常,如:

org.hibernate.hql.internal.ast.QuerySyntaxException: 
Member is not mapped [FROM Member]

或運行時錯誤指向 `java.lang.reflect.Member` 介面。

根本原因

HQL 解析器在解析 `FROM Member` 時,優先解析為 Java 反射 API 中的 `java.lang.reflect.Member` 介面,而非你的實體類。這是因為 Hibernate 內部導入了 `java.lang.reflect.*`,且 `Member` 是該包下的核心介面。

解決方案

方案一:重命名實體類 (徹底根治,推薦)

將類名改為非保留字,如 `SysMember`、`UserMember`、`Account`:

// 修改前
@Entity
public class Member { ... }

// 修改後
@Entity
@Table(name = "t_member") // 指定表名,不影響數據庫
public class SysMember { ... }

同步修改 `.hbm.xml` (若用 XML 映射) 或註解中的 `@Entity(name = "SysMember")`。

方案二:HQL 中使用全限定類名
// 原寫法 (易出錯)
Query query = session.createQuery("FROM Member");

// 修正寫法
Query query = session.createQuery("FROM com.example.entity.Member");
// 或
Query query = session.createQuery("FROM Member m WHERE m.id = :id"); // 別名不影響
方案三:使用 Session API 直接操作物件 (繞過 HQL 解析)
    類別衝突名稱原因
    Java 核心Member, Class, Object, String, System, Thread, Package, Modulejava.lang 包核心類/介面
    反射/註解Annotation, Parameter, Type, WildcardType, AnnotatedElementjava.lang.reflect / java.lang.annotation
    集合/流List, Set, Map, Stream, Optional, Collectorjava.util / java.util.stream
    SQL 關鍵字 (表名/列名需轉義)Order, Group, User, Key, Index, Trigger, View, Schema, Table, Column數據庫保留字,需 `@Table(name="`order`")` 或 `@Column(name="`key`")`


三、通用異常處理最佳實踐

1. 統一異常處理器

@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(EntityNotFoundException.class)
    public R handleNotFound(EntityNotFoundException e) {
        log.warn("資源不存在: {}", e.getMessage());
        return R.fail(404, e.getMessage());
    }

    @ExceptionHandler(DataIntegrityViolationException.class)
    public R handleDataIntegrity(DataIntegrityViolationException e) {
        log.error("數據完整性違規", e);
        String msg = e.getMostSpecificCause().getMessage();
        if (msg.contains("Duplicate entry")) {
            return R.fail(409, "數據已存在,請勿重複提交");
        }
        return R.fail(500, "數據操作失敗");
    }

    @ExceptionHandler(Exception.class)
    public R handleAll(Exception e) {
        log.error("系統異常", e);
        return R.fail(500, "服務器內部錯誤");
    }
}

2. 自定義業務異常體系

public class BizException extends RuntimeException {
    private final int code;
    public BizException(int code, String message) { super(message); this.code = code; }
    public int getCode() { return code; }
}

// 使用
throw new BizException(400, "參數校驗失敗");
throw new BizException(403, "權限不足");

3. 參數校驗異常處理

@ExceptionHandler(MethodArgumentNotValidException.class)
public R handleValid(MethodArgumentNotValidException e) {
    String msg = e.getBindingResult().getFieldErrors().stream()
            .map(fe -> fe.getField() + ": " + fe.getDefaultMessage())
            .collect(Collectors.joining("; "));
    return R.fail(400, msg);
}

四、總結

  1. EL 失效:頁面頂部加 `<%@ page isELIgnored="false" %>`,升級 `web.xml` Servlet 版本至 4.0+。
  2. Hibernate 命名衝突:堅決避免 使用 `Member`、`Class`、`Order` 等 Java 核心類/介面名或 SQL 保留字作為實體類名。首選業務語義清晰的名稱 (如 `SysMember`、`UserAccount`)。
  3. 異常處理:建立分層異常體系,統一攔截,返回標準化錯誤碼與訊息,避免堆棧追蹤洩露給前端。

規範命名、正確配置、分層異常處理,是構建穩健 Java Web 應用的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved