- 浏览: 112062 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
ron.luo:
干货,必须得顶。
JAXB使用经验总结 -
csdn_zuoqiang:
能否看下DWR的配置情况?谢谢
结合webservice实现dwr推送 -
友友水:
。。。。不好意思,无心之失,删不掉前一条评论
JAXB使用经验总结 -
友友水:
[/flash][/flash][/flash][/flash ...
JAXB使用经验总结 -
lihong11:
大哥,加加注释好不?看不懂唉
小玩dwr实现服务器推送
用main的形式在服务器上启动了一个netty服务,有端口有地址,可请求
package com.mazing.wx; import java.io.IOException; import java.io.InputStream; import org.apache.logging.log4j.core.config.ConfigurationSource; import org.apache.logging.log4j.core.config.Configurator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.codec.http.HttpResponseEncoder; /** * */ public class WxHttpServer { static {//指定初始化哪个log配置 try { InputStream is = WxHttpServer.class.getResourceAsStream("/log4j2-wx.xml"); ConfigurationSource cs = new ConfigurationSource(is); Configurator.initialize(null, cs); } catch (IOException e) { System.err.println(e); } } private static final Logger logger = LoggerFactory.getLogger(WxHttpServer.class); public void start(int port) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { // server端发送的是httpResponse,所以要使用HttpResponseEncoder进行编码 ch.pipeline().addLast(new HttpResponseEncoder()); // server端接收到的是httpRequest,所以要使用HttpRequestDecoder进行解码 ch.pipeline().addLast(new HttpRequestDecoder()); ch.pipeline().addLast(new HttpServerInboundHandler()); } }).option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); ChannelFuture f = b.bind(port).sync(); f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } logger.info("Http server stopped ..."); } public static void main(String[] args) throws Exception { logger.info("http main ..."); WxHttpServer server = new WxHttpServer(); final WxAccessTokenReaderThread thread = new WxAccessTokenReaderThread(); thread.start(); Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { logger.info("shutdowning ..."); thread.stopRunning(); } }); logger.info("Http Server listening on 20090 ..."); server.start(20090); } }
package com.mazing.wx; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.handler.codec.http.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.InetSocketAddress; import static io.netty.handler.codec.http.HttpHeaders.Names.*; import static io.netty.handler.codec.http.HttpResponseStatus.OK; import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; /** * */ public class HttpServerInboundHandler extends ChannelInboundHandlerAdapter { private static Logger logger = LoggerFactory.getLogger(HttpServerInboundHandler.class); private HttpRequest request; @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { if (msg instanceof HttpRequest) { request = (HttpRequest) msg; String uri = request.getUri(); InetSocketAddress insocket = (InetSocketAddress) ctx.channel() .remoteAddress(); String clientIP = insocket.getAddress().getHostAddress(); logger.info("uri: {}, ip: {}", uri, clientIP); } if (msg instanceof HttpContent) { HttpContent content = (HttpContent) msg; ByteBuf buf = content.content(); buf.release(); String text = WxAccessTokenReaderThread.wxAccessToken + "|" + WxAccessTokenReaderThread.wxJsapiTicket; FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, OK, Unpooled.wrappedBuffer(text.getBytes("UTF-8"))); response.headers().set(CONTENT_TYPE, "text/plain"); response.headers().set(CONTENT_LENGTH, response.content().readableBytes()); if (HttpHeaders.isKeepAlive(request)) { response.headers().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE); } ctx.write(response); ctx.flush(); } } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { logger.error(cause.getMessage()); ctx.close(); } }
package com.mazing.wx; import com.fasterxml.jackson.core.type.TypeReference; import com.mazing.CommonConstants; import com.mazing.commons.utils.HttpClientUtils; import com.mazing.commons.utils.JsonUtils; import com.mazing.commons.utils.cfg.DesPropertiesEncoder; import com.mazing.core.remote.config.Config; import com.mazing.core.web.RestResult; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 读取微信 access token 的线程 * */ public class WxAccessTokenReaderThread extends Thread { private static final Logger logger = LoggerFactory.getLogger(WxAccessTokenReaderThread.class); private boolean running = true; /** * 获取间隔 */ private static final int INTERVAL = 2 * 60 * 1000; // access token 在 7200秒过期, private long TOKEN_TIMEOUT = 7200 * 1000L - INTERVAL; private long lastReadTime = 0L; private String appid = null; private String secret = null; /** * access token */ static volatile String wxAccessToken = ""; /** * jsapi_ticket */ static volatile String wxJsapiTicket = ""; public WxAccessTokenReaderThread() { super("WxAccessTokenReaderThread"); } public void stopRunning() { running = false; interrupt(); } @Override public void run() { logger.info("WxAccessTokenReaderThread started ..."); if (!readConfig()) { logger.error("读取配置错误,线程结束,请配置 group=weixin_mp 的内容。 "); running = false; } while (running) { long now = System.currentTimeMillis(); if (now - lastReadTime >= TOKEN_TIMEOUT) { try { readToken(); readTicket(); lastReadTime = now; } catch (Exception e) { logger.error("读取微信 access token / jsapi ticket 错误", e); } } try { sleep(INTERVAL); } catch (InterruptedException e) { break; } } logger.info("WxAccessTokenReaderThread stopped ..."); } /** * 读取配置,只读一次 * @throws Exception */ public boolean readConfig() { String json = HttpClientUtils.doGet(CommonConstants.CONFIG_DOMAIN + "/api/base/allConfigs"); // logger.info("wx#readConfig | http response | result: {}", json.substring(0, 10) + "***"); RestResult<List<Config>> result = JsonUtils.parseObject(json, new TypeReference<RestResult<List<Config>>>() { }); if (!(result.isSuccess())) { logger.warn("wx#readConfig#Failure | Failure Request | result: {}", json); return false; } final String groupCode = "weixin_mp"; DesPropertiesEncoder decoder = new DesPropertiesEncoder(); int found = 0; for (Config config : result.getObject()) { if (groupCode.equals(config.getGroupCode())) { if ("appid".equalsIgnoreCase(config.getConfigKey())) { appid = decoder.decode(config.getConfigValue()); found++; } else if ("secret".equalsIgnoreCase(config.getConfigKey())) { secret = decoder.decode(config.getConfigValue()); found++; } } if (found >= 2) break; } return found >= 2; } /** * 读取 access token */ private void readToken() { Map<String, String> params = new HashMap<>(4); params.put("grant_type", "client_credential"); params.put("appid", appid); params.put("secret", secret); String json = HttpClientUtils.doGet("https://api.weixin.qq.com/cgi-bin/token", 10000, params); if (StringUtils.isBlank(json)) { logger.error("读取微信 access token 错误"); } Map<String, Object> map = JsonUtils.parseObject(json.trim(), new TypeReference<Map<String, Object>>() { }); if (map.containsKey("access_token")) { wxAccessToken = (String) map.get("access_token"); logger.info("读取微信 access token 成功"); if (map.containsKey("expires_in")) { int expiresIn = ((Number)map.get("expires_in")).intValue(); logger.info("过期时间 (s):" + expiresIn); TOKEN_TIMEOUT = expiresIn * 1000L - INTERVAL; if (TOKEN_TIMEOUT < 1000) { TOKEN_TIMEOUT = 10 * 60 * 1000L - INTERVAL; } } } else { logger.error("读取微信 access token 错误:" + json); } } /** * 读取 jsapi_ticket */ private void readTicket() { Map<String, String> params = new HashMap<>(4); params.put("access_token", wxAccessToken); params.put("type", "jsapi"); String json = HttpClientUtils.doGet("https://api.weixin.qq.com/cgi-bin/ticket/getticket", 10000, params); Map<String, Object> map = JsonUtils.parseObject(json.trim(), new TypeReference<Map<String, Object>>() { }); int errcode = -1; if (map.get("errcode") != null) { errcode = ((Number) map.get("errcode")).intValue(); logger.info("读取微信 jsapi_ticket 结果,errcode: {}, errmsg: {}", errcode, map.get("errmsg")); if (errcode == 0) { wxJsapiTicket = (String) map.get("ticket"); logger.info("读取微信 jsapi_ticket 成功!"); } } else { logger.error("读取微信 jsapi_ticket 错误:" + json); } } }
以上代码在启动WxHttpServer 中的main后,也就相当于启动了端口为20090的服务了, 可以通过请求如:
http://123.40.50.60:20090/ 获取到 HttpServerInboundHandler 中写入的参数
WeixinAccessToken.ACCESS_TOKEN 和
WeixinAccessToken.JSAPI_TICKET
发表评论
-
动态多数据源实现
2019-12-18 12:58 392背景: 目前基于连接了mobile库 从库的 项目(sprin ... -
java快速读取大文件
2018-02-08 11:19 320public static String readCon ... -
微信JSSDK 使用
2016-05-26 11:49 1910获取微信JSAPI_TICKET package com ... -
安全性,加密
2016-03-07 15:55 614/** * 随机字符串集 */ pri ... -
并发队列
2015-12-03 15:26 601import java.util.concurrent ... -
一致性hash算法测试
2014-12-17 18:40 1244因为用memcached集群缓存数据,所以增删服务器节点 对缓 ... -
ant脚本编译部署java工程到tomcat服务器
2013-06-28 15:35 1061<?xml version="1.0& ... -
Myeclipse反向生成pojo及hibernate映射文件(由数据库表)
2013-03-18 14:38 1054在这之前请创建一个web工程,然后右键选择myeclipse- ... -
手写比较器comparator
2012-07-12 15:47 1256项目中需要对一些数据进行排序,应用到了个比较强大的比较器,感觉 ... -
copy到粘贴板
2012-05-22 11:39 1142直接上代码,实现了IE和火狐下的copy content ... -
取两个集合的交集数据
2011-08-30 11:13 1235List<String> a = new A ... -
常用正则表达式收藏
2011-04-26 12:26 6931。^\d+$ //匹配非负整数(正整数 + 0) 2。 ... -
对日期类型与String类型之间转换方法的小结
2011-03-07 19:25 1223关于日期的方法举例程序如下: package c ... -
线程同步
2011-02-26 10:47 800转自http://www.iteye.com/topic/16 ... -
java多线程
2011-02-26 08:15 880本文转载自 http://www.iteye.com/topi ... -
对java中反射的整理
2011-02-24 20:04 857什么是Java中的类反射: ... -
关于线程----线程间的数据共享
2011-02-19 19:45 1551当多个线程的执行代码来自同一个类的run方法,既称他们共 ...
相关推荐
netty通讯实践,里面的例子有详细的注释,分析了netty通讯的环节步骤
Netty的现Tech Lead Norman在本书中循序渐进地讲解了Netty的各个关键部分,在看完本书后,你不但可以熟练地使用Netty来构建以上系统,并且还可以避免很多常见的陷阱。 无论是想要学习Spring 5 、Spark、...
23_Gradle Wrapper在Gradle项目构建中的最佳实践 24_gRPC整合Gradle与代码生成 25_gRPC通信示例与JVM回调钩子 26_gRPC服务器流式调用实现 27_gRPC双向流式数据通信详解 28_gRPC与Gradle流畅整合及问题解决的完整过程...
23_Gradle Wrapper在Gradle项目构建中的最佳实践;24_gRPC整合Gradle与代码生成············82_Netty引用计数原子更新揭秘与AtomicIntegerFieldUpdater深度剖析;83_AtomicIntegerFieldUpdater实例演练...
第23讲:Gradle Wrapper在Gradle项目构建中的最佳实践 第24讲:gRPC整合Gradle与代码生成 第25讲:gRPC通信示例与JVM回调钩子 第26讲:gRPC服务器流式调用实现 第27讲:gRPC双向流式数据通信详解 第28讲:gRPC...
本工程致力于netty实践学习案例,是netty初学者及核心技术巩固的最佳实践 a。『基础-入门篇』 :OK_hand: :netty-helloworld b。 『基础-通讯协议篇』 :OK_hand: :netty-http :OK_hand: netty-springboot-...
20_通过Apache Thrift实现Java与Python的RPC调用 21_gRPC深入详解 22_gRPC实践 23_Gradle Wrapper在Gradle项目构建中的最佳实践 24_gRPC整合Gradle与代码生成 25_gRPC通信示例与JVM回调钩子 26_gRPC服务器流式调用...
Netty是一款用于创建高性能网络应用程序的... 使用Netty构建应用程序,你不必是一名网络编程专家; 使用Netty比直接使用底层的Java API容易得多; Netty推崇良好的设计实践,例如,将你的应用程序逻辑和网络层解耦。
Netty + JavaFx实战:仿制桌面版微信聊天本专栏是作者小傅哥使用JavaFx , Netty4.x , SpringBoot , Mysql等技术栈和偏向于DDD领域驱动设计方式,构建的仿制桌面版微信聊天工程实现通信核心功能。 ,请请给予支持...
随着逐步对NIO的深入学习和对Netty框架的了解,以及...基于Netty构建京麦TCP网关的长连接容器,作为网关接入层提供服务API请求调用。客户端通过域名+端口访问TCP网关,域名不同的运营商对应不同的VIP,VIP发布在LVS上,
构建分布式架构最重要因素 CDN静态文件访问 分布式存储 分布式搜索引擎 应用发布与监控 应用容灾及机房规划 系统动态扩容 分布式架构策略-分而治之 从简到难,从网络通信探究分布式通信原理 基于消息方式...
netty Redis Spring Spring4新特性 Spring使用注意事项 Spring验证Validation SpringBoot 开发知识 相关技术名词 开发技术框架工具整理 架构知识 开发过程注意事项整理 常用开发技巧 数据库 数据库基础知识 分库分表...
Superman是什么:构建Java Android 高级开发技术的知识体系,Android 系统原理的深入剖析,Java项目最佳实践,从基础不断打怪升级成为超人之路。编程基础、JVM深度剖析、并发编程、 Spring全家桶、高并发、分布式、...
《Linux多线程服务端编程:使用muduo C++网络库》主要讲述采用现代C++在x86-64 Linux上编写多线程TCP网络服务程序的主流常规技术,重点讲解一种适应性较强的多线程服务器的编程模型,即one loop per thread。...