`
xuehu2010
  • 浏览: 4518 次
  • 性别: Icon_minigender_1
  • 来自: 西安
最近访客 更多访客>>
社区版块
存档分类
最新评论

Applet与Servlet通讯的四种方法

阅读更多
Applet与Servlet之间的联系一般是间接的,即页面请求由浏览器发送给Servlet,作为回答,Servlet将结果生成HTML文档发送给浏览器。很多时候在Servlet与Applet之间建立直接的联系是没有必要的,但如果要显示一些实时的动态数据,如聊天室窗口、新闻显示、股市行情等,建立两者之间的直接联系就很有用了。特别地,在较为复杂的分布式Java应用中,这种通讯更是必不可少。在客户端Java程序与服务器端Java程序之间建立这种复杂的交互方式仅仅使用Servlet与Applet API是不够的,本文为你介绍和比较四种通讯方式:通过HTML页面传递参数,用java.net包的网络功能建立直接网络连接,远程方法调用(RMI)与CORBA。
   一、通过HTML页面传递Applet参数

   通过HTML页面传递参数是在Servlet与Applet之间建立联系最为常用的方法。Servlet只要把传递给Applet的参数写入HTML页面就可以了。这种通讯是单向的,用于实现Servlet对Applet的控制。其实现方法类如:
// doGet()方法生成一个包含Applet的HTML页面,
// 该Applet需要一个Data参数

public void doGet(HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = new PrintWriter ( response.getOutputStream());
out.write("< HTML>< HEAD>< TITLE> HTML Example< /TITLE> < /HEAD>< BODY>");
out.write("Servlet通过PARAM标记传递参数给Applet. ");
out.write("< APPLET code=\"SimpleApplet\" width=\"225\" height=\"149\">");
// 写入PARAM标记
out.write("< param name=\"Data\" value=\"");
out.write(java.text.DateFormat.getDateInstance().format(new java.util.Date()));
out.write("\">< /APPLET>< /BODY>< /HTML>");
out.close();
}

   这种方法很简单,但它有两个缺点。首先,所有参数都是静态的,即一旦HTML页面发送完成,要更新其中部分数据就很困难了。虽然可以使用HTTP的刷新机制,但这种刷新需要重新下载整个页面,效率是很低的。第二,如果需要传递给Applet的数据量很大或数据结构很复杂,就会使得HTML页面过于庞大或复杂了。

   二、用java.net包建立双向通讯

   第二种方法是利用java.net包提供的网络能力。以有连接流通讯方式为例,在服务器端的操作为一般为:

   ⑴ 创建一个ServerSocket对象,在指定端口监听客户端发来的请求。

   ⑵ 在接收到请求时accept()方法将返回一个Socket对象。

   ⑶ 用上述Socket对象创建输入、输出流对象。

   ⑷ 通过输入、输出流与客户交互。

   ⑸ 交互完毕,关闭输入、输出流与Socket。

   ⑹ 服务程序运行结束,关闭ServerSocket。

   实现代码代码类如:

try{

boolean flag=true;
Socket clientSocket=null;

ServerSocket serverSocket = new ServerSocket(0);
System.out.println("Server listen on: " +serverSocket.getLocalPort());
while(flag){
clientSocket=serverSocket.accept();
DataInputStream is=new DataInputStream( new bufferedInputStream(clientSocket.getInputStream()));
PrintStream os=new PrintStream( new bufferedOutputStream(clientSocket.getOutputStream()));
// 处理Applet请求
os.close();
is.close();
clientSocket.close();
}
serverSocket.close();
}catch( IOException e){
System.err.println(" Exception: "+e);
}

   在客户端的操作为:

   ⑴ 创建Socket对象建立与服务器的连接。

   ⑵ 用该Socket对象创建输入、输出流。

   ⑶ 与服务器交互。

   ⑷ 交互完毕,关闭输入、输出流与Socket。

   实现代码类如:
try {
Socket clientSocket =new Socket("serverName",7);
OutputStream os=clientSocket.getOutputStream();
DataInputStream is=new DataInputStream( clientSocket.getInputStream());
// 其它操作.
os.close();
is.close();
clientSocket.close();
}catch(Exception e){
System.err.println("Exception:"+e);
}

   这种方法只依赖于标准的Java网络支持,不需要用到附加的软件包或工具, 因此显得相当简洁和灵活,易于实现某些特殊的需要。但在另一方面,服务器端对进入请求以及客户端对返回结果的分析工作量较大。如果服务器端要执行大量的操作,可以考虑使用RMI。

   三、远程方法调用RMI

   Java的RMI技术显著地改善了客户程序操作复杂的服务器端对象的能力。对Applet来说,服务器端对象所提供的远程方法可以象普通的客户端句柄一样调用。使用RMI时应先定义远程接口,即一个继承自java.rmi.Remote的公用接口。在该接口中定义要求在服务器上运行的方法,所有这些方法的throws子句至少应该声明java.rmi.RemoteException异常。

   接下来是实现远程接口,远程接口的实现类应该:

   ⑴ 指定所实现的一个或多个接口。

   ⑵ 定义远程对象的构造方法。

   ⑶ 提供所有可供远程调用的方法的实现。

   ⑷ 创建和安装安全管理器。

   ⑸ 创建一个或多个远程对象实例。

   ⑹ 注册至少一个远程对象。

   下面的代码实现一个返回日期字符串的getData()远程方法,该方法由接口RMIServ2App定义:
// 本类继承自UnicastRemoteObject,实现接口serv2app

package com.servletsolutions.serv2app.rmi;
import java.rmi.*;
import java.rmi.server.*;

public class RMIImplementation extends UnicastRemoteObject
implements RMIServ2App{
public RMIImplementation() throws RemoteException{}
public String getData() throws RemoteException{
return java.text.DateFormat.getDateInstance().format(
new java.util.Date());
}

public static void main(String[] args){
// 安全管理器
System.setSecurityManager(new RMISecurityManager());
try{
// 远程对象实例
RMIImplementation bootStrap = new RMIImplementation();
// 注册
Naming.bind(args[0], bootStrap);
System.out.println(args[0] + " 注册成功");
}catch(Exception e){
System.err.println("注册失败.");
System.err.println(e);
}
}
}

   在客户端,Applet对接口RMIServ2App的引用通过调用Naming.lookup(String)获得,如下所示:

   RMIServ2App obj = (RMIServ2App)Naming.lookup("//" + getCodeBase().getHost() + "/ServerName");

   除了编译Java代码之外,还要用rmic编译器生成远程对象的存根和骨架。存根(Stub)是远程对象在客户端的代理,它将RMI调用传递给服务器端的骨架(Skeleton),后者负责将该调用传递给实际的远程方法。例如执行命令rmic com.servletsolutions.RMIImplementation,则生成的两个类文件分别为RMIImplementation_Stub.class 和RMIImplementation_Stub.class,前者封装入Applet且运行于客户端,后者封装入Servlet且运行与服务器端。

   当大量的数据是由服务器端的对象动态提供时使用RMI是非常合适的。虽然RMI支持面向对象的分布式编程,但它要求客户端和服务器端都是Java程序。因此,对于使用混合语言开发的应用来说,CORBA比RMI更为适用。

   四、使用CORBA

   CORBA即公用对象请求代理体系(Common Object Request Broker Architecture),它的使用方法类似于RMI:定义接口,使用某个工具创建Stub和Skeleton,实现接口,在服务器上注册后客户就可以像本地对象一样访问远程对象了。两者主要的不同之处在于,CORBA使用一种语言中立的接口定义语言(IDL)来定义接口,IDL是一种可用于混合语言环境的更为广泛的协议集。CORBA最大的缺点在于客户本身必须具备调用ORB的能力,这往往意味着增加一个体积较大的JAR文件。

   下面的CORBAServ2App.idl是上述getData()接口的IDL描述,它定义了一组与Java包名字对应的嵌套模块:
module com {
module servletsolutions {
module serv2app {
module corba {
interface CORBAServ2App{
string getData();
};
};
};
};
};

   可以用idl2java从IDL文件生成对应的java文件。其中_CORBAServ2AppImplBase.java包含了描述该接口的java抽象类,下面的CORBAImplementation类继承自抽象类_CORBAServ2AppImplBase并具体实现getData()方法:
package com.servletsolutions.serv2app.corba;

public class CORBAImplementation extends _CORBAServ2AppImplBase {
CORBAImplementation(String s){ super(s); }
public String getData(){
return java.text.DateFormat.getDateInstance().format(new java.util.Date());
}
}

   为了让该类可以被客户访问,Servlet中还应该创建其实例。代码如下所示:
// 在Servlet的init()方法中初始化CORBAImplementation对象
// 其中BOA(Basic Object Adapter)的作用类似于RMI中的注册服务

public class CORBAServlet extends HttpServlet{
String CORBAName;
public void init(
ServletConfig config) throws ServletException {
super.init(config);
try {
CORBAName = getInitParameter("CORBAName");
org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
org.omg.CORBA.BOA boa = orb.BOA_init();
com.servletsolutions.serv2app.corba.CORBAServ2App implObject =
new CORBAImplementation(CORBAName);
boa.obj_is_ready(implObject);
boa.impl_is_ready();
}
catch (Exception e) {
e.printStackTrace();
}
}

   IDL2Java同时为客户端生成CORBAServ2AppHelper类,Applet通过该类与服务器交互。Stub与Skeletion的作用类似于它们在RMI中,不同之处在于本地ORB接口负责所有与远程ORB之间的连接。

   如果服务器端的数据计算量非常大(比如数据库操作),或在未知客户端应用程序的情况下需要从服务器端引出大量的功能,RMI和CORBA较为合适。考虑到已有大量可用的ORB以及CORBA规范的成熟,在大多数情况下CORBA更为可取。但如果希望减小客户端的复杂程度,则RMI是最好的方法


一个Applet(JApplet)访问数据库的例子
用JApplet做的Applet和一般的Applet有些不同。主要是因为Swing库类的单线程原则,所以当JApplet的界面生成后,由其它线程(一般是消息分发线程)试图改变界面(如setText())可能会导致问题发生。这是可以借助SwingUtilities.invokeLater()或SwingUtilities.invokeAndWait()来解决。下面是一个用JApplet访问数据库的例子。

DBApplet.java
======================================================================
import java.sql.*;
import javax.swing.*;

public class DBApplet extends javax.swing.JApplet {

final static private String[] jdbcDriver = {
"com.informix.jdbc.IfxDriver",
"sun.jdbc.odbc.JdbcOdbcDriver",
"com.borland.datastore.jdbc.DataStoreDriver",
"com.sybase.jdbc.SybDriver",
"oracle.jdbc.driver.OracleDriver",
"COM.ibm.db2.jdbc.net.DB2Driver",
"interbase.interclient.Driver",
"weblogic.jdbc.mssqlserver4.Driver"
};

private boolean connected = false;
private Connection connection = null;
private ResultSet rs = null;
private String query = null;
private String rsLine = null;
private String driver = null;
private String url = null;
private String user = null;
private String password = null;

public DBApplet() {
initComponents ();
postInit();
}

private void postInit() {
for (int i = 0; i < jdbcDriver.length; i++) {
cbDriver.addItem(jdbcDriver[i]);
}
}

private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
taResponse = new javax.swing.JTextArea();
jPanel2 = new javax.swing.JPanel();
jPanel1 = new javax.swing.JPanel();
jLabel6 = new javax.swing.JLabel();
tfSql = new javax.swing.JTextField();
btnExecute = new javax.swing.JButton();
jPanel3 = new javax.swing.JPanel();
jLabel3 = new javax.swing.JLabel();
jPanel4 = new javax.swing.JPanel();
cbDriver = new javax.swing.JComboBox();
jLabel7 = new javax.swing.JLabel();
tfUrl = new javax.swing.JTextField();
jLabel9 = new javax.swing.JLabel();
tfUser = new javax.swing.JTextField();
jLabel10 = new javax.swing.JLabel();
tfPassword = new javax.swing.JTextField();
btnConnect = new javax.swing.JButton();
btnDisconnect = new javax.swing.JButton();
setFont(new java.awt.Font ("Verdana", 0, 12));

jScrollPane1.setViewportView(taResponse);

getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);

getContentPane().add(jPanel2, java.awt.BorderLayout.EAST);

jLabel6.setText("SQL:");
jPanel1.add(jLabel6);

tfSql.setPreferredSize(new java.awt.Dimension(300, 21));
jPanel1.add(tfSql);

btnExecute.setText("Execute Query");
btnExecute.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnExecuteActionPerformed(evt);
}
});
jPanel1.add(btnExecute);

getContentPane().add(jPanel1, java.awt.BorderLayout.SOUTH);

jPanel3.setPreferredSize(new java.awt.Dimension(550, 100));
jPanel3.setMinimumSize(new java.awt.Dimension(550, 100));
jPanel3.setMaximumSize(new java.awt.Dimension(550, 100));

jLabel3.setText("JDBC Driver:");
jPanel3.add(jLabel3);

jPanel3.add(jPanel4);

cbDriver.setPreferredSize(new java.awt.Dimension(450, 26));
cbDriver.setMinimumSize(new java.awt.Dimension(100, 26));
jPanel3.add(cbDriver);

jLabel7.setText("Database URL:");
jPanel3.add(jLabel7);

tfUrl.setPreferredSize(new java.awt.Dimension(450, 21));
jPanel3.add(tfUrl);

jLabel9.setText("User:");
jPanel3.add(jLabel9);

tfUser.setPreferredSize(new java.awt.Dimension(100, 21));
jPanel3.add(tfUser);

jLabel10.setText("Password:");
jPanel3.add(jLabel10);

tfPassword.setPreferredSize(new java.awt.Dimension(100, 21));
jPanel3.add(tfPassword);

btnConnect.setPreferredSize(new java.awt.Dimension(89, 27));
btnConnect.setMaximumSize(new java.awt.Dimension(89, 27));
btnConnect.setText("Connect");
btnConnect.setMinimumSize(new java.awt.Dimension(89, 27));
btnConnect.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnConnectActionPerformed(evt);
}
});
jPanel3.add(btnConnect);

btnDisconnect.setText("Disconnect");
btnDisconnect.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnDisconnectActionPerformed(evt);
}
});
jPanel3.add(btnDisconnect);


getContentPane().add(jPanel3, java.awt.BorderLayout.NORTH);

}

private void btnExecuteActionPerformed(java.awt.event.ActionEvent evt) {
if (!connected) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
taResponse.append("No database connected.\n");
}
}
);
} else {
if (connection == null) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
taResponse.append("Database connection error.\n");
}
}
);
} else {
try {
query = tfSql.getText();
Statement stmt = connection.createStatement();
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
taResponse.append("Executing query: " + query + "\n");
}
}
);
rs = stmt.executeQuery(query);
ResultSetMetaData rsmd = rs.getMetaData();
int count = rsmd.getColumnCount();
int i;
rsLine = "\n";
while (rs.next()) {
for (i = 1; i <= count; i++) {
rsLine += rs.getString(i) + " ";
}
rsLine += "\n";
}
rsLine += "\n";
stmt.close();
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
taResponse.append(rsLine);
}
}
);
} catch (SQLException e) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
taResponse.append("Query failed.\n");
}
}
);
e.printStackTrace();
}
}
}
}

private void btnDisconnectActionPerformed(java.awt.event.ActionEvent evt) {
if (connected) {
try {
if (connection != null) {
connection.close();
connection = null;
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
taResponse.append("Database disconnected.\n");
}
}
);
}
} catch (SQLException e) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
taResponse.append("Database disconnecting error.\n");
}
}
);
e.printStackTrace();
}
connected = false;
driver = null;
url = null;
user = null;
password = null;
} else {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
taResponse.append("Database already disconnected.\n");
}
}
);
}
}

private void btnConnectActionPerformed(java.awt.event.ActionEvent evt) {
if (connected) {
taResponse.append("Database already connected.\n");
} else {

driver = (String) cbDriver.getSelectedItem();
url = tfUrl.getText();
user = tfUser.getText();
password = tfPassword.getText();
try {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
taResponse.append("Using JDBC driver: " + driver + "\n");
}
}
);
Class.forName(driver).newInstance();
connection = DriverManager.getConnection(url, user, password);
if (connection != null) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
taResponse.append("Database " + url + " connected.\n");
}
}
);
connected = true;
}
} catch (ClassNotFoundException e) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
taResponse.append("Cannot load the driver.\n");
}
}
);
e.printStackTrace();
} catch (SQLException e) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
taResponse.append("Cannot connect to the database.\n");
}
}
);
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}

private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTextArea taResponse;
private javax.swing.JPanel jPanel2;
private javax.swing.JPanel jPanel1;
private javax.swing.JLabel jLabel6;
private javax.swing.JTextField tfSql;
private javax.swing.JButton btnExecute;
private javax.swing.JPanel jPanel3;
private javax.swing.JLabel jLabel3;
private javax.swing.JPanel jPanel4;
private javax.swing.JComboBox cbDriver;
private javax.swing.JLabel jLabel7;
private javax.swing.JTextField tfUrl;
private javax.swing.JLabel jLabel9;
private javax.swing.JTextField tfUser;
private javax.swing.JLabel jLabel10;
private javax.swing.JTextField tfPassword;
private javax.swing.JButton btnConnect;
private javax.swing.JButton btnDisconnect;
}

dbapplet.html

分享到:
评论

相关推荐

    applet与servlet通讯

    Applet 提供了构建强大、动态的界面到应用程序的便捷方法,而 Servlet 则为我们提供了高效处理 Web 或应用服务器请求的方式。Sun 的应用编程模型推荐在前端使用 Applet、HTML 和 JavaServer Pages(JSP),在后端...

    applet和servlet的通讯,并打印

    总结起来,Applet与Servlet的通信是一种常见的Java Web应用交互方式,它允许客户端与服务器进行数据交换。在这个特定的案例中,这种通信被用来实现在客户端的Applet中打印由服务器提供的文件内容。尽管Applet已经...

    Applet与Servlet的通讯.txt

    根据提供的文件信息,我们可以深入探讨Applet与Servlet之间的通信机制及其实现细节。下面将详细介绍Applet与Servlet如何通过网络进行数据交换,以及涉及到的关键技术点。 ### Applet与Servlet通信概述 Applet是一...

    Applet and Servlet Communication

    包含的文档"Applet与Servlet通讯的四种方法及比较.doc"可能详细介绍了这四种通信方式的实现步骤和优缺点。在实际项目中,开发者会根据需求和环境选择最合适的通信方式。例如,对于简单的数据交换,HTTP请求/响应...

    Applet与Servlet的通信技术.pdf

    文章中提出了一种新的思想,即构建“通讯隧道”来优化Applet与Servlet之间的通信。这个“通讯隧道”可以理解为一种高效的信息传输机制,减少了不必要的网络开销,提高了通信效率。实现这一机制的关键是采用面向对象...

    一个servlet 和 applet 通讯的完整项目

    这个"一个servlet 和 applet 通讯的完整项目"提供了实现这两种技术间通信的实际示例,对于理解它们如何协同工作非常有帮助。 Servlet是Java Servlet API定义的一种服务器端组件,主要用于扩展Web服务器的功能,处理...

    servlet applet通讯的例子

    另一种方式是Applet直接通过URLConnection或HttpURLConnection与Servlet通信,发送请求并接收响应。 2. **URLConnection类**: - TestURLConnection这个文件可能是一个演示如何使用URLConnection来建立Servlet和...

    聊天系统(java+applet).rar

    《构建基于Java与Applet的网页聊天系统》 在当今互联网时代,实时通讯技术已经成为各类网站和应用不可或缺的一部分。本文将深入探讨如何使用Java和Applet技术构建一个基本的网页聊天系统,即使没有深厚的Java基础,...

    基于JSP applet的聊天室

    JSP的主要优势在于它的可扩展性、可维护性和与Servlet的无缝集成。在这个聊天室系统中,JSP主要负责接收和处理用户的请求,以及动态生成聊天室的页面内容。 【Applet】 Applet是Java的一种小程序,它可以在Web...

    JSP訳文--工具--Java

    Java IDL 用连接池提高Servlet访问数据库的效率 在 ASP 文件中调用 Servlet Java Applet介绍 Applet与Servlet通讯的四种方法及其比较 在Applet中应用JDBC访问数据库 用XML与Servlet构建在线问答...

    基于JSP技术实现的web的串口通讯方法

    - **Servlet概述**:Servlet是一种服务器端程序,类似于运行于客户端的Applet,但不具备与用户直接交互的能力。它们通常用于处理客户端发送的HTTP请求,并返回相应的响应。 - **Servlet与CGI的比较**:CGI (Common ...

    Java项目源码之聊天系统的实现(java+applet).zip

    聊天系统是一个基于Java和Applet技术实现的即时通讯项目,旨在提供用户之间的实时消息交流和沟通。以下是该系统的一些关键特点和功能: 系统架构: 客户端-服务器架构:系统采用客户端-服务器模式,客户端通过...

    Java 项目-聊天系统(java+applet) (2).zip

    本项目"Java 项目-聊天系统(java+applet)"就是一个典型的例子,它利用了Java的核心技术和Web应用的特定组件来实现用户间的实时通讯。 首先,我们看到"java+applet"的组合,这表明这个聊天系统可能采用了Java Applet...

    聊天系统(java+applet)130227.zip

    标题中的“聊天系统(java+applet)130227.zip”表明这是一个基于Java技术和Applet实现的在线聊天系统的源代码压缩包。这个系统可能是在2013年2月27日创建或更新的。Applet是Java的一个早期特性,它允许Java程序在...

    pushlet.jar(2.0.4)

    Pushlet是一种comet实现:在Servlet机制下,数据从server端的Java对象直接推送(push)到(动态)HTML页面,而无需任何Java applet或者插件的帮助。它使server端可以周期性地更新client的web页面,这与传统的request...

    数据库中间件及其几种技术比较

    JDBCAPI 定义了一个 Java 类集,允许 Applet、Servlet、JavaBean 和 Java 应用程序连接数据库。 OLEDB(OLE Database)作为一种数据访问接口体系,体现了 Microsoft 的通用数据访问(UDA)策略的理念。UDA 能够通过...

    JavaWeb答辩问题.doc

    在servlet API中,forward和redirect是两个不同的方法。forward方法可以获取request作用域的信息,而redirect方法不能获得。forward方法由request对象发出,而redirect方法由response对象发起。redirect方法可以跨越...

    java-IM.rar_im_java IM

    Java即时通讯(IM)系统是基于Java编程语言和Socket通信技术构建的一种实时通讯平台。在这个“java-IM.rar”压缩包中,包含了实现一个简单的本地IM应用的相关代码和资源。以下将详细介绍标题、描述和标签所涉及的...

    JSP实用技巧集合,jsp编程的一些小技巧总结

    86. Applet与Servlet的通讯? 87. JSP表格直接导入EXCEL? 88. 访问类路径上的资源? 89. 操作文件目录? 90. 获取文件的属性? 91.如何开发并部署一个servlet 92.如何取得配置文件中的servlet的参数 93.使servlet成为...

Global site tag (gtag.js) - Google Analytics