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

Jdk1.6新特性:

2014-08-23 12:53 211 查看
1.Web服务元数据

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技术堆栈.

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;

/**

* @author chinajash

*/

@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文件贴上了,大家可以自己动手试试.

2.脚本语言支持

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程序

/** * @author chinajash */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;/** * @author chinajash */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>

3.JTable的排序和过滤

原来的JTable基本上是只能显示数据,在JDK6新增了对JTable的排序和过滤功能,下面代码演示了这两个功能

/**

* @author chinajash

*/

public class JTableTester {

static String data[][] = {

{"China","Beijing","Chinese"},

{"America","Washington","English"},

{"Korea","Seoul","Korean"},

{"Japan","Tokyo","Japanese"},

{"France","Paris","French"},

{"England","London","English"},

{"Germany","Berlin","German"},

};

static String titles[] = {"Country","Capital","Language"};

public static void main(String[] args) {

DefaultTableModel m = new DefaultTableModel(data,titles);

JTable t = new JTable(m);

final TableRowSorter sorter = new TableRowSorter(m);

t.setRowSorter(sorter); //为JTable设置排序器

JScrollPane sPane = new JScrollPane();

sPane.setViewportView(t);

JPanel p = new JPanel();

p.setLayout(new BoxLayout(p,BoxLayout.X_AXIS));

JLabel l = new JLabel("Criteria:");

final JTextField tf = new JTextField();

JButton b = new JButton("Do Filter");

p.add(l);

p.add(tf);

p.add(b);

b.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

if(tf.getText().length()==0){

sorter.setRowFilter(null);

}else{

sorter.setRowFilter(RowFilter.regexFilter(tf.getText()));//为JTable设置基于正则表达式的过滤条件

}

}

});

JFrame f = new JFrame("JTable Sorting and Filtering");

f.getContentPane().add(sPane,BorderLayout.CENTER);

f.getContentPane().add(p,BorderLayout.SOUTH);

f.setSize(400,300);

f.setVisible(true);

}

}

运行上面程序,单击JTable的某一个title,这个title对应的列就会按照升序/降序重新排列;在下面的Criteria文本框中输入"ese",点击"Do Filter"按钮,JTable将只显示带有"ese"字符串的行,也就是China和Japan两行,如果文本框里面什么都没有,点击"Do
Filter"按钮,这时JTable会显示所有的行。

4.更简单,更强大的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类的源代码:

/**

* @author chinajash

*/

@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

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

5.轻量级Http Server

JDK6的新特性之五:轻量级Http Server

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

/**

* Created by IntelliJ IDEA.

* User: Chinajash

* Date: Dec 30, 2006

*/

public class HTTPServerAPITester {

public static void main(String[] args) {

try {

HttpServer hs = HttpServer.create(new InetSocketAddress(8888),0);//设置HttpServer的端口为8888

hs.createContext("/chinajash", new MyHandler());//用MyHandler类内处理到/chinajash的请求

hs.setExecutor(null); // creates a default executor

hs.start();

} catch (IOException e) {

e.printStackTrace();

}

}

}

class MyHandler implements HttpHandler {

public void handle(HttpExchange t) throws IOException {

InputStream is = t.getRequestBody();

String response = "<h3>Happy New Year 2007!--Chinajash</h3>";

t.sendResponseHeaders(200, response.length());

OutputStream os = t.getResponseBody();

os.write(response.getBytes());

os.close();

}

}

运行程序后,在浏览器内输入http://localhost:8888/xx,浏览器输出

6.嵌入式数据库 Derby

Derby是IBM送给开源社区的又一个礼物,是一个pure java的数据库,现在已经被列入到java1.6中。

不知道对于大数据量的性能如何,但传说中启动derby只会给JVM添加2M的内存,对那些小数据库应用,比如像用access那种应该是挺有诱惑力的。

另外,麻雀虽小,五脏俱全,功能要比access多得多咯,包括事务处理,并发,触发器都有,管理又简单,因此自己用来做点工具正好合适。

废话少说,介绍一下我折腾了半天的经验吧。

我的Derby配置过程:

1,下载db-derby-10.1.3.1-bin.tar.gz,derby_core_plugin_10.1.3.zip和derby_ui_plugin_1.1.0.zip,把两个插件安装到eclipse上

2,打开ecllipse,新建一个project

3,右键这个project,选择Apache Derby,再选择add apache derby native,发现只是给我的project添加了几个derby的jar,还不是在我看着顺眼的lib目录里,索性干掉,换上db-derby- 10.1.3.1-bin.tar.gz解压出来以后lib目录下的jar文件,在Build
Path里设置一下;

4,右键Project,在apache derby里选择start apache derby network server,控制台可以看到derby启动后打出的“服务器准备在端口 1527 上接受连接。”

5,右键Project,在apache derby里选择ij(Interactive SQL),启动SQL控制台;

6,输入connect jdbc:derby:testdb;create=true; 注意要有单引号,可以在工程跟目录下创建testdb数据库,可以看到一个新建的目录testdb,那里的文件就是数据库咯;

7,用标准的SQL语句来建一个数据库试试:

create table test (a varchar(4) not null, b char(2) primary key);

居然可以用,太神奇了,呵呵

8,再插入一条语句试试呢,insert into test(a,b) values(a,11);,嗯,不错,可以用select 查出来的哦。

9,再插一下:insert into test(a,b) values(a,11);,哦哦,报错了,“错误 23505:语句异常终止,因为它导致“TEST”上所定义的“SQL060710092132480”标识的唯一或主键约束或唯一索引中出现重复键值。” 呵呵。

10,好了,现在可以像你控制的其他数据库一样来控制Derby了。

如果上述方法不行,或者你习惯了在eclipse之外使用和管理数据库,那么可以很方便的把Derby“装”在系统里。下面我说一下步骤:

1,把db-derby-10.1.3.1-bin.tar.gz解压到c:\derby,使lib和framework两个目录在c:\derby下边即可

2,设置环境变量

设置一个c:\derby\framework\embeded\bin或c:\derby\framework\NetworkServe\bin到Path中,这样我们就可以直接执行上边介绍的connect这样的命令而不用每次钻到那个目录下去执行了

设置c:\derby\lib\derby.jar;c:\derby\lib\derbytoos.jar到CLASSPATH中,以便让这些java编成的命令能够正确执行;

3,打开cmd

4,敲入startNetworkServer,可以看到像在eclisp中提示的那样启动了server

5,再打开一个cmd,敲入sysinfo,可以看到derby的环境信息了,注意在java user dir这一项,也许是java用户目录上和上边看到的会有所不同哦,这样在connect jdbc:derby:testdb;create=true;的建的数据库目录就不一样咯。

6,敲入ij,好了,进入到上边的交互界面,可以建一个数据库看看了。

7,最后在另外一个cmd中敲入stopNetworkServer就可以关闭数据库了。

如果你两种方法都试过了,那么需要注意的,还是上边步骤5的问题,这个问题是你可能随时会启动一个数据库或新建一个数据库,但如果你刚刚使用derby,你可能还没有察觉。

derby实际上有两种启动方式,一种是嵌入式的,一种是网络服务器的启动。

1,我们在eclipse中右键start apache derby network server那个,就是网络服务器的启动方式,在这种方式下可以用另外一台计算机在ij中以:

connect jdbc:derby://192.168.0.28:1527/testdb

的方式进行链接。

2,第二种启动方式是在ij里边就直接

connect jdbc:derby:testdb

这实际是在连当前配置环境下java user dir下那个目录的数据库。

看到这里可能有点糊涂了,这么就会出问题了那?

实际上derby的访问更像是一种使用derby driver对本地文件系统的访问,不管启动不启动网络服务器,都可以用driver访问本地的数据库。这样,在ij里边像第二种方式那样建立连接是完全可以的。启动了网络服务器,只不过是能够让其他主机访问罢了。

另外一个问题是,在eclipse中和在系统中连接服务器,在connect的时候这个当前配置环境是不一样的,eclipse默认工程所在路径是数据库的所在路径,而在系统中“装”derby则会认为 c:\document and settings下边那个用户目录是数据库的所在路径。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: