SpringBoot在自定义实现类中调用service层等Spring其他层报错为null的解决办法

简介: SpringBoot在自定义实现类中调用service层等Spring其他层报错为null的解决办法

背景:

使用Springboot整合Netty写了一个TCP实现客户端服务端通信接收主板信息,然后需要将设备实时发送的检测数据等关键信息存储到数据库,也是为了能最快利用mybatis框架实现数据访问,然后在TCP服务器消息处理时,需要写数据库,直接调用DAO层,编译报错。改为调用Service层,编译正常,运行到调用的地方,报空指针异常,跟踪到异常位置,发现service为空,也就是按照之前controller层通过

@Autowired注入service层失效。

解决方案:

1.不要用mybatis,使用原生的jdbc连接数据库进行存储

代码如下:

blic class MessageHandler extends ChannelInboundHandlerAdapter {
  private static Logger logger = LoggerFactory.getLogger(MessageHandler.class);
  /**
   * 本方法用于读取客户端发送的信息
   * @param ctx
   * @param msg
   * @throws Exception
   */
  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    System.out.println("输出接收过来的信息: "+msg);
        //将msg进行入库操作
        //基础的jdbc连接操作,这里省去基础的连接方法
        String str;
        // 传递sql语句
        Statement stt;
        Connection conn = null;
        String sql = "insert into test_db(datas) values ('"+msg+"')";  //写SQL
        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;
        }

这种方法可以实现,但是不推荐,本来这里数据量就大,再用jdbc没有连接池将会造成业务阻塞netty本身的worker工作线程。

所以推荐使用下一种方法:

2.使用@PostConstruct静态初始化spring的成员变量

代码如下:

channelRead方法:

  //调用线程池处理大数据量问题
  ExecutorService executor = Executors.newFixedThreadPool(5);
    int num=0;
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println();
        log.info("加载客户端报文......");
        log.info("【" + ctx.channel().id() + "】" + " :" + msg);
        /**
         *  下面可以解析数据,保存数据,生成返回报文,将需要返回报文写入write函数
         */
        num++;
        System.out.println(num);//输出当前已经接收过来的条数
        //引入异步业务线程池的方式,避免长时间业务耗时业务阻塞netty本身的worker工作线程
        executor.submit(new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                log.info("收到服务端发来的方法请求了--------------------------------------------");
                ServerHandler handler = new ServerHandler();//这个类在下面
                handler.test(msg.toString());
                return null;
            }
        });
        //响应客户端
        this.channelWrite(ctx.channel().id(), msg);
    }
@Component 
public class ServerHandler extends IoHandlerAdapter {
    @Autowired
    private ITest2StaticService test2StaticService;// 注入service方法
    private static ServerHandler serverHandler;
    @PostConstruct //通过@PostConstruct实现初始化bean之前进行的操作
    //在初始化的时候初始化静态对象和它的静态成员变量healthDataService,原理是拿到service层bean对象,静态存储下来,防止被释放。
    public void init() {
        serverHandler = this;
        serverHandler.test2StaticService = this.test2StaticService;
        // 初使化时将已静态化的testService实例化
    }
    //测试调用
    public void test(String msg) {
        Test2Static test2Static = new Test2Static();
        test2Static.setBb(Double.valueOf(msg));
        test2Static.setCreateTime(LocalDateTime.now());
        System.out.println("1111111111111111");
        boolean b = serverHandler.test2StaticService.save(test2Static);
        System.out.println("---! "+b);
    }
}
IoHandlerAdapter类 所用到的maven坐标:
  <!-- https://mvnrepository.com/artifact/org.apache.mina/mina-core -->
        <dependency>
            <groupId>org.apache.mina</groupId>
            <artifactId>mina-core</artifactId>
            <version>2.1.3</version>
        </dependency>

2.说明:

将需要调用Spring的Service层的类通过@Component注解为组件加载;

同样通过@Autowired获取Service层的Bean对象;

为类声明一个静态变量,方便下一步存储bean对象;

划重点:通过注解@PostConstruct ,在初始化的时候初始化静态对象和它的静态成员变量healthDataService,原理是拿到service层bean对象,静态存储下来,防止被释放。


找了好久,终于找到这个方法,本来以为很简单,却总是怎么也写不进去数据库。调用service一直为空,可困扰我好久。

特此记录。。。。。。。。。。。。。。。。。


*那些浪费的时间,都是丢在真理路上的金子~~~~!*

目录
相关文章
|
25天前
|
监控 Java 数据库连接
详解Spring Batch:在Spring Boot中实现高效批处理
详解Spring Batch:在Spring Boot中实现高效批处理
134 12
|
25天前
|
安全 Java 测试技术
详解Spring Profiles:在Spring Boot中实现环境配置管理
详解Spring Profiles:在Spring Boot中实现环境配置管理
73 10
|
22天前
|
负载均衡 Java 开发者
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
深入探索Spring Cloud与Spring Boot:构建微服务架构的实践经验
70 5
|
1月前
|
Java
SpringBoot 内部方法调用,事务不起作用的原因及解决办法
在做业务开发时,遇到了一个事务不起作用的问题。大概流程是这样的,方法内部的定时任务调用了一个带事务的方法,失败后事务没有回滚。查阅资料后,问题得到解决,记录下来分享给大家。
72 4
|
2月前
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
102 2
|
2月前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
204 1
|
2月前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
34 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
|
2月前
|
Java Spring
springboot 学习十一:Spring Boot 优雅的集成 Lombok
这篇文章是关于如何在Spring Boot项目中集成Lombok,以简化JavaBean的编写,避免冗余代码,并提供了相关的配置步骤和常用注解的介绍。
122 0
|
2月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
178 1
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
116 62