解决SpringBoot webSocket 资源无法加载、tomcat启动报错的问题
作者:fyhju1 发布时间:2021-07-28 05:06:42
问题描述:
1. 项目集成WebSocket,且打包发布tomcat时出现websocket is already in CLOSING or CLOSE state这样的问题,建议参考“解决方法二”,但是“解决方法一”请要了解查看 ,因为解决方法二是在一的基础上进行更正
2. 如果出现javax.websocket.server.ServerContainer not available这样的错误,请参考“解决方法一”中步骤3
解决方法一:(常规解决、不推荐)
步骤1:在BootApplication中修改:
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(BootApplication.class);
springApplication.addListeners(new ApplicationPidFileWriter());
ConfigurableApplicationContext applicationContext = springApplication.run(args);
WebSocketServer.setApplicationContext(applicationContext);
注:这里的WebSocketServer是指你自定义的websocket接受消息的服务类
步骤2:修改WebSocketServer
private static ManageUserMapper manageUserMapper;
public static void setApplicationContext(ConfigurableApplicationContext applicationContext) {
WebSocketServer.manageUserMapper = applicationContext.getBean(ManageUserMapper.class);
}
步骤3: 修改pom.xml
由于我们在开发过程中,如果按照以上步骤1、2进行修改,一般不会出现问题,
但是如果我们打包发布tomcat,就会出现:javax.websocket.server.ServerContainer not available这样的错误,步骤3为常规解决一下问题方式
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 去除内嵌tomcat -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
需要去除web-starter的tomcat,因为如果不去除会导致冲突,
如果出现这种问题,你还需要在websocketConfig中做如下修改:(websocket为自定义配置类)
/**
* 服务器节点
*
* 如果使用独立的servlet容器,而不是直接使用springboot的内置容器,就不要注入ServerEndpointExporter,因为它将由容器自己提供和管理
* @return
*/
@Bean
@Profile("dev")
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
在application.properties做如下配置
##prod:生产环境 dev:开发环境(WINDOWS)
spring.profiles.active=dev
这里加入了@Profile("dev") 这个注解。意思是在开发的过程中去调用
.记住如果开发过程中,记得一定要把pom.xml中的去除tomcat那句话给注释掉,上线才需要去除
问题反思:(为什么不建议这么解决问题)
这种方式确实可以常规解决websocket打包tomcat不报错问题,同时也解决了在资源无法加载的问题,但是这样却十分的麻烦,理由如下:
1. 繁琐:生产环境和开发环境要一直切换是否注释tomcat
2. 局限性大:我们在BootApplication中添加了websocketserver去访问资源的语句,但是其他地方难道没有需要调用的吗,如果有,难道像这样一直累计添加下去,每个server设置一下
核心思想是资源无法加载的问题,如果你有写线程,且线程你也调用了数据库资源,那么解决方法是一致,编写一个公用的工具类解决
解决方法二:(推荐)
步骤1:新建一个工具类,getbeanTool
此工具类为之后加载资源的工具类,公用
@Component
public class GetBeanTool implements ApplicationContextAware{
private static ApplicationContext applicationContext = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
GetBeanTool.applicationContext = applicationContext;
}
public static Object getBeanByName(String beanName) {
if (applicationContext == null){
return null;
}
return applicationContext.getBean(beanName);
}
public static <T> T getBean(Class<T> type) {
return applicationContext.getBean(type);
}
}
步骤2:在线程、websocket等server中,加载资源
以WebSocketServer作为参考,如下修改:
private ManageUserMapper manageUserMapper;
public WebSocketServer() {
this.manageUserMapper=GetBeanTool.getBean(ManageUserMapper.class);
}
这么做你就不用在BootApplication中添加语句,来让你的server去调用资源了,一步到位,大家都能用,需要的时候直接通过getbeanTool去请求就行了
步骤3:解决tomcat开发环境,生产环境pom.xml中注释和打开内置tomcat的问题
这里需要修改BootApplication,如下修改:
@SpringBootApplication
@Configuration
public class BootApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(
SpringApplicationBuilder application) {
return application.sources(BootApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(BootApplication.class, args);
}
}
可以看到这里我继承了SpringBootServletInitializer ,同时重写了configure方法。采用这种写法,如论是开发还是测试,你都不用管是否需要注释内置的tomcat了,是不是很方便,至于原理,这里不解释,篇幅太长,自己去百度吧
总结:
1. 最近做了一个简单的IM功能,遇到了这些问题,作为记录,防止哪天我忘了
2. 网上解决方法的可能有用,但是写的不明不白,不友好,而且不见得好用,在解决问题的时候一定要考虑到通用性,开发一定要为了便利,不然坑了你也坑了被人,改这改那谁尼玛记得住
3. 此博文为本人自身角度进行编写,作为记录。如对他人有帮助,可以点个赞,本人不回复,不评论。
来源:https://blog.csdn.net/fyhju1/article/details/110111135


猜你喜欢
- 首先安装consul环境,参照之前的文章:https://www.jb51.net/article/141789.htm项目规划,2个服务端
- 这篇文章主要介绍了Spring Cloud基于zuul实现网关过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学
- 1、回顾一下大家有没有注意到,目前讲到的所有 controller 中的方法接收到请求之后,都是有返回值的,返回值主要有 2 种类型:1、
- 本文实例讲述了Java实现的Base64加密算法。分享给大家供大家参考,具体如下:一 算法实现1、JDK2、Commonc Codec3、B
- 这篇文章主要介绍了Springboot打包部署代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋
- 通常来说,多线程的并发及条件断点的debug是很难完成的,或许本篇文章会给你提供一个友好的调试方法。让你在多线程开发过程中的调试更加的有的放
- java生成json隐藏关键属性今天在工作中遇到一个这样的问题,当后端返回数据时一些关键信息或敏感信息并不想返回到前端,但是又懒得定义专用的
- 本文实例讲述了Android开发实现模仿微信小窗口功能。分享给大家供大家参考,具体如下:运用方法:将显示窗口的风格 设置为对话框风格即可具体
- AlertDialog可以在当前的界面上显示一个对话框,这个对话框是置顶于所有界面元素之上的,能够屏蔽掉其他控件的交互能力,因此AlertD
- C# 获取某个时间的0点0分和23点59分59秒,具体代码如下所示:C#获取当月第一天和最后一天当月第一天0时0分0秒:DateTime.N
- Java 实现汉字转换为拼音转换类public class PINYINChinese { private static int
- 问题我们发现,之所以我们现在离不开 xml 配置文件,是因为我们有一句很关键的配置:<!-- 告知spring框架在,读取配置文件,创
- 汉诺(Hanoi)塔问题:古代有一个梵塔,塔内有三个座A、B、C,A座上有n个盘子,盘子大小不等,大的在下,小的在上(如图)。有一个和尚想把
- 优点1.观察者和被观察者是抽象耦合的。2.建立一套触发机制。缺点1.如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知
- 基本功能刚拿到需求,很简单的一个功能,二话不说,很快就出来了:完美!顺利上线!没过几天领导拿着手机过来说:“这一堆数字在一起看着很费劲,像其
- 1、pom.xml文件添加distributionManagement节点。模块项目中如果存在父子项目,且父子项目的jar包都需要上传到 *
- 在计算机科学中,正则表达式是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。在很多文本编辑器或其他工具里,正则表达式通常被
- lombok插件使用引入依赖,在项目中使用Lombok可以减少很多重复代码的书写。比如说getter/setter/toString等方法的
- 去年就已经学了这个技术了,一直没去写,现在抽个时间写了个俄罗斯方块游戏。只有简单的新游戏,暂停,继续,积分功能。简单的实现了俄罗斯的经典功能
- 最近做了一个文件上传、下载、与在线打开文件的功能,刚开始对文件上传的界面中含有其它表单(例如输入框、密码等)在上传的过程中遇到了许多问题,下