Java 中文官方教程 2022 版(三十)(3)https://developer.aliyun.com/article/1487965
课程:网络资源的国际化
在现代互联网社区中,许多用户不再满足于仅使用 ASCII 符号来识别域名或网络资源。例如,他们希望能够注册一个新的域名,使用阿拉伯语或中文中的本地字符。这就是为什么网络资源的国际化是拓宽万维网视野的基石。
本课程描述了网络域名资源的国际化。
国际化域名
国际化域名
从历史上看,互联网域名仅包含 ASCII 符号。随着互联网的普及和在全球范围内的采用,支持域名的国际化变得必要,特别是支持包含 Unicode 字符的域名。
应用程序中的国际化域名(IDNA)机制被采用为将 Unicode 字符转换为标准 ASCII 域名的标准,从而保持域名系统的稳定性。该系统执行查找服务,将用户友好的名称转换为网络地址。
国际化域名的示例:
http://清华大学.cn
http://www.транспорт.com
如果您点击这些链接,您会看到地址栏中表示的 Unicode 域名被替换为 ASCII 字符串。
要在应用程序中实现类似的功能,java.net.IDN
类提供了方法,用于在 ASCII 和非 ASCII 格式之间转换域名。
方法 | 目的 |
toASCII(String) toASCII(String, flag) |
在将 IDN 发送到域名解析系统或写入期望 ASCII 字符的文件(例如 DNS 主文件)之前使用。如果输入字符串不符合RFC 3490,这些方法会抛出IllegalArgumentException 异常。 |
toUnicode(String) toUnicode(String, flag) |
在向用户显示名称时使用,例如从 DNS 区域获取的名称。此方法将字符串从 ASCII 兼容编码(ACE)转换为 Unicode 代码点。此方法永远不会失败;在出现错误时,输入字符串保持不变并原样返回。 |
可选的flag
参数指定转换过程的行为。ALLOW_UNASSIGNED
标志允许包含 Unicode 3.2 中未分配的代码点。USE_STD3_ASCII_RULES
标志确保遵守 STD-3 ASCII 规则。您可以单独使用这些标志或逻辑上合并它们。如果不需要任何标志,请使用该方法的单参数版本。
教程:国际化的服务提供者
原文:
docs.oracle.com/javase/tutorial/i18n/serviceproviders/index.html
国际化的服务提供者使得可以插入区域相关的数据和服务。由于可以插入区域相关的数据和服务,第三方能够提供java.text
和java.util
包中大多数区域敏感类的实现。
服务是一组提供对特定应用程序功能或特性访问的编程接口和类。服务提供者接口(SPI)是服务定义的一组公共接口和抽象类。服务提供者实现了 SPI。服务提供者使您能够创建可扩展的应用程序,可以在不修改其原始代码库的情况下进行扩展。您可以通过新的插件或模块增强其功能。有关服务提供者和可扩展应用程序的更多信息,请参阅创建可扩展应用程序。
您可以使用国际化的服务提供者来提供以下区域敏感类的自定义实现:
BreakIterator
对象Collator
对象Locale
类的语言代码、国家代码和变体名称- 时区名称
- 货币符号
DateFormat
对象DateFormatSymbols
对象NumberFormat
对象DecimalFormatSymbols
对象
相应的 SPI 包含在java.text.spi
和java.util.spi
包中:
java.util.spi |
java.text.spi |
|
|
BreakIteratorProvider
CollatorProvider
DateFormatProvider
DateFormatSymbolsProvider
DecimalFormatSymbolsProvider
NumberFormatProvider
|
例如,如果您想为新的区域设置提供一个NumberFormat
对象,请实现java.text.spi.NumberFormatProvider
类并实现以下方法:
getCurrencyInstance(Locale locale)
getIntegerInstance(Locale locale)
getNumberInstance(Locale locale)
getPercentInstance(Locale locale)
Locale loc = new Locale("da", "DK"); NumberFormat nf = NumberFormatProvider.getNumberInstance(loc);
这些方法首先检查 Java 运行时环境是否支持请求的区域设置;如果支持,则使用该支持。否则,方法会调用已安装提供者的适当接口的getAvailableLocales
方法,以找到支持请求的区域设置的提供者。
要深入了解如何使用国际化服务提供者的示例,请参阅将自定义资源包作为扩展安装。本节展示了如何实现ResourceBundleControlProvider
接口,使您能够在不对应用程序源代码进行任何其他更改的情况下使用任何自定义ResourceBundle.Control
类。
安装自定义资源包作为扩展
原文:
docs.oracle.com/javase/tutorial/i18n/serviceproviders/resourcebundlecontrolprovider.html
自定义资源包加载部分向您展示如何更改资源包的加载方式。这涉及从类ResourceBundle.Control
派生一个新类,然后通过调用以下方法检索资源包:
ResourceBundle getBundle( String baseName, Locale targetLocale, ResourceBundle.Control control)
参数control
是您对ResourceBundle.Control
的实现。
java.util.spi.ResourceBundleControlProvider
接口使您能够更改以下方法加载资源包的方式:
ResourceBundle getBundle( String baseName, Locale targetLocale)
请注意,此版本的ResourceBundle.getBundle
方法不需要ResourceBundle.Control
类的实例。ResourceBundleControlProvider
是一个服务提供者接口(SPI)。SPI 使您能够创建可扩展的应用程序,即可以在不修改其原始代码库的情况下轻松扩展的应用程序。有关更多信息,请参阅创建可扩展应用程序。
要使用 SPI,首先通过实现类似ResourceBundleControlProvider
的 SPI 来创建一个服务提供者。当您实现一个 SPI 时,您指定它将如何提供服务。ResourceBundleControlProvider
SPI 提供的服务是在应用程序调用方法ResourceBundle.getBundle(String baseName, Locale targetLocale)
时获取适当的ResourceBundle.Control
实例。您将服务提供者与 Java 扩展机制一起打包为已安装的扩展。运行应用程序时,不需要在类路径中命名您的扩展;运行时环境会找到并加载这些扩展。
已安装的ResourceBundleControlProvider
SPI 实现将替换默认的ResourceBundle.Control
类(定义了默认的包加载过程)。因此,ResourceBundleControlProvider
接口使您可以使用任何自定义的ResourceBundle.Control
类,而无需对应用程序的源代码进行任何其他更改。此外,该接口使您能够编写应用程序,而无需引用任何自定义的ResourceBundle.Control
类。
RBCPTest.java
示例展示了如何实现ResourceBundleControlProvider
接口以及如何将其打包为已安装的扩展。这个示例被打包在 zip 文件RBCPTest.zip
中,包含以下文件:
src
java.util.spi.ResourceBundleControlProvider
RBCPTest.java
rbcp
PropertiesResourceBundleControl.java
PropertiesResourceBundleControlProvider.java
XMLResourceBundleControl.java
XMLResourceBundleControlProvider.java
resources
RBControl.properties
RBControl_zh.properties
RBControl_zh_CN.properties
RBControl_zh_HK.properties
RBControl_zh_TW.properties
XmlRB.xml
XmlRB_ja.xml
lib
rbcontrolprovider.jar
build
:包含所有打包在rbcontrolprovider.jar
中的文件以及类文件RBCPTest.class
build.xml
以下步骤展示了如何重新创建文件RBCPTest.zip
的内容,RBCPTest
示例的工作原理以及如何运行它:
- 创建 ResourceBundle.Control 类的实现。
- 实现 ResourceBundleControlProvider 接口。
- 在应用程序中调用 ResourceBundle.getBundle 方法。
- 通过创建配置文件注册服务提供者。
- 将提供者、其所需的类以及配置文件打包到一个 JAR 文件中。
- 运行 RBCPTest 程序。
1. 创建 ResourceBundle.Control 类的实现。
RBCPTest.java
示例使用了两种ResourseBundle.Control
的实现:
PropertiesResourceBundleControlProvider.java
:这是在自定义资源包加载中定义的相同ResourceBundle.Control
实现。XMLResourceBundleControl.java
:这个ResourceBundle.Control
实现使用Properties.loadFromXML
方法加载基于 XML 的包。
XML 属性文件
如在 使用属性文件支持 ResourceBundle 部分所述,属性文件是简单的文本文件。它们每行包含一个键值对。XML 属性文件与属性文件类似:它们包含键值对,只是具有 XML 结构。以下是 XML 属性文件 XmlRB.xml
:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties [ <!ELEMENT properties ( comment?, entry* ) > <!ATTLIST properties version CDATA #FIXED "1.0"> <!ELEMENT comment (#PCDATA) > <!ELEMENT entry (#PCDATA) > <!ATTLIST entry key CDATA #REQUIRED> ]> <properties> <comment>Test data for RBCPTest.java</comment> <entry key="type">XML</entry> </properties>
以下是等效的属性文本文件:
# Test data for RBCPTest.java type = XML
所有 XML 属性文本文件具有相同的结构:
- 指定文档类型定义(DTD)的 DOCTYPE 声明:DTD 定义了 XML 文件的结构。注意:在 XML 属性文件中,你可以使用以下 DOCTYPE 声明:
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
- 系统 URI (
http://java.sun.com/dtd/properties.dtd
) 在导出或导入属性时不会被访问;它是一个唯一标识 XML 属性文件的 DTD 的字符串。 - 根元素
:此元素包含所有其他元素。
- 任意数量的
元素:用于注释。
- 任意数量的
元素:使用属性
key
指定键;在标签之间指定键的值。
查看 Properties
类以获取有关 XML 属性文件的更多信息。
2. 实现 ResourceBundleControlProvider 接口。
这个接口包含一个方法,ResourceBundle.Control getControl(String baseName)
方法。参数 baseName
是资源包的名称。在 getBundle
方法的定义中,指定应返回的 ResourceBundle.Control
实例,给定资源包的名称。
RBCPTest
示例包含 ResourceBundleControlProvider
接口的两个实现,PropertiesResourceBundleControlProvider.java
和 XMLResourceBundleControlProvider.java
。如果资源包的基本名称以 resources.RBControl
开头,则方法 PropertiesResourceBundleControlProvider.getBundle
返回 PropertiesResourceBundleControl
的实例(在此示例中,所有资源文件都包含在 resources
包中):
package rbcp; import java.util.ResourceBundle; import java.util.spi.ResourceBundleControlProvider; public class PropertiesResourceBundleControlProvider implements ResourceBundleControlProvider { static final ResourceBundle.Control PROPERTIESCONTROL = new PropertiesResourceBundleControl(); public ResourceBundle.Control getControl(String baseName) { System.out.println("Class: " + getClass().getName() + ".getControl"); System.out.println(" called for " + baseName); // Throws a NPE if baseName is null. if (baseName.startsWith("resources.RBControl")) { System.out.println(" returns " + PROPERTIESCONTROL); return PROPERTIESCONTROL; } System.out.println(" returns null"); System.out.println(); return null; } }
类似地,如果资源包的基本名称以 resources.Xml
开头,则方法 XMLResourceBundleControlProvider.getControl
返回 XMLResourceBundleControl
的实例。
注意:你可以创建一个实现 ResourceBundleControlProvider
接口的实现,根据基本名称返回 PropertiesResourceBundleControl
或 XMLResourceBundleControl
的实例。
3. 在你的应用程序中,调用方法 ResourceBundle.getBundle。
类RBCPTest
使用方法ResourceBundle.getBundle
检索资源包:
import java.io.*; import java.net.*; import java.util.*; public class RBCPTest { public static void main(String[] args) { ResourceBundle rb = ResourceBundle.getBundle( "resources.XmlRB", Locale.ROOT); String type = rb.getString("type"); System.out.println("Root locale. Key, type: " + type); System.out.println(); rb = ResourceBundle.getBundle("resources.XmlRB", Locale.JAPAN); type = rb.getString("type"); System.out.println("Japan locale. Key, type: " + type); System.out.println(); test(Locale.CHINA); test(new Locale("zh", "HK")); test(Locale.TAIWAN); test(Locale.CANADA); } private static void test(Locale locale) { ResourceBundle rb = ResourceBundle.getBundle( "resources.RBControl", locale); System.out.println("locale: " + locale); System.out.println(" region: " + rb.getString("region")); System.out.println(" language: " + rb.getString("language")); System.out.println(); } }
请注意,此类中没有ResourceBundle.Control
或ResourceBundleControlProvider
的实现。因为ResourceBundleControlProvider
接口使用 Java 扩展机制,运行时环境会找到并加载这些实现。但是,使用 Java 扩展机制安装的ResourceBundleControlProvider
实现和其他服务提供程序是使用ServiceLoader
类加载的。使用此类意味着您必须使用配置文件注册服务提供程序,下一步将对此进行描述。
4. 通过创建配置文件注册服务提供程序。
配置文件的名称是提供程序实现的接口或类的完全限定名称。配置文件包含您的提供程序的完全限定类名。文件java.util.spi.ResourceBundleControlProvider
包含PropertiesResourceBundleControlProvider
和XMLResourceBundleControlProvider
的完全限定名称,每行一个名称:
rbcp.XMLResourceBundleControlProvider rbcp.PropertiesResourceBundleControlProvider
5. 将提供程序、其所需类和配置文件打包到 JAR 文件中。
编译源文件。从包含build.xml
文件的目录中,运行以下命令:
javac -d build src/java.* src/rbcp/*.java
此命令将编译src
目录中包含的源文件,并将类文件放在build
目录中。在 Windows 上,请确保使用反斜杠(\
)来分隔目录和文件名。
创建一个 JAR 文件,其中包含编译的类文件、资源文件和配置文件,目录结构如下:
META-INF
services
java.util.spi.ResourceBundleControlProvider
rbcp
PropertiesResourceBundleControl.class
PropertiesResourceBundleControlProvider.class
XMLResourceBundleControl.class
XMLResourceBundleControlProvider.class
资源
RBControl.properties
RBControl_zh.properties
RBControl_zh_CN.properties
RBControl_zh_HK.properties
RBControl_zh_TW.properties
XmlRB.xml
XmlRB_ja.xml
注意,配置文件java.util.spi.ResourceBundleControlProvider
必须打包在目录/META-INF/services
中。此示例将这些文件打包在lib
目录中的 JAR 文件rbcontrolprovider.jar
中。
查看在 JAR 文件中打包程序以获取有关创建 JAR 文件的更多信息。
或者,下载并安装Apache Ant,这是一个可以帮助您自动化构建过程的工具,例如编译 Java 文件和创建 JAR 文件。确保 Apache Ant 可执行文件在您的PATH
环境变量中,以便您可以从任何目录运行它。安装 Apache Ant 后,请按照以下步骤操作:
- 编辑文件
build.xml
,将${JAVAC}
更改为您的 Java 编译器javac
的完整路径名,并将${JAVA}
更改为您的 Java 运行时可执行文件java
的完整路径名。 - 从包含文件
build.xml
的相同目录运行以下命令:
ant jar
- 这个命令编译 Java 源文件并将它们与所需的资源和配置文件打包到
lib
目录中的 JAR 文件rbcontrolprovider.jar
中。
6. 运行 RBCPTest 程序。
在命令提示符下,从包含build.xml
文件的目录运行以下命令:
java -Djava.ext.dirs=lib -cp build RBCPTest
此命令假定以下情况:
- 包含 RBCPTest 示例编译代码的 JAR 文件位于
lib
目录中。 - 编译后的类
RBCPTest.class
位于build
目录中。
或者,使用 Apache Ant,并从包含build.xml
文件的目录运行以下命令:
ant run
当您安装 Java 扩展时,通常将扩展的 JAR 文件放在 JRE 的lib/ext
目录中。但是,此命令使用系统属性java.ext.dirs
指定包含 Java 扩展的目录。
RBCPTest
程序首先尝试使用基本名称为resources.XmlRB
和区域设置为Locale.ROOT
和Local.JAPAN
的资源包。程序检索这些资源包的输出类似于以下内容:
Class: rbcp.XMLResourceBundleControlProvider.getControl called for resources.XmlRB returns rbcp.XMLResourceBundleControl@16c1857 Root locale. Key, type: XML Class: rbcp.XMLResourceBundleControlProvider.getControl called for resources.XmlRB returns rbcp.XMLResourceBundleControl@16c1857 Japan locale. Key, type: Value from Japan locale
该程序成功获取XMLResourceBundleControl
的实例并访问属性文件XmlRB.xml
和XmlRB_ja.xml
。
当RBCPTest
程序尝试检索资源包时,它调用配置文件java.util.spi.ResourceBundleControlProvider
中定义的所有类。例如,当程序检索基本名称为resources.RBControl
和区域设置为Locale.CHINA
的资源包时,它打印以下输出:
Class: rbcp.XMLResourceBundleControlProvider.getControl called for resources.RBControl returns null Class: rbcp.PropertiesResourceBundleControlProvider.getControl called for resources.RBControl returns rbcp.PropertiesResourceBundleControl@1ad2911 locale: zh_CN region: China language: Simplified Chinese
教程:2D 图形
本教程向你介绍了 Java 2D™ API,并展示了如何在 Java 程序中显示和打印 2D 图形。本教程适用于希望丰富其对 Java 2D API 知识的开发人员,以及计算机图形初学者。几乎每个部分都包含相关示例来说明特定功能。Java 2D API 可以轻松执行以下任务:
- 绘制线条、矩形和任何其他几何形状。
- 用纯色、渐变和纹理填充这些形状。
- 使用选项绘制文本,对字体和渲染过程进行精细控制。
- 绘制图像,可选择应用滤镜操作。
- 在上述任何渲染操作期间应用诸如合成和变换等操作。
本章还解释了较不熟悉的概念,如合成。
使用 2D 图形 API 显示复杂图表
使用图像滤镜操作
本章描述了在屏幕和离屏图像、表面和打印机设备上绘制的概念。本教程涵盖了 Java 2D API 的最常见用法,并简要描述了一些更高级功能。
介绍了关键的 Java 2D 概念,并描述了 Java 2D 渲染模型。这节课比本教程的其他课程更具概念性,它让你深入了解基本概念和类描述。
使用一个开发的示例向你展示如何获取 Graphics 对象并将其用于常见的图形渲染任务。
教你如何使用 API 绘制图形基元和任意形状,以及如何应用花哨的描边和填充样式。
展示了如何有效地使用文本 API,包括如何创建具有所需属性的Font
对象,测量文本,并确定系统中可用字体的名称。
解释了如何创建 BufferedImage 对象,执行图像滤镜操作,并在图像上绘制。
教你如何将 2D 图形渲染到打印机,打印复杂文档,并使用打印服务。
解释了如何执行变换,裁剪绘图区域,合成重叠图形,指定渲染偏好,并控制渲染质量。
课程:Java 2D API 概念概述
Java 2D API 通过对抽象窗口工具包(AWT)的扩展,为 Java 程序提供了二维图形、文本和图像功能。这个全面的渲染包支持线条艺术、文本和图像,提供了一个灵活、功能齐全的框架,用于开发更丰富的用户界面、复杂的绘图程序和图像编辑器。Java 2D 对象存在于一个称为用户坐标空间或用户空间的平面上。当对象在屏幕或打印机上呈现时,用户空间坐标被转换为设备空间坐标。以下链接对开始学习 Java 2D API 很有帮助:
Java 2D API 提供以下功能:
- 用于显示设备和打印机的统一渲染模型
- 一系列几何基元,如曲线、矩形和椭圆,以及一种渲染几乎任何几何形状的机制
- 用于在形状、文本和图像上执行命中检测的机制
- 一个合成模型,提供对重叠对象如何呈现的控制
- 增强的颜色支持,有助于颜色管理
- 支持打印复杂文档
- 通过使用渲染提示控制渲染质量
这些主题在以下章节中讨论:
- Java 2D 渲染
- 几何基元
- 文本
- 图像
- 打印