Netty服务器端获取数据并存入数据库

Netty服务器

在学习了一段时间Netty后写的一个小demo
1.—添加Maven依赖

		
            io.netty
            netty-all
            5.0.0.Alpha1
        

2.—服务端代码

/**
 * @program: AGPS
 * @description: Netty服务器
 * @author: Mr.Liu
 * @create: 2019-02-23 16:51
 **/
public class NettyServer {
    public void bind(int port) throws Exception{
        //配置服务端的NIO线程组
        // Boss线程:由这个线程池提供的线程是boss种类的,用于创建、连接、绑定socket, (有点像门卫)然后把这些socket传给worker线程池。
		// 在服务器端每个监听的socket都有一个boss线程来处理。在客户端,只有一个boss线程来处理所有的socket。
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        // Worker线程:Worker线程执行所有的异步I/O,即处理操作
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try{
        // ServerBootstrap 启动NIO服务的辅助启动类,负责初始话netty服务器,并且开始监听端口的socket请求
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup,workerGroup)//将两个NIO线程组当作参数传入ServerBootstrap
                    .channel(NioServerSocketChannel.class)// 设置非阻塞,用它来建立新accept的连接,用于构造serversocketchannel的工厂类
                    .option(ChannelOption.SO_BACKLOG,1024)
                    .childHandler(new ChildChannelHandler());// ChildChannelHandler 对出入的数据进行的业务操作,其继承ChannelInitializer
            ChannelFuture f = b.bind(port).addListener(future -> {   //添加监听
                if(future.isSuccess()) {
                    System.out. println( new Date() + ": 端口["+ port + "]绑定成功!");
                } else{
                    System.err. println( "端口["+ port + "]绑定失败!");
                }})
                    .sync();//绑定并堵塞 等待服务器链路关闭后main才退出
            //等待服务器监听端口关闭
            f.channel().closeFuture().sync();
        }finally {
            //优雅的退出,释放线程池资源
            bossGroup.shutdownGracefully();//使用shutdownGracefully()优雅的退出
            workerGroup.shutdownGracefully();
        }
    }
    private class ChildChannelHandler extends ChannelInitializer{
        @Override
        protected void initChannel(SocketChannel arg0) throws Exception{
            //arg0.pipeline().addLast("decoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4));
            //arg0.pipeline().addLast("encoder", new LengthFieldPrepender(4, false));
            //arg0.pipeline().addLast(new LineBasedFrameDecoder(1024)); //以\n 或者\r\n为截止的结束符 --回车换行符解决TCP半包/粘包问题
            arg0.pipeline().addLast(new StringDecoder());
            arg0.pipeline().addLast(new TimeServerHandler()); //自己的Handler
        }
    }
    public static void main(String[] args) throws Exception{
        int port = 8090; // 先设置一个默认的,要是有其他的端口传进来就是执行下面的代码
        if(args != null & args.length>0){
            try {
                port = Integer.valueOf(args[0]);
            }catch (NumberFormatException e){
            }
        }
        System.out.println("服务器启动成功:开始监听端口:"+port);
        new TimeServer().bind(port);
    }
}

3.—Handler类

/**
 * @program: Agps
 * @description:
 * @author: Mr.Liu
 * @create: 2019-02-23 17:01
 **/
public class TimeServerHandler extends ChannelHandlerAdapter {
    private final static Logger logger = LoggerFactory.getLogger(TimeServerHandler.class);

    //$数据#
    private int counter;
    @Override
    public void channelRead(ChannelHandlerContext ctx,Object msg) throws  Exception{ //msg是服务端接收到客户端的消息
        String body = (String) msg;
        String currentTime;
        //获取客户端ip
        InetSocketAddress ipSocket = (InetSocketAddress)ctx.channel().remoteAddress();
        String clientIp = ipSocket.getAddress().getHostAddress();

        System.out.println("The time server receive order :"+body+"; the counter is :"+ ++counter);

        //数据效验
        currentTime = DataFormatCheck(body);

        //System.getProperty("line.separator") 这也是换行符,功能和"\n"是一致的,但是此种写法屏蔽了 Windows和Linux的区别 ,更保险一些
        currentTime = "<<>>"+currentTime + System.getProperty("line.separator");
        ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());
        ctx.writeAndFlush(resp);
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx , Throwable cause){
        ctx.close();
    }

    /**
     * 数据效验
     * @param body
     * @return
     */
    public String DataFormatCheck(String body){
        String currentTime = "";
        int lenth = body.length();
        if("QUERY TIME ORDER".equalsIgnoreCase(body)){
            currentTime = new java.util.Date(
                    System.currentTimeMillis()).toString();
        }else if(!"".equalsIgnoreCase(body)){      简单的判断协议
            if(body.substring(0, 1).equals("$")){
                if(body.substring(lenth-1,lenth).equals("#")){
                    String news = body.substring(1,lenth-1);
                    try{
                        currentTime =  TimeServerHandler.insertMysql(news);
                    }catch (Exception e){
                        currentTime = Const.ERROR;
                    }
                }else {
                    currentTime = Const.BAD_FORMAT;
                }
            }else {
                currentTime = Const.BAD_FORMAT;
            }
        }else {
            currentTime = Const.BAD_ORDER;
        }
        return currentTime;
    }

    /**
     * 数据存入数据库
     * @param msg
     * @return
     */
    public static String insertMysql(String msg){
        String str;
        // 传递sql语句
        Statement stt;
        Connection conn = null;
        String sql = "insert into env_data(datas) values ('"+msg+"')";  //env_data()一定要连起来不然会有错误
        try {
            conn = mysqlimages.getConn();  //一个连接数据库的方法,这就不贴了,很简单的
            //获取Statement对象
            stt = conn.createStatement();
            //执行sql语句
            stt.executeUpdate(sql);
            logger.info(">>>插入数据库成功");
            str = Const.SECCESS;
        } catch (Exception e) {
            logger.error("<<<插入数据错误--"+e.getMessage());
            str = Const.ERROR;
        }finally {
            try {
                conn.close();
            } catch (SQLException e) {
                logger.error("<<<关闭数据库错误"+e.getMessage());
            }
        }
        return str;
    }
}

你可能感兴趣的:(Netty)