EJB3 阶段总结+一个EJB3案例 (2)

摘要:
在上一篇博文中,基本上描述了程序的体系结构,EJB模块分为五层。使用@EJB注释来调用dao层的对象。绑定表示类。服务代表服务。它通常注册到服务的绑定。服务包括web服务访问的地址。为了便于维护,在web服务项目中,类型节点中的元素定义通常是分开的,即模式文件。

这篇博文接着上一篇博文的EJB案例。

在上一篇博文中,将程序的架构基本给描述出来了,EJB模块分为5层。

1)DB层,即数据库层

    在则一部分,我使用的数据库为mysql。在EJB程序中,访问数据库是通过Jboss中配置好的数据源进行的,然后在数据库中建立相应的数据库,不用建立表,在程序中使用JPA后通过Jboss启动会自动在数据库中间表

    具体的,可以看我之前写过的博文 wildfly8+jpa EntityBean 简单入门 在这篇博文中具体讲解了如何在Jboss中绑定一个数据源

2)dao层

    在这一层中,首先设计好具体的对象EntityBean,然后通过JPA的注解,将EntityBean和数据库进行映射。

    在这里还要使用一个EntityManage对象,该对象用于操作数据库,通过该对象可以使程序进行持久化,免去了JDBC时复杂的代码,该对象可分为容器管理和Bean管理,这里使用的是容器管理的EntityManage,通过@PersistenceContext注解将对象注入

    并且在该层中,通过接口的方式实现该层,并将该层定义为Local和Stateless,应为该层主要是用于该EJB的内部使用,是在一个JVM中的调用所以使用@Local注解的方式更加的节省资源。

    在该层中的方法均抛出继承RunTimeException的异常,为之后的Rollback做准备

3)Business层

    该层是业务层,其设计方式同dao层类似,均为实现类和接口方式,使用@Stateless和@Local将接口继续暴露给下一层。

    使用@EJB注解调用dao层的对象。(@EJB只能注入EJB对象,@Resource可以注入普通对象)

    在该层中,继续抛出RunTimeException异常,以支持回滚,在此处使用容器管理的事物方式,不需要代码管理开头结束,通过RunTimeException来管理

4)Service层

    服务层,主要是用于暴露给其他模块调用,在这里我使用的是WebService的方式,当然也可以通过Remote的方式(个人觉得太low),其设置为@Stateless的EJB

    在设计这一层代码时,应为使用的是WebService的模式,便产生一个问题:即现有Wsdl还是先有代码。前者的工作量无疑是大于后者的,在设计之初我也更倾向于后者,但项目组的技术大牛给了我很多的启示。一般的企业级javaee项目都会有许多不同的模块,甚至于在有的企业中还有C、C#等各种不同语言写的模块。而在这种情况下,如果使用的是先有代码再有wsdl,无疑开发速度将会加快,但在后期不同模块间使用WebService进行交互时会产生许多问题,如传输的参数在两个模块间类型不一致、参数的个数不一致等等。所以在这里我使用的是先有wsdl再有代码的方式。

     一个wsdl分为5个类型节点:types、message、porttype、binding、service。

     一个binding表示一个类。一个prottype中包含了具体的方法返回对象。message表示的是具体的方法参数通常成对出现。types中包含各种基本的类型(即组成方法参数的元素)。service表示的是服务,通常是将一个binding注册到服务上,service中包括了webservice访问的地址。

     为了便于维护,在一个webservice项目中,通常将types节点中的元素定义部分分割出去,即schema文件。(schema的作用类似与DTD,用于约束xml的节点元素,其适用性强于DTD,目前的项目大部分使用schema)

     话不多讲,先上wsdl和一个最基础的schema:

EJB3 阶段总结+一个EJB3案例 (2)第1张EJB3 阶段总结+一个EJB3案例 (2)第2张
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
    xmlns:tns="http://www.welv.com/wsdl/TeaStuService" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="TeaStuService"
    targetNamespace="http://www.welv.com/wsdl/TeaStuService"
    xmlns:addGroupType="http://www.welv.com/schema/business/addGroupType"
    xmlns:addTeacheType="http://www.welv.com/schema/business/addTeacheType"
    xmlns:findTeacheType="http://www.welv.com/schema/business/findTeacheType">
    <wsdl:types xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:schema targetNamespace="http://www.welv.com/wsdl/TeaStuService">
            <xsd:import schemaLocation="../schema/business/addGroupType.xsd"
                namespace="http://www.welv.com/schema/business/addGroupType" />
            <xsd:import schemaLocation="../schema/business/addTeacheType.xsd"
                namespace="http://www.welv.com/schema/business/addTeacheType" />
            <xsd:import schemaLocation="../schema/business/findTeacheType.xsd"
                namespace="http://www.welv.com/schema/business/findTeacheType" />
        </xsd:schema>
    </wsdl:types>

    <wsdl:message name="addGroupRequest">
        <wsdl:part element="addGroupType:addGroupRequest" name="addGroupRequest" />
    </wsdl:message>
    <wsdl:message name="addGroupResponse">
        <wsdl:part element="addGroupType:addGroupResponse" name="addGroupResponse" />
    </wsdl:message>
    <wsdl:message name="addTeacheRequest">
        <wsdl:part element="addTeacheType:addTeacheRequest" name="addTeacheRequest" />
    </wsdl:message>
    <wsdl:message name="addTeacheResponse">
        <wsdl:part element="addTeacheType:addTeacheResponse" name="addTeacheResponse" />
    </wsdl:message>
    <wsdl:message name="findTeacheRequest">
        <wsdl:part element="findTeacheType:findTeacheRequest" name="findTeacheRequest" />
    </wsdl:message>
    <wsdl:message name="findTeacheResponse">
        <wsdl:part element="findTeacheType:findTeacheResponse" name="findTeacheResponse" />
    </wsdl:message>
    
    
    <wsdl:portType name="TeaStuService">
        <wsdl:operation name="addGroup">
            <wsdl:input message="tns:addGroupRequest" />
            <wsdl:output message="tns:addGroupResponse" />
        </wsdl:operation>
        <wsdl:operation name="addTeache">
            <wsdl:input message="tns:addTeacheRequest" />
            <wsdl:output message="tns:addTeacheResponse" />
        </wsdl:operation>
        <wsdl:operation name="findTeache">
            <wsdl:input message="tns:findTeacheRequest" />
            <wsdl:output message="tns:findTeacheResponse" />
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="TeaStuServiceBinding-SOAP11HTTP" type="tns:TeaStuService">
        <soap:binding style="document"
            transport="http://schemas.xmlsoap.org/soap/http" />
        <wsdl:operation name="addGroup">
            <soap:operation soapAction="http://www.welv.com/wsdl/TeaStuService/addGroup" />
            <wsdl:input>
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="addTeache">
            <soap:operation soapAction="http://www.welv.com/wsdl/TeaStuService/addTeache" />
            <wsdl:input>
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
        <wsdl:operation name="findTeache">
            <soap:operation soapAction="http://www.welv.com/wsdl/TeaStuService/findTeache" />
            <wsdl:input>
                <soap:body use="literal" />
            </wsdl:input>
            <wsdl:output>
                <soap:body use="literal" />
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="TeaStuService-SOAP11HTTP">
        <wsdl:port binding="tns:TeaStuServiceBinding-SOAP11HTTP"
            name="TeaStuServiceSOAP">
            <soap:address location="http://localhost:8080/service/TeaStuServiceSOAP" />
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>
wsdl
EJB3 阶段总结+一个EJB3案例 (2)第1张EJB3 阶段总结+一个EJB3案例 (2)第4张
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    targetNamespace="http://www.welv.com/schema/common/common" xmlns:tns="http://www.welv.com/schema/common/common"
    elementFormDefault="qualified">

    <xsd:simpleType name="nameType">
        <xsd:restriction base="xsd:string"></xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="ageType">
        <xsd:restriction base="xsd:integer"></xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="addressType">
        <xsd:restriction base="xsd:string"></xsd:restriction>
    </xsd:simpleType>

    <xsd:simpleType name="idType">
        <xsd:restriction base="xsd:int"></xsd:restriction>
    </xsd:simpleType>


    <xsd:simpleType name="infoType">
        <xsd:restriction base="xsd:string"></xsd:restriction>
    </xsd:simpleType>


    <xsd:element name="name" type="tns:nameType"></xsd:element>

    <xsd:element name="address" type="tns:addressType"></xsd:element>

    <xsd:element name="age" type="tns:ageType"></xsd:element>
  
    <xsd:element name="id" type="tns:idType"></xsd:element>

    <xsd:element name="info" type="tns:infoType"></xsd:element>
</xsd:schema>
schema

     在schema中可以看到,在types节点中,使用了import节点,将schema引入了wsdl中,而schema则将方法的参数给细分,通过最基本的common文件来组合成各个方法的参数,有利于后期的维护,如Student中的name的字段长度设置为7,则可通过修改common文件中的定义便可。

     wsdl准备好后,将其放入EJB工程的Src目录下,然后使用命令:wsimport -keep -verbose -s E:ResourcesJavaEcAEJB-allejbModule E:ResourcesJavaEcAEJB-allejbModuleMETA-INFwsdlTeaStuService.wsdl   将wsdl对应的java代码生成到src目录下,这样一来wsdl对应的java代码便有了。

     以下是我使用命令生成的java代码,实现的带有Webservice功能的EJB代码:

@Stateless
@WebService(name = "TeaStuService", targetNamespace = "http://www.welv.com/wsdl/TeaStuService", wsdlLocation = "META-INF/wsdl/TeaStuService.wsdl")
public class TeaStuService_SOAP implements
        com.welv.wsdl.teastuservice.TeaStuService {

    @EJB
    private TeaStuService teaStuService;

    public AddGroupResponseType addGroup(AddGroupRequestType addGroupRequest) {
        // TODO Auto-generated method stub
        AddGroupResponseType dd = new AddGroupResponseType();
        dd.setInfo("wwwww");
        return dd;
    }

    public AddTeacheResponseType addTeache(AddTeacheRequestType addTeacheRequest) {

        TeacheType tt = addTeacheRequest.getTeache();
        Teache t = new Teache();
        t.setAddress(tt.getAddress());
        t.setAge(tt.getAge());
        t.setName(tt.getName());
        AddTeacheResponseType atr = new AddTeacheResponseType();
        atr.setInfo(teaStuService.addTeache(t));
        return atr;

    }

    public FindTeacheResponseType findTeache(
            FindTeacheRequestType findTeacheRequest) {
        Teache teache = teaStuService.findTeache(findTeacheRequest.getId());
        FindTeacheResponseType ftr = new FindTeacheResponseType();
        TeacheType tt = new TeacheType();
        tt.setAddress(teache.getAddress());
        tt.setAge(teache.getAge());
        tt.setId(teache.getId());
        tt.setName(teache.getName());
        ftr.setTeache(tt);
        return ftr;
    }

}

    该类是继承由wsdl生成的java接口的一个类。在类的开头使用@WebService注解,并将wsdl的相对路径注册其中,并要有name和targetnamespace两个属性

    将该类部署到Jboss8中,我使用的是Eclipse部署的方式。

    EJB3 阶段总结+一个EJB3案例 (2)第5张

    在控制台的log中可以看到一个地址,即wsdl中Service节点中定义的webservice地址,在该地址后面加上?wsdl即可访问部署到jboss上的webservice服务。

5)测试

    部署完EJB后,使用SoapUI进行测试,Soap的使用不在这里描述。

    使用webservice的访问地址将测试工程在SoapUI中建立好后,首先测试的是添加一个Teache对象:

    EJB3 阶段总结+一个EJB3案例 (2)第6张

     从图中的信息可看出访问成功,然后使用查找Teache的功能检验上一个case是否成功插入数据库

      EJB3 阶段总结+一个EJB3案例 (2)第7张

     查找成功,WebService和EJB的功能实现

*********************************************************

技术点:

1)wsdl开发中,使用的targetnamespace即目标名称空间,他表示的是文件本身,所以在文件中使用xmlns:tns=“targetnamespace URL”来表示应用自身的节点,而要使用其他的schema文件中的节点会使用import也是通过namespace来引用

2)在EJB中通常使用@Stateless的EJB,应为该类型占内存少

上述EJB的继续开发

1)目前使用的是SoapUI进行访问WebService服务,但实际的开发中,还是会有许多不同的模块,而由于历史原因这些模块的WebService接口往往是不同的,会导致不同模块间难以交互,这时可以使用ESB的技术,将ESB作为一个中转站,将不同的Wsdl的信息进行交换转发

2)在EJB的事物中,可以支持JDBC事物和JTA事物,我使用的是JTA事物,但在程序中只管理了JDBC的事物并没有跨资源管理事物

3)没有使用更加复杂的sql语句

4)可以使用Jmoke来进行单元测试

在上述的EJBdemo中,还有一些问题尚未解决

1)我之前设想的是将wsdl文件以及wsdl生成的java文件独立的使用一个java工程,然后将其打成jar包,在EJB中使用该jar包,但编译可以通过,部署到jboss中则会产生无法找到jar的异常(notfundclassException)

2)如何使用maven搭建一个EJB工程

3)事物管理的时候,runtimeException的作用不是很清楚

###代码下载

免责声明:文章转载自《EJB3 阶段总结+一个EJB3案例 (2)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇rabbitmq的笔记(四)小版本的升级操作oracle 嵌套表 老猫下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

.NET调用Java写的WebService

最近遇到一个用.net调用java写的webservice的应用,对方程序员提供了一个后缀为wsdl的文件,这个跟.Net里面生成的wsdl文件差不多,起初没什么概念就查了点资料,知道可以将这个wsdl文件编译动态库直接调用,也就是生成一个代理了,这个跟以往经常将.net的webservice描述地址进行编译似乎差不多,于是就尝试这写,还基本能实现。基本格...

EhCache之最简单的缓存框架

一、简介 Ehcache是一个用Java实现的使用简单,高速,实现线程安全的缓存管理类库,ehcache提供了用内存,磁盘文件存储,以及分布式存储方式等多种灵活的cache管理方案。同时ehcache作为开放源代码项目,采用限制比较宽松的Apache License V2.0作为授权方式,被广泛地用于Hibernate, Spring,Cocoon等其他...

Ubuntu20.04.1LTS系统Super simple美化与配置

啰嗦两句 再次安装好了Ubuntu20.04系统,每次的回归都能get到一些新的姿势;本篇主要用于记录和分享自己本次对系统的美化和配置。 桌面效果 主题部分 应用程序主题 光标主题 图标主题 shell主题我最终选择了和应用程序主题自带的shell 扩展插件 扩展插件网站将Dash合并到顶栏Dash to Panel配置文件如下 [/] appicon-...

多租户数据隔离的三种方案

另附一片论文,关于SaaS和多租户下的数据存储与扩容:http://www.360doc.com/document/12/0823/16/10636892_231933452.shtml 一、多租户在数据存储上存在三种主要的方案,分别是:1. 独立数据库这是第一种方案,即一个租户一个数据库,这种方案的用户数据隔离级别最高,安全性最好,但成本较高。  优点:...

Selenium示例集锦--常见元素识别方法、下拉框、文本域及富文本框、鼠标操作、一组元素定位、弹窗、多窗口处理、JS、frame、文件上传和下载

元素定位及其他操作 0、常见的识别元素的方法是什么? 1 driver.find_element_by_id() 2 driver.find_element_by_name() 3 driver.find_element_by_class_name() 4 driver.find_element_by_tag_name() 5 driver.find...

02-OpenLDAP配置

OpenLDAP配置 在OpenLDAP 2.4版本中,配置OpenLDAP的方法有两种:一种通过修改配置文件实现配置,另一种通过修改数据库的形式完成配置。 通过配置数据库完成各种配置,属于动态配置且不需要重新启动slapd进程服务。此配置数据库(cn=config)包含一个基于文本的集合LDIF文件(位于/etc/openldap/slapd.d目录下)...