The NoteBook of EricKong

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks

#

EGit released for Supported Version of Eclipse
3.1.0.201310021548-rN/AEclipse 3.8.2/4.2.2 + (Juno)
3.0.3.201309161630-r4.3.1 (Kepler SR1)Eclipse 3.8.2/4.2.2 + (Juno)
3.0.1.201307141637-r4.3.0 (Kepler)Eclipse 3.8.2/4.2.2 + (Juno)
2.3.1.201302201838-r3.8.2/4.2.2 (Juno SR2)Eclipse 3.7.2+ (Indigo) (except EGit Import Support feature, which is optional)
2.2.0.201212191850-r3.8.1/4.2.1 (Juno SR1)Eclipse 3.7.2+ (Indigo) (except EGit Import Support feature, which is optional)
2.1.0.201209190230-r3.8.1/4.2.1 (Juno SR1)Eclipse 3.5.2+ (Galileo) (except EGit Import Support feature, which is optional)
2.0.0.201206130900-r3.8/4.2 (Juno)Eclipse 3.5.2+ (Galileo) (except EGit Import Support feature, which is optional)
1.3.0.201202151440-r3.7.2 (Indigo SR2)Eclipse 3.5.2+ (Galileo)
1.2.0.201112221803-r3.7.2 (Indigo SR2)Eclipse 3.5.2+ (Galileo)
1.1.0.201109151100-r3.7.1 (Indigo SR1)Eclipse 3.5.2+ (Galileo)
1.0.0.201106090707-r3.7.0 (Indigo)Eclipse 3.5.2+ (Galileo)

 

EGIT下载地址:

 

Release Version p2 repository URL browse p2 repository
3.1.0.201310021548-r (latest release)http://download.eclipse.org/egit/updates-3.1updates-3.1
3.0.3.201309161630-rhttp://download.eclipse.org/egit/updates-3.0.3updates-3.0.3
3.0.1.201307141637-rhttp://download.eclipse.org/egit/updates-3.0.1updates-3.0.1
3.0.0.201306101825-rhttp://download.eclipse.org/egit/updates-3.0updates-3.0
2.3.1.201302201838-rhttp://download.eclipse.org/egit/updates-2.3updates-2.3
2.2.0.201212191850-rhttp://download.eclipse.org/egit/updates-2.2updates-2.2
2.1.0.201209190230-rhttp://download.eclipse.org/egit/updates-2.1updates-2.1
2.0.0.201206130900-rhttp://download.eclipse.org/egit/updates-2.0updates-2.0
1.3.0.201202151440-rhttp://download.eclipse.org/egit/updates-1.3updates-1.3
1.2.0.201112221803-rhttp://download.eclipse.org/egit/updates-1.2updates-1.2
1.1.0.201109151100-rhttp://download.eclipse.org/egit/updates-1.1updates-1.1
1.0.0.201106090707-rhttp://download.eclipse.org/egit/updates-1.0updates-1.0
0.12.1 (Incubation)http://download.eclipse.org/egit/updates-0.12updates-0.12
0.11.3 (Incubation)http://download.eclipse.org/egit/updates-0.11updates-0.11
0.10.1 (Incubation)http://download.eclipse.org/egit/updates-0.10updates-0.10
0.9.3 (Incubation)http://download.eclipse.org/egit/updates-0.9updates-0.9
0.8.4 (Incubation)http://download.eclipse.org/egit/updates-0.8updates-0.8

 

posted @ 2015-03-03 11:17 Eric_jiang 阅读(193) | 评论 (0)编辑 收藏

一、Eclipse上安装GIT插件EGit

 

      Eclipse的版本eclipse-java-helios-SR2-win32.zip(在Eclipse3.3版本找不到对应的 EGit插件,无法安装)

 

     

 

 

 

EGit插件地址:http://download.eclipse.org/egit/updates

 

OK,随后连续下一步默认安装就可以,安装后进行重启Eclipse

 

二、在Eclipse中配置EGit

 

准备工作:需要在https://github.com 上注册账号

 

Preferences > Team > Git > Configuration

 

 

这里的user.name 是你在https://github.com上注册用户名

 

 

user.email是你在github上绑定的邮箱。在这里配置user.name即可

 

 

三、新建项目,并将代码提交到本地的GIT仓库中

 

1、新建项目 git_demo,并新建HelloWorld.java类

 

 

2、将git_demo项目提交到本地仓库,如下图

 

 

 

 

 

 

到此步,就成功创建GIT仓库。但文件夹处于untracked状态(文件夹中的符号”?”表示),下面我们需要提交代码到本地仓库,如下图

 

 

 

 

 

 

 

OK,这样代码提交到了本地仓库

 

 

四:将本地代码提交到远程的GIT仓库中

 

准备工作:在https://github.com上创建仓库

 

 

 

 

 

 

点击“Create repository” ,ok,这样在github上的仓库就创建好了。

 

注意创建好远程仓库后,点击进去,此时可以看到一个HTTP地址,如红线框,这个是你http协议的远程仓库地址

 

 

准备工作做好了,那开始将代码提交到远程仓库吧

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

OK,这样提交远程GIT就完成了,可以在https://github.com核对一下代码是否已经提交

 

 

注意的问题

   如果是首次提交会第一步:先在本地建立一个一样的仓库,称本地仓库。

          第二步:在本地进行commit操作将把更新提交到本地仓库;

          第三步: 将服务器端的更新pull到本地仓库进行合并,最后将合并好的本地仓库push到服务器端,这样就进行了一次远程提交。

 

  如果非首次提交同样的道理

          第一步:将修改的代码commit操作更新到本地仓库;

         第二步:第三步: 将服务器端的更新pull到本地仓库进行合并,最后将合并好的本地仓库push到服务器端

@import url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
posted @ 2015-03-03 10:45 Eric_jiang 阅读(178) | 评论 (1)编辑 收藏

ImageView中XML属性src和background的区别:

background会根据ImageView组件给定的长宽进行拉伸,而src就存放的是原图的大小,不会进行拉伸。src是图片内容(前景),bg是背景,可以同时使用。

此外:scaleType只对src起作用;bg可设置透明度,比如在ImageButton中就可以用android:scaleType控制图片的缩放方式


如上所述,background设置的图片会跟View组件给定的长宽比例进行拉伸。举个例子, 36x36 px的图标放在 xhdpi 文件夹中,在854x480(FWVGA,对应hdpi)环境下,按照

xhdpi : hdpi : mdpi: ldip = 2 : 1.5 : 1 : 0.75

的比例计算,在FWVGA下,图标的实际大小应该是 27x27。

但是当我把它放到一个 layout_width = 96px, layout_height = 75px 的 LinearLayout,布局代码如下:

  1. <LinearLayout android:gravity="center" android:layout_width="96px" android:layout_height="75px"  >  
  2.     <ImageButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/toolbar_bg"/>      
  3. </LinearLayout>  

实际情况是,我们得到的ImageButton的大小是 33x27,很明显width被拉伸了,这是我们不想看到的情况。

解决方案一:

代码中动态显式设置ImageButton的layout_width和layout_width,如下 

  1. LinearLayout.LayoutParams layoutParam = new LinearLayout.LayoutParams(2727);  
  2. layout.addView(imageButton, layoutParam);  
不过,事实上我们并不希望在代码存在“硬编码”的情况。

解决方案二:

在你通过setBackgroundResource()或者在xml设置android:background属性时,将你的background以XML Bitmap的形式定义,如下:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <bitmap xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:id="@id/toolbar_bg_bmp"  
  4.     android:src="@drawable/toolbar_bg"  
  5.     android:tileMode="disabled" android:gravity="top" >  
  6. </bitmap>  
调用如下:

    imageButton.setBackgroundResource(R.drawable.toolbar_bg_bmp)

或者

    <ImageButton ...  android:background="@drawable/toolbar_bg_bmp" ... />

若背景图片有多种状态,还可参照toolbar_bg_selector.xml:

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <selector xmlns:android="http://schemas.android.com/apk/res/android" >  
  3.     <item android:state_pressed="true" >  
  4.         <bitmap android:src="@drawable/toolbar_bg_sel" android:tileMode="disabled" android:gravity="top" />  
  5.     </item>  
  6.     <item >  
  7.         <bitmap android:src="@drawable/toolbar_bg" android:tileMode="disabled" android:gravity="top" />  
  8.     </item>  
  9. </selector>  


如此,不管是通过代码方式setBackgroundResource()或XML android:background方式设置背景,均不会产生被拉伸的情况。

@import url(http://www.blogjava.net/CuteSoft_Client/CuteEditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);
posted @ 2015-03-01 00:31 Eric_jiang 阅读(316) | 评论 (0)编辑 收藏

在任何浏览器上方便地实现Ajax请求是每一个Ajax框架的初衷。Dojo在这方面无疑提供了非常丰富的支持。除了XMLHttpRequest之外,动态script、iframe、RPC也应有尽有,并且接口统一,使用方便,大多数情况下都只需要一句话就能达到目的,从而免除重复造轮子的麻烦。而且,Dojo一贯追求的概念完整性也在这里有所体现,换句话说,在使用Dojo的Ajax工具的过程中不会感到任何的不自然,相反更容易有触类旁通的感觉,因为API的模式是统一的,而且这里涉及到的某些概念(如Deferred对象)也贯穿在整个Dojo之中。

  Dojo的XHR函数

  Dojo的XMLHttpRequest函数就叫dojo.xhr,除了把自己取名美元符号之外,这好像是最直接的办法了。它定义在Dojo基本库里,所以不需要额外的require就能使用。它可以实现任何同域内的http请求。不过更常用的是dojo.xhrGet和dojo.xhrPost,它们只不过是对dojo.xhr函数的简单封装;当然根据REST风格,还有dojo.xhrPut和dojo.xhrDelete。

  这些函数的参数都很统一。除了dojo.xhr的第一个参数是http方法名之外,所有的dojo.xhr*系列函数都接受同一种散列式的参数,其中包含请求的细节,例如url、是否同步、要传给服务器的内容(可以是普通对象、表单、或者纯文本)、超时设定、返回结果的类型(非常丰富且可扩展)、以及请求成功和失败时的回调。所有dojo.xhr*函数(实际上是所有IO函数)返回值也都一样,都是一个Deferred对象,顾名思义,它能让一些事情延迟发生,从而让API用起来更灵活。

  下面的两个例子可能会带来一点直观感受:

dojo.xhrGet({
url:
"something.html",
load: function(response, ioArgs){
//用response干一些事
console.log("xhr get success:", response)
return response //必须返回response
},
error: function(response, ioArgs){
console.log(
"xhr get failed:", response)
return response //必须返回response
}
})
//Deferred对象允许用同步调用的写法写异步调用
var deferredResult = dojo.xhrPost({
url:
"something.html",
form: formNode,
//Dojo会自动将form转成object
timeout: 3000, //Dojo会保证超时设定的有效性
handleAs: "json" //得到的response将被认为是JSON,并自动转为object
})
//当响应结果可用时再调用回调函数
deferredResult.then(function(response){
console.log(
"xhr get success:", response)
return response //必须返回response
})

  首先解释一下timeout。除了IE8之外,目前大多数XMLHttpRequest对象都没有内置的timeout功能,因此必须用 setTimeout。当同时存在大量请求时,需要为每一个请求设置单独的定时器,这在某些浏览器(主要是IE)会造成严重的性能问题。dojo的做法是只用一个单独的setInterval,定时轮询(间隔50ms)所有还未结束的请求的状态,这样就高效地解决了一切远程请求(包括JSONP和 iframe)的超时问题。

  值得一提的还有handleAs参数,通过设置这个参数,可以自动识别服务器的响应内容格式并转换成对象或文本等方便使用的形式。根据文档,它接受如下值:text (默认), json, json-comment-optional, json-comment-filtered, javascript, xml。

  而且它还是可扩展的。其实handleAs只是告诉xhr函数去调用哪个格式转换插件,即dojo.contentHandlers对象里的一个方法。例如 dojo.contentHandlers.json就是处理JSON格式的插件。你可以方便地定制自己所需要的格式转换插件,当然,你也可修改现有插件的行为:

dojo.contentHandlers.json = (function(old){
return function(xhr){
var json
= old(xhr)
if(json.someSignalFormServer){
doSomthing(json)
delete json.someSignalFormServer
}
return json
}
})(dojo.contentHandlers.json)
//一个小技巧,利用传参得到原方法

  如果要了解每个参数的细节,可以参考Dojo的文档

  虚拟的参数类

  这里特别提一下Dojo在API设计上的两个特点。其一是虚拟的参数类概念:通过利用javascript对象可以灵活扩展的特点,强行规定一个散列参数属于某个类。例如dojo.xhr*系列函数所接受的参数就称为dojo.__XhrArgs。这个类并不存在于实际代码中(不要试图用 instanceof验证它),只停留在概念上,比抽象类还抽象,因此给它加上双下划线前缀(Dojo习惯为抽象类加单下划线前缀)。

  这样做看起来没什么意思,但实际上简化了API,因为它使API之间产生了联系,更容易记忆也就更易于使用。这一点在对这种类做继承时更明显。例如 dojo.__XhrArgs继承自dojo.__IoArgs,这是所有IO函数所必须支持的参数集合,同样继承自dojo.__IoArgs的还有 dojo.io.script.__ioArgs和dojo.io.iframe.__ioArgs,分别用于动态脚本请求和iframe请求。子类只向父类添加少量的属性,这样繁多的参数就具有了树形类结构。原本散列式参数是用精确的参数名代替了固定的参数顺序,在增加灵活性和可扩展性的同时,实际上增加了记忆量(毕竟参数名不能拼错),使得API都不像看起来那么好用,有了参数类的设计就缓解了这个问题。

  这种参数类的做法在Dojo里随处可见,读源码的话就会发现它们都是被正儿八经地以正常代码形式声明在一种特殊注释格式里的,像这样:

/*=====
dojo.declare("dojo.__XhrArgs", dojo.__IoArgs, {
constructor: function(){
//summary:
//...
//handleAs:
//...
//......
}
})
=====
*/

  这种格式可以被jsDoc工具自动提取成文档,在文档里这些虚拟出来的类就像真的类一样五脏俱全了。

  Deferred对象

  另一个API设计特点就是Deferred对象的广泛使用。Dojo里的Deferred是基于MochiKit实现稍加改进而成的,而后者则是受到 python的事件驱动网络工具包Twisted里同名概念的启发。概括来说的话,这个对象的作用就是将异步IO中回调函数的声明位置与调用位置分离,这样在一个异步IO最终完成的地方,开发人员可以简单地说货已经到了,想用的可以来拿了,而不用具体地指出到底该调用哪些回调函数。这样做的好处是让异步IO的写法和同步IO一样(对数据的处理总是在取数据函数的外面,而不是里面),从而简化异步编程。

  具体做法是,异步函数总是同步地返回一个代理对象(这就是Deferred对象),可以将它看做你想要的数据的代表,它提供一些方法以添加回调函数,当数据可用时,这些回调函数(可以由很多个)便会按照添加顺序依次执行。如果在取数据过程中出现错误,就会调用所提供的错误处理函数(也可以有很多个);如果想要取消这个异步请求,也可通过Deferred对象的cancel方法完成。

dojo.Deferred的核心方法如下:

then(callback, errback)
//添加回调函数
callback(result) //表示异步调用成功完成,触发回调函数
errback(error) //表示异步调用中产生错误,触发错误处理函数
cancel() //取消异步调用

  Dojo还提供了一个when方法,使同步的值和异步的Deferred对象在使用时写法一样。例如:

//某个工具函数的实现
var obj = {
getItem: function(){
if(this.item){
return this.item //这里同步地返回数据
}else{
return dojo.xhrGet({ //这里返回的是Deferred对象
url: "toGetItem.html",
load: dojo.hitch(
this, function(response){
this.item = response
return response
})
})
}
}
}
//用户代码
dojo.when(obj.getItem(), function(item){
//无论同步异步,使用工具函数getItem的方式都一样
})

  在函数闭包的帮助下,Deferred对象的创建和使用变得更为简单,你可以轻易写出一个创建Deferred对象的函数,以同步的写法做异步的事。例如写一个使用store获取数据的函数:

var store = new dojo.data.QueryReadStore({...})
function getData(start, count){
var d
= new dojo.Deferred() //初始化一个Deferred对象
store.fetch({
start: start,
count: count,
onComplete: function(items){
//直接取用上层闭包里的Deferred对象
d.callback(items)
}
})
return d //把它当做结果返回
}

  用dojo.io.script跨域

  dojo.xhr* 只是XmlHttpRequest对象的封装,由于同源策略限制,它不能发跨域请求,要跨域还是需要动态创建script标签。Dojo 没有像JQuery一样把所有东西都封装在一起(JQuery的ajax()方法可以跨域,当然用的是JSONP,所以它不敢把自己称为xhr),而是坚持一个API只干一件事情。毕竟在大部分应用中,同域请求比跨域请求多得多,如果一个应用不需要跨域,就没必要加载相关代码。因此与xhr不同,dojo 的跨域请求组件不在基本库,而在核心库,需要require一下才能使用:

dojo.require("dojo.io.script")

  这个包里面基本上只需要用到一个函数:dojo.io.script.get()。它也返回Deferred对象,并接受类型为 dojo.io.script.__ioArgs的散列参数。受益于虚拟参数类,我们不用从头开始学习这个参数,它继承了dojo.__IoArgs,因此和dojo.xhr*系列的参数大同小异。唯一需要注意的是handleAs在这里无效了,代之以jsonp或者checkString。

  前者用于实现JSONP协议,其值由服务器端指定,当script标签加载后就按照JSONP协议执行这个函数,然后Dojo会自动介入,负责把真正的数据传给load函数。需要指出的是在Dojo1.4以前,这个参数叫callbackParamName,冗长但意义明确。毕竟Dojo太早了,它成型的时候(2005)JSONP这个词才刚出现不久。现在callbackParamName还是可用的(为了向后兼容),不过处于deprecated状态。

  下面的例子从flickr获取feed数据:

dojo.io.script.get({
url:
"http://www.flickr.com/services/feeds/photos_public.gne",
jsonp:
"jsoncallback", //由flickr指定
content: {format: "json"},
load: function(response){
console.log(response)
return response
},
error: function(response){
console.log(response)
return response
}
})

  与jsonp不同,checkString参数专门用于跨域获取javascript代码,它其实是那段跨域脚本里的一个有定义的变量的名字,Dojo会用它来判断跨域代码是否加载完毕,配合前面提到的timeout机制就能实现有效的超时处理。

dojo.io.script.get({
url:
"http://......", //某个提供脚本的URL
checkString: "obj",
load: function(response){
//脚本加载完毕,可以直接使用其中的对象了,如obj。
Return response
}
})

  用dojo.io.iframe传数据

  dojo.io 包里还有一个工具就是iframe,常用于以不刷新页面的方式上传或下载文件。这个很经典的Ajax技巧在Dojo里就是一句 dojo.io.iframe.send({...})。这个函数接受dojo.io.iframe.__ioArgs,相比 dojo.__IoArgs,它只多了一个method参数,用于指定是用GET还是POST(默认)方法发送请求。下面的例子就实现了通过无刷新提交表单来上传文件:

dojo.io.iframe.send({
form:
"formNodeId", //某个form元素包含本地文件路径
handleAs: "html", //服务器将返回html页面
load: onSubmitted, //提交成功
error: onSubmitError //提交失败
})

  目前send函数的handleAs参数支持html, xml, text, json, 和javascript五种响应格式。除了html和xml之外,使用其他格式有一个比较特别的要求,就是服务端返回的响应必须具有以下格式: 

html
head/head
body
textarea真正的响应内容/textarea
/body
/html

  这是因为服务器返回的东西是加载在iframe里的,而只有html页面才能在任何浏览器里保证成功加载(有个DOM在,以后取数据也方便)。加一个textarea则可以尽量忠实于原始文本数据的格式,而不会受到html的影响。

  试试RPC(远程过程调用)

  如果dojo.xhr*函数以及Deferred机制仍然无法避免代码的混乱,那RPC可能就是唯一的选择了。dojo.rpc包提供了基于简单方法描述语言(SMD)的RPC实现。SMD的原理类似于WSDL(Web服务描述语言),不过是基于JSON的,它定义了远程方法的名称、参数等属性,让 Dojo能创建出代理方法以供调用。

  Dojo提供了两种方式实现rpc:XHR和JSONP,分别对应dojo.rpc.JsonService类和dojo.rpc.JsonpService类,用户可以根据是否需要跨域各取所需。

一个简单的例子:

var smdObj = {
serviceType:
"JSON-RPC",
serviceURL:
"http://...."
methods: [
{name:
"myFunc", parameters: []}
]
}
var rpc
= new dojo.rpc.JsonpService(smdObj) //传入SMD
var result = rpc.myFunc() //直接调用远程方法,返回Deferred对象
dojo.when(result, function(result){
//得到结果
})

  SMD还没有一个被广泛认可的官方标准,一直以来都是Dojo社区领导着它的发展,以后这个模块也有可能发生改变,但整个RPC基本的框架会保持稳定。

  结语

  Ajax请求这个主题太大,本文只能挂一漏万地介绍一点dojo在这方面设计和实现的皮毛,包括基本XHR请求、动态script、iframe请求、以及RPC,并特别强调了几个有Dojo特色的设计,如timeout机制、虚拟参数类、Deferred对象等。

  Dojo由Ajax领域的先驱们写就,相信从它的代码中我们一定能学到更多的东西。

posted @ 2015-02-09 23:09 Eric_jiang 阅读(443) | 评论 (1)编辑 收藏

String[] str = {};
InternetAddress[] address=new InternetAddress[amount];
for (int i=0;i<str.length;i++){
address[i]=new InternetAddress(str[i]]);
}
msg.setRecipients(Message.RecipientType.TO,address);
posted @ 2015-02-09 13:05 Eric_jiang 阅读(281) | 评论 (2)编辑 收藏

何时我们需要 Dojo 的 build 工具

Dojo 作为一个非常实用的 Ajax 实现框架已经被许多 web2.0 开发人员广泛使用,但使用 Dojo 会导致客户端浏览器需要加载大量的 Dojo 文件,导致应用程序性能下降。解决 Dojo 性能问题的方法之一就是对 Dojo 文件进行定制打包和压缩 ( 提高 Dojo 性能的具体方案请参看“提高基于 Dojo 的 Web 2.0 应用程序的性能”。Dojo 本身已经提供了一套对 Dojo 库文件 ( 自己编写的 Javascript 文件只要符合 Dojo 的规范同样可以进行打包 ) 进行 build 的工具,通过定制库文件和压缩文件的方法来减少浏览器加载文件的时间。

Dojo 的主要库文件 (dojo 包 ) 大小在 1M 左右,dijit 包和 dojox 包大小都在 4M-5M,但我们并不总是需要所有的这些库文件,可以根据开发者自身的需要定制一份 Dojo 库,实际使用的库文件大小往往能大大降低;以笔者目前的开发项目为例,经过定制后实际使用的 Dojo 库文件大小只有 300K 左右。

另外 Dojo 的 build 工具也通过压缩 Javascript 文件的手段来降低浏览器加载文件的时间(该过程中需要使用 ShrinkSafe,有关其详细介绍请参看“http://dojotoolkit.org/docs/shrinksafe”),具体的方法如下:

  1. 压缩 Javascript 文件,包括:
    1. 删除所有的空格和空行
    2. 删除所有的注释
    3. 将定义变量名用更简短的字符代替
  2. 将所有打包的的 Javascript 文件的内容合并为一个文件

经过压缩处理,Javascript 文件的大小总体可减少 30%-50%,同时将所有的 Javascript 文件打包成一个文件也减少了浏览器加载时多次开闭文件的负担,从而降低了加载时间。


准备工作

  • 到“dojo 下载网站”下载 Dojo 源代码,下载后直接解压即可,设 Dojo 的解压目录为 \dojo(下文中皆用“\dojo”指代 Dojo 文件的解压目录);
  • 下载并安装 JDK( 尽量使用 1.5 以上的版本 ),设置 JAVA_HOME 环境变量;

jdk 下载地址:http://java.sun.com/javase/downloads/index.jsp


使用 Dojo 的 build 工具

Dojo 提供的 build 工具位于 \dojo\util\buildsrcipts 下,在 windows 下调用该目录内的 build.bat(linux 下使用 build.sh)文件既可执行 build 工作。

下面是在一个在 windows 下调用 build.bat 的例子:

build profile=base action=release releaseName=myDojo optimize=shrinksafe

该命令中包括了几个最常用的参数,其意义如下:

  • action: 指定本次命令的类型,提供的三个值是:clean, release, help;
  • releaseName:本次 release 的名字,默认为 dojo;
  • optimize:本次 build 中进行优化的方式,一般使用 shrinksafe 既可;
  • profile:指定 build 使用的 profile 文件,profile 文件中提供了 build 相关的配置信息,在 \dojo\util\buildsrcipts\profiles 目录下有很多 *.profile.js 文件,我们自定义的 profile 文件也放在这个目录下,例子中“profile=base”表示指定 base.profile.js 作为 build 的参数。

实际上在使用 Dojo 的 build 工具时,关键在于提供的 profile 文件里的内容,在下面的例子中会详细说明 profile 文件的配置方法。

定制 Dojo 文件

Dojo 库中提供了大量的文件供使用者调用,但有的时候我们并不是需要所有的这些文件,此时我们可以使用 Dojo 的 build 工具定制一份个性化的 Dojo 库文件,首先我们需要编写一个 profile 文件来描述我们的需求:

清单 1. profile 文件配置示例 1
 /* example.profile.js */ 
 dependencies = { 
 layers: [    // 可以根据需要制定多个不同的 layer 
 { 
 name: "example.js",   // 打包生成的 js 文件的名
 dependencies: [       // 需要打包的 js 文件列表
"dojo.date", 
"dojox.uuid"       
 ] 
 } 
 ], 
 prefixes: [       // 设置路径
 [ "dijit", "../dijit" ], 
 [ "dojox", "../dojox" ] 
 ] 
 }

注意:

  1. dojo.js 是默认被打包的,不需要在 dependencies中声明
  2. 在 prefixes 设置路径应该是相对 dojo\dojo\dojo.js 的路径,../dijit 实际上是 dojo\dijit

将该文件 (example.profile.js) 放在 \dojo\util\buildsrcipts\profiles 目录下,执行:

 build profile=example action=release releaseName=myDojo optimize=shrinksafe

build 完成后,会在 \dojo 下生成一个 release 文件夹,如下图所示:

图示 1. build 后释放的文件示意:
图示 1. build 后释放的文件示意:

因为我们设置了 build 的参数 releaseName=myDojo, 因此 release 下会生成一个 myDojo 文件夹,本次 build 产生的文件都置于该文件夹下。在 \dojo\release\myDojo\dojo\ 目录下,我们可以找到两个文件:example.js 和 example.uncompressed.js,这就是我们需要的打包后的文件,example.uncompressed.js 只是包含了我们指定的所有 dojo 文件,example.js 则在 example.uncompressed.js 基础上又进行了压缩处理。

build 我们自己的 Javascript 文件

对于我们自己编写的 Javascript 文件,我们同样可是借助 Dojo 提供的 build 工具进行压缩和打包,前提是这些 js 文件需要按照 Dojo 相关的的规范编写。打包我们自己的 Javascript 文件与打包 Dojo 文件并没有太大的差别,假设我们有两个 Javascript 文件如下:

清单 2. 假设需要打包的 2 个 Javascript 文件
 /* my.example1 */ 
 dojo.provide("my.example1");  
 dojo.require("my.example2");   // 声明了对 my.example2 的依赖
 /* 
 * this is a js file witch named example1.js 
 */ 

 /* my.example2 */ 
 dojo.provide("my.example2"); 
 /* 
 * this is a js file witch named example2.js 
 */

在 \dojo 下新建一个文件夹“my”, 将上面的两个文件放在该文件夹下,profile 文件配置如下:

清单 3. profile 文件配置示例 2
 /* example.profile.js */ 
 dependencies = { 
	 layers: [ 
 { 
        name: "example.js",   
 dependencies: [       
"dojo.date", 
"dojox.uuid", 
"my.example1"     // 注意这里我们只声明了 my.example1 
 ]   
    } 
 ], 
	 prefixes: [ 
    [ "dijit", "../dijit" ], 
 [ "dojox", "../dojox" ], 
 [ "my", "../my"]      // 刚才新建的 my 文件夹需要在此声明路径
	 ] 
 }

执行:

 build.bat profile=example action=release releaseName=myDojo optimize=shrinksafe

请注意,在 profile 文件中,只声明了将 my.example1 进行打包,但在 build 生成的 example.js 中我们会发现 my.example2 中的内容也已经被添加进来了。这是因为在 build 过程中,build 程序在分析 js 文件内容时通过识别一些关键字 ( 例如 dojo.require) 来判断当前文件是否依赖其他的文件,并将这些依赖的文件一同进行打包。因此当 build 程序在 my.example1 中读到 dojo.require("my.example2"); 时,判断出该文件需要依赖另一个文件"my.example2",根据 prefixes 提供的路径 build 程序找到了 my.example2.js 文件,并将该文件的内容添加进来。

按照上面的例子 build 后,我们自己编写的 Javascript 文件会和我们定制 Dojo 的文件合并在一个文件中,我们可能需要独立使用这些自己编写的 Javascript 文件,那么我们修改一下 profile 文件既可:

清单 4. profile 文件配置示例 3
 /* example.profile.js */ 
 dependencies = { 
 layers: [ 
 {   // 这个 layer 用来打包我们定制的 dojo 文件
 name: "mydojo.js",   
 dependencies: [       
"dojo.date", 
"dojox.uuid"
 ] 
 }, 
 {  // 这个 layer 用于打包我们自己的 js 文件
 name: "example.js",   
 dependencies: [       
"my.example1"
 ] 
 } 
 ], 
 prefixes: [ 
 [ "dijit", "../dijit" ], 
 [ "dojox", "../dojox" ], 
 [ "my", "../my"] 
 ] 
 }

执行:

 build.bat profile=example action=release releaseName=myDojo optimize=shrinksafe

这样 build 后在 \dojo\release\myDojo\dojo\ 我们会分别得到 mydojo 和 example 两个 layer 的打包文件:

  • mydojo.js 和 mydojo.uncompressed.js:打包的是我们定制的 Dojo 文件
  • example.js 和 example.uncompressed.js:打包了我们自己编写 Javascript 文件,我们可以根据需要独立使用他们

需要注意的问题

  1. 在上面我们已经讲到了 build 程序会按照 dojo.require 等关键字将依赖文件添加进来,因此在每个 layer 的 dependencies 中我们不必列出所有我们需要打包的文件,只需要将一些根文件列出既可 ( 如清单 3 所示 );另外我们也应该确保这些需要打包的文件以及他们所依赖的其他文件所在的路径都在 prefixes 声明注册过,否则 build 程序会因为找不到所需要的文件而失败。
  2. 上面提到在 build 过程中,会调用 shrinksafe 将 js 文件进行压缩,压缩策略包括将定义的变量名用更为简洁的字符串替代,例如我们定义 ”var identifier”,经过压缩处理可能就变成了 ”var _v01”,。如果我们的 Javascript 代码中使用了 eval语句,并且 eval的内容里包含了一些我们定义的变量名,就会导致打包后的文件出现错误而无法使用。例如下面的 Javascript 代码:
 var identifier = “”; 
 eval(“alert(identifier)”);

因为经过压缩后变量名 identifier 被 build 程序以其他的名字替代,因此在执行 eval 方法 , 也就是调用 alert(identifier) 时,会因为无法识别 identifier 而报出 undefined 的错误。


小结

本文站在一个初学者的角度简单地介绍了 Dojo 的 build 工具的使用方法(关键在于 profile 文件的配置),通过以上内容读者应该能够使用该工具进行基本的定制和打包处理,有兴趣的读者可以通过提供的参考资料进行进一步的学习。

posted @ 2015-01-29 15:20 Eric_jiang 阅读(226) | 评论 (0)编辑 收藏

1. HTTPS概念

        1)简介   

        HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。这个系统的最初研发由网景公司进行,提供了身份验证与加密通讯方法,现在它被广泛用于万维网上安全敏感的通讯,例如交易支付方面。

      2)HTTPS和HTTP的区别

  a. https协议需要到ca申请证书,一般免费证书很少,需要交费。

  b. http是超文本传输协议,信息是明文传输;https 则是具有安全性的ssl加密传输协议。

  c. http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

d. http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

      3)HTTPS的作用

      它的主要作用可以分为两种:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。

  a. 一般意义上的https,就是服务器有一个证书。主要目的是保证服务器就是他声称的服务器,这个跟第一点一样;服务端和客户端之间的所有通讯,都是加密的。

  b. 具体讲,是客户端产生一个对称的密钥,通过服务器的证书来交换密钥,即一般意义上的握手过程。

  c. 接下来所有的信息往来就都是加密的。第三方即使截获,也没有任何意义,因为他没有密钥,当然篡改也就没有什么意义了。

  d.少许对客户端有要求的情况下,会要求客户端也必须有一个证书。

这里客户端证书,其实就类似表示个人信息的时候,除了用户名/密码,还有一个CA 认证过的身份。因为个人证书一般来说是别人无法模拟的,所有这样能够更深的确认自己的身份。目前少数个人银行的专业版是这种做法,具体证书可能是拿U盘(即U盾)作为一个备份的载体。

 

2.SSL简介

  1)简介

  SSL (Secure Socket Layer)为Netscape所研发,用以保障在Internet上数据传输之安全,利用数据加密(Encryption)技术,可确保数据在网络上之传输过程中不会被截取及窃听。它已被广泛地用于Web浏览器与服务器之间的身份认证和加密数据传输。SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。

  2)SSL提供的服务

  a.认证用户和服务器,确保数据发送到正确的客户机和服务器

  b.加密数据以防止数据中途被窃取

  c.维护数据的完整性,确保数据在传输过程中不被改变。

  3) SSL协议的握手过程

  SSL 协议既用到了公钥加密技术又用到了对称加密技术,对称加密技术虽然比公钥加密技术的速度快,可是公钥加密技术提供了更好的身份认证技术。SSL 的握手协议非常有效的让客户和服务器之间完成相互之间的身份认证,其主要过程如下:

  ①客户端的浏览器向服务器传送客户端SSL 协议的版本号,加密算法的种类,产生的随机数,以及其他服务器和客户端之间通讯所需要的各种信息。

  ②服务器向客户端传送SSL 协议的版本号,加密算法的种类,随机数以及其他相关信息,同时服务器还将向客户端传送自己的证书。

  ③客户利用服务器传过来的信息验证服务器的合法性,服务器的合法性包括:证书是否过期,发行服务器证书的CA 是否可靠,发行者证书的公钥能否正确解开服务器证书的“发行者的数字签名”,服务器证书上的域名是否和服务器的实际域名相匹配。如果合法性验证没有通过,通讯将断开;如果合法性验证通过,将继续进行第四步。

  ④用户端随机产生一个用于后面通讯的“对称密码”,然后用服务器的公钥(服务器的公钥从步骤②中的服务器的证书中获得)对其加密,然后传给服务器。

  ⑤服务器用私钥解密“对称密码”(此处的公钥和私钥是相互关联的,公钥加密的数据只能用私钥解密,私钥只在服务器端保留。详细请参看: http://zh.wikipedia.org/wiki/RSA%E7%AE%97%E6%B3%95),然后用其作为服务器和客户端的“通话密码”加解密通讯。同时在SSL 通讯过程中还要完成数据通讯的完整性,防止数据通讯中的任何变化。

  ⑥客户端向服务器端发出信息,指明后面的数据通讯将使用的步骤⑤中的主密码为对称密钥,同时通知服务器客户端的握手过程结束。

  ⑦服务器向客户端发出信息,指明后面的数据通讯将使用的步骤⑤中的主密码为对称密钥,同时通知客户端服务器端的握手过程结束。

  ⑧SSL 的握手部分结束,SSL 安全通道的数据通讯开始,客户和服务器开始使用相同的对称密钥进行数据通讯,同时进行通讯完整性的检验。

       

 

3.配置服务器端证书

  为了能实施SSL,一个web服务器对每个接受安全连接的外部接口(IP 地址)必须要有相应的证书(Certificate)。关于这个设计的理论是一个服务器必须提供某种合理的保证以证明这个服务器的主人就是你所认为的那个人。这个证书要陈述与这个网站相关联的公司,以及这个网站的所有者或系统管理员的一些基本联系信息。

  这个证书由所有人以密码方式签字,其他人非常难伪造。对于进行电子商务(e-commerce)的网站,或其他身份认证至关重要的任何商业交易,认证书要向大家所熟知的认证权威(Certificate Authority (CA))如VeriSign或Thawte来购买。这样的证书可用电子技术证明属实。实际上,认证权威单位会担保它发出的认证书的真实性,如果你信任发出认证书的认证权威单位的话,你就可以相信这个认证书是有效的。

  关于权威证书的申请,请参考:http://www.cnblogs.com/mikespook/archive/2004/12/22/80591.aspx

  在许多情况下,认证并不是真正使人担忧的事。系统管理员或许只想要保证被服务器传送和接收的数据是秘密的,不会被连接线上的偷窃者盗窃到。庆幸的是,Java提供相对简单的被称为keytool的命令行工具,可以简单地产生“自己签名”的证书。自己签名的证书只是用户产生的证书,没有正式在大家所熟知的认证权威那里注册过,因此不能确保它的真实性。但却能保证数据传输的安全性。

  用Tomcat来配置SSL主要有下面这么两大步骤:

  1)生成证书

  a. 在命令行下执行:

  %Java_home%\bin\keytool -genkey -alias tomcat -keyalg RSA

  在此命令中,keytool是JDK自带的产生证书的工具。把RSA运算法则作为主要安全运算法则,这保证了与其它服务器和组件的兼容性。

这个命令会在用户的home directory产生一个叫做" .keystore " 的新文件。在执行后,你首先被要求出示keystore密码。Tomcat使用的默认密码是" changeit "(全都是小写字母),如果你愿意,你可以指定你自己的密码。你还需要在server.xml配置文件里指定自己的密码,这在以后会有描述。

  b .你会被要求出示关于这个认证书的一般性信息,如公司,联系人名称,等等。这些信息会显示给那些试图访问你程序里安全网页的用户,以确保这里提供的信息与他们期望的相对应。

  c.你会被要求出示密钥(key)密码,也就是这个认证书所特有的密码(与其它的储存在同一个keystore文件里的认证书不同)。你必须在这里使用与keystore密码相同的密码。(目前,keytool会提示你按ENTER键会自动帮你做这些)。

  如果一切顺利,你现在就拥有了一个可以被你的服务器使用的有认证书的keystore文件。

  2) 配置tomcat

  第二个大步骤是把secure socket配置在$CATALINA_HOME/conf/server.xml文件里。$CATALINA_HOME代表安装Tomcat的目录。一个例子是SSL连接器的元素被包括在和Tomcat一起安装的缺省server.xml文件里。它看起来象是这样:

$CATALINA_HOME/conf/server.xml

复制代码
< -- Define a SSL Coyote HTTP/1.1 Connector on port 8443 -->

< !--

< Connector

port
="8443" minProcessors="5" maxProcessors="75"

enableLookups
="true" disableUploadTimeout="true"

acceptCount
="100" debug="0" scheme="https" secure="true";

clientAuth
="false" sslProtocol="TLS"/>

-->
复制代码

  Connector元素本身,其默认形式是被注释掉的(commented out),所以需要把它周围的注释标志删除掉。然后,可以根据需要客户化(自己设置)特定的属性。一般需要增加一下keystoreFile和keystorePass两个属性,指定你存放证书的路径(如:keystoreFile="C:/.keystore")和刚才设置的密码(如:keystorePass="123456")。关于其它各种选项的详细信息,可查阅Server Configuration Reference。

  在完成这些配置更改后,必须象重新启动Tomcat,然后你就可以通过SSL访问Tomcat支持的任何web应用程序。只不过指令需要像下面这样:https://localhost:8443

 

4.客户端代码实现

  在Java中要访问Https链接时,会用到一个关键类HttpsURLConnection;参见如下实现代码:

复制代码
        // 创建URL对象
URL myURL = new URL("https://www.sun.com");

// 创建HttpsURLConnection对象,并设置其SSLSocketFactory对象
HttpsURLConnection httpsConn = (HttpsURLConnection) myURL.openConnection();

// 取得该连接的输入流,以读取响应内容
InputStreamReader insr = new InputStreamReader(httpsConn.getInputStream());

// 读取服务器的响应内容并显示
int respInt = insr.read();
while (respInt != -1) {
System.out.print((char) respInt);
respInt = insr.read();
}
复制代码

  在取得connection的时候和正常浏览器访问一样,仍然会验证服务端的证书是否被信任(权威机构发行或者被权威机构签名);如果服务端证书不被信任,则默认的实现就会有问题,一般来说,用SunJSSE会抛如下异常信息:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building 
failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

  上面提到SunJSSE,JSSE(Java Secure Socket Extension)是实现Internet安全通信的一系列包的集合。它是一个SSL和TLS的纯Java实现,可以透明地提供数据加密、服务器认证、信息完整性等功能,可以使我们像使用普通的套接字一样使用JSSE建立的安全套接字。JSSE是一个开放的标准,不只是Sun公司才能实现一个SunJSSE,事实上其他公司有自己实现的JSSE,然后通过JCA就可以在JVM中使用。

  关于JSSE的详细信息参考官网Reference:http://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html
  以及Java Security Guide:http://java.sun.com/j2se/1.5.0/docs/guide/security/

  在深入了解JSSE之前,需要了解一个有关Java安全的概念:客户端的TrustStore文件。客户端的TrustStore文件中保存着被客户端所信任的服务器的证书信息。客户端在进行SSL连接时,JSSE将根据这个文件中的证书决定是否信任服务器端的证书。在SunJSSE中,有一个信任管理器类负责决定是否信任远端的证书,这个类有如下的处理规则:
1)若系统属性javax.net.sll.trustStore指定了TrustStore文件,那么信任管理器就去jre安装路径下的lib/security/目录中寻找并使用这个文件来检查证书。
2)若该系统属性没有指定TrustStore文件,它就会去jre安装路径下寻找默认的TrustStore文件,这个文件的相对路径为:lib/security/jssecacerts
3)若jssecacerts不存在,但是cacerts存在(它随J2SDK一起发行,含有数量有限的可信任的基本证书),那么这个默认的TrustStore文件就是lib/security/cacerts

  那遇到这种情况,怎么处理呢?有以下两种方案:
  1)按照以上信任管理器的规则,将服务端的公钥导入到jssecacerts,或者是在系统属性中设置要加载的trustStore文件的路径;证书导入可以用如下命令:keytool -import -file src_cer_file –keystore dest_cer_store;至于证书可以通过浏览器导出获得;
  2)、实现自己的证书信任管理器类,比如MyX509TrustManager,该类必须实现X509TrustManager接口中的三个method;然后在HttpsURLConnection中加载自定义的类,可以参见如下两个代码片段,其一为自定义证书信任管理器,其二为connect时的代码:

  

复制代码
package test;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class MyX509TrustManager implements X509TrustManager {
/*
* The default X509TrustManager returned by SunX509. We'll delegate
* decisions to it, and fall back to the logic in this class if the
* default X509TrustManager doesn't trust it.
*/
X509TrustManager sunJSSEX509TrustManager;
MyX509TrustManager() throws Exception {
// create a "default" JSSE X509TrustManager.
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("trustedCerts"),
"passphrase".toCharArray());
TrustManagerFactory tmf =
TrustManagerFactory.getInstance("SunX509", "SunJSSE");
tmf.init(ks);
TrustManager tms [] = tmf.getTrustManagers();
/*
* Iterate over the returned trustmanagers, look
* for an instance of X509TrustManager. If found,
* use that as our "default" trust manager.
*/
for (int i = 0; i < tms.length; i++) {
if (tms[i] instanceof X509TrustManager) {
sunJSSEX509TrustManager = (X509TrustManager) tms[i];
return;
}
}
/*
* Find some other way to initialize, or else we have to fail the
* constructor.
*/
throw new Exception("Couldn't initialize");
}
/*
* Delegate to the default trust manager.
*/
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
try {
sunJSSEX509TrustManager.checkClientTrusted(chain, authType);
} catch (CertificateException excep) {
// do any special handling here, or rethrow exception.
}
}
/*
* Delegate to the default trust manager.
*/
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
try {
sunJSSEX509TrustManager.checkServerTrusted(chain, authType);
} catch (CertificateException excep) {
/*
* Possibly pop up a dialog box asking whether to trust the
* cert chain.
*/
}
}
/*
* Merely pass this through.
*/
public X509Certificate[] getAcceptedIssuers() {
return sunJSSEX509TrustManager.getAcceptedIssuers();
}
}
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();
// 创建URL对象
URL myURL = new URL("https://ebanks.gdb.com.cn/sperbank/perbankLogin.jsp");
// 创建HttpsURLConnection对象,并设置其SSLSocketFactory对象
HttpsURLConnection httpsConn = (HttpsURLConnection) myURL.openConnection();
httpsConn.setSSLSocketFactory(ssf);
// 取得该连接的输入流,以读取响应内容
InputStreamReader insr = new InputStreamReader(httpsConn.getInputStream());
// 读取服务器的响应内容并显示
int respInt = insr.read();
while (respInt != -1) {
System.out.print((char) respInt);
respInt = insr.read();
}
复制代码

  对于以上两种实现方式,各有各的优点,第一种方式不会破坏JSSE的安全性,但是要手工导入证书,如果服务器很多,那每台服务器的JRE都必须做相同的操作;第二种方式灵活性更高,但是要小心实现,否则可能会留下安全隐患;

 

  参考文献:        

  http://baike.baidu.com/view/14121.htm

  http://zh.wikipedia.org/wiki/RSA%E7%AE%97%E6%B3%95

  http://blog.csdn.net/sfdev/article/details/2957240

  http://blog.csdn.net/cyberexp2008/article/details/6695691

posted @ 2015-01-27 10:28 Eric_jiang 阅读(370) | 评论 (2)编辑 收藏

就是在前台中调用proxy程序的servlet,设置参数servletName和其它参数。代理程序会将该请求发送到目的地址的名称为servletName的servlet中去,并将其它参数作为请求的参数,在得到结果后,将内容原样输出到请求页面。
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ProxyServlet extends HttpServlet {
private String url;
/**
* 对servlet进行请求处理,并将结果在指定输出流中输出
* @param os
* @param servletName
* @param parm
* @throws IOException
* @throws MalformedURLException
*/
private void process(HttpServletRequest req, HttpServletResponse resp,
String[] target) throws MalformedURLException, IOException {
// 取得连接
HttpURLConnection huc = (HttpURLConnection) new URL(url + target[0])
.openConnection();
// 设置连接属性
huc.setDoOutput(true);
huc.setRequestMethod("POST");
huc.setUseCaches(false);
huc.setInstanceFollowRedirects(true);
huc.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
huc.connect();
// 往目标servlet中提供参数
OutputStream targetOS = huc.getOutputStream();
targetOS.write(target[1].getBytes());
targetOS.flush();
targetOS.close();
// 取得页面输出,并设置页面编码及缓存设置
resp.setContentType(huc.getContentType());
resp.setHeader("Cache-Control", huc.getHeaderField("Cache-Control"));
resp.setHeader("Pragma", huc.getHeaderField("Pragma"));
resp.setHeader("Expires", huc.getHeaderField("Expires"));
OutputStream os = resp.getOutputStream();
// 将目标servlet的输入流直接往页面输出
InputStream targetIS = huc.getInputStream();
int r;
while ((r = targetIS.read()) != -1) {
os.write(r);
}
targetIS.close();
os.flush();
os.close();
huc.disconnect();
}
/**
* 将参数中的目标分离成由目标servlet名称和参数组成的数组
* @param queryString
* @return
* @throws UnsupportedEncodingException
*/
private String[] parse(Map map) throws UnsupportedEncodingException {
String[] arr = { "", "" };
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry me = (Entry) iter.next();
String[] varr = (String[]) me.getValue();
if ("servletName".equals(me.getKey())) {
// 取出servlet名称
arr[0] = varr[0];
} else {
// 重新组装参数字符串
for (int i = 0; i < varr.length; i++) {
// 参数需要进行转码,实现字符集的统一
arr[1] += "&" + me.getKey() + "="
+ URLEncoder.encode(varr[i], "utf-8");
}
}
}
arr[1] = arr[1].replaceAll("^&", "");
return arr;
}
@Override
public void init() throws ServletException {
// 设置目标服务器地址
url = this.getInitParameter("url");
if (!url.endsWith("/"))
url = url + "/";
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String[] target = parse(req.getParameterMap());
process(req, resp, target);
}
}
posted @ 2015-01-26 17:32 Eric_jiang 阅读(254) | 评论 (0)编辑 收藏

现在很多厂商比如,百度、谷歌在调用api接口时早已开始使用json数据。
但是古老的XMLHttpRequest设计时,为了安全性,不能使用跨站数据(就是调用其它的网站的数据)
如果需要访问由远程服务器上一个web服务托管的json数据,则要使用JSONP。
假设,我要进行百度地图坐标转换,这是文档http://developer.baidu.com/map/changeposition.htm
运行示例 http://api.map.baidu.com/geoconv/v1/?coords=114.21892734521,29.575429778924;114.21892734521,29.575429778924&from=1&to=1
浏览器打开得到返回值 (注意当前返回错误,本文只是随便找个例子用来讲解)
{"status":22,"message":"param error:to illegal, not support such coord type","result":[]}
那么我们该如何来让我们的页面程序获取这个值呢?
在示例链接中加入
callback=GetValue
然后新建html页面
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <script>
        var getVal;
        function GetValue(Value)
        {
            getVal = Value;
            alert("ok");
        }
        
    </script>
</head>
<body>
    <script src="http://api.map.baidu.com/geoconv/v1/?coords=114.21892734521,29.575429778924;114.21892734521,29.575429778924&from=1&to=1&callback=GetValue">
    </script>
</body>
</html>
!注意html页面中新建的GetValue函数
通过<script>标签调用示例链接产生GetValue值时就会弹窗
然后通过火狐firebug进入控制台查看GetValue的参数传递给getVal的值
Object { status=22, message="param error:to illegal, ...support such coord type", result=[0]}
posted @ 2015-01-23 20:50 Eric_jiang 阅读(434) | 评论 (2)编辑 收藏

  1. package position;  
  2.   
  3. import org.junit.Test;  
  4.   
  5. /** 
  6.  * 各地图API坐标系统比较与转换; 
  7.  *  
  8.  * WGS84坐标系:即地球坐标系,国际上通用的坐标系。设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系,谷歌地图采用的是WGS84地理坐标系(中国范围除外); 
  9.  *  
  10.  * GCJ02坐标系:即火星坐标系,是由中国国家测绘局制订的地理信息系统的坐标系统。由WGS84坐标系经加密后的坐标系。谷歌中国地图和搜搜中国地图采用的是GCJ02地理坐标系; 
  11.  *  
  12.  * BD09坐标系:即百度坐标系,GCJ02坐标系经加密后的坐标系; 
  13.  *  
  14.  * 搜狗坐标系、图吧坐标系等,估计也是在GCJ02基础上加密而成的。 
  15.  *  
  16.  * @author chenhua 
  17.  *  
  18.  */  
  19. public class PositionUtil  
  20. {  
  21.     private static double pi = 3.1415926535897932384626;  
  22.     private static double a = 6378245.0;  
  23.     private static double ee = 0.00669342162296594323;  
  24.   
  25.     @Test  
  26.     public void t1()  
  27.     {  
  28.         // 北斗芯片获取的经纬度为WGS84地理坐标 31.426896,119.496145  
  29.   
  30.         Gps gps = new Gps(31.426896119.496145);  
  31.         System.out.println("gps :" + gps);  
  32.   
  33.         Gps gcj = gps84_To_Gcj02(gps.getWgLat(), gps.getWgLon());  
  34.         System.out.println("gcj :" + gcj);  
  35.   
  36.         Gps star = gcj_To_Gps84(gcj.getWgLat(), gcj.getWgLon());  
  37.         System.out.println("star:" + star);  
  38.   
  39.         Gps bd = gcj02_To_Bd09(gcj.getWgLat(), gcj.getWgLon());  
  40.         System.out.println("bd  :" + bd);  
  41.   
  42.         Gps gcj2 = bd09_To_Gcj02(bd.getWgLat(), bd.getWgLon());  
  43.         System.out.println("gcj :" + gcj2);  
  44.   
  45.     }  
  46.   
  47.     /** 
  48.      * 84 to 火星坐标系 (GCJ-02) 
  49.      *  
  50.      * World Geodetic System ==> Mars Geodetic System 
  51.      *  
  52.      * @param lat 
  53.      * @param lon 
  54.      * @return 
  55.      */  
  56.     public static Gps gps84_To_Gcj02(double lat, double lon)  
  57.     {  
  58.         if (outOfChina(lat, lon))  
  59.         {  
  60.             return null;  
  61.         }  
  62.         double dLat = transformLat(lon - 105.0, lat - 35.0);  
  63.         double dLon = transformLon(lon - 105.0, lat - 35.0);  
  64.         double radLat = lat / 180.0 * pi;  
  65.         double magic = Math.sin(radLat);  
  66.         magic = 1 - ee * magic * magic;  
  67.         double sqrtMagic = Math.sqrt(magic);  
  68.         dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);  
  69.         dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);  
  70.         double mgLat = lat + dLat;  
  71.         double mgLon = lon + dLon;  
  72.   
  73.         return new Gps(mgLat, mgLon);  
  74.     }  
  75.   
  76.     /** 
  77.      * 火星坐标系 (GCJ-02) to 84 
  78.      *  
  79.      * @param lon 
  80.      * @param lat 
  81.      * @return 
  82.      */  
  83.     public Gps gcj_To_Gps84(double lat, double lon)  
  84.     {  
  85.         Gps gps = transform(lat, lon);  
  86.         double lontitude = lon * 2 - gps.getWgLon();  
  87.         double latitude = lat * 2 - gps.getWgLat();  
  88.   
  89.         return new Gps(latitude, lontitude);  
  90.   
  91.     }  
  92.   
  93.     /** 
  94.      * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 
  95.      *  
  96.      * 将 GCJ-02 坐标转换成 BD-09 坐标 
  97.      *  
  98.      * @param gg_lat 
  99.      * @param gg_lon 
  100.      */  
  101.     public static Gps gcj02_To_Bd09(double gg_lat, double gg_lon)  
  102.     {  
  103.         double x = gg_lon, y = gg_lat;  
  104.   
  105.         double z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * pi);  
  106.   
  107.         double theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * pi);  
  108.   
  109.         double bd_lon = z * Math.cos(theta) + 0.0065;  
  110.   
  111.         double bd_lat = z * Math.sin(theta) + 0.006;  
  112.   
  113.         return new Gps(bd_lat, bd_lon);  
  114.     }  
  115.   
  116.     /** 
  117.      * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 
  118.      *  
  119.      * 将 BD-09 坐标转换成GCJ-02 坐标 
  120.      *  
  121.      * @param bd_lat 
  122.      * @param bd_lon 
  123.      * @return 
  124.      */  
  125.     public static Gps bd09_To_Gcj02(double bd_lat, double bd_lon)  
  126.     {  
  127.         double x = bd_lon - 0.0065, y = bd_lat - 0.006;  
  128.   
  129.         double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * pi);  
  130.   
  131.         double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * pi);  
  132.   
  133.         double gg_lon = z * Math.cos(theta);  
  134.   
  135.         double gg_lat = z * Math.sin(theta);  
  136.   
  137.         return new Gps(gg_lat, gg_lon);  
  138.     }  
  139.   
  140.     private static boolean outOfChina(double lat, double lon)  
  141.     {  
  142.         if (lon < 72.004 || lon > 137.8347)  
  143.             return true;  
  144.         if (lat < 0.8293 || lat > 55.8271)  
  145.             return true;  
  146.         return false;  
  147.     }  
  148.   
  149.     private Gps transform(double lat, double lon)  
  150.     {  
  151.         if (outOfChina(lat, lon))  
  152.         {  
  153.             return new Gps(lat, lon);  
  154.         }  
  155.         double dLat = transformLat(lon - 105.0, lat - 35.0);  
  156.         double dLon = transformLon(lon - 105.0, lat - 35.0);  
  157.         double radLat = lat / 180.0 * pi;  
  158.         double magic = Math.sin(radLat);  
  159.         magic = 1 - ee * magic * magic;  
  160.         double sqrtMagic = Math.sqrt(magic);  
  161.         dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);  
  162.         dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);  
  163.         double mgLat = lat + dLat;  
  164.         double mgLon = lon + dLon;  
  165.   
  166.         return new Gps(mgLat, mgLon);  
  167.     }  
  168.   
  169.     private static double transformLat(double x, double y)  
  170.     {  
  171.         double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));  
  172.         ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;  
  173.         ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;  
  174.         ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;  
  175.         return ret;  
  176.     }  
  177.   
  178.     private static double transformLon(double x, double y)  
  179.     {  
  180.         double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));  
  181.         ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;  
  182.         ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;  
  183.         ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0 * pi)) * 2.0 / 3.0;  
  184.         return ret;  
  185.     }  
  186.   
  187. }  
  1. package position;  
  2.   
  3. public class Gps  
  4. {  
  5.   
  6.     private double wgLat;  
  7.     private double wgLon;  
  8.   
  9.     public Gps(double wgLat, double wgLon)  
  10.     {  
  11.         setWgLat(wgLat);  
  12.         setWgLon(wgLon);  
  13.     }  
  14.   
  15.     public double getWgLat()  
  16.     {  
  17.         return wgLat;  
  18.     }  
  19.   
  20.     public void setWgLat(double wgLat)  
  21.     {  
  22.         this.wgLat = wgLat;  
  23.     }  
  24.   
  25.     public double getWgLon()  
  26.     {  
  27.         return wgLon;  
  28.     }  
  29.   
  30.     public void setWgLon(double wgLon)  
  31.     {  
  32.         this.wgLon = wgLon;  
  33.     }  
  34.   
  35.     @Override  
  36.     public String toString()  
  37.     {  
  38.         return wgLat + "," + wgLon;  
  39.     }  
  40.   
  41. }  
posted @ 2015-01-23 20:12 Eric_jiang 阅读(865) | 评论 (0)编辑 收藏

仅列出标题
共57页: First 上一页 2 3 4 5 6 7 8 9 10 下一页 Last