開發過程中,有些「詭異」問題實則是配置缺失或命名規範不當導致。本文匯總兩個高頻坑點及解決方案,助你快速定位、避免踩坑。
JSP 頁面寫入 `${errorMsg}`,瀏覽器顯示為字面文本 `${errorMsg}`,而非後台傳遞的值。
在 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>
| 層級 | 配置 | 優先級 |
|---|---|---|
| 頁面級 | `<%@ page isELIgnored="true/false" %>` | 最高 |
| 應用級 | `web.xml` 中 ` | 中 |
| 容器預設 | Servlet 版本 ≥ 2.4 啟用,≤ 2.3 禁用 | 最低 |
實體類命名為 `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")`。
// 原寫法 (易出錯)
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"); // 別名不影響
類別 衝突名稱 原因
Java 核心 Member, Class, Object, String, System, Thread, Package, Module java.lang 包核心類/介面
反射/註解 Annotation, Parameter, Type, WildcardType, AnnotatedElement java.lang.reflect / java.lang.annotation
集合/流 List, Set, Map, Stream, Optional, Collector java.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);
}
四、總結
- EL 失效:頁面頂部加 `<%@ page isELIgnored="false" %>`,升級 `web.xml` Servlet 版本至 4.0+。
- Hibernate 命名衝突:堅決避免 使用 `Member`、`Class`、`Order` 等 Java 核心類/介面名或 SQL 保留字作為實體類名。首選業務語義清晰的名稱 (如 `SysMember`、`UserAccount`)。
- 異常處理:建立分層異常體系,統一攔截,返回標準化錯誤碼與訊息,避免堆棧追蹤洩露給前端。
規範命名、正確配置、分層異常處理,是構建穩健 Java Web 應用的基石。