求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
     
   
分享到
在Java SE平台上使用Headless模式
 
作者 Artem Ananiev,火龙果软件    发布于 2013-11-25
 

哪里才能用到此模式呢?想想你的应用不停的生成一张图片,比如,当用户每次登陆系统是都要生成一张认证图片。当创建图片时,你得应用既不需要显示器也不需要键盘。让我们假设一下,现在你的应用有个主架构或者专有服务器,但这个服务没有显示器,键盘或者鼠标。

这篇文章介绍怎样在标准Java(Java SE,也称作J2SE)平台上用Headless模式。

Headless模式是在缺少显示屏、键盘或者鼠标时的系统配置。听起来不可思议,但事实上你可以在这中模式下完成不同的操作,甚至是用图形数据也可以。

哪里才能用到此模式呢?想想你的应用不停的生成一张图片,比如,当用户每次登陆系统是都要生成一张认证图片。当创建图片时,你得应用既不需要显示器也不需要键盘。让我们假设一下,现在你的应用有个主架构或者专有服务器,但这个服务没有显示器,键盘或者鼠标。理想的决定是用环境的大量视觉计算能力而不是非视觉特性。在Headless模式下生成的图片可以传递到Headful系统进行更深层次渲染。

在java.awt.toolkit和java.awt.graphicsenvironment 类中有许多方法,除了对字体,图像和打印的操作外还有调用显示器,键盘和鼠标的方法。但是有一些类中,比如Canvas 和 Panel,可以在headless模式下执行。在J2SE 1.4平台之后就提供了对Headless模式的支持。

注:这篇文章重点讲的是Java SE6 平台版本的文档。任何API的增加或其他增强Java SE平台的规范是由JSR270专家组(JSR 270 Expert Group.)的审查和批准。

Toolkit

java.awt.Toolkit类是Abstract Window Toolkit (AWT)的 所有实现类的抽象父类。Toolkit的子类用于把各种AWT组件绑定到特定的本地toolkit实现上去。

如果显示设备,键盘或鼠标不支持的话,很多组件都会受影响。一个合适的类构造器应当抛出一个HeadlessException异常:

Button

Checkbox

Choice

Dialog

FileDialog

Frame

Label

List

Menu

MenuBar

MenuItem

PopupMenu

Scrollbar

ScrollPane

TextArea

TextField

Window

这种重量级的组件需要有一个操作系统级别上对等的图形函数来支持它,在headless的机器上它们将不能正常工作。

与Canvas、Panel和Image组件相关的组件不需要抛出HeadlessException异常,因为这些组件在操作系统级别上的对等图形函数可以使用空函数,然后作为轻量级组件来处理。

一个Headless的toolkit也会把Java组件绑定到本地资源上去,但是它只有在资源中不包含显示设备或输入设备时才会这样做。

Graphics Environment

java.awt.GraphicsEnvironment类是一个抽象类,它描述了在给定平台中,可以在Java技术中使用的由GraphicsDevice对象和Font对象组成的集合。该GraphicsEnvironment中的资源可以是本地的也可以是远程设备。

GraphicsDevice对象可以是显示器,打印机或者图形缓存等,并且它们是Graphics2D 绘制函数的目标。每一个GraphicsDevice都有许多与之关联的GraphicsConfiguration对象。这些对象指定了不同的配置环境,在这些配置环境中可以使用GraphicsDevice。

Table 1 显示GraphicsEnvironment 方法,检查Headless模式支持

Table 1. Headless 模式方法

方法描述 描述
public static boolean
isHeadless()
测试环境是否为headless, 对于是否不支持display device,keyboard,mouse。如果这个方法returns true,theToolkitandGraphicsEnvironmentclasses 抛出(thrown)依赖于display device, keyboard, mouse的aHeadlessExceptionis异常.
public boolean
isHeadlessInstance()
Returns thisGraphicsEnvironmentcan 是否支持dieplay device,keyboard,mouse. 如果这个方法 returns true, theGraphicsEnvironmentthat 抛出(throw)一个依赖于 display device, keyboard, mouse的aHeadlessExceptionis 异常.

注意:isHeadless()方法检查特定的系统属性,java.awt.headless而不是系统的硬件配置.

HeadlessException 抛出的代码,这取决于display device、keyboard、mouse在一个环境称为不支持任何这些.唯一的例外是来自一个 UnsupportedOperationException,本身就是来源于一个RuntimeException.

设置Headless模式

使用Headless模式操作,您必须首先了解如何检查和设置系统属性与此相关的模式。此外,你必须了解如何创建一个默认的工具包使用工具箱的无头实现类.

系统属性配置

为了启用headless模式,需要使用setProperty()方法去设置相应的系统属性。本方法可以让你用期望的值来设置系统属性。

System.setProperty("java.awt.headless", "true"); 

上面的代码中,java.awt.headless是一个系统属性,true是我们设定的值。

如果你想在一个相同的程序中使用headless和传统环境,你可以使用下面的命令行来完成:

java -Djava.awt.headless=true   

创建默认Toolkit

如果名字为java.awt.headless的系统属性被设置为true,那么headless工具包就会被使用。接下来使用getDefaultToolkit()方法来创建一个headless toolkit的实例:

Toolkit tk = Toolkit.getDefaultToolkit(); 

Headless模式检查

要检查Headless模式的可用性,使用GraphicsEnvironment类的isHeadless()方法:

GraphicsEnvironment ge =  
GraphicsEnvironment.getLocalGraphicsEnvironment();
boolean headless_check = ge.isHeadless();

该方法检查java.awt.headless系统属性。如果这个属性有一个为true的值,那么就会从工具包和依赖于一个显示器,键盘,鼠标的GraphicsEnvironment类的区域中抛出一个HeadlessException。

在Headless模式中操作

设置好headless模式并创建一个headless工具包的实例后,您的应用程序可以执行以下操作:

创建轻量级组件,如Canvas,Panel,和Swing组件,除了top级别.

收集关于可用的字体、字体指标和字体设置的信息

设置颜色来渲染文本和图形

创造和获取图像,为渲染准备图片

使用java.awt.PrintJob, java.awt.print.*, 和 javax.print.* 类进行打印。

发出"哔哔"音频。

Canvas(画布)

下面的代码会在屏幕上绘制出一个空白的矩形区域,你可以在上面绘制线条。可以使用Canvas类创建一个新的Canvas组件。

final Canvas c = new Canvas()  
{
public void paint(Graphics g)
{
Rectangle r = getBounds();
g.drawLine(0, 0, r.width - 1, r.height - 1);
g.drawLine(0, r.height - 1, r.width - 1, 0);
}
};

Fonts(字体)

这段代码显示了怎么使用Font类画一个文本字符串并设置文字的字体。Graphics对象是用来绘制这个字符串的。

public void paint(Graphics g)  
{
g.setFont(new Font("Arial", Font.ITALIC, 12));
g.drawString("Test", 32, 8);
}

Colors

这段代码显示了如何使用指定的红,绿,蓝的值来设置一条线的颜色。Graphics对象是用来绘制这条线的。

public void paint(Graphics g)  
{
g.setColor(new Color(255, 127, 0));
g.drawLine(0, r.height - 1, r.width - 1, 0);
}

Images

在下面的代码中,javax.imageio.ImageIO类的使用read()方法对图1所示的grapefruit.jpg文件进行解码,并返回一个缓存图片。

Image i = null;  
try
{
File f = new File("grapefruit.jpg");
i = ImageIO.read(f);
}
catch (Exception z)
{
z.printStackTrace(System.err);
}

这段代码演示了如何打印已经准备好的画布,你可以使用paint方法自定义打印机的的默认画面。

PrinterJob pj = PrinterJob.getPrinterJob();  
pj.setPrintable(new Printable()
{
public int print(Graphics g, PageFormat pf, int pageIndex)
{
if (pageIndex > 0)
{
return Printable.NO_SUCH_PAGE;
}

((Graphics2D)g).translate(pf.getImageableX(),
pf.getImageableY());

// Paint canvas.
c.paint(g);

return Printable.PAGE_EXISTS;
}
});

Beep

下面的这段代码展示了如果使用 Toolkit类的beep方法发出嘟嘟声。

Toolkit tk = Toolkit.getDefaultToolkit();  
tk.beep();

使用Headless模式简单例子

以下的HeadlessBasics例子运用了文章中描述的所有功能。

要运行这个的例子,需要用javac对下面的代码进行编译。复制grapefruit.jpg图片文件到HeadlessBasics类所在的目录下面。

import java.awt.*;  
import java.io.*;
import java.awt.print.*;

import javax.imageio.*;

public class HeadlessBasics
{
public static void main(String[] args)
{
// Set system property.
// Call this BEFORE the toolkit has been initialized, that is,
// before Toolkit.getDefaultToolkit() has been called.
System.setProperty("java.awt.headless", "true");

// This triggers creation of the toolkit.
// Because java.awt.headless property is set to true, this
// will be an instance of headless toolkit.
Toolkit tk = Toolkit.getDefaultToolkit();
// Standard beep is available.
tk.beep();

// Check whether the application is
// running in headless mode.
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
System.out.println("Headless mode: " + ge.isHeadless());

// No top levels are allowed.
boolean created = false;
try
{
Frame f = new Frame("Frame");
created = true;
}
catch (Exception z)
{
z.printStackTrace(System.err);
created = false;
}
System.err.println("Frame is created: " + created);

// No other components except Canvas and Panel are allowed.
created = false;
try
{
Button b = new Button("Button");
created = true;
}
catch (Exception z)
{
z.printStackTrace(System.err);
created = false;
}
System.err.println("Button is created: " + created);

// Canvases can be created.
final Canvas c = new Canvas()
{
public void paint(Graphics g)
{
Rectangle r = getBounds();
g.drawLine(0, 0, r.width - 1, r.height - 1);
// Colors work too.
g.setColor(new Color(255, 127, 0));
g.drawLine(0, r.height - 1, r.width - 1, 0);
// And fonts
g.setFont(new Font("Arial", Font.ITALIC, 12));
g.drawString("Test", 32, 8);
}
};
// And all the operations work correctly.
c.setBounds(32, 32, 128, 128);

// Images are available.
Image i = null;
try
{
File f = new File("grapefruit.jpg");
i = ImageIO.read(f);
}
catch (Exception z)
{
z.printStackTrace(System.err);
}
final Image im = i;

// Print system is available.
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPrintable(new Printable()
{
public int print(Graphics g, PageFormat pf, int pageIndex)
{
if (pageIndex > 0)
{
return Printable.NO_SUCH_PAGE;
}
((Graphics2D)g).translate(pf.getImageableX(),
pf.getImageableY());

// Paint the canvas.
c.paint(g);

// Paint the image.
if (im != null)
{
g.drawImage(im, 32, 32, 64, 64, null);
}

return Printable.PAGE_EXISTS;
}
});
try
{
pj.print();
}
catch (Exception z)
{
z.printStackTrace(System.err);
}
}
}

此外,你可以看到以下的信息:

Headless mode: true 
java.awt.HeadlessException
at java.awt.GraphicsEnvironment.checkHeadless(Unknown Source)
at java.awt.Window.<init>(Unknown Source)
at java.awt.Frame.<init>(Unknown Source)
at HeadlessBasics.main(HeadlessBasics.java:24)
Frame is created: false
java.awt.HeadlessException
at java.awt.GraphicsEnvironment.checkHeadless(Unknown Source)
at java.awt.Button.<init>(Unknown Source)
at HeadlessBasics.main(HeadlessBasics.java:39)
Button is created: false

注:出于演示的目的,最初的代码会导致此应用程序抛出2个java.awt.HeadlessExceptions异常。

作为上一种方式的替代,你可以把标准输出信息放到一个文件中,然后把文件打印出来。在这种情况下,使用下面的命令行来运行这个例子:

java HeadlessBasics 2> standard_output.txt

把现有的应用程序转换为Headless模式。

你怎么把现有的应用程序转换为可执行的headless模式?要执行此转换的最有效的方法是分析你的源代码以确定任何的功能都是依赖于Headless模式的。换句话说,要实现相同的功能,你必须找到那些会抛出HeadlessException异常的类和方法,然后使用独立的headless模式替换这些类和方法。

你可以使用Java SE 6 API说明来判断一个特定的类或方法是否支持headless模式。如果一个特定的组件不支持headless模式,你的程序需要捕获的唯一的异常是 HeadlessException。它会在其它可能的异常之前被抛出。这也是为什么在本节的代码示例"举例: 使用Headless模式"中,没有什么特殊的必要性来捕获其它异常。

你肯定会发现其它有用的方法来使用headless模式带来的好处。我们希望本文能帮你完成此项任务,在Java SE平台中玩出一片新天地。

相关文章

Java微服务新生代之Nacos
深入理解Java中的容器
Java容器详解
Java代码质量检查工具及使用案例
相关文档

Java性能优化
Spring框架
SSM框架简单简绍
从零开始学java编程经典
相关课程

高性能Java编程与系统性能优化
JavaEE架构、 设计模式及性能调优
Java编程基础到应用开发
JAVA虚拟机原理剖析
 
分享到
 
 


Java 中的中文编码问题
Java基础知识的三十个经典问答
玩转 Java Web 应用开发
使用Spring更好地处理Struts
用Eclipse开发iPhone Web应用
插件系统框架分析
更多...   


Struts+Spring+Hibernate
基于J2EE的Web 2.0应用开发
J2EE设计模式和性能调优
Java EE 5企业级架构设计
Java单元测试方法与技术
Java编程方法与技术


Struts+Spring+Hibernate/EJB+性能优化
华夏基金 ActiveMQ 原理与管理
某民航公司 Java基础编程到应用开发
某风电公司 Java 应用开发平台与迁移
日照港 J2EE应用开发技术框架与实践
某跨国公司 工作流管理JBPM
东方航空公司 高级J2EE及其前沿技术
更多...