`
xiaoliang330
  • 浏览: 115310 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

Netty服务构建实践

 
阅读更多

用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






分享到:
评论

相关推荐

    Android使用Netty网络框架实践(客户端、服务端)

    总之,Netty为Android开发者提供了强大的网络通信能力,通过理解和实践,我们可以构建出稳定、高效、可扩展的网络应用。无论是在服务端处理大量并发请求,还是在客户端实现低延迟的数据传输,Netty都能成为你得力的...

    Netty4.0学习笔记系列之三:构建简单的http服务

    Netty4.0学习笔记系列之三是关于构建简单的HTTP服务的教程,这主要涉及网络编程、服务器开发以及Java NIO(非阻塞I/O)的相关知识。Netty是一个高性能、异步事件驱动的网络应用程序框架,它使得开发可伸缩且稳定的...

    Netty实践学习案例

    在深入探讨 Netty 的实践学习案例之前,我们先了解一下 Netty 的核心特性: 1. **异步非阻塞 I/O**:Netty 基于 Java NIO(非阻塞I/O)构建,允许它处理大量并发连接,减少了线程创建和上下文切换的开销。 2. **零...

    Netty实战 电子版.pdf_java_netty_服务器_

    Netty不仅简化了网络编程的复杂性,还提供了丰富的特性和组件,使得开发人员能够快速构建出可靠且高效的网络服务。 Netty的核心特性包括: 1. **异步模型**:Netty基于Java NIO(非阻塞I/O)构建,采用异步事件...

    netty游戏服务器核心

    Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。...通过学习这个项目,可以深入理解 Netty 在游戏服务器开发中的应用,以及如何构建高性能的网络服务。

    netty服务器解析16进制数据

    Netty 是一个高性能、异步事件驱动的网络应用程序框架,常用于开发高并发、低延迟的网络服务。在处理网络通信时,数据通常以各种格式传输,包括...理解和掌握这些概念和实践技巧对于构建高效、可靠的网络应用至关重要。

    java物联网的netty服务器

    Java物联网的Netty服务器是一种基于Java的高性能网络应用框架,主要应用于开发高并发...通过深入学习和实践这个项目,开发者可以掌握利用Netty构建物联网服务器的关键技术,为构建高效、可靠的物联网应用打下坚实基础。

    netty通讯实践

    Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。在本文中,我们将深入探讨 Netty 的通讯实践...学习并应用 Netty,有助于构建高性能、稳定可靠的网络应用程序。

    WebSocket利用netty连接入门项目

    这个入门项目是学习WebSocket与Netty结合的一个好起点,通过实际操作,你可以更深入地理解WebSocket协议的工作原理,以及如何使用Netty构建高效稳定的WebSocket服务器。同时,对于前端开发人员,这也是一个了解...

    netty 通过端口调用关闭

    综上所述,理解和掌握 Netty 通过端口调用关闭的机制对于构建可靠的网络应用至关重要。通过细致的配置、适当的监听器和异常处理,我们可以确保服务器能够安全、高效地运行和退出。在实践中,结合源码分析和使用工具...

    netty-4.1_javaNetty_netty_服务器_

    Netty 是一个基于 Java 的高性能、异步事件驱动的网络应用...通过学习和实践这些知识点,你可以熟练掌握 Netty 并用其构建高性能的网络应用。在 "netty-4.1" 的文档和示例代码中,你会找到更多关于这些主题的详细信息。

    netty3实现的websocket服务

    在这个“netty3实现的websocket服务”项目中,开发者利用Netty 3版本构建了一个WebSocket服务器和一个简单的Web服务器,旨在帮助学习者深入理解Netty的工作原理以及如何基于Netty构建实际项目。 WebSocket协议是一...

    Netty实战.epub_netty实战epub_netty实战epub_netty_

    总的来说,《Netty实战》这本书全面覆盖了Netty的基础到高级知识,通过实例教学,使读者能够深入理解Netty的工作原理,并具备使用Netty构建高性能网络应用的能力。对于想要提升Java网络编程技能,或者已经在使用...

    Netty 入门与实战

    Netty 是一个高性能、异步事件驱动的网络应用...通过以上知识点的学习和实践,你将能够熟练掌握Netty的基本用法,实现高性能的网络应用。在实际项目中,结合具体的业务需求,Netty可以展现出强大的灵活性和可扩展性。

    Netty 教程 Netty权威指南

    4. **云服务**:云服务提供商利用 Netty 构建高可用、高性能的 API 网关和内部服务通信。 总之,《Netty 权威指南》507页的完整版教程将深入探讨这些知识点,并通过实例帮助读者掌握如何在实际项目中运用 Netty ...

    springboot整合netty的demo

    总的来说,SpringBoot整合Netty的实践涉及到SpringBoot的应用构建、Netty的服务器和客户端创建、响应式编程模型、以及两者的交互和配置优化等多个层面。通过这个Demo,开发者能够更好地理解和掌握如何在SpringBoot...

    整合netty实时通讯

    通过学习和实践 Netty 实现的 WebSocket 服务,你可以构建出强大的实时通讯系统,适用于游戏、金融、物联网等多种场景。不过,实际生产环境中,还需要考虑负载均衡、容错恢复、安全性等更多因素,以确保服务的稳定性...

    读书笔记:基于netty构建的web微服务应用框架最佳实践.zip

    读书笔记:基于netty构建的web微服务应用框架最佳实践

    Netty权威指南PDF书籍

    Netty 的设计目标是提供一个灵活且高效的基础架构,允许开发者快速构建网络服务,同时避免常见的性能瓶颈。 2. **Netty 的主要特点** - **异步事件驱动**:Netty 使用非阻塞 I/O 模型,提高了系统的并发处理能力。...

    NIO+Netty5视频教程与Netty源码剖析视频教程

    这部分课程将理论与实践相结合,让学习者在实际项目中运用Netty5构建不同类型的RPC(远程过程调用)架构。这涵盖了Netty5在RPC通信中的应用,如TCP、UDP协议的实现,以及HTTP、WebSocket等常见协议的处理。学习者将...

Global site tag (gtag.js) - Google Analytics