用EJB开发在线课堂.doc_第1页
用EJB开发在线课堂.doc_第2页
用EJB开发在线课堂.doc_第3页
用EJB开发在线课堂.doc_第4页
用EJB开发在线课堂.doc_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Java 学习资料 制作 : 刘晏2019-2-19导读在项目开发中如何进行需求分析,如何规划数据库、数据库建模以及怎样将模式设计应用于具体的项目困扰了开发人员。本文以一个在线课程项目为线索全景展现软件开发的各个步骤。阅读导航 导航简介CoursesOnline简介简要介绍CoursesOnline系统的设计目的开发环境介绍开发工具需求分析CoursesOnline系统开发初期的需求调研,数据库建模、数据字典、数据表的规划CoursesOnline系统设计在系统设计中引入设计模式,如何选择设计模式创建数据库在Oracle9i中创建数据库CoursesOnline的具体实现用JBuilder9开发CoursesOnline系统步骤部分代码部分步骤代码附录Jbuilder9、Oracle9i、Weblogic7的安装配置;数据表SQL脚本 一、CoursesOnline简介CoursesOnline是一个实验性质的系统,CoursesOnline是在线课程的意思,在这个CoursesOnline系统里,学生选择课程,老师可以开设课程,系统管理员则对学生、老师以及课程进行管理。CoursesOnline使用J2EE来实现,目的是为其它EJB系统的开发提供一些参考。二、开发环境CoursesOnline使用Jbuilder9 + Oracle9i + WebLogic7的开发环境。因为J2EE是一种行业标准,所以采用哪种开发环境的搭配并不是最重要的。目前其它常见开发环境的搭配还有Eclipse + MySQL + Jboss(都是OpenSource),VJA + DB2 + WebSphere,等等。Jbuilder9 + Oracle9i + WebLogic 7开发环境的配置请参考附录A。三、CoursesOnline需求分析 3.1 CoursesOnline用例上图是CourcesOnline的Use Case Diagram。显而易见,系统中有学生、老师和系统管理员三种Actor。学生需要注册成系统用户后才能浏览课程和选课。3.2 数据库建模(ER图)及数据字典上图是CoursesOnline的数据库ER图,建模工具是ERWin。顺便提一下,ERWin的正向工程支持ER图直接生成数据库表结构,逆向工程支持数据库表结构生成ER图。CoursesOnline使用到的表有5个,数据字典如下:3.2.1 Actor登录信息表(Actor)序号字段名数据类型约束备注1 ActorID SmallIntPK Actor标识符2 UserNameVarchar(20)Actor登录帐号3 PasswordChar(8) Actor登录口令4 ActorTypeSmallInt Actor类型,0:系统管理员;1:老师;2:学生3.2.2 Actor基本信息表(ActorInfo)序号字段名数据类型约束 备注1 ActorIDSmallInt FK(Actor)Actor标识符2 ActorNameVarchar(20)Actor姓名3 Phone Varchar(16)电话4 EmailVarchar(50)Email3.2.3 课程信息表(Courses)序号字段名数据类型约束备注1 CoursesIDSmallIntPK 课程标识符2 CoursesNameVarchar(20)课程名称3 StartDate Date 课程开始时间4 EndDate Date 课程结束5 ActorID SmallIntFK(Actor) 6 RoomIDSmallIntFK(Room)教室标识符3.2.4 学生选课表(Appointment)序号 字段名数据类型 约束 备注1 ActorID SmallInt FK(Actor) Actor标识符(学生,ActorType=2)2 CoursesIDSmallInt FK(Courses) 课程标识符3.2.5 教室信息表(Room)序号字段名数据类型 约束备注1 RoomIDSmallIntPK 教室标识符2 RoomNameVarchar(30)教室名称四、CoursesOnline系统设计4.1 Design Pattern的选择和思考在系统设计上,Design Pattern的选择是很重要的。因为正确的Design Pattern不仅在开发阶段可以让开发人员思路清晰得心应手,而且在维护阶段也不至于让维护人员抓狂。除此之外,对于系统的健壮和运行效率而言也起着举足轻重的作用。如果采用了错误的Design Pattern,那么对于系统来说就像是在错误的时间错误的地点与错误的敌人打了一场错误的战争。下面以CoursesOnline系统学生注册时采用的两种不同的处理方法为例来简单说明选择Design Pattern的重要性。学生在Client提交注册信息,包括登录帐号,登录口令,姓名,电话和Email五项内容。从数据库ER图中我们可以看到学生信息被分散在两张表里,也就是说服务器端有两个Entity Bean来存取学生的注册信息,一个为Actor,另一个为ActorInfo。方法一:客户端直接与Entity Bean沟通以完成工作方法二:客户端与Session Bean交互,由Session Bean与Entity Bean沟通以完成工作方法一的设计虽然也能完成对学生注册的处理,但是客户端必须写所有的业务逻辑代码,而且由于客户端直接访问Entity Bean,不但造成了多次的网络roundtrip,使执行效率大幅下降,也使客户端与Entity Bean形成强耦合,日后不管修改客户端还是Entity Bean,都会牵一发而动全身,对系统的改造简直就是一场灾难。方法二不但大幅降低了网络的roundtrip,而且Session Facade分隔了客户端和Entity Bean,Entity Bean对于客户端来说是透明的,客户端需要关心的只是Session Facade提供的接口。这样一来系统的可扩展性就得到了质的提升。4.2 CoursesOnline系统示意图五、创建数据库先有鸡再有蛋?还是先有蛋再有鸡?先有数据库表再有Entity Bean?还是先有Entity Bean再有数据库表?这两个问题有异曲同工之妙。鸡与蛋的问题已经讨论几千年了,哲学的Big Fans可能会争的脸红耳赤唾沫横飞;偶们只是普通的程序员,谁先谁后的问题还留给理论学家吧。可能会有人先设计Entity Bean再建数据库表,也有可能反其道而行。在CoursesOnline这个实验性质系统的开发过程中,是先建数据库表然后才有Entity Bean。5.1 新建一个数据库Oracle可以在命令行模式下敲入dbca,或者直接在开始菜单里找到并运行Database Configuration Assistant,然后根据向导的提示新建一个名为CoursesDB的数据库。Oracle 9i新建数据库的详细过程请参考Oracle的相关文档。5.2 为数据库创建一个用户在命令行下敲入oemapp console,或者直接在开始菜单里找到EnterPrise Manager Console打开Oracle管理控制中心,以SYSDBA的身份进入CoursesDB数据库后,在安全性-用户中新增一个用户,如chenxc,口令chenxc,并赋予dba的角色。这些设置在接下来的CourseseOnline系统具体开发中会用到。Oracle 9i新建用户的具体操作请参考Oracle的相关文档。5.3 建表及表的初始化5.3.1 建表建表的方法有N种:1)用sqlplus连上CoursesDB数据库后,用sql语句把数据字典中列出来的表结构敲进去;2)把数据字典中表结构写成sql脚本文件,然后用sqlplus连上CoursesDB,执行SQL c:CoursesDB.sql;3)使用一种支持正向工程的数据库建模工具直接把ER图转换成数据库表结构,如ERWin;4)使用可视化工具建表,如PLSQL Developer。其它的我知道的还有我还不知道的数据库的建表方法,在这里就不一一列举了,有兴趣的请自行研究,然后把经验告诉大家。附录C提供了CoursesOnline建表及表的初始化的sql脚本。5.3.2 表的初始化从CoursesOnline用例图中可以看出,系统没有提供系统管理员、老师以及教室的管理的接口,系统管理员、老师和教室的信息在数据库建完后就应该初始化了。也就是说,这些信息是已经存在的,除非直接操作数据库,否则无法改变系统管理员、老师和教室的信息。建完表后,我们为CoursesOnline系统初始化了一位系统管理员,名为sysadmin;三位老师,分别为任我行、东方不败和岳不群;除此之外还初始化了三间教室,分别为黑木崖教室1、黑木崖教室2和华山教室3。附录C提供了CoursesOnline建表及表的初始化的sql脚本。六、CoursesOnline的具体实现6.1 在Jbuilder 9中新建一个工程启动Jbuilder 9,File-New Project,项目名为CoursesOnline,选择路径后,点击finish因为CoursesOnline项目使用Oracle 9i数据库,所以还需要把Oracle的驱动加载进来,Project - Project Properties - Path - Required libraries,点击add,在Select One Or More Libraries窗口中选择OracleJDBCLibOracleJDBCLib的配置请参考附录A.5.3 配置数据库驱动6.2 创建Entity Bean(CMP)6.2.1 新建一个EJB ModuleFile - New - Enterprise -EJB Module点击ok,并在接下来的窗口中为EJB Module命名为Courses,结果如下图6.2.2 Import Schema From Database在上图中的DataSources上点击右键,或者在Courses设计面板上点击右键,然后点击Import Schema From Database,在弹出的窗口中输入Driver,URL等参数,如下图所示点击ok,这时数据库中的5个表在DataSources面板中显示出来,如下图所示6.2.3 创建Entity Bean在上图中DataSources面板中右键Actor,在弹出菜单中选择Create CMP 2.0 Entity Bean,结果如下图左键点击Entity Bean Actor可以在弹出的窗口中编辑它的属性,在这里我们暂时使用默认值。接下来用同样的方法为其它四个表创建CMP 2.0 Entity Bean,结果如下图从左边的Project下拉菜单中可以看到,每个Entity Bean都有三个(或四个)Java程序与之相对应,例如Actor.java、ActorBean.java和ActorHome.java。为了便于管理,以及避免和后面的程序胡搅蛮缠搞得眼睛高度紧张,我把Entity Bean对应的java程序都放在com.chenxc.coursesOnline.ejb20下。点击Entity Bean的名称,在Bean Properties窗口中点击Classes And Packages按钮,然后为每个类指定路径。6.2.4 阶段总结这一节中创建了五个CMP 2.0 Entity Bean,是CMP而不是BMP,是2.0而不是1.x,是local接口而不是remote接口,而且还没有动手写过任何代码。本文并不打算深入探讨EJB的内部机制,而仅仅是举例子来说明使用EJB实现分层思想及分布式计算的方法。如果要研究EJB的细节,请参考附录B 参考资料列举的书籍或文章。当前阶段的五个Entity Bean只能算是半成品,要完成业务逻辑还需要进一步加工,这些在接下来开发Session Bean的过程中会提到。欲知后事如何,请听下回分解。6.3 创建Session Bean(Stateless)6.3.1 SessionFacade - 连接Struts与Entity Bean的桥梁新建一个名为SessionFacade的Session Bean。SessionFacade负责与Entity Bean沟通,并为Struts提供接口。这个Session Bean扮演一个中间人的角色,就像是北京西客站的售票厅,旅客可以买T97的火车票去往广州,也可以买T31的火车票去往上海。在CoursesOnline系统中,Struts跟购买火车票的旅客一样,通过SessionFacade提供的接口完成系统登录、学生注册、学生选课等操作。下面以Actor登录为例来说明SessionFacade是怎样扮演中间人的角色,如下图:在SessionFacade中新增一个名为actorLogin的方法,返回值boolean,输入参数用户名,口令和用户类型(学生、老师或系统管理员),接口remote。方法actorLogin提供给远程的Struts调用。登录处理流程如下:1、用户在页面上输入用户名、口令和用户类型并提交;2、JavaBean存储用户在页面提交上来的用户名、口令和用户类型;3、Struts读取JavaBean的用户名、口令和用户类型;4、Struts通过远程接口调用SessionFacade的actorLogin(String username,String Password,int actortype)方法;5、SessionFacade通过本地接口调用Entity Bean(Actor)的findByName(String username,int actortype)方法;6、SessionFacade获取Entity Bean(Actor)的findByName(String username,int actortype)方法的返回值;7、SessionFacade在actorLogin(String username,String Password,int actortype)方法中比较Entity Bean(Actor)的findByName(String username,int actortype)得到的password的值;8、如果两个password的值相等,则actorLogin(String username,String Password,int actortype)返回true,否则返回false;9、Struts根据SessionFacade的actorLogin(String username,String Password,int actortype)的返回值(true or false)判断登录是否成功,并导航到对应的页面。6.3.2 登录流程的代码/*-*/1、用户登录界面 - login.jsp!- 部分HTML代码此处省略 - form name=teaForm method=post action=%=contextPath%/login.dotable border=0 cellspacing=0 cellpadding=0trtd width=60font size=2用户类型/font/tdtdinput type=radio value=0 name=actortype checkedfont size=2系统管理员 /fontinput type=radio value=1 name=actortypefont size=2学生 /fontinput type=radio value=2 name=actortypefont size=2老师 /font/td/trtrtd width=60font size=2用户名/font/tdtdinput name=username value= size=12 */td/trtrtd width=60font size=2口令/font/tdtdinput type=password name=password value= size=8 maxlength=8 */td/tr/tablebrtable border=0 cellspacing=0 cellpadding=0trtd width=50 /tdtdinput type=submit value=登 录/td/tr/table/form/*-*/2、Struts程序 /2.1 LoginForm.java(存储用户在页面上提交的用户名、口令和用户类型)package com.chenxc.coursesonline.struts;/* Title: LoginForm* Description: 存储登录信息* Time: 2004-3-20* Company: * Author: chenxc* version 1.0*/import java.util.*;public class LoginForm extends org.apache.struts.action.ActionFormprivate String username; /用户名private String password; /口令private int actortype; /用户类型/用户名public void setUsername(String username) this.username = username;public String getUsername() return username;/口令public void setPassword(String password) this.password = password;public String getPassword() return password;/用户类型public void setActortype(int actortype)this.actortype = actortype;public int getActortype()return actortype;/2.2 LoginAction.java(控制登录流程的走向)package com.chenxc.coursesonline.struts;/* Title: LoginAction* Description: 登录验证* Time: 2004-3-20* Company: * Author: chenxc* version 1.0*/import java.io.*;import javax.servlet.*;import javax.servlet.http.*;import java.util.*;import org.apache.struts.action.*;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.ServletException;import com.chenxc.coursesonline.struts.*;public class LoginAction extends org.apache.struts.action.Actionpublic ActionForward execute(ActionMapping mapping,ActionForm actionForm,HttpServletRequest request,HttpServletResponse response) throws ExceptionActionErrors errors = new ActionErrors();HttpSession session = request.getSession();ActionForward forward = null;LoginForm loginForm = (LoginForm)actionForm;FacadeBean facadeBean = new FacadeBean();if(facadeBean.actorlogin(loginForm.getUsername(),loginForm.getPassword(),loginForm.getActortype()forward = mapping.findForward(success);return forward;return (new ActionForward(mapping.getInput();/2.3 FacadeBean.java(实现登录验证)package com.chenxc.coursesonline.struts;/* Title: FacadeBean* Description: 负责与Session Bean沟通* Time: 2004-3-20* Company: * Author: chenxc* version 1.0*/import com.chenxc.coursesonline.ejb20.*;import javax.naming.*;import java.util.Properties;import javax.rmi.PortableRemoteObject;import javax.ejb.CreateException;import java.rmi.RemoteException;public class FacadeBeanextends Object private static final String ERROR_NULL_REMOTE = Remote interface reference is null. It must be created by calling one of the Home interface methods first.;private static final int MAX_OUTPUT_LINE_LENGTH = 100;private CoursesFacadeHome coursesFacadeHome = null;private CoursesFacade coursesFacade = null;/Construct the FacadeBeanpublic FacadeBean() initialize();public void initialize() try /get naming contextContext context = getInitialContext();/look up jndi nameObject ref = context.lookup(CoursesFacade);/look up jndi name and cast to Home interfacecoursesFacadeHome = (CoursesFacadeHome) PortableRemoteObject.narrow(ref,CoursesFacadeHome.class);catch (Exception e) e.printStackTrace();private Context getInitialContext() throws Exception String url = t3:/34:7001;String user = null;String password = null;Properties properties = null;try properties = new Properties();properties.put(Context.INITIAL_CONTEXT_FACTORY, weblogic.jndi.WLInitialContextFactory);properties.put(Context.PROVIDER_URL, url);if (user != null) properties.put(Context.SECURITY_PRINCIPAL, user);properties.put(Context.SECURITY_CREDENTIALS,password = null ? : password);return new InitialContext(properties);catch (Exception e) throw e;/actorloginpublic boolean actorlogin(String username, String password, int actortype) try coursesFacade = coursesFacadeHome.create();if (coursesFacade.actorLogin(username, password, actortype) return true;elsereturn false;catch (CreateException ex) ex.printStackTrace();catch (RemoteException ex) ex.printStackTrace();return false;/*-*/3、Session Bean程序 /3.1 SessionFacadeHome.javapackage com.chenxc.coursesonline.ejb20;import javax.ejb.*;import java.util.*;import java.rmi.*;public interface SessionFacadeHome extends javax.ejb.EJBHome public SessionFacade create() throws CreateException, RemoteException;/3.2 SessionFacade.javapackage com.chenxc.coursesonline.ejb20;import javax.ejb.*;import java.util.*;import java.rmi.*;public interface SessionFacade extends javax.ejb.EJBObject public boolean actorLogin(String actor, String password, int actortype) throwsRemoteException;/3.2 SessionFacadeBean.javapackage com.chenxc.coursesonline.ejb20;import javax.ejb.*;import javax.naming.*;import java.rmi.RemoteException;public class SessionFacadeBean implements SessionBean SessionContext sessionContext;ActorHome actorHome;Actor actor;public void ejbCreate() throws CreateException tryContext ctx = new InitialContext();actorHome = (ActorHome)ctx.lookup(Actor);catch (Exception ex) throw new EJBException(ex);public void ejbRemove() /*todo Complete this method*/public void ejbActivate() /*todo Complete this method*/public void ejbPassivate() /*todo Complete this method*/public void setSessionContext(SessionContext sessionContext) this.sessionContext = sessionContext;public boolean actorLogin(String username, String password, int actortype) tryactor = actorHome.findByName(username,actortype);if(actor.getPassword().equals(password)System.out.println(username + 登录成功!);return true;catch(ObjectNotFoundException ex) catch(Exception ex) ex.printStackTrace();return false;/*-*/4、为Entity Bean(Actor)新增一个findByName的Finder,如下图Finder名findByName,返回值Actor,输入参数用户名,用户类型,接口local home,EJB-QL: SELECT OBJECT(a) FROM Actor AS a WHERE a.username = ?1 AND a.actortype = ?26.3.3 阶段总结Client - Struts - Session Bean - Entity Bean,实现一个登录流程用了十几个java程序,真是累人的说。一个JSP程序就可以实现的功能却要大阵战对待,杀鸡用牛刀乎?答案是否定的,因为EJB存在的意义在于分布式计算和分层的思想。6.4未完成的写到这里,CoursesOnline系统只实现了系统登录验证的功能,主要的业务逻辑基本上没实现,但MVC框架,Facade Design Pattern都或多或少有所描述,继续完成CoursesOnline系统应该不会太困难。另外由于使用CMP查询记录集时处理起来比较麻烦,所以在浏览课程或浏览学生等记录集查询时可以考虑用BMP来实现,或者干脆在Session Bean实现。附录A 开发环境的配置对于JBuilder、Oracle9i、WebLogic 7、WebLogic Domain的安装配置除参考相关的安装手册外,可参考本栏目发表的Jbuilder9+Oracle9i+Weblogic8.1安装配置A. 配置Jbuilder 9A.选择Tools-Configure Servers配置Server信息Home Directory:选择Weblogic安装目录下的Server目录,如:C:beaweblogic700serverMain Class,VM Parameters:系统会自动获得,不用修改Working Directory:创建的新Domain目录 如:C:beauser_projectsmydomainClass 中:由于没有Weblogic的SP包,删除weblogic_sp.jar包,仅保留weblogic.jarJDK Install directory:选择安装Weblogic目录下的JDK目录 如:D:beajdk131_03BEA Home directory: 选择安装Weblogic目录 如:C:beaUser Name and Password:创建Domain时Administor的用户名称和密码。Domain Name and Server Name:系统会自动获得配置缺省工程的Server信息(Project-Default Projects Properties)这样一来新建的工程默认情况下就使用这种Server配置配置数据库驱动点击Add按钮在本机Oracle的目录下选择Oracle JDBC lib的路径,如D:OracleOra92jdbclibclasses12.jar配置数据库驱动后需重启JB才能使设置生效附录B 参考资料1)Mastering EJB 22)Enterprise JavaBeans, 3rd Edition3)EJB Design Pattern4)5)附录C 建表及表初始化的sql脚本C.1 建表CREATE TABLE Appointment (ActorID SMALLINT NOT NULL,CoursesID SMALLINT NOT NULL);ALTER TABLE Appointment ADD ( PRIMARY KEY (ActorID, CoursesID) ) ;CREATE TABLE Courses (CoursesID SMALLINT NOT NULL,CoursesName VARCHAR(30) NU

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论