PJAX的实现与应用实例

前端开发atool 发表了文章 • 0 个评论 • 1945 次浏览 • 2016-04-22 13:14 • 来自相关话题

一、前言

web发展经历了一个漫长的周期,最开始很多人认为Javascript这们语言是前端开发的累赘,是个鸡肋,那个时候人们还享受着从一个a链接蹦到另一个页面的web神奇魔术。后来随着JavaScript的不断更新换代,他的功能不仅仅是为网页添加一点特效了,语言本身的加强以及对DOM操作能力的提升让他在前端大放光彩。尤其是ajax的出现,让JavaScript以及整个web的发展翻开了崭新的一页。

利用ajax局部刷新页面,相信很多人玩得相当熟练了。如果整个页面的刷新都是使用ajax,我们可以称之为一个webapp,所有的逻辑都是在当页处理,这种形式的页面带来的体验是十分不错的,减少了那些比较“冗余”的页面跳转、新开页面等。不过,webapp的代码是十分不好维护的,页面逻辑太多太深,出点小问题,整个页面就会瘫痪,而且不方便定位bug,可维护性很低。

二、PJAX的实现与应用

1.场景再现-ajax弊端

ajax是一个非常好玩的小东西,不过用起来也会存在一些问题。

我们可以利用ajax进行无刷新改变文档内容,但是没办法去修改URL,有童鞋要问,这里为什么一定要修改URL呢?一个URL代表一个特定的网络资源,ajax修改了页面的内容,所以用不同的URL去标识他们,这个还是挺有必要的。

比如我们设计了一个单词查询的页面,比较合理的UR应该是http://example.com/word,不同的word对应不同的内容,但是如果整个页面都是ajax实现,我们就没法去修改/word了,当然我们可以使用hash如http://example.com#word,但这样就不能很好的处理浏览器的前进和后退问题。如:在页面中查询了单词A的翻译,接着又查询了单词B,这个时候浏览器的浏览历史会生成http://example.com#A和http://example.com#B两个记录,可是当我们从B转回A的时候,AJAX的效果还停留在B的状态(页面显示的还是单词B的翻译)。部分浏览器对此问题引入了onhashchange的接口,只要URL的hash值发生变化,我们的程序就可以监听并做出相应。不过对于那些木有这个接口的浏览器,就得定时去判断hash的变化了。

而这样的方式对搜索引擎是十分不友好的,twitter和google约定使用hash bang (#!xxx),也就是hash后面的第一个字符为感叹号,这样的网址他们是会爬取的,但是其他搜索引擎不支持。PJAX可以在改变页面内容的同时也改变他的URL,下面来说说PJAX和他的应用。

2.什么是PJAX

history API中有几个新特性,分别是history.pushState和history.replaceState,我们把pushState+AJAX进行封装,合起来简单点叫,就是PJAX~ 虽说实现技术上没什么新东西,但是概念上还是有所不同的。

PJAX的基本思路是,用户点击一个链接,通过ajax更新页面变化的部分,然后使用HTML5的pushState修改浏览器的URL地址,这样有效地避免了整个页面的重新加载。如果浏览器不支持history的两个新API或者JS被禁用了,那这个链接就只能跳转并重新刷新整个页面了。和传统的ajax设计稍微不同,ajax通常是从后台获取JSON数据,然后由前端解析渲染,而PJAX请求的是一个在服务器上生成好的HTML碎片,如下图所示:





客户端向服务器发送一个普通的请求(1),其实也就是点击了一个链接,服务器会相应这个请求(2),返回一个html文档。客户端向服务器发送一个有PJAX标志的请求(3),此时服务器只返回一个html碎片(4)。但是这两次请求都让客户端的URL变化了,希望上面的说明可以让你明白了PAJX和AJAX的区别了。

3.PJAX的实现

先看一个小DEMO吧,这个DEMO也写了我半个多小时,看之前先说明一下,打开你的现代浏览器(chrome,Firefox,opera,IE9+等),进入gallery页面,查看图片的时候注意观察浏览器的title和url变化,点击前进后退按钮也注意查看其变化。我已经在浏览历史管理中push了三条历史记录。

DEMO地址:http://qianduannotes.duapp.com ... .html

如果你还没有理解上面说的PJAX和AJAX的区别,看完这个demo,你应该有所领悟吧!在URL变化之后,页面并没有刷新,而是继续完成自己的动画(demo中为fadeOut)。

在HTML4,Histroy对象有下面属性方法:

length:历史堆栈中的记录数。

back():返回上一页。

forward():前进到下一页。

go([delta]):delta是个数字,如果不写或为0,则刷新本页;如果为正数,则前进到相应数目的页面;若为负数,则后退到相应数目的页面。

在HTML5中,新增了两个方法:

pushState(data, title [, url]):往历史堆栈的顶部添加一条记录。data为一个对象或null,它会在触发window的popstate事件(window.onpopstate)时,作为参数的state属性传递过去;title为页面的标题,但当前所有浏览器都忽略这个参数;url为页面的URL,不写则为当前页。

replaceState(data, title [, url]):更改当前页面的历史记录。参数同上。这种更改并不会去访问该URL。

当点击“上一张”、“下一张”这两个链接的时候,首先通过pushState修改URL以及修改document.title,那这个时候你就可以当做文档已经进入了另外一个链接了,然后该干什么干什么。demo中是让图片fadeOut,fadeOut完了之后让浏览器去加载资源,这个步骤就是正常的AJAX操作啦,没有什么特殊之处了~

因为只准备了三张图片,所有后台写的也比较简单:
<?phperror_reporting(false);$num = $_GET['num'];if(array_key_exists('HTTP_X_PJAX', $_SERVER) && $_SERVER['HTTP_X_PJAX'] === 'true'){ if($num == 1) {?>
<div class="imgwrap">
<img src="./images/1.jpg" />
</div>
<span><a href="num=2" class="next">下一张>></a></span>
<?php
} else if ($num == 2) {?>
<div class="imgwrap">
<img src="./images/2.jpg" />
</div>
<span><a href="num=1" class="previous"><<上一张</a>
<a href="num=3" class="next">下一张>></a></span>
<?php
} else {?>
<div class="imgwrap">
<img src="./images/3.jpg" />
</div>
<span><a href="num=2" class="previous"><<上一张</a></span>
<?php
}
}?>上面那张图中,我们看到了,并不是每个连接都使用PJAX来加载,如果有X_PJAX标识,我们才会添加相应的处理。js中稍加注意可以看到:
$.ajax({
"url": "./interface.php",
"data": {
"num": num
},
"dataType": "html",
"headers": {
"X_PJAX": true
}
});请求中:
Accept:text/html, */*; q=0.01
Accept-Encoding:gzip,deflate,sdch
Connection:keep-alive
Host:qianduannotes.duapp.com
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
X-Requested-With:XMLHttpRequest
X_PJAX:true我在请求的header中加了一个X_PJAX的头,而后台在处理的时候也做了判断:
function is_pjax(){
return array_key_exists('HTTP_X_PJAX', $_SERVER)
&& $_SERVER['HTTP_X_PJAX'] === 'true';
}并不是一定要求在header头部中加入X_PJAX的信息,你也可以在url中加入相关的参数,比如:http://example.com?pjax=1,或者其他方式,只要前后端达到一个共识就行。

三、开源的PJAX库

已经有人对这个东西做了封装,我就不重复造轮子了。

welefen封装的库,对jquery、qwrap和kissy都做了封装,github地址

Yahoo团队 PJAX地址

并不是页面中所有的链接都需要使用PJAX加载,所有在需要这个东西的a标签上加一个属性,如data-pjax=true,然后统一添加事件。

四、注意事项

如果浏览器不支持pushState接口函数,那就只能退化为ajax或者使用hash bang了~

本地环境下使用的话,浏览器会报错:`Uncaught SecurityError: A history state object with URL file:///E:/baidu_app/demo/PJAX/pic-2' cannot be created in a document with origin 'null'. ,所以如果你要测试的话,请把代码丢到服务器上!

为了得到更好的体验,PJAX经常配合localStorage来使用,把请求到的内容缓存到本地,再一次请求的时候先从本地查看。如果你的内容是动态变化的,缓存的时候加一个缓存时间,方便更新缓存。

还有一个容易忽略的东西是统计,使用PJAX只会局部刷新页面,如果忽略了对统计函数的更新,那就会让你失去很多数据。

五、参考资料
 
http://www.welefen.com/pjax-fo ... .html   welefen
http://ntotten.com/2012/04/09/ ... pjax/   Nathan Totten
http://yuilibrary.com/yui/docs/pjax/   YUI Pjax 查看全部
一、前言

web发展经历了一个漫长的周期,最开始很多人认为Javascript这们语言是前端开发的累赘,是个鸡肋,那个时候人们还享受着从一个a链接蹦到另一个页面的web神奇魔术。后来随着JavaScript的不断更新换代,他的功能不仅仅是为网页添加一点特效了,语言本身的加强以及对DOM操作能力的提升让他在前端大放光彩。尤其是ajax的出现,让JavaScript以及整个web的发展翻开了崭新的一页。

利用ajax局部刷新页面,相信很多人玩得相当熟练了。如果整个页面的刷新都是使用ajax,我们可以称之为一个webapp,所有的逻辑都是在当页处理,这种形式的页面带来的体验是十分不错的,减少了那些比较“冗余”的页面跳转、新开页面等。不过,webapp的代码是十分不好维护的,页面逻辑太多太深,出点小问题,整个页面就会瘫痪,而且不方便定位bug,可维护性很低。

二、PJAX的实现与应用

1.场景再现-ajax弊端

ajax是一个非常好玩的小东西,不过用起来也会存在一些问题。

我们可以利用ajax进行无刷新改变文档内容,但是没办法去修改URL,有童鞋要问,这里为什么一定要修改URL呢?一个URL代表一个特定的网络资源,ajax修改了页面的内容,所以用不同的URL去标识他们,这个还是挺有必要的。

比如我们设计了一个单词查询的页面,比较合理的UR应该是http://example.com/word,不同的word对应不同的内容,但是如果整个页面都是ajax实现,我们就没法去修改/word了,当然我们可以使用hash如http://example.com#word,但这样就不能很好的处理浏览器的前进和后退问题。如:在页面中查询了单词A的翻译,接着又查询了单词B,这个时候浏览器的浏览历史会生成http://example.com#Ahttp://example.com#B两个记录,可是当我们从B转回A的时候,AJAX的效果还停留在B的状态(页面显示的还是单词B的翻译)。部分浏览器对此问题引入了onhashchange的接口,只要URL的hash值发生变化,我们的程序就可以监听并做出相应。不过对于那些木有这个接口的浏览器,就得定时去判断hash的变化了。

而这样的方式对搜索引擎是十分不友好的,twitter和google约定使用hash bang (#!xxx),也就是hash后面的第一个字符为感叹号,这样的网址他们是会爬取的,但是其他搜索引擎不支持。PJAX可以在改变页面内容的同时也改变他的URL,下面来说说PJAX和他的应用。

2.什么是PJAX

history API中有几个新特性,分别是history.pushState和history.replaceState,我们把pushState+AJAX进行封装,合起来简单点叫,就是PJAX~ 虽说实现技术上没什么新东西,但是概念上还是有所不同的。

PJAX的基本思路是,用户点击一个链接,通过ajax更新页面变化的部分,然后使用HTML5的pushState修改浏览器的URL地址,这样有效地避免了整个页面的重新加载。如果浏览器不支持history的两个新API或者JS被禁用了,那这个链接就只能跳转并重新刷新整个页面了。和传统的ajax设计稍微不同,ajax通常是从后台获取JSON数据,然后由前端解析渲染,而PJAX请求的是一个在服务器上生成好的HTML碎片,如下图所示:
111.jpg


客户端向服务器发送一个普通的请求(1),其实也就是点击了一个链接,服务器会相应这个请求(2),返回一个html文档。客户端向服务器发送一个有PJAX标志的请求(3),此时服务器只返回一个html碎片(4)。但是这两次请求都让客户端的URL变化了,希望上面的说明可以让你明白了PAJX和AJAX的区别了。

3.PJAX的实现

先看一个小DEMO吧,这个DEMO也写了我半个多小时,看之前先说明一下,打开你的现代浏览器(chrome,Firefox,opera,IE9+等),进入gallery页面,查看图片的时候注意观察浏览器的title和url变化,点击前进后退按钮也注意查看其变化。我已经在浏览历史管理中push了三条历史记录。

DEMO地址:http://qianduannotes.duapp.com ... .html

如果你还没有理解上面说的PJAX和AJAX的区别,看完这个demo,你应该有所领悟吧!在URL变化之后,页面并没有刷新,而是继续完成自己的动画(demo中为fadeOut)。

在HTML4,Histroy对象有下面属性方法:

length:历史堆栈中的记录数。

back():返回上一页。

forward():前进到下一页。

go([delta]):delta是个数字,如果不写或为0,则刷新本页;如果为正数,则前进到相应数目的页面;若为负数,则后退到相应数目的页面。

在HTML5中,新增了两个方法:

pushState(data, title [, url]):往历史堆栈的顶部添加一条记录。data为一个对象或null,它会在触发window的popstate事件(window.onpopstate)时,作为参数的state属性传递过去;title为页面的标题,但当前所有浏览器都忽略这个参数;url为页面的URL,不写则为当前页。

replaceState(data, title [, url]):更改当前页面的历史记录。参数同上。这种更改并不会去访问该URL。

当点击“上一张”、“下一张”这两个链接的时候,首先通过pushState修改URL以及修改document.title,那这个时候你就可以当做文档已经进入了另外一个链接了,然后该干什么干什么。demo中是让图片fadeOut,fadeOut完了之后让浏览器去加载资源,这个步骤就是正常的AJAX操作啦,没有什么特殊之处了~

因为只准备了三张图片,所有后台写的也比较简单:
<?phperror_reporting(false);$num = $_GET['num'];if(array_key_exists('HTTP_X_PJAX', $_SERVER) && $_SERVER['HTTP_X_PJAX'] === 'true'){    if($num == 1) {?>
<div class="imgwrap">
<img src="./images/1.jpg" />
</div>
<span><a href="num=2" class="next">下一张>></a></span>
<?php
} else if ($num == 2) {?>
<div class="imgwrap">
<img src="./images/2.jpg" />
</div>
<span><a href="num=1" class="previous"><<上一张</a>
<a href="num=3" class="next">下一张>></a></span>
<?php
} else {?>
<div class="imgwrap">
<img src="./images/3.jpg" />
</div>
<span><a href="num=2" class="previous"><<上一张</a></span>
<?php
}
}?>
上面那张图中,我们看到了,并不是每个连接都使用PJAX来加载,如果有X_PJAX标识,我们才会添加相应的处理。js中稍加注意可以看到:
$.ajax({
"url": "./interface.php",
"data": {
"num": num
},
"dataType": "html",
"headers": {
"X_PJAX": true
}
});
请求中:
Accept:text/html, */*; q=0.01
Accept-Encoding:gzip,deflate,sdch
Connection:keep-alive
Host:qianduannotes.duapp.com
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
X-Requested-With:XMLHttpRequest
X_PJAX:true
我在请求的header中加了一个X_PJAX的头,而后台在处理的时候也做了判断:
function is_pjax(){
return array_key_exists('HTTP_X_PJAX', $_SERVER)
&& $_SERVER['HTTP_X_PJAX'] === 'true';
}
并不是一定要求在header头部中加入X_PJAX的信息,你也可以在url中加入相关的参数,比如:http://example.com?pjax=1,或者其他方式,只要前后端达到一个共识就行。

三、开源的PJAX库

已经有人对这个东西做了封装,我就不重复造轮子了。

welefen封装的库,对jquery、qwrap和kissy都做了封装,github地址

Yahoo团队 PJAX地址

并不是页面中所有的链接都需要使用PJAX加载,所有在需要这个东西的a标签上加一个属性,如data-pjax=true,然后统一添加事件。

四、注意事项

如果浏览器不支持pushState接口函数,那就只能退化为ajax或者使用hash bang了~

本地环境下使用的话,浏览器会报错:`Uncaught SecurityError: A history state object with URL file:///E:/baidu_app/demo/PJAX/pic-2' cannot be created in a document with origin 'null'. ,所以如果你要测试的话,请把代码丢到服务器上!

为了得到更好的体验,PJAX经常配合localStorage来使用,把请求到的内容缓存到本地,再一次请求的时候先从本地查看。如果你的内容是动态变化的,缓存的时候加一个缓存时间,方便更新缓存。

还有一个容易忽略的东西是统计,使用PJAX只会局部刷新页面,如果忽略了对统计函数的更新,那就会让你失去很多数据。

五、参考资料
 
http://www.welefen.com/pjax-fo ... .html   welefen
http://ntotten.com/2012/04/09/ ... pjax/   Nathan Totten
http://yuilibrary.com/yui/docs/pjax/   YUI Pjax

github如何发起一个push request注意事项

软件工程atool 发表了文章 • 0 个评论 • 999 次浏览 • 2016-04-22 13:11 • 来自相关话题

github发起一个push request步骤

1、在 Fork 的代码库中添加上游代码库的 remote 源,该操作只需操作一次即可。

如: 其中# upstream 表示上游代码库名, 可以任意。
git remote add upstream git@github.com:hustcc/dig_hash.git2、将本地的修改提交 commit

3、在每次 Pull Request 前做如下操作,即可实现和上游版本库的同步。

3.1 更新源项目的代码到最新 
git remote update upstream3.2 rebase最新代码

注意在rebase之前,将自己项目切换到对应的branch,如:
git checkout develop然后:
git rebase upstream/{branch name}需要注意的是在操作3.2之前,一定要将checkout到{branch name}所指定的branch,如:
git checkout develop4、 Push 代码到 Github
git push origin {branch name}5、push request
到github网页上发起push request即可。 查看全部
github发起一个push request步骤

1、在 Fork 的代码库中添加上游代码库的 remote 源,该操作只需操作一次即可。

如: 其中# upstream 表示上游代码库名, 可以任意。
git remote add upstream git@github.com:hustcc/dig_hash.git
2、将本地的修改提交 commit

3、在每次 Pull Request 前做如下操作,即可实现和上游版本库的同步。

3.1 更新源项目的代码到最新 
git remote update upstream
3.2 rebase最新代码

注意在rebase之前,将自己项目切换到对应的branch,如:
git checkout develop
然后:
git rebase upstream/{branch name}
需要注意的是在操作3.2之前,一定要将checkout到{branch name}所指定的branch,如:
git checkout develop
4、 Push 代码到 Github
git push origin {branch name}
5、push request
到github网页上发起push request即可。

【微信公众平台改版后】Java模拟登录微信平台,主动推送消息给用户

企业开发atool 发表了文章 • 2 个评论 • 1768 次浏览 • 2016-04-22 13:08 • 来自相关话题

一、简要说明

在博文《Java模拟登录微信公众平台,主动推送图文消息给用户》中提到使用Java语言登录微信公众平台,然后发送图文消息给用户,基本可以符合使用要求,但是在今年10月23日,微信公众平台的界面有所变化,所以,上一篇博文的代码不再适用,很多朋友留言,不能使用了怎么办,这篇文章针对新版本做了处理,并且加入了新的功能,代码上要感谢trprebel这位朋友。

再备注:如果遇到获取粉丝返回-1的问题,有需要的给这个网友发邮件。 yyn_0210@sina.com

二、代码功能和要求

*.new Weixin()对象,先登录再取粉丝数和者发消息;
*.发消息需要设置post参数中的content;
*.内容中的超链接可以直接发送不用使用标签;
*.经过我(trprebel)修改之后,此份代码可在2013年11月之后使用;
*.我只做了获取粉丝列表和发送消息,其他部分未做;
*.理论上可以获取到粉丝的地址,签名等一切你登陆可以得到的信息;
*.另外可能需要你在本机先登陆过至少一次微信公众平台获取SSL证书;
*.此份代码作者较多,函数前面都有作者名,我只修改了登陆,获取粉丝列表和发送消息;
*.其他代码可能已经不能用了但我并没有删除,方便大家扩展,我做的也比较粗糙,没整理;
*.另外,腾讯3天之内又加了一条限制,粉丝24小时之内没有主动说话,微信公众平台不能主动与其说话,官方平台登陆也不行;

使用到的库:commons-codec-1.3.jar、commons-httpclient-3.1.jar、commons-lang.jar、commons-logging-1.0.4.jar、fastjson-1.1.15.jar、gson-2.2.4.jar、httpclient-4.1.3.jar、httpcore-4.1.4.jar、jsoup-1.5.2.jar

环境:JDK1.6

三、代码下载

使用的库请自己下载,源代码如下附件,如果使用有任何的问题,请直接回复博文即可...

四、核心代码和说明

Weixin.java模拟请求的链接及结构
public final static String HOST = "http://mp.weixin.qq.com";
public final static String LOGIN_URL = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String INDEX_URL = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String SENDMSG_URL = "https://mp.weixin.qq.com/cgi-bin/singlesend";
public final static String FANS_URL = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String LOGOUT_URL = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String DOWNLOAD_URL = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String VERIFY_CODE = "http://mp.weixin.qq.com/cgi-bin/verifycode?";
public final static String POST_MSG = "https://mp.weixin.qq.com/cgi-b ... 3B%3B
public final static String VIEW_HEAD_IMG = "http://mp.weixin.qq.com/cgi-bin/viewheadimg";
public final static String GET_IMG_DATA = "http://mp.weixin.qq.com/cgi-bin/getimgdata";
public final static String GET_REGIONS = "http://mp.weixin.qq.com/cgi-bin/getregions";
public final static String GET_MESSAGE = "http://mp.weixin.qq.com/cgi-bin/getmessage";
public final static String OPER_ADVANCED_FUNC = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String MASSSEND_PAGE = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String FILE_MANAGE_PAGE = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String OPERATE_APPMSG = "https://mp.weixin.qq.com/cgi-b ... 3B%3B
public final static String FMS_TRANSPORT = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
// public final static String CONTACT_MANAGE_PAGE =
// "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String CONTACT_MANAGE_PAGE = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String OPER_SELF_MENU = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String REPLY_RULE_PAGE = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String SINGLE_MSG_PAGE = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String USER_INFO_PAGE = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String DEV_APPLY = "http://mp.weixin.qq.com/cgi-bin/devapply";
public final static String UPLOAD_MATERIAL = "https://mp.weixin.qq.com/cgi-b ... 3B%3B
/**
* 登录,登录失败会重复请求登录
*/
public void login() {}
/**
* 发送登录信息,记录cookie,登录状态,token等信息
*/
private boolean _login() {}
/**
* 从登录成功的信息中分离出token信息
*/
private String getToken(String s) {}
/**
* 获取首页
* @throws HttpException
* @throws IOException
*/
public void index() throws HttpException, IOException {}
/**
* 登出操作
* @throws HttpException
* @throws IOException
*/
public void logout() throws HttpException, IOException {}
/**
* 获取验证码
* @throws HttpException
* @throws IOException
*/
public InputStream code() throws HttpException, IOException {}
/**
* 获取粉丝列表,返回粉丝数量,出错则返回-1
*/
public int getFans() {}
/**
* 从返回文本中提取粉丝数量
*/
private int parseFansCount(String text) {}
/**
* 解析粉丝列表,将粉丝列表存入List<fan>
*/
private int parseFans(String text) {}
/**
* <strong>群发消息</strong>
* 返回码说明
* 0:发送成功
* 64004:今天的群发数量已到,无法群发
* -20000:请求被禁止,请仔细检查token是否合法
* 可通过msgSendCode取得发送状态码
*/
public boolean msgSend(MsgForm form, MsgType type) {}
/**
* 向粉丝发送消息,默认发送第二个粉丝,想不受限制的群发可以循环向粉丝列表中的粉丝发送消息
*/
public boolean sendMsg(int i) {}
public void updateImg(ImgFileForm form) {}
/**
* 页面跳转
*/
public void redirect(String url) {}
//使用样例说明
public static void main(String[] args) {
String LOGIN_USER = "knight.ding@gmail.com"; // 此为上一任作者的用户名和密码,截止到我最后用发现还能用
String LOGIN_PWD = "AAbb1122";
Weixin wx = new Weixin(LOGIN_USER, LOGIN_PWD);
wx.login();
wx.getCookiestr();
// ImgFileForm form = new ImgFileForm();
// form.setUploadfile(new File("D:Dataimage4.jpg"));
// wx.updateImg(form);
System.out.println("粉丝数:" + wx.getFans());
wx.sendMsg(1);// 像好友列表中的第几个好友发消息,从0开始
}
Enjoy~~~如果能帮助到你,请回复博文或者分享给他人,谢谢~ 查看全部
一、简要说明

在博文《Java模拟登录微信公众平台,主动推送图文消息给用户》中提到使用Java语言登录微信公众平台,然后发送图文消息给用户,基本可以符合使用要求,但是在今年10月23日,微信公众平台的界面有所变化,所以,上一篇博文的代码不再适用,很多朋友留言,不能使用了怎么办,这篇文章针对新版本做了处理,并且加入了新的功能,代码上要感谢trprebel这位朋友。

再备注:如果遇到获取粉丝返回-1的问题,有需要的给这个网友发邮件。 yyn_0210@sina.com

二、代码功能和要求

*.new Weixin()对象,先登录再取粉丝数和者发消息;
*.发消息需要设置post参数中的content;
*.内容中的超链接可以直接发送不用使用标签;
*.经过我(trprebel)修改之后,此份代码可在2013年11月之后使用;
*.我只做了获取粉丝列表和发送消息,其他部分未做;
*.理论上可以获取到粉丝的地址,签名等一切你登陆可以得到的信息;
*.另外可能需要你在本机先登陆过至少一次微信公众平台获取SSL证书;
*.此份代码作者较多,函数前面都有作者名,我只修改了登陆,获取粉丝列表和发送消息;
*.其他代码可能已经不能用了但我并没有删除,方便大家扩展,我做的也比较粗糙,没整理;
*.另外,腾讯3天之内又加了一条限制,粉丝24小时之内没有主动说话,微信公众平台不能主动与其说话,官方平台登陆也不行;

使用到的库:commons-codec-1.3.jar、commons-httpclient-3.1.jar、commons-lang.jar、commons-logging-1.0.4.jar、fastjson-1.1.15.jar、gson-2.2.4.jar、httpclient-4.1.3.jar、httpcore-4.1.4.jar、jsoup-1.5.2.jar

环境:JDK1.6

三、代码下载

使用的库请自己下载,源代码如下附件,如果使用有任何的问题,请直接回复博文即可...

四、核心代码和说明

Weixin.java模拟请求的链接及结构
public final static String HOST = "http://mp.weixin.qq.com";
public final static String LOGIN_URL = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String INDEX_URL = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String SENDMSG_URL = "https://mp.weixin.qq.com/cgi-bin/singlesend";
public final static String FANS_URL = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String LOGOUT_URL = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String DOWNLOAD_URL = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String VERIFY_CODE = "http://mp.weixin.qq.com/cgi-bin/verifycode?";
public final static String POST_MSG = "https://mp.weixin.qq.com/cgi-b ... 3B%3B
public final static String VIEW_HEAD_IMG = "http://mp.weixin.qq.com/cgi-bin/viewheadimg";
public final static String GET_IMG_DATA = "http://mp.weixin.qq.com/cgi-bin/getimgdata";
public final static String GET_REGIONS = "http://mp.weixin.qq.com/cgi-bin/getregions";
public final static String GET_MESSAGE = "http://mp.weixin.qq.com/cgi-bin/getmessage";
public final static String OPER_ADVANCED_FUNC = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String MASSSEND_PAGE = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String FILE_MANAGE_PAGE = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String OPERATE_APPMSG = "https://mp.weixin.qq.com/cgi-b ... 3B%3B
public final static String FMS_TRANSPORT = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
// public final static String CONTACT_MANAGE_PAGE =
// "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String CONTACT_MANAGE_PAGE = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String OPER_SELF_MENU = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String REPLY_RULE_PAGE = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String SINGLE_MSG_PAGE = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String USER_INFO_PAGE = "http://mp.weixin.qq.com/cgi-bi ... 3B%3B
public final static String DEV_APPLY = "http://mp.weixin.qq.com/cgi-bin/devapply";
public final static String UPLOAD_MATERIAL = "https://mp.weixin.qq.com/cgi-b ... 3B%3B
/**
* 登录,登录失败会重复请求登录
*/
public void login() {}
/**
* 发送登录信息,记录cookie,登录状态,token等信息
*/
private boolean _login() {}
/**
* 从登录成功的信息中分离出token信息
*/
private String getToken(String s) {}
/**
* 获取首页
* @throws HttpException
* @throws IOException
*/
public void index() throws HttpException, IOException {}
/**
* 登出操作
* @throws HttpException
* @throws IOException
*/
public void logout() throws HttpException, IOException {}
/**
* 获取验证码
* @throws HttpException
* @throws IOException
*/
public InputStream code() throws HttpException, IOException {}
/**
* 获取粉丝列表,返回粉丝数量,出错则返回-1
*/
public int getFans() {}
/**
* 从返回文本中提取粉丝数量
*/
private int parseFansCount(String text) {}
/**
* 解析粉丝列表,将粉丝列表存入List<fan>
*/
private int parseFans(String text) {}
/**
* <strong>群发消息</strong>
* 返回码说明
* 0:发送成功
* 64004:今天的群发数量已到,无法群发
* -20000:请求被禁止,请仔细检查token是否合法
* 可通过msgSendCode取得发送状态码
*/
public boolean msgSend(MsgForm form, MsgType type) {}
/**
* 向粉丝发送消息,默认发送第二个粉丝,想不受限制的群发可以循环向粉丝列表中的粉丝发送消息
*/
public boolean sendMsg(int i) {}
public void updateImg(ImgFileForm form) {}
/**
* 页面跳转
*/
public void redirect(String url) {}
//使用样例说明
public static void main(String[] args) {
String LOGIN_USER = "knight.ding@gmail.com"; // 此为上一任作者的用户名和密码,截止到我最后用发现还能用
String LOGIN_PWD = "AAbb1122";
Weixin wx = new Weixin(LOGIN_USER, LOGIN_PWD);
wx.login();
wx.getCookiestr();
// ImgFileForm form = new ImgFileForm();
// form.setUploadfile(new File("D:Dataimage4.jpg"));
// wx.updateImg(form);
System.out.println("粉丝数:" + wx.getFans());
wx.sendMsg(1);// 像好友列表中的第几个好友发消息,从0开始
}
Enjoy~~~如果能帮助到你,请回复博文或者分享给他人,谢谢~

华中科技大学第三届研究生红色楷模十佳特色党日活动——自动化学院

其他类型atool 发表了文章 • 0 个评论 • 469 次浏览 • 2016-04-22 13:06 • 来自相关话题

       华中科技大学第三届研究生红色楷模十佳特色党日活动——自动化学院

习近平总书记在参观《复兴之路》展览时指出:实现中华民族伟大复兴,就是中华民族近代以来最伟大的梦想!这一时代解读,既饱含着对近代以来中国历史的深刻洞悉,又彰显了全国各族人民的共同愿望和宏伟愿景,为党带领人民开创未来指明了前进方向。为了让广大研究生党员更好更透彻地领悟习总书记指出的“中国梦”的于党、于自身的含义,自动化学院特举办以“夏日繁星”为主题的特色党日活动。

浩瀚的星空总是给人无穷的遐想,也总是启迪和激励着人们去研究和探索未知的事物。而夏日里明亮的星辰又总是显得如此耀眼和浪漫,那一眨一眨的星光似乎在告诉着人们:这里才是未来的方向。“中国梦·学术情”这两个大主题,正如夏日里的星空一般,是如此的浩瀚与广阔,却也如此的闪亮和执着,正基于此,我们特将此次特色党日活动命名为“夏日繁星”。

本次特色党日活动是华中科技大学自动化学院成立后举办的第一次特党活动,活动由院党委、支部联合会、研究生会精心策划和筹办,活动主要分为“学术之星”评选、“学术之星”风采展示、自研智语优秀学子交流会等三个部分组成。活动内容严谨朴实却也不失趣味,让所有的研究生同学都能在活动过程中领悟“中国梦”于自身的意义,激励自己更加勤奋努力的学习,为实现中华民族伟大复兴的“中国梦”做出自己的贡献。

自动化学院成立不久,很多同学都不熟悉,很多制度还没来得及完全建立起来,在这样一个情况下,能够把大家召集起来参与这样一个活动是很不容易的。但是让我感到惊讶的是,虽然同学们各有各的忙,但是有一种莫名的凝聚力把我们凝聚在了一起。我深刻的感觉到我们这个支部的凝聚力和团队协作能力,要知道,无论是在学校还是将来出来工作的时候,团队协作的能力是十分重要的的,自己一个人完成工作除了会使自己更累之外,工作的结果也未必令人满意。只有同学之间或同事之间互相合作,为工作一起能力,一起出点子,才能将工作轻松且出色的完成。 查看全部
       华中科技大学第三届研究生红色楷模十佳特色党日活动——自动化学院

习近平总书记在参观《复兴之路》展览时指出:实现中华民族伟大复兴,就是中华民族近代以来最伟大的梦想!这一时代解读,既饱含着对近代以来中国历史的深刻洞悉,又彰显了全国各族人民的共同愿望和宏伟愿景,为党带领人民开创未来指明了前进方向。为了让广大研究生党员更好更透彻地领悟习总书记指出的“中国梦”的于党、于自身的含义,自动化学院特举办以“夏日繁星”为主题的特色党日活动。

浩瀚的星空总是给人无穷的遐想,也总是启迪和激励着人们去研究和探索未知的事物。而夏日里明亮的星辰又总是显得如此耀眼和浪漫,那一眨一眨的星光似乎在告诉着人们:这里才是未来的方向。“中国梦·学术情”这两个大主题,正如夏日里的星空一般,是如此的浩瀚与广阔,却也如此的闪亮和执着,正基于此,我们特将此次特色党日活动命名为“夏日繁星”。

本次特色党日活动是华中科技大学自动化学院成立后举办的第一次特党活动,活动由院党委、支部联合会、研究生会精心策划和筹办,活动主要分为“学术之星”评选、“学术之星”风采展示、自研智语优秀学子交流会等三个部分组成。活动内容严谨朴实却也不失趣味,让所有的研究生同学都能在活动过程中领悟“中国梦”于自身的意义,激励自己更加勤奋努力的学习,为实现中华民族伟大复兴的“中国梦”做出自己的贡献。

自动化学院成立不久,很多同学都不熟悉,很多制度还没来得及完全建立起来,在这样一个情况下,能够把大家召集起来参与这样一个活动是很不容易的。但是让我感到惊讶的是,虽然同学们各有各的忙,但是有一种莫名的凝聚力把我们凝聚在了一起。我深刻的感觉到我们这个支部的凝聚力和团队协作能力,要知道,无论是在学校还是将来出来工作的时候,团队协作的能力是十分重要的的,自己一个人完成工作除了会使自己更累之外,工作的结果也未必令人满意。只有同学之间或同事之间互相合作,为工作一起能力,一起出点子,才能将工作轻松且出色的完成。

xcode编译cocos2d-x 3.0及以上版本支持arm64位

游戏开发atool 发表了文章 • 0 个评论 • 2967 次浏览 • 2016-04-22 13:05 • 来自相关话题

在使用cocos2d-x 3.0rc lua版本完成游戏过程中,真机存在一个问题:

1. 使用iphone4s真机调试,可以正常运行通过;

2. 使用iphone4s以上版本真机调试的时候,不能够正常编译,出现的的错误是cc命名空间下的很多方法找不到,具体都是cocos2d-x的代码找不到。

虽然直接使用iphone4s连接手机,achieve出来的ipa包也可以在所有ios设备上运行,但是提交appstore的时候,就会出现错误:ERROR ITMS-90086:"missing 64-bit support. beginning on february 1, 2015, new iOS apps submitted to the app store must be include 64-bit support and be built with the ios8 SDK......"。




大致意思是app store从2015年2月1号开始,不再接受不支持64位的app上线。

解决办法如下:

1.将所有的cocos2d-x xcode项目的project和target中的building-setting设置项中的architectures、supported platforms、validarchitectures,另外非常重要的一个配置是build active architecture only全部设置为No。下图所示:




需要修改p2,cocos2d_lua_bindings.xcodeproj, cocos2d_libs.xcodeproj三个项目中的building-setting。如下图所示:




修改之后,就会发现之前出现的“cc命名空间下的很多方法找不到”的错误都消失了,出现的都是关于图片读取的问题,这个问题解决见步骤2;

2.因为cocos2d-x3.0rc版本没有将图片相关的64位库加入,引入相关的图片读取解析的64位库;如下图所示:




具体就是上述中_arm64.a结尾的库。

上述问题解决了,但是又出现lua里面的方法找不到的错误,解决办法见步骤3;

3.由于cocos2d-x3.0rc使用的是luajit,但是只引入了libluagit.a库,这个库是32位的,所以无法编译64位,于是找到一个liblua.a的库,引入lua.a到项目即可。如下图:




三步完成,问题全部解决,打包,重签,测试,没有任何问题。

Enjoy~
  查看全部
在使用cocos2d-x 3.0rc lua版本完成游戏过程中,真机存在一个问题:

1. 使用iphone4s真机调试,可以正常运行通过;

2. 使用iphone4s以上版本真机调试的时候,不能够正常编译,出现的的错误是cc命名空间下的很多方法找不到,具体都是cocos2d-x的代码找不到。

虽然直接使用iphone4s连接手机,achieve出来的ipa包也可以在所有ios设备上运行,但是提交appstore的时候,就会出现错误:ERROR ITMS-90086:"missing 64-bit support. beginning on february 1, 2015, new iOS apps submitted to the app store must be include 64-bit support and be built with the ios8 SDK......"。
111.png

大致意思是app store从2015年2月1号开始,不再接受不支持64位的app上线。

解决办法如下:

1.将所有的cocos2d-x xcode项目的project和target中的building-setting设置项中的architectures、supported platforms、validarchitectures,另外非常重要的一个配置是build active architecture only全部设置为No。下图所示:
222.png

需要修改p2,cocos2d_lua_bindings.xcodeproj, cocos2d_libs.xcodeproj三个项目中的building-setting。如下图所示:
333.png

修改之后,就会发现之前出现的“cc命名空间下的很多方法找不到”的错误都消失了,出现的都是关于图片读取的问题,这个问题解决见步骤2;

2.因为cocos2d-x3.0rc版本没有将图片相关的64位库加入,引入相关的图片读取解析的64位库;如下图所示:
444.png

具体就是上述中_arm64.a结尾的库。

上述问题解决了,但是又出现lua里面的方法找不到的错误,解决办法见步骤3;

3.由于cocos2d-x3.0rc使用的是luajit,但是只引入了libluagit.a库,这个库是32位的,所以无法编译64位,于是找到一个liblua.a的库,引入lua.a到项目即可。如下图:
555.png

三步完成,问题全部解决,打包,重签,测试,没有任何问题。

Enjoy~
 

Cocos2d-x 3.0修改Android平台帧率fps - 解决游戏运行手机发热发烫问题

游戏开发atool 发表了文章 • 2 个评论 • 2829 次浏览 • 2016-04-22 13:01 • 来自相关话题

使用Cocos2d-x 3.0开发游戏之后,发现游戏在android手机上发热非常严重,在魅族2上,几乎担心手机会爆炸了~~~采取的一个措施就是降低帧率,因为游戏对于帧率要求不是非常高。

做过cocos2d开发的同学应该都知道在win32平台修改帧率的方式非常简单,就是在AppDelegate.cpp文件中修改:
director->setAnimationInterval(1.0 / 40);但是这种修改方式在导出android安卓apk到真机测试的时候,发现左下角的调试信息还是现实60~65帧,完全不受影响,网上搜索之后,发小安卓的修改需要修改cocos2dx-x生成的java代码中修改,具体在文件:Cocos2dxRenderer.java

在代码中可以看到以下的属性设置和重写的方法:
private static long sAnimationInterval = (long) (1.0 / 60 * Cocos2dxRenderer.NANOSECONDSPERSECOND);
public void onDrawFrame(final GL10 gl) {}如果要修改android平台的帧率,可以通过修改这些代码来改进,具体的操作方法如下:

1.修改帧率将60改成40
private static long sAnimationInterval = (long) (1.0 / 40 * Cocos2dxRenderer.NANOSECONDSPERSECOND);
2.增加一个属性变量
private long renderingElapsedTime = 0;3.重写渲染方法onDrawFrame
@Override
public void onDrawFrame(final GL10 gl) {
try {
if (renderingElapsedTime * NANOSECONDSPERMICROSECOND < Cocos2dxRenderer.sAnimationInterval) {
Thread.sleep((Cocos2dxRenderer.sAnimationInterval - renderingElapsedTime * NANOSECONDSPERMICROSECOND) / NANOSECONDSPERMICROSECOND);
}
} catch (InterruptedException e) {
e.printStackTrace();
}

// Get the timestamp when rendering started
long renderingStartedTimestamp = System.currentTimeMillis();

// should render a frame when onDrawFrame() is called or there is a
// "ghost"
Cocos2dxRenderer.nativeRender();

// Calculate the elapsed time during rendering
renderingElapsedTime = (System.currentTimeMillis() - renderingStartedTimestamp);
}代码中将渲染消耗的时间算进去,所以得到的帧率应该来说非常准确了。

注意,Cocos2dxRenderer中的onDrawFrame官方有实现好的帧率算法,但是被注释掉了,注释文本说存在一定的bug,帧率不精确,实际上大部分情况都可已正常使用,所以最好不要采用了~

这么做了之后,游戏的帧率在38~41左右,发热的问题也基本解决了。

最后,如果你要更好,更精确的帧率算法,也可以留言回复... 查看全部
使用Cocos2d-x 3.0开发游戏之后,发现游戏在android手机上发热非常严重,在魅族2上,几乎担心手机会爆炸了~~~采取的一个措施就是降低帧率,因为游戏对于帧率要求不是非常高。

做过cocos2d开发的同学应该都知道在win32平台修改帧率的方式非常简单,就是在AppDelegate.cpp文件中修改:
director->setAnimationInterval(1.0 / 40);
但是这种修改方式在导出android安卓apk到真机测试的时候,发现左下角的调试信息还是现实60~65帧,完全不受影响,网上搜索之后,发小安卓的修改需要修改cocos2dx-x生成的java代码中修改,具体在文件:Cocos2dxRenderer.java

在代码中可以看到以下的属性设置和重写的方法:
private static long sAnimationInterval = (long) (1.0 / 60 * Cocos2dxRenderer.NANOSECONDSPERSECOND);
public void onDrawFrame(final GL10 gl) {}
如果要修改android平台的帧率,可以通过修改这些代码来改进,具体的操作方法如下:

1.修改帧率将60改成40
private static long sAnimationInterval = (long) (1.0 / 40 * Cocos2dxRenderer.NANOSECONDSPERSECOND);
2.增加一个属性变量
private long renderingElapsedTime = 0;
3.重写渲染方法onDrawFrame
@Override
public void onDrawFrame(final GL10 gl) {
try {
if (renderingElapsedTime * NANOSECONDSPERMICROSECOND < Cocos2dxRenderer.sAnimationInterval) {
Thread.sleep((Cocos2dxRenderer.sAnimationInterval - renderingElapsedTime * NANOSECONDSPERMICROSECOND) / NANOSECONDSPERMICROSECOND);
}
} catch (InterruptedException e) {
e.printStackTrace();
}

// Get the timestamp when rendering started
long renderingStartedTimestamp = System.currentTimeMillis();

// should render a frame when onDrawFrame() is called or there is a
// "ghost"
Cocos2dxRenderer.nativeRender();

// Calculate the elapsed time during rendering
renderingElapsedTime = (System.currentTimeMillis() - renderingStartedTimestamp);
}
代码中将渲染消耗的时间算进去,所以得到的帧率应该来说非常准确了。

注意,Cocos2dxRenderer中的onDrawFrame官方有实现好的帧率算法,但是被注释掉了,注释文本说存在一定的bug,帧率不精确,实际上大部分情况都可已正常使用,所以最好不要采用了~

这么做了之后,游戏的帧率在38~41左右,发热的问题也基本解决了。

最后,如果你要更好,更精确的帧率算法,也可以留言回复...

Error Domain=AVFoundationErrorDomain Code=-11800 "这项操作无法完成"

移动开发atool 发表了文章 • 0 个评论 • 3775 次浏览 • 2016-04-22 12:59 • 来自相关话题

在iOS上开发视频操作的时候,出现错误:

Error Domain=AVFoundationErrorDomain Code=-11800 "这项操作无法完成"UserInfo=0x1780fb480 {NSUnderlyingError=0x1706495d0 "The operation couldn’t be completed. (OSStatus error -12673.)", NSLocalizedFailureReason=发生未知错误(-12673), AVErrorRecordingSuccessfullyFinishedKey=false, NSLocalizedDescription=这项操作无法完成},file:///var/mobile/Applications/D0CA65C7-F218-46F1-80BC-B0FA886EDF3B/video.mov

具体是使用AVFoundation录制使用,然后保存再文件中。

产生错误:Error Domain=AVFoundationErrorDomain Code=-11800 "这项操作无法完成"的原因都是因为存储的文件路径NSURL有问题。即使你打印出来没有什么问题,但是就是报错,确实蛋疼。

解决办法,重写输出文件的路径NSURL。给一个例子:
// 初始化保存的路径
NSString *documentsDirPath =[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSURL *documentsDirUrl = [NSURL fileURLWithPath:documentsDirPath isDirectory:YES];
self.saveMovieFile = [NSURL URLWithString:@"video.mp4" relativeToURL:documentsDirUrl];当然,在使用这个路径之前,记得先检查这个文件是否存在,如果存在则先删除文件,否则会报另外一个错误。
Enjoy~
  查看全部
在iOS上开发视频操作的时候,出现错误:

Error Domain=AVFoundationErrorDomain Code=-11800 "这项操作无法完成"UserInfo=0x1780fb480 {NSUnderlyingError=0x1706495d0 "The operation couldn’t be completed. (OSStatus error -12673.)", NSLocalizedFailureReason=发生未知错误(-12673), AVErrorRecordingSuccessfullyFinishedKey=false, NSLocalizedDescription=这项操作无法完成},file:///var/mobile/Applications/D0CA65C7-F218-46F1-80BC-B0FA886EDF3B/video.mov

具体是使用AVFoundation录制使用,然后保存再文件中。

产生错误:Error Domain=AVFoundationErrorDomain Code=-11800 "这项操作无法完成"的原因都是因为存储的文件路径NSURL有问题。即使你打印出来没有什么问题,但是就是报错,确实蛋疼。

解决办法,重写输出文件的路径NSURL。给一个例子:
// 初始化保存的路径
NSString *documentsDirPath =[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSURL *documentsDirUrl = [NSURL fileURLWithPath:documentsDirPath isDirectory:YES];
self.saveMovieFile = [NSURL URLWithString:@"video.mp4" relativeToURL:documentsDirUrl];
当然,在使用这个路径之前,记得先检查这个文件是否存在,如果存在则先删除文件,否则会报另外一个错误。
Enjoy~
 

小黄鸡SimSimi API以及小i机器人的说明——如何免费使用?

移动开发atool 发表了文章 • 0 个评论 • 3837 次浏览 • 2016-04-22 12:57 • 来自相关话题

一、什么是Simsimi?

simsimi公司是提供智能服务,其中一个服务是simsimi聊天机器人服务,每天有超过百万的用户聊天,国内最大的搜索引擎——百度的产品siri使用的就是simsimi提供的api。

你可以在网址http://www.simsimi.com/talk.htm# 进行体验

SimSimi inc. is specialized in collective intelligence service. All kinds of services we provide generates unique entertainment and values through systemized collective intelligence.

One of our services, a chatting robot SimSimi exceeds the limitation of technology of natural-language processing system by collective intelligence and it has a chat with over millions user per day. Our Premium knowledge providing service “Jisikman” creates millions of valuable knowledges a day.

We invite you to our realm of service which is available through our cloud of collective intelligence, Crowd Cloud that SimSimi inc. creates.

二、Simsimi小黄鸡API

在去年的这个时候,小黄鸡的非官方api一度被大家疯狂的在微信公众号上使用,一时间不知道成就了多少微信营销号,同时,华科某位大四学生利用这个api,结合人人网开发平台,制作了一个小黄鸡的人人号,@小黄鸡之后,就可以利用api自动进行回复,是的这个人人号瞬间粉丝陡增。

然而大家使用的都是非官方的API,所谓非官方,就是不是simsimi公司提供的合法使用途径,API大致的原理是利用编程语言,模拟浏览器发送post请求到http://www.simsimi.com/talk.htm# 链接,解析响应,然后作成相关的小黄鸡API。这个方法后来被我在本博客中在博文中发布,导致使用人数激增,simsimi公司似乎察觉了什么,立马对这种模拟请求的方式做出了屏蔽,一旦某ip请求数量和频率超过限制,则终端对它的请求。正式官方对非法API的封锁,也使用国内的开发这关注到之前并不出名的小i机器人,同样使用语言模拟请求web聊天界面,时间没有过很久,这个页面就加入了图片验证码防止程序模拟。

至此,两个聊天机器人都走上了收费的道路...准确的说,应该是被这帮子开发者赶上了收费的道路,因为他们给它带来了知名度。

三、SimsimiAPI使用




目前,小黄鸡API已经公然收费(http://developer.simsimi.com/api)
不过,和之前一样,会给注册用户提供30天的试用API。
API请求链接为:
Trial-key    http://sandbox.api.simsimi.com/request.p
Paid-key    http://api.simsimi.com/request.p

API请求参数见官网。
 
API返回格式为:

result:100-ok. 400-Bad Request. 401-Unauthorized. 404-Not found. 500-Server Error.    返回的code

id:Response id. (you can get only if returning result is 100)回复的id,由系统生成,当请求成功返回时才有这个字段。 

response:Response message(you can get only if returning result is 100)返回的回复内容。

msg:Result  msg(Description of result code) 返回的code对应的含义

四、Simsimi使用举例

请求举例:

Trial-key    http://sandbox.api.simsimi.com ... %3Dhi   
Paid-key    http://api.simsimi.com/request ... %3Dhi

响应举例:

{ "result": 100, "response": "Who are you?!", "id": 13185569, "msg": "OK." }

五、如何免费的使用Simsimi API

我想,大家都懂了,写这篇文章的原因就是很多人搜索小黄鸡 api到我的博客,我想大家都是要找免费的小黄鸡API。这里提供给大家一个思路:
 
合作伙伴中,有人人网,为什么?本博文前面提高某大四学生做了一个人人号,@小黄鸡之后,会自动进行回复,他使用的就是simsimi的官方正版付费API,既然人人网提供开发平台,可以对帐号进行回复,获得回复等等操作,为什么不能使用程序,登录帐号,然后@小黄鸡,然后获得它的回复,再返回给你自己的用户呢?答案当然是可以的!!!

下面贴出一段可供参考的Java代码,之所以为仅供参考,就是说只能参考思路,代码运行是运行不起来的!!!如果能够帮助到你,希望回复点评一下,并点点广告,你懂的...
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
/**
* 利用httpclient操作人人网 比如登陆,发状态,模拟你访问任何人主页等等
* @author: http://50vip.com
*
*/
public class RenRen {
private String userName = "";
private String password = "";

private static String redirectURL = "http://www.renren.com/home";
private static String renRenLoginURL = "http://www.renren.com/PLogin.do";
private static String talkUrl = "http://photo.renren.com/photo/ ... 3B%3B
private HttpResponse response;
private DefaultHttpClient httpclient = null;
private String requestToken = null;
private String _rtk = null;

public RenRen(String userName, String password) {
this.userName = userName;
this.password = password;
}

public static void main(String[] args) {
RenRen rr = null;
rr = new RenRen("xxxxx@hotmail.com", "yyyyy");
rr.login();
System.out.println(rr.talk("820"));
}
/**
* 登陆
* @author: http://50vip.com
* @return
*/
public boolean login() {
if (httpclient != null) {
return true;
}
httpclient = null;
httpclient = new DefaultHttpClient();
HttpPost httpost = new HttpPost(renRenLoginURL);
// All the parameters post to the web site
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("origURL", redirectURL));
nvps.add(new BasicNameValuePair("domain", "renren.com"));
nvps.add(new BasicNameValuePair("autoLogin", "true"));
nvps.add(new BasicNameValuePair("formName", ""));
nvps.add(new BasicNameValuePair("method", ""));
nvps.add(new BasicNameValuePair("submit", "登录"));
nvps.add(new BasicNameValuePair("email", userName));
nvps.add(new BasicNameValuePair("password", password));
try {
httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
response = httpclient.execute(httpost);
//System.out.println(response);
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
httpost.abort();
}

String redirectLocation = getRedirectLocation();
if (redirectLocation != null) {
// 跳到首页,登录完成
String indexHtml=getText(redirectLocation);

//获取requestToken get_check:'-2062261917'
Pattern pattern1 = Pattern.compile("get_check:'(.*)',get_check_x");
Matcher m1 = pattern1.matcher(indexHtml);
if (m1.find()) {
requestToken=m1.group(1);
} else {
System.out.println("获取requestToken失败!");
}

//"获取_rtk失败!"get_check_x:'50d55fbd'
Pattern pattern2 = Pattern.compile("get_check_x:'(.*)',env:");
Matcher m2 = pattern2.matcher(indexHtml);
if (m2.find()) {
_rtk=m2.group(1);
} else {
System.out.println("获取_rtk失败!");
}
}
return true;
}

/**
* 和人人的小黄鸡交谈
* @author: http://50vip.com
* @param msg
* @return
*/
public String talk(String msg) {
String repMsg="";//小黄的回复

HttpPost httpost = new HttpPost(talkUrl);
// All the parameters post to the web site
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("_rtk", _rtk));
nvps.add(new BasicNameValuePair("requestToken", requestToken));
nvps.add(new BasicNameValuePair("message", msg));

try {
ResponseHandler<String> responseHandler = new BasicResponseHandler();
httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
repMsg=httpclient.execute(httpost, responseHandler);
} catch (Exception e) {
e.printStackTrace();
} finally {
httpost.abort();
}
return repMsg;
}

/**
* 此处人人网会302跳转
* @author: http://50vip.com
* @return
*/
private String getRedirectLocation() {
Header locationHeader = response.getFirstHeader("Location");
if (locationHeader == null) {
return null;
}
return locationHeader.getValue();
}

/**
* 读取首页内容
* @author: http://50vip.com
* @param redirectLocation
* @return
*/
private String getText(String redirectLocation) {
HttpGet httpget = new HttpGet(redirectLocation);
// Create a response handler
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseBody = "";
try {
responseBody = httpclient.execute(httpget, responseHandler);
} catch (Exception e) {
e.printStackTrace();
responseBody = null;
} finally {
httpget.abort();
}
return responseBody;
}
} 查看全部
一、什么是Simsimi?

simsimi公司是提供智能服务,其中一个服务是simsimi聊天机器人服务,每天有超过百万的用户聊天,国内最大的搜索引擎——百度的产品siri使用的就是simsimi提供的api。

你可以在网址http://www.simsimi.com/talk.htm# 进行体验

SimSimi inc. is specialized in collective intelligence service. All kinds of services we provide generates unique entertainment and values through systemized collective intelligence.

One of our services, a chatting robot SimSimi exceeds the limitation of technology of natural-language processing system by collective intelligence and it has a chat with over millions user per day. Our Premium knowledge providing service “Jisikman” creates millions of valuable knowledges a day.

We invite you to our realm of service which is available through our cloud of collective intelligence, Crowd Cloud that SimSimi inc. creates.

二、Simsimi小黄鸡API

在去年的这个时候,小黄鸡的非官方api一度被大家疯狂的在微信公众号上使用,一时间不知道成就了多少微信营销号,同时,华科某位大四学生利用这个api,结合人人网开发平台,制作了一个小黄鸡的人人号,@小黄鸡之后,就可以利用api自动进行回复,是的这个人人号瞬间粉丝陡增。

然而大家使用的都是非官方的API,所谓非官方,就是不是simsimi公司提供的合法使用途径,API大致的原理是利用编程语言,模拟浏览器发送post请求到http://www.simsimi.com/talk.htm# 链接,解析响应,然后作成相关的小黄鸡API。这个方法后来被我在本博客中在博文中发布,导致使用人数激增,simsimi公司似乎察觉了什么,立马对这种模拟请求的方式做出了屏蔽,一旦某ip请求数量和频率超过限制,则终端对它的请求。正式官方对非法API的封锁,也使用国内的开发这关注到之前并不出名的小i机器人,同样使用语言模拟请求web聊天界面,时间没有过很久,这个页面就加入了图片验证码防止程序模拟。

至此,两个聊天机器人都走上了收费的道路...准确的说,应该是被这帮子开发者赶上了收费的道路,因为他们给它带来了知名度。

三、SimsimiAPI使用
13845160832840.jpg

目前,小黄鸡API已经公然收费(http://developer.simsimi.com/api
不过,和之前一样,会给注册用户提供30天的试用API。
API请求链接为:
Trial-key    http://sandbox.api.simsimi.com/request.p
Paid-key    http://api.simsimi.com/request.p

API请求参数见官网。
 
API返回格式为:

result:100-ok. 400-Bad Request. 401-Unauthorized. 404-Not found. 500-Server Error.    返回的code

id:Response id. (you can get only if returning result is 100)回复的id,由系统生成,当请求成功返回时才有这个字段。 

response:Response message(you can get only if returning result is 100)返回的回复内容。

msg:Result  msg(Description of result code) 返回的code对应的含义

四、Simsimi使用举例

请求举例:

Trial-key    http://sandbox.api.simsimi.com ... %3Dhi   
Paid-key    http://api.simsimi.com/request ... %3Dhi

响应举例:

{ "result": 100, "response": "Who are you?!", "id": 13185569, "msg": "OK." }

五、如何免费的使用Simsimi API

我想,大家都懂了,写这篇文章的原因就是很多人搜索小黄鸡 api到我的博客,我想大家都是要找免费的小黄鸡API。这里提供给大家一个思路:
 
合作伙伴中,有人人网,为什么?本博文前面提高某大四学生做了一个人人号,@小黄鸡之后,会自动进行回复,他使用的就是simsimi的官方正版付费API,既然人人网提供开发平台,可以对帐号进行回复,获得回复等等操作,为什么不能使用程序,登录帐号,然后@小黄鸡,然后获得它的回复,再返回给你自己的用户呢?答案当然是可以的!!!

下面贴出一段可供参考的Java代码,之所以为仅供参考,就是说只能参考思路,代码运行是运行不起来的!!!如果能够帮助到你,希望回复点评一下,并点点广告,你懂的...
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
/**
* 利用httpclient操作人人网 比如登陆,发状态,模拟你访问任何人主页等等
* @author: http://50vip.com
*
*/
public class RenRen {
private String userName = "";
private String password = "";

private static String redirectURL = "http://www.renren.com/home";
private static String renRenLoginURL = "http://www.renren.com/PLogin.do";
private static String talkUrl = "http://photo.renren.com/photo/ ... 3B%3B
private HttpResponse response;
private DefaultHttpClient httpclient = null;
private String requestToken = null;
private String _rtk = null;

public RenRen(String userName, String password) {
this.userName = userName;
this.password = password;
}

public static void main(String[] args) {
RenRen rr = null;
rr = new RenRen("xxxxx@hotmail.com", "yyyyy");
rr.login();
System.out.println(rr.talk("820"));
}
/**
* 登陆
* @author: http://50vip.com
* @return
*/
public boolean login() {
if (httpclient != null) {
return true;
}
httpclient = null;
httpclient = new DefaultHttpClient();
HttpPost httpost = new HttpPost(renRenLoginURL);
// All the parameters post to the web site
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("origURL", redirectURL));
nvps.add(new BasicNameValuePair("domain", "renren.com"));
nvps.add(new BasicNameValuePair("autoLogin", "true"));
nvps.add(new BasicNameValuePair("formName", ""));
nvps.add(new BasicNameValuePair("method", ""));
nvps.add(new BasicNameValuePair("submit", "登录"));
nvps.add(new BasicNameValuePair("email", userName));
nvps.add(new BasicNameValuePair("password", password));
try {
httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
response = httpclient.execute(httpost);
//System.out.println(response);
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
httpost.abort();
}

String redirectLocation = getRedirectLocation();
if (redirectLocation != null) {
// 跳到首页,登录完成
String indexHtml=getText(redirectLocation);

//获取requestToken get_check:'-2062261917'
Pattern pattern1 = Pattern.compile("get_check:'(.*)',get_check_x");
Matcher m1 = pattern1.matcher(indexHtml);
if (m1.find()) {
requestToken=m1.group(1);
} else {
System.out.println("获取requestToken失败!");
}

//"获取_rtk失败!"get_check_x:'50d55fbd'
Pattern pattern2 = Pattern.compile("get_check_x:'(.*)',env:");
Matcher m2 = pattern2.matcher(indexHtml);
if (m2.find()) {
_rtk=m2.group(1);
} else {
System.out.println("获取_rtk失败!");
}
}
return true;
}

/**
* 和人人的小黄鸡交谈
* @author: http://50vip.com
* @param msg
* @return
*/
public String talk(String msg) {
String repMsg="";//小黄的回复

HttpPost httpost = new HttpPost(talkUrl);
// All the parameters post to the web site
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
nvps.add(new BasicNameValuePair("_rtk", _rtk));
nvps.add(new BasicNameValuePair("requestToken", requestToken));
nvps.add(new BasicNameValuePair("message", msg));

try {
ResponseHandler<String> responseHandler = new BasicResponseHandler();
httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
repMsg=httpclient.execute(httpost, responseHandler);
} catch (Exception e) {
e.printStackTrace();
} finally {
httpost.abort();
}
return repMsg;
}

/**
* 此处人人网会302跳转
* @author: http://50vip.com
* @return
*/
private String getRedirectLocation() {
Header locationHeader = response.getFirstHeader("Location");
if (locationHeader == null) {
return null;
}
return locationHeader.getValue();
}

/**
* 读取首页内容
* @author: http://50vip.com
* @param redirectLocation
* @return
*/
private String getText(String redirectLocation) {
HttpGet httpget = new HttpGet(redirectLocation);
// Create a response handler
ResponseHandler<String> responseHandler = new BasicResponseHandler();
String responseBody = "";
try {
responseBody = httpclient.execute(httpget, responseHandler);
} catch (Exception e) {
e.printStackTrace();
responseBody = null;
} finally {
httpget.abort();
}
return responseBody;
}
}

使用Java给微信公众号创建自定义的菜单

编程语言atool 发表了文章 • 0 个评论 • 1541 次浏览 • 2016-04-22 12:53 • 来自相关话题

最近一段时间,微信公众平台做了很多的改进啊~

微信目前将公众帐号分成服务号和订阅号两种,之前的微信公众号默认为订阅号,不过有一次机会可以自由选择,两者之间各有优劣:

服务号每月只能推送一条消息,不过消息是显示在消息列表中,并有消息提示;订阅号每天有一条消息推送,不过消息不显示在消息列表,没有消息提示。

除此之外,目前微信公众号可以自定义菜单,下面将介绍如果使用Java作一个微信公众号的菜单,参考API可到官网查看:http://mp.weixin.qq.com/wiki/index.php?title=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E6%8E%A5%E5%8F%A3
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import org.json.JSONObject;

public class MenuUtil {
/**
* 获得ACCESS_TOKEN
* @Title: getAccess_token
* @Description: 获得ACCESS_TOKEN
* @param @return 设定文件
* @return String 返回类型
* @throws
*/
private static String getAccess_token(){

String APPID="";
String APPSECRET="";

String url = "https://api.weixin.qq.com/cgi- ... 3B%2B APPID + "&secret=" +APPSECRET;
String accessToken = null;
try {
URL urlGet = new URL(url);
HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();

http.setRequestMethod("GET"); //必须是get方式请求
http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
http.setDoOutput(true);
http.setDoInput(true);
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");//连接超时30秒
System.setProperty("sun.net.client.defaultReadTimeout", "30000"); //读取超时30秒

http.connect();

InputStream is =http.getInputStream();
int size =is.available();
byte[] jsonBytes =new byte[size];
is.read(jsonBytes);
String message=new String(jsonBytes,"UTF-8");

JSONObject demoJson = new JSONObject(message);
accessToken = demoJson.getString("access_token");

System.out.println(message);
} catch (Exception e) {
e.printStackTrace();
}
return accessToken;
}

/**
* 创建Menu
* @Title: createMenu
* @Description: 创建Menu
* @param @return
* @param @throws IOException 设定文件
* @return int 返回类型
* @throws
*/
public static String createMenu() {
String menu = "{\"button\":[{\"type\":\"click\",\"name\":\"MENU01\",\"key\":\"1\"},{\"type\":\"click\",\"name\":\"天气查询\",\"key\":\"西安\"},{\"name\":\"日常工作\",\"sub_button\":[{\"type\":\"click\",\"name\":\"待办工单\",\"key\":\"01_WAITING\"},{\"type\":\"click\",\"name\":\"已办工单\",\"key\":\"02_FINISH\"},{\"type\":\"click\",\"name\":\"我的工单\",\"key\":\"03_MYJOB\"},{\"type\":\"click\",\"name\":\"公告消息箱\",\"key\":\"04_MESSAGEBOX\"},{\"type\":\"click\",\"name\":\"签到\",\"key\":\"05_SIGN\"}]}]}";

//此处改为自己想要的结构体,替换即可
String access_token= getAccess_token();

String action = "https://api.weixin.qq.com/cgi- ... en%3B
try {
URL url = new URL(action);
HttpURLConnection http = (HttpURLConnection) url.openConnection();

http.setRequestMethod("POST");
http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
http.setDoOutput(true);
http.setDoInput(true);
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");//连接超时30秒
System.setProperty("sun.net.client.defaultReadTimeout", "30000"); //读取超时30秒

http.connect();
OutputStream os= http.getOutputStream();
os.write(menu.getBytes("UTF-8"));//传入参数
os.flush();
os.close();

InputStream is =http.getInputStream();
int size =is.available();
byte[] jsonBytes =new byte[size];
is.read(jsonBytes);
String message=new String(jsonBytes,"UTF-8");
return "返回信息"+message;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "createMenu 失败";
}

/**
* 删除当前Menu
* @Title: deleteMenu
* @Description: 删除当前Menu
* @param @return 设定文件
* @return String 返回类型
* @throws
*/
public static String deleteMenu()
{
String access_token= getAccess_token();
String action = "https://api.weixin.qq.com/cgi-bin/menu/delete? access_token="+access_token;
try {
URL url = new URL(action);
HttpURLConnection http = (HttpURLConnection) url.openConnection();

http.setRequestMethod("GET");
http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
http.setDoOutput(true);
http.setDoInput(true);
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");//连接超时30秒
System.setProperty("sun.net.client.defaultReadTimeout", "30000"); //读取超时30秒

http.connect();
OutputStream os= http.getOutputStream();
os.flush();
os.close();

InputStream is =http.getInputStream();
int size =is.available();
byte[] jsonBytes =new byte[size];
is.read(jsonBytes);
String message=new String(jsonBytes,"UTF-8");
return "deleteMenu返回信息:"+message;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "deleteMenu 失败";
}

public static void main(String[] args) {
System.out.println(createMenu());
}
}代码来源于:http://www.oschina.net/code/snippet_945711_24355 ,后续会做PHP版,并加入到自己的微信公众号上面,我的微信公众号二维码见右侧。Enjoy~ 查看全部
最近一段时间,微信公众平台做了很多的改进啊~

微信目前将公众帐号分成服务号和订阅号两种,之前的微信公众号默认为订阅号,不过有一次机会可以自由选择,两者之间各有优劣:

服务号每月只能推送一条消息,不过消息是显示在消息列表中,并有消息提示;订阅号每天有一条消息推送,不过消息不显示在消息列表,没有消息提示。

除此之外,目前微信公众号可以自定义菜单,下面将介绍如果使用Java作一个微信公众号的菜单,参考API可到官网查看:http://mp.weixin.qq.com/wiki/index.php?title=%E8%87%AA%E5%AE%9A%E4%B9%89%E8%8F%9C%E5%8D%95%E6%8E%A5%E5%8F%A3
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

import org.json.JSONObject;

public class MenuUtil {
/**
* 获得ACCESS_TOKEN
* @Title: getAccess_token
* @Description: 获得ACCESS_TOKEN
* @param @return 设定文件
* @return String 返回类型
* @throws
*/
private static String getAccess_token(){

String APPID="";
String APPSECRET="";

String url = "https://api.weixin.qq.com/cgi- ... 3B%2B APPID + "&secret=" +APPSECRET;
String accessToken = null;
try {
URL urlGet = new URL(url);
HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();

http.setRequestMethod("GET"); //必须是get方式请求
http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
http.setDoOutput(true);
http.setDoInput(true);
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");//连接超时30秒
System.setProperty("sun.net.client.defaultReadTimeout", "30000"); //读取超时30秒

http.connect();

InputStream is =http.getInputStream();
int size =is.available();
byte[] jsonBytes =new byte[size];
is.read(jsonBytes);
String message=new String(jsonBytes,"UTF-8");

JSONObject demoJson = new JSONObject(message);
accessToken = demoJson.getString("access_token");

System.out.println(message);
} catch (Exception e) {
e.printStackTrace();
}
return accessToken;
}

/**
* 创建Menu
* @Title: createMenu
* @Description: 创建Menu
* @param @return
* @param @throws IOException 设定文件
* @return int 返回类型
* @throws
*/
public static String createMenu() {
String menu = "{\"button\":[{\"type\":\"click\",\"name\":\"MENU01\",\"key\":\"1\"},{\"type\":\"click\",\"name\":\"天气查询\",\"key\":\"西安\"},{\"name\":\"日常工作\",\"sub_button\":[{\"type\":\"click\",\"name\":\"待办工单\",\"key\":\"01_WAITING\"},{\"type\":\"click\",\"name\":\"已办工单\",\"key\":\"02_FINISH\"},{\"type\":\"click\",\"name\":\"我的工单\",\"key\":\"03_MYJOB\"},{\"type\":\"click\",\"name\":\"公告消息箱\",\"key\":\"04_MESSAGEBOX\"},{\"type\":\"click\",\"name\":\"签到\",\"key\":\"05_SIGN\"}]}]}";

//此处改为自己想要的结构体,替换即可
String access_token= getAccess_token();

String action = "https://api.weixin.qq.com/cgi- ... en%3B
try {
URL url = new URL(action);
HttpURLConnection http = (HttpURLConnection) url.openConnection();

http.setRequestMethod("POST");
http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
http.setDoOutput(true);
http.setDoInput(true);
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");//连接超时30秒
System.setProperty("sun.net.client.defaultReadTimeout", "30000"); //读取超时30秒

http.connect();
OutputStream os= http.getOutputStream();
os.write(menu.getBytes("UTF-8"));//传入参数
os.flush();
os.close();

InputStream is =http.getInputStream();
int size =is.available();
byte[] jsonBytes =new byte[size];
is.read(jsonBytes);
String message=new String(jsonBytes,"UTF-8");
return "返回信息"+message;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "createMenu 失败";
}

/**
* 删除当前Menu
* @Title: deleteMenu
* @Description: 删除当前Menu
* @param @return 设定文件
* @return String 返回类型
* @throws
*/
public static String deleteMenu()
{
String access_token= getAccess_token();
String action = "https://api.weixin.qq.com/cgi-bin/menu/delete? access_token="+access_token;
try {
URL url = new URL(action);
HttpURLConnection http = (HttpURLConnection) url.openConnection();

http.setRequestMethod("GET");
http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
http.setDoOutput(true);
http.setDoInput(true);
System.setProperty("sun.net.client.defaultConnectTimeout", "30000");//连接超时30秒
System.setProperty("sun.net.client.defaultReadTimeout", "30000"); //读取超时30秒

http.connect();
OutputStream os= http.getOutputStream();
os.flush();
os.close();

InputStream is =http.getInputStream();
int size =is.available();
byte[] jsonBytes =new byte[size];
is.read(jsonBytes);
String message=new String(jsonBytes,"UTF-8");
return "deleteMenu返回信息:"+message;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return "deleteMenu 失败";
}

public static void main(String[] args) {
System.out.println(createMenu());
}
}
代码来源于:http://www.oschina.net/code/snippet_945711_24355 ,后续会做PHP版,并加入到自己的微信公众号上面,我的微信公众号二维码见右侧。Enjoy~

amcharts图表避免遮挡或重叠横坐标值斜着、竖着、间隔显示

前端开发atool 发表了文章 • 0 个评论 • 1149 次浏览 • 2016-04-22 12:49 • 来自相关话题

amCharts是一个致力于图表组件开发的公司,公司地址在立陶宛首都维尔纽斯,2004年开始推出图表和地图组件。截至目前,amCharts提供了JavaScript/HTML5 Charts、Javascript/HTML5 Stock Chart、JavaScript Maps三种图表组件。amCharts图形效果炫丽,得到了广大使用者的青睐,amCharts的用户遍布全球各地,不乏Microsoft, Cisco, NASA, Motorola之类的行业巨头。

amCharts在1.x版本是基于flash实现,目前2.x版本改为Javascript/HTML5实现,显得更轻量。效果如下所示:




 
针对问题:amcharts图表避免遮挡或重叠横坐标值斜着、竖着、间隔显示,如下所示:categoryAxis.labelRotation = 90; //竖着显示
categoryAxis.labelRotation = 60; //斜着显示
categoryAxis.autoGridCount = false; //自动间隔横坐标显示另外,有时候需要在图表最上面加一个显示区间的滑动条SCROLLBARvar chartScrollbar = new AmCharts.ChartScrollbar();
chart.addChartScrollbar(chartScrollbar); 查看全部
amCharts是一个致力于图表组件开发的公司,公司地址在立陶宛首都维尔纽斯,2004年开始推出图表和地图组件。截至目前,amCharts提供了JavaScript/HTML5 Charts、Javascript/HTML5 Stock Chart、JavaScript Maps三种图表组件。amCharts图形效果炫丽,得到了广大使用者的青睐,amCharts的用户遍布全球各地,不乏Microsoft, Cisco, NASA, Motorola之类的行业巨头。

amCharts在1.x版本是基于flash实现,目前2.x版本改为Javascript/HTML5实现,显得更轻量。效果如下所示:
5351375266081.png

 
针对问题:amcharts图表避免遮挡或重叠横坐标值斜着、竖着、间隔显示,如下所示:
categoryAxis.labelRotation = 90; //竖着显示
categoryAxis.labelRotation = 60; //斜着显示
categoryAxis.autoGridCount = false; //自动间隔横坐标显示
另外,有时候需要在图表最上面加一个显示区间的滑动条SCROLLBAR
var chartScrollbar = new AmCharts.ChartScrollbar();
chart.addChartScrollbar(chartScrollbar);