Archive for July 8th, 2007

You are currently browsing the archives of Enabling Technology .

回国了,周日中午一点多飞,周一晚上约7点到上海。

上海至旧金山 CA985 2.4.5.6.7 1750 1155 CA986 2.5.7 1355 1930+1
NW5986 2.4.5.6.7 1750 1155 NW5986 2.5.7 1355 1930+1
UA858 1.2.4.6.7 1235 0700 UA857 2.4.5.6.7 1345 1900+1

Posted by micas on Jul 8th 2007 | Filed in Work | Comments (0)

Software Engineer, Client 客户端软件工程师(2/2)

帮朋友招人,公司是世界著名的游戏开发公司:EA,电子艺界

Location: Shanghai,China

Responsibilities:

  • Develop and maintain client applications, and online games
  • Work with internal product definition and operation team, to develop, integrate, maintain and enhance software applications
  • Flexible with working hours to accommodate interaction with a global customer base (different time zones) and during ramp up times

Requirements:

  • Self-motivated with strong work ethics
  • Solid understanding of software engineering and object oriented design principles
  • Strong knowledge and practical experience with the C++ and Windows Programming
  • 4+ years of solid programming experience in game industry or related
  • Practical experience with Windows UI/MFC/etc
  • Willingness to work with different technologies
  • Ability to communicate effectively with internal staff members and external studio partners
  • Computer science Degree or equivalent
  • May require travel as needed

Desirable Skills:

  • COM/ATL programming,IE Control programming
  • Able to read/write in English
  • Experienced in Java
  • Working knowledge of UNIX (Solaris and Linux) environments.
  • Experience with Apache/Tomcat, J2EE, XML.
  • Experience developing multi-tier distributed applications that use multithreading, synchronization, and databases.
  • Experience with HTML, JSP’s, servlets, relational databases (Oracle preferred), SQL, and JDBC.
  • 3D graphic programming ability, including DierctX9, Maya scripting and plugins

有意者请将应聘信及简历,电邮至admin@enabling-tech.com 

Posted by micas on Jul 8th 2007 | Filed in Enabling-tech | Comments (0)

Software Engineer-Online 软件工程师-网络游戏(1/2)

帮朋友招人,公司是世界著名的游戏开发公司:EA,电子艺界 

Location: Shanghai,China

Responsibilities:

  • Online game technical design, implementation and maintenance.
  • Work with producers, artists and QA on implementing, maintaining and enhancing online games
  • Flexible with working hours to accommodate interaction with a global customer base (different time zones) and during ramp up times

Requirements:

  • Self-motivated with strong work ethics
  • Solid understanding of software engineering and object oriented design principles 
  • Strong knowledge and practical experience with the C++ as well as Java programming language 
  • Demonstrated experience with a full dev cycle on a shipped game software product 
  • 5+ years of solid programming experience in game industry or related 
  • Ability to analyze and debug complex systems 
  • Willingness to work with different technologies 
  • Computer science Degree or equivalent 
  • Passion for developing great games 
  • May be required to travel

Desirable Skills:

  • 3d Graphics / DirectX / HLSL / XNA 
  • Physics Simulations 
  • Working knowledge of UNIX (Solaris and Linux) environments. 
  • Experience with Apache/Tomcat, J2EE, XML. 
  • Experience developing multi-tier distributed applications that use multithreading, synchronization, and databases.
  • Experience with HTML, JSP’s, servlets, relational databases (Oracle preferred), SQL, and JDBC.

有意者请将应聘信及简历,电邮至admin@enabling-tech.com 

Posted by micas on Jul 8th 2007 | Filed in Work | Comments (0)

AOP = Proxy Pattern + Method Reflection + Aspect DSL + 自动代码生成

学如逆水行舟,不进则退。
半年多来,居无常所,没有稳定的上网环境,这次抽空上来一看,又有好多陌生的名词漫天飞舞了。
落伍退化得很厉害。不过,我还能温故而知新,炒炒冷饭,写写基本的内容AOP。怀旧一番。

AOP = Proxy Pattern + Method Reflection + Aspect DSL + 自动代码生成

Declarative Programming & DSL

Aspect Oriented Programming(面向方面编程,简称AOP)是一种Declarative Programming(声明式编程)。
Declarative Programming(声明式编程)是和Imperative Programming(命令式编程)相对的概念。
我们平时使用的编程语言,比如C++、Java、Ruby、Python等,都属于Imperative Programming(命令式编程)。Imperative Programming(命令式编程)的意思是,程序员需要一步步写清楚程序需要如何做什么(How to do What)。
Declarative Programming(声明式编程)的意思是,程序员不需要一步步告诉程序如何做,只需要告诉程序在哪些地方做什么(Where to do What)。比起Imperative Programming(命令式编程)来,Declarative Programming(声明式编程)是在一个更高的层次上编程。Declarative Programming编程语言是更高级的语言。Declarative Programming通常处理一些总结性、总览性的工作,不适合做顺序相关的细节相关的底层工作。
如果说Imperative Programming是拼杀在第一线的基层工作人员,Declarative Programming就是总设计师、规则制定者。
Declarative Programming Language的概念,和Domain Specific Language(领域专用语言,简称DSL)的概念有相通之处。DSL主要是指一些对应专门领域的高层编程语言,和通用编程语言的概念相对。DSL对应的专门领域(Domain)一般比较狭窄,或者对应于某个行业,或者对应于某一类具体应用程序,比如数据库等。
最常见的DSL就是关系数据库的结构化数据查询语言SQL。同时,SQL也是一门Declarative Programming Language。SQL只需要告诉数据库,处理符合一定条件的数据,而不需要自己一步步判断每一条数据是否符合条件。SQL的形式一般是 select … where …,update … where …,delete … where …。
当然,这样一来,很多基层工作,SQL做不了。因此,大部分数据库都提供了另外的Imperative Programming Language,用来编写Stored Procedure(存储过程)等,以便处理一些更加细节的工作。
常见的DSL还有Rule Engine(规则引擎)语言、Workflow(工作流)语言等。Rule Engine和Workflow同时带有Imperative Programming和Declarative Programming的特点。
Rule Engine允许用户按照优先级定义一系列条件组合,并定义对满足条件的数据的处理过程。
Workflow也大致类似。Workflow把最基本的条件判断和循环语句的常见组合,定义为更加高级复杂的常用程序流程逻辑块。用户可以用这些高级流程块组合更加复杂的流程块,从而定义更加复杂的流程跳转条件。用户也可以定义当程序运行上下文满足一定条件的时候,应该做什么样的处理工作。
Rule Engine和Workflow的语言形式有可能是XML格式,也有可能是Ruby、Python、Javascript等脚本格式。我个人比较倾向于脚本格式,因为XML适合表达结构化数据,而不擅长表达逻辑流程。当然,XML格式的好处也是显而易见的。解析器可以很容易分析XML文件的结构,XML定义的条件或者程序流程都可以很方便地作为数据来处理。
介绍了Declarative Programming和DSL之后,我们来看本章题目表达的内容——AOP。
AOP是Declarative Programming,AOP语言也可以看作是DSL。AOP语言对应的专门领域(Domain)就是程序结构的方方面面(Aspect),比如程序的类、方法、成员变量等结构,以及针对这些程序结构的通用工作处理,比如日志管理、权限管理、事务管理等。
AOP处理的工作内容一般都是这样的一些总结性工作:“我想让所有的数据库类都自动进行数据库映射”、“我想打印出所有业务类的工作流程日志”、“我想给所有关键业务方法都加上事务管理功能”、“我想给所有敏感数据处理方法都加上安全管理授权机制”等等。
下面我们介绍AOP的实现原理和使用方法。

AOP实现原理

AOP的实现原理可以看作是Proxy/Decorator设计模式的泛化。
我们先来看Proxy模式的简单例子。
Proxy {
innerObject; // 真正的对象
f1() {
// 做一些额外的事情

innerObject.f1(); // 调用真正的对象的对应方法

// 做一些额外的事情
}
}

在Python、Ruby等动态类型语言中,只要实现了f1()方法的类,都可以被Proxy包装。在Java等静态类型语言中,则要求Proxy和被包装对象实现相同的接口。动态语言实现Proxy模式要比静态语言容易得多,动态语言实现AOP也要比静态语言容易得多。
假设我们用Proxy包装了10个类,我们通过调用Proxy的f1()方法来调用这10个类的f1()方法,这样,所有的f1()调用都会执行同样的一段“额外的工作”,从而实现了“所有被Proxy包装的类,都执行一段同样的额外工作”的任务。这段“额外的工作”可能是进行日志记录,权限检查,事务管理等常见工作。
Proxy模式是可以叠加的。我们可以定义多种完成特定方面任务(Aspect),比如,我们可以定义LogProxy、SecurityProxy、TransactionProxy,分别进行日志管理、权限管理、事务管理。
LogProxy {
f1(){
// 记录方法进入信息

innerObject.f1();// 调用真正的对象的对应方法

// 记录方法退出信息
}
}

SecurityProxy {
f1(){
// 进行权限验证

innerObject.f1();// 调用真正的对象的对应方法
}
}

TransactonProxy {
f1(){
Open Transaction

innerObject.f1();// 调用真正的对象的对应方法

Close Transaction
}
}

根据AOP的惯用叫法,上述的这些Proxy也叫做Advice。这些Proxy(or Advice)可以按照一定的内外顺序套起来,最外面的Proxy会最先执行。
包装f1()方法,也叫做截获(Intercept)f1()方法。Proxy/Advice有时候也叫做Interceptor。
看到这里,读者可能会产生两个问题。
问题一:上述代码采用的Proxy模式只是面向对象的特性,怎么会扯上一个新概念“面向方面(AOP)”呢?
问题二:Proxy模式虽然避免了重复“额外工作”代码的问题,但是,每个相关类都要被Proxy包装,这个工作也是很烦人。AOP Proxy如何能在应用程序中大规模使用呢?
下面我们来解答着两个问题。

对于问题一,我们来看一个复杂一点的例子。
假设被包装对象有f1()和f2()两个方法都要被包装。
RealObject{
f1() {…}
f2() {…}
}

这个时候,我们应该如何做?难道让Proxy也定义f1()和f2()两个方法?就象下面代码这样?
Proxy {
innerObject; // 真正的对象
f1() {
// 做一些额外的事情

innerObject.f1(); // 调用真正的对象的对应方法

// 做一些额外的事情
}

f2() {
// 做一些额外的事情

innerObject.f2(); // 调用真正的对象的对应方法

// 做一些额外的事情
}

}

这样做有几个不利之处。一是会造成代码重复,Proxy的f1()和f2()里面的“做一些额外的事情”代码重复。二是难以扩展,被包装对象可能有多个不同的方法,不同的被包装对象需要被包装的方法也可能不同。
现在的问题就变成,“Proxy如何才能包装截获任何类的任何方法?”
答案呼之欲出。对,就是Reflection。Java、Python、Ruby都支持Reflection,都支持Method(方法)对象。那么我们就利用Method Reflection编写一个能够解惑任何类的任何方法的Proxy/Advice/Interceptor。

MethodInterceptor{

around( method ){
// 做些额外的工作

method.invoke(…); // 调用真正的对象方法

// 做些额外的工作
}
}

上述的MethodInterceptor就可以分别包装和截获f1()和f2()两个方法。
这里的method参数就是方法对象,在Java、Ruby等面向对象语言中,需要用Reflection获取方法对象。这个方法对象就相当于函数式编程的函数对象。
在函数式编程中,函数对象属于“一等公民”,函数对象的获取不需要经过Reflection机制。所以,函数式编程对AOP的支持,比面向对象编程更好。
由此我们看到,AOP对应的问题领域确实超出了OOP的力所能及的范围。OOP只能处理同一个类体系内的同一个方法签名的截获和包装工作,一旦涉及到一个类的多个不同方法,或者多个不同类体系的不同方法,OOP就黔驴技穷,无能为力了。
使用Method Reflection的方式截获任何方法对象,是AOP的常用实现手段之一。另一个常见手段就是自动代码生成了。这也回答了前面提出的问题二——如何在应用系统中大规模使用AOP。
Proxy Pattern + Method Reflection + 自动代码生成 这样一个三元组合,就是AOP的基本实现原理。
Proxy Pattern 和 Method Reflection,前面已经做了阐述,下面我们来讲解自动代码生成。
首先,AOP需要定义一种Aspect描述的DSL。Aspect DSL主要用来描述这样的内容:“用TransactionProxy包装截获business目录下的所有类的公共业务方法”、“ 用SecurityProxy包装截获所有Login/Logout开头的类的所有公共方法”、“用LogProxy包装截获所有文件的所有方法”等等。
Aspect DSL的形式有多种多样。有的是一种类似Java的语法,比如AspectJ;有的是XML格式或者各种脚本语言,比如,Spring AOP等。
有了Aspect DSL,AOP处理程序就可以生成代码了。AOP生成代码有三种可能方式:
(1)静态编译时期,源代码生成。为每个符合条件的类方法产生对应的Proxy对象。AspectJ以前就是这种方式。
(2)静态编译时期,处理编译后的字节码。Java、Python之类的虚拟机语言都有一种中间代码(Java的中间代码叫做字节码),AOP处理程序可以分析字节码,并直接产生字节码形式的Proxy。这种方式也叫做静态字节码增强。AspectJ也支持这种方式。Java有一些开源项目,比如ASM、Cglib等,可以分析并生成Java字节码。这些开源项目不仅可以静态分析增强字节码,还可以在程序运行期动态分析增强字节码。很多AOP项目,比如Spring AOP,都采用ASM/Cglib处理字节码。
(3)动态运行时期,即时处理装载到虚拟机内部的类结构字节码。这也叫做动态增强。比如,Spring AOP。如前所述,Spring AOP使用ASM/Cglib之类的处理字节码的开源项目。Java运行库本身也提供了类似于ASM/Cglib的简单的动态处理字节码的API,叫做Dynamic Proxy。

以上就是AOP的实现原理:Proxy Pattern + Method Reflection + Aspect DSL + 自动代码生成。
总体来说,实现AOP的便利程度,函数式编程语言 > 动态类型语言 > 静态类型语言。当然,这个不等式并不是绝对的。有些动态类型语言提供了丰富强大的语法特性,实现AOP的便利程度,可能要超过函数式编程语言。

DSL & Parser

本章前面还提到了DSL。SQL、Rule Engine、Workflow、Aspect DSL都属于DSL。
DSL有可能是XML格式,也有可能是脚本格式。XML的解析比较容易,但是,XML不适合表达逻辑。脚本格式表达逻辑很方便灵活,但是,解析上就没有XML那么容易。
DSL不是通用编程语言,语法一般比较简单,没有通用编程语言那么复杂。很多DSL提供商都自己定义语法。一些程序设计大师甚至提出Language Oriented Programming(面向语言编程,简称LOP)的激进观点,认为每一个应用程序都可能需要一套独立的自定义DSL。这个观点提出来之后,跟风者众。业界掀起自定义DSL的狂潮。
从特定角度来看,这个观点是有一定道理的。一般来说,每一个应用程序都需要一套特定功能的公用函数库。DSL的目的正好就是处理特定领域的特定问题。从这个意义上来说,特定功能公用函数库和DSL的作用是一致的。DSL可以代替特定功能公用函数库的作用。DSL定义的关键字就相当于公用函数库的API函数名。
DSL关键字比起API函数名的优势在于可读性好。
比如,用DSL(比如SQL)我们可以写,select * from …. where a = 1
用API函数我们就要写,Query.find( tableName, new NumberEqualCriteria(“a”, 1) )
两者的可读性优劣一目了然。
而且,DSL一般都是解释执行,不需要参与源程序编译,这使得DSL程序(相当于API函数的调用程序)很容易修改和配置。
但DSL的实现不如编写API函数那么容易,尤其是脚本格式的DSL,程序员需要解析并执行DSL脚本,需要实现一个小型解释器。
对于很简单的语法,可以利用动态类型语言的高级特性,实现DSL脚本语句到函数方法调用的映射。比如,Open Transaction这条DSL语句经过简单的分析处理,可以映射为函数调用Transaction.open()。
复杂一些的DSL语法就需要用到专门的Parser(解析器)了。看过编译原理知识的读者,应该还有印象:Parser(解析器)是编译器的重要组成部分,Parser可以分为字符串分析、词法分析、语法分析、语义分析等部分,Parser是一个相当复杂的程序。
如果每一套自定义DSL都需要程序员从头开始重新写一个Parser,代价很大,得不偿失。幸亏有一些辅助产生Parser的应用程序,可以帮助生成Parser。
Parser产生器可以分为两种:
(1)Parser Generator。比如,antlr、javacc、yacc等项目。程序员定义BNF格式的语法说明,然后用Parser Generator根据BNF语法说明,产生对应的Parser程序。BNF格式是类似于这样的一种表达方式:a ::= b & c; d ::= e | f。有兴趣的读者可以查阅BNF的具体定义。Parser Generator的优点在于BNF语法简单通用,缺点在于需要静态生成Parser源代码。
(2)Parser Combinator。代表作是Haskell语言编写的一个叫做Parsec的项目。Parser Generator提供了基本的字符串解析器、词法分析器等,还提供了与或非、循环、选择、提前几步判断等语法组合子。
一个叫做ajoo的程序员把Parsec翻译成Java、c#.net、Ruby等多种语言版本的开源项目。这些项目把各种高级编程概念体现得淋漓尽致,是很好的学习和研究资料。

Posted by micas on Jul 8th 2007 | Filed in Enabling-tech | Comments (0)

纯java 的javascript引擎:rhino 【转】

关键字: 企业应用   纯java 的javascript引擎 rhino js引擎 java脚本引擎    

前段时间,在浏览javaeye论坛,看见有人征集如何在java中运行数学表达式。
结果方案五花八门:
1.jakarta commons JEXL.
2.Beanshell
3.Java Math Expression Parser jep
4.parse combinator jparsec
5.jdk 6.0的 script
6.利用SQL
7.自己写语法分析
如果自己写语法分析,没有个2000行估计搞不定。有人用sql来运行数学表达式,比较另类。
不过由于前段时间较深入的学习了一些java的javascript引擎,我给出的方案就是用javascript来计算了。
java中比较著名的js引擎当属mozilla开源的rhino,不过jdk6已经把它收归帐下,成了正规军。

  1. public class MathEval   
  2. {   
  3.     public static void main(String[] args)   
  4.     {   
  5.         Context cx = Context.enter();   
  6.         try  
  7.         {   
  8.             Scriptable scope = cx.initStandardObjects();   
  9.             String str = “9*(1+2)”;   
  10.             Object result = cx.evaluateString(scope, str, null1null);   
  11.             double res = Context.toNumber(result);   
  12.             System.out.println(res);   
  13.         }   
  14.         finally  
  15.         {   
  16.             Context.exit();   
  17.         }   
  18.     }   
  19. }  

下面总结一下前段时间学习rhino的心得(给自己的程序添加脚本功能,其实是很酷的):

一:环境配置及运行js脚本:
在 http://www.mozilla.org/rhino/ 下载rhino:
把js.jar加入系统CLASSPATH中
可以以交互模式调用js解释器:
java org.mozilla.javascript.tools.shell.Main
然后您应该会看到解释器的版本号,后面跟着提示符 js>
用法如下:
比如:有一个js文件:
D:\eclipse-workshop\rhinoExample\src\isPrime.js
内容如下:

js 代码

  1. function isPrime (num)   
  2. {   
  3.     if (num <= 1) {   
  4.         print(“Please enter a positive integer >= 2.”)   
  5.         return false  
  6.     }   
  7.        
  8.     var prime = true  
  9.     var sqrRoot = Math.round(Math.sqrt(num))   
  10.        
  11.     for (var n = 2; prime & n <= sqrRoot; ++n) {   
  12.         prime = (num % n != 0)   
  13.     }   
  14.        
  15.     return prime   
  16. }  

如何运行呢:
1:在命令行下键入:
java org.mozilla.javascript.tools.shell.Main
2:在js〉下键入:
load(”D:/eclipse-workshop/rhinoExample/src/isPrime.js”);
注意:是“/”而不是“\”
3:键入:
isPrime(77);
可看见返回结果为false。
键入:
isPrime(71);返回true

再给个例子,脚本如下:

  1. person = {   
  2.   name:“Mike Squillace”,   
  3.   age:37,   
  4.   position:“software engineer”,   
  5.   getFirstName:function () {return this.name.split(“ ”)[0]}   
  6. }   
  7. person.getFirstName()  

js产生swing的例子:
load(”D:/eclipse-workshop/rhinoExample/src/SwingApplication.js”);
怎么样?看见效果没?是不是很强悍?其中SwingApplication.js是rhnio自带的例子。


Rhino还有一个js脚本的调试器:
Rhino JavaScript Debugger:
java org.mozilla.javascript.tools.debugger.Main [options] [filename.js] [script-arguments]

只须运行java org.mozilla.javascript.tools.debugger.Main,就可以看到调试器的界面了。
为了加快js文件运行的速度,可以把它编译为class文件:
compile:
java org.mozilla.javascript.tools.jsc.Main D:/eclipse-workshop/rhinoExample/src/FirstCompile.js
编译产生FirstCompile.class文件
在D:/eclipse-workshop/rhinoExample/src/下运行该class文件:
java FirstCompile

二:在实际应用中不可避免的需要遇到java代码如何和javascript脚本相互访问的问题:
这是一个最简单的例子:(liveConnect.js是rhnio自带的例子):
load(”D:/eclipse-workshop/rhinoExample/src/liveConnect.js”);

在给个复杂点的例子, 没有什么逻辑,纯技术展示,呵呵:
JSFunction.java:

java 代码

  1. package co.test;   
  2.   
  3. import org.mozilla.javascript.Function;   
  4.   
  5. public class JSFunction  //extends ScriptableObject   
  6. {   
  7.  private String name;    
  8.     
  9.  private Function handle;   
  10.     
  11.  public void setHandler(Function func)   
  12.  {   
  13.   this.handle = func;   
  14.  }   
  15.     
  16.  public Function getHandler()   
  17.  {   
  18.   return this.handle;   
  19.  }   
  20.   
  21.     
  22.  public JSFunction(String s)   
  23.  {   
  24.   this.name = s;   
  25.  }    
  26.     
  27.  public static void print(String s)   
  28.  {   
  29.   System.out.println(s);   
  30.  }   
  31.   
  32.  public String getName() {   
  33.   return name;   
  34.  }   
  35.  public void setName(String name) {   
  36.   this.name = name;   
  37.  }   
  38.   
  39. }   
  40.   

JSExploration.java:

java 代码

  1. package co.test;   
  2.   
  3. import java.io.FileReader;   
  4. import java.io.LineNumberReader;   
  5.   
  6. import org.mozilla.javascript.Context;   
  7. import org.mozilla.javascript.Function;   
  8. import org.mozilla.javascript.Scriptable;   
  9.   
  10. public class JSExploration   
  11. {   
  12.     private Context cx;   
  13.   
  14.     private Scriptable scope;   
  15.   
  16.     public JSExploration()   
  17.     {   
  18.         this.cx = Context.enter();   
  19.         this.scope = cx.initStandardObjects();   
  20.     }   
  21.   
  22.     public Object runJavaScript(String filename)   
  23.     {   
  24.         String jsContent = this.getJsContent(filename);   
  25.         Object result = cx.evaluateString(scope, jsContent, filename, 1null);   
  26.         return result;   
  27.     }   
  28.   
  29.     private String getJsContent(String filename)   
  30.     {   
  31.         LineNumberReader reader;   
  32.         try  
  33.         {   
  34.             reader = new LineNumberReader(new FileReader(filename));   
  35.             String s = null;   
  36.             StringBuffer sb = new StringBuffer();   
  37.             while ((s = reader.readLine()) != null)   
  38.             {   
  39.                 sb.append(s).append(“\n”);   
  40.             }   
  41.             return sb.toString();   
  42.         }   
  43.         catch (Exception e)   
  44.         {   
  45.             // TODO Auto-generated catch block   
  46.             e.printStackTrace();   
  47.             return null;   
  48.         }   
  49.     }   
  50.   
  51.   
  52.     public Scriptable getScope()   
  53.     {   
  54.         return scope;   
  55.     }   
  56.   
  57.     public static void main(String[] args)   
  58.     {   
  59.         String filename = System.getProperty(“user.dir”) + “/jsmap.js”;   
  60.         JSExploration jsExploration = new JSExploration();   
  61.         Object result = jsExploration.runJavaScript(filename);   
  62.         Scriptable scope = jsExploration.getScope();   
  63.         Scriptable obj = (Scriptable) scope.get(“obj”, scope);   
  64.         System.out.println(“obj.a == ” + obj.get(“a”, obj));   
  65.         Scriptable b = (Scriptable) obj.get(“b”, obj);   
  66.         System.out.println(“b[0] == ” + b.get(0, b));   
  67.         Boolean flag = (Boolean) scope.get(“flag”, scope);   
  68.         System.out.println(flag);   
  69.   
  70.         Scriptable myobj = (Scriptable) scope.get(“obj”, scope);   
  71.         Boolean myflag = (Boolean) scope.get(“flag”, scope);   
  72.         System.out.println(myflag);   
  73.   
  74.         Scriptable jsFunction = (Scriptable) scope.get(“jsFunction”, scope);   
  75.         Function fc = (Function) jsFunction.get(“handler”, jsFunction);   
  76.         Object isPrime = fc.call(Context.getCurrentContext(), jsFunction, fc, new Object[] { “this is my test” });   
  77.     }   
  78. }   
  79.   

js脚本:jsmap.js

js 代码

  1. var swingNames = JavaImporter();   
  2.   
  3. swingNames.importPackage(Packages.java.lang);   
  4. swingNames.importPackage(Packages.co.test);   
  5.   
  6. obj = {a:1, b:[’x',’y']}   
  7. next = isPrime   
  8. flag = isPrime(5)   
  9. with (swingNames) {   
  10.  System.out.println(“in javascript”);   
  11.  JSFunction.print(“in JSFunction”);   
  12.   jsFunction = new JSFunction(“lichunlei”);   
  13.  var name = jsFunction.getName();   
  14.  System.out.println(“get name from java source: ” + name);   
  15.  jsFunction.setHandler(log);    
  16. }    
  17.   
  18. java.lang.System.out.println(“not use swingNames”);   
  19. function isPrime (num)   
  20. {   
  21.  java.lang.System.out.println(“in isPrime(num)”);   
  22.     if (num <= 1) {   
  23.         java.lang.System.out.println(“Please enter a positive integer >= 2.”)   
  24.         return false  
  25.     }   
  26.        
  27.     var prime = true  
  28.     var sqrRoot = Math.round(Math.sqrt(num))   
  29.        
  30.     for (var n = 2; prime & n <= sqrRoot; ++n) {   
  31.         prime = (num % n != 0)   
  32.     }   
  33.        
  34.     return prime   
  35. }   
  36.   
  37. function log(msg)   
  38. {   
  39.  java.lang.System.out.println(“in function log: ” + msg);   
  40. }   
  41.   
  42.     

Posted by micas on Jul 8th 2007 | Filed in J2EE, JavaBasic, Enabling-tech | Comments (0)

socket, nio socket,及xml传递object 方法 【转】

关键字:   nio socket xml base64    

最近在弄关于socket的东东,现总结如下:1:如何通过socket代理来访问服务端:

  1. String proxyHost = “192.168.204.212″;   
  2. String proxyPort = “1080″;   
  3.   
  4. //通知Java要通过代理进行连接。   
  5. System.getProperties().put(“socksProxySet”,“true”);   
  6. //指定代理所在的机器   
  7. System.getProperties().put(“socksProxyHost”,proxyHost);   
  8. //指定代理监听的端口。   
  9. System.getProperties().put(“socksProxyPort”,proxyPort);    
  10.   
  11. String host = “134.01.69.80″;   
  12. int port = 12086;   
  13. System.out.println(“connetioning:” + host + “:” + port);   
  14. server = new Socket(host, port);  

二:老socket传递Object对象:

要传递的对象:

  1. public class Employee implements Serializable {    
  2.   
  3.        private int employeeNumber;    
  4.        private String employeeName;    
  5.   
  6.        Employee(int num, String name) {    
  7.           employeeNumber = num;    
  8.           employeeName= name;    
  9.        }    
  10.   
  11.         public int getEmployeeNumber() {    
  12.           return employeeNumber ;    
  13.        }    
  14.   
  15.        public void setEmployeeNumber(int num) {    
  16.           employeeNumber = num;    
  17.        }    
  18.   
  19.        public String getEmployeeName() {    
  20.           return employeeName ;    
  21.        }    
  22.   
  23.        public void setEmployeeName(String name) {    
  24.           employeeName = name;    
  25.        }    
  26.     }   

client:

  1. public class Client {   
  2.     public static void main(String[] arg) {   
  3.         try {   
  4.             Employee joe = new Employee(150“Joe”);   
  5.             System.out.println(“employeeNumber= ” + joe.getEmployeeNumber());   
  6.             System.out.println(“employeeName= ” + joe.getEmployeeName());   
  7.             Socket socketConnection = new Socket(“127.0.0.1″11111);   
  8.             ObjectOutputStream clientOutputStream = new ObjectOutputStream(   
  9.                     socketConnection.getOutputStream());   
  10.             ObjectInputStream clientInputStream = new ObjectInputStream(   
  11.                     socketConnection.getInputStream());   
  12.             clientOutputStream.writeObject(joe);   
  13.             joe = (Employee) clientInputStream.readObject();   
  14.             System.out.println(“employeeNumber= ” + joe.getEmployeeNumber());   
  15.             System.out.println(“employeeName= ” + joe.getEmployeeName());   
  16.             clientOutputStream.close();   
  17.             clientInputStream.close();   
  18.         } catch (Exception e) {   
  19.             System.out.println(e);   
  20.         }   
  21.     }   
  22. }  

server端:

java 代码

  1. public class Server {   
  2.     public static void main(String[] arg) {   
  3.         Employee employee = null;   
  4.         try {   
  5.             ServerSocket socketConnection = new ServerSocket(11111);   
  6.             System.out.println(“Server Waiting”);   
  7.             Socket pipe = socketConnection.accept();   
  8.             ObjectInputStream serverInputStream = new ObjectInputStream(pipe   
  9.                     .getInputStream());   
  10.             ObjectOutputStream serverOutputStream = new ObjectOutputStream(pipe   
  11.                     .getOutputStream());   
  12.             employee = (Employee) serverInputStream.readObject();   
  13.             employee.setEmployeeNumber(256);   
  14.             employee.setEmployeeName(“li”);   
  15.             serverOutputStream.writeObject(employee);   
  16.             serverInputStream.close();   
  17.             serverOutputStream.close();   
  18.         } catch (Exception e) {   
  19.             System.out.println(e);   
  20.         }   
  21.     }   
  22. }  

三:nio socket传递Object:

client:

  1. public class Client {   
  2.     private String hostname;   
  3.        
  4.     private int port;   
  5.        
  6.     public Client(String hostname, int port)   
  7.     {   
  8.         this.hostname = hostname;   
  9.         this.port = port;   
  10.     }   
  11.   
  12.     public static void main(String[] args) {   
  13.         String hostname = “192.168.0.81″;   
  14.         int port = 8234;   
  15.         Student stu = new Student();   
  16.         stu.setId(849);   
  17.         stu.setName(“Squall”);   
  18.         Client client = new Client(hostname, port);   
  19.         try {   
  20.             client.write(stu);   
  21.         } catch (IOException e) {   
  22.             // TODO Auto-generated catch block   
  23.             e.printStackTrace();   
  24.         }   
  25.     }   
  26.   
  27.     public void write(Object obj) throws IOException {   
  28.         SocketChannel channel = null;   
  29.         try {   
  30.             channel = SocketChannel.open(new InetSocketAddress(hostname, port));   
  31.             ByteBuffer buf = Client.getByteBuffer(obj);   
  32.             channel.write(Client.getByteBuffer(obj));   
  33.             channel.write(Client.getByteBuffer(obj));   
  34.         } catch (Exception e) {   
  35.             e.printStackTrace();   
  36.         } finally {   
  37.             channel.close();   
  38.         }   
  39.     }   
  40.        
  41.     public static ByteBuffer getByteBuffer(Object obj) throws IOException   
  42.     {   
  43.         ByteArrayOutputStream bOut = new ByteArrayOutputStream();   
  44.         ObjectOutputStream out = new ObjectOutputStream(bOut);   
  45.         out.writeObject(obj);   
  46.         out.flush();   
  47.         byte[] arr = bOut.toByteArray();   
  48.         System.out.println(“Object in ” + arr.length + “ bytes”);   
  49.         ByteBuffer bb = ByteBuffer.wrap(arr);   
  50.         out.close();   
  51.            
  52.         return bb;   
  53.     }   
  54. }  

server端:

java 代码

  1. public class Server {   
  2.   
  3.     public static void main(String[] args) {   
  4.         System.out.println(“in server!”);   
  5.         ServerThread server = new ServerThread();   
  6.         new Thread(server).start();   
  7.     }   
  8.   
  9.     static class ServerThread implements Runnable {   
  10.   
  11.         public void run() {   
  12.             try {   
  13.                 ServerSocketChannel sc = ServerSocketChannel.open();   
  14.   
  15.                 ServerSocket s = sc.socket();   
  16.                 s.bind(new InetSocketAddress(8234));   
  17.                 while (true) {   
  18.                     Socket incoming = s.accept();   
  19.                     Runnable r = new GetObjThread(incoming);   
  20.                     Thread t = new Thread(r);   
  21.                     t.start();   
  22.                 }   
  23.             } catch (Exception e) {   
  24.                 e.printStackTrace();   
  25.             }   
  26.         }   
  27.     }   
  28.   
  29.     static class GetObjThread implements Runnable {   
  30.         public GetObjThread(Socket s) {   
  31.             incoming = s;   
  32.         }   
  33.   
  34.         public void run() {   
  35.             try {   
  36.                 SocketChannel sc = incoming.getChannel();   
  37.                 ByteBuffer bbIn = ByteBuffer.allocate(1024);   
  38.                 sc.read(bbIn);   
  39.                    
  40.                 sc.close();   
  41.                 bbIn.flip();   
  42.                 ByteArrayInputStream bIn = new ByteArrayInputStream(bbIn   
  43.                         .array());   
  44.                 ObjectInputStream in = new ObjectInputStream(bIn);   
  45.                 Student nStu = (Student) in.readObject();   
  46.                 System.out.println(“student id is ” + nStu.getId() + “\n”  
  47.                         + “student name is ” + nStu.getName());   
  48.             } catch (IOException e) {   
  49.                 e.printStackTrace();   
  50.             } catch (ClassNotFoundException e) {   
  51.                 e.printStackTrace();   
  52.             }   
  53.         }   
  54.   
  55.         private Socket incoming;   
  56.     }   
  57. }  

四:备份一个有用的util class:对象序列化,反序列化(序列化对象转byte[],ByteBuffer, byte[]转object: 

java 代码

  1. public class ByteUtil {   
  2.     public static byte[] getBytes(Object obj) throws IOException   
  3.     {   
  4.         ByteArrayOutputStream bout = new ByteArrayOutputStream();   
  5.         ObjectOutputStream out = new ObjectOutputStream(bout);   
  6.         out.writeObject(obj);   
  7.         out.flush();   
  8.         byte[] bytes = bout.toByteArray();   
  9.         bout.close();   
  10.         out.close();   
  11.            
  12.         return bytes;   
  13.     }   
  14.        
  15.     public static Object getObject(byte[] bytes) throws IOException, ClassNotFoundException   
  16.     {   
  17.            ByteArrayInputStream bi = new ByteArrayInputStream(bytes);   
  18.            ObjectInputStream oi = new ObjectInputStream(bi);   
  19.            Object obj = oi.readObject();   
  20.            bi.close();   
  21.            oi.close();   
  22.         return obj;   
  23.     }   
  24.        
  25.     public static ByteBuffer getByteBuffer(Object obj) throws IOException   
  26.     {   
  27.         byte[] bytes = ByteUtil.getBytes(obj);   
  28.         ByteBuffer buff = ByteBuffer.wrap(bytes);   
  29.            
  30.         return buff;   
  31.     }   
  32. }  

五:如何通过xml传递Object对象:

可以先把object转成一个byte[]数组,然后用base64编码成一个base64格式的String,放入xml的CDATA中,就可以传了。

接收方,收到该xml后,把CDATA中的String用base64解码为byte[],进而根据四中的方法,还原为object:

java 代码

  1. public class Base64 {   
  2.   
  3.     public static String getEncodedText(byte[] bytes) {   
  4.   
  5.         try {   
  6.             BASE64Encoder encoder = new BASE64Encoder();   
  7.             String text = encoder.encode(bytes);   
  8.             return text;           
  9.         } catch (Exception e) {   
  10.             e.printStackTrace();   
  11.             return null;   
  12.         }          
  13.   
  14.     }   
  15.        
  16.     public static byte[] decode(String src)    
  17.     {   
  18.         BASE64Decoder decoder = new BASE64Decoder();   
  19.         try {   
  20.             return decoder.decodeBuffer(src);   
  21.         } catch (IOException e) {   
  22.             // TODO Auto-generated catch block   
  23.             e.printStackTrace();   
  24.             return null;   
  25.         }   
  26.     }   
  27.        
  28.     public static void main(String[] args) {   
  29.         String s = “ly89″;   
  30.         byte[] bytes = s.getBytes();   
  31.         String  encode = Base64.getEncodedText(bytes);   
  32.         System.out.println(“the encode string is: ” + encode);   
  33.   
  34.         byte[] dbytes = Base64.decode(encode);   
  35.         for (int i = 0; i < bytes.length; i++) {   
  36.             System.out.println(dbytes[i]);             
  37.         }   
  38.     }   
  39. }  

Posted by micas on Jul 8th 2007 | Filed in Distributed System, Enabling-tech | Comments (0)

nio socket 及其开源框架MINA学习总结(二) [转]

关键字:   nio socket MINA    

3:Socket网络框架 MINA
MINA是一个网络应用框架,在不牺牲性能和可扩展性的前提下用于解决如下问题:
1:快速开发自己的英勇。
2:高可维护性,高可复用性:网络I/O编码,消息的编/解码,业务逻辑互相分离。
3:相对容易的进行单元测试。

3.1 IoFilters:
IoFilter为MINA的功能扩展提供了接口。它拦截所有的IO事件进行事件的预处理和后处理(AOP)。我们可以把它想象成
Servlet的filters。
IoFilter能够实现以下几种目的:
事件日志
性能检测
数据转换(e.g. SSL support),codec
防火墙…等等

3.2 codec: ProtocolCodecFactory
MINA提供了方便的Protocol支持。如上说讲,codec在IoFilters中设置。
通过它的Encoder和Decoder,可以方便的扩展并支持各种基于Socket的网络协议,比如HTTP服务器、FTP服务器、Telnet服务器等等。

要实现自己的编码/解码器(codec)只需要实现interface: ProtocolCodecFactory即可.
在MINA 1.0版本,MINA已经实现了几个常用的(codec factory):

DemuxingProtocolCodecFactory,
NettyCodecFactory,
ObjectSerializationCodecFactory,
TextLineCodecFactory
 
其中:
TextLineCodecFactory:
 A ProtocolCodecFactory that performs encoding and decoding between a text line data and a Java
 string object. This codec is useful especially when you work with a text-based protocols such as SMTP and IMAP.

ObjectSerializationCodecFactory:
A ProtocolCodecFactory that serializes and deserializes Java objects. This codec is very useful when
you have to prototype your application rapidly without any specific codec.

DemuxingProtocolCodecFactory:
A composite ProtocolCodecFactory that consists of multiple MessageEncoders and MessageDecoders. ProtocolEncoder
and ProtocolDecoder this factory returns demultiplex incoming messages and buffers to appropriate MessageEncoders
and MessageDecoders.

NettyCodecFactory:
A MINA ProtocolCodecFactory that provides encoder and decoder for Netty2 Messages and MessageRecognizers.

3.3 business logic: IoHandler

MINA中,所有的业务逻辑都有实现了IoHandler的class完成
interfaceHandles:
 all protocol events fired by MINA. There are 6 event handler methods, and they are all invoked by MINA automatically.
 当事件发生时,将触发IoHandler中的方法:
 sessionCreated(),
sessionOpened(),
sessionClosed(),
sessionIdle(),
exceptionCaught(),
messageReceived(),
messageSent()


MINA 1.O中,IoHandler的实现类:
ChainedIoHandler,
DemuxingIoHandler,
IoHandlerAdapter,
SingleSessionIoHandlerDelegate,
StreamIoHandler

具体细节可参考javadoc。

3.4   MINA的高级主题:线程模式
MINA通过它灵活的filter机制来提供多种线程模型。
没有线程池过滤器被使用时MINA运行在一个单线程模式。
如果添加了一个IoThreadPoolFilter到IoAcceptor,将得到一个leader-follower模式的线程池。
如果再添加一个ProtocolThreadPoolFilter,server将有两个线程池;
一个(IoThreadPoolFilter)被用于对message对象进行转换,另外一个(ProtocolThreadPoolFilter)被用于处理业务逻辑。
SimpleServiceRegistry加上IoThreadPoolFilter和ProtocolThreadPoolFilter的缺省实现即可适用于需
要高伸缩性的应用。如果想使用自己的线程模型,请参考SimpleServiceRegistry的源代码,并且自己

初始化Acceptor。

java 代码

  1. IoThreadPoolFilter threadPool = new IoThreadPoolFilter();threadPool.start();   
  2. IoAcceptor acceptor = new SocketAcceptor();   
  3. acceptor.getFilterChain().addLast( “threadPool”, threadPool);   
  4. ProtocolThreadPoolFilter threadPool2 = new ProtocolThreadPoolFilter();   
  5. threadPool2.start();   
  6. ProtocolAcceptor acceptor2 = new IoProtocolAcceptor( acceptor );   
  7. acceptor2.getFilterChain().addLast( “threadPool”, threadPool2 );   
  8. …   
  9. threadPool2.stop();   
  10. threadPool.stop();  

3.5 采用MINA进行socket开发,一般步骤如下:
1:

  1. IoAcceptor acceptor = new SocketAcceptor(); //建立client接收器   
  2. or client:   
  3. SocketConnector connector = new SocketConnector();  //建立一个连接器  

2:server的属性配置:

java 代码

  1. SocketAcceptorConfig cfg = new SocketAcceptorConfig();   
  2. cfg.setReuseAddress(true);   
  3. cfg.getFilterChain().addLast(   
  4.             “codec”,   
  5.             new ProtocolCodecFilter( new ObjectSerializationCodecFactory() ) ); //对象序列化 codec factory   
  6. cfg.getFilterChain().addLast( “logger”new LoggingFilter() );  

3:绑定address和business logic
server:

java 代码

  1. acceptor.bind(   
  2.         new InetSocketAddress( SERVER_PORT ),   
  3.         new ServerSessionHandler( ), cfg ); // 绑定address和handler   
  4.   
  5.   
  6. connector.connect(new InetSocketAddress( HOSTNAME, PORT ),   
  7.                 new ClientSessionHandler(msg), cfg );   

下面的这个简单的example演示client和server传递object的过程:
Message.java

java 代码

  1. public class Message implements Serializable {   
  2.   
  3.     private int type;   
  4.     private int status;   
  5.     private String msgBody;   
  6.        
  7.     public Message(int type, int status, String msgBody)   
  8.     {   
  9.         this.type = type;   
  10.         this.status = status;   
  11.         this.msgBody = msgBody;   
  12.     }   
  13.   
  14.     public String getMsgBody() {   
  15.         return msgBody;   
  16.     }   
  17.   
  18.     public void setMsgBody(String msgBody) {   
  19.         this.msgBody = msgBody;   
  20.     }   
  21.   
  22.     public int getStatus() {   
  23.         return status;   
  24.     }   
  25.   
  26.     public void setStatus(int status) {   
  27.         this.status = status;   
  28.     }   
  29.   
  30.     public int getType() {   
  31.         return type;   
  32.     }   
  33.   
  34.     public void setType(int type) {   
  35.         this.type = type;   
  36.     }   
  37. }   
  38.   

Client.java

java 代码

  1. public class Client   
  2. {   
  3.     private static final String HOSTNAME = “localhost”;   
  4.     private static final int PORT = 8080;   
  5.     private static final int CONNECT_TIMEOUT = 30// seconds   
  6.   
  7.   
  8.     public static void main( String[] args ) throws Throwable   
  9.     {   
  10.         SocketConnector connector = new SocketConnector();           
  11.         // Configure the service.   
  12.         SocketConnectorConfig cfg = new SocketConnectorConfig();   
  13.         cfg.setConnectTimeout( CONNECT_TIMEOUT );   
  14.           cfg.getFilterChain().addLast(   
  15.                     “codec”,   
  16.                     new ProtocolCodecFilter( new ObjectSerializationCodecFactory() ) );   
  17.   
  18.         cfg.getFilterChain().addLast( “logger”new LoggingFilter() );   
  19.            
  20.         IoSession session;   
  21.         Message msg = new Message(0,1,“hello”);   
  22.         connector.connect(new InetSocketAddress( HOSTNAME, PORT ),   
  23.                         new ClientSessionHandler(msg), cfg );   
  24.   
  25.     }   
  26. }   

ClientSessionHandler.java

java 代码

  1. public class ClientSessionHandler extends IoHandlerAdapter   
  2. {   
  3.     private Object msg;   
  4.        
  5.     public ClientSessionHandler(Object msg)   
  6.     {   
  7.         this.msg = msg;   
  8.     }   
  9.   
  10.   
  11.     public void sessionOpened( IoSession session )   
  12.     {   
  13.         session.write(this.msg);   
  14.     }   
  15.   
  16.     public void messageReceived( IoSession session, Object message )   
  17.     {   
  18.         System.out.println(“in messageReceived!”);   
  19.         Message rm = (Message ) message;           
  20.         SessionLog.debug(session, rm.getMsgBody());   
  21.         System.out.println(“message is: ” + rm.getMsgBody());   
  22.         session.write(rm);   
  23.     }   
  24.   
  25.     public void exceptionCaught( IoSession session, Throwable cause )   
  26.     {   
  27.         session.close();   
  28.     }   
  29. }   
  30.   

Server.java

java 代码

  1. public class Server   
  2. {   
  3.     private static final int SERVER_PORT = 8080;   
  4.   
  5.     public static void main( String[] args ) throws Throwable   
  6.     {   
  7.         IoAcceptor acceptor = new SocketAcceptor();   
  8.            
  9.         // Prepare the service configuration.   
  10.         SocketAcceptorConfig cfg = new SocketAcceptorConfig();   
  11.         cfg.setReuseAddress( true );   
  12.   
  13.         cfg.getFilterChain().addLast(   
  14.                     “codec”,   
  15.                     new ProtocolCodecFilter( new ObjectSerializationCodecFactory() ) );   
  16.         cfg.getFilterChain().addLast( “logger”new LoggingFilter() );   
  17.   
  18.         acceptor.bind(   
  19.                 new InetSocketAddress( SERVER_PORT ),   
  20.                 new ServerSessionHandler( ), cfg );   
  21.   
  22.         System.out.println( “The server Listening on port ” + SERVER_PORT );   
  23.     }   
  24. }  

ServerSessionHandler.java

java 代码

  1. public class ServerSessionHandler extends IoHandlerAdapter   
  2. {   
  3.     public void sessionOpened( IoSession session )   
  4.     {   
  5.         // set idle time to 60 seconds   
  6.         session.setIdleTime( IdleStatus.BOTH_IDLE, 60 );   
  7.         session.setAttribute(“times”,new Integer(0));   
  8.     }   
  9.   
  10.     public void messageReceived( IoSession session, Object message )   
  11.     {   
  12.         System.out.println(“in messageReceived”);   
  13.         int times = ((Integer)(session.getAttribute(“times”))).intValue();   
  14.         System.out.println(“tiems = ” + times);   
  15.         // communicate 30 times,then close the session.   
  16.         if (times < 30)   
  17.         {   
  18.             times++;   
  19.             session.setAttribute(“times”new Integer(times));              
  20.          Message msg;   
  21.          msg = (Message) message;   
  22.          msg.setMsgBody(“in server side: ” + msg.getMsgBody());    
  23.          System.out.println(“begin send msg: ” + msg.getMsgBody());   
  24.          session.write(msg);   
  25.         }   
  26.         else  
  27.         {   
  28.             session.close();   
  29.         }   
  30.     }   
  31.   
  32.     public void sessionIdle( IoSession session, IdleStatus status )   
  33.     {   
  34.         SessionLog.info( session, “Disconnecting the idle.” );   
  35.         // disconnect an idle client   
  36.         session.close();   
  37.     }   
  38.   
  39.     public void exceptionCaught( IoSession session, Throwable cause )   
  40.     {   
  41.         // close the connection on exceptional situation   
  42.         session.close();   
  43.     }   
  44. }   
  45.   

MINA自己附带的Demo已经很好的说明了它的运用。
值得一提的是它的SumUp:客户端发送几个数字,服务端求和后并返回结果。这个简单的程序演示了如何自己实现CODEC。

补充提示:
下载并运行MINA的demo程序还颇非周折:
运行MINA demo appli擦tion:
1:在JDK5
产生错误:
Exception in thread “main” java.lang.NoClassDefFoundError: edu/emory/mathcs/backport/java/util/concurrent/Executor
 at org.apache.mina.example.reverser.Main.main(Main.java:44)
 
察看mina的QA email:
 http://www.mail-archive.com/mina-dev@directory.apache.org/msg02252.html

原来需要下载:backport-util-concurrent.jar并加入classpath
http://dcl.mathcs.emory.edu/util/backport-util-concurrent

继续运行还是报错:
Exception in thread “main” java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory

原来MINA采用了slf4j项目作为log,继续下载
slf4j-simple.jar等,并加入classpath:
http://www.slf4j.org/download.html

附件是mina demo的eclipse工程。导入就可运行,所有的相关jar包在bin目录下
http://lcllcl987.javaeye.com/blog/70708

Posted by micas on Jul 8th 2007 | Filed in Distributed System, Enabling-tech | Comments (0)

nio socket 及其开源框架MINA学习总结(一) [转]

关键字:   nio socket MINA    

最近花了点时间研究了一下nio,及其开源框架MINA,现把心得总结如下:1:传统socket:阻塞式通信

每建立一个Socket连接时,同时创建一个新线程对该Socket进行单独通信(采用阻塞的方式通信)。这种方式具有很高的响应速度,并且控制起来也很简单,在连接数较少的时候非常有效,但是如果对每一个连接都产生一个线程的无疑是对系统资源的一种浪费,如果连接数较多将会出现资源不足的情况。

example:
server code:

java 代码

  1. public class MultiUserServer extends Thread {   
  2.     private Socket client;   
  3.        
  4.     public MultiUserServer(Socket c) {   
  5.         this.client = c;   
  6.     }   
  7.   
  8.     public void run() {   
  9.         try {   
  10.             BufferedReader in = new BufferedReader(new InputStreamReader(client   
  11.                     .getInputStream()));   
  12.             PrintWriter out = new PrintWriter(client.getOutputStream());   
  13.             //  Mutil User but can’t parallel   
  14.             while (true) {   
  15.                 String str = in.readLine();   
  16.                 System.out.println(str);   
  17.                 SocketLog.debug(“receive message: ” + str);   
  18.                 out.println(“has receive….”);   
  19.                 out.flush();   
  20.                 if (str.equals(“end”))   
  21.                     break;   
  22.             }   
  23.             client.close();   
  24.         } catch (IOException ex) {   
  25.         }    
  26.     }   
  27.   
  28.     public static void main(String[] args) throws IOException {   
  29.         int port = 5678;   
  30.         if (args.length > 0)   
  31.             port = Integer.parseInt(args[0]);   
  32.         ServerSocket server = new ServerSocket(port);   
  33.         SocketLog.debug(“the server socket application is created!”);   
  34.         while (true) {   
  35.             //  transfer location change Single User or Multi User   
  36.             MultiUserServer mu = new MultiUserServer(server.accept());   
  37.             mu.start();   
  38.         }   
  39.     }   
  40. }  

client code:

java 代码

  1. public class Client {   
  2.   
  3.     static Socket server;   
  4.   
  5.     public static void main(String[] args) throws Exception {   
  6.            
  7.         //set socket proxy.   
  8.         String proxyHost = “192.168.254.212″;   
  9.         String proxyPort = “1080″;   
  10.         System.getProperties().put(“socksProxySet”,“true”);   
  11.         System.getProperties().put(“socksProxyHost”,proxyHost);   
  12.         System.getProperties().put(“socksProxyPort”,proxyPort);    
  13.            
  14.         String host = “132.201.69.80″;   
  15.         int port = 13086;   
  16.         if (args.length > 1)   
  17.         {   
  18.             host = args[0];   
  19.             port = Integer.parseInt(args[1]);   
  20.         }   
  21.         System.out.println(“connetioning:” + host + “:” + port);   
  22.         server = new Socket(host, port);   
  23.         BufferedReader in = new BufferedReader(new InputStreamReader(server   
  24.                 .getInputStream()));   
  25.         PrintWriter out = new PrintWriter(server.getOutputStream());   
  26.         BufferedReader wt = new BufferedReader(new InputStreamReader(System.in));   
  27.         while (true) {   
  28.             String str = wt.readLine();   
  29.             out.println(str);   
  30.             out.flush();   
  31.             if (str.equals(“end”)) {   
  32.                 break;   
  33.             }   
  34.             System.out.println(in.readLine());   
  35.         }   
  36.         server.close();   
  37.     }   
  38. }  

 2.nio:非阻塞通讯模式

2.1NIO 设计背后的基石:反应器模式,用于事件多路分离和分派的体系结构模式。
反应器模式的核心功能如下:
将事件多路分用
将事件分派到各自相应的事件处理程序

NIO 的非阻塞 I/O 机制是围绕 选择器和 通道构建的。Channel 类表示服务器和客户机之间的一种通信机制。Selector 类是 Channel 的多路复用器。 Selector 类将传入客户机请求多路分用并将它们分派到各自的请求处理程序。
通道(Channel 类):表示服务器和客户机之间的一种通信机制。
选择器(Selector类):是 Channel 的多路复用器。

Selector 类将传入的客户机请求多路分用并将它们分派到各自的请求处理程序。简单的来说:NIO是一个基于事件的IO架构,最基本的思想就是:有事件我通知你,你再去做你的事情.而且NIO的主线程只有一个,不像传统的模型,需要多个线程以应对客户端请求,也减轻了JVM的工作量。
当Channel注册至Selector以后,经典的调用方法如下:
       nio中取得事件通知,就是在selector的select事件中完成的。在selector事件时有一个线程向操作系统询问,selector中注册的Channel&&SelectionKey的键值对的各种事件是否有发生,如果有则添加到selector的selectedKeys属性Set中去,并返回本次有多少个感兴趣的事情发生。如果发现这个值>0,表示有事件发生,马上迭代selectedKeys中的SelectionKey,
根据Key中的表示的事件,来做相应的处理。实际上,这段说明表明了异步socket的核心,即异步socket不过是将多个socket的调度(或者还有他们的线程调度)全部交给操作系统自己去完成,异步的核心Selector,不过是将这些调度收集、分发而已。

java 代码

  1. while (somecondition) {   
  2.     int n = selector.select(TIMEOUT);   
  3.     if (n == 0)   
  4.         continue;   
  5.     for (Iterator iter = selector.selectedKeys().iterator(); iter   
  6.             .hasNext();) {   
  7.         if (key.isAcceptable())   
  8.             doAcceptable(key);   
  9.         if (key.isConnectable())   
  10.             doConnectable(key);   
  11.         if (key.isValid() && key.isReadable())   
  12.             doReadable(key);   
  13.         if (key.isValid() && key.isWritable())   
  14.             doWritable(key);   
  15.         iter.remove();   
  16.     }   
  17. }  

2.2 nio example:
server code:

java 代码

  1. public class NonBlockingServer   
  2. {   
  3.     public Selector sel = null;   
  4.     public ServerSocketChannel server = null;   
  5.     public SocketChannel socket = null;   
  6.     public int port = 4900;   
  7.     String result = null;   
  8.   
  9.   
  10.     public NonBlockingServer()   
  11.     {   
  12.         System.out.println(“Inside default ctor”);   
  13.     }   
  14.        
  15.     public NonBlockingServer(int port)   
  16.     {   
  17.         System.out.println(“Inside the other ctor”);   
  18.         this.port = port;   
  19.     }   
  20.   
  21.     public void initializeOperations() throws IOException,UnknownHostException   
  22.     {   
  23.         System.out.println(“Inside initialization”);   
  24.         sel = Selector.open();   
  25.         server = ServerSocketChannel.open();   
  26.         server.configureBlocking(false);   
  27.         InetAddress ia = InetAddress.getLocalHost();   
  28.         InetSocketAddress isa = new InetSocketAddress(ia,port);   
  29.         server.socket().bind(isa);   
  30.     }   
  31.        
  32.     public void startServer() throws IOException   
  33.     {   
  34.         System.out.println(“Inside startserver”);   
  35.         initializeOperations();   
  36.         System.out.println(“Abt to block on select()”);   
  37.         SelectionKey acceptKey = server.register(sel, SelectionKey.OP_ACCEPT );    
  38.        
  39.         while (acceptKey.selector().select() > 0 )   
  40.         {      
  41.            
  42.             Set readyKeys = sel.selectedKeys();   
  43.             Iterator it = readyKeys.iterator();   
  44.   
  45.             while (it.hasNext()) {   
  46.                 SelectionKey key =