1.2 JavaEE核心技术
JavaEE为了适应大型企业级系统开发的需要,制定和规范了大量的技术,JavaEE核心技术平台如图1.5所示。
图1.5 JavaEE核心技术平台
下面对JavaEE所涉及的核心技术进行简要讲解。
1.2.1 JSP(Java服务页面)
JSP(Java Server Pages)是由Sun公司组织其他公司一起建立的一种动态网页技术标准。JSP技术的推出是为了对抗ASP,但它又有点类似ASP技术,它可以在传统的网页HTML文件中插入Java程序段和脚本文件及JSP标记。用JSP开发的Web应用是跨平台的,既能在Linux下运行,也能在其他操作系统上运行。
JSP的运行方式是:当客户端向服务器发出请求时,被请求的JSP首先被Web应用服务器编译成Servlet并执行,然后将所产生的结果作为一个HTML文件传给浏览器。如果该JSP文件没有被修改过,当客户端再次向服务器发出请求时,JSP文件将不会再被编译,而是直接执行已编译好的Servlet,从而加快了访问速度。
JSP内置了6种对象,它们分别是:
● Request,该对象封装了用户提交的信息,通过调用该对象相应的方法可以获取用户提交的信息。
● Response,该对象对客户的请求做出动态的响应,向客户端发送数据。
● Session,该对象在第一个JSP页面被装载时自动创建,同时产生一个ID号,JSP引擎同时将这个ID号发送到客户端,存放在Cookie中,当客户再次访问连接该服务器的其他页面时,不再分配给客户新的Session对象,这样Session对象和客户之间就建立了一一对应的关系。直到客户关闭浏览器后,服务器端该客户的Session对象才被取消,并且和客户的会话对应关系消失,当客户重新打开浏览器再次连接到该服务器时,服务器为该客户再创建一个新的Session对象。
● Application,当服务器启动时该对象自动创建,当客户在所访问网站的各个页面之间浏览时,共享同一个Application对象,直到服务器关闭。与Session对象不同的是所有客户端共享一个Application对象,而Session对象是一个客户共享一个Session对象。
● Out,该对象是一个输出流,用来向客户端输出各种数据。
● Cookie,该对象是服务器保存在客户端硬盘上的一段文本,它以“关键字=值”的格式来保存内容,并且允许用户自己创建和读取它。
1.2.2 Servlet
借助Java的跨平台特性,Servlet被设计成一种独立于平台和协议的服务器端的Java应用程序,可以生成动态的Web页面。Servlet由Web服务器进行加载,该Web服务器必须包含支持Servlet的Java虚拟机。Servlet不是独立的Java应用程序,没有main方法,它不是由用户直接调用,而是由容器调用的。
JSP编译后就是Servlet,但它并没有增强Servlet的功能,只是比直接使用Servlet进行编程更加方便。Servlet采用请求响应的工作方式,Servlet技术作为Web服务器功能的增强器,其功能涵盖了从客户端请求响应动态生成文档到保证会话安全、访问后台数据库服务器等。
每个Servlet都有自己的生命周期,都包含init和destroy方法,每个Servlet都需要实现Servlet接口,其主要的逻辑将集中在service方法中。当一个请求映射到一个Servlet时,该容器执行下列步骤:
01 如果一个Servlet的实例并不存在,Web容器将加载Servlet类,创建一个Servlet类的实调用init方法初始化Servlet实例。
02 调用service方法,传递一个请求和响应对象。
03 如果该容器要移除这个Servlet,可调用Servlet的destroy方法来结束该Servlet。Servlet的生命周期包括加载、初始化、处理客户端请求及服务结束。
1.加载和初始化
在Servlet的生命周期中,仅执行一次init方法,它是在服务器装入Servlet时执行的。可以配置服务器,以便在启动服务器或客户机首次访问Servlet时装入Servlet。无论有多少客户机访问Servlet,都不会重复执行init方法。
2.处理客户端请求
每一个请求由ServletRequest类型的对象代表,而Servlet使用ServletResponse返回该请求。这些对象被作为service方法的参数传递给Servlet,service方法是Servlet的核心。每当一个客户请求一个ServletRequest对象时,该对象的service方法就要被调用。
当一个客户通过HTML表单发出一个HTTP POST请求时,doPost方法被调用;当一个客户通过HTML表单发出一个HTTP GET请求或直接请求一个URL时,doGet方法被调用。与GET请求相关的参数添加到URL的后面,并与这个请求一起发送。
在HTTP请求的情况下,容器必须提供代表请求和响应的HttpServletRequest和HttpServletResponse的具体实现。
3.服务结束
destroy方法和init方法一样,仅执行一次,即在服务器停止且卸载Servlet时执行该方法。当服务器卸载Servlet时,将在所有service方法调用完成后,或在指定的时间间隔过后调用destroy方法。一个Servlet在运行service方法时可能会产生其他的线程,因此请确认在调用destroy方法时,这些线程已终止或完成。一旦destroy方法被调用,容器就不会再向该实例发送任何请求;如果容器需要再使用该Servlet,则必须创建新的实例。
1.2.3 EJB(企业级JavaBean)
EJB是一个Java服务器端组件开发的规范,定义了一个用来开发面向对象分布式应用组件的标准方法,软件厂商根据它来实现EJB服务器。EJB主要由3种Bean组成:
● 会话Bean,用于实现业务逻辑,它可以是有状态的,也可以是无状态的。每当客户端请求时,容器就会选择一个会话Bean来为客户端服务。
● 实体Bean,用于实现O/R(对象/关系)映射,负责将数据库中的表记录映射为内存中的Entity对象,事实上,创建一个实体Bean对象相当于新建一条记录;修改一个实体Bean时,容器会自动将Entity Bean的状态和数据库同步;删除一个实体Bean会同时从数据库中删除对应记录。
● 消息驱动Bean,它基于JMS消息,只能接收客户端发送的JMS消息然后处理。它实际上是一个异步的无状态会话Bean,客户端调用消息驱动Bean后无须等待,立刻返回,消息驱动Bean将异步处理客户端请求。
Java程序员可以将一些EJB组件组合起来,从而方便、快捷地构建起分布式应用程序。EJB规范在简化分布式应用程序开发复杂性方面也做了大量的工作,EJB程序员不必太担心事务处理、多线程、资源管理等方面的问题,可以专注于支持应用所需的商业逻辑,而不用担心周围框架的实现问题。使用EJB可以使整个程序分块明确,并且EJB可以使用其他EJB或JDBC等服务,从而增强了分布式应用程序的可扩展性和性能;另外,EJB的使用增强了整个系统程序的可靠性、可管理性和可移植性。
EJB的调用过程由如下几步组成:先初始化上下文InitialContext,然后获取远程的或者本地的Home接口,再进行Home.create(),获取远程EJB对象,最后通过EJB对象调用业务方法。
1.2.4 JDBC(Java数据库连接)
JDBC是Java提供的用来执行SQL语句的Java API,可以为多种关系数据库提供统一访问。它由一组用Java语言编写的类和接口组成,是用于Java应用程序连接数据库的标准方法。有了JDBC,向各种关系数据发送SQL语句就是一件很容易的事了。像ODBC一样,JDBC对开发者屏蔽了一些细节问题;另外,JDBC对数据库的访问也具有平台无关性,JDBC使用已有的SQL标准并支持与其他数据库连接标准。
JDBC用来和数据库打交道的一般步骤是:加载驱动程序、与数据库建立连接、发送SQL语句、处理结果。示意代码如下:
//加载驱动程序 Class.forName("com.ibm.db2.jcc.DB2Driver"); //建立连接 Connection con = DriverManager.getConnection (" jdbc:db2://10.1.1.10:50000/ db2 ","db2admin"," db2admin "); //创建Statement,发送SQL语句 Statement stmt = con.createStatement(); //获取结果集 ResultSet rs = stmt.executeQuery(" select * from user "); //循环获取结果集中的值 while(r.next()){ String s=r.getString("name"); }
目前,比较常见的JDBC驱动程序可分为以下4类。
● JDBC-ODBC桥+ODBC驱动程序:JDBC桥产品利用ODBC驱动程序提供JDBC访问。这种类型的驱动程序最适合于企业网,或者用Java编写的具有三层结构的应用程序服务器。
● 本地API:这种类型的驱动程序把客户机API上的JDBC调用转换为Oracle、Sybase、Informix、DB2或其他DBMS的调用。
● JDBC网络纯Java驱动程序:这种驱动程序将JDBC转换为与DBMS无关的网络协议,之后这种协议又被某个服务器转换为一种DBMS协议。这种网络服务器中间件能够将它的纯Java客户机连接到多种不同的数据库上,所用的具体协议取决于提供者。这是最为灵活的JDBC驱动程序,有可能所有的这种解决方案的提供者都提供适合于Intranet用的产品。
● 本地协议纯Java驱动程序:这种类型的驱动程序将JDBC调用直接转换为DBMS所使用的网络协议。这将允许从客户机上直接调用DBMS服务器,是Intranet访问的一个很实用的解决方法。由于许多这样的协议都是专用的,因此数据库提供者自己将是主要来源。
1.2.5 JTA(Java事务)
一般来说,事务处理由若干个步骤组成。作为一个整体的操作过程,所有步骤必须同时操作成功或者失败。当所有的步骤都操作成功时,事务就算操作成功了;而当其中某一个步骤操作失败时,该步骤之前的操作就必须撤销。简单来说,所谓事务就是一系列必须都成功的操作,只要有一步操作失败,所有其他的步骤将都被撤销。因此,事务中有提交和回滚两个概念。
● 提交(Commit):当所有的操作步骤都被完整执行后,称该事务被提交。
● 回滚(RollBack):由于某一操作步骤执行失败,导致所有步骤都没有被提交,则事务必须回滚,即回到事务执行前的状态。
在JavaEE中,事务主要有Bean-Managed Transaction和Container-Managed Transaction两大类,其中在Bean-Managed Transaction中还会分为JDBC Transaction和JTA Transaction两种。JTA的英文全称是Java Transaction API,它为JavaEE平台提供了分布式事务服务。要用JTA进行事务界定、提交和回滚,应用程序需调用javax.transaction.UserTransaction接口中的begin、commit和rollback方法。JTA接口包含在javax.transaction和javax.transaction.xa这两个包中,进行JTA事务处理的示意代码如下:
public void test() { //获取事务 UserTransaction ut = context.getUserTransaction(); try { //事务开始 ut.begin(); //执行业务代码 … //提交事务 ut.commit(); } catch (Exception ex) { try { //事务回滚 ut.rollback(); } catch (SystemException syex) { throw new EJBException ("Rollback failed: " + syex.getMessage()); } //抛出异常 throw new EJBException ("Transaction failed: " + ex.getMessage()); } }
JTA可以实现同一事务对应不同的数据库,但它无法实现事务的嵌套。JTA只定义了一组Java接口用于描述JavaEE中事务管理器与应用程序、资源管理器及应用服务器之间的事务通信。它主要包括高层接口(即面向应用程序的接口)、XAResource接口(即面向资源的接口)及事务管理器的接口,JTA没有具体的实现,JTS是服务OTS的JTA的实现。简单地说,JTS实现了JTA接口,并且符合OTS的规范。
1.2.6 JavaMail(Java邮件服务)
JavaMail是Sun公司提供给开发者处理电子邮件的编程接口,它可以方便地执行一些常用的邮件传输。在使用JavaMail开发邮件系统之前,有必要先了解几个常用的邮件传输协议。
● SMTP:英文全称是Simple Mail Transfer Protocol,中文意思是“简单邮件传输协议”,它由RFC821定义,定义了发送邮件的机制。在JavaMail环境中,基于JavaMail的程序将和因特网服务供应商(ISP)的SMTP服务器通信,SMTP服务器会将邮件消息发送给接收方SMTP服务器,以便最终让用户经由POP或者IMAP获得。
● POP:英文全称是Post Office Protocol,中文意思是“邮局协议”,它一般被称为POP3,代表目前的版本号是3。这个协议是由RFC1939定义的。POP是一种机制,因特网上大多数用户用它得到邮件。
● IMAP:英文全称是Internet Message Access Protocol,中文意思是“因特网消息访问协议”,它是更高级的用户接收消息的协议。这个协议由RFC2060定义,它一般被称为IMAP4,代表目前的版本号是4。在用到IMAP时,邮件服务器必须支持这个协议。
● MIME:英文全称是Multipurpose Internet Mail Extensions,中文意思是“多用途的因特网邮件扩展”标准,它不是邮件传输协议,只是定义了被传输内容、附件及其他信息的格式。
核心JavaMail API由7个类组成:Session、Message、Address、Authenticator、Transport、Store及Folder。通过上述类,可以完成包括发送消息、接收消息、认证、回复消息、转发消息、管理附件等功能。使用JavaMail来发送邮件的示意代码如下:
//创建一个格式为“mail.smtp.host”的文件用来发送信息 Properties props = new Properties(); props.put("mail.smtp.host", "smtp.jspinsider.com"); //基于JavaMail的程序都至少需要一个或全部的对话目标 Session sendMailSession; sendMailSession = Session.getInstance(props, null); //邮件的传输只有送出或收到两种状态,传输将送出邮件,而存储将收取邮件 Transport transport; transport = sendMailSession.getTransport("smtp"); //封装邮件信息 Message newMessage = new MimeMessage(sendMailSession); //设定邮件内容 newMessage.setSubject("subject"); newMessage.setSentDate(new Date()); newMessage.setText("text"); //发送邮件 transport.send(newMessage);
1.2.7 JMS(Java消息服务)
JMS是JavaEE中有关面向消息中间件的技术规范,它提供创建、发送、接收和读取消息的服务。它的英文全称是Java Message Service,即Java消息服务。
JMS的消息传递机制分为两种:点对点式(P2P)和发布订阅式(P/S)。两种消息的传递机制都实现了异步传递模式,点对点式通过Queue的形式,在Consumer(消费者)和Producer (制造者)之间进行了安全连接,使得消息传递只在这两者之间进行。如果应用程序开发者希望每一条消息都能够被处理,那么应该使用P2P消息模型;发布订阅式通过Topic的形式,实现一到多的消息广播,如果一定程度的消息传递的不可靠性可以被接受的话,那么应用程序开发者也可以使用P/S消息模型。
JMS中的消息由两部分组成:报头和消息主体。报头由路由信息及有关该消息的元数据组成;消息主体则携带着应用程序的数据或有效负载。消息可以分为5种类型:简单文本(TextMessage)、可序列化的对象(ObjectMessage)、属性集合(MapMessage)、字节流(BytesMessage)和原始值流(StreamMessage)。
JMS的运行机制是:客户机将消息发送给一个主题或队列,而其他的JMS客户机则预订或监听这个虚拟通道,当JMS客户机发送消息后,它并不等待回应,而是继续执行下一条指令,消息可能最终转发到一个或多个客户机,这些客户机都不需要做出回应。发送一个消息队列的示意代码如下:
TextMessage message = queueSession.createTextMessage(); //设定要发送的消息 message.setText(msg_text); //发送消息 queueSender.send(message);
接收一个消息队列的示意代码如下:
Message m = queueReceiver.receive(); //判断接收到的消息类型是否是文本类型 if (m instanceof TextMessage) { TextMessage message = (TextMessage) m; } else { //进行其他类型的处理 }
1.2.8 RMI(远程方法调用)
RMI允许开发人员使用Java编写分布式对象,它大大增强了Java开发分布式应用的能力。RMI的英文全称是Remote Method Invocation,即远程方法调用,它支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用。
RMI用来进行通信的协议是JRMP(Java Remote Messaging Protocol,Java远程消息交换协议), JRMP是专为Java的远程对象制定的协议,是分布式应用系统的Java解决方案,但RMI对于用非Java语言开发的应用系统的支持不足,不能与用非Java语言书写的对象进行通信。
使用RMI的步骤如下:
01 定义和实现远端接口中的参数。
02 定义和实现远端接口。
03 编写服务端代码。
04 编写客户端代码。
05 生成stub和skeltion,并将stub打包到客户端JAR中,将skeltion打包到服务器端JAR中。
06 启动rmiregistry,并将服务注册到rmiregistry中,然后运行代码。
1.2.9 JNDI(Java命名和目录服务)
JNDI是Sun公司提供的一种标准的Java命名系统接口,它的英文全称为Java Naming and Directory Interface,即Java命名和目录服务。它是一个应用程序设计的API,为开发人员提供了查找和访问各种命名和目录服务的通用、统一的接口,类似于JDBC,都是构建在抽象层上。使用JNDI的示意代码如下:
Connection conn=null; try { //初始化上下文 Context ctx=new InitialContext(); //根据JNDI获取数据源 DataSource ds =(Datasource)ctx.lookup("java:comp/env/jdbc/mydb"); //获取连接 Connection c=ds.getConnection(); //进行业务处理 ... //关闭连接 c.close(); } catch(Exception e) { e.printStackTrace(); } finally { //关闭连接 if(conn!=null) { try { conn.close(); } catch(SQLException e) { } } }
为了让JNDI解析java:comp/env/jdbc/mydb,必须把<resource-ref>标签插入到web.xml文件中。web.xml文件中的示意代码如下:
<resource-ref> <description>JNDI</description> //设定数据源 <res-ref-name>jdbc/mydb</res-ref-name> <res-ref-type>javax.sql.DataSource</res-ref-type> <res-auth>Container</res-auth> </resource-ref>
1.2.10 XML(扩展标识语言)
XML的英文全称是eXtensible Markup Language,它是一种简单的数据存储语言,使用一系列简单的标记描述数据,而这些标记可以用方便的方式建立。虽然XML比二进制数据要占用更多的空间,但XML极其简单且易于掌握和使用。与数据库不同的是,XML不提供数据索引、排序、查找等功能,它仅仅是展示数据。下面展示一个XML的示例:
<?xml version="1.0"?> <employees> <employee> <name>志学</name> <sex>男</sex> <age>28</age> <department>信息化部</department> <head>项目经理</head> </employee> </employees >
SGML是所有标记语言的母语言,HTML和XML都派生自SGML,这三者之间的关系如图1.6所示。
图1.6 HTML、XML和SGML之间的关系
HTML、SGML和XML将凭借各自的特点继续用于其合适的地方,它们中的任何一个都不会使其他的废弃。HTML仍是在Web上快速发布数据的最简单的方法;SGML在高端复杂结构的应用及规范制定方面将继续适用;而对于数据广泛性和灵活性有特定要求的用户,XML则是最好的选择。
1.2.11 JMX(Java分布式管理)
JMX是一个为应用程序、设备、系统等植入管理功能的框架,它的英文全称是Java Management Extensions,即Java分布式管理。JMX可以跨越一系列异构操作系统平台、系统体系结构和网络传输协议,灵活地开发无缝集成的系统、网络和服务管理应用。
JMX的体系结构图如图1.7所示。
图1.7 JMX的体系结构图
JMX的体系结构分为以下4个层次。
● 设备层:主要定义了信息模型。在JMX中,各种管理对象以管理构件的形式存在,需要管理时,向MBean服务器进行注册。
● 代理层:主要定义了各种服务及通信模型。该层的核心是一个MBean服务器,所有的管理构件都需要向它注册,才能被管理。
● 分布服务层:主要定义了能对代理层进行操作的管理接口和构件,这样管理者就可以操作代理了。
● 附加管理协议API:定义的API主要用来支持当前已经存在的网络管理协议,如SNMP、TMN、CIM/WBEM等。
1.2.12 JACC(Java容器授权合同)
JACC为了将各种授权认证服务器置入到JavaEE产品中,它在JavaEE应用服务器和特定的授权认证服务器之间定义了一个连接协议。JACC的英文全称是Java Authorization Service Provider Contract for Containers,它是一种基于标准的方法,用于将外部安全管理器与应用服务器集成。JACC提供了将安全授权的权限检查委托给外部提供程序的功能。由于授权检查是在容器将控制权交给应用程序前进行的,因此JACC具有能够清楚区分自定义授权逻辑和应用程序逻辑的优势,从而满足了关注点分离的需求。
1.2.13 JCA(Java连接器体系)
JCA定义了一种使JavaEE应用程序与EIS用一种安全和事务性的方式进行通信的方法。JCA的英文全称是Java Connector Architecture,即Java连接器体系,它帮助开发者进行不同种类的EIS之间的无缝集成,用一种安全和事务性的方法连接JavaEE应用程序和非JavaEE环境。JCA连接器一方面与JavaEE应用服务器建立系统级连接,另一方面与访问EIS资源的应用组件建立应用级连接。
JCA规范中定义了两种级别的编程接口:
● 公共客户机接口,任何JavaEE组件都可以用这种接口与EIS进行交互。
● 系统编程接口,它们只在应用程序服务器内部使用。
JCA的体系结构图如图1.8所示。
图1.8 JCA的体系结构图
使用JCA比使用JMS能更好地结合JavaEE应用程序和EIS,使用JCA和JMS连接JavaEE和EIS的示意图如图1.9所示。
图1.9 使用JCA和JMS连接JavaEE和EIS的示意图