(一)添加socket服务
因为项目基于 springboot 框架,要提供 socket 服务,网上查资料好多说是要添加 websocket 组件,感觉挺麻烦就没去看,直接使用原始的方式写个 socket 服务类,然后在 springboot 启动类的 main 方法中,添加 socket 服务启动方法。
1.socket服务类代码如下(网上有好多例子,随便拿了个模板略作修改):
import java.io.*;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Set;
/**
* nio socket服务端
*/
public class SocketServer {
//解码buffer
private Charset cs = Charset.forName("UTF-8");
//接受数据缓冲区
private static ByteBuffer sBuffer = ByteBuffer.allocate(1024);
//发送数据缓冲区
private static ByteBuffer rBuffer = ByteBuffer.allocate(1024);
//选择器(叫监听器更准确些吧应该)
private static Selector selector;
/**
* 启动socket服务,开启监听
* @param port
* @throws IOException
*/
public void startSocketServer(int port){
try {
//打开通信信道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//设置为非阻塞
serverSocketChannel.configureBlocking(false);
//获取套接字
ServerSocket serverSocket = serverSocketChannel.socket();
//绑定端口号
serverSocket.bind(new InetSocketAddress(port));
//打开监听器
selector = Selector.open();
//将通信信道注册到监听器
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
//监听器会一直监听,如果客户端有请求就会进入相应的事件处理
while (true){
selector.select();//select方法会一直阻塞直到有相关事件发生或超时
Set<SelectionKey> selectionKeys = selector.selectedKeys();//监听到的事件
for (SelectionKey key : selectionKeys) {
handle(key);
}
selectionKeys.clear();//清除处理过的事件
}
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 处理不同的事件
* @param selectionKey
* @throws IOException
*/
private void handle(SelectionKey selectionKey) throws IOException {
ServerSocketChannel serverSocketChannel = null;
SocketChannel socketChannel = null;
String requestMsg = "";
int count = 0;
if (selectionKey.isAcceptable()) {
//每有客户端连接,即注册通信信道为可读
serverSocketChannel = (ServerSocketChannel)selectionKey.channel();
socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
}
else if (selectionKey.isReadable()) {
socketChannel = (SocketChannel)selectionKey.channel();
rBuffer.clear();
count = socketChannel.read(rBuffer);
//读取数据
if (count > 0) {
rBuffer.flip();
requestMsg = String.valueOf(cs.decode(rBuffer).array());
}
String responseMsg = "已收到客户端的消息:"+requestMsg;
//返回数据
sBuffer = ByteBuffer.allocate(responseMsg.getBytes("UTF-8").length);
sBuffer.put(responseMsg.getBytes("UTF-8"));
sBuffer.flip();
socketChannel.write(sBuffer);
socketChannel.close();
}
}
}2.在 springboot 启动类 main 方法中添加 socket 服务端启动代码import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.xxx.mapper")
public class PlatformApplication {
public static void main(String[] args) {
SpringApplication.run(PlatformApplication.class, args);
//起socket服务
SocketServer server = new SocketServer();
server.startSocketServer(8088);
}
}
(二 )获取 spring bean
因为没使用 websocket 组件,在 SocketServer 类中使用注解方式注入到 spring 容器中的 Service 会存在问题,举个例子:
数据持久层使用了 mybatis 框架,如果实现数据持久化,需要如下文件
1.实体类 entity.java
2.sql 映射文件 mapper.xml
3.mapper 接口类 mapper.java
4.service 接口类 service.java
5.service 实现类 serviceimpl,java
现在需要做个查询,通常情况下是调用注入的 service 的 find 方法,过程应该是先获取 注入的 service(即 serviceimpl 的实例),再获取注入到 service 的 mapper ,
最后通过 mapper.xml 配置文件获取相应的 sql 到数据库查询。
SocketServer 作为普通类是无法将 servcie 注入进来的,那通过 new 一个实例的方法可以吗?不可以! new 出来的 serviceimpl 的实例中 mapper 是 null 。所以我们只能从 spring 容器中获取 serviceimpl bean ,得到的 bean 中 mapper 就不是 null 了。
首先,创建从 spring 容器中获取 bean 的工具类:
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* Created by
*/
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
}
//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
//通过class获取Bean.
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
//通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name,Class<T> clazz){
return getApplicationContext().getBean(name, clazz);
}
}然后在使用的时候调用下:
Service service = SpringUtil.getBean(ServiceImpl.class);
这样,就能在普通类中获取注解方式注入到 spring 容器中的 bean 了。
本文介绍了如何在SpringBoot项目中不使用websocket组件,而是通过创建普通的socket服务类来实现socket服务。在遇到普通类无法直接注入Service的问题时,通过SpringUtil工具类从Spring容器中获取bean,确保能够正确使用注入的Mapper和服务。
1万+

被折叠的 条评论
为什么被折叠?



