My Calendar

2015年2月3日 星期二

getReader() 的用法

getReader() 


在 HTTPServletRequest 中有定義 getReader() 方法,可以讀取一個 BufferedReader 物件。透過這個物件可以讀取請求本體資料。以下有個範例.

1) 首先建立一個HTML表單用來發出請求 (form.html)。Servlet的名稱為body.view

Figure 1.1

2) 準備好HTML後,現在建立一個 Servlet 命名為 body.view.


package com.learn.servlet;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/body.view")
public class BodyServlet extends HttpServlet {
 private static final long serialVersionUID = 1L;
       
    public BodyServlet() {
        super();
    }

 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  String body = readBody(request);
  PrintWriter out = response.getWriter();
  out.println("");
  out.println("");
  out.println("");
  out.println(body);
  out.println("");
  out.println("");
  
 }
 
 private String readBody(HttpServletRequest request) throws IOException{
  BufferedReader reader = request.getReader();
  String input = null;
  String requestBody = "";
  while((input = reader.readLine()) != null)
   requestBody += input + "
";
  
  return requestBody;
 }

}


執行結果如下圖

 
Figure 1.2

2015年1月29日 星期四

HttpServletResponse

HttpServletResponse是Servlet處理好的內容發送到瀏覽器的一個物件.

發送數據到瀏覽器的方法








設定回應標頭的方法



















設定HTTP Status Code的方法






HTTP Status Code

HTTPServletResponse 定義了很多狀態碼













HttpServletResponse常見的應用

1.使用PrintWriter將資料回傳給瀏覽器
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet("/demo")
public class Demo extends HttpServlet {

 private static final long serialVersionUID = -7819316605366593662L;

 public Demo() {
        super(); 
 }

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
  //設定UTF-8編碼
  response.setCharacterEncoding("UTF-8");
  //設定header告訴瀏覽器要以UTF-8的编码显示資料,如果沒有設定,瀏覽器顯示中文字將會出現亂碼
  response.setHeader("content-type", "text/html;charset=UTF-8");
  PrintWriter writer = response.getWriter();
  writer.println("你好");
 }

 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  
 }
}

運行結果如下:










2.檔案下載

在網頁開發中下載檔案大家經常使用到的功能,使用HttpServletResponse就可以實現這個功能。話不多說直接上code.

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet("/demo")
public class Demo extends HttpServlet {

 private static final long serialVersionUID = -7819316605366593662L;

 public Demo() {
    super(); 
 }

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
 { 
   //1.讀取檔案
   File downloadFile = new File("D:\\測試.jpg");
   //2.下載文件的名稱
   String fileName = downloadFile.getName();

   //3.設定content-disposition標頭讓瀏覽器以下载的形式打開文件
   response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8"));
  
   int len;
   InputStream in = new FileInputStream(downloadFile);
   //3.設定緩衝區
   byte[] buffer = new byte[1024];
  
   //4. 透過response物件獲取OutputStream
   OutputStream os = response.getOutputStream();
 
   //5.將FileInputStream寫入到buffer緩衝區;
   while ((len = in.read(buffer)) > 0) {
    //6.使用OutputStream将緩衝區的資料输出到瀏覽器
    os.write(buffer, 0, len);
   }
  
   os.close();
   in.close();
}

P.S: 檔案是中文名稱要使用URLEncoder.encode方法進行編碼,否則會出現檔案名亂會是亂碼。

運行結果如下:



























3. 產生驗證碼.
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet("/demo")
public class Demo extends HttpServlet {

 private static final long serialVersionUID = -7819316605366593662L;

 public Demo() {
    super(); 
 }

 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
  
  //设置refresh標頭讓瀏覽器每3秒钟刷新一次
  response.setHeader("refresh", "3");
  //在記憶體產生一張寬60高20的圖片
  BufferedImage image = new BufferedImage(60, 20, BufferedImage.TYPE_INT_RGB);
  Graphics2D g = (Graphics2D)image.getGraphics();//得到圖片
  g.setColor(Color.WHITE);//设置图片
  g.fillRect(0, 0, 60, 20);//背景顏色填滿
  //3.將一個亂數寫在圖片上
  g.setColor(Color.RED);//設定图片上字體的顏色
  g.setFont(new Font(null, Font.BOLD, 20));
  g.drawString(randomNum(), 0, 20);
     //4.設定標頭头控制瀏覽器以图片的方式打開
  response.setContentType("image/jpeg");
  //5.設定响应头控制浏览器不缓存图片数据
  response.setDateHeader("expries", -1);
  response.setHeader("Cache-Control", "no-cache");
  //6.將图片送出給瀏覽器
  ImageIO.write(image, "jpg", response.getOutputStream());
 }

 private String randomNum()
 {
  Random random = new Random();
  String num = random.nextInt(99999)+"";
  StringBuffer sb = new StringBuffer();
  for (int i = 0; i < 5-num.length(); i++) 
        sb.append("0");
  
  num = sb.toString()+num;
  return num;
 }

運行結果如下:






2015年1月25日 星期日

HttpServletRequest

HttpServletRequest

關於HttpServletRequest
當 Web 容器收到 HTTP 的請求時,容器會自動收集 web.xml@WebServlet 所定義的資訊,並產生 HttpServletRequest 物件,這個物件可以取得HTTP請求中的資訊。可以在 Servlet 中處理請求,或是將請求轉發給另一個 Servlet 進行處理。各個 Servlet/JSP 在同一個請求週期中需要共用資料的時候,可以透過 HttpServletRequest 物件設定 attribute.

處理請求參數和標頭
HttpServletRequest 定義了一些方法可以取得 HTTP 請求的資訊。例如可以使用以下的方法取得請求參數:

1) getParameter() :

指定請求參數的名稱取得值,例如:
             
String userName = request.getParameter("name");

getParameter() 回傳的是 String 物件, 若請求中沒有指定的參數名稱,則會回傳null。

2) getParameterValues() :

當表單上有可以複選的選項,例如 Checkbox, List 等等,同一個參數將會有多個值,這時候可以使用 getParameterValue() 取得一個 String array, array elements 代表所有選項的值。例如 :

String [] params = request.getParameterValue("checkList");

3) getParameterNames() :

如果想知道每一次請求有多少個參數名稱,則可以使用 getParameterNames(), 這會回傳一個 Enumeration 物件,當中包含全部請求參數名稱。例如:

Enumeration  params = request.getParameterNames();
while(param.hasNextElement())
{
   System.out.println("Request Parameter = "+ params.nextElement);
}

4) getParameterMap()

將請求參數以 Map 的形式回傳, Map 中的 Key 是請求參數名稱 Values 是請求參數值,Values 是 String array 的方式回傳因為請求參數值有肯能有多個值。例如:
// get request parameter map
Map  requestParams = request.getParameterMap();

// retrieve parameter name - values pair from parameter map
StringBuilder sb = new StringBuilder();
for (Map.Entry entry : requestParams.entrySet()) 
{
    String key = entry.getKey();         // parameter name
    String[] value = entry.getValue();   // parameter values as array of String
    .....
}

5) getHeader()

如果想獲取 HTTP 的標頭資訊,則用 getHeader() 這回傳一個 String 物件。例如 :

Sting headers - request.getHeader()

6)  getHeaders()

使用方法和 getParameterNames() 一樣

接下來有個範例顯示如何取得 HTTP 標頭資訊 :


package com.learn.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class Header
 */
@WebServlet("/header.view")
public class HeaderServlet extends HttpServlet {
 private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public HeaderServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

 /**
  * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
  */
 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  // TODO Auto-generated method stub
  PrintWriter out = response.getWriter();
  out.println("");
  out.println("");
  out.println("HeaderDemo");
  out.println("
");
  out.println("");
  out.println("HeaderServlet at "+ request.getContextPath()+"
");  // Application environment path
  Enumeration  e = request.getHeaderNames();     //Get all header names
  
  while(e.hasMoreElements())
  {
      String name = e.nextElement();
      out.println(name +" = "+ request.getHeader(name)+"
");
  }
  
  out.println("");
  out.println("");
  out.close();
  
 }

 /**
  * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
  */
 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  // TODO Auto-generated method stub
 }

}


顯示結果如下:


參考資料
  1. Servlet&JSP 教學手冊

2015年1月17日 星期六

使用@WebServlet

使用@WebServlet

       在開始使用@WebServlet之前有個先決條件,那就是要有一個Servlet程式。如果沒有的朋友請到『第一個Servlet程式』這裡有範例程式提供參考。準備好Servlet,接下來就要告訴Web Container這個Servlet的一些資訊。在這當中有兩種方法:
  1. 使用web.xml定義 
  2. 使用@WebServlet (Servlet 3.0以上才支援)

使用web.xml
要使用web.xml需要在Web應用程式中的WEB-INF目錄建立一個web.xml檔案定義Servlet的資訊,相關內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
  http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
 <servlet>
  <servlet-name>HelloServlet</servlet-name>
  <servlet-class>com.learn.servlet.HelloServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name>HelloServlet</servlet-name>
  <url-pattern>/helloUser.view</url-pattern>
 </servlet-mapping>
</web-app>

這樣的檔案稱為部署描述檔(Deployment Descriptor)。使用web.xml定義會比較麻煩,但web.xml中的設定會覆蓋Servlet中的Annotation設定(也就是第二種方法)。那現在透過這個web.xml是如何定義Servlet的資訊。舉例,若有client發出/helloUser.view的請求,那將會由HelloServlet這個Servlet處理,這分別是由<servlet-mapping>中的<url-pattern><servlet-name>定義。

使用@WebServlet
在 Servlet 3.0 中,已經可以使用 Annotation 告知容器哪些 Servlet 會提供服務。例如在一個 Servlet 中:

@WebServlet("/hello.view")
public class HelloServlet extends HttpServlet {
......
}

只要 Servlet 有設定 @WebServlet 屬性,容器就能自動讀取當中的資訊。以上面的例子為例,@WebServlet 告訴容器,如果URL是 /hello.view , 就由 HelloServlet 的實例提供服務。

參考資料
  1. Servlet&JSP 教學手冊

2015年1月1日 星期四

第一個Servlet程式

第一個 Servlet 程式

所謂工欲善其事,必先利其器。所以開始寫我們的第一支Servlet程式之前必須先準備好開發環境。

開發環境設定
1) 下載 Apache Tomcat (因為是用Servlet 3.0以上,所以Tomcat需要7.x 以上才能支援。)
3) 執行eclipse然後選擇 Windows -> Preferences -> Server ->  Runtime Environment。
4) 在Server Runtime Environments 選擇 Add -> Apache Tomcat  v7.0。然後在Tomcat installation       directory中選擇Tomcat的安裝目錄,最後按下Finish這就完成設定如下圖。


設定完成後就開始我們的第一支Servlet程式吧。

第一個Servlet程式
1) 在選單選擇 File->New->Dynamic Web Project.
2) 在Dynamic Web Project 當中的Target Runtime選擇剛才所新建的Server,Dynamic web 
     module version 選擇 3.0如下圖


3) 展開專案中的 Java Resources -> src 新增一個Servlet

接著可以開始寫第一支Servlet程式的內容了,在新增的Servlet加入一下的內容吧。

package com.learn.servlet;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class HelloServlet
 */
@WebServlet("/hello.view")
public class HelloServlet extends HttpServlet {  //繼承 HttpServlet
 private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public HelloServlet() {
        super();
    }

 /**
  * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
  */
 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  response.setContentType("text/html;charset=UTF-8");
  PrintWriter out = response.getWriter();
  String name = request.getParameter("name");
  
  out.println("");
  out.println("");
  out.println("Hellow Servlet");
  out.println("");
  out.println("");
  out.println("

Hello! "+ name +" !

"); out.println(""); out.println(""); out.close(); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }

在以上的範例程式可以看到繼承了 HttpServlet ,然後重新定義 doGet()方法。當瀏覽器發出GET請求時,會呼叫該方法。

在doGet()可以看到兩個參數分別是HttpServletResponse 和 HttpServletRequest。當Web Container 收到HTTP請求後,將會分別建立Request和Response的Java物件,而後在呼叫doGet()時將這兩個物件當成參數傳入。如果需要取得GET或POST請求的參數值,那將透過HttpServletRequestgetParameter()指定參數名稱即可。HttpServletResponse 是response物件,我們可以透過setContentType()設定回傳類型,然後再使用getWriter()取得PrintWriter物件在藉由PrintWriter物件中的println()將HTML回傳給瀏覽器。

執行Servlet
  1. 在『HelloServlet.java』右鍵 Run As -> Run on Server
  2. Tomcat 啟動成功後,你將會看到以下的畫面(恭喜!你的第一個Servlet程式完成了)

                     瀏覽器的網址設定是 http://localhost:8080/FirstServlet/hello.view?name=Eric.

Tomcat預設的port是8080,注意網址的路徑FirstServlet是專案的名稱,為什麼請求的URL是/hello.view呢?請注意看以上的範例程式中有以下一行:

@WebServlet("/hello.view")

這表示,如果請求的URL是/hello.view,就會由HelloServlet處理請求。

參考資料
  1. Servlet&JSP 教學手冊


2014年10月30日 星期四

EJB - Bean Types

EJB - Bean Types

根據上一篇EJB-簡介所提到,EJB根據beans的功用分成三大類分別是session beans, message-driven beansentities

Session Beans
Session bean是為了執行特定商業操作而被client調用,如檢查客戶信用historySession這個名字意味著bean實例存在時間是“每個工作單位”和當伺服器shutdowncrash的時候就會消失。Session bean可以將任何應用程式邏輯模組化。Session bean有兩類分別為: statefulstateless
           Stateful session bean當客戶調用的時候在不需要寫任何多餘的程式碼的狀況下可以自動儲存bean的狀態。比較典型的例子就是網頁商城裡的購物車系統。相反,stateless session bean 不會維護任何狀態和模組應用程式服務。我們可以實作商業流程如信用卡付費或檢查查客戶信用記錄而建立stateless session bean.
           一個session beans不管在本地或遠端都可以透過Java RMI被調用。一個stateless session bean可以公開為網頁服務。

Message-driven Beans
MDBs 就像session beans,都是處理商業邏輯。但MDBs最大的不同是clients永遠不會直接調用MDB method。相反MDBs是透過訊息驅動然後傳給messaging server, 就是在系統元件之間啟動傳送非同步訊息。Messaging servers的典型例子有IBM WebSphere MQSonicMQ Oracle Advance Queueing, TIBCOMDBs通常是使用在系統整合或非同步處理的健全性。上。Messaging的一個例子,從自動零售系統傳送庫存補貨的需求到供應鏈管理系統。

Entities and the Java Persistence API
EJB 3當中其中一個新特色就是處理persistence的方法。之前我們概略的提到persistence 提供者和JPA,現在讓我們更深入到細節。 
         Persistence的能力是將Java objects中包含的data自動儲存到關聯式資料庫像Oracle, SQL Server, DB2Persistence 在 EJB 3是透過JPA管理。它自動的使用Object-relational mapping(ORM)這項技術persists Java objectsORM的本質是透過設定檔在java objects處理mapping data然後儲存到資料表中。它緩解我們寫底層,複雜的JDBC程式碼persist objects到資料庫的工作。
           EJB 3中,persistence provider基本上就是Java Persistence API (JPA)所支援的ORM框架。JPA定義了一些標準:
  •  ORM設定metadata的建立mapping entities relational tables.
  •  EntityManager API – 是一個標準的APIentities執行CRUD persistence operations.
  •  Java Persistence Query Language (JPQL),是用來搜尋和獲取persisted application data.
自從為了Java平台JPA ORM frameworks標準化,我們可以在應用程式plug in ORM 產品如 JBOSS Hibernate,OracleTopLink,或BEA Kodo 做為JPApersistence provider”的底層。

Entities
如果在我們的應用程式採用JPA建立persistence logic,那就必須使用entities. EntitiesJava objects用來persisted到資料庫。就像session beansprocess模組化,entities將低階應用概念包裝成高階商業流程管理。

The EntityManager
JPA EntityManager介面管理entities和提供persistence 服務。Entities會告訴JPA provider如何map資料庫。EntityManager 介面讀取ORM metadataentity和執行persistence. EntityManager知道如何對entities在資料庫中執行CRUDCREATE, RETRIEVE, UPDATE, DELETE)。另外JPA 提供處理lifecycle managementperformance tuningcachingtransaction management的能力。

Java Persistence Query Language
JPA 有提供一個類似SQL的語言稱為Java Persistence Query Language (JPQL) 可以搜尋儲存在資料庫中的entities. 在一個健全和彈性的APIJPQL,我們在選擇自動persistence而不是手寫JDBC是不會遺失任何東西。另外,JPA支援native database-specific SQL, 在一些罕有的案件是這是值得使用。
         在這時候,我們應該對EJB各個部分都有部分的認識。我們也知道需要透過EJB container去執行session beansMDBs persistence provider執行entities,那這些元件都能存取EJB 3所提供的服務。

Reference:

1)EJB 3 in action

2014年10月16日 星期四

EJB - 簡介

EJB – 簡介
         EJB 的全名是Enterprise JavaBeans,簡單來說它是一個平台讓開發人員使用Java語言開發一個portable, reusable 和 scalable 的商業應用程式。自EJB推出的時候就一直宣導它是一個元件模組或框架且可以讓我們在開發商業應用程式時不需要重新開發一些服務例如:transactions, security, automated persistence 等等。EJB允許開發人員在開發應用程式時專注在商業邏輯不需要花費時間在建立基礎架構的程式碼。
        在開發人員的觀點來看,EJB只是一段的Java程式碼執行在一個特別的運行環境稱為 EJB container, 且提供大量的component services.

EJB as a Component
        在這每當提到EJBs時,指的是伺服端components可以用它來構建應用程序的某些部分例如:商業邏輯,persistence code. 很多人往往對 components這個詞聯想到開發一個複雜和重量級的CORBA, Microsoft COM+ 程式碼。但在EJB3.0這個嶄新的世界,component 它只是一個不外乎多了一些特別功能的POJO。更重要的是,這些功能在不需要的時候都是“隱形”,不要分散component真正用途上的注意力。
        Component 背後真正的想法是有效率的封裝應用程式的行為。Component的使用者不需要了解內部如何運作。他們只需要知道傳入什麼和回傳什麼。EJB components 有三種:session beans, message-driven beansentities. Session beansmessage-driven beans 是在EJB應用程式實作商業邏輯,而entities則使用在persistence.
        Component 是可以重複使用。假設現在公司開發一個賣書的網站,設計了一個用信用卡過賬的模組只是簡單的Java物件。然後另一組人又在不同的開發環境當中開發了賣CD的網站,這時候因為開發環境的不同所以不能直接套用之前信用卡的模組,另一組人需要將你整個模組複製到他們的網站才能使用,因為沒有更容易的方法可以存取之前的模組。如果是使用EJB components建立的信用卡模組,這會讓新使用者更簡單的重複使用該模組而不需要知道其內部運作(Figure 1)。

Figure 1


EJB as a Framework
        EJB components 是在container中。Componentscontainer可以看成對商業應用程式開發提供有價值服務的框架。
        雖然很多人認為使用EJB開發中等的網頁應用程式有點大材小用。但從頭開發一個商業應用程式是不實際的。大多數的伺服端應用程式有很多是普遍的 ,就像管理應用程式狀態 ,資料庫提取或儲存資料,安全性,非同步進程,整合系統等等。
        作為一個框架,EJB container提供了這些普遍的功能,那EJB components 可以直接使用這些功能到自己的應用程式也不需要重新開發這類功能。這些服務,當EJB components 部署在EJB container的時候就能使用,就像Figure 2. 這代表開發一個高品質,豐富功能的應用程式比你所想的還要快。


Figure 2

        Container使用了一些優雅的新方法提供服務給EJB componentsmetadata annotations 是當container部署EJBs用來預設EJBs 服務的類別。在Java 5中有介紹metadata annotations是設定一段程式碼的設定,如某些class需要特定屬性。這是程式語言的宣告方式讓開發者註明需要完成什麼然後系統將程式碼加上。
        EJB meta annotations 大大的簡化了應用程式的開發和測試,不需要額外的xml 設定檔案. 這允許當開發者需要的時可宣告式的增加愛服務到EJB components就像Figure
3 描繪,annotations 將一個簡單的POJO轉換成 EJB


Figure 3
Layered architectures and EJB
        大多數的企業應用程式包含大量的components.企業應用程式是為了解決客戶特定問題所設計,但它們共享很多common 特色。舉例來說,多數企業應用程式有些UI界面,商業模式,將資料儲存到資料庫特性。因為這些共同特性,在構建企業應用程式可以跟隨常見架構或設計原則稱為 “patterns”.
        對於伺服端開發,較好patternlayered architectures. layered architecture components被劃分在tiers應用程式的每一個tier都有很好定義。EJB在建立應用程式允許採用兩種不同的layered architecture分別是:traditional four-tier architecture domain-drive design (DDD).

Traditional four-tier layered architecture
Figure 4 顯示traditional four-tier layered architecture.這個架構非常直覺也非常普及。在這架構presentation layer是負責GUI和處理user input, 然後將每個得到的request傳給business logic layer. Business logic layer是應用程式的核心而且包含工作流程和processing的邏輯。Business logic layer透過persistence tier 從資料庫獲取或儲存資料。Persistence layer database layer之上提供高階的抽象的OODatabase layer 就是DBMS


Figure 4

EJB 明顯不是presentation layer. EJB完全支援在實作商業邏輯和persistence layer. Figure 5 顯示 EJB如何透過它的服務支援這些layers.在一開始有提到bean的種類session beans message-driven beans是用在business logic tier, entities實在persistence layer.

Figure 5
        Traditional four-tier architecture 是不完美的。其中一個常見的批評就是破壞了OO模組化商業領域為物件且封裝資料和行為的理想。因為traditional architecture 專注在business process的模組化而不是領域。而且persistence layer也比較像簡單的資料處理元件,像資料庫資料的定義而不是OO世界的第一級公民。

Domain-driven design
Domain-driven design (DDD )重點放在領域的物件應該包含商業邏輯和不應該只是複製資料庫的資料。Domain objects EJB3 也稱為entities。在DDD中,一個貿易應用程式的CatalogCustomer物件是entities的典型例子,它們應該包含商業邏輯。

        然而,就算EJB發布的時它的價值已經非常清楚,但還是很困難的實作DDD。在EJB 2 實作 domain model是不可能的,因為beans不是 POJOs 且沒有支援多數的OO特色,如:inheritance polymorphism。有個好消息是EJB 3 已經可以讓我們簡單的跟隨好的OO設計或DDD。在EJB 3 Java Persistence API (JPA)定義的entities 支援OO。我們可以簡單的實作persistence object,最重要的是可以簡單的增加商業邏輯在entities上,那在透過EJB 3實作一個rich domain 是在簡單不過的任務。


Reference:
1)EJB 3 in action