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一直为空,可困扰我好久。

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


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

目录
相关文章
|
9月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
784 2
|
10月前
|
人工智能 Java 机器人
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
Spring AI Alibaba集成Ollama,基于Java构建本地大模型应用,支持流式对话、knife4j接口可视化,实现高隐私、免API密钥的离线AI服务。
7336 2
基于Spring AI Alibaba + Spring Boot + Ollama搭建本地AI对话机器人API
存储 JSON Java
973 0
|
11月前
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
1493 3
|
安全 Java Apache
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 身份和权限认证
本文介绍了 Apache Shiro 的身份认证与权限认证机制。在身份认证部分,分析了 Shiro 的认证流程,包括应用程序调用 `Subject.login(token)` 方法、SecurityManager 接管认证以及通过 Realm 进行具体的安全验证。权限认证部分阐述了权限(permission)、角色(role)和用户(user)三者的关系,其中用户可拥有多个角色,角色则对应不同的权限组合,例如普通用户仅能查看或添加信息,而管理员可执行所有操作。
695 0
|
安全 Java 数据安全/隐私保护
微服务——SpringBoot使用归纳——Spring Boot中集成 Shiro——Shiro 三大核心组件
本课程介绍如何在Spring Boot中集成Shiro框架,主要讲解Shiro的认证与授权功能。Shiro是一个简单易用的Java安全框架,用于认证、授权、加密和会话管理等。其核心组件包括Subject(认证主体)、SecurityManager(安全管理员)和Realm(域)。Subject负责身份认证,包含Principals(身份)和Credentials(凭证);SecurityManager是架构核心,协调内部组件运作;Realm则是连接Shiro与应用数据的桥梁,用于访问用户账户及权限信息。通过学习,您将掌握Shiro的基本原理及其在项目中的应用。
520 0
|
消息中间件 Java 微服务
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——发布/订阅消息的生产和消费
本文详细讲解了Spring Boot中ActiveMQ的发布/订阅消息机制,包括消息生产和消费的具体实现方式。生产端通过`sendMessage`方法发送订阅消息,消费端则需配置`application.yml`或自定义工厂以支持topic消息监听。为解决点对点与发布/订阅消息兼容问题,可通过设置`containerFactory`实现两者共存。最后,文章还提供了测试方法及总结,帮助读者掌握ActiveMQ在异步消息处理中的应用。
615 0
|
消息中间件 网络协议 Java
微服务——SpringBoot使用归纳——Spring Boot中集成ActiveMQ——ActiveMQ集成
本文介绍了在 Spring Boot 中集成 ActiveMQ 的详细步骤。首先通过引入 `spring-boot-starter-activemq` 依赖并配置 `application.yml` 文件实现基本设置。接着,创建 Queue 和 Topic 消息类型,分别使用 `ActiveMQQueue` 和 `ActiveMQTopic` 类完成配置。随后,利用 `JmsMessagingTemplate` 实现消息发送功能,并通过 Controller 和监听器实现点对点消息的生产和消费。最后,通过浏览器访问测试接口验证消息传递的成功性。
964 0

热门文章

最新文章