-
使用新浪云 Java 环境搭建一个简单的微信处理后台
前一段时间,写了一篇在新浪云上搭建自己的网站的教程,通过简单构建了一个 maven 的项目,展示部署的整个流程,具体的操作可以参看这里。
新浪云服务器除了可以搭建自己的网站以外,也非常的适合作为微信公众号回调地址来使用(熟悉微信公众号开发的朋友可能已经了解了,如果不太清楚请参看微信公众平台),微信公众号的开发需要一个公网可以访问的服务器,用于处理消息的 token 的验证,以及自身业务的定制开发。在这里,写了一些简单操作的例子,给大家参考。
准备
开发微信公众号首先要申请自己的公众号,或者获得相关需要开发的公众号的操作权限,如何申请,这里就不具体讲了,具体的流程大家可以参看微信公众号的申请流程,需要注意的是自己的 AppID 和自己的 AppSecret ,不要泄漏,还需要自己设置一个 token 令牌,这里还有一个消息的加密密钥 EncodingAESKey ,可以随机生成,用于消息的加密解密。如下图所示:
这里 URL 填写在新浪云申请的服务器的地址,当然具体指向到那个 path 我们需要自己去写一个 servlet,这里我自己定义了一个 WX 的 servlet,令牌我自己定义了一个,消息加密密钥使用了系统随机生成的,为了便于开发,所以消息加密方式,使用了明文的方式,这样消息就可以直观的看到,在填写完这些配置之后,在提交之后,微信的服务器会发一个 get 请求到我们填写的 URL 地址,去验证下 token,所以这里我们就预先要将这个 servlet 写好,简单的验证一步 token(代码会在下面列出),当验证通过后,修改才会成功,点击启用后,微信的服务器才会将客户端的消息,发送到我们提供的服务器。这里有具体的 接入指南。
我在我的项目中建立了一个叫 WX 的 servlet。添加了如下的代码。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String sig = request.getParameter("signature"); String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); String token = "xxxx"; // 这里填写自己的 token List<String> list = new ArrayList<String>(); list.add(nonce); list.add(token); list.add(timestamp); Collections.sort(list); String hash = getHash(list.get(0)+list.get(1)+list.get(2), "SHA-1"); if(sig.equals(hash)){ // 验证下签名是否正确 response.getWriter().println(echostr); }else{ response.getWriter().println(""); } } public String getHash(String source, String hashType) { StringBuilder sb = new StringBuilder(); MessageDigest md5; try { md5 = MessageDigest.getInstance(hashType); md5.update(source.getBytes()); for (byte b : md5.digest()) { sb.append(String.format("%02x", b)); } return sb.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return null; }
在验证完成后, 原样返回 echostr 字符串就行了。这样填写服务器配置之后就可以成功的保存配置了。注意需要点击启用微信才会将客户端的消息转发给自己的服务器。
以上这个环节条中通过之后,我们来处理下消息,根据消息的输入做一些简单的返回,比如输入 hello 返回特定的字符串,返回定义的字符串,输入 time,返回当前的时间。这里要注意,咱们服务器接受的请求是由微信的服务器 post 过来的,所以,我们的处理过程要写在 doPost 方法里。
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String sig = request.getParameter("signature"); System.out.println("sig : "+sig); String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); String token = "nero"; String responseContent = defaultStr; List<String> list = new ArrayList<String>(); list.add(nonce); list.add(token); list.add(timestamp); Collections.sort(list); String hash = getHash(list.get(0)+list.get(1)+list.get(2), "SHA-1").toLowerCase(); if(sig.equals(hash)){ if(request.getMethod().equals("POST")){ Map<String,String> map = XMLParse.extract(convertStreamToString(request.getInputStream())); if(map.get("Content").equals("hello")){ responseContent = "Hello,This message from SinaCloud"; } if(map.get("Content").equals("time")){ sf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); responseContent = sf.format(new Date()); } responseMsg = formatResponseMsg(responseContent, map); } response.setCharacterEncoding("utf-8"); response.getWriter().println(responseMsg); }else{ response.getWriter().println("success"); } } public String convertStreamToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } public String formatResponseMsg(String content,Map map){ String responseMsg = "<xml>" + "<ToUserName><![CDATA[%1$s]]></ToUserName>" + "<FromUserName><![CDATA[%2$s]]></FromUserName>" + "<CreateTime>%3$s</CreateTime>" + "<MsgType><![CDATA[%4$s]]></MsgType>" + "<Content><![CDATA[%5$s]]></Content>" + "<MsgId>%6$s</MsgId>" + "</xml>"; return String.format(responseMsg, map.get("FromUserName"),map.get("ToUserName"),map.get("CreateTime"),map.get("MsgType"),content,map.get("MsgId")); }
以上的代码就是处理的大概的过程,处理的效果如下。
以上就是使用新浪云大概搭建一个微信处理的后端程序,简单的实现了一些文本信息的交互功能,以后有时间继续写点其他消息的交互过程。
-
如何在新浪云上部署一个 Hubot 机器人
What is Hubot? Hubot is your company's robot. Install him in your company to dramatically improve and reduce employee efficiency.
Hubot 是 GitHub 开源的一个聊天机器人,可以用来在公司的在线聊天室(Slack、Campfire、Bearychat 等)里接受指令并完成一些自动化的工作(比如运维中重启机器、查看机器信息等)。
下文我们以 Hubot + Bearychat 为例,一步一步说明一下如何在新浪云上部署一个 Hubot 机器人。
创建一个新 bot
首先,按照 Hubot 官方文档的说明,使用 yo 创建一个新的 Hubot 项目。
$ npm install -g hubot coffee-script yo generator-hubot $ cd /path/to/hubot $ yo hubot
yo 提示输入 Bot adapter 时,输入 bearychat ,yo 会自动安装完 Hubot 以及 Bearychat adapter 所有相关的依赖包。
本地运行
进入 Hubot 代码目录,执行以下命令进入一个本地调试的命令行。检查调试 Hubot 功能是否 OK。
$ cd /path/to/hubot $ bin/hubot
部署到线上
进入新浪云的控制台,创建一个新的云应用,语言选择 NodeJS。
进入 Bearychat 的机器人管理页面,选择添加一个 Hubot 机器人,在 Hubot URL 框里填入应用的 URL 地址。复制 Hubot Token ,进入新浪云应用控制台的 应用/环境变量 页面,创建一个新的环境变量。变量名为 HUBOT_BEARYCHAT_TOKENS ,值为刚才复制过来的 Token 。
最后我们进入刚才创建好的 Hubot 目录中,执行以下命令将代码部署到线上。
$ git remote add origin https://git.sinacloud.com/应用名 $ git push -u origin master
完成,现在,我们可以在 Bearychat 里调戏一把我们新加的 Hubot 机器人了。
给机器人添加新的命令
给 Hubot 添加新的命令非常的简单,在 scripts 目录下建一个 .coffee 或者 .js 结尾的文件,按照 scripts/example.coffee 中的示例添加你自己需要的命令即可。
参考:
-
手把手教你用新浪云容器 Java 搭建自己的网站
经过一段时间的开发,更新,迭代,新浪云容器 Java 环境逐渐成熟起来,相比过去的 Java 运行环境,可用性和易用性都得到了大量的提升。同时也收到了不少用户反馈的使用问题,特此在这篇文章里综合介绍一下容器 Java 使用以及相关服务的整合。
环境说明
新浪云容器 Java 环境基于 Docker 搭建,支持多实例负载均衡,近乎原生虚拟机环境,使用无门槛。
- JDK 1.8
- Web 容器 tomcat-8.0.35
注意:这里以后可能会提供相应的 Web 容器定制服务
准备
开发自己的应用之前,我们先要准备好自己的开发环境,新浪云的容器 Java 应用所需的环境和一般开发环境类似。
- JDK(最好是能与线上同步,当然低版本也可以) version:1.7 以上
- 开发 IDE(推荐 eclipse,有相应的开发插件,能够快速上传) version:eclipse(Mars.1 Release (4.5.1) 此版本自带了 maven 插件,不需要另装了)
- maven(推荐使用,能够方便使用新浪云提供的 sdk) version:3.3.9
安装方式就不累述了,各个环境下如何安装配置,大家可以自行用百度谷歌一下
创建初始化应用
首先我们要创建自己的新浪云账号,这个就不累述了,具体参看新浪云。
然后我们来着手建立一个 maven 的项目,当然我们可以通过 maven 的命令来创建一个项目,不过我们有 IDE,可以方便的利用可视化界面操作,而且也方便使用插件。
好了,我们打开 Eclipse,接下来我们就开始创建自己的 Web 项目,点击"File"->"New"->"Maven project",如下图
然后点击"Next",注意接下来选择的"Archetype",咱们是 Web 项目,所以一定要选择"maven-archetype-webapp",如下图
然后点击"Next",填写 Group Id 和 Artifact Id,然后在点击"Finish"。
然后咱们的项目就建好了,目录结构如下图,接下来我们就开始开发我们自己的项目
首先我们建立一下源码目录,在 src->main 下面新建一个文件夹 java,然后就可以看到如图的应用结构了
这里还有一个注意的地方,建立好新的 maven 项目之后,可能需要一些简单的配置,如果默认配置好了可以忽略了,主要注意两个方面的配置,一是 Servlet 版本,一是 JDK 版本,以及项目结构。
改下 JDK,点击项目右键 ->proerties->java compile,如下图
将 JDK 版本调整为 1.7 以上以匹配线上版本。
在修改下项目的结构,如下图。点击 Project Facet,修改下 Java 的版本和刚刚修改的版本一致。
修改下 Dynamic Web Module,改成 3.1 版本(如果点击下面提示无法改变版本的话,就先反选 Dynamic Web Module 然后确定,在重新进入这个界面在勾选即可修改)。如下图
注意图中的标注位置,点击进去,配置一下 Web 目录,如下图
将我们建立项目的 Web 目录配置下。
最后,我们在来安装下新浪云的 Eclipse 插件,具体安装的方法参见使用 Eclipse 插件部署 Java 应用。
至此,我们开发前的准备工作就完成了,接下来我们可以开始开发了。
接下来的 Web 应用就可以根据自己的业务需求开始开发,就不说具体的开发过程了,下面着重介绍下新浪云相关服务的使用方法和注意事项。 我们先来建立一个 Servlet,通过这个 Servlet 来演示相关功能的展示,建立一个如下图的 package 在建立一个名为 test 的 Servlet。
然后可以通过 Eclipse 插件将应用上传到新浪云,插件使用见使用 Eclipse 插件部署 Java 应用,也就是你刚刚创建的应用,注意填写相关的信息。部署时间大约为 3 分钟,然后可以在浏览器里访问我们创建的 servlet 了,如下图。
这样,我们的 Servlet 的就建立好了,接下来我们的演示就基于这个 Servlet 展开介绍。
MySQL
新浪云的数据库服务有两种,一种是共享型数据库,一种是独享型数据库,但其实操作方式都是一样的,具体参看相关文档。以共享型数据库为例子吧,通过 jdbc 方式即可连接。
首先,在新浪云控制面板中创建自己的共享型 mysql 实例,然后在pom.xml里添加下 jdbc 驱动
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.20</version> </dependency>
然后,在咱们刚刚创建的 Serlvet 中,添加如下代码。
String driver = "com.mysql.jdbc.Driver"; String username = System.getenv("ACCESSKEY"); String password = System.getenv("SECRETKEY"); String dbName = System.getenv("MYSQL_DB"); String host = System.getenv("MYSQL_HOST"); String port = System.getenv("MYSQL_PORT"); String dbUrl = "jdbc:mysql://"+host+":"+port + "/" +dbName; try { Class.forName(driver); Connection conn = DriverManager.getConnection(dbUrl,username,password); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("show status"); while(rs.next()){ response.getWriter().println(rs.getString("Variable_name") + " : " +rs.getString("value")); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }
通过插件在上传到你的应用上,稍等一会就能看到如下的效果。
这里只是展示了最基本的使用方法,有些项目中会使用连接池,连接池只需要注意一项,将 idle 时间调整到 10 秒以下即可,无论是独享型还是共享型都是如此。
Memcached
Memcached 服务同样也要在你创建的应用中开启面板,初始化一下。容器使用的 memcache 有 auth 认证,需要使用支持 SASL 协议的客户端,推荐使用spymemcached客户端,首先在pom.xml文件中添加如下依赖。
<dependency> <groupId>net.spy</groupId> <artifactId>spymemcached</artifactId> <version>2.12.0</version> </dependency>
同样,我们在刚刚我们新建的 servlet 中添加如下的代码。
String username = System.getenv("ACCESSKEY"); String password = System.getenv("SECRETKEY"); String server = System.getenv("MEMCACHE_SERVERS"); AuthDescriptor ad = new AuthDescriptor(new String[] { "PLAIN" }, new PlainCallbackHandler(username, password)); MemcachedClient mc = new MemcachedClient( new ConnectionFactoryBuilder().setProtocol(Protocol.BINARY).setAuthDescriptor(ad).build(), AddrUtil.getAddresses(server)); OperationFuture<Boolean> of = mc.set("key", 0, "sinacloud"); try { response.setCharacterEncoding("gbk"); response.getWriter().println("设置结果是否成功:"+ of.get()); response.getWriter().println("获取结果:"+mc.get("key")); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); }
上传服务器后效果如下
这里只是简单的实现了 set 和 get 方法,其他的可以参看 spymemcached。
Redis
新浪云 Redis 服务,类似于 Memcache 服务,先在pom.xml里添加一个 redis 的客户端,如 jedis
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.0.0</version> </dependency>
然后还是在刚刚建立的 Servlet 里添加如下代码。
String redis_url = System.getenv("REDIS_URL"); try { URI redisUri = new URI(redis_url); JedisPool pool = new JedisPool(new JedisPoolConfig(),redisUri.getHost(),redisUri.getPort(),Protocol.DEFAULT_TIMEOUT,redisUri.getUserInfo().split(":",2)[1]); Jedis jedis = pool.getResource(); response.getWriter().println(jedis.set("key".getBytes(), "sinacloud".getBytes())); response.getWriter().println(jedis.get("key")); } catch (URISyntaxException e) { e.printStackTrace(); }
最后上传到新浪云上,可以看到效果。如下图。
MongoDB
首先还是在pom.xml中添加一下依赖。
<dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>3.2.2</version> </dependency>
同时也需要在面板里初始化服务。然后可以根据自己的需要在 mongodb 实例中创建库或者是集合,我自己建立了一个叫"test"的库,然后建立了一个叫"users"的集合。
还是在那个 servlet 中插入如下的代码。
MongoClientURI uri = new MongoClientURI("YOUR_MONGODB_URL"); MongoClient client = new MongoClient(uri); MongoDatabase db = client.getDatabase("test"); MongoCollection<Document> users = db.getCollection("users"); Document user = new Document("key", "sinacloud"); users.insertOne(user); response.getWriter().println(users.find(user).iterator().next().get("key"));
然后上传到新浪云,可以看到如下结果
存储服务
这里还是在上面建立的那个 Servlet 演示操作。对于容器 Java,我们提供了一套 SDK 支持,相关存储的操作,SDK 已经放在了 maven 的中央仓库上,可以通过 maven 进行下载,在项目的pom.xml中添加如下依 赖。
<dependency> <groupId>com.sinacloud.java</groupId> <artifactId>java-sdk</artifactId> <version>1.2.1</version> </dependency>
目前,SDK 里包含了 kvdb(已经在 1.2.2 版本中去除)、云存储、Storage,以后新的服务,会在不断的增加。
Storage
Storage 服务是新浪云开发的一套对象存储服务,首先也要在面板上开启服务,初始化,然后在 servlet 中添加如下的代码。
StorageClient sc = new StorageClient(); sc.createBucket("testbucket"); sc.putObjectFile("testbucket", "test.txt", "test storage client upload text".getBytes(), null);
然后上传到新浪云上,然后访问一下 Servlet,之后可以在自己 Storage 面板里,可以看到文件。如下图
云存储
分布式 Session
多实例的情况下,准备了两种解决方案,一种是粘滞会话,另一种是第三方 Session 存储。粘滞会话可以在创建应用的时候开启。下面演示一下使用第三方 Redis 服务存储 Session
为了方便演示,我先把我测试的容器实例扩展到多个,到了 3 个 JVM,如图所示。
然后我们创建一个 redis 服务,具体创建参见 Redis 文档,然后进入"应用"->"环境变量面板",点击添加环境变量,添加以下两个环境变量。添加如下的环境变量。
- REDISURL="YOURREDIS_URL"
- SESSION_MANAGER=REDIS
然后我们重启下我们的应用。
还是在我们上面创建的 Servlet 里演示
HttpSession session = request.getSession(); session.setAttribute("key", "sinacloud"); response.getWriter().println(session.getAttribute("key"));
然后我们访问下我们的 Servlet,如下图。
最后我们在确认下是否将 Session 的数据存储到了 Redis,进入到 Redis 控制面板,点击管理,输入如下命令。
- keys *
可以看到如下的效果。
可以看到,由 Tomcat 自主存的 Session 信息,都在我们的 Redis 里了,这样就可以实现多实例之间的 Session 共享了。如果使用过程中需要存储对象,要预先对对象进行序列化
最后
以上简单的介绍了一下,新浪云容器环境 Java 相关的问题,主要是在新浪云相关的服务上,如果以后有新的服务或者问题,我会继续更新相关的使用方法和文档。当然使用中如果遇到上面问题,可以提交工单 求助。
具体相关的服务可以参看容器服务的文档中心。
-
全文搜索服务下线通知
由于产品的升级调整,我们将于本月底(2016-08-31)下线『全文搜索』服务。
现有全文搜索服务用户可以迁移至我们新的 『Elasticsearch』 服务,详细见:https://www.sinacloud.com/doc/sae/services/es.html 。
为了方便用户尽快的迁移,我们提供了一个基于 Elasticsearch 的全文搜索兼容客户端( 点击这里下载 ),你可以直接使用这个客户端替换之前的全文搜索客户端。详细的使用说明见客户端文档。
如果你在迁移过程中遇到问题,可以通过 工单系统 联系我们,我们提供迁移数据所需的全部支持。
-
PHP Web 服务器添加.htaccess 配置文件支持
.htaccess文件(或者"分布式配置文件")提供了针对每个目录改变配置的方法,即在一个特定的目录中放置一个包含指令的文件,其中的指令作用于此目录及其所有子目录。
详细请参见: https://www.sinacloud.com/doc/sae/php/runtime.html#htaccess-pei-zhi-wen-jian
subscribe via RSS