java - spring-boot netty?

 任我闯2502871177 发布于 2022-11-03 13:48

用spring-boot和netty做一个心跳程序,安卓端和服务端连接,服务端检查客户端是否在线,并且记录在线时间和离开时间,并保存到数据库中,现在调用service层的方法时,出现了java.lang.NullPointerException,下面是部分代码:

@SpringBootApplication
public class App
{
    public static void main(String[] args)
    {
        SpringApplication.run(App.class, args);
        HeartbeatServer.start(8089);
    }
}
public class HeartbeatServer
{

    public static void start(int port)
    {
        // Configure the server.
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap b = new ServerBootstrap();
        try
        {
            b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 10000).childHandler(new ChannelInitializer()
            {
                @Override
                public void initChannel(SocketChannel ch) throws Exception
                {
                    ch.pipeline().addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())).addLast("decoder", new StringDecoder()).addLast("encoder", new StringEncoder()).addLast(new IdleStateHandler(60, 0, 0), // 心跳控制
                            new ServerHandler());
                }
            });

            // Start the server.
            ChannelFuture f = b.bind(port).sync();

            // Wait until the server socket is closed.
            f.channel().closeFuture().sync();
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        } finally
        {
            // Shut down all event loops to terminate all threads.
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
@Component
public class ServerHandler extends SimpleChannelInboundHandler
{
    private long comingTime;
    private long leaveTime;
    private Map users = new HashMap();

    @Autowired
    @Qualifier(CompanyAttendanceService.SERVICE_NAME)
    private CompanyAttendanceService cs;

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception
    {
        comingTime = System.currentTimeMillis();
        System.out.println(ctx.channel().remoteAddress() + "连接成功:" + comingTime);
        ctx.fireChannelRegistered();
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String message) throws Exception
    {
        Channel incoming = ctx.channel();
        Integer userId = users.get(ctx.channel().remoteAddress());
        if (userId == null)
        {
            cs.updateLeaveTime(Integer.valueOf(message), comingTime);
        }

        users.put(incoming.localAddress().toString(), Integer.valueOf(message));
        System.out.println("收到客户端" + "[" + incoming.remoteAddress() + "]" + "的消息:" + message);

        incoming.writeAndFlush("[" + incoming.remoteAddress() + "]" + message + "\n");
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception
    {
        Channel incoming = ctx.channel();
        System.out.println(incoming.remoteAddress() + "在线");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
    {
        Channel incoming = ctx.channel();
        System.out.println(incoming.remoteAddress() + "异常");
        // 当出现异常就关闭连接
        cause.printStackTrace();
        ctx.close();
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception
    {
        leaveTime = System.currentTimeMillis();
        Channel incoming = ctx.channel();
        int userId = users.get(incoming.localAddress().toString());
        System.out.println(incoming.remoteAddress() + "掉线,userId:" + userId);
        users.remove(incoming.localAddress().toString());

        cs.updateOnlineTime(userId, leaveTime, comingTime);
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception
    {
        /* 心跳处理 */
        if (evt instanceof IdleStateEvent)
        {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE)
            {
                /* 读超时 */
                System.out.println("READER_IDLE 读超时");
                ctx.disconnect();
            } else if (event.state() == IdleState.WRITER_IDLE)
            {
                /* 写超时 */
                System.out.println("WRITER_IDLE 写超时");
            } else if (event.state() == IdleState.ALL_IDLE)
            {
                /* 总超时 */
                System.out.println("ALL_IDLE 总超时");
            }
        }
    }

}
1 个回答
  • 注意这几块代码:

    @Component
    public class ServerHandler extends SimpleChannelInboundHandler<String>{
        ...
    }

    你的原意是想通过@Component进行注入,但是

    xxx.addLast(new IdleStateHandler(60, 0, 0), new ServerHandler());

    你这里的ServerHandler是自己new的,所以Spring就无能为力了
    所以你这里的ServerHandler应该通过Spring创建,交给Spring容器管理

    2022-11-12 01:50 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有