JDK6 新特性

JDK6新特性目录导航:

  • Desktop类和SystemTray类
  • JAXB2实现对象与XML之间的映射
  • StAX
  • Compiler API
  • 轻量级 Http Server API
  • 插入式注解处理API(Pluggable Annotation Processing API)
  • 用Console开发控制台程序
  • 对脚本语言的支持(如:ruby,groovy,javascript)
  • Common Annotations

 

Desktop类和SystemTray类

JDK6在java.awt包下新增了两个类:Desktop和SystemTray

Desktop类:允许 Java 应用程序启动已在本机桌面上注册的关联应用程序来处理 URI 或文件。

Desktop类的主要方法

1.browse(URI uri): 使用默认浏览器打开uri资源。

2.checkActionSupport(Action actionType): 检查是否支持的Action。

3.open(File file): 启动关联应用程序来打开文件。

4.edit(File file): 启动关联编辑器应用程序并打开一个文件编辑。

5.print(File file): 使用关联应用程序打印文件。

6.mail(): 启动用户默认邮件客户端的邮件组合窗口。

7.mail(URI mailtoURI): 启动用户默认邮件客户端的邮件组合窗口, 填充由 mailto:URI 指定的消息字段。

示例代码:

 1 import java.awt.*;
 2 import java.io.File;
 3 import java.io.IOException;
 4 import java.net.URI;
 5 
 6 public class Test {
 7     public static void main(String[] args) throws IOException {
 8         //先判断当前平台是否支持Desktop类
 9         if (Desktop.isDesktopSupported()) {
10             //获取Desktop实例
11             Desktop desktop = Desktop.getDesktop();
12             //使用默认浏览器打开链接
13             desktop.browse(URI.create("http://www.cnblogs.com/peter1018"));
14             // 打开指定文件/文件夹
15             desktop.open(new File("D:\\"));
16 
17             //......
18 
19             //其他方法可以自行演示...
20         }else {
21             System.out.println("当前平台不支持 Desktop类!");
22         }
23 
24     }
25 
26 }

SystemTray类代表一个系统托盘桌面。在微软的Windows上,它被称为“任务栏”状态区域,在Gnome上,它被称为“通知”在KDE上,它被称为“系统托盘”。该系统托盘由在桌面上运行的所有应用程序共享。

SystemTray类的主要方法:

1.isSupported() : 检测系统是否支持SystemTray类。

2.getSystemTray() : 获得SystemTray实例。

1.add(TrayIcon trayIcon): 在“系统托盘”上添加一个“TrayIcon”。TrayIcon对象代表一个托盘图标,它可以有一个工具提示(文本),一个图像,一个弹出框菜单,以及一组与之相关的侦听器。托盘图标一旦出现,就会在系统托盘中显示。

2.remove(TrayIcon trayIcon): 删除指定的“TrayIcon”。

3.getTrayIcons(): 返回一个由这个托盘添加到托盘上的所有图标的数组应用程序。

4.getTrayIconSize():  以像素为单位,返回在系统托盘中占据的一个托盘图标的大小

5.addPropertyChangeListener(String propertyName,PropertyChangeListener listener): 将 PropertyChangeListener 添加到监听器

6.removePropertyChangeListener(String propertyName,PropertyChangeListener listener): 将PropertyChangeListener 从监听器移除

7.getPropertyChangeListeners(String propertyName) : 返回所有已关联的监听器数组

示例代码:

 

 1 import javax.swing.*;
 2 import java.awt.*;
 3 
 4 public class Test {
 5     public static void main(String[] args) throws AWTException {
 6         //先判断当前平台是否支持SystemTray类
 7         if (SystemTray.isSupported()) {
 8             //获取SystemTray实例
 9             SystemTray systemTray = SystemTray.getSystemTray();
10             //获得托盘显示图标
11             ImageIcon imageIcon=new ImageIcon("D:\\icon.jpg");
12             //获得Image对象
13             Image icon=imageIcon.getImage();
14             //任务栏程序托盘图标
15             TrayIcon trayicon = new TrayIcon(icon,"JAVA系统托盘");
16             //关键点,设置托盘图标的自适应属性,这样才能在系统显示托盘处正常显示出需要的图片。
17             trayicon.setImageAutoSize(true);
18             //添加系统托盘
19             systemTray.add(trayicon);
20             //......
21             //其他方法可以自行演示...
22             //移除系统托盘
23             systemTray.remove(trayicon);
24         }else {
25             System.out.println("当前平台不支持 SystemTray类!");
26         }
27 
28     }
29 
30 }

 

展示结果如下:

 

JAXB2实现对象与XML之间的映射

JAXB是Java Architecture for XML Binding的缩写,可以将一个Java对象转变成为XML格式,反之亦然。我们把对象与关系数据库之间的映射称为ORM, 其实也可以把对象与XML之间的映射称为OXM(Object XML Mapping)。原来JAXB是Java EE的一部分,在JDK6中,SUN将其放到了Java SE中,这也是SUN的一贯做法。JDK6中自带的这个JAXB版本是2.0, 比起1.0(JSR 31)来,JAXB2(JSR 222)用JDK5的新特性Annotation来标识要作绑定的类和属性等,这就极大简化了开发的工作量。实际上,在Java EE 5.0中,EJB和Web Services也通过Annotation来简化开发工作。另外,JAXB2在底层是用StAX(JSR 173)来处理XML文档。 

重要的注解和说明

注解 说明

@XmlRootElement

将类或enum类型映射到XML元素,类名或名作为根节点

@XmlAttribute

将JavaBean属性映射到XML属性

@XmlElement

将JavaBean属性映射到源自属性名的XML元素

@XmlAnyAttribute

将JavaBean属性映射到通配符属性的映射

@XmlAnyElement

将JavaBean属性映射到XML infoset或JAXB

@XmlElements

一个用于多XmlElement注解的容器。

@XmlID

将JavaBean属性映射到XML ID

@XmlIDREF

将JavaBean属性映射到XML IDREF

@XmlList

用来将一个属性映射到一个List

@XmlSchema

将包映射到XML名称空间

@XmlTransient

该属性无需映射到XML

 

示例代码:

Address类

 1 import javax.xml.bind.annotation.XmlAttribute;
 2 import javax.xml.bind.annotation.XmlElement;
 3 
 4 public class Address {
 5 
 6     @XmlAttribute
 7     String province;
 8     @XmlElement
 9     String area;
10     @XmlElement
11     String street;
12 
13     public Address() {}
14 
15     public Address(String province, String area, String street) {
16         this.province = province;
17         this.area = area;
18         this.street = street;
19     }
20 
21     @Override
22     public String toString() {
23         return "Address{" +
24                 "province='" + province + '\'' +
25                 ", area='" + area + '\'' +
26                 ", street='" + street + '\'' +
27                 '}';
28     }
29 }

Person类

 1 import javax.xml.bind.annotation.XmlAttribute;
 2 import javax.xml.bind.annotation.XmlElement;
 3 import javax.xml.bind.annotation.XmlRootElement;
 4 
 5 @XmlRootElement
 6 public class Person{
 7 
 8     @XmlAttribute
 9     private String name;
10 
11     @XmlElement
12     private int age;
13 
14     @XmlElement
15     private Address address;
16 
17     public Person() {
18     }
19 
20     public Person(String name, int age, Address address) {
21         this.name = name;
22         this.age = age;
23         this.address = address;
24     }
25 
26     @Override
27     public String toString() {
28         return "Person{" +
29                 "name='" + name + '\'' +
30                 ", age=" + age +
31                 ", address=" + address +
32                 '}';
33     }
34 }

测试类:

 1 import javax.xml.bind.JAXBContext;
 2 import javax.xml.bind.JAXBException;
 3 import javax.xml.bind.Marshaller;
 4 import javax.xml.bind.Unmarshaller;
 5 import java.io.FileReader;
 6 import java.io.FileWriter;
 7 import java.io.IOException;
 8 
 9 public class Test {
10     public static void main(String[] args) throws JAXBException, IOException {
11         JAXBContext jaxbContext = JAXBContext.newInstance(Person.class);
12 
13         //根据Person对象转换为person.xml文件
14         Marshaller marshaller = jaxbContext.createMarshaller();
15         Address address = new Address("广东省","深圳市","宝安区");
16         Person person = new Person("niannianjiuwang", 20, address);
17         FileWriter fileWriter = new FileWriter("D:\\person.xml");
18         marshaller.marshal(person, fileWriter);
19 
20         //根据person.xml文件转换为对象
21         FileReader fileReader = new FileReader("D:\\person.xml");
22         Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
23         Person personNew = (Person) unmarshaller.unmarshal(fileReader);
24         System.out.println(personNew);
25     }
26 }

输出结果:

先看看person.xml文件:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person name="niannianjiuwang">
    <age>20</age>
    <address province="广东省">
        <area>深圳市</area>
        <street>宝安区</street>
    </address>
</person>

控制台结果:

Person{name='niannianjiuwang', age=20, address=Address{province='广东省', area='深圳市', street='宝安区'}}

 

StAX

StAX的来历 :

在JAXP1.3(JSR 206)有两种处理XML文档的方法:DOM(Document Object Model)和SAX(Simple API for XML).由于JDK6.0中的JAXB2(JSR 222)和JAX-WS 2.0(JSR 224)都会用到StAX所以Sun决定把StAX加入到JAXP家族当中来,并将JAXP的版本升级到1.4(JAXP1.4是JAXP1.3的维护版本). JDK6里面JAXP的版本就是1.4。

StAX简介:

StAX是Streaming API for XML的缩写,它包含在2004年3月的JSR 173 中。StAX是JDK6.0中包含的新特性。
在推式模型中,直到整个XML文件全部被解析,解析器才会产生解析事件。而拉式解析由应用程序来控制,也就是说解析事件由应用程序产生。这就意味着,你可以暂缓解析、解析时跳过某个元素或者同时解析多个文件。用DOM解析式要先将XML文件解析成DOM结构,因此降低了解析效率。使用StAX,解析事件在XML文件解析过程中产生。

下面是各种解析方法之间的比较:

XML Parser API Feature Summary
Feature StAX SAX DOM TrAX
API Type Pull, streaming Pull, streaming In memory tree XSLT Rule
Ease of Use High Medium High Medium
XPath Capability No No Yes Yes
CPU and Memory Efficiency Good Good Varies Varies
Forward Only Yes Yes No No
Read XML Yes Yes Yes Yes
Write XML Yes No Yes Yes
Create, Read, Update, Delete No No Yes No

StAX API同样也在JWSDP(Java Web Services Developer Pack )1.6中得到实现,你可以在包javax.xml.stream 中找到它。XMLStreamReader接口用来解析XML文件。XMLStreamWriter接口用来生成XML文件,XMLEventReader用一个对象事件迭代器来解析XML事件。与之相反,XMLStreamReader采用的是游标机制。

示例代码:

 

 1 import javax.xml.stream.*;
 2 import javax.xml.stream.events.XMLEvent;
 3 import java.io.FileInputStream;
 4 import java.io.FileNotFoundException;
 5 import java.io.FileOutputStream;
 6 
 7 public class Test {
 8     public static void main(String[] args) throws FileNotFoundException, XMLStreamException {
 9         writeXMLByStAX();//用XMLStreamWriter写xml文档
10         readXMLByStAX();//用XMLEventReader解析xml文档
11     }
12 
13     /**
14      * 通过StAX读XML
15      */
16     private static void readXMLByStAX() throws XMLStreamException, FileNotFoundException {
17         XMLInputFactory xmlif = XMLInputFactory.newInstance();
18         XMLEventReader xmler = xmlif.createXMLEventReader(new FileInputStream("D:\\write.xml"));
19         XMLEvent event;
20         StringBuffer parsingResult = new StringBuffer();
21         while (xmler.hasNext()) {
22             event = xmler.nextEvent();
23             parsingResult.append(event.toString());
24         }
25         System.out.println(parsingResult);
26     }
27 
28     /**
29      * 通过StAX写XML
30      */
31     private static void writeXMLByStAX() throws FileNotFoundException, XMLStreamException {
32         XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newFactory();
33         XMLStreamWriter xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(new FileOutputStream("D:\\write.xml"));
34 
35         // 写入默认的 XML 声明到xml文档
36         xmlStreamWriter.writeStartDocument();
37         // 写入注释到xml文档
38         xmlStreamWriter.writeComment("testing comment");
39         // 写入一个catalogs根元素
40         xmlStreamWriter.writeStartElement("catalogs");
41         xmlStreamWriter.writeNamespace("myUrl", "http://www.cnblogs.com/peter1018");
42         xmlStreamWriter.writeAttribute("name","niannianjiuwang");
43         // 写入子元素catalog
44         xmlStreamWriter.writeStartElement("http://www.cnblogs.com/peter1018", "catalog");
45         xmlStreamWriter.writeAttribute("id","StAX");
46         xmlStreamWriter.writeCharacters("Apparel");
47         // 写入catalog元素的结束标签
48         xmlStreamWriter.writeEndElement();
49         // 写入catalogs元素的结束标签
50         xmlStreamWriter.writeEndElement();
51         // 结束 XML 文档
52         xmlStreamWriter.writeEndDocument();
53         xmlStreamWriter.close();
54     }
55 }

输出结果:

write.xml文件内容:

<?xml version="1.0" ?><!--testing comment--><catalogs xmlns:myUrl="http://www.cnblogs.com/peter1018" name="niannianjiuwang"><myUrl:catalog id="StAX">Apparel</myUrl:catalog></catalogs>

 

控制台打印结果:

<?xml version="1.0" encoding='UTF-8' standalone='no'?><!--testing comment--><catalogs name='niannianjiuwang' xmlns:myUrl='http://www.cnblogs.com/peter1018'><['http://www.cnblogs.com/peter1018']:myUrl:catalog id='StAX'>Apparel</['http://www.cnblogs.com/peter1018']:myUrl:catalog></catalogs>ENDDOCUMENT

 

Compiler API

Java编程语言编译器javac读取以Java编程语言编写的源文件,并将它们编译为字节码class文件。或者,编译器也可以使用注解找到源文件和类文件并使用comiler API。编译器是一个命令行工具,但也可以使用Java compiler API调用。原话:官网介绍

我们可以用JDK6 的Compiler API(JSR 199)去动态编译Java源文件,Compiler API结合反射功能就可以实现动态的产生Java代码并编译执行这些代码,有点动态语言的特征。这个特性对于某些需要用到动态编译的应用程序相当有用, 比如JSP Web Server,当我们手动修改JSP后,是不希望需要重启Web Server才可以看到效果的,这时候我们就可以用Compiler API来实现动态编译JSP文件,当然,现在的JSP Web Server也是支持JSP热部署的,现在的JSP Web Server通过在运行期间通过Runtime.exec或ProcessBuilder来调用javac来编译代码,这种方式需要我们产生另一个进程去做编译工作,不够优雅而且容易使代码依赖与特定的操作系统;Compiler API通过一套易用的标准的API提供了更加丰富的方式去做动态编译,而且是跨平台的。

API Specification

 

示例代码:(Tips:运行代码之前必须在D目录下存放TestObject.java文件)

 1 import javax.tools.JavaCompiler;
 2 import javax.tools.JavaFileObject;
 3 import javax.tools.StandardJavaFileManager;
 4 import javax.tools.ToolProvider;
 5 import java.io.IOException;
 6 
 7 public class Test {
 8     public static void main(String[] args) throws IOException {
 9         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
10         StandardJavaFileManager standardJavaFileManager = compiler.getStandardFileManager(null,null,null);
11         Iterable<? extends JavaFileObject> sourcefiles = standardJavaFileManager.getJavaFileObjects("D:\\TestObject.java");
12         compiler.getTask(null, standardJavaFileManager, null, null, null, sourcefiles).call();
13         standardJavaFileManager.close();
14 
15     }
16 }

输出结果:会在D目录下生成TestObject.class文件。

轻量级 Http Server API 

JDK6 提供了一个简单的Http Server API,据此我们可以构建自己的嵌入式Http Server,它支持Http和Https协议,提供了HTTP1.1的部分实现,没有被实现的那部分可以通过扩展已有的Http Server API来实现,必须自己实现HttpHandler接口,HttpServer会调用HttpHandler实现类的回调方法来处理客户端请求,我们把一个Http请求和它的响应称为一个交换,包装成HttpExchange类,HttpServer负责将HttpExchange传给 HttpHandler实现类的回调方法。

示例代码:

 1 import com.sun.net.httpserver.HttpExchange;
 2 import com.sun.net.httpserver.HttpHandler;
 3 
 4 import java.io.*;
 5 
 6 public class TestHandler implements HttpHandler {
 7 
 8 
 9     @Override
10     public void handle(HttpExchange httpExchange) throws IOException {
11         System.out.println("==进入Hadnler方法");
12         String responseMsg = "OK";   //响应信息
13         InputStream in = httpExchange.getRequestBody(); //获得输入流
14         BufferedReader reader = new BufferedReader(new InputStreamReader(in));
15         String temp = null;
16         while((temp = reader.readLine()) != null) {
17             System.out.println("client request:"+temp);
18         }
19         httpExchange.sendResponseHeaders(200, responseMsg.length()); //设置响应头属性及响应信息的长度
20         OutputStream out = httpExchange.getResponseBody();  //获得输出流
21         out.write(responseMsg.getBytes());
22         out.flush();
23         httpExchange.close();
24     }
25 }
 1 import com.sun.net.httpserver.HttpServer;
 2 import com.sun.net.httpserver.spi.HttpServerProvider;
 3 
 4 import java.io.IOException;
 5 import java.net.InetSocketAddress;
 6 
 7 public class Test {
 8     public static void main(String[] args) throws IOException {
 9         //启动服务,监听来自客户端的请求
10         HttpServerProvider provider = HttpServerProvider.provider();
11         //监听8888端口,能同时接受100个请求
12         HttpServer httpserver =provider.createHttpServer(new InetSocketAddress(8888), 100);
13         //将 /test  请求交给 TestHandler 处理器处理
14         httpserver.createContext("/test", new TestHandler());
15         httpserver.setExecutor(null);
16         httpserver.start();
17         System.out.println("server started");
18     }
19 }

输出结果:

server started
==进入Hadnler方法
==进入Hadnler方法
==进入Hadnler方法

 

插入式注解处理 API(Pluggable Annotation Processing API)

插入式注解处理API(JSR 269)提供一套标准API来处理Annotations(JSR 175)。实际上JSR 269不仅仅用来处理Annotation,它还建立了Java 语言本身的一个模型,它把method, package, constructor, type, variable, enum,,annotation等Java语言元素映射为Types和Elements, 从而将Java语言的语义映射成为对象,我们可以在javax.lang.model包下面可以看到这些类. 所以我们可以利用JSR 269提供的API来构建一个功能丰富的元编程(metaprogramming)环境。JSR 269用Annotation Processor在编译期间而不是运行期间处理Annotation, Annotation Processor相当于编译器的一个插件,所以称为插入式注解处理。如果Annotation Processor处理Annotation时(执行process方法)产生了新的Java代码,编译器会再调用一次Annotation Processor,如果第二次处理还有新代码产生,就会接着调用Annotation Processor,直到没有新代码产生为止。每执行一次process()方法被称为一个"round",这样整个Annotation processing过程可以看作是一个round的序列,JSR 269主要被设计成为针对Tools或者容器的API。

举个例子,我们想建立一套基于Annotation的单元测试框架(如TestNG),在测试类里面用Annotation来标识测试期间需要执行的测试方法,如下所示:

@TestMethod
 public void testCheckName(){
       //do something here
 }

这时我们就可以用JSR 269提供的API来处理测试类,根据Annotation提取出需要执行的测试方法。

另一个例子是如果我们出于某种原因需要自行开发一个符合Java EE 5.0的Application Server(当然不建议这样做),我们就必须处理Common Annotations(JSR 250),Web Services Metadata(JSR 181)等规范的Annotations,这时可以用JSR 269提供的API来处理这些Annotations. 在现在的开发工具里面,Eclipse 3.3承诺将支持JSR 269

下面我用代码演示如何来用JSR 269提供的API来处理Annotations和读取Java源文件的元数据(metadata)

@SupportedAnnotationTypes("PluggableAPT.ToBeTested")//可以用"*"表示支持所有Annotations
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class MyAnnotationProcessor extends AbstractProcessor {
    private void note(String msg) {
        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, msg);
    }
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        //annotations的值是通过@SupportedAnnotationTypes声明的且目标源代码拥有的所有Annotations
        for(TypeElement te:annotations){
            note("annotation:"+te.toString());
        }
        Set<? extends Element> elements = roundEnv.getRootElements();//获取源代码的映射对象
        for(Element e:elements){
            //获取源代码对象的成员
            List<? extends Element> enclosedElems = e.getEnclosedElements();
            //留下方法成员,过滤掉其他成员
            List<? extends ExecutableElement> ees = ElementFilter.methodsIn(enclosedElems);
            for(ExecutableElement ee:ees){
                note("--ExecutableElement name is "+ee.getSimpleName());
                List<? extends AnnotationMirror> as = ee.getAnnotationMirrors();//获取方法的Annotations
                note("--as="+as); 
                for(AnnotationMirror am:as){
                    //获取Annotation的值
                    Map<? extends ExecutableElement, ? extends AnnotationValue> map= am.getElementValues();
                    Set<? extends ExecutableElement> ks = map.keySet();
                    for(ExecutableElement k:ks){//打印Annotation的每个值
                        AnnotationValue av = map.get(k);
                        note("----"+ee.getSimpleName()+"."+k.getSimpleName()+"="+av.getValue());
                    }
                }
            }
        }
        return false;
    }
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface ToBeTested{
    String owner() default "Chinajash";
    String group();
}

编译以上代码,然后再创建下面的Testing对象,不要编译Testing对象,我在后面会编译它

public class Testing{    
    @ToBeTested(group="A")
    public void m1(){
    }
    @ToBeTested(group="B",owner="QQ")
    public void m2(){
    }    
    @PostConstruct//Common Annotation里面的一个Annotation
    public void m3(){
    }    
}

下面我用以下命令编译Testing对象

javac -XprintRounds -processor PluggableAPT.MyAnnotationProcessor Testing.java

-XprintRounds表示打印round的次数,运行上面命令后在控制台会看到如下输出:

Round 1:
        input files: {PluggableAPT.Testing}
        annotations: [PluggableAPT.ToBeTested, javax.annotation.PostConstruct]
        last round: false
Note: annotation:PluggableAPT.ToBeTested
Note: --ExecutableElement name is m1
Note: ")
Note: ----m1.group=A
Note: --ExecutableElement name is m2
Note: ", owner="QQ")
Note: ----m2.group=B
Note: ----m2.owner=QQ
Note: --ExecutableElement name is m3
Note: --as=@javax.annotation.PostConstruct
Round 2:
        input files: {}
        annotations: []
        last round: true

本来想用JDK6.0的Compiler API来执行上面编译命令,可是好像现在Compiler API还不支持-processor参数,运行时总报以下错误

Exception in thread "main" java.lang.IllegalArgumentException: invalid flag: -processor PluggableAPT.MyAnnotationProcessor

调用Compiler API的代码是这样的

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> sourcefiles = fileManager.getJavaFileObjects("Testing.java");
Set<String> options = new HashSet<String>();
options.add("-processor PluggableAPT.MyAnnotationProcessor");
compiler.getTask(null, fileManager, null, options, null, sourcefiles).call();

不知道这是不是Compiler API的一个bug。

 

用Console开发控制台程序

JDK6中提供 了java.io.Console类专用来访问基于字符的控制台设备。程序如果要与Windows下的cmd或者Linux下的Terminal交互,就可以用Console类代劳。但我们不总是能得到可用的Console,一个JVM是否有可用的Console依赖于底层平台和JVM如何被调用。如果JVM是在交互式命令行(比如Windows的cmd)中启动的,并且输入输出没有重定向到另外的地方,那么就可以得到一个可用的Console实例 。

Console类:

 

示例代码:

 1 import java.io.Console;
 2 
 3 public class Test {
 4     public static void main(String[] args){
 5         Console console = System.console();
 6         if(console!=null){//判断console是否可用
 7             String user = new String(console.readLine("Enter user:")); //读取整行字符
 8             String pwd = new String(console.readPassword("Enter passowrd:")); //读取密码,密码输入时不会显示
 9             console.printf("User is:"+user+"/n");
10             console.printf("Password is:"+pwd+"/n");
11         }else{
12             System.out.println("JVM无法使用当前的Console");
13         }
14     }
15 }

在IntelliJ IDEA 中直接运行执行结果:

JVM无法使用当前的Console

在cmd里面直接 java Test 结果:红色字体是输入部分,密码后面输入默认是隐藏的

F:\test\>java Test
Enter user:niannianjiuwang
Enter passowrd:
User is:niannianjiuwang/nPassword is:123456/n

 

对脚本语言的支持(如: ruby, groovy, javascript)

JDK6增加了对脚本语言的支持(JSR 223),原理上是将脚本语言编译成字节码,这样脚本语言也能享用Java平台的诸多优势,包括可移植性,安全等,另外,由于现在是编译成字节码后再执行,所以比原来边解释边执行效率要高很多。加入对脚本语言的支持后,对

Java语言也提供了以下好处。
1、许多脚本语言都有动态特性,比如,你不需要用一个变量之前先声明它,你可以用一个变量存放完全不同类型的对象,你不需要做强制类型转换,因为转换都是自动的。现在Java语言也可以通过对脚本语言的支持间接获得这种灵活性。
2、可以用脚本语言快速开发产品原型,因为现在可以Edit-Run,而无需Edit-Compile-Run,当然,因为Java有非常好的IDE支持,我 们完全可以在IDE里面编辑源文件,然后点击运行(隐含编译),以此达到快速开发原型的目的,所以这点好处基本上可以忽略。
3、通过引入脚本语言可以轻松实现Java应用程序的扩展和自定义,我们可以把原来分布在在Java应用程序中的配置逻辑,数学表达式和业务规则提取出来,转用JavaScript来处理。

Sun的JDK6实现包含了一个基于Mozilla Rhino的 脚本语言引擎,支持JavaScript,这并不是说明JDK6只支持JavaScript,任何第三方都可以自己实现一个JSR-223兼容的脚本引擎 使得JDK6支持别的脚本语言,比如,你想让JDK6支持Ruby,那你可以自己按照JSR 223的规范实现一个Ruby的脚本引擎类,具体一点,你需要实现 javax.script.ScriptEngine(简单起见,可以继承 javax.script.AbstractScriptEngine) 和 javax.script.ScriptEngineFactory 两个接口。当然,在你实现自己的脚本语引擎之前,先到 scripting.dev.java.net project 这里看看是不是有人已经帮你做了工作,这样你就可以直接拿来用。

Scripting API

Scripting API是用于在Java里面编写脚本语言程序的API, 在Javax.script中可以找到Scripting API,我们就是用这个API来编写JavaScript程序,这个包里面有一个ScriptEngineManager类,它是使用Scriptng API 的入口,ScriptEngineManager可以通过Jar服务发现(service discovery)机制寻找合适的脚本引擎类(ScriptEngine),使用Scripting API的最简单方式只需下面三步
1、创建一个ScriptEngineManager对象
2、通过ScriptEngineManager获得ScriptEngine对象
3、用ScriptEngine的eval方法执行脚本

示例代码: 

 1 import javax.script.Invocable;
 2 import javax.script.ScriptEngine;
 3 import javax.script.ScriptEngineManager;
 4 
 5 public class Test {
 6     public static void main(String[] args){
 7         ScriptEngineManager factory = new ScriptEngineManager();
 8         ScriptEngine engine = factory.getEngineByName("JavaScript");
 9         String script;
10         try {
11             script = "print('Hello')";
12             engine.eval(script);// 执行脚本
13             script = "1-23*9/3+77";
14             System.out.println(engine.eval(script).toString());// 不用对字符串做解析便可得到算式结果
15             engine.put("a", "一个字符串");
16             script = "print(a)";
17             engine.eval(script);// 脚本调用java对象
18             script = "function hello(name) { return 'Hello,' + name;}";
19             engine.eval(script);
20             Invocable inv = (Invocable) engine;
21             System.out.println(inv.invokeFunction("hello", "Scripting"));//java调用脚本方法
22         } catch (Exception e) {
23             e.printStackTrace();
24         }
25     }
26 
27 }

输出结果:

Hello
9
一个字符串
Hello,Scripting

 

 Common Annotations

 Common annotations原本是Java EE 5.0(JSR 244)规范的一部分,现在SUN把它的一部分放到了Java SE 6.0中。随着Annotation元数据功能(JSR 175)加入到Java SE 5.0里面,很多Java 技术(比如EJB,Web Services)都会用Annotation部分代替XML文件来配置运行参数(或者说是支持声明式编程,如EJB的声明式事务), 如果这些技术为通用目的都单独定义了自己的Annotations,显然有点重复建设, 所以,为其他相关的Java技术定义一套公共的Annotation是有价值的,可以避免重复建设的同时,也保证Java SE和Java EE 各种技术的一致性。

下面列举出Common Annotations 1.0里面的10个Annotations Common Annotations 

  • @Generated:生成的注释用于标记已生成的源代码。
  • @Resource: 用于标注所依赖的资源,容器据此注入外部资源依赖,有基于字段的注入和基于setter方法的注入两种方式 。
  • @Resources: 同时标注多个外部依赖,容器会把所有这些外部依赖注入 。
  • @PostConstruct:标注当容器注入所有依赖之后运行的方法,用来进行依赖注入后的初始化工作,只有一个方法可以标注为PostConstruct 。
  • @RunAs:执行期间应用程序的角色 。
  • @PreDestroy:当对象实例将要被从容器当中删掉之前,要执行的回调方法要标注为RunAs用于标注用什么安全角色来执行被标注类的方法,这个安全角色必须和Container 的Security角色一致的。
  • @RolesAllowed: 用于标注允许执行被标注类或方法的安全角色,这个安全角色必须和Container 的Security角色一致的 。
  • @PermitAll:允许所有角色执行被标注的类或方法 。
  • @DenyAll:不允许任何角色执行被标注的类或方法,表明该类或方法不能在Java EE容器里面运行 。
  • @DeclareRoles:用来定义可以被应用程序检验的安全角色,通常用isUserInRole来检验安全角色 。

注意:

  1. RolesAllowed,PermitAll,DenyAll不能同时应用到一个类或方法上 
  2. 标注在方法上的RolesAllowed,PermitAll,DenyAll会覆盖标注在类上的RolesAllowed,PermitAll,DenyAll 
  3. RunAs,RolesAllowed,PermitAll,DenyAll和DeclareRoles还没有加到Java SE 6.0上来 
  4. 处理以上Annotations的工作是由Java EE容器来做, Java SE 6.0只是包含了上面表格的前五种Annotations的定义类,并没有包含处理这些Annotations的引擎,这个工作可以由Pluggable Annotation Processing API(JSR 269)来做

 

JDK6 改动最大的就是java GUI界面的显示,JDK6支持最新的windows vista系统的Windows Aero视图效果,而JDK5不支持。

 

posted @ 2018-06-11 15:46  念念就忘  阅读(972)  评论(0编辑  收藏