3 層的系統架構:
- 客戶層 (Client tier)
- 商業邏輯層 (Business tier)
- 資料層 (Enterprise Information Systems(EIS) tier)
而 4 層則是在 客戶層 (Client tier) 和 商業邏輯層 (Business tier) 之間加插一個網絡服務層 (Web tier)
4 層的系統架構:
4 層的系統架構:
- 客戶層 (Client tier)
- 網絡服務層 (Web tier)
- 商業邏輯層 (Business tier)
- 資料層 (Enterprise Information Systems(EIS) tier)
給大家一張圖片比較好理解
上圖左邊是 3 層架構
右邊則是 4 層架構
Web-Based Client 大多數是指瀏覽器
其實在上圖的例子不是只有瀏覽器才會使用到網絡服務層 (Web tier)
就好像下圖一樣
就好像下圖一樣
因為網絡服務層 (Web tier) 包含 Web service
Web service 可以經由各種不同的應用程式去使用
現在開始試作 4 層的系統架構
開發軟件: Eclipse IDE for Java EE Developer
服務器: GlassFish v3
資料庫: MySQL 5.1
安裝好以上的工具後便開始進行設定
- Eclipse 整合 GlassFish v3 可參考: http://lawpronotes.blogspot.com/2010/01/eclipse-glassfish-3.html
- GlassFish v3 整合 MySQL 5.1 可參考: http://lawpronotes.blogspot.com/2010/01/glassfish-3-java-ee-server-mysql.html
打開 MySQL Command Line Client
輸入密碼
然後輸入以下的 SQL
CREATE TABLE IF NOT EXISTS `test`.`User` (
`UID` INT NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(45) NOT NULL ,
`password` VARCHAR(45) NOT NULL ,
PRIMARY KEY (`UID`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;
**在安裝 MySQL 後 test 這個 Database 會自動加入**
在 Eclipse 按 File -> New -> Enterprise Application Project
- Project name: TestEAR
- Target runtime: GlassFish v3 Java EE 6
- EAR version: 5.0
- Configuration: Default Configuration for GlassFish v3 Java EE 6
按下 Finish
打開 File -> New -> JPA Project
- Project name: TestJPA
- Configuration: Default Configuration for GlassFish v3 Java EE 6
- EAR membership: Add project to an EAR
- EAR project name: TestEAR
按下 Finish
打開 File -> New -> EJB Project
- Project name: TestEJB
- EJB Module version: 3.0 (還沒有 3.1 可供選擇)
- Configuration: Default Configuration for GlassFish v3 Java EE 6
- EAR membership: Add project to an EAR
- EAR project name: TestEAR
再按 Next
不要選取 Create an EJB client JAR module to hold the client interface and class
按下 Finish
打開 File -> New -> Dynamic Web Project
- Project name: TestWAR
- Dynamic Web module version: 2.5 (還沒有 3.0 可供選擇)
- Configuration: Default Configuration for GlassFish v3 Java EE 6
- EAR membership: Add project to an EAR
- EAR project name: TestEAR
按下 Finish
設換到 JPA 的版面
在 Data Source Explorer 的 Database connection 按下滑鼠右鍵
按下 New
- 選擇 MySQL
- Name: Test Connection
按下 Next
現在是沒有 Driver 可供選擇的
按下右邊第二個按鈕
選擇 MySQL 5.1
在上方的標籤選擇 Jar List
按下 Edit JAR/Zip… 選擇 MySQL JDBC Driver
沒有 Driver 的可在這裡下載: http://dev.mysql.com/downloads/connector/j/
按下 OK 回到剛才的頁面
- Database: test
- URL: jdbc:mysql://localhost:3306/test
- User name: root
- password: (不用教吧)
確定資料正確後可以按一下 Test Connection 測試一下連接有沒有問題
正確連接會看見以下畫面
按下 Finish 完成
在 TestJPA project 新增一個 Entities
選取 New -> Entities From Table
- Connection: Test Connection
- Schema: test
- Table: user
按下 Next
再按下 Next
Key generator: auto- Collection properties type: java.util.List
- Package: com.blogspot.lawpronotes.jpa
按下 Finish
在 src 的 資料夾會出現 User.java
原始碼如下
package com.blogspot.lawpronotes.jpa;
import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the user database table.
*
*/
@Entity
@Table(name = "User")
@NamedQueries( { @NamedQuery(name = "User.findAll", query = "SELECT u FROM User u") })
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Column(name = "UID")
private int uid;
private String name;
private String password;
public User() {
}
public int getUid() {
return this.uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
}
現在設定 EJB
到 TestEJB -> Properties
找尋 Java EE Module Dependencies
將 TestJPA 打勾起來
按下 OK
在 TestEJB 新增一個 Session Bean (EJB 3.x)
- Java package: com.blogspot.lawpronotes.ejb
- Class name: UserController
- Status type: Stateless
- 不要將 Remote 打勾 (在同一個 JVM 環境下不需要用到 Remote)
- 將 Local 打勾並輸入: com.blogspot.lawpronotes.ejb.UserControllerLocal
按下 Next
- Bean name: UserController
- Mapped name: ejb/UserController
- Transaction type: Container
按下 Finish
在 TestEJB project 內會多出 2 個 file
將 UserControllerLocal.java 換成以下程式碼
package com.blogspot.lawpronotes.ejb;
import javax.ejb.Local;
@Local
public interface UserControllerLocal {
public void addUser(String userName, String password) throws Exception;
public java.util.List<com.blogspot.lawpronotes.jpa.User> getAllUser()
throws Exception;
}
再將 UserController.java 換成以下程式碼
package com.blogspot.lawpronotes.ejb;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import com.blogspot.lawpronotes.jpa.User;
/**
* Session Bean implementation class UserController
*/
@Stateless(mappedName = "ejb/UserController")
public class UserController implements UserControllerLocal {
@PersistenceContext
private EntityManager entityManager;
/**
* Default constructor.
*/
public UserController() {
// TODO Auto-generated constructor stub
}
@Override
public void addUser(String userName, String password) throws Exception {
// TODO Auto-generated method stub
User user = new User();
user.setName(userName);
user.setPassword(password);
entityManager.persist(user);
entityManager.flush();
}
@SuppressWarnings("unchecked")
@Override
public List<User> getAllUser() throws Exception {
// TODO Auto-generated method stub
List<User> userList = null;
Query query = entityManager.createNamedQuery("User.findAll");
userList = (List<User>) query.getResultList();
return userList;
}
}
在 TestEJB -> ejbModule -> META-INF 新增一個 XML 檔案
File name: persistence.xml
按下 Finish
貼上以下內容
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="TestJPA">
<jta-data-source>jdbc/test</jta-data-source>
<class>com.blogspot.lawpronotes.jpa.User</class>
</persistence-unit>
</persistence>
其中的 jta-data-source 一定要跟 GlassFish JDBC Resources 的 JNDI name 要一致
<jta-data-source>jdbc/test</jta-data-source>
進入 TestWAR -> Properties
找尋 Java EE Module Dependencies
將 TestJPA 和 TestEJB 打勾起來
按下 OK
在 TestWAR 新增一個 Servlet
- Java package: com.blogspot.lawpronotes.servlet
- Class name: IndexServlet
按下 Finish
將 IndexServlet.java 換成以下內容
package com.blogspot.lawpronotes.servlet;
import java.io.IOException;
import java.util.List;
import javax.ejb.EJB;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.blogspot.lawpronotes.ejb.UserControllerLocal;
import com.blogspot.lawpronotes.jpa.User;
/**
* Servlet implementation class IndexServlet
*/
@WebServlet(name = "Index", urlPatterns = { "/index" })
public class IndexServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@EJB
private UserControllerLocal userController;
/**
* @see HttpServlet#HttpServlet()
*/
public IndexServlet() {
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
try {
List<User> userList = userController.getAllUser();
request.setAttribute("userList", userList);
RequestDispatcher dispatcher = request
.getRequestDispatcher("/WEB-INF/pages/index.jsp");
dispatcher.forward(request, response);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
try {
String userName = request.getParameter("userName");
String password = request.getParameter("password");
userController.addUser(userName, password);
List<User> userList = userController.getAllUser();
request.setAttribute("userList", userList);
RequestDispatcher dispatcher = request
.getRequestDispatcher("/WEB-INF/pages/index.jsp");
dispatcher.forward(request, response);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
將 TestWAR -> Web Content 的 index.jsp 移除掉
在 TestWAR -> Web Content -> WEB-INF 新增一個資料夾
Folder name: pages
按下 Finish
在 pages 資料夾新增一個 JSP
File name: index.jsp
按下 Finish
貼上以下程式碼
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Sample</title>
</head>
<body>
<c:if test="${userList.size() > 0}">
<table>
<thead>
<tr>
<td>User Name</td>
<td>Password</td>
</tr>
</thead>
<tbody>
<c:forEach var="user" items="${userList}">
<tr>
<td>${user.getName()}</td>
<td>${user.getPassword()}</td>
</tr>
</c:forEach>
</tbody>
</table>
</c:if>
<form method="post">
<label>User Name:</label><input type="text" name="userName"/><br/>
<label>Password:</label><input type="password" name="password"/><br/>
<input type="submit"/>
</form>
</body>
</html>
最後要修改一下 web.xml
到 TestWAR -> Web Content -> WEB-INF -> web.xml
貼上以下內容
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>TestWAR</display-name>
<welcome-file-list>
<welcome-file>index</welcome-file>
</welcome-file-list>
</web-app>
現在完成了!
立即去測試一下
到 TestEAR -> Run As - Run on Server
選擇 GlassFish v3 Java EE 6 at localhost
按下 Finish
Eclipse 便會將整個 Project 打包放到 GlassFish Server 上
在瀏覽器輸入網址: http://localhost:8080/TestWAR/
將會看見以下畫面
其實這是一個加入 User 的表格 (好像太陽春了點….)
- User Name: Lawrence
- Password: 123456
按下提交
結果會顯示如以下畫面
現在講解一下流程:
- 按下提交
- 瀏覽器將表格內容送回 IndexServlet
- IndexServlet 接收內容後將 userName 和 password 送到 EJB Session bean - UserController 的 addUser function
- UserController 利用 EntityManager 將 userName 和 password 加入到 user table 內
- IndexServlet 將所有 user 找出來
- IndexServlet 將 user list 送到 index.jsp 顯示