EJB调用和练习

1、引言

2、实验环境

  • 操作系统:Windows 10
  • 实验工具:IntelliJ IDEA
  • 环境:Java jdk 1.8

3、实验过程

3.1 掌握EJB调用原理

3.1.1 EJB 的基本原理

EJB(Enterprise Java Bean)是JavaEE中面向服务的体系架构的解决方案,可以将功能封装在服务器端,以服务的形式对外发布,客户端在无需知道方法细节的情况下来远程调用方法,大大降低了模块间的耦合性,提高了系统的安全性和可维护性。
EJB实际上是服务器端运行的一个对象,只不过该对象所对应的类并不被客户端所知,该对象对外发布的是一个服务名称,并提供一个可以被客户端调用的接口。通俗点说,EJB就是一个可以被客户端调用,但是并不让客户端知道源代码的类的对象。

因此,EJB并不是普通的Java Bean,普通的JavaBean是一个符合某种规范的Java类文件,只能作为一个类被调用,只有调用的时候才运行,是一个进程内组件。而EJB并不是一个单独的文件,其组成包括:

  1. 类文件:实现基本方法的类,封装了需要实现的商务逻辑,数据逻辑或消息处理逻辑,具有一定的编程规范,代码不能被客户端得知。

  2. 接口文件:接口是EJB组件模型的一部分,里面提供的方法一般和需要被远程调用的方法一致,一般情况下,要求类文件必须和接口中的定义保持一致性。

  3. 必要的情况下,编写一些配置文件,用于描述EJB部署过程中的一些信息。

EJB可以作为一个服务被调用,可以单独运行,是一个进程级组件。EJB中还提供了一些安全管理、事务控制功能,使得我们调用EJB时,不需要太多地束缚于这些问题的编码。

EJB 定义了四种类型的组件:

  1. Session Bean:会话Bean,封装业务逻辑,负责完成某个操作。根据生命周期的不同,又可以分为:

    (1) Stateless Session Bean: 无状态会话Bean,不存储用户相关信息,一般说来,在服务器端,一个Bean对象可能为很多客户服务,如下图所示:
    figure1
    (2) Stateful Session Bean: 有状态会话Bean,可以存储用户相关信息,在服务器端,一个Bean对象只为一个客户服务,如下图所示:
    figure2

  2. Entity Bean:实体Bean,类似Hibernate,封装数据库中的数据,代表底层数据的持久化对象,把表中的列映射到对象的成员,主键在实体Bean中具有唯一性,一个实体Bean对象对应表中的一行,这将在下一章讲解。

  3. Message Driven Bean:消息驱动Bean,是一种异步的无状态组件,和无状态会话组件具有相似性,是JMS消息的消费者,可以和JMS配合起来使用。

3.1.2 EJB运行原理

在EJB中,常用的的组件有:客户端、接口(远程接口或者本地接口)、EJB实现类、JNDI名称等。它们之间的关系如下图所示:
figure3
对于一个业务操作,其执行步骤为:
首先,服务器端将EJB发布为一个JNDI名称,并提供一个接口文件。不过,值得注意的是,如果客户端和EJB运行在同一个容器内,可以提供的是本地(Local)接口,如果运行在不同的Java虚拟机内,提供的是远程(Remote)接口。接下来步骤如下:

  1. 客户端向服务器发起连接,在服务器上寻找相应的JNDI名称,如果找到,返回一个对象。

  2. 客户端将该对象强制转换为接口类型。

  3. 客户端调用接口中的方法,实际上调用了服务器端EJB内的方法。

因此,利用EJB编程,有以下几个步骤:

  1. 编写EJB实现类。

  2. 编写接口。

  3. 部署到服务器中,设定JNDI名称。

  4. 编写客户端,并将接口拷贝给客户端,将JNDI名称公布,客户端调用EJB。

3.2 实验实现过程

3.2.1 校友信息类创建

包含校友信息成员变量以及相应的getter和setter方法;
figure5

3.2.2 接口创建

创建接口类,包括基本的增删改查方法;
接口类

3.2.3 创建接口的实现类

创建实现类,并用Stateful注解,表明这是一个有状态的会话bean;
实现类
连接数据库并创建数据库表ALUMNI来存储校友信息;
数据库连接
以下为实现类实现的接口方法:以select方法为例展示数据库访问操作;
select

3.2.4 以假乱真的校友信息生成器

校友各个信息的自动生成:

public String getRandomName() {
        String[] firstNameArray = { "李", "王", "张", "刘", "陈", "杨", "赵", "黄", "周", "吴", "徐", "孙", "胡", "朱", "高", "欧阳", "太史", "端木", "上官", "司马" };// 20个姓,其中5个复姓
        String[] lastNameArray = { "伟", "勇", "军", "磊", "涛", "斌", "强", "鹏", "杰", "峰", "超", "波", "辉", "刚", "健", "明", "亮", "俊", "飞", "凯", "浩", "华",
                "平", "鑫", "毅", "林", "洋", "宇", "敏", "宁", "建", "兵", "旭", "雷", "锋", "彬", "龙", "翔", "阳", "剑", "静", "敏", "燕", "艳", "丽", "娟", "莉", "芳", "萍", "玲", "娜", "丹", "洁", "红", "颖", "琳", "霞", "婷", "慧",
                "莹", "晶", "华", "倩", "英", "佳", "梅", "雪", "蕾", "琴", "璐", "伟", "云", "蓉", "青", "薇", "欣", "琼", "宁", "平", "媛" };// 80个常用于名字的单字
        int firstPos = (int) (20 * random());
        StringBuilder name = new StringBuilder(firstNameArray[firstPos]);
        int lastLen = (int) (2 * random()) + 1;
        for (int i = 0; i < lastLen; i++) {
            int lastPos = (int) (80 * random());
            name.append(lastNameArray[lastPos]);
        }
        return name.toString();
    }

    public String getRandomGender() {
        String[] genderArray = { "男", "女"};
        int genderPos = (int) (2 * random()) ;
        StringBuilder gender = new StringBuilder(genderArray[genderPos]);
        return gender.toString();
    }

    public String getRandomBirthday(int year){
        int byear=year-18;
        int month=(int) (12 * random())+1; //生成[1,12]的整数;月
        int day;
        if(month==2)
        {
            day=(int) (28 * random())+1;
        }
        else
        {
            day=(int) (30 * random())+1;
        }
        return byear+"-"+month+"-"+day;
    }



    public String getRandomWechat() {
        char[] numArray = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
        int wechatLen = (int) (5 * random()) + 7; // wechat长度可能为7~11位
        StringBuilder wechat = new StringBuilder();
        for (int i = 0; i < wechatLen; i++) {
            int wechatPos = (int) (10 * random());
            wechat.append(numArray[wechatPos]);
        }
        return wechat.toString();
    }

    public String getRandomEnterYear() {
        int enter = (int) (24 * random()) + 1990;
        return String.valueOf(enter);
    }

    public String getRandomGraduateYear(int year) {
        int gyear = year+4;
        return String.valueOf(gyear);
    }

    public String getRandomPhone() {
        String[] telFirst="184,135,136,137,138,139,150,151,152,157,158,159,130,131,132,155,156,133,153".split(",");
        int index=(int) (telFirst.length * random());
        String first=telFirst[index];
        String second=String.valueOf((int) (8888 * random())+10000).substring(1);
        String thrid=String.valueOf((int) (9100 * random())+10000).substring(1);
    return first+second+thrid;
    }

    public String getRandomEmail() {
        int length = (int) (10 * random())+6;
        String base ="abcdefghijklmnopqrstuvwxyz0123456789";
        String[] email_suffix = {"@gmail.com","@yahoo.com","@msn.com","@hotmail.com","@aol.com","@ask.com","@live.com","@qq.com","@0355.net","@163.com",
                        "@163.net","@263.net","@3721.net","@yeah.net","@googlemail.com","@126.com","@sina.com","@sohu.com","@yahoo.com.cn"};
        StringBuffer email = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = (int) (random() * base.length());
            email.append(base.charAt(number));
        }
        email.append(email_suffix[(int) (random() * email_suffix.length)]);
        return email.toString();
    }


    public String getRandomWorkPlace() {
        String[] road="长城南路,流亭立交桥,虹桥广场,华城路,康城街,正阳路,和阳广场,中城路,江城大厦,顺城路,安城街,山城广场,春城街,国城路,泰城街,德阳路,明阳大厦,春阳路,艳阳街,秋阳路,硕阳街,青威高速,瑞阳街,丰海路,双元大厦,天津路,保定街,安徽路,河北大厦,黄岛路,北京街,莘县路,台西纬四街,台西纬二路,西陵峡二街,西陵峡三路,台西纬三广场,台西纬五路,明月峡大厦,青铜峡路,台西二街,观音峡广场,瞿塘峡街,台西四街,三门峡路,寿张街,嘉祥路,南村广场,范县路,西康街,云南路,滋阳街,邹县广场,濮县街,磁山路,汶水街,西藏路,信号山支路,延安一街,信号山路,兴安支街,福山支广场,红岛支大厦,金口二街,海阳路,龙口街,恒山路,鱼山广场,掖县路,福山大厦,红岛路,常州街,大学广场,龙华街,齐河路,莱阳街,黄县路,张店大厦,祚山路,苏州街,华山路,伏龙街,江苏广场,龙江街,王村路,琴屿大厦,齐东路,京山广场,龙山路,牟平街,延安三路,延吉街,南京广场,东海东大厦,银川西路,海口街,山东路,太平角三大厦,漳州路一路,漳州街二街,新湛二路,三明北街,新湛支路,湛山五街,泰州三广场,东海一大厦,天台二路,闽江二广场,闽江一大厦,屏东支路,大尧三路,晓望支街,秀湛二路,逍遥三大厦,澄海路,莆田街,海游路,镇江街,石岛广场,宜兴大厦,旌德路,汇泉广场,宁国路,泉州街,如东路,奉化街,鹊山广场,莲岛大厦,华严路,嘉义街,古田路,南平广场,秀湛路,长汀街,湛山路,徐州大厦,丰县广场,汕头街,新竹路,黄海街,安庆路,基隆广场,韶关路,云霄大厦,新安路,仙居街,屏东广场,晓望街,海门路,珠海街,上杭路,永嘉大厦,冠县支广场,小港一大厦,市场一路,小港二街,清平路,广东广场,新疆路,博平街,港通路,小港沿,福建广场,高唐街,茌平路,港青街,高密路,阳谷广场,平阴路,夏津大厦,邱县路,渤海街,恩县广场,旅顺街,长清街,长安路,惠民街,禹城街,临清路,东阿街,吴淞路,大港沿,辽宁路,棣纬二大厦,大港纬一路,无棣三街,黄台支广场,大港三街,无棣一路,贮水山大厦,泰山支路,大港一广场,无棣四路,大连支街,大港二路,锦州支街,德平广场,高苑大厦,长山路,乐陵街,临邑路,嫩江广场,合江路,大连街,博兴路,蒲台大厦,黄台广场,城阳街,临淄路,安邱街,临朐路,青城广场,商河路,热河大厦,包头路,无棣街,铁山广场,锦州街,桓台路,兴安大厦,邹平路,胶东广场,章丘路,丹东街,华阳路,青海街,泰山广场,顺兴街,利津路,阳明广场,人和路,郭口大厦,营口路,昌邑街,标山路,云溪广场,太清路".split(",");
        int index=(int) (road.length * random());
        String first=road[index];
        String second=String.valueOf((int)(random()*11+100))+"号";
        return first+second;
    }

    public String getRandomCity(){
        String citys[] = {"北京","广东","山东","江苏","河南","上海","河北","浙江","香港","山西","陕西","湖南","重庆","福建","天津","云南","四川","广西","安徽","海南","江西","湖北","山西","辽宁","内蒙古"};
        int index=(int) (citys.length * random());
        return citys[index];
    }

    public String getRandomJob(){
        String jobs[] = {"大学老师","C++程序员","Java程序员","PHP程序员","前端程序员","运维","中学老师","分析师","经理","工程师","科学家","医生","总经理","设计师","商人"};
        int index=(int) (jobs.length * random());
        return jobs[index];
    }

生成校友信息:

 public void setRandomStudent(){
        this.studentName = getRandomName();
        this.gender=getRandomGender();
        this.enterYear = getRandomEnterYear();
        int year=Integer.parseInt(enterYear);
        this.birthday=getRandomBirthday(year);
        this.graduateYear=getRandomGraduateYear(year);
        this.city=getRandomCity();
        this.email=getRandomEmail();
        this.job=getRandomJob();
        this.phone=getRandomPhone();
        this.workplace=getRandomWorkPlace();
        this.wechat=getRandomWechat();
    }

生成校友信息存入数据库:

@Override
    public void initStudent(){
        try {

            SchoolFellow schoolFellow =new SchoolFellow();
            for(int i=0;i<5;i++)
            {
                schoolFellow.setRandomStudent();
                String sql="insert into ALUMNI(studentName,gender,birthday,enterYear,graduateYear,city,workplace,job,phone,email,wechat) " +
                        "values('"+ schoolFellow.getStudentName()+"','"+ schoolFellow.getGender()+"','"+ schoolFellow.getBirthday()+"','"+ schoolFellow.getEnterYear() +"','"
                        + schoolFellow.getGraduateYear()+"','"+ schoolFellow.getCity()+"','"+ schoolFellow.getWorkplace()+"','"+ schoolFellow.getJob()+"','"+ schoolFellow.getPhone()
                        +"','"+ schoolFellow.getEmail()+"','"+ schoolFellow.getWechat()+"')";
                stmt.execute(sql);
            }
            System.out.println("init students successful");

        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

3.2.5 运行结果

服务器端:
在这里插入图片描述
登录:
在这里插入图片描述
删除:
在这里插入图片描述
插入:
在这里插入图片描述
修改:
在这里插入图片描述
第二次登录显示登录次数和上次登录时间:
在这里插入图片描述

4、总结

1、端口冲突问题:刚开始服务器端运行时会出现端口冲突,但是修改wildfly配置文件standalone.xml修改端口是没有用的,所以后面就把和它冲突的其他服务进程关闭了。
2、要理解清楚EJB调用的原理,这样对于在实验中遇到的问题才能准确定位和解决。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值