• 解决springboot整合websocket、redis、openfeign,redisTemplate,openfeign的类无法注入的问题


    在部分业务中,我们需要使用长连接,我们可以使用http长连接或者websocket,在springboot作为后端的框架中, 可以借用的技术是(netty,websocket)

    版本如下 

    软件版本号
    jdk21
    springboot

    3.1.5

    springcloud

    2022.0.4

     场景复现

    pom文件

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0modelVersion>
    5. <parent>
    6. <groupId>org.springframework.bootgroupId>
    7. <artifactId>spring-boot-starter-parentartifactId>
    8. <version>3.1.5version>
    9. <relativePath/>
    10. parent>
    11. <groupId>com.examplegroupId>
    12. <artifactId>testDiartifactId>
    13. <version>0.0.1-SNAPSHOTversion>
    14. <name>testDiname>
    15. <description>testDidescription>
    16. <properties>
    17. <java.version>21java.version>
    18. <spring-cloud.version>2022.0.4spring-cloud.version>
    19. properties>
    20. <dependencies>
    21. <dependency>
    22. <groupId>org.springframework.bootgroupId>
    23. <artifactId>spring-boot-starter-data-redisartifactId>
    24. dependency>
    25. <dependency>
    26. <groupId>org.springframework.bootgroupId>
    27. <artifactId>spring-boot-starter-websocketartifactId>
    28. dependency>
    29. <dependency>
    30. <groupId>org.springframework.cloudgroupId>
    31. <artifactId>spring-cloud-starter-openfeignartifactId>
    32. dependency>
    33. <dependency>
    34. <groupId>org.springframework.cloudgroupId>
    35. <artifactId>spring-cloud-starter-loadbalancerartifactId>
    36. dependency>
    37. <dependency>
    38. <groupId>org.projectlombokgroupId>
    39. <artifactId>lombokartifactId>
    40. dependency>
    41. <dependency>
    42. <groupId>org.springframework.bootgroupId>
    43. <artifactId>spring-boot-starter-testartifactId>
    44. <scope>testscope>
    45. dependency>
    46. dependencies>
    47. <dependencyManagement>
    48. <dependencies>
    49. <dependency>
    50. <groupId>org.springframework.cloudgroupId>
    51. <artifactId>spring-cloud-dependenciesartifactId>
    52. <version>${spring-cloud.version}version>
    53. <type>pomtype>
    54. <scope>importscope>
    55. dependency>
    56. dependencies>
    57. dependencyManagement>
    58. <build>
    59. <plugins>
    60. <plugin>
    61. <groupId>org.springframework.bootgroupId>
    62. <artifactId>spring-boot-maven-pluginartifactId>
    63. plugin>
    64. plugins>
    65. build>
    66. project>

     配置类

    1. package com.example.testdi.config;
    2. import org.springframework.context.annotation.Bean;
    3. import org.springframework.context.annotation.Configuration;
    4. import org.springframework.web.socket.server.standard.ServerEndpointExporter;
    5. import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
    6. @Configuration
    7. public class WebsocketConfig {
    8. @Bean
    9. public ServerEndpointExporter serverEndpointExporter() {
    10. return new ServerEndpointExporter();
    11. }
    12. @Bean
    13. public ServletServerContainerFactoryBean createWebSocketContainer() {
    14. ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
    15. container.setMaxTextMessageBufferSize(8192 * 4);
    16. container.setMaxBinaryMessageBufferSize(8192 * 4);
    17. return container;
    18. }
    19. }

    rpc类

    1. package com.example.testdi.rpc;
    2. import org.springframework.cloud.openfeign.FeignClient;
    3. import org.springframework.web.bind.annotation.GetMapping;
    4. import org.springframework.web.bind.annotation.ResponseBody;
    5. @FeignClient(value = "http://localhost:9090")
    6. public interface TestRpc {
    7. @GetMapping("/hello")
    8. @ResponseBody
    9. String hello();
    10. }

    websocket

    1. @Slf4j
    2. @Component
    3. @ServerEndpoint(value = "/example")
    4. public class ExampleWebsocket {
    5. @Resource
    6. private RedisTemplate redisTemplate;
    7. @Resource
    8. private TestRpc testRpc;
    9. @OnOpen
    10. public void open(Session session) {
    11. log.info("===============open=================");
    12. log.info("redisTemplate: {}", redisTemplate);
    13. log.info("testRpc: {}", testRpc);
    14. }
    15. }

    启动类

    1. @EnableFeignClients
    2. @SpringBootApplication
    3. public class TestDiApplication {
    4. public static void main(String[] args) {
    5. SpringApplication.run(TestDiApplication.class, args);
    6. }
    7. }

    配置文件

    1. spring:
    2. data:
    3. redis:
    4. host: xxx.xxx.xxx.xxx
    5. database: xx
    6. port: xxxx
    7. timeout: xxxx
    8. password: xxxxxxxxxxxxxxx
    9. server:
    10. port: 9090

    效果

    可以看到都是空指针

    问题分析

    可能是bean没有注入到spring容器吗?

    修改启动类

    1. package com.example.testdi;
    2. import jakarta.annotation.Resource;
    3. import org.springframework.boot.CommandLineRunner;
    4. import org.springframework.boot.SpringApplication;
    5. import org.springframework.boot.autoconfigure.SpringBootApplication;
    6. import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
    7. import org.springframework.cloud.openfeign.EnableFeignClients;
    8. import org.springframework.context.ApplicationContext;
    9. import java.util.Arrays;
    10. import java.util.List;
    11. @EnableFeignClients
    12. @SpringBootApplication
    13. public class TestDiApplication extends SpringBootServletInitializer implements CommandLineRunner {
    14. @Resource
    15. private ApplicationContext appContext;
    16. public static void main(String[] args) {
    17. SpringApplication.run(TestDiApplication.class, args);
    18. }
    19. @Override
    20. public void run(String... args) throws Exception
    21. {
    22. String[] beans = appContext.getBeanDefinitionNames();
    23. Arrays.sort(beans);
    24. List list = Arrays.stream(beans).filter(ele -> ele.contains("TestRpc") || ele.contains("redisTemplate")).toList();
    25. for (String bean : list)
    26. {
    27. System.out.println(bean + " of Type :: " + appContext.getBean(bean).getClass());
    28. }
    29. }
    30. }

    查看控制台

    发现并不是上述情况

    没获取到/获取的方式错误

    解决方案 

    使用辅助类

    1. package com.example.testdi.utils;
    2. import org.springframework.beans.BeansException;
    3. import org.springframework.context.ApplicationContext;
    4. import org.springframework.context.ApplicationContextAware;
    5. import org.springframework.stereotype.Component;
    6. @Component
    7. public class ApplicationHelper implements ApplicationContextAware {
    8. private static ApplicationContext applicationContext;
    9. @Override
    10. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    11. ApplicationHelper.applicationContext = applicationContext;
    12. }
    13. public static ApplicationContext getApplicationContext() {
    14. return applicationContext;
    15. }
    16. public static Object getBean(String beanName) {
    17. return applicationContext.getBean(beanName);
    18. }
    19. }

    修改websocket代码

    1. package com.example.testdi.websocket;
    2. import com.example.testdi.rpc.TestRpc;
    3. import com.example.testdi.utils.ApplicationHelper;
    4. import jakarta.annotation.Resource;
    5. import jakarta.websocket.OnOpen;
    6. import jakarta.websocket.Session;
    7. import jakarta.websocket.server.ServerEndpoint;
    8. import lombok.extern.slf4j.Slf4j;
    9. import org.springframework.data.redis.core.RedisTemplate;
    10. import org.springframework.stereotype.Component;
    11. @Slf4j
    12. @Component
    13. @ServerEndpoint(value = "/example")
    14. public class ExampleWebsocket {
    15. private RedisTemplate redisTemplate= (RedisTemplate) ApplicationHelper.getBean("redisTemplate");
    16. private TestRpc testRpc= (TestRpc) ApplicationHelper.getBean("com.example.testdi.rpc.TestRpc");
    17. @OnOpen
    18. public void open(Session session) {
    19. log.info("===============open=================");
    20. log.info("redisTemplate: {}", redisTemplate);
    21. log.info("testRpc: {}", testRpc);
    22. }
    23. }

    效果

    一些问题 

    怎么测试websocket接口

    这里推荐2个,一个是postman,一个是网站

    postman 

    即可开始测试

    网站

    这边推荐测试网站测试,支持ws/wss

  • 相关阅读:
    esbuild中文文档-路径解析配置项(Path resolution - External、Main fields)
    第三章:最新版零基础学习 PYTHON 教程(第十三节 - Python 运算符—Python 中的运算符函数 - 套装2)
    AngelScript -- C++程序最好的脚本语言
    “竞速”智能网联汽车,领头雁为何是长沙?
    JAVA构造单例模式的一些小困扰-1
    YOLOv5 分类模型 数据集加载 1
    夯基提质|正雅膜片及附件定位系统双升级
    JS选择框全选效果(从入门到优化)
    modbus的协议
    基于MATLAB开发AUTOSAR软件应用层模块-part8.AUTOSAR工具箱的功能介绍
  • 原文地址:https://blog.csdn.net/weixin_44808225/article/details/134248506