赞
踩
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <springboot.version>2.2.1.RELEASE</springboot.version> <java.version>1.8</java.version> <swagger.version>2.7.0</swagger.version> <lombok.version>1.18.10</lombok.version> </properties> <dependencies> <!--Springboot--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <!--swagger--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${swagger.version}</version> </dependency> <!--swagger ui--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>${swagger.version}</version> </dependency> <!--lombok用来简化实体类:需要安装lombok插件--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> <scope>provided</scope> </dependency> <!-- webSocket 集成 springboot--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency> </dependencies>
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter; @Configuration public class WebSocketConfig { /** * 向spring容器中注入这个ServerEndpointExporter对象 * @return */ @Bean public ServerEndpointExporter serverEndpointExporter(){ return new ServerEndpointExporter(); } }
decoders = {OperatorDecoder.class},
encoders = {OperatorEncoder.class}
是进行webSocketMessage和实体类之间映射关系的类
import com.camera.entity.LoginCamera; import com.camera.entity.Operator; import com.camera.entity.OperatorDecoder; import com.camera.entity.OperatorEncoder; import com.camera.service.CloudService; import com.camera.service.LoginService; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.websocket.*; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.atomic.AtomicInteger; @ServerEndpoint(value = "/ptzControl",decoders = {OperatorDecoder.class},encoders = {OperatorEncoder.class}) @Component public class WebSocketServer { //在WebSocket也是这样注入,因 SpringBoot+WebSocket 对每个客户端连接都会创建一个 WebSocketServer(@ServerEndpoint 注解对应的)对象, // Bean 注入操作会被直接略过,因而手动注入一个全局变量 private static final AtomicInteger OnlineCount = new AtomicInteger(0); // concurrent包的线程安全Set,用来存放每个客户端对应的Session对象。 private static CopyOnWriteArraySet<Session> SessionSet = new CopyOnWriteArraySet<Session>(); private static CloudService cloudService = new CloudServiceImpl(); @PostConstruct public void init(){ System.out.println("websocket loading"); } /** * 连接建立成功调用方法 * @param session */ @OnOpen public void onOpen(Session session){ SessionSet.add(session); OnlineCount.incrementAndGet(); // 在线数+1 SendMessage(session,"连接成功"); // 告知客户端连接成功 } /** * 连接关闭调用方法 */ @OnClose public void onClose(Session session){ loginService.logOutAndCleanUp(); SessionSet.remove(session); OnlineCount.decrementAndGet(); } /** * 收到客户端消息后调用的方法 * (这一部分有些丑啊 别骂 别骂) */ @OnMessage public void onMessage(Operator operator, Session session){ SendMessage(session,"接收到消息,消息内容:"+ operator); System.out.println(operator.toString()); if ("moveLeft".equals(operator.getOperate())) cloudService.moveLeft(operator.getNChannelID(), operator.getIparam2()); if ("moveRight".equals(operator.getOperate())) cloudService.moveRight(operator.getNChannelID(), operator.getIparam2()); if ("moveUp".equals(operator.getOperate())) cloudService.moveUp(operator.getNChannelID(), operator.getIparam2()); if ("moveDown".equals(operator.getOperate())) cloudService.moveDown(operator.getNChannelID(), operator.getIparam2()); } /** * 出现错误 */ @OnError public void onError(Session session,Throwable error){ error.printStackTrace(); } /** * 发送消息 实践表明 每次浏览器刷新 session会发生变化 */ public static void SendMessage(Session session,String message){ try { session.getBasicRemote().sendText(String.format("%s (From Server,Session ID=%s)",message,session.getId())); session.getBasicRemote().sendText(message); } catch (IOException e) { e.printStackTrace(); } } /** * 群发消息 */ public static void BroadCastInfo(String message) throws IOException { for (Session session : SessionSet) { if (session.isOpen()) SendMessage(session,message); } } /** * 指定Session发送消息 * @param sessionId * @param message * @throws IOException */ public static void SendMessage(String message,String sessionId) throws IOException { Session session = null; for (Session s : SessionSet) { if(s.getId().equals(sessionId)){ session = s; break; } } if(session!=null) SendMessage(session, message); } }
import com.alibaba.fastjson.JSON; import javax.websocket.EncodeException; import javax.websocket.Encoder; import javax.websocket.EndpointConfig; /** * 将JSON编码为entity */ public class OperatorEncoder implements Encoder.Text<Operator> { /** * 发送编码 entity->json * @param object * @return * @throws EncodeException */ @Override public String encode(Operator object) throws EncodeException { return JSON.toJSONString(object); } @Override public void init(EndpointConfig endpointConfig) { } @Override public void destroy() { } }
import com.alibaba.fastjson.JSON; import javax.websocket.Decoder; import javax.websocket.EndpointConfig; /** * 解码 json-> entity映射 */ public class OperatorDecoder implements Decoder.Text<Operator> { /** * 转换json->entity * @param move * @return */ @Override public Operator decode(String move) { return JSON.parseObject(move, Operator.class); } /** * 是否进行转换 * @param s * @return */ @Override public boolean willDecode(String s) { return true; } @Override public void init(EndpointConfig endpointConfig) { } @Override public void destroy() { } }
至此,即可使用
1、空指针
在WebSocket也是这样注入,因 SpringBoot+WebSocket
对每个客户端连接都会创建一个WebSocketServer对象,Bean
注入操作会被直接略过,因而手动注入一个全局变量
2、主动发送消息时如果需要发送entity类型的数据使用
session.getBasicRemote().sendObject();
3、解码时报错无法解析
willDecode()会在decode()之前执行,查看是否被拦截导致无法转换
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。