由于单单依靠JSP、JavaScript和HTML很难做出一个Rich Editor能够在里面对一些文字进行超链接化,因此这里我采用了Java applet来完成这项使命。因为在Java中含有许多丰富多彩的组件、控件,所以我这里就利用了javax.swing中的组件来实现功能。而且applet可以被插入到Web中,由浏览器加载执行,所以这一部分也减轻了服务器端的部分开销。
下面简单地讲讲这个小应用程序的框架以及要完成的任务。
这个applet所要完成的一个主要任务就是将一些特定文字表示成超链接,然后用户点击它们就可以链接到相应的URL所指向的页面去。这里用到了Swing中的 HTML编辑工具。利用这个编辑工具可以使得在特定的文本编辑器中显示HTML页面的效果。也就是说这个HTML编辑工具可以解析HTML元素然后将相对应的页面显示在指向它的编辑控件中。这真的很酷!
但是如果要显示超链接必须让编辑控件处于不可被编辑状态。因此所要显示的文字就是从服务器端传给它的。这里就用了java.net中的组件进行远程通信。由于applet在客户端运行,所以这里需要进行网络通信。
对于applet的另一些状态控制以及参数获取需要依靠JavaScript的帮忙,比如获得服务器的URL,是否可让自己运行等。还有如果打开的超链接不是一个HTTP或FTP这样的网络标准协议中的链接,那么要由JavaScript进行打开。
下面贴出applet部分的源代码:
package
applet;

import
javax.swing.JApplet;
import
javax.swing.JTextPane;
import
javax.swing.JScrollPane;
import
javax.swing.text.html.HTMLDocument;
import
javax.swing.text.html.HTMLEditorKit;
import
javax.swing.event.HyperlinkListener;
import
javax.swing.event.HyperlinkEvent;

import
java.awt.event.MouseListener;
import
java.awt.event.MouseEvent;

import
java.io.DataInputStream;
import
java.io.IOException;
import
java.net.Socket;
import
java.net.URL;


/** */
/**
* This applet is used for a text area that can make some particular
* strings displayed as hyperlinks. So some components in Java Swing
* are used.<br>
* NB:Java swing is really powerful!
*
* @author Zenny Chen
*
*/


public
class
TestApplet
extends
JApplet
implements
HyperlinkListener, Runnable, MouseListener
...
{

/** *//**
* Without this, there will be a warning.
*/
private static final long serialVersionUID = -5281871014922105280L;

/** *//**
* client socket
*/
private Socket sock = null;
private DataInputStream in = null;
private Thread thread = null;
// Swing components

/** *//**
* Please see j2se docs
*/
private HTMLEditorKit edit = null;

/** *//**
* Please see j2se docs
*/
private HTMLDocument doc = null;

/** *//**
* Please see j2se docs
*/
private JTextPane textpane = null;

/** *//**
* Please see j2se docs
*/
private JScrollPane scroll = null;

/** *//**
* the URL which is specified by the user when a hyperlink is
* clicked.
*/
private volatile String socketURL = null;

/** *//**
* Flag that marks whether the applet running thead is over
* or not.
*/
private volatile boolean isOver = false;

/** *//**
* Flag that marks whether the applet can currently be run
* or not.
*/
private volatile boolean mayRun = false;

/** *//**
* Flag that marks whether connecting to the server has failed.
*/
private volatile boolean isFailed = false;

/** *//**
* the port number of the server(hard coded here)
*/
private final int port = 8079;

/** *//**
* the url of the server<br>
* This will be passed to the applet through JavaScript.
*/
private String urlname = "";
// private static int counter = 0; // for debug


/** *//**
* Initialize the applet.
*/

public void init() ...{
edit = new HTMLEditorKit();
doc = new HTMLDocument();
textpane = new JTextPane(doc);
textpane.setEditorKit(edit);

scroll = new JScrollPane(textpane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
getContentPane().add(scroll);
textpane.setEditable(false);

/**//*
String s = "<a href="http://www.google.com">www.google.com </a>";
s += "<br>This is another link:</br>";
s += "<br> <a href="http://www.yahoo.com">www.yahoo.com </a> </br>";
textpane.setText(s);
*/
textpane.addHyperlinkListener(this);
scroll.addMouseListener(this);
// textpane.setText("Stopped: " + counter); // for debug
System.out.println("applet initialized");
}

/** *//**
* Start the applet and make it running.
*/

public void start() ...{
System.out.println("applet start");

if(thread == null) ...{
thread = new Thread(this);
thread.start();
}
}

/** *//**
* Stop the applet.
*/

public void stop() ...{

try ...{

if(sock != null) ...{
sock.close();
sock = null;
}
}

catch(IOException e) ...{
System.out.println("socket stop exception");
}

if(thread != null && thread.isAlive()) ...{
Thread.yield();
thread = null;
}
System.out.println("applet stop");
// counter++; // for debug
}

/** *//**
* the applet's running method
*
*/

public void run() ...{

while(!mayRun) ...{

try ...{
Thread.yield();
Thread.sleep(300);
}

catch(InterruptedException e) ...{
e.printStackTrace();
}
}
System.out.println("applet run");
System.out.println(Thread.currentThread().getName());
String s = "";

while(socketURL == null) ...{

try ...{
Thread.yield();
Thread.sleep(800);
}

catch(InterruptedException e) ...{
e.printStackTrace();
}
}
filterIPAddress();
System.out.println(socketURL);

do ...{

try ...{

if(isFailed) ...{
Thread.yield();
Thread.sleep(200);
}
isFailed = false;
sock = new Socket(socketURL, port);
in = new DataInputStream(sock.getInputStream());
while(in == null || sock == null || textpane == null)
Thread.sleep(800);
System.out.println("socket created");

do ...{
s = in.readUTF();
Thread.sleep(200);
}

while(s == null /**//*|| s.equals("")*/);
System.out.println(s);
}

catch(IOException e) ...{
System.out.println("Connecting...");
isFailed = true;
}

catch(InterruptedException ee) ...{
System.out.println("Sleep interrupted");
isFailed = true;
}
}
while(isFailed);
// s += "<br>Stopped: " + counter + " </br>"; // for debug

textpane.setText(s);
System.out.println("applet run over");

try ...{
Thread.sleep(800);
}

catch(InterruptedException e) ...{
}
isOver = true;
}

/** *//**
* Catch the hyperlink event.
*/

public void hyperlinkUpdate(HyperlinkEvent e) ...{

if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) ...{
// String link = e.getDescription(); // just for debug
URL url = e.getURL();
if(url == null)
urlname = e.getDescription();
else
getAppletContext().showDocument(url, "_blank");
}
}

/** *//**
* for communicating with JavaScript<br>
* Transmit the URL of a specified hyperlink to JavaScript.
* @return urlname
*/

public String getURLName() ...{
return urlname;
}

/** *//**
* for communicating with JavaScript</br>
* Clear the last URL of a specified hyperlink for the preparation
* for the next one.
*
*/

public void clearURLName() ...{
urlname = "";
}

/** *//**
* for communicating with JavaScript<br>
* Get the server's URL thru JavaScript
* @param href reference to the URL string
*/

public void setSocketURL(String href) ...{
socketURL = href;
}

/** *//**
* invoked by JavaScript<br>
* Get isOver flag.
* @return the isOver flag
*/

public boolean GetIsOver() ...{
return isOver;
}

/** *//**
* invoked by JavaScript</br>
* whether the applet can be run or not is determined by JavaScript.
* @param b the boolean value
*/

public void setMayRun(boolean b) ...{
mayRun = b;
}

/** *//**
* invoked by JavaScript<br>
* JavaScript invoke this method to judge if the applet failed
* at connecting with the specified server. If the connection fails,
* JavaScript will invoke the applet's start() method to make it
* restart.
* @return isFailed flag
* @deprecated
*/

public boolean GetIsFailed() ...{
return isFailed;
}

/** *//**
* Filter the IP address of the server.<br>
* For example: The server URL is: "http://172.31.25.170:8080.../".
* Just extract "172.31.25.170" from the URL above.
*
*/

private void filterIPAddress() ...{
//if(!socketURL.contains("http"))
// return;
char[] ch = socketURL.toCharArray();
int i = "http://".length();
int k = 0;

for(k=i; k<ch.length; k++) ...{
if(ch[k] == ':')
break;
}
socketURL = String.copyValueOf(ch, i, k-i);
}

public void mouseClicked(MouseEvent e) ...{
//repaint();
}

public void mouseEntered(MouseEvent e) ...{
System.out.println("applet activated!");
repaint();
}

public void mouseExited(MouseEvent e) ...{
}

public void mousePressed(MouseEvent e) ...{
}

public void mouseReleased(MouseEvent e) ...{
}
}