模式类的方法
原文:
docs.oracle.com/javase/tutorial/essential/regex/pattern.html
到目前为止,我们只使用测试工具来创建Pattern
对象的最基本形式。本节探讨了一些高级技术,如使用标志创建模式和使用嵌入式标志表达式。它还探讨了一些我们尚未讨论的其他有用方法。
使用标志创建模式
Pattern
类定义了一个替代的compile
方法,接受一组影响模式匹配方式的标志。标志参数是一个位掩码,可以包括以下任何公共静态字段:
-
Pattern.CANON_EQ
启用规范等价性。当指定此标志时,只有当两个字符的完整规范分解匹配时,它们才被视为匹配。例如,表达式"au030A"
将在指定此标志时匹配字符串"u00E5"
。默认情况下,匹配不考虑规范等价性。指定此标志可能会带来性能损失。 -
Pattern.CASE_INSENSITIVE
启用不区分大小写的匹配。默认情况下,不区分大小写的匹配假定只有在 US-ASCII 字符集中的字符被匹配。通过与此标志一起指定 UNICODE_CASE 标志,可以启用 Unicode 感知的不区分大小写匹配。不区分大小写的匹配也可以通过嵌入式标志表达式(?i)
启用。指定此标志可能会带来轻微的性能损失。 -
Pattern.COMMENTS
允许在模式中使用空格和注释。在此模式下,空格被忽略,并且以#
开头的嵌入式注释被忽略直到行尾。注释模式也可以通过嵌入式标志表达式(?x)
启用。 -
Pattern.DOTALL
启用 dotall 模式。在 dotall 模式下,表达式.
匹配任何字符,包括行终止符。默认情况下,此表达式不匹配行终止符。Dotall 模式也可以通过嵌入式标志表达式(?s)
启用。(s 是"single-line"模式的缩写,在 Perl 中称为这种模式。) -
Pattern.LITERAL
启用模式的字面解析。当指定此标志时,指定模式的输入字符串被视为一系列字面字符。输入序列中的元字符或转义序列将不被赋予特殊含义。当与此标志一起使用时,CASE_INSENSITIVE
和UNICODE_CASE
标志在匹配时保留其影响。其他标志变得多余。没有嵌入式标志字符用于启用字面解析。 -
Pattern.MULTILINE
启用多行模式。在多行模式下,表达式^
和$
分别在行终止符之后或之前匹配,或在输入序列的末尾。默认情况下,这些表达式仅在整个输入序列的开头和结尾匹配。多行模式也可以通过嵌入式标志表达式(?m)
启用。 -
Pattern.UNICODE_CASE
启用 Unicode 感知大小写折叠。当指定此标志时,大小写不敏感匹配(由CASE_INSENSITIVE
标志启用)将按照 Unicode 标准一致的方式进行。默认情况下,大小写不敏感匹配假定只匹配 US-ASCII 字符集中的字符。Unicode 感知大小写折叠也可以通过嵌入式标志表达式(?u)
启用。指定此标志可能会带来性能损失。 -
Pattern.UNIX_LINES
启用 UNIX 行模式。在此模式下,只有'n'
行终止符在.
,^
, 和$
的行为中被识别。UNIX 行模式也可以通过嵌入式标志表达式(?d)
启用。
在以下步骤中,我们将修改测试工具RegexTestHarness.java
以创建一个具有大小写不敏感匹配的模式。
首先,修改代码以调用compile
的另一个版本:
Pattern pattern =
Pattern.compile(console.readLine("%nEnter your regex: "),
Pattern.CASE_INSENSITIVE);
然后编译并运行测试工具以获得以下结果:
代码语言:javascript复制Enter your regex: dog
Enter input string to search: DoGDOg
I found the text "DoG" starting at index 0 and ending at index 3.
I found the text "DOg" starting at index 3 and ending at index 6.
正如你所看到的,字符串字面量"dog"匹配两个实例,不考虑大小写。要编译带有多个标志的模式,请使用按位 OR 运算符"|
"分隔要包含的标志。为了清晰起见,以下代码示例硬编码正则表达式而不是从Console
中读取:
pattern = Pattern.compile("[az]$", Pattern.MULTILINE | Pattern.UNIX_LINES);
你也可以指定一个int
变量:
final int flags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE;
Pattern pattern = Pattern.compile("aa", flags);
嵌入式标志表达式
也可以使用嵌入式标志表达式来启用各种标志。嵌入式标志表达式是compile
的两参数版本的替代方案,并在正则表达式本身中指定。以下示例使用原始测试工具RegexTestHarness.java
与嵌入式标志表达式(?i)
来启用大小写不敏感匹配。
Enter your regex: (?i)foo
Enter input string to search: FOOfooFoOfoO
I found the text "FOO" starting at index 0 and ending at index 3.
I found the text "foo" starting at index 3 and ending at index 6.
I found the text "FoO" starting at index 6 and ending at index 9.
I found the text "foO" starting at index 9 and ending at index 12.
再次,不管大小写,所有匹配都成功。
对应于Pattern
的公共可访问字段的嵌入式标志表达式如下表所示:
常量 | 等效的嵌入式标志表达式 |
---|---|
Pattern.CANON_EQ | 无 |
Pattern.CASE_INSENSITIVE | (?i) |
Pattern.COMMENTS | (?x) |
Pattern.MULTILINE | (?m) |
Pattern.DOTALL | (?s) |
Pattern.LITERAL | 无 |
Pattern.UNICODE_CASE | (?u) |
Pattern.UNIX_LINES | (?d) |
使用matches(String,CharSequence)
方法
Pattern
类定义了一个方便的matches
方法,允许您快速检查给定输入字符串中是否存在模式。与所有公共静态方法一样,您应该通过其类名调用matches
,例如Pattern.matches("\d","1");
。在这个例子中,该方法返回true
,因为数字"1"与正则表达式d
匹配。
使用split(String)
方法
split
方法是一个很好的工具,用于收集与已匹配模式两侧的文本。如下所示,在SplitDemo.java
中,split
方法可以从字符串"one:two:three:four:five
"中提取单词"one two three four five
":
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class SplitDemo {
private static final String REGEX = ":";
private static final String INPUT =
"one:two:three:four:five";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
String[] items = p.split(INPUT);
for(String s : items) {
System.out.println(s);
}
}
}
代码语言:javascript复制OUTPUT:
one
two
three
four
five
为简单起见,我们匹配了一个字符串字面量,即冒号(:
),而不是一个复杂的正则表达式。由于我们仍在使用Pattern
和Matcher
对象,您可以使用 split 来获取任何正则表达式两侧的文本。这里是相同的示例,SplitDemo2.java
,修改为按数字拆分:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class SplitDemo2 {
private static final String REGEX = "\d";
private static final String INPUT =
"one9two4three7four1five";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
String[] items = p.split(INPUT);
for(String s : items) {
System.out.println(s);
}
}
}
代码语言:javascript复制OUTPUT:
one
two
three
four
five
其他实用方法
您可能也会发现以下方法有些用处:
-
public static String quote(String s)
为指定的String
返回一个字面模式String
。此方法生成一个String
,可用于创建一个Pattern
,该Pattern
将匹配String s
,就好像它是一个字面模式。输入序列中的元字符或转义序列将不被赋予特殊含义。 -
public String toString()
返回此模式的String
表示。这是编译此模式的正则表达式。
java.lang.String
中的Pattern
方法等效项
通过几种模仿java.util.regex.Pattern
行为的方法,java.lang.String
中也存在正则表达式支持。为方便起见,以下是它们 API 中的关键摘录。
-
public boolean matches(String regex)
: 告诉这个字符串是否与给定的正则表达式匹配。形式为*str*.matches(*regex*)
的此方法的调用产生与表达式Pattern.matches(*regex*, *str*)
完全相同的结果。 -
public String[] split(String regex, int limit)
: 将此字符串围绕给定正则表达式的匹配项拆分。形式为*str*.split(*regex*, *n*)
的此方法的调用产生与表达式Pattern.compile(*regex*).split(*str*, *n*)
相同的结果。 -
public String[] split(String regex)
: 将此字符串围绕给定正则表达式的匹配项拆分。此方法的工作方式与使用给定表达式和限制参数为零调用两参数拆分方法相同。结果数组中不包括尾随空字符串。
还有一个替换方法,用另一个CharSequence
替换一个:
public String replace(CharSequence target,CharSequence replacement)
: 用指定的文字替换序列替换此字符串的每个与字面目标序列匹配的子字符串。替换从字符串的开头到结尾进行,例如,在字符串“aaa”中用“b”替换“aa”将导致“ba”而不是“ab”。
Matcher 类的方法
原文:
docs.oracle.com/javase/tutorial/essential/regex/matcher.html
本节描述了Matcher
类的一些额外有用的方法。为方便起见,下面列出的方法根据功能进行了分组。
索引方法
索引方法提供了有用的索引值,精确显示匹配在输入字符串中的位置:
-
public int start()
: 返回先前匹配的起始索引。 -
public int start(int group)
: 返回在先前匹配操作期间由给定组捕获的子序列的起始索引。 -
public int end()
: 返回匹配的最后一个字符后的偏移量。 -
public int end(int group)
: 返回在先前匹配操作期间由给定组捕获的子序列的最后一个字符后的偏移量。
学习方法
学习方法审查输入字符串并返回一个布尔值,指示模式是否被找到。
-
public boolean lookingAt()
: 尝试从区域的开头开始匹配输入序列与模式。 -
public boolean find()
: 尝试查找与模式匹配的输入序列的下一个子序列。 -
public boolean find(int start)
: 重置此匹配器,然后尝试查找从指定索引开始的输入序列的下一个与模式匹配的子序列。 -
public boolean matches()
: 尝试将整个区域与模式匹配。
替换方法
替换方法是用于替换输入字符串中文本的有用方法。
-
public Matcher appendReplacement(StringBuffer sb, String replacement)
: 实现了一个非终端追加和替换步骤。 -
public StringBuffer appendTail(StringBuffer sb)
: 实现了一个终端追加和替换步骤。 -
public String replaceAll(String replacement)
:用给定替换字符串替换与模式匹配的输入序列的每个子序列。 -
public String replaceFirst(String replacement)
:用给定的替换字符串替换与模式匹配的输入序列的第一个子序列。 -
public static String quoteReplacement(String s)
:为指定的String
返回一个字面替换String
。此方法生成一个将作为Matcher
类的appendReplacement
方法中的字面替换s
的String
。生成的String
将匹配将s
视为字面序列处理的字符序列。反斜杠(''
)和美元符号('$'
)将不被赋予特殊含义。
使用 start
和 end
方法
这里有一个例子,MatcherDemo.java
,它计算输入字符串中单词"dog"出现的次数。
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class MatcherDemo {
private static final String REGEX =
"\bdog\b";
private static final String INPUT =
"dog dog dog doggie dogg";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
// get a matcher object
Matcher m = p.matcher(INPUT);
int count = 0;
while(m.find()) {
count ;
System.out.println("Match number "
count);
System.out.println("start(): "
m.start());
System.out.println("end(): "
m.end());
}
}
}
代码语言:javascript复制OUTPUT:
Match number 1
start(): 0
end(): 3
Match number 2
start(): 4
end(): 7
Match number 3
start(): 8
end(): 11
您可以看到,此示例使用单词边界来确保字母"d" "o" "g"
不仅仅是更长单词的子字符串。它还提供了有关匹配发生在输入字符串的哪个位置的一些有用信息。start
方法返回在先前匹配操作期间由给定组捕获的子序列的起始索引,而 end
返回匹配的最后一个字符的索引加一。
使用 matches
和 lookingAt
方法
matches
和 lookingAt
方法都尝试将输入序列与模式进行匹配。然而,不同之处在于 matches
要求整个输入序列匹配,而 lookingAt
则不需要。这两种方法始终从输入字符串的开头开始。以下是完整代码,MatchesLooking.java
:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class MatchesLooking {
private static final String REGEX = "foo";
private static final String INPUT =
"fooooooooooooooooo";
private static Pattern pattern;
private static Matcher matcher;
public static void main(String[] args) {
// Initialize
pattern = Pattern.compile(REGEX);
matcher = pattern.matcher(INPUT);
System.out.println("Current REGEX is: "
REGEX);
System.out.println("Current INPUT is: "
INPUT);
System.out.println("lookingAt(): "
matcher.lookingAt());
System.out.println("matches(): "
matcher.matches());
}
}
代码语言:javascript复制Current REGEX is: foo
Current INPUT is: fooooooooooooooooo
lookingAt(): true
matches(): false
使用 replaceFirst(String)
和 replaceAll(String)
replaceFirst
和 replaceAll
方法替换与给定正则表达式匹配的文本。正如它们的名称所示,replaceFirst
替换第一次出现,而 replaceAll
替换所有出现。以下是 ReplaceDemo.java
代码:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class ReplaceDemo {
private static String REGEX = "dog";
private static String INPUT =
"The dog says meow. All dogs say meow.";
private static String REPLACE = "cat";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
// get a matcher object
Matcher m = p.matcher(INPUT);
INPUT = m.replaceAll(REPLACE);
System.out.println(INPUT);
}
}
代码语言:javascript复制OUTPUT: The cat says meow. All cats say meow.
在这个第一个版本中,所有 dog
的出现都被替换为 cat
。但为什么要停在这里呢?与其仅替换简单的文字dog
,不如替换与任何正则表达式匹配的文本。该方法的 API 表明,“给定正则表达式a*b
,输入aabfooaabfooabfoob
,替换字符串为-
,对该表达式的匹配器调用此方法将产生字符串-foo-foo-foo-
。”
以下是 ReplaceDemo2.java
代码:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class ReplaceDemo2 {
private static String REGEX = "a*b";
private static String INPUT =
"aabfooaabfooabfoob";
private static String REPLACE = "-";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
// get a matcher object
Matcher m = p.matcher(INPUT);
INPUT = m.replaceAll(REPLACE);
System.out.println(INPUT);
}
}
代码语言:javascript复制OUTPUT: -foo-foo-foo-
要仅替换模式的第一次出现,只需调用 replaceFirst
而不是 replaceAll
。它接受相同的参数。
使用 appendReplacement(StringBuffer,String)
和 appendTail(StringBuffer)
Matcher
类还提供了 appendReplacement
和 appendTail
方法用于文本替换。下面的示例,RegexDemo.java
,使用这两种方法实现与 replaceAll
相同的效果。
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class RegexDemo {
private static String REGEX = "a*b";
private static String INPUT = "aabfooaabfooabfoob";
private static String REPLACE = "-";
public static void main(String[] args) {
Pattern p = Pattern.compile(REGEX);
Matcher m = p.matcher(INPUT); // get a matcher object
StringBuffer sb = new StringBuffer();
while(m.find()){
m.appendReplacement(sb,REPLACE);
}
m.appendTail(sb);
System.out.println(sb.toString());
}
}
代码语言:javascript复制OUTPUT: -foo-foo-foo-
java.lang.String
中的 Matcher
方法等效
为方便起见,String
类也模仿了一些 Matcher
方法:
-
public String replaceFirst(String regex, String replacement)
:用给定的替换内容替换此字符串匹配给定正则表达式的第一个子字符串。形式为*str*.replaceFirst(*regex*, *repl*)
的此方法调用产生的结果与表达式Pattern.compile(*regex*).matcher(*str*).replaceFirst(*repl*)
完全相同。 -
public String replaceAll(String regex, String replacement)
:用给定的替换内容替换此字符串中与给定正则表达式匹配的每个子字符串。形式为*str*.replaceAll(*regex*, *repl*)
的此方法调用产生的结果与表达式Pattern.compile(*regex*).matcher(*str*).replaceAll(*repl*)
完全相同。
PatternSyntaxException 类的方法
原文:
docs.oracle.com/javase/tutorial/essential/regex/pse.html
PatternSyntaxException
是一个未经检查的异常,表示正则表达式模式中的语法错误。PatternSyntaxException
类提供以下方法,帮助您确定出了什么问题:
-
public String getDescription()
: 检索错误的描述。 -
public int getIndex()
: 检索错误索引。 -
public String getPattern()
: 检索错误的正则表达式模式。 -
public String getMessage()
: 返回一个包含语法错误描述、错误索引、错误的正则表达式模式以及模式中错误索引的可视指示的多行字符串。
以下源代码,RegexTestHarness2.java
,更新了我们的测试工具以检查格式不正确的正则表达式:
import java.io.Console;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.regex.PatternSyntaxException;
public class RegexTestHarness2 {
public static void main(String[] args){
Pattern pattern = null;
Matcher matcher = null;
Console console = System.console();
if (console == null) {
System.err.println("No console.");
System.exit(1);
}
while (true) {
try{
pattern =
Pattern.compile(console.readLine("%nEnter your regex: "));
matcher =
pattern.matcher(console.readLine("Enter input string to search: "));
}
catch(PatternSyntaxException pse){
console.format("There is a problem"
" with the regular expression!%n");
console.format("The pattern in question is: %s%n",
pse.getPattern());
console.format("The description is: %s%n",
pse.getDescription());
console.format("The message is: %s%n",
pse.getMessage());
console.format("The index is: %s%n",
pse.getIndex());
System.exit(0);
}
boolean found = false;
while (matcher.find()) {
console.format("I found the text"
" "%s" starting at "
"index %d and ending at index %d.%n",
matcher.group(),
matcher.start(),
matcher.end());
found = true;
}
if(!found){
console.format("No match found.%n");
}
}
}
}
要运行此测试,请将?i)foo
输入为正则表达式。这个错误是程序员在嵌入式标志表达式(?i)
中忘记开括号的常见情况。这样做将产生以下结果:
Enter your regex: ?i)
There is a problem with the regular expression!
The pattern in question is: ?i)
The description is: Dangling meta character '?'
The message is: Dangling meta character '?' near index 0
?i)
^
The index is: 0
从这个输出中,我们可以看到语法错误是在索引 0 处的悬空元字符(问号)。缺少的开括号是罪魁祸首。
Unicode 支持
原文:
docs.oracle.com/javase/tutorial/essential/regex/unicode.html
从 JDK 7 版本开始,正则表达式模式匹配已扩展功能以支持 Unicode 6.0。
- 匹配特定代码点
- Unicode 字符属性
匹配特定代码点
您可以使用形式为uFFFF
的转义序列匹配特定的 Unicode 代码点,其中FFFF
是您想匹配的代码点的十六进制值。例如,u6771
匹配东方的汉字。
或者,您可以使用 Perl 风格的十六进制表示法指定一个代码点,x{...}
。例如:
String hexPattern = "x{" Integer.toHexString(codePoint) "}";
Unicode 字符属性
每个 Unicode 字符除了其值之外,还具有某些属性或特性。您可以使用表达式p{*prop*}
匹配属于特定类别的单个字符。您可以使用表达式P{*prop*}
匹配不属于特定类别的单个字符。
支持的属性类型有脚本、区块和“通用”类别。
脚本
要确定代码点是否属于特定脚本,您可以使用script
关键字或sc
的简写形式,例如,p{script=Hiragana}
。或者,您可以在脚本名称前加上字符串Is
,例如p{IsHiragana}
。
Pattern
支持的有效脚本名称是UnicodeScript.forName
接受的那些。
区块
可以使用block
关键字或blk
的简写形式指定一个区块,例如,p{block=Mongolian}
。或者,您可以在区块名称前加上字符串In
,例如p{InMongolian}
。
Pattern
支持的有效区块名称是UnicodeBlock.forName
接受的那些。
通用类别
类别可以用可选前缀Is
指定。例如,IsL
匹配 Unicode 字母的类别。类别也可以通过使用general_category
关键字或简写形式gc
来指定。例如,大写字母可以使用general_category=Lu
或gc=Lu
来匹配。
支持的类别是由Character
类指定的Unicode 标准版本中的类别。
其他资源
原文:
docs.oracle.com/javase/tutorial/essential/regex/resources.html
现在您已经完成了关于正则表达式的这节课,您可能会发现您的主要参考资料将是以下类的 API 文档:Pattern
、Matcher
和PatternSyntaxException
。
对于正则表达式构造的行为更精确的描述,我们建议阅读 Jeffrey E. F. Friedl 的书籍精通正则表达式。
问题和练习:正则表达式
原文:
docs.oracle.com/javase/tutorial/essential/regex/QandE/questions.html
问题
-
java.util.regex
包中有哪三个公共类?描述每个类的目的。 - 考虑字符串字面值
"foo"
。起始索引是多少?结束索引是多少?解释这些数字的含义。 - 普通字符和元字符之间有什么区别?举例说明。
- 如何让一个元字符表现得像一个普通字符?
- 一组字符被方括号括起来叫什么?它的作用是什么?
- 这里有三个预定义的字符类:
d
、s
和w
。描述每一个,并使用方括号重写它们。 - 对于每个
d
、s
和w
,写出两个简单的表达式,匹配相反的字符集。 - 考虑正则表达式
(dog){3}
。识别两个子表达式。这个表达式匹配什么字符串?
练习
- 使用反向引用编写一个表达式,只有当一个人的名字和姓氏相同时才匹配该人的名字。
检查你的答案。
路径:部署
原文:
docs.oracle.com/javase/tutorial/deployment/index.html
Java 富互联网应用程序(RIA)是具有类似桌面应用程序特征的应用程序,但是通过互联网部署。Java RIA 可以作为 Java 小程序或 Java Web Start 应用程序开发和部署。
- 小程序 - Java 小程序在浏览器环境中运行。Java 插件软件控制 Java 小程序的执行和生命周期。
- Java Web Start 应用程序 - Java Web Start 应用程序首次通过浏览器启动。随后可以通过桌面快捷方式启动。一旦下载了 Java Web Start 应用程序并且用户接受了其安全证书,它的行为几乎像一个独立的应用程序。
基于组件的架构用于富互联网应用程序
在过去,决定将 Java 富互联网应用程序作为小程序在浏览器内部部署,还是作为 Java Web Start 应用程序在浏览器外部部署,可能会显著影响应用程序的设计。有了最新的 Java 插件,这个决定变得简单多了。
传统上,应用程序在 main
方法中构建其用户界面,包括顶级 Frame
。这种编程风格阻碍了应用程序在浏览器中的重新部署,因为它假定应用程序创建自己的 Frame
。在浏览器中作为小程序运行时,小程序是应该容纳应用程序用户界面的顶级容器。不需要顶级 Frame
。
在设计 Java 富互联网应用程序时,请使用基于组件的架构。尝试将其功能组织成一个或多个可以组合在一起的组件。在这种情况下,“组件”一词指的是 AWT Component
类的子类、Swing JComponent
类或另一个子类的 GUI 元素。例如,您可以有一个顶级 JPanel
,其中包含其他 UI 组件(如更多嵌套的 JPanels 和文本字段、组合框等)。通过这种设计,将核心功能部署为小程序或 Java Web Start 应用程序变得相对容易。
要部署为 Java 小程序,只需将核心功能封装在 Applet
或 JApplet
中,并添加必要的浏览器特定功能。要部署为 Java Web Start 应用程序,请将功能封装在 JFrame
中。
选择 Java 小程序和 Java Web Start 应用程序之间
富互联网应用程序决策指南包含详细信息,帮助您决定将代码部署为 Java 小程序还是 Java Web Start 应用程序。
自包含应用程序替代方案
自包含应用程序提供了一种部署选项,不需要浏览器。用户在本地安装您的应用程序,并类似于本机应用程序运行它。自包含应用程序包括运行应用程序所需的 JRE,因此用户始终拥有正确的 JRE。
本教程讨论了 RIA 和自包含应用程序的开发和部署。请查看新功能,了解客户端 Java 运行时环境(JRE)软件各个版本引入的功能。
支持工具
课程:Java 小程序
原文:
docs.oracle.com/javase/tutorial/deployment/applet/index.html
本课程讨论了 Java 小程序的基础知识,如何开发与环境交互丰富的小程序,以及如何部署小程序。
Java 小程序是一种特殊类型的 Java 程序,可以由启用了 Java 技术的浏览器从互联网上下载并运行。小程序通常嵌入在网页中,并在浏览器的上下文中运行。小程序必须是 java.applet.Applet
类的子类。Applet
类提供了小程序与浏览器环境之间的标准接口。
Swing 提供了 Applet
类的一个特殊子类,名为 javax.swing.JApplet
。应该使用 JApplet
类来构建使用 Swing 组件构建其图形用户界面(GUI)的所有小程序。
浏览器的 Java 插件软件管理小程序的生命周期。
使用 Web 服务器来测试本课程中的示例。不建议使用本地小程序,当 Java 控制面板中的安全级别设置为高或非常高时,本地小程序将被阻止。
注意: 要运行小程序,请在 Microsoft Edge 上使用 IE 模式。请参阅Microsoft Edge Internet Explorer mode: Getting Started guide。
注意: 请确保您的客户端机器上至少安装了Java SE Development Kit (JDK) 6 update 10版本,然后再继续。您将需要此版本才能查看示例丰富的互联网应用程序并在不中断的情况下阅读后续章节。
开始使用小程序
原文:
docs.oracle.com/javase/tutorial/deployment/applet/getStarted.html
接下来展示的 HelloWorld 小程序是一个显示字符串"Hello World"的 Java 类。
//<![CDATA[ var attributes = { code:‘HelloWorld.class’, archive:‘examples/dist/applet_HelloWorld/applet_HelloWorld.jar’, width:150, height:30} ; var parameters = { permissions:‘sandbox’ } ; deployJava.runApplet(attributes, parameters, ‘1.4’); //]]>
注意: 如果你看不到示例运行,可能需要在浏览器中启用 JavaScript 解释器,以便部署工具包脚本能够正常运行。
以下是 HelloWorld 小程序的源代码:
代码语言:javascript复制import javax.swing.JApplet;
import javax.swing.SwingUtilities;
import javax.swing.JLabel;
public class HelloWorld extends JApplet {
//Called when this applet is loaded into the browser.
public void init() {
//Execute a job on the event-dispatching thread; creating this applet's GUI.
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
JLabel lbl = new JLabel("Hello World");
add(lbl);
}
});
} catch (Exception e) {
System.err.println("createGUI didn't complete successfully");
}
}
}
这样的小程序通常由浏览器中的Java 插件软件管理和运行。
下载源代码以进一步进行实验。
定义一个小程序子类
原文:
docs.oracle.com/javase/tutorial/deployment/applet/subclass.html
每个 Java 小程序都必须定义Applet
或JApplet
类的子类。在 Hello World 小程序中,这个子类被称为HelloWorld
。以下是HelloWorld
类的源代码。
import javax.swing.JApplet;
import javax.swing.SwingUtilities;
import javax.swing.JLabel;
public class HelloWorld extends JApplet {
//Called when this applet is loaded into the browser.
public void init() {
//Execute a job on the event-dispatching thread; creating this applet's GUI.
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
JLabel lbl = new JLabel("Hello World");
add(lbl);
}
});
} catch (Exception e) {
System.err.println("createGUI didn't complete successfully");
}
}
}
Java applets inherit significant functionality from the Applet
or JApplet
class, including the capabilities to communicate with the browser and present a graphical user interface (GUI) to the user.
一个将使用来自 Swing(Java 的 GUI 工具包)的 GUI 组件的小程序应该扩展javax.swing.JApplet
基类,它提供了与 Swing 的 GUI 设施最佳集成。
JApplet
提供了一个根窗格,它与 Swing 的JFrame
和JDialog
组件具有相同的顶层组件结构,而Applet
只提供了一个基本面板。有关如何使用此功能的更多详细信息,请参见如何使用根窗格。
一个小程序可以扩展java.applet.Applet
类,当它不使用 Swing 的 GUI 组件时。
里程碑方法
原文:
docs.oracle.com/javase/tutorial/deployment/applet/appletMethods.html
Applet
类为小程序执行提供了一个框架,定义了系统在里程碑发生时调用的方法。里程碑是小程序生命周期中的重要事件。大多数小程序会覆盖其中一些或全部方法以适当地响应里程碑。
init
方法
init
方法适用于不需要太长时间的一次性初始化。init
方法通常包含通常放在构造函数中的代码。小程序通常没有构造函数的原因是在调用其init
方法之前不能保证其具有完整的环境。保持init
方法简短,以便您的小程序可以快速加载。
start
方法
每个在初始化后执行任务(除了直接响应用户操作)的小程序必须覆盖start
方法。start
方法启动小程序的执行。从start
方法快速返回是一个良好的实践。如果需要执行计算密集型操作,最好为此目的启动一个新线程。
stop
方法
大多数覆盖start
方法的小程序也应该覆盖stop
方法。stop
方法应该暂停小程序的执行,这样当用户不查看小程序页面时,它就不会占用系统资源。例如,显示动画的小程序在用户不查看时应该停止尝试绘制动画。
destroy
方法
许多小程序不需要覆盖destroy
方法,因为它们的stop
方法(在destroy
之前调用)将执行关闭小程序执行所需的所有任务。但是,destroy
方法适用于需要释放额外资源的小程序。
注意: 尽量保持destroy
方法的实现尽可能简短,因为不能保证该方法会完全执行。在长destroy
方法完成之前,Java 虚拟机可能会退出。
小程序的生命周期
原文:
docs.oracle.com/javase/tutorial/deployment/applet/lifeCycle.html
小程序可以对以下重大事件做出反应:
- 它可以初始化自身。
- 它可以开始运行。
- 它可以停止运行。
- 它可以执行最终清理,为即将卸载做准备。
本节介绍了一个新的小程序Simple
,它使用了所有这些方法。与 Java 应用程序不同,小程序不需要实现main
方法。
这是Simple
小程序。
//<![CDATA[ var attributes = { code:‘Simple.class’, archive:‘examples/dist/applet_Simple/applet_Simple.jar’, width:500, height:20} ; var parameters = { permissions:‘sandbox’ } ; deployJava.runApplet(attributes, parameters, ‘1.4’); //]]>
注意: 如果您看不到示例运行,请确保在浏览器中启用 JavaScript 解释器,以便部署工具包脚本能够正常运行。
以下是Simple
小程序的源代码。该小程序在其生命周期中遇到重要里程碑时会显示描述性字符串,例如当用户首次访问包含小程序的页面时。
import java.applet.Applet;
import java.awt.Graphics;
//No need to extend JApplet, since we don't add any components;
//we just paint.
public class Simple extends Applet {
StringBuffer buffer;
public void init() {
buffer = new StringBuffer();
addItem("initializing... ");
}
public void start() {
addItem("starting... ");
}
public void stop() {
addItem("stopping... ");
}
public void destroy() {
addItem("preparing for unloading...");
}
private void addItem(String newWord) {
System.out.println(newWord);
buffer.append(newWord);
repaint();
}
public void paint(Graphics g) {
//Draw a Rectangle around the applet's display area.
g.drawRect(0, 0,
getWidth() - 1,
getHeight() - 1);
//Draw the current string inside the rectangle.
g.drawString(buffer.toString(), 5, 15);
}
}
注意: 在此示例中,Applet
类被扩展,而不是 Swing JApplet
类,因为 Swing 组件不需要添加到此小程序中。
加载小程序
由于小程序被加载,您应该看到文本“初始化…启动…”。小程序加载时,会发生以下情况:
- 创建小程序控制类的一个实例(
Applet
子类)。 - 小程序初始化自身。
- 小程序开始运行。
离开并返回到小程序的页面
当用户离开页面,例如前往另一页时,浏览器会停止并销毁小程序。小程序的状态不会被保留。当用户返回页面时,浏览器会初始化并启动小程序的新实例。
重新加载小程序
当您刷新或重新加载浏览器页面时,当前小程序实例会被停止和销毁,并创建一个新实例。
退出浏览器
当用户退出浏览器时,小程序有机会在浏览器退出之前停止自身并执行最终清理。
下载源代码以进一步实验Simple 小程序示例。
Applet 的执行环境
原文:
docs.oracle.com/javase/tutorial/deployment/applet/appletExecutionEnv.html
Java applet 在浏览器的上下文中运行。浏览器中的 Java 插件软件控制 Java applet 的启动和执行。浏览器还有一个 JavaScript 解释器,用于运行网页上的 JavaScript 代码。本主题描述了 Java 平台标准版 6 更新 10 中发布的 Java 插件软件的行为。
Java 插件
Java 插件软件为每个 Java applet 创建一个工作线程。它在 Java Runtime Environment (JRE)软件的一个实例中启动 applet。通常,所有 applet 在同一个 JRE 实例中运行。Java 插件软件在以下情况下启动新的 JRE 实例:
- 当 applet 请求在特定版本的 JRE 中执行时。
- 当 applet 指定自己的 JRE 启动参数时,例如堆大小。如果新 applet 的要求是现有 JRE 的子集,则新 applet 使用现有 JRE,否则启动新的 JRE 实例。
如果满足以下条件,applet 将在现有 JRE 中运行:
- applet 所需的 JRE 版本与现有的 JRE 匹配。
- JRE 的启动参数满足 applet 的要求。
以下图表显示了 applet 在 JRE 中的执行方式。
Java 插件和 JavaScript 解释器的交互
Java applet 可以调用网页中存在的 JavaScript 函数。JavaScript 函数也允许调用同一网页上嵌入的 applet 的方法。Java 插件软件和 JavaScript 解释器协调 Java 代码到 JavaScript 代码的调用以及 JavaScript 代码到 Java 代码的调用。
Java 插件软件是多线程的,而 JavaScript 解释器在单个线程上运行。因此,为了避免线程相关问题,特别是当多个 applet 同时运行时,请保持 Java 代码和 JavaScript 代码之间的调用简短,并尽量避免往返。查看以下主题以了解 Java 代码和 JavaScript 代码之间的交互更多信息:
- 从 Applet 调用 JavaScript 代码
- 从 JavaScript 代码调用 Applet 方法
开发 Applet
原文:
docs.oracle.com/javase/tutorial/deployment/applet/developingApplet.html
使用基于组件的架构设计的应用程序可以开发为 Java applet。考虑具有基于 Swing 的图形用户界面(GUI)的 Java applet 的示例。通过组件化设计,GUI 可以使用更小的构建块或组件构建。以下是用于创建 applet GUI 的一般步骤:
- 创建一个名为
MyTopJPanel
的类,它是javax.swing.JPanel
的子类。在MyTopJPanel
类的构造函数中布置您的 applet 的 GUI 组件。 - 创建一个名为
MyApplet
的类,它是javax.swing.JApplet
的子类。 - 在
MyApplet
的init
方法中,实例化MyTopJPanel
并将其设置为 applet 的内容窗格。
以下部分通过使用动态树演示 applet 更详细地探讨这些步骤。如果您对 Swing 不熟悉,请参阅使用 Swing 创建 GUI 以了解更多关于使用 Swing GUI 组件的信息。
//<![CDATA[ var attributes = { code:‘appletComponentArch.DynamicTreeApplet.class’, archive:‘examples/dist/applet_ComponentArch_DynamicTreeDemo/DynamicTreeDemo.jar’, width:300, height:300} ; var parameters = {jnlp_href: ‘examples/dist/applet_ComponentArch_DynamicTreeDemo/dynamictree_applet.jnlp’} ; deployJava.runApplet(attributes, parameters, ‘1.4’); //]]>
注意: 如果您看不到示例运行,请确保在浏览器中启用 JavaScript 解释器,以便部署工具包脚本能够正常运行。
创建顶部JPanel
类
创建一个是JPanel
子类的类。这个顶部JPanel
充当所有其他 UI 组件的容器。在下面的示例中,DynamicTreePanel
类是最顶层的JPanel
。DynamicTreePanel
类的构造函数调用其他方法来正确创建和布局 UI 控件。
public class DynamicTreePanel extends JPanel implements ActionListener {
private int newNodeSuffix = 1;
private static String ADD_COMMAND = "add";
private static String REMOVE_COMMAND = "remove";
private static String CLEAR_COMMAND = "clear";
private DynamicTree treePanel;
public DynamicTreePanel() {
super(new BorderLayout());
//Create the components.
treePanel = new DynamicTree();
populateTree(treePanel);
JButton addButton = new JButton("Add");
addButton.setActionCommand(ADD_COMMAND);
addButton.addActionListener(this);
JButton removeButton = new JButton("Remove");
// ...
JButton clearButton = new JButton("Clear");
// ...
//Lay everything out.
treePanel.setPreferredSize(
new Dimension(300, 150));
add(treePanel, BorderLayout.CENTER);
JPanel panel = new JPanel(new GridLayout(0,3));
panel.add(addButton);
panel.add(removeButton);
panel.add(clearButton);
add(panel, BorderLayout.SOUTH);
}
// ...
}
创建 Applet
对于具有基于 Swing 的 GUI 的 Java applet,请创建一个类,它是javax.swing.JApplet
的子类。不包含基于 Swing 的 GUI 的 applet 可以扩展java.applet.Applet
类。
覆盖 applet 的init
方法以实例化您的顶部JPanel
类并创建 applet 的 GUI。DynamicTreeApplet
类的init
方法在 AWT 事件分发线程中调用createGUI
方法。
package appletComponentArch;
import javax.swing.JApplet;
import javax.swing.SwingUtilities;
public class DynamicTreeApplet extends JApplet {
//Called when this applet is loaded into the browser.
public void init() {
//Execute a job on the event-dispatching thread; creating this applet's GUI.
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
createGUI();
}
});
} catch (Exception e) {
System.err.println("createGUI didn't complete successfully");
}
}
private void createGUI() {
//Create and set up the content pane.
DynamicTreePanel newContentPane = new DynamicTreePanel();
newContentPane.setOpaque(true);
setContentPane(newContentPane);
}
}
将核心功能与最终部署机制分离的好处
另一种创建 applet 的方法是只需移除抽象层(单独的顶部JPanel
)并在 applet 的init
方法中布置所有控件。直接在 applet 中创建 GUI 的缺点是,如果以后选择将功能部署为 Java Web Start 应用程序,则现在将更难部署您的功能。
在动态树演示示例中,核心功能位于DynamicTreePanel
类中。现在,将DynamicTreePanel
类放入JFrame
并部署为 Java Web Start 应用程序变得轻而易举。
因此,为了保持可移植性并保持部署选项开放,请按照本页描述的基于组件的设计。
下载源代码以进一步实验动态树演示程序示例。
部署一个 Applet
译文:
docs.oracle.com/javase/tutorial/deployment/applet/deployingApplet.html
要部署您的 Java applet,首先编译源代码,将其打包为 JAR 文件,并对 JAR 文件进行签名。
Java applet 可以以两种方式启动。
- 您可以使用 Java 网络启动协议(JNLP)启动您的 applet。使用 JNLP 启动的 applet 可以访问强大的 JNLP API 和扩展。
- 或者,您可以通过直接在 applet 标记中指定 applet 的启动属性来启动 applet。然而,这种部署 applet 的旧方法对 applet 施加了严格的安全限制。
部署工具包脚本包含可用于在网页中部署 applet 的有用 JavaScript 函数。
如果您对这些部署技术不熟悉,请在继续之前查看 深入部署 课程。
以下是一些逐步说明,用于打包和部署您的 applet。Dynamic Tree Demo applet 用于说明 applet 的部署。您可能希望设置构建脚本来执行以下一些步骤。
//<![CDATA[ var attributes = { code:‘appletComponentArch.DynamicTreeApplet.class’, archive:‘examples/dist/applet_ComponentArch_DynamicTreeDemo/DynamicTreeDemo.jar’, width:300, height:300} ; var parameters = {jnlp_href: ‘examples/dist/applet_ComponentArch_DynamicTreeDemo/dynamictree_applet.jnlp’} ; deployJava.runApplet(attributes, parameters, ‘1.7’); //]]>
注意: 如果您看不到示例运行,请确保在浏览器中启用 JavaScript 解释器,以便部署工具包脚本能够正常运行。
编译您的 applet 的 Java 代码,并确保所有类文件和资源(如图像)位于单独的目录中。
在 DynamicTree Demo applet 的情况下,编译后的类文件将放置在 build/classes/appletComponentArch
目录中。
创建一个包含您的 applet 需要的任何 JAR 文件清单属性的文本文件。
对于 DynamicTree Demo applet,创建一个名为 mymanifest.txt
的文件在 build/classes
目录中,并添加 Permissions
、Codebase
和 Application-Name
属性。该 applet 不需要访问用户系统资源,因此对于权限使用 sandbox
。对于代码库,使用您将加载示例的域,例如 myserver.com
。将以下属性添加到 mymanifest.txt
文件中。
Permissions: sandbox
Codebase: myserver.com
Application-Name: Dynamic Tree Demo
其他清单属性可用于限制 applet 仅使用受信任的代码,并为需要在特权 Java 代码和沙箱 Java 代码之间进行调用,或者具有调用 applet 的 JavaScript 代码的 applet 提供安全性。请参阅 使用清单属性增强安全性 课程以了解更多可用的清单属性。
创建一个包含您 applet 的类文件和资源的 JAR 文件。在您之前创建的 mymanifest.txt
文件中包含清单属性。
例如,以下命令将创建一个 JAR 文件,其中包含 build/classes/appletComponentArch
目录中的类文件和 build/classes
目录中的清单文件。
% cd build/classes
% jar cvfm DynamicTreeDemo.jar mymanifest.txt appletComponentArch
参阅 在 JAR 文件中打包程序 课程,了解有关创建和使用 JAR 文件的更多信息。
为您的 applet 签署 JAR 文件并为签名加上时间戳。使用由受信任的证书颁发机构颁发的有效的当前代码签名证书,向用户提供确保可以安全运行 applet 的保证。
请参阅 签署 JAR 文件 课程以获取更多信息。
如果您想要使用签名的 JNLP 文件以确保安全性,请按照下一步中描述的方式创建 JNLP 文件,并在签名 JAR 文件之前将其包含在 JAR 文件中。有关详细信息,请参阅 Java 平台标准版部署指南中的 签名的 JNLP 文件。
创建描述您的 applet 应如何启动的 JNLP 文件。
这是用于启动动态树演示 applet 的 JNLP 文件。
dynamictree_applet.jnlp
的源代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0 " codebase="" href="">
<information>
<title>Dynamic Tree Demo</title>
<vendor>Dynamic Team</vendor>
</information>
<resources>
<!-- Application Resources -->
<j2se version="1.7 "
href="http://java.sun.com/products/autodl/j2se" />
<jar href="DynamicTreeDemo.jar" main="true" />
</resources>
<applet-desc
name="Dynamic Tree Demo Applet"
main-class="components.DynamicTreeApplet"
width="300"
height="300">
</applet-desc>
<update check="background"/>
</jnlp>
请注意,JNLP 文件中不存在请求额外权限的安全元素,因此 applet 仅在安全沙箱中运行。
主题,JNLP 文件的结构,描述了 JNLP 文件的语法和选项。
创建将显示 applet 的 HTML 页面。调用部署工具包函数以部署 applet。
在我们的示例中,动态树演示 applet 部署在 AppletPage.html
中。
<body>
<!-- ... -->
<script src="https://www.java.com/js/deployJava.js"></script>
<script>
var attributes = {
code:'components.DynamicTreeApplet', width:300, height:300} ;
var parameters = {jnlp_href: 'dynamictree_applet.jnlp'} ;
deployJava.runApplet(attributes, parameters, '1.7');
</script>
<!-- ... -->
</body>
将 applet 的 JAR 文件、JNLP 文件和 HTML 页面放置在适当的文件夹中。
对于此示例,请将 DynamicTreeDemo.jar
、dynamictree_applet.jnlp
和 AppletPage.html
放置在本地计算机或 Web 服务器上的同一目录中。建议使用 Web 服务器。要从本地计算机运行,必须将应用程序添加到例外站点列表中,该列表可从 Java 控制面板的安全选项卡中管理。
在浏览器中打开 applet 的 HTML 页面以查看 applet。在提示时同意运行 applet。检查 Java 控制台日志以查看错误和调试消息。
下载源代码 以进一步尝试 动态树演示 applet 示例。
使用 Applet 标签部署
原文:
docs.oracle.com/javase/tutorial/deployment/applet/html.html
如果您不确定最终用户的浏览器是否启用了 JavaScript 解释器,您可以通过手动编码 <applet>
HTML 标签来部署您的 Java applet,而不是使用 Deployment Toolkit 函数。根据您需要支持的浏览器,您可能需要使用 <object>
或 <embed>
HTML 标签来部署您的 Java applet。查看W3C HTML 规范以获取有关这些标签的使用详情。
您可以使用 Java 网络启动协议(JNLP)启动您的 applet,或者直接在 <applet>
标签中指定启动属性。
部署准备
按照部署 applet 主题中描述的步骤编译您的源代码,创建并签名 JAR 文件,如有必要创建 JNLP 文件。部署的整体步骤仍然相关。只有包含 applet 的 HTML 页面的内容会发生变化。
手动编码 Applet 标签,使用 JNLP 启动
AppletPage_WithAppletTag.html
页面使用手动编码的 <applet>
标签部署了 Dynamic Tree Demo applet(意味着该 applet 不是使用自动生成所需 HTML 的 Deployment Toolkit 部署的)。该 applet 仍然使用 JNLP 启动。JNLP 文件在 jnlp_href
属性中指定。
<applet code = 'appletComponentArch.DynamicTreeApplet'
jnlp_href = 'dynamictree_applet.jnlp'
width = 300
height = 300 />
手动编码 Applet 标签,无需使用 JNLP 启动
使用 JNLP 是部署 applet 的首选方式,但您也可以在没有 JNLP 文件的情况下部署您的 applet。
AppletPage_WithAppletTagNoJNLP.html
部署了 Dynamic Tree Demo applet,如下面的代码片段所示。
<applet code = 'appletComponentArch.DynamicTreeApplet'
archive = 'DynamicTreeDemo.jar'
width = 300
height = 300>
<param name="permissions" value="sandbox" />
</applet>
其中
-
code
是 applet 类的名称。 -
archive
是包含 applet 及其资源的 jar 文件的名称。 -
width
是 applet 的宽度。 -
height
是 applet 的高度。 -
permissions
表示 applet 是否在安全沙箱中运行。将值指定为"sandbox"以在沙箱中运行。将值指定为"all-permissions"以在沙箱外运行。如果未提供permissions
参数,则签名的 applet 默认为"all-permissions",未签名的 applet 默认为"sandbox"。
进一步使用小程序
原文:
docs.oracle.com/javase/tutorial/deployment/applet/doingMoreWithApplets.html
Java 小程序 API 使您能够充分利用小程序与浏览器之间的密切关系。该 API 由javax.swing.JApplet
类和java.applet.AppletContext
接口提供。小程序执行架构使小程序能够与其环境交互,从而产生丰富的用户体验。小程序可以操纵其父网页,与网页中的 JavaScript 代码交互,查找在同一网页中运行的其他小程序等等。
探索 Java 小程序的高级功能在后续主题中。
有关常见小程序和 Java Web 启动应用程序的高级主题的进一步信息,请参阅使用 Java 丰富互联网应用程序做更多事情(例如设置参数和属性,使用 Java 网络启动协议 API)。
查找和加载数据文件
原文:
docs.oracle.com/javase/tutorial/deployment/applet/data.html
每当 Java applet 需要从指定了相对 URL 的文件加载数据(指定了文件位置但不完全指定的 URL),applet 通常使用代码库或文档库来形成完整的 URL。
由 JApplet
的 getCodeBase
方法返回的代码库是一个 URL,指定了 applet 的类加载的目录。对于本地部署的 applet,getCodeBase
方法返回 null。
由 JApplet
的 getDocumentBase
方法返回的文档库指定包含 applet 的 HTML 页面的目录。对于本地部署的 applet,getDocumentBase
方法返回 null。
除非 <applet>
标签指定了代码库,否则代码库和文档库都指向同一服务器上的同一目录。
applet 可能需要的数据,或者需要依赖的备份数据,通常相对于代码库指定。通常由 applet 开发人员指定的数据,通常通过使用参数指定,通常相对于文档库指定。
**注意:**出于安全原因,浏览器限制了不受信任的 applet 可以读取的 URL。例如,大多数浏览器不允许不受信任的 applet 使用 “…” 访问代码库或文档库上面的目录。此外,由于不受信任的 applet 不能读取除了位于 applet 源主机上的文件之外的文件,因此如果文档和不受信任的 applet 位于不同的服务器上,则文档库通常是无用的。
JApplet
类定义了方便的图像加载和声音加载方法,使您能够相对于基本 URL 指定图像和声音。例如,假设 applet 设置为以下图中显示的其中一个目录结构。
要创建一个使用 imgDir
下的 a.gif
图像文件的 Image
对象,applet 可以使用以下代码:
Image image = getImage(getCodeBase(), "imgDir/a.gif");
定义和使用 Applet 参数
原文:
docs.oracle.com/javase/tutorial/deployment/applet/param.html
参数对于 Java applet 就像命令行参数对于应用程序一样重要。它们使用户能够自定义 applet 的操作。通过定义参数,你可以增加 applet 的灵活性,使其在多种情况下工作而无需重新编码和重新编译。
指定 Applet 的输入参数
你可以在 applet 的 Java 网络启动协议(JNLP)文件或 <applet>
标签的 <parameter>
元素中指定 applet 的输入参数。通常最好在 applet 的 JNLP 文件中指定参数,这样即使 applet 部署在多个网页上,参数也可以一致提供。如果 applet 的参数会因网页而异,则应在 <applet>
标签的 <parameter>
元素中指定参数。
如果你对 JNLP 不熟悉,请查看 Java 网络启动协议 主题获取更多信息。
考虑一个需要三个参数的 applet。paramStr
和 paramInt
参数在 applet 的 JNLP 文件中指定,applettakesparams.jnlp
。
<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0 " codebase="" href="">
<!-- ... -->
<applet-desc
name="Applet Takes Params"
main-class="AppletTakesParams"
width="800"
height="50">
<param name="paramStr"
value="someString"/>
<param name="paramInt" value="22"/>
</applet-desc>
<!-- ... -->
</jnlp>
paramOutsideJNLPFile
参数在传递给部署工具包脚本的 runApplet
函数的 parameters
变量中指定在 AppletPage.html
。
<html>
<head>
<title>Applet Takes Params</title>
<meta http-equiv="Content-Type" content="text/html;
charset=windows-1252">
</head>
<body>
<h1>Applet Takes Params</h1>
<script
src="https://www.java.com/js/deployJava.js"></script>
<script>
var attributes = { code:'AppletTakesParams.class',
archive:'applet_AppletWithParameters.jar',
width:800, height:50 };
var parameters = {jnlp_href: 'applettakesparams.jnlp',
paramOutsideJNLPFile: 'fooOutsideJNLP' };
deployJava.runApplet(attributes, parameters, '1.7');
</script>
</body>
</html>
查看 部署 Applet 获取有关 runApplet
函数的更多信息。
检索 Applet 的输入参数
你可以使用 Applet
类的 getParameter
方法来检索 applet 的输入参数。AppletTakesParams.java
applet 检索并显示其所有输入参数(paramStr
,paramInt
和 paramOutsideJNLPFile
)。
import javax.swing.JApplet;
import javax.swing.SwingUtilities;
import javax.swing.JLabel;
public class AppletTakesParams extends JApplet {
public void init() {
final String inputStr = getParameter("paramStr");
final int inputInt = Integer.parseInt(getParameter("paramInt"));
final String inputOutsideJNLPFile = getParameter("paramOutsideJNLPFile");
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
createGUI(inputStr, inputInt, inputOutsideJNLPFile);
}
});
} catch (Exception e) {
System.err.println("createGUI didn't successfully complete");
}
}
private void createGUI(String inputStr, int inputInt, String inputOutsideJNLPFile) {
String text = "Applet's parameters are -- inputStr: " inputStr
", inputInt: " inputInt
", paramOutsideJNLPFile: " inputOutsideJNLPFile;
JLabel lbl = new JLabel(text);
add(lbl);
}
}
下面显示了 AppletTakesParams
applet。
//<![CDATA[ var attributes = { code:‘AppletTakesParams.class’, archive:‘examples/dist/applet_AppletWithParameters/applet_AppletWithParameters.jar’, width:800, height:50} ; var parameters = { jnlp_href: ‘examples/dist/applet_AppletWithParameters/applettakesparams.jnlp’, paramOutsideJNLPFile: ‘fooOutsideJNLP’ }; deployJava.runApplet(attributes, parameters, ‘1.6’); //]]>
注意: 如果你看不到 applet 运行,你需要安装至少 Java SE Development Kit (JDK) 6 update 10 版本。
注意: 如果你看不到示例运行,可能需要在浏览器中启用 JavaScript 解释器,以便部署工具包脚本能够正常运行。
下载源代码 以进一步进行实验。
显示短状态字符串
原文:
docs.oracle.com/javase/tutorial/deployment/applet/showStatus.html
所有浏览器都允许 Java applets 显示一个简短的状态字符串。页面上的所有 Java applets 以及浏览器本身共享同一状态行。
永远不要将关键信息放在状态行中。如果许多用户可能需要该信息,请在 applet 区域内显示该信息。如果只有少数精通的用户可能需要该信息,请考虑将信息发送到标准输出(参见将诊断信息写入标准输出和错误流)。
状态行通常不太显眼,并且可能被其他 applets 或浏览器覆盖。因此,最好将其用于偶发的、短暂的信息。例如,一个加载多个图像文件的 applet 可能会显示当前正在加载的图像文件的名称。
Applets 使用showStatus
方法显示状态行,该方法从Applet
类继承到JApplet
类。
这里是其使用示例:
代码语言:javascript复制showStatus("MyApplet: Loading image file " file);
注意: 不要在状态行中放置滚动文本。浏览器用户会觉得这种行为非常恼人。
在浏览器中显示文档
原文:
docs.oracle.com/javase/tutorial/deployment/applet/browser.html
一个 Java 小程序可以使用 java.applet.AppletContext
类中的 showDocument
方法在浏览器窗口中加载网页。
以下是 showDocument
的两种形式:
public void showDocument(java.net.URL *url*)
public void showDocument(java.net.URL *url*, String *targetWindow*)
showDocument
的单参数形式简单地指示浏览器显示指定 URL 的文档,而不指定显示文档的窗口。
showDocument
的双参数形式允许您指定显示文档的窗口或 HTML 框架。第二个参数可以有以下值之一:
-
"_blank"
– 在一个新的、无名称的窗口中显示文档。 -
"*windowName*"
– 在名为 windowName 的窗口中显示文档。如有必要,将创建此窗口。 -
"_self"
– 在包含小程序的窗口和框架中显示文档。 -
"_parent"
– 在小程序框架的父框架中显示文档。如果小程序框架没有父框架,则与"_self"
相同。 -
"_top"
– 在顶层框架中显示文档。如果小程序框架是顶层框架,则与"_self"
相同。
注意: 在这个讨论中,frame 指的不是一个 Swing JFrame
,而是浏览器窗口内的 HTML 框架。
以下小程序使您可以尝试 showDocument
两种形式的每个参数。该小程序打开一个窗口,让您输入 URL 并选择 targetWindow
参数的选项。当您按下 Return 键或点击显示文档按钮时,小程序调用 showDocument
。
//<![CDATA[ var attributes = { code:‘ShowDocument.class’, archive:‘examples/dist/applet_ShowDocument/applet_ShowDocument.jar’, width:200, height:30} ; var parameters = { permissions:‘sandbox’ } ; deployJava.runApplet(attributes, parameters, ‘1.4’); //]]>
注意: 如果您看不到示例运行,可能需要在浏览器中启用 JavaScript 解释器,以便部署工具包脚本能够正常运行。
以下是调用 showDocument
的小程序代码。这是整个程序,ShowDocument
。
*...//In an Applet subclass:*
urlWindow = new URLWindow(getAppletContext());
. . .
class URLWindow extends Frame {
...
public URLWindow(AppletContext appletContext) {
...
this.appletContext = appletContext;
...
}
...
public boolean action(Event event, Object o) {
...
String urlString =
*/* user-entered string */*;
URL url = null;
try {
url = new URL(urlString);
} catch (MalformedURLException e) {
*...//Inform the user and return...*
}
if (url != null) {
if (*/* user doesn't want to specify
the window */*) {
appletContext.showDocument(url);
} else {
appletContext.showDocument(url,
*/* user-specified window */*);
}
}
...
下载源代码 以进一步尝试 Show Document 示例。
从小程序调用 JavaScript 代码
原文:
docs.oracle.com/javase/tutorial/deployment/applet/invokingJavaScriptFromApplet.html
Java 小程序可以调用与小程序在同一网页中的 JavaScript 函数。LiveConnect 规范描述了 JavaScript 代码如何与 Java 代码通信的详细信息。
netscape.javascript.JSObject
类使 Java 小程序能够检索对 JavaScript 对象的引用并与网页交互。接下来描述的数据摘要小程序调用 JavaScript 代码从网页中检索信息,并将数据摘要写回网页。
假设您有一个带有几个 JavaScript 函数的网页。示例AppletPage.html
具有用于检索年龄、地址和电话号码的 JavaScript 函数。还有一个名为userName
的变量,一开始没有值。
<head>
<title>Data Summary Applet Page - Java to JavaScript LiveConnect</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"/>
<script language="javascript">
var userName = "";
// returns number
function getAge() {
return 25;
}
// returns an object
function address() {
this.street = "1 Example Lane";
this.city = "Santa Clara";
this.state = "CA";
}
// returns an array
function getPhoneNums() {
return ["408-555-0100", "408-555-0102"];
}
function writeSummary(summary) {
summaryElem =
document.getElementById("summary");
summaryElem.innerHTML = summary;
}
</script>
<!-- ... -->
</head>
<body>
<script src =
"https://www.java.com/js/deployJava.js"></script>
<script>
<!-- ... -->
deployJava.runApplet(attributes, parameters, '1.6');
</script>
<!-- ... -->
<p id="summary"/> // this HTML element contains
// the summary
<!-- ... -->
</body>
接下来,考虑一个名为DataSummaryApplet
的小程序类。DataSummaryApplet
类执行以下操作。
- 调用
JSObject
的setMember
方法将userName
变量设置为"John Doe"。 - 检索年龄、地址和电话号码,并构建包含这些数据摘要的字符串。
- 调用
writeSummary
JavaScript 函数将摘要写回网页。
该小程序首先需要按以下方式检索对JSObject
的引用:
...
JSObject window = JSObject.getWindow(this);
...
将前述语句放入 try…catch…块中以处理netscape.javascript.JSException
。
现在,小程序已经有了对JSObject
的引用,它可以通过JSObject
的eval
和call
方法调用相关的 JavaScript 函数。
package javatojs;
import java.applet.Applet;
import netscape.javascript.*; // add plugin.jar to classpath during compilation
public class DataSummaryApplet extends Applet {
public void start() {
try {
JSObject window = JSObject.getWindow(this);
String userName = "John Doe";
// set JavaScript variable
window.setMember("userName", userName);
// invoke JavaScript function
Number age = (Number) window.eval("getAge()");
// get a JavaScript object and retrieve its contents
JSObject address = (JSObject) window.eval("new address();");
String addressStr = (String) address.getMember("street") ", "
(String) address.getMember("city") ", "
(String) address.getMember("state");
// get an array from JavaScript and retrieve its contents
JSObject phoneNums = (JSObject) window.eval("getPhoneNums()");
String phoneNumStr = (String) phoneNums.getSlot(0) ", "
(String) phoneNums.getSlot(1);
// dynamically change HTML in page; write data summary
String summary = userName " : " age " : "
addressStr " : " phoneNumStr;
window.call("writeSummary", new Object[] {summary}) ;
} catch (JSException jse) {
jse.printStackTrace();
}
}
}
要编译具有对netscape.javascript
包中类的引用的 Java 代码,请在类路径中包含<您的 JDK 路径>/jre/lib/plugin.jar
。在运行时,Java 插件软件会自动使这些类对小程序可用。
数据摘要小程序在网页上显示以下结果:
代码语言:javascript复制Result of applet's Java calls to JavaScript on this page
John Doe : 25 : 1 Example Lane, Santa Clara, CA : 408-555-0100, 408-555-0102
在浏览器中打开AppletPage.html
以查看数据摘要小程序。
注意: 如果您看不到小程序运行,请安装至少Java SE Development Kit (JDK) 6 update 10版本。
注意: 如果您看不到示例运行,请确保在浏览器中启用 JavaScript 解释器,以便部署工具包脚本能够正常运行。
下载源代码以进一步实验从小程序调用 JavaScript 代码示例。
从 JavaScript 代码调用 Applet 方法
原文:
docs.oracle.com/javase/tutorial/deployment/applet/invokingAppletMethodsFromJavaScript.html
网页上的 JavaScript 代码可以与嵌入在页面上的 Java applet 进行交互。JavaScript 代码可以执行以下操作:
- 调用 Java 对象上的方法
- 获取并设置 Java 对象中的字段
- 获取和设置 Java 数组元素
LiveConnect 规范描述了 JavaScript 代码如何与 Java 代码通信的详细信息。
当 JavaScript 代码调用 Java applet 时,会显示安全警告。要抑制这些警告,需要在 JAR 文件清单中添加Caller-Allowable-Codebase
属性。指定允许调用 applet 的 JavaScript 代码的位置。有关Caller-Allowable-Codebase
属性的信息,请参阅安全的 JAR 文件清单属性。
本主题探讨了使用 Math applet 示例进行 JavaScript 代码到 Java applet 通信。MathApplet
类和支持的Calculator
类提供了一组公共方法和变量。网页上的 JavaScript 代码调用和评估这些公共成员以传递数据并检索计算结果。
Math Applet 和相关类
这是MathApplet
类的源代码。getCalculator
方法返回Calculator
辅助类的引用。
package jstojava;
import java.applet.Applet;
public class MathApplet extends Applet{
public String userName = null;
public String getGreeting() {
return "Hello " userName;
}
public Calculator getCalculator() {
return new Calculator();
}
public DateHelper getDateHelper() {
return new DateHelper();
}
public void printOut(String text) {
System.out.println(text);
}
}
Calculator
类中的方法允许用户设置两个值,相加数字,并在范围内检索数字。
package jstojava;
public class Calculator {
private int a = 0;
private int b = 0; // assume b > a
public void setNums(int numA, int numB) {
a = numA;
b = numB;
}
public int add() {
return a b;
}
public int [] getNumInRange() {
int x = a;
int len = (b - a) 1;
int [] range = new int [len];
for (int i = 0; i < len; i ) {
range[i]= x ;
System.out.println("i: " i " ; range[i]: " range[i]);
}
return range;
}
}
DateHelper
类的getDate
方法返回当前日期。
package jstojava;
import java.util.Date;
import java.text.SimpleDateFormat;
public class DateHelper {
public static String label = null;
public String getDate() {
return label " " new SimpleDateFormat().format(new Date());
}
}
部署 Applet
在网页中部署 applet,AppletPage.html
。部署 applet 时,请确保为 applet 指定一个 id。稍后将使用 applet id 获取对 applet 对象的引用。
<script src=
"https://www.java.com/js/deployJava.js"></script>
<script>
<!-- applet id can be used to get a reference to
the applet object -->
var attributes = { id:'mathApplet',
code:'jstojava.MathApplet', width:1, height:1} ;
var parameters = { jnlp_href: 'math_applet.jnlp'} ;
deployJava.runApplet(attributes, parameters, '1.6');
</script>
接下来,在AppletPage.html
网页中添加一些 JavaScript 代码。JavaScript 代码可以使用 applet id 作为对 applet 对象的引用,并调用 applet 的方法。在下面的示例中,JavaScript 代码设置了 applet 的公共成员变量,调用了公共方法,并检索了由 applet 引用的另一个对象(Calculator
)的引用。JavaScript 代码能够处理基本类型、数组和对象返回类型。
<script language="javascript">
function enterNums(){
var numA = prompt('Enter number 'a'?','0');
var numB = prompt(
'Enter number 'b' (should be greater than number 'a' ?','1');
// set applet's public variable
mathApplet.userName = "John Doe";
// invoke public applet method
var greeting = mathApplet.getGreeting();
// get another class referenced by applet and
// invoke its methods
var calculator = mathApplet.getCalculator();
calculator.setNums(numA, numB);
// primitive datatype returned by applet
var sum = calculator.add();
// array returned by applet
var numRange = calculator.getNumInRange();
// check Java console log for this message
mathApplet.printOut("Testing printing to System.out");
// get another class, set static field and invoke its methods
var dateHelper = mathApplet.getDateHelper();
dateHelper.label = "Today's date is: ";
var dateStr = dateHelper.getDate();
<!-- ... -->
</script>
当数字 a = 0 和 b = 5 时,Math applet 在网页上显示以下结果:
代码语言:javascript复制Results of JavaScript to Java Communication
Hello John Doe
a = 0 ; b = 5
Sum: 5
Numbers in range array: [ 0, 1, 2, 3, 4, 5 ]
Today's date is: 5/28/13 4:12 PM //*shows current date*
在浏览器中打开AppletPage.html
以查看数学小程序。
注意: 如果您看不到小程序运行,请至少安装Java SE 开发工具包(JDK)6 更新 10版本。
注意: 如果您看不到示例运行,请确保在浏览器中启用 JavaScript 解释器,以便部署工具包脚本能够正常运行。
检查由 JavaScript 代码调用的小程序所受到的安全限制。
下载源代码以进一步进行实验的通过 JavaScript 代码调用小程序方法示例。
使用事件处理程序处理初始化状态
原文:
docs.oracle.com/javase/tutorial/deployment/applet/appletStatus.html
在 applet 初始化之前,applet 无法处理来自网页中 JavaScript 代码的请求。从 JavaScript 代码调用 applet 方法或访问 applet 变量将被阻塞,直到 applet 的init()
方法完成或 applet 首次从部署的网页中调用 JavaScript 代码。由于许多浏览器中 JavaScript 实现是单线程的,因此在 applet 启动期间,网页可能会出现冻结的情况。
从 JDK 7 版本开始,您可以在 applet 加载时检查status
变量,以确定 applet 是否准备好处理来自 JavaScript 代码的请求。您还可以注册事件处理程序,在 applet 初始化的各个阶段自动调用。为了利用这个功能,应该将 applet 部署时的java_status_events
参数设置为"true"
。
在状态和事件处理程序示例中,JavaScript 代码向 applet 注册了一个onLoad
处理程序。当 applet 初始化完成时,Java 插件软件会自动调用onLoad
处理程序。onLoad
处理程序调用 applet 的其他方法,在网页上绘制图形。DrawingApplet
类的init
方法休眠两秒,模拟长时间的 applet 初始化过程。
以下步骤描述了如何注册事件处理程序并检查 applet 的状态。请参阅Applet 状态和事件处理程序,了解可以注册事件处理程序的完整的 applet 状态值和 applet 事件列表。
创建一个 JavaScript 函数来注册事件处理程序。以下代码片段显示了registerAppletStateHandler
函数,如果 applet 尚未加载,则注册一个onLoad
事件处理程序。
<script>
<!-- ... -->
var READY = 2;
function registerAppletStateHandler() {
// register onLoad handler if applet has
// not loaded yet
if (drawApplet.status < READY) {
drawApplet.onLoad = onLoadHandler;
} else if (drawApplet.status >= READY) {
// applet has already loaded or there
// was an error
document.getElementById("mydiv").innerHTML =
"Applet event handler not registered because applet status is: "
drawApplet.status;
}
}
function onLoadHandler() {
// event handler for ready state
document.getElementById("mydiv").innerHTML =
"Applet has loaded";
draw();
}
<!-- ... -->
</script>
在body
标签的 onload 方法中调用先前创建的registerAppletStateHandler
函数。这样可以确保在注册 applet 的事件处理程序之前,applet 的 HTML 标签已经在网页的文档对象模型(DOM)树中创建。
<body onload="registerAppletStateHandler()">
将 applet 部署时的java_status_events
参数设置为"true"
。
<script src=
"https://www.java.com/js/deployJava.js"></script>
<script>
// set java_status_events parameter to true
var attributes = { id:'drawApplet',
code:'DrawingApplet.class',
archive: 'applet_StatusAndCallback.jar',
width:600, height:400} ;
var parameters = {java_status_events: 'true', permissions:'sandbox' } ;
deployJava.runApplet(attributes, parameters, '1.7');
</script>
在浏览器中打开AppletPage.html
以查看 applet 事件处理程序的行为。在AppletPageUpdatedDuringLoading.html
页面中,检查 applet 的status
变量以确定 applet 是否已加载。根据状态,当 applet 被加载时,网页会持续更新。
注意: 如果您看不到 applet 运行,请安装至少 Java SE Development Kit (JDK) 7 版本。
注意: 如果您看不到示例运行,您可能需要在浏览器中启用 JavaScript 解释器,以便 Deployment Toolkit 脚本能够正常运行。
下载源代码 以进一步进行实验的 状态和事件处理程序 示例。
操作小程序网页的 DOM
原文:
docs.oracle.com/javase/tutorial/deployment/applet/manipulatingDOMFromApplet.html
每个网页由一系列嵌套对象组成。这些对象构成了文档对象模型(DOM)。Java 小程序可以使用Common DOM API
遍历和修改其父网页的对象。
考虑一个 Java 小程序的示例,它会转储其父网页的内容。
为了遍历和操作 DOM 树,您必须首先获取网页的Document
对象的引用。您可以使用com.sun.java.browser.plugin2.DOM
类中的getDocument
方法来实现。以下是在DOMDump
小程序的start
方法中检索Document
对象引用的代码片段。请查看代码中的内联注释。
public void start() {
try {
// use reflection to get document
Class c =
Class.forName("com.sun.java.browser.plugin2.DOM");
Method m = c.getMethod("getDocument",
new Class[] { java.applet.Applet.class });
// cast object returned as HTMLDocument;
// then traverse or modify DOM
HTMLDocument doc = (HTMLDocument) m.invoke(null,
new Object[] { this });
HTMLBodyElement body =
(HTMLBodyElement) doc.getBody();
dump(body, INDENT);
} catch (Exception e) {
System.out.println("New Java Plug-In not available");
// In this case, you could fallback to the old
// bootstrapping mechanism available in the
// com.sun.java.browser.plugin.dom package
}
}
现在您已经获得了Document
对象的引用,您可以使用 Common DOM API 遍历和修改 DOM 树。DOMDump
小程序遍历 DOM 树并将其内容写入 Java 控制台日志。
private void dump(Node root, String prefix) {
if (root instanceof Element) {
System.out.println(prefix
((Element) root).getTagName()
" / " root.getClass().getName());
} else if (root instanceof CharacterData) {
String data =
((CharacterData) root).getData().trim();
if (!data.equals("")) {
System.out.println(prefix
"CharacterData: " data);
}
} else {
System.out.println(prefix
root.getClass().getName());
}
NamedNodeMap attrs = root.getAttributes();
if (attrs != null) {
int len = attrs.getLength();
for (int i = 0; i < len; i ) {
Node attr = attrs.item(i);
System.out.print(prefix HALF_INDENT
"attribute " i ": "
attr.getNodeName());
if (attr instanceof Attr) {
System.out.print(" = "
((Attr) attr).getValue());
}
System.out.println();
}
}
if (root.hasChildNodes()) {
NodeList children = root.getChildNodes();
if (children != null) {
int len = children.getLength();
for (int i = 0; i < len; i ) {
dump(children.item(i), prefix
INDENT);
}
}
}
}
在浏览器中打开AppletPage.html
以查看DOMDump
小程序的运行情况。检查 Java 控制台日志以获取网页 DOM 树的转储。
注意: 如果您看不到小程序运行,请至少安装Java SE Development Kit (JDK) 6 update 10版本。
注意: 如果您看不到示例运行,您可能需要在浏览器中启用 JavaScript 解释器,以便 Deployment Toolkit 脚本能够正常运行。
下载源代码以进一步进行实验的DOM Dump示例。