隨著J2EE進入5.0時代後,J2SE5.0的很多特性也被廣泛應用在J2EE程序中。而J2SE5.0的注釋(Annotations)特性就是其中應用最廣泛的特性之一。
在以前的J2EE版本中,都是使用大量的配置文件來設置Web程序、EJB等。但這一切在J2SE5.0中得到了徹底的改善。在J2EE5.0的注釋中的一些是專門針對Web和EJB程序的。如@Resource, @EJB和@WebServiceRef等。其它的一些注釋,如@RunAs和@DeclareRoles則和安全相關。
雖然我們可以在不同的Web應用組件(Class類)中使用注釋,但卻不能在JSP中使用注釋。不過我們也不用感到遺憾。雖然無法在JSP中使用注釋,但Web庫卻支持注釋。這就意味著我們可以在Servlet過濾器和標簽(Tag)庫或是其它使用Class的地方使用注釋。下面將列舉幾種注釋在J2EE5.0中的應用。
一、在Servlet中使用注釋
首先讓我們來看看如何在Servlet中使用注釋。在本文的例子中,servlet使用一個本地的接口SlessLocal調用了一個企業Bean(在本例子中是一個無狀態的會話Bean)。Servlet將一個message對象作為一個請求屬性傳入到EJB中,並定向到一個JSP頁:display.jsp中。為了演示這一過程,下面是servlet的主要代碼:
@DeclareRoles({"arole"})
@RunAs("myrole")
public class TestServlet extends HttpServlet {
private @EJB SlessLocal slessLocal;
public void service(
HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (req.isUserInRole("arole")) {
String message = slessLocal.hello("World");
req.setAttribute("EJB_MESSAGE", message);
}
RequestDispatcher rd =
req.getRequestDispatcher("display.jsp");
rd.forward(req, resp);
}
}
從上面的代碼可以看到,@EJB注釋被用來使用適當的接口查詢企業Bean,這些Bean最終將被Servlet調用。@DeclareRoles注釋定義了被HttpServletRequest.isUserInRole(String role)使用的角色。isUserInRole方法確定了當前用戶是否是被指定的角色。在本例中的角色中只有一個用戶“arole”將使Servlet獲得“message”字符串,並將其賦給HttpServletRequest屬性。
@RunAs注釋指定了角色"myrole"可以訪問企業Bean方法SlessLocal.hello(String message)。
二、在企業Bean中使用注釋
下面是上述的無狀態企業Bean的主要代碼:
@Stateless
@Local({SlessLocal.class})
public class SlessBean implements SlessLocal {
@RolesAllowed(value={"myrole"})
public String hello(String message) {
return "Hello, " + message + ", " + new Date();
}
}
從上面的代碼我們可以注意到hello方法通過使用@RolesAllowed注釋被保護了起。這個注釋指定了只有用戶"myrole"才能訪問hello方法。
三、在JSP和標簽庫中使用注釋
在顯示業display.jsp中,調用了JSP標簽庫中的一個動作,並將屬性EJB_MESSAGE作為一個參數傳入HttpServletRequest。下面是display.jsp的部分代碼:
<%@taglib prefix="di"
uri="http://java.sun.com/techtip/webann/test-taglib"%>
...
<di:displayInfo ejbMessage="${requestScope.EJB_MESSAGE}"/>
...
上面所使用的標簽將從ejbMessage參數中讀取值,並將這個值顯示在HTML中。而且它會這數據源打印出登錄超時。下面是標簽處理類似部分代碼:
public class DisplayInfoTagHandler extends SimpleTagSupport {
private @Resource(name="jdbc/__default") DataSource ds;
...
public void doTag() throws JspException, IOException {
try {
JspWriter out = getJspContext().getOut();
int timeout = ds.getLoginTimeout();
if (ejbMessage != null && ejbMessage.length() > 0)
{
out.println(
"<li> Ejb Message: " + ejbMessage);
}
out.println(
"<li> DataSource login timeout: " + timeout);
...
}
public void setEjbMessage(String ejbMessage) {
this.ejbMessage = ejbMessage;
}
}
上面代碼中的@Resource注釋在標簽類中使用JNDI"jdbc/__default"來查詢DataSource。這個JNDI名對應於默認的數據庫。如果我們想訪問數據庫連接,可以在tag處理類中加入ds.getConnection()。