Browse Source

新增基于命令的websocket服务接口,新增websocket消息推送接口。新增测试类

zh.sqy 9 years ago
parent
commit
bf694e0a55

+ 19 - 1
hsweb-web-websocket/pom.xml

@@ -10,7 +10,25 @@
     <modelVersion>4.0.0</modelVersion>
     <modelVersion>4.0.0</modelVersion>
 
 
     <artifactId>hsweb-web-websocket</artifactId>
     <artifactId>hsweb-web-websocket</artifactId>
-    <version>1.0-SNAPSHOT</version>
+    <version>${parent.version}</version>
 
 
 
 
+    <dependencies>
+        <dependency>
+            <groupId>org.hsweb</groupId>
+            <artifactId>hsweb-web-bean</artifactId>
+            <version>${parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+            <version>${spring.boot.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-logging</artifactId>
+            <version>${spring.boot.version}</version>
+        </dependency>
+    </dependencies>
 </project>
 </project>

+ 69 - 0
hsweb-web-websocket/src/main/java/org/hsweb/web/socket/CmdWebSocketHandler.java

@@ -0,0 +1,69 @@
+package org.hsweb.web.socket;
+
+import com.alibaba.fastjson.JSON;
+import org.hsweb.web.bean.po.user.User;
+import org.hsweb.web.socket.cmd.CMD;
+import org.hsweb.web.socket.cmd.CmdProcessor;
+import org.hsweb.web.socket.cmd.CmdProcessorContainer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.socket.CloseStatus;
+import org.springframework.web.socket.TextMessage;
+import org.springframework.web.socket.WebSocketSession;
+import org.springframework.web.socket.handler.TextWebSocketHandler;
+
+import javax.annotation.Resource;
+
+/**
+ * 基于命令的socket处理器
+ * Created by 浩 on 2015-09-08 0008.
+ */
+@Component
+public class CmdWebSocketHandler extends TextWebSocketHandler {
+
+    protected Logger logger = LoggerFactory.getLogger(this.getClass());
+
+    @Resource
+    private CmdProcessorContainer processorContainer;
+
+    @Override
+    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
+        if (logger.isInfoEnabled())
+            logger.info("handleMessage,id:{} msg={}", session.getId(), message.getPayload());
+        try {
+            CMD request = JSON.parseObject(message.getPayload(), CMD.class);
+            CmdProcessor processor = processorContainer.getCmdProcessor(request.getCmd());
+            if (null != processor) {
+                request.setSession(session);
+                processor.exec(request);
+            }
+        } catch (Exception e) {
+            logger.error("handleTextMessage error!", e);
+        }
+    }
+
+    private User getUser(WebSocketSession session) {
+        return (User) session.getAttributes().get("user");
+    }
+
+    @Override
+    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
+        User user = getUser(session);
+//        if (user == null) {
+//            session.close(CloseStatus.BAD_DATA.withReason("请登陆!"));
+//            return;
+//        }
+        for (CmdProcessor processor : processorContainer.getAll()) {
+            processor.onSessionClose(session);
+        }
+    }
+
+    @Override
+    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
+        for (CmdProcessor processor : processorContainer.getAll()) {
+            processor.onSessionClose(session);
+        }
+    }
+
+}

+ 25 - 0
hsweb-web-websocket/src/main/java/org/hsweb/web/socket/WebSocketSessionListener.java

@@ -0,0 +1,25 @@
+package org.hsweb.web.socket;
+
+import org.springframework.web.socket.WebSocketSession;
+
+/**
+ * Created by 浩 on 2016-01-19 0019.
+ */
+public interface WebSocketSessionListener {
+    /**
+     * 当session创建时,调用此方法
+     *
+     * @param session WebSocketSession 实例
+     * @throws Exception
+     */
+    void onSessionConnect(WebSocketSession session) throws Exception;
+
+    /**
+     * 当session关闭时,调用此方法
+     *
+     * @param session WebSocketSession 实例
+     * @throws Exception
+     */
+    void onSessionClose(WebSocketSession session) throws Exception;
+
+}

+ 49 - 0
hsweb-web-websocket/src/main/java/org/hsweb/web/socket/cmd/CMD.java

@@ -0,0 +1,49 @@
+package org.hsweb.web.socket.cmd;
+
+import org.springframework.web.socket.WebSocketSession;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * websocket命令
+ * Created by 浩 on 2016-01-19 0019.
+ */
+public class CMD {
+
+    private String cmd;
+
+    /**
+     * 发送命令的会话
+     */
+    private transient WebSocketSession session;
+
+    /**
+     * 命令参数
+     */
+    private Map<String, Object> params = new LinkedHashMap<>();
+
+    public WebSocketSession getSession() {
+        return session;
+    }
+
+    public void setSession(WebSocketSession session) {
+        this.session = session;
+    }
+
+    public Map<String, Object> getParams() {
+        return params;
+    }
+
+    public void setParams(Map<String, Object> params) {
+        this.params = params;
+    }
+
+    public String getCmd() {
+        return cmd;
+    }
+
+    public void setCmd(String cmd) {
+        this.cmd = cmd;
+    }
+}

+ 34 - 0
hsweb-web-websocket/src/main/java/org/hsweb/web/socket/cmd/CmdProcessor.java

@@ -0,0 +1,34 @@
+package org.hsweb.web.socket.cmd;
+
+
+import org.hsweb.web.socket.WebSocketSessionListener;
+
+/**
+ * 基于命令的wesocket执行器
+ * Created by 浩 on 2015-09-08 0008.
+ */
+public interface CmdProcessor extends WebSocketSessionListener {
+    /**
+     * 获取命令名称
+     *
+     * @return 命令名称
+     */
+    String getName();
+
+    /**
+     * 执行命令
+     *
+     * @param cmd 要执行的命令
+     * @return 执行结果
+     * @throws Exception 异常
+     */
+    void exec(CMD cmd) throws Exception;
+
+
+    /**
+     * 初始化方法,用于自动注册命令等操作
+     *
+     * @throws Exception
+     */
+    void init() throws Exception;
+}

+ 47 - 0
hsweb-web-websocket/src/main/java/org/hsweb/web/socket/cmd/CmdProcessorContainer.java

@@ -0,0 +1,47 @@
+package org.hsweb.web.socket.cmd;
+
+import java.util.List;
+
+/**
+ * cmd处理器容器,用于注册和获取命令处理器
+ * Created by 浩 on 2016-01-19 0019.
+ */
+public interface CmdProcessorContainer {
+
+    /**
+     * 根据命令名获取一个命令处理器
+     *
+     * @param name 命令名称
+     * @return 处理器实例,处理器不存在则返回null
+     */
+    CmdProcessor getCmdProcessor(String name);
+
+    /**
+     * 向容器中注册一个命令处理器
+     *
+     * @param processor 处理器实例
+     * @return 注册后的处理器实例
+     */
+    CmdProcessor registerCmdProcessor(CmdProcessor processor);
+
+    /**
+     * 从容器中注销一个命令处理器
+     *
+     * @param name 要注销命令名称
+     * @return 被注销的处理器实例
+     */
+    CmdProcessor cancelCmdProcessor(String name);
+
+    /**
+     * 获取所有命令处理器
+     *
+     * @return
+     */
+    List<CmdProcessor> getAll();
+
+    /**
+     * 容器初始化
+     */
+    void init();
+
+}

+ 61 - 0
hsweb-web-websocket/src/main/java/org/hsweb/web/socket/cmd/SpringCmdProcessorContainer.java

@@ -0,0 +1,61 @@
+package org.hsweb.web.socket.cmd;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
+import org.springframework.web.bind.annotation.InitBinder;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * spring管理的处理器容器
+ * Created by 浩 on 2016-01-19 0019.
+ */
+@Component
+public class SpringCmdProcessorContainer implements CmdProcessorContainer {
+
+
+    private Map<String, CmdProcessor> cache = new HashMap<>();
+
+    @Resource
+    private ApplicationContext applicationContext;
+
+    @Override
+    public CmdProcessor getCmdProcessor(String name) {
+        return cache.get(name);
+    }
+
+    @Override
+    public CmdProcessor registerCmdProcessor(CmdProcessor processor) {
+        return cache.put(processor.getName(), processor);
+    }
+
+    @Override
+    public CmdProcessor cancelCmdProcessor(String name) {
+        return cache.remove(name);
+    }
+
+    @Override
+    public List<CmdProcessor> getAll() {
+        return new ArrayList<>(cache.values());
+    }
+
+    /**
+     * 通过获取spring管理的bean,向容器注册处理器
+     */
+    @Override
+    @PostConstruct
+    public void init() {
+        Map<String, CmdProcessor> processorMap = applicationContext.getBeansOfType(CmdProcessor.class);
+        if (processorMap != null) {
+            for (CmdProcessor cmdProcessor : processorMap.values()) {
+                registerCmdProcessor(cmdProcessor);
+            }
+        }
+    }
+}

+ 89 - 0
hsweb-web-websocket/src/main/java/org/hsweb/web/socket/message/WebSocketMessage.java

@@ -0,0 +1,89 @@
+package org.hsweb.web.socket.message;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * websocket消息
+ * Created by 浩 on 2016-01-19 0019.
+ */
+public class WebSocketMessage implements Serializable {
+    private static final long serialVersionUID = 755525816405705645L;
+    /**
+     * 接收者
+     */
+    private String to;
+
+    /**
+     * 发送者
+     */
+    private String from;
+
+    /**
+     * 消息类型
+     */
+    private String type;
+
+    /**
+     * 消息内容
+     */
+    private String content;
+
+    /**
+     * 发送日期
+     */
+    private Date sendTime;
+
+    /**
+     * 前端回掉,前端注册了此消息的回掉后,在接收到消息时,会自动触发该回掉
+     */
+    private String callBack;
+
+    public String getTo() {
+        return to;
+    }
+
+    public void setTo(String to) {
+        this.to = to;
+    }
+
+    public String getFrom() {
+        return from;
+    }
+
+    public void setFrom(String from) {
+        this.from = from;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getContent() {
+        return content;
+    }
+
+    public void setContent(String content) {
+        this.content = content;
+    }
+
+    public Date getSendTime() {
+        return sendTime;
+    }
+
+    public void setSendTime(Date sendTime) {
+        this.sendTime = sendTime;
+    }
+
+    public String getCallBack() {
+        return callBack;
+    }
+
+    public void setCallBack(String callBack) {
+        this.callBack = callBack;
+    }
+}

+ 19 - 0
hsweb-web-websocket/src/main/java/org/hsweb/web/socket/message/WebSocketMessageManager.java

@@ -0,0 +1,19 @@
+package org.hsweb.web.socket.message;
+
+import org.hsweb.web.socket.WebSocketSessionListener;
+
+/**
+ * websocket消息管理器,用于使用websocket进行消息推送
+ * Created by 浩 on 2016-01-19 0019.
+ */
+public interface WebSocketMessageManager extends WebSocketSessionListener {
+
+    /**
+     * 发送一个消息
+     *
+     * @param message 消息实例
+     * @return 是否发送成功
+     */
+    boolean send(WebSocketMessage message);
+
+}

+ 35 - 0
hsweb-web-websocket/src/test/java/org/hsweb/web/socket/WebSocketTest.java

@@ -0,0 +1,35 @@
+package org.hsweb.web.socket;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.config.annotation.WebSocketConfigurationSupport;
+import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
+
+/**
+ * Created by 浩 on 2016-01-19 0019.
+ */
+@Configuration
+@ComponentScan(basePackages = "org.hsweb.web.socket")
+@EnableAutoConfiguration
+public class WebSocketTest extends WebSocketConfigurationSupport {
+
+    @Autowired
+    private CmdWebSocketHandler cmdWebSocketHandler;
+
+    @Override
+    protected void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
+        registry.addHandler(cmdWebSocketHandler, "/socket");
+    }
+
+    public static void main(String[] args) {
+        SpringApplication.run(WebSocketTest.class);
+        //运行成功后 请使用浏览器打开: http://localhost:8080
+        //忽略错误提示,按F12,进入console。
+        //运行:var ws = new WebSocket('ws://localhost:8080/socket');
+        //运行:ws.send('{"cmd":"test"}'); 按回车
+        //如果看到后台日志显示 handleMessage,id:0 msg={"cmd":"test"} 则代表成功了
+    }
+}