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

J2EE 5.0 中註解驅動開發全面解析

     編輯:Java 相關知識

前言

J2EE 5.0 (Java EE 5) 引入 JSR 175 (Metadata Annotations) 與 JSR 250 (Common Annotations),徹底改變了「部署描述符至上」的配置模式。@Resource、@EJB、@WebServiceRef 等註解讓依賴注入、安全聲明、服務引用直接寫在 Java 類上,大幅減少 XML 配置。本文深度解析 Servlet、EJB、JSP Tag Handler 三大場景的註解實戰應用。

核心註解速查表

註解作用目標主要屬性說明
@Resource類、欄位、方法name, type, authentication, shareable, mappedName注入資料源、JMS、環境項目等資源
@EJB類、欄位、方法name, beanInterface, beanName, mappedName, description注入 Session Bean (Local/Remote)
@WebServiceRef類、欄位、方法name, type, wsdlLocation, value注入 Web Service 客戶端
@DeclareRoles類value (String[])聲明 Servlet/EJB 使用的角色
@RolesAllowed類、方法value (String[])指定可訪問的角色 (EJB 專用)
@RunAs類value (String)指定執行身份角色 (傳播給 EJB)
@PermitAll / @DenyAll方法無允許/拒絕所有角色訪問

場景一:Servlet 中注入 EJB 與安全聲明

@DeclareRoles({"arole"})           // 聲明 Servlet 使用的角色
@RunAs("myrole")                    // 呼叫 EJB 時傳播的角色
public class TestServlet extends HttpServlet {
    
    @EJB                            // 自動查找實現 SlessLocal 的 Stateless Bean
    private SlessLocal slessLocal;
    
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        
        // 程式化安全檢查
        if (req.isUserInRole("arole")) {
            String message = slessLocal.hello("World");
            req.setAttribute("EJB_MESSAGE", message);
        }
        
        req.getRequestDispatcher("display.jsp").forward(req, resp);
    }
}

關鍵機制

  1. @EJB 注入:容器根據欄位類型 SlessLocal 自動綁定對應 Bean,無需 JNDI 查找代碼
  2. @DeclareRoles:讓 isUserInRole("arole") 生效,否則永遠返回 false
  3. @RunAs("myrole"):Servlet 以 myrole 身份呼叫 EJB,滿足 EJB 端 @RolesAllowed("myrole") 檢查

場景二:無狀態 Session Bean 實現與授權

@Stateless                          // 聲明為無狀態會話 Bean
@Local({SlessLocal.class})          // 暴露本地介面
public class SlessBean implements SlessLocal {
    
    @RolesAllowed({"myrole"})       // 僅允許 myrole 角色調用
    public String hello(String message) {
        return "Hello, " + message + ", " + new Date();
    }
}

容器部署時自動生成 JNDI 名稱 (如 java:module/SlessBean),Servlet 端 @EJB 即可精準匹配。

場景三:JSP Tag Handler 中注入資料源

限制:JSP 頁面本身不支援註解 (JSP 2.1+ 僅支援 @taglib 等指令),但 Tag Handler 類是普通 Java 類,完全支援註解注入。

public class DisplayInfoTagHandler extends SimpleTagSupport {
    
    @Resource(name = "jdbc/__default")  // JNDI 名稱對應資料源
    private DataSource ds;
    
    private String ejbMessage;
    
    public void doTag() throws JspException, IOException {
        JspWriter out = getJspContext().getOut();
        
        try {
            // 使用注入的資料源
            int timeout = ds.getLoginTimeout();
            
            if (ejbMessage != null && !ejbMessage.isEmpty()) {
                out.println("<li> Ejb Message: " + ejbMessage);
            }
            out.println("<li> DataSource login timeout: " + timeout);
        } catch (SQLException e) {
            throw new JspException("DB error", e);
        }
    }
    
    public void setEjbMessage(String ejbMessage) {
        this.ejbMessage = ejbMessage;
    }
}

JSP 頁面調用

<%@ taglib prefix="di" uri="https://example.com/tags" %>
<di:displayInfo ejbMessage="${requestScope.EJB_MESSAGE}" />

註解 vs XML:共存與覆蓋規則

配置項註解優先級web.xml/ejb-jar.xml 覆蓋
資源注入 (@Resource/@EJB)預設值XML 覆蓋註解
安全角色 (@RolesAllowed)預設值XML 覆蓋註解
Servlet 映射不支援 (需 @WebServlet Servlet 3.0+)XML 唯一途徑 (Servlet 2.5)

最佳實踐:基礎配置用註解 (類內聚合),環境差異 (JNDI 名稱、安全角色映射) 用 XML 覆蓋,實現「開發期零配置、部署期靈活調整」。

進階:攔截器與生命週期註解 (EJB 3.0)

@Stateless
public class AuditedBean {
    
    @PostConstruct
    public void init() { /* 初始化資源 */ }
    
    @PreDestroy
    public void cleanup() { /* 釋放資源 */ }
    
    @AroundInvoke
    public Object audit(InvocationContext ctx) throws Exception {
        long start = System.currentTimeMillis();
        try { return ctx.proceed(); }
        finally { 
            System.out.println(ctx.getMethod() + " took " + (System.currentTimeMillis() - start) + "ms");
        }
    }
    
    @PostActivate
    public void activate() { /* 狀態 Bean 活化 */ }
    
    @PrePassivate
    public void passivate() { /* 狀態 Bean 鈍化 */ }
}

遷移建議與現代視角

  1. Java EE 5/6 專案:全面拥抱註解,僅在環境差異處保留 XML
  2. Spring 生態:@Autowired、@Value、@PostConstruct 等提供更豐富功能,但標準註解 (javax.annotation.*) 保證可移植性
  3. Jakarta EE 9+:包名遷移至 jakarta.annotation.*,升級時需批量替換 import
  4. MicroProfile:@ConfigProperty、@Health、@Metrics 擴展雲原生能力

總結

J2EE 5.0 註解標準化了依賴注入、安全授權、生命週期管理等核心關注點,讓開發者從龐雜的 XML 描述符中解脫。掌握 @Resource/@EJB/@WebServiceRef 注入模式、@DeclareRoles/@RolesAllowed/@RunAs 安全傳播鏈、Tag Handler 註解注入技巧,即可在標準 Java EE 容器中構建清晰、可維護、可移植的企業級應用。

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