您的位置:首页 > 编程语言 > Java开发

jdk6.0新特性介绍(续)

2011-06-13 09:29 453 查看
JDK6的新特性之七:用Console开发控制台程序

JDK6的新特性之七:用Console开发控制台程序

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

/**

* @authorWuLi

*/

public class ConsoleTest {

public static void main(String[] args) {

Console console = System.console();//获得Console实例

if(console!=null){//判断console是否可用

String user = new String(console.readLine("Enter user:")); //读取整行字符

String pwd = new String(console.readPassword("Enter passowrd:")); //读取密码,密码输入时不会显示

console.printf("User is:"+user+"/n");

console.printf("Password is:"+pwd+"/n");

}else{

System.out.println("Console is unavailable");

}

}

}

如果在NetBean5.5里面运行上面程序,会输出

Console is unavailable

表示Console不可获得,那是因为JVM不是在命令行中被调用的或者输入输出被重定向了. 但是如果我们在命令行中运行上面程序(java ConsoleTest),程序能够获得Console实例,并执行如下:

Enter user:chinajash

Enter passowrd:

User is:chinajash

Password is:chinajash

在这里可以看到输入密码时,控制台时不显示这些密码字符的,但是程序可以得到输入的密码字符串,这与Linux下面输入密码的情况是一样的

JDK6.0新特性之八:用Console开发控制台程序

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

/**

* @authorWuLi

*/

public class ConsoleTest {

 public static void main(String[] args) {

  Console console = System.console();//获得Console实例

  if(console!=null){//判断console是否可用

   String user = new String(console.readLine("Enter user:")); //读取整行字符

   String pwd = new String(console.readPassword("Enter passowrd:")); //读取密码,密码输入时不会显示

   console.printf("User is:"+user+"/n");

   console.printf("Password is:"+pwd+"/n");

  }else{

   System.out.println("Console is unavailable");

  }

 }

}

如果在NetBean5.5里面运行上面程序,会输出

  Console is unavailable

  表示Console不可获得,那是因为JVM不是在命令行中被调用的或者输入输出被重定向了. 但是如果我们在命令行中运行上面程序(java ConsoleTest),程序能够获得Console实例,并执行如下:

Enter user:chinajash

Enter passowrd:

User is:chinajash

Password is:chinajash

在这里可以看到输入密码时,控制台时不显示这些密码字符的,但是程序可以得到输入的密码字符串,这与Linux下面输入密码的情况是一样的。

JDK6的新特性之九:Common Annotations

JDK6的新特性之九: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

Annotation Retention Target Description

Generated Source ANNOTATION_TYPE, CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE 用于标注生成的源代码

Resource Runtime TYPE, METHOD, FIELD 用于标注所依赖的资源,容器据此注入外部资源依赖,有基于字段的注入和基于setter方法的注入两种方式

Resources Runtime TYPE 同时标注多个外部依赖,容器会把所有这些外部依赖注入

PostConstruct Runtime METHOD 标注当容器注入所有依赖之后运行的方法,用来进行依赖注入后的初始化工作,只有一个方法可以标注为PostConstruct

PreDestroy Runtime METHOD 当对象实例将要被从容器当中删掉之前,要执行的回调方法要标注为PreDestroy

RunAs Runtime TYPE 用于标注用什么安全角色来执行被标注类的方法,这个安全角色必须和Container 的Security角色一致的

RolesAllowed Runtime TYPE, METHOD 用于标注允许执行被标注类或方法的安全角色,这个安全角色必须和Container 的Security角色一致的

PermitAll Runtime TYPE, METHOD 允许所有角色执行被标注的类或方法

DenyAll Runtime TYPE, METHOD 不允许任何角色执行被标注的类或方法,表明该类或方法不能在Java EE容器里面运行

DeclareRoles Runtime TYPE 用来定义可以被应用程序检验的安全角色,通常用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的新特性之十:Web服务元数据(Web Services metadata)

JDK6的新特性之十:Web服务元数据(Web Services metadata)

.Net的Web Services元数据

早在.Net Framework 1.0中,微软就用元数据功能(.net的attribute特性)来标注要暴露成Web Service的方法,下面是用C#演示的利用.net的元数据功能暴露Web Service方法的代码片断.

public class TestWS{

[WebMethod]

public String sayHi(){

return "Hi!";

}

public int add(int d1,int d2){

return d1+d2;

}

}


面的[WebMethod]是加在方法sayHi上面的元数据,用来告诉Web Services引擎(一般是ASP.NET Runtime),
我这个方法需要暴露为一个Web Service,你需要帮我生成相应的WSDL描述及相关支持文件.而另一个方法add没有加这个元数据,所以Web
Services引擎就不会为该方法生成WSDL及相关支持文件

Java的Web Services元数据

Java
里的Web服务元数据跟微软的方案基本没有语义上的区别,自从JDK5添加了元数据功能(Annotation)之后,SUN几乎重构了整个J2EE体
系, 由于变化很大,干脆将名字也重构为Java EE, Java EE(当前版本为5.0)将元数据纳入很多规范当中,这其中就包括Web
Services的相关规范, 加入元数据之后的Web Services服务器端编程模型就跟上面看到的C#片断差不多了,
这显然比以前的JAX-RPC编程模型简单(当然, Axis的编程模型也很简单).这里要谈的Web服务元数据(JSR 181)只是Java Web
服务规范中的一个,它跟Common Annotations, JAXB2, StAX, SAAJ和JAX-WS等共同构成Java EE
5的Web Services技术堆栈.

JSR-181的元数据清单

下面介绍JSR-181里面各个元数据的相关参数及用途

Annotation Retention Target Description

WebService Runtime Type

标注要暴露为Web Services的类或接口

WebParam Runtime Parameter 自定义服务方法参数到WSDL的映射

WebResult Runtime Method 自定义服务方法返回值到WSDL的映射

WebMethod Runtime Method 自定义单个服务方法到WSDL的映射

Oneway Runtime Method 必须与@WebMethod连用,表明被标注方法只有输入没有输出,这就要求被标注方法不能有返回值,也不能声明checked exception

HandlerChain Runtime Type,Method,Field 将Web服务与外部Handler chain关联起来

SOAPBinding Runtime Type,Method 自定义SOAPBinding

JSR-181元数据使用示例

package WebServices;

import java.io.File;

import java.io.IOException;

import javax.jws.Oneway;

import javax.jws.WebMethod;

import javax.jws.WebParam;

import javax.jws.WebResult;

import javax.jws.WebService;

import javax.xml.ws.Endpoint;

/**

* @authorWuLi

*/

@WebService(targetNamespace="http://blog.csdn.net/chinajash

",serviceName="HelloService")

public class WSProvider {

@WebResult(name="Greetings")//自定义该方法返回值在WSDL中相关的描述

@WebMethod

public String sayHi(@WebParam(name="MyName") String name){

return "Hi,"+name; //@WebParam是自定义参数name在WSDL中相关的描述

}

@Oneway //表明该服务方法是单向的,既没有返回值,也不应该声明检查异常

@WebMethod(action="printSystemTime",operationName="printSystemTime")//自定义该方法在WSDL中相关的描述

public void printTime(){

System.out.println(System.currentTimeMillis());

}

public static void main(String[] args) {

Thread wsPublisher = new Thread(new WSPublisher());

wsPublisher.start();

}

private static class WSPublisher implements Runnable{

public void run() {

//发布WSProvider到http://localhost:8888/chinajash/WSProvider

这个地址,之前必须调用wsgen命令

//生成服务类WSProvider的支持类,命令如下:

//wsgen -cp . WebServices.WSProvider

Endpoint.publish("http://localhost:8888/chinajash/WSProvider

",new WSProvider());

}

}

}


果想看到Web Services Engine生成的WSDL文件是否遵守上面的元数据,
我们没有必要将上面的WSProvider部署到支持JSR-181的应用服务器或Servlet形式的Web Services
Engine,现在JDK6已经提供了一个很简单的机制可以用来测试和发布Web Services,下面讲讲如何在JDK6环境下发布Web
Services和查看生成的WSDL

1.将<JDK_HOME>/bin加入path环境变量

2.在命令行下切换当前目录到WSProvider的class文件所在的目录,运行下面命令

wsgen -cp . WebServices.WSProvider

在这个例子中会生成以下3个类的源代码文件及class文件

SayHi

SayHiResponse

PrintTime

3.执行如下代码发布WSProvider到http://localhost:8888/chinajash/WSProvider

,在这里可以执行WSProvider类的main方法就可以

Endpoint.publish("http://localhost:8888/chinajash/WSProvider

",new WSProvider());

4.在浏览器输入http://localhost:8888/chinajash/WSProvider?wsdl

就可以看到生成的WSDL文件,为了节省篇幅,这里就不把生成的WSDL文件贴上了,大家可以自己动手试试

JDK6的新特性之十一:更简单,更强大的JAX-WS

JDK6的新特性之十一:更简单,更强大的JAX-WS

JAX-WS2.0的来历

--------------------------------------------------------------------------------

JAX-WS(JSR-224)
是Java Architecture for XML Web Services的缩写,简单说就是一种用Java和XML开发Web
Services应用程序的框架, 目前版本是2.0, 它是JAX-RPC 1.1的后续版本, J2EE 1.4带的就是JAX-RPC1.1,
而Java EE 5里面包括了JAX-WS 2.0,但为了向后兼容,仍然支持JAX-RPC. 现在,SUN又把JAX-WS直接放到了Java
SE 6里面,由于JAX-WS会用到Common Annotation(JSR 250),Java Web Services
Metadata(JSR 181), JAXB2(JSR 222), StAX(JSR 173), 所以SUN也必须把后几个原属于Java
EE范畴的Components下放到Java SE, 现在我们可以清楚地理解了为什么Sun要把这些看似跟Java
SE没有关系的Components放进来,终极目的就是要在Java SE里面支持Web Services.

JAX-WS2.0的架构

--------------------------------------------------------------------------------

JAX-WS不是一个孤立的框架,它依赖于众多其他的规范,本质上它由以下几部分组成

1.用来开发Web Services的Java API

2.
用来处理Marshal/Unmarshal的XML Binding机制,JAX-WS2.0用JAXB2来处理Java
Object与XML之间的映射,Marshalling就是把Java
Object映射到XML,Unmarshalling则是把XML映射到Java Object.之所以要做Java
Object与XML的映射,是因为最终作为方法参数和返回值的Java
Object要通过网络传输协议(一般是SOAP)传送,这就要求必须对Java
Object做类似序列化和反序列化的工作,在SOAP中就是要用XML来表示Java object的内部状态

3.众多元数据(Annotations)会被JAX-WS用来描述Web Services的相关类,包括Common Annotations, Web Services Metadata, JAXB2的元数据和JAX-WS2.0规范自己的元数据.

4.Annotation
Processing
Tool(APT)是JAX-WS重要的组成部分,由于JAX-WS2.0规范用到很多元数据,所以需要APT来处理众多的Annotations.
在<JDK_HOME>/bin下有两个命令wsgen和wsimport,就是用到APT和Compiler
API来处理碰到的Annotations,wsgen可以为Web Services
Provider产生并编译必要的帮助类和相关支持文件,wsimport以WSDL作为输入为Web Service
Consumer产生并编译必要的帮助类和相关支持文件.

5.JAX-WS还包括JAX-WS Runtime与应用服务器和工具之间的契约关系

JAX-WS2.0的编程模型

--------------------------------------------------------------------------------


在用JAX-WS2.0来编写Web Services非常简单,不像JAX-RPC,JAX-WS可以把任意POJO暴露为Web
Services,服务类不需要实现接口,服务方法也没有必要抛出RMI异常.下面介绍在JDK6环境下用JAX-WS2.0开发和测试Web
Services的步骤

1.编写服务类,并用Web Services Metadata(JSR-181)标注这个服务类,我用我的另一篇BlogJDK6的新特性之十:Web服务元数据中的WSProvider类作为服务类的例子,在此我重复贴一下WSProvider类的源代码:

/**

* @authorWuLi

*/

@WebService(targetNamespace="http://blog.csdn.net/chinajash

",serviceName="HelloService")

public class WSProvider {

@WebResult(name="Greetings")//自定义该方法返回值在WSDL中相关的描述

@WebMethod

public String sayHi(@WebParam(name="MyName") String name){

return "Hi,"+name; //@WebParam是自定义参数name在WSDL中相关的描述

}

@Oneway //表明该服务方法是单向的,既没有返回值,也不应该声明检查异常

@WebMethod(action="printSystemTime",operationName="printSystemTime")//自定义该方法在WSDL中相关的描述

public void printTime(){

System.out.println(System.currentTimeMillis());

}

public static void main(String[] args) {

Thread wsPublisher = new Thread(new WSPublisher());

wsPublisher.start();

}

private static class WSPublisher implements Runnable{

public void run() {

//发布WSProvider到http://localhost:8888/chinajash/WSProvider

这个地址,之前必须调用wsgen命令

//生成服务类WSProvider的支持类,命令如下:

//wsgen -cp . WebServices.WSProvider

Endpoint.publish("http://localhost:8888/chinajash/WSProvider

",new WSProvider());

}

}

}

2.用wsgen生成上面服务类的必要的帮助类,然后调用用EndPoint类的静态方法publish发布服务类(步骤请参考我的另一篇Blog JDK6的新特性之十:Web服务元数据),我在这里是将服务类发布到http://localhost:8888/chinajash/WSProvider

3.用wsimport为服务消费者(也就是服务的客户端)生成必要的帮助类,命令如下:

wsimport http://localhost:8888/chinajash/WSProvider?wsdl

这会在<当前目录>/net/csdn/blog/chinajash下生成客户端的帮助类,在这个例子中会生成7个类

HelloService.class

ObjectFactory.class

package-info.class

PrintSystemTime.class

SayHi.class

SayHiResponse.class

WSProvider.class

4.在客户端用下面代码即可调用步骤1定义的Web Service

HelloService hs = new HelloService();

WSProvider ws = hs.getWSProviderPort();

System.out.println(ws.sayHi("chinajash"));

ws.printSystemTime();

调用上述代码后客户端控制台输出

hi,chinajash

服务端控制台输出服务器当前系统时间

JDK6的新特性之十二:脚本语言支持(Scripting)

JDK6的新特性之十二:脚本语言支持(Scripting)

概述

--------------------------------------------------------------------------------

JDK6
增加了对脚本语言的支持(JSR
223),原理上是将脚本语言编译成bytecode,这样脚本语言也能享用Java平台的诸多优势,包括可移植性,安全等,另外,由于现在是编译成
bytecode后再执行,所以比原来边解释边执行效率要高很多。加入对脚本语言的支持后,对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类,它是使用Scripting
API的入口,ScriptEngineManager可以通过jar服务发现(service
discovery)机制寻找合适的脚本引擎类(ScriptEngine),使用Scripting API的最简单方式只需下面三步

1、创建一个ScriptEngineManager对象

2、通过ScriptEngineManager获得ScriptEngine对象

3、用ScriptEngine的eval方法执行脚本

下面是一个Hello World程序

/**
* @authorWuLi */

public class HelloScript {

public static void
main(String[] args) throws Exception {

ScriptEngineManager
factory = new ScriptEngineManager();//step 1

ScriptEngine engine =
factory.getEngineByName("JavaScript");//Step 2

engine.eval("print('Hello, Scripting')");//Step 3 }

}

运行上面程序,控制台会输出Hello,
Scripting上面这个简单的Scripting程序演示了如何在Java里面运行脚本语言,除此之外,我们还可以利用Scripting
API实现以下功能1、暴露Java对象为脚本语言的全局变量2、在Java中调用脚本语言的方法3、脚本语言可以实现Java的接口4、脚本语言可以像
Java一样使用JDK平台下的类

下面的类演示了以上4种功能

package Scripting;

import
java.io.File;

import javax.script.Invocable;

import
javax.script.ScriptEngine;

import javax.script.ScriptEngineManager;

import
javax.script.ScriptException;

/** * @authorWuLi */

public class
ScriptingAPITester {

public static void main(String[] args) throws
Exception {

ScriptEngineManager manager = new
ScriptEngineManager();

ScriptEngine engine =
manager.getEngineByName("JavaScript");

testScriptVariables(engine);//演示如何暴露Java对象为脚本语言的全局变量

testInvokeScriptMethod(engine);//演示如何在Java中调用脚本语言的方法

testScriptInterface(engine);//演示脚本语言如何实现Java的接口

testUsingJDKClasses(engine);//演示脚本语言如何使用JDK平台下的类

}

public
static void testScriptVariables(ScriptEngine engine) throws
ScriptException{

File file = new File("test.txt");

engine.put("f", file);

engine.eval("println('Total
Space:'+f.getTotalSpace())");

}

public static void
testInvokeScriptMethod(ScriptEngine engine) throws Exception{

String script = "function hello(name) {

return 'Hello,' + name;}";

engine.eval(script);

Invocable inv = (Invocable) engine;

String res = (String)inv.invokeFunction("hello", "Scripting" );

System.out.println("res:"+res); }

public static void
testScriptInterface(ScriptEngine engine) throws ScriptException{

String script = "var obj = new Object();

obj.run = function() {
println('run method called'); }";

engine.eval(script);

Object obj = engine.get("obj");

Invocable inv = (Invocable)
engine;

Runnable r = inv.getInterface(obj,Runnable.class);

Thread th = new Thread(r);

th.start(); }

public static
void testUsingJDKClasses(ScriptEngine engine) throws Exception{

//Packages是脚本语言里的一个全局变量,专用于访问JDK的package

String js = "function
doSwing(t){

var f=new
Packages.javax.swing.JFrame(t);

f.setSize(400,300);f.setVisible(true);}";

engine.eval(js);

Invocable inv = (Invocable) engine;

inv.invokeFunction("doSwing", "Scripting Swing" );

}}Scripting
Tool

--------------------------------------------------------------------------------

SUN
提供的JDK6中有一个命令行工具??jrunscript,你可以在<JDK6_Home>/bin下面找到这个工
具,jrunscript是一个脚本语言的解释程序,它独立于脚本语言,但默认是用JavaScript,我们可以用jrunscript来测试自己写的
脚本语言是否正确,下面是一个在命令行运行jrunscript的简单例子

jrunscript

js>println("Hello,JrunScript");

Hello,JrunScript

js>9*8

72.0

js>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: