一、前言
二、相關(guān)概念與工具介紹
三、實(shí)例需求與總體設(shè)計(jì)
四、持久化層與業(yè)務(wù)層實(shí)踐(Hibernate實(shí)踐)
五、控制層與表示層實(shí)踐(Struts實(shí)踐)
六、發(fā)布與運(yùn)行
七、寫在最后
一、前言
J2EE和.NET是目前企業(yè)級(jí)運(yùn)用的兩大陣營,誰優(yōu)誰劣各有說法。筆者是做J2EE方向的,覺得J2EE比起.NET最大的優(yōu)勢(shì)就是其經(jīng)過長(zhǎng)實(shí)踐發(fā)展總結(jié)出來的大量模式和大量先進(jìn)的框架。這些框架許多都是開源的——開源也是J2EE陣營的另一優(yōu)勢(shì)。本篇文章的主角就是目前J2EE web應(yīng)用中最流行的兩大開源框架——Hibernate和Struts。
二、相關(guān)概念與工具介紹
下面我將分別對(duì)本文“三大主角”所涉及到相關(guān)概念進(jìn)行說明。
Hibernate及相關(guān)知識(shí)介紹
Hibernate:
中文意思是"冬眠“,呵呵,不知道設(shè)計(jì)者為何用這個(gè)名字。它是一個(gè)開源的ORM框架(關(guān)于ORM下文還會(huì)講解),它是通過對(duì)JDBC API進(jìn)行封裝從而實(shí)現(xiàn)對(duì)java對(duì)象持久化的。有人可能要問:JDBC其實(shí)不難操作,為什么還要封裝它哪?其實(shí)答案很簡(jiǎn)單,因?yàn)楝F(xiàn)在通用的數(shù)據(jù)庫都是關(guān)系數(shù)據(jù)庫,我們通過JDBC操作無法做到OOP,所以Hibernate將JDBC封裝起來,并且提供了一套OO化的Hibernate API供頂層操作。Hibernate現(xiàn)在幾乎已經(jīng)成為ORM的公認(rèn)標(biāo)準(zhǔn)了(剛推出的EJB 3.0標(biāo)準(zhǔn)中使用的ORM事實(shí)上就是Hibernate)
ORM:
這里解釋下ORM。ORM是一種模式(關(guān)于模式,筆者之前在這里發(fā)表過一篇介紹工廠模式的文章,讀者可以看看),它的英文是Object-Relation Mapping,中譯為對(duì)象-關(guān)系映射,它指的是“在單個(gè)組建中負(fù)責(zé)所有實(shí)體域?qū)ο蟮某志没?,封裝數(shù)據(jù)訪問細(xì)節(jié)”(注:此定義來自《精通Hibernate:java對(duì)象持久化技術(shù)詳解》,孫衛(wèi)琴,電子工業(yè)出版社)。筆者的覺得很容易理解:把關(guān)系數(shù)據(jù)庫對(duì)象化。
Struts及相關(guān)知識(shí)介紹
Struts:
Struts是由著名的Apache基金會(huì)開發(fā)的開源項(xiàng)目。中譯為“框架”,顧名思義,它就是一種MVC框架。眾所周知,MVC是一種業(yè)務(wù)邏輯與表示分離的模式,在java web上的應(yīng)用十分廣泛。以前MVC的主要表現(xiàn)形式是JSP Model2,也就是JSP+Servlet+Javabean的應(yīng)用,而近年來Struts的應(yīng)用越來越廣泛,目前已經(jīng)是最流行的MVC框架了。
MVC:
Model-View-Controller,中譯為模型-視圖-控制器。MVC不是真正意義上的軟件設(shè)計(jì)模式,而更是一種解決方案,它把軟件系統(tǒng)的所有業(yè)務(wù)邏輯方面的編程交給了Model,把所有UI視圖的設(shè)計(jì)和編程交給了View,再用Controller控制器控制Model并生成相應(yīng)的View,從而真正實(shí)現(xiàn)了業(yè)務(wù)邏輯與用戶界面的分離。
Eclipse介紹
Eclipse是由IBM公司開發(fā)出來,后來又免費(fèi)捐獻(xiàn)出來的開源工具,是一套主要用于Java開發(fā)的IDE(Eclipse通過添加某些插件可以實(shí)現(xiàn)對(duì)UML、C++等的開發(fā))。Eclipse具有強(qiáng)大的擴(kuò)展功能,加上其開源的特性,導(dǎo)致許多愛好者和公司為其開發(fā)了非常優(yōu)秀的插件,Myeclipse就是其中之一。Myeclipse是面向J2EE開發(fā)者的Eclipse插件,功能強(qiáng)大,好用。本文的實(shí)例就是基于Eclipse+Myeclipse環(huán)境下開發(fā)出來的。
創(chuàng)建/運(yùn)行本文實(shí)例除了安裝以上工具和插件外還需要安裝一個(gè)Web容器,本文使用的是Jboss,筆者可以自行選擇使用Tomcat或Weblogic等,這些對(duì)運(yùn)行本文實(shí)例影響不大。
本文選擇的數(shù)據(jù)庫是SQLServer2000,關(guān)于Mysql、Oracle等其他數(shù)據(jù)庫的操作方法類似。
關(guān)于Eclipse下載和安裝方法本文不做介紹,請(qǐng)讀者自行在網(wǎng)上查找相關(guān)方法。
三、實(shí)例需求與總體設(shè)計(jì)
1、需求定義
由于本文的目的是介紹在Eclipse IDE下開發(fā)Struts+Hibernate的具體方法,而不是介紹項(xiàng)目開發(fā)/軟件設(shè)計(jì)的技巧,所以本文實(shí)例需求非常簡(jiǎn)單。
本文實(shí)例是一個(gè)web留言簿,可以讓匿名用戶發(fā)表一些留言信息,并保存至數(shù)據(jù)庫。做過web開發(fā)的朋友肯定做過這類實(shí)例,非常經(jīng)典。由于實(shí)例簡(jiǎn)單并且容易理解,所以筆者也省去畫用例圖說明的步驟。
2、總體設(shè)計(jì)
本實(shí)例按傳統(tǒng)J2EE web項(xiàng)目的設(shè)計(jì)方法,分為5層架構(gòu),自底向上分別是:數(shù)據(jù)庫層 -> ORM層(Hibernate層) -> 業(yè)務(wù)邏輯層 -> 控制層(Struts Action) -> 視圖表示層。
數(shù)據(jù)庫的DDL語句如下:
四、持久化層與業(yè)務(wù)層實(shí)踐(Hibernate實(shí)踐)
好,戲肉開始。
1、先打開Eclipse。點(diǎn)擊“新建項(xiàng)目”->“Web Project”,出現(xiàn)如下窗口,在窗口中Project Name填入“Memo”作為項(xiàng)目名:
create database memotest
create table Memo
(
ID int not null identity(1,1),
topic varchar(255),
content text,
guest varchar(50),
primary key(ID)
)
?
2、點(diǎn)擊“窗口”->“打開透視圖”->“其他”,出現(xiàn)如下窗口,雙擊“Myeclipse Database Explorer”,切換到如下視圖:
3、在“DB Browser”控制面板點(diǎn)擊“new”,新建一個(gè)數(shù)據(jù)庫連接。在彈出的窗口中點(diǎn)擊“new driver”新建一個(gè)數(shù)據(jù)庫連接驅(qū)動(dòng)。如下圖:
4、上一步后回到以下視圖,在列表中選擇上一步創(chuàng)建的驅(qū)動(dòng),填入相關(guān)數(shù)據(jù)庫資料,點(diǎn)擊確定即可。(此步驟前必須已經(jīng)打開數(shù)據(jù)庫,最后已經(jīng)按照本實(shí)例的DDL創(chuàng)建了庫和表)
5、完成上一步后出現(xiàn)以下視圖。點(diǎn)擊“memo”的右鍵,點(diǎn)擊“open connetion”->“確定”。如果上述步驟成功的話這里會(huì)連接到數(shù)據(jù)庫,并顯示相關(guān)的數(shù)據(jù)庫結(jié)構(gòu)。
成功后如下圖:
6、點(diǎn)擊“窗口”->“打開透視圖”->“其他”->“Myeclipse”切換到項(xiàng)目控制視圖。在項(xiàng)目名上點(diǎn)擊右鍵->“myeclipse”->“Add Hibernate capabilites”,出現(xiàn)以下視圖,并按下圖填入相關(guān)信息:
點(diǎn)下一步后出現(xiàn)如下框圖,按圖片上內(nèi)容填寫:
提交后出現(xiàn)以下視圖,按圖片內(nèi)容填寫:
7、在項(xiàng)目名上點(diǎn)擊右鍵->“myeclipse”->“Add Struts capabilites”,出現(xiàn)下面視圖,按圖中內(nèi)容天下:
8、點(diǎn)擊“窗口”->“打開透視圖”->“其他”,出現(xiàn)如下窗口,雙擊“Myeclipse Database Explorer”,切換到數(shù)據(jù)庫管理視圖,找到我們?yōu)楸敬螌?shí)例創(chuàng)建的表格,點(diǎn)右鍵->“create hibernate mapping”后出現(xiàn)下圖,按圖上內(nèi)容填寫:
9、至此Hibernate的創(chuàng)建工作已經(jīng)完成,如下圖,接下來我們寫個(gè)DAO工廠類來操作Hibernate API。
點(diǎn)擊com.woden包,新建個(gè)類,如下圖:
輸入以下代碼:
package com.woden;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Session;
import net.sf.hibernate.Transaction;
public class MemoDAOFactory {
? ? ? ? Session session;
? ? Transaction tx;
? ?
? ? public void add(Memo memo) throws HibernateException{
? ?? ?? ?? ?try{
? ?? ?? ?? ?? ?? ???session = SessionFactory.currentSession();
? ?? ?? ?? ?? ?? ???tx = session.beginTransaction();
? ?? ?? ?? ?? ?? ???session.save(memo);
? ?? ?? ?? ?? ?? ???tx.commit();
? ?? ?? ?? ?}catch(HibernateException e){
? ?? ?? ?? ?? ?? ???System.out.println(e.toString());
? ?? ?? ?? ?}finally{
? ?? ?? ?? ?? ?? ???if(tx!=null){
? ?? ?? ?? ?? ?? ?? ?? ?? ? tx.rollback();
? ?? ?? ?? ?? ?? ???}
? ?? ?? ?? ?? ?? ???SessionFactory.closeSession();
? ?? ?? ?? ?}
? ? }
}
以上只有一個(gè)插入方法,如果讀者需要更多方法可以在DAO中自行添加。
至此,數(shù)據(jù)庫層、ORM層和業(yè)務(wù)層的代碼已經(jīng)完成。
五、控制層與表示層實(shí)踐(Struts實(shí)踐)
1、新建一個(gè)welcome.jsp文件,作為實(shí)例的首頁。具體方法是在“webroot”文件夾圖標(biāo)點(diǎn)右鍵->new->“jsp”,接下來填寫的東西很簡(jiǎn)單就不用介紹了吧。
2、在上一步驟的第7步中已經(jīng)在myeclipse中導(dǎo)入了struts,我們下面就可以開始編輯設(shè)置我們的struts實(shí)例。打開webboot目錄下WEB-INF中的struts配置文件“struts-config.xml”,如下圖:
3、在屏幕空白處點(diǎn)右鍵->“new”->“new form,action and jsp”,會(huì)出現(xiàn)如下視圖,按下圖提示填寫內(nèi)容:
這里記得點(diǎn)擊“jsp”標(biāo)簽條,出現(xiàn)以下界面,按下圖設(shè)置:
4、上一步驟設(shè)置了form,點(diǎn)擊下一步看到如下視圖,按下圖設(shè)置,具體步驟是:點(diǎn)擊“foward”標(biāo)簽->“add”->name填“success”,path選擇“welcome.jsp”,其他不用填->確定。
5、上一步驟點(diǎn)擊了“完成”后出現(xiàn)下圖:
6、這一步驟是設(shè)置資源文件,為了struts的國際化和錯(cuò)誤提示做準(zhǔn)備。找到項(xiàng)目文件夾中src(源文件夾),找到ApplicationResourse.properties,雙擊打開,如下圖所示配置:(注:這里筆者安裝了一個(gè)免費(fèi)的ascii轉(zhuǎn)unicode的插件)
如果讀者沒有安裝ascii自動(dòng)轉(zhuǎn)unicode組建,可以直接copy我轉(zhuǎn)換后的資源文件內(nèi)容:
form.addmemo.err.content=\u7559\u8a00\u5185\u5bb9\u4e0d\u80fd\u4e3a\u7a7a\u3002
form.addmemo.err.guest=\u7559\u8a00\u8005\u59d3\u540d\u4e0d\u80fd\u4e3a\u7a7a\u3002
form.addmemo.err.topic=\u7559\u8a00\u6807\u9898\u4e0d\u80fd\u4e3a\u7a7a\u3002
jsp.addmemo.content=\u8bf7\u8f93\u5165\u5185\u5bb9\uff1a
jsp.addmemo.guest=\u60a8\u7684\u59d3\u540d\uff1a
jsp.addmemo.pagetitle=\u7559\u8a00\u6dfb\u52a0
jsp.addmemo.reset=\u91cd\u8bbe
jsp.addmemo.submit=\u63d0\u4ea4
jsp.addmemo.topic=\u6807\u9898\uff1a
jsp.welcome.content=\u6b22\u8fce\u4f7f\u7528Hibernate+Struts\u5b9e\u4f8b\u3002
jsp.welcome.title=\u4f60\u597d\u3002\u3002\u3002
7、下面打開com.woden.form.MemoForm.java文件,輸入以下代碼:
package com.woden.form;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
public class MemoForm extends ActionForm {
? ? ? ? private String topic;
? ? ? ? private String content;
? ? ? ? private String guest;
? ? ? ? public ActionErrors validate(
? ? ? ? ? ? ? ? ActionMapping mapping,
? ? ? ? ? ? ? ? HttpServletRequest request) {
? ? ? ? ? ? ? ? ActionErrors errors = new ActionErrors();
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? if(getGuest()==null||"".equals(getGuest()))
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? errors.add("memoform.err.guest",new ActionMessage("form.addmemo.err.guest"));
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? if(getTopic()==null||"".equals(getTopic()))
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? errors.add("memoform.err.topic",new ActionMessage("form.addmemo.err.topic"));
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? if(getContent()==null||"".equals(getContent()))
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? errors.add("memoform.err.content",new ActionMessage("form.addmemo.err.content"));
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? return errors;
? ? ? ? }
? ? ? ? public void reset(ActionMapping mapping, HttpServletRequest request) {
? ? ? ? ? ? ? ? this.topic=null;
? ? ? ? ? ? ? ? this.content=null;
? ? ? ? ? ? ? ? this.guest=null;
? ? ? ? }
? ? ? ? public String getTopic() {
? ? ? ? ? ? ? ? return topic;
? ? ? ? }
? ? ? ? public void setTopic(String topic) {
? ? ? ? ? ? ? ? this.topic = topic;
? ? ? ? }
? ? ? ? public String getContent() {
? ? ? ? ? ? ? ? return content;
? ? ? ? }
? ? ? ? public void setContent(String content) {
? ? ? ? ? ? ? ? this.content = content;
? ? ? ? }
? ? ? ? public String getGuest() {
? ? ? ? ? ? ? ? return guest;
? ? ? ? }
? ? ? ? public void setGuest(String guest) {
? ? ? ? ? ? ? ? this.guest = guest;
? ? ? ? }
}
8、上面已經(jīng)寫出了ActionForm的代碼,具體代碼筆者在這里不解釋,我想看過struts基礎(chǔ)的朋友都應(yīng)該很清楚了,下面貼處Action的代碼:
package com.woden.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import com.woden.Memo;
import com.woden.MemoDAOFactory;
import com.woden.form.MemoForm;
public class MemoAction extends Action {
? ? ? ? public ActionForward execute(
? ? ? ? ? ? ? ? ActionMapping mapping,
? ? ? ? ? ? ? ? ActionForm form,
? ? ? ? ? ? ? ? HttpServletRequest request,
? ? ? ? ? ? ? ? HttpServletResponse response) {
? ? ? ? ? ? ? ? MemoForm memoForm = (MemoForm) form;
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? MemoDAOFactory memoDAO = new MemoDAOFactory();
? ? ? ? ? ? ? ? Memo memo = new Memo();
? ? ? ? ? ? ? ? memo.setTopic(memoForm.getTopic());
? ? ? ? ? ? ? ? memo.setContent(memoForm.getContent());
? ? ? ? ? ? ? ? memo.setGuest(memoForm.getGuest());
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? try{
? ? ? ? ? ? ? ? ? ? ? ? memoDAO.add(memo);? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? }catch(Exception e)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? System.out.print(e.toString());
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? return mapping.findForward("success");
? ? ? ? }
}
9、最后編輯下幾個(gè)相關(guān)jsp文件的內(nèi)容,分別如下:
welcome.jsp
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html:html>
??<head>
? ? <html:base />
? ? <title><bean:message key="jsp.welcome.title"/></title>
??</head>
??
??<body>
? ? <bean:message key="jsp.welcome.content"/>
??</body>
</html:html>
addmemo.jsp
<%@ page contentType="text/html; charset=utf-8"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>
<html>
? ? ? ? <head>
? ? ? ? ? ? ? ? <title><bean:message key="jsp.addmemo.pagetitle"/></title>
? ? ? ? </head>
? ? ? ? <body>
? ? ? ? ? ? ? ? <html:form action="/memo">
? ? ? ? ? ? ? ? ? ? ? ? <bean:message key="jsp.addmemo.guest"/><html:text property="guest"/><html:errors property="memoform.err.guest"/><br/>
? ? ? ? ? ? ? ? ? ? ? ? <bean:message key="jsp.addmemo.topic"/><html:text property="topic"/><html:errors property="memoform.err.topic"/><br/>
? ? ? ? ? ? ? ? ? ? ? ? <bean:message key="jsp.addmemo.content"/><html:textarea property="content"/><html:errors property="memoform.err.content"/><br/>
? ? ? ? ? ? ? ? ? ? ? ? <html:submit><bean:message key="jsp.addmemo.submit"/></html:submit>
? ? ? ? ? ? ? ? ? ? ? ? <html:reset><bean:message key="jsp.addmemo.reset"/></html:reset>
? ? ? ? ? ? ? ? </html:form>
? ? ? ? </body>
</html>
至此,本實(shí)例完成。
六、發(fā)布與運(yùn)行
1、在項(xiàng)目文件點(diǎn)右鍵->“myeclipse”->“Add and remove project deployment”,如下圖:
2、點(diǎn)擊
圖標(biāo),選擇“Jboss”->“start”(注:這里如果用的是tomcat也類似操作,關(guān)于服務(wù)器配置的方法這里不祥談,請(qǐng)讀者自行在網(wǎng)上查找相關(guān)資料),會(huì)發(fā)現(xiàn)控制臺(tái)會(huì)輸出類似如下信息:
打開瀏覽器,輸入:http://localhost:8080/ 后如果出現(xiàn)下圖證明啟動(dòng)成功:
3、輸入網(wǎng)址:http://localhost:8080/Memo/addmemo.jsp ,會(huì)看到效果圖如下圖:
4、按照正常流程和非正常流程分別留言一次,呵呵,效果出來沒有?如果沒有出現(xiàn)預(yù)期效果請(qǐng)檢查前面步驟。
七、寫在最后
在本文最后,筆者再次強(qiáng)調(diào),本文的目的是介紹Eclipse IDE關(guān)于創(chuàng)建Struts+Hibernate應(yīng)用的方法,而不是介紹j2ee框架的概念和運(yùn)用,更不是介紹java設(shè)計(jì)與模式。本文對(duì)IDE的配置、服務(wù)器配置的方法也沒做詳細(xì)介紹,因?yàn)檫@都不是本文重點(diǎn)。對(duì)以上知識(shí)想了解多點(diǎn)的讀者可以google一下。
本文的實(shí)例只是一個(gè)入門,強(qiáng)調(diào)的是一種方法,而不是強(qiáng)調(diào)功能,所以本文的實(shí)例只有一個(gè)簡(jiǎn)單的錄入功能。在看完本文后讀者可以添加更多的功能(我想,當(dāng)這一架構(gòu)搭建起來后,添加功能已經(jīng)是相當(dāng)容易的事情了)。