"沙箱"机制:Java虚拟机为Applet提供能够良好运行的沙箱,一旦它们试图离开沙箱则会被禁止。
由于小应用程序是通过网络传递的,这就不可避免地使人想到会发生安全问题。例如有人编写恶意程序通过小应用程序读取用户密码并散播到网络上,这将会是一件非常可怕的事情。所以,必须对小应用程序进行限制。
浏览器禁止Applet执行下列操作:
(1)在运行时调用其它程序。
(2)文件读写操作。
(3)装载动态连接库和调用任何本地方法。
(4)试图打开一个socket进行网络通信,但是所连接的主机并不是提供Applet的主机。
◇ Applet的类层次:
◇ Applet的生命周期
小应用程序的生命周期相对于Application而言较为复杂。在其生命周期中涉及到Applet类的四个方法(也被JApplet类继承):init()、start()、stop()和destroy()。下面首先用图来表示一个小应用程序的生命周期,然后再简要描述这四个方法。
Applet的生命周期中有四个状态:初始态、运行态、停止态和消亡态。当程序执行完init()方法以后,Applet程序就进入了初始态;然后马上执行start()方法,Applet程序进入运行态;当Applet程序所在的浏览器图标化或者是转入其它页面时,该Applet程序马上执行stop()方法,Applet程序进入停止态;在停止态中,如果浏览器又重新装载该Applet程序所在的页面,或者是浏览器从图标中复原,则Applet程序马上调用start()方法,进入运行态;当然,在停止态时,如果浏览器关闭,则Applet程序调用destroy()方法,进入消亡态。
◇ Applet的主要方法:
1. init( )
创建Applet时执行,只执行一次
当小应用程序第一次被支持Java的浏览器加载时,便执行该方法。在小应用程序的生命周期中,只执行一次该方法,因此可以在其中进行一些只执行一次的初始化操作,如处理由浏览器传递进来的参数、添加用户接口组件、加载图像和声音文件等。
小应用程序有默认的构造方法,但它习惯于在init()方法中执行所有的初始化,而不是在默认的构造方法内。
2.start( )
多次执行,当浏览器从图标恢复成窗口,或者是返回该主页时执行。
系统在调用完init()方法之后,将自动调用start()方法。而且每当浏览器从图标恢复为窗口时,或者用户离开包含该小应用程序的主页后又再返回时,系统都会再执行一遍start()方法。start()方法在小应用程序的生命周期中被调用多次,以启动小应用程序的执行,这一点与init()方法不同。该方法是小应用程序的主体,在其中可以执行一些需要重复执行的任务或者重新激活一个线程,例如开始动画或播放声音等。
3.stop( )
多次执行,当浏览器变成图标时,或者是离开主页时执行,主要功能是停止一些耗用系统资源的工作,。
与start()相反,当用户离开小应用程序所在页面或浏览器变成图标时,会自动调用stop()方法。因此,该方法在生命周期中也被多次调用。这样使得可以在用户并不注意小应用程序的时候,停止一些耗用系统资源的工作(如中断一个线程),以免影响系统的运行速度,且并不需要去人为地去调用该方法。如果你的小应用程序中不包含动画、声音等程序,通常也不必重载该方法。
4.destroy( )
用来释放资源,在stop( )之后执行
浏览器正常关闭时,Java自动调用这个方法。destroy()方法用于回收任何一个与系统无关的内存资源。当然,如果这个小应用程序仍然处于活动状态,Java会在调用destroy()之前,调用stop()方法。
下面的例子使用了小应用程序生命周期中的这几个方法。
例6.8
import java.awt.Graphics;
import java.applet.Applet;
public class HWloop extends Applet {
AudioClip sound; //声音片断对象
public void init( ){
sound=getAudioClip("audio/hello.au"); //获得声音片断
}
public void paint(Graphics g) {
g.drawString("hello Audio",25,25); //显示字符串
}
public void start( )
{
sound.loop( ); //声音片断开始播放
}
public void stop( )
{
sound.stop( ); //声音片断停止
}
}
在本例子中,Applet开始执行后就不停的播放声音,如果浏览器图标化或者是转到其它页面,则声音停止播放;如果浏览器恢复正常或者是从其它页面跳回,则程序继续播放声音。
由于Applet程序要嵌入到HTML文件中才能够正常执行,下面介绍与Applet程序有关的HTML文件标记。
<applet>
[archive=archiveList] //同一个codebase中需预先下载的文件
code=appletFile.class //applet的名称
width=pixels height=pixels //applet的初始显示空间
[codebase=codebaseURL] //代码的地址
[alt=alternateText] //如果浏览器不支持applet时,显示的替代文本
[name=appletInstanceName]
//给该applet取名,用于同页面applet之间的通信
[align=alignment] //对齐方式,如left,right,top,baseline...
[vspace=pixels] [hspace=pixels] //预留的边缘空白
>
[<param name=appletAttribute1 value=value>]
[<param name=appletAttribute2 value=value>]
…… //参数名称及其值
[alternateHTML]
</applet>
注意:
1)不支持Java的浏览器会把<applet></applet>之间的普通HTML文档显示出来;支持Java的浏览器,则把其中的普通HTML文档忽略。
2)AppletViewer仅支持<applet> </applet>标记,其它标记不会被显示出来。
经过精心设计,可以使java程序同时是Applet与Application,如下例所示:
例6.9
import java.awt.*;
import java.awt.event.*;
public class AppletApp extends Applet {
public void main(String args[]) {
Frame frame=new Frame("Application"); //构造一个Frame
AppletApp app=new AppletApp();
frame.add("Center",app);
frame.setSize(200,200); //改变Frame的尺寸
frame.validate();
frame.setVisible(true); //使Frame可见
frame.addWindwoListener(new WindowControl(app));
//给Frame加入监听器
app.init(); //初始化Applet
app.start(); //运行该Applet
}
public void paint(Graphics g) { //重画方法
g.drawString("hello world",25,25);
}
public void destroy(){
System.exit(0);
}
}
class WindowControl extends WindowAdapter { //监听器类
Applet c;
public WindowControl(Applet c) { //构造函数
this.c=c;
}
public void windowClosing(WindowEvent e) {
//关闭窗口时调用的方法
c.destroy( );
}
}
6.3.2 Applet的AWT绘制
Applet程序中所采用的AWT的绘图机制主要涉及三个方法:paint()方法、update()方法和repaint()方法,update()方法和paint()方法都有一个Graphics类参数。Graphics是画图的关键,它可以支持两种绘图:一种是基本的绘图,如:画线、矩形、圆等;另一种是画图象,主要用于动画制作。
要进行绘图,首先要找到一个Graphics类的对象。update()方法和paint()方法所传递的参数都是Graphics类的对象,因此主要是通过重载它们来进行绘图,这是在动画程序中经常使用的方法。我们还可以通过getGraphics()方法得到一个Graphics类的对象,这个对象和update()方法和paint()方法中所传递的对象一样,都是该成员所对应的Graphics类的对象。得到了Graphics类的对象,就可使用各种绘图方法。
Graphics中提供的图形绘制方法有:
paint( ) //进行绘图的具体操作,必须有程序员重写
update( ) //用于更新图形,先清除背景、前景,再调用paint()
repaint( ) /*用于重绘图形,在组件外形发生变化,即大小改变或位置移动时,repaint( )方法立即被系统自动调用,而实际上repaint()方法是自动调用update()方法*/
下面的方法支持基本的绘图和画图像:
void drawLine( )
void drawArc( )
void drawPolygon( )
void drawRect( )
void drawRoundRect( )
void fill3DRect( )
void fillOval( )
java.awt.Graphics类
输出文字:
void drawBytes( )
void drawChars( )
void drawString( )
Applet 的AWT绘制举例如下:
例6.10
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class ArcTest extends Applet implements WindowListener {
ArcControls controls;
pulic void init(){ //Applet的入口方法
setLayout(new BorderLayout());
ArcCanvas c=new ArcCanvas();
Add("Center",c);
add("South",controls=new ArcControls(C));
}
public void start(){
controls.setEnabled(true); //激活controls
}
public void stop(){
controls.setEnabled(false);
}
public void windowActivated(WindowEvent e){ }
//重写WindowListener的方法
public void windowClosed(WindowEvent e){ }
//重写WindowListener的方法
public void windowClosing(WindowEvent e){
//重写WindowListener的方法
System.exit(0); }
public void windowDeactivated(WindowEvent e){}
//重写WindowListener的方法
public void windowDeiconified(WindowEvent e){}
//重写WindowListener的方法
public void windowIconified(WindowEvent e){ }
//重写WindowListener的方法
public void windowOpend(WindowEvent e){ }
//重写WindowListener的方法
public static void main(String args[]) {
Frame f=new Frame("ArcTest"); //构造Frame
ArcTest arcTest=new ArcTest(); //构造arcTest
atcTest.init();
arcTest.start();
f.add("Center",arcTest);
f.setSize(300,300);
f.show();
f.addWindowListener(arcTest);
}
}
class ArcCanvas extends Canvas{ //类ArcCanvas
int startAngle=0;
int endAngle=45;
boolean filled=false;
Font font;
public void paint(Graphics g){
//paint方法,该方法的作用是在Canvas上画图
Rectangle r=getBounds();
int hlines=r.height/10;
int vlines=r.width/10;
g.setColor(Color.pink);
for(int i=1;i<=hlines;i++) {
g.drawLine(0,i*10,r.width,i*10);
}
for(int i=1;i<=vlines;i++) {
g.drawLine(i*10,0,i*10,r.height);
}
g.setColor(Color.red);
if(filled) {
g.fillArc(0,0,r.width-1,r.height-1,startAngle,endAngle); }
else { g.drawArc(0,0,r.width-1,r.height-1,startAngle, endAngle);
}
g.setColor(Color.black);
g.setFont(font);
g.drawLine(0,r.height/2,r.width,r.height/2);
g.drawLine(r.width/2,0,r.width/2,r.height);
g.drawLine(0,,0,r.width,r.height);
g.drawLine(r.width,0,0,r.height);
int sx=10;
int sy=r.height-28;
g.drawString("S="+startAngle,sx,sy);
g.drawString("E="+ednAngle,sx,sy+14);
}
public void redraw(boolean filled,int start,int end){ //重画方法
this.filled=filled;
this.startAngle=start;
this.endAngle=end;
repaint();
//通过调用repaint()方法,从而最终调用paint方法完成重画
}
}
class ArcControls extends Panel implements ActionListener { //ArcControls类
TextFiled s;
TextFiled e;
ArcCanvas canvas;
public ArcControls(ArcCanvas canvas) {
Button b=null;
this.canvas=canvas;
add(s=new TextField("0",4));
add(e=new TextField("45",4));
b=new Button("Fill");
b.addActionListener(this);
add(b);
b=new Button("Draw");
b.addActionListener(this);
add(b);
}
public void actionPerformed(ActionEvent ev) {
//实现接口ActionListener的方法
String label=ev.getActionCommand();
canvas.redraw(label.equals("Fill"),
Integer.parseInt(s.getText(),trim()),
Integer.parserInt(e.getText().trim());
}
}
6.3.3 Applet和浏览器间的通信
在Applet类中提供了许多方法,使之可以与浏览器进行通信。下面对这些方法进行简要的介绍:
一个Web页可包含一个以上的小应用程序。一个Web页中的多个小应用程序可以直接通过java.applet包中提供的方法进行通信。
getDocumentBase( ) //返回当前网页所在的URL
getCodeBase( ) //返回当前applet所在的URL
getImage(URL base,String target) //返回网址URL中名为target的图像
getAudioClip(URL base,String target)
//返回网址URL中名为target的声音对象
getParameter(String target ) //提取HTML文件中名为target的参数的值
同页Applet间的通信
在java.applet.Applet类中提供了如下方法得到当前运行页的环境上下文AppletContext对象。
public AppletContext getAppletContext();
通过AppletContext对象,可以得到当前小应用程序运行环境的信息。AppletContext是一个接口,其中定义了一些方法可以得到当前页的其它小应用程序,进而实现同页小应用程序之间的通信。
(1)得到当前运行页的环境上下文AppletContext对象
public AppletContext getAppletContext();
(2)取得名为name的Applet对象
public abstract Applet getApplet(String name);
(3)得到当前页中所有Applet对象
public abstract Enumeration getApplets();
例6.11
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Enumeration;
public class GetApplets extends Applet implemements ActionListener {
private TextArea textArea; //声明一个TextArea
private String newline;
public void init() {
Button b=new Button("Click to call getApplets()");
b.addActionListener(this);
setLayout(new BorderLayout());
add("North",b);
textArea=new TextAred(5,40);
textArea.setEditable(false);
add("Center",textArea);
newline=System.getProperty("line,separator");
//取得系统当前的换行符
}
public void actionPerformed(ActionEvent event) {
/*Button b点击后的事件处理函数*/
printApplets();
}
public String getAppletInfo() {
return "GetApplets by Dong.li";
}
public void printApplets()}
Enumeration e=getAppletContext().getApplets();
/*得到当前网页所有的Applet对象*/
textArea.append("Results of getApplets():" + newline);
while(e.hasMoreElements()) {
Applet applet=(Applet) e.nextElement();
String info=((Applet)applet).getAppletInfo();
/*逐个取得当前网页Applet对象的信息*/
if (info!=null) {
textArea.append("-"+info+newline);
/*在textArea中输出网页所有Applet的信息*/
} else {
textArea.append("-"+applet.getClass().getName()+newline) ;
}
}
textArea.append("__________"+newline+newline);
}
}
【本讲小结】
本讲介绍了Java的线程和Java Applet的一些基本知识和简单应用,通过对线程简介,阐明了线程与进程的区别,通过描述线程的概念模型的基本原理以及线程体的构造方法和应用实例,讲解了线程的基本特性和线程的不同状态的转换关系和调用方法,明确了线程的使用方法,然后,我们又进一步讲述了线程的几种调度策略,在不同的调度策略下优先级的作用。以及如何进行基本的线程的控制,线程的重点和难点在于多线程的互斥与同步,首先我们必须明白互斥锁的概念和作用,如何使用互斥锁来控制和处理多线程的同步问题。
本讲的后半部分我们对Java Applet做了介绍和一些基本的应用的讲解,例如Applet的创建,生命周期和Applet的主要方法以及Applet的AWT绘制,最后简单介绍了Applet和浏览器间的通信的方法。