Spring Boot分布式系统实践【基础模块构建3.2】集成websocket,做扫码二维码登录

添加依赖

    
        org.springframework.boot    
        spring-boot-starter-websocket
 

注入ServerEndpointExporter

这个bean会自动注册使用了@ServerEndpoint注解声明的Websocket endpoint。

 package com.halburt.site.common.socket.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

websocket实现

@ServerEndpoint(value = "/web/admin/anon/ws")
@Component
public class TestWebSocket {
    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    // concurrent包的线程安全Set,用来存放每个客户端对应的ProductWebSocket对象。
    private static ConcurrentHashMap webSocketSet = new ConcurrentHashMap();
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        webSocketSet.put(session.getId() , this);
        try {
            session.getBasicRemote().sendText("sessionId="+session.getId());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session) {
        webSocketSet.remove(session.getId());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) throws IOException, EncodeException {
        session.getBasicRemote().sendText(JsonResult.success("来自客户端的消息:"+message).toJSONString());
        System.out.println("来自客户端的消息:" + message);

    }
    /**
     * 服务器端调用,发送消息
     * @param sessionId
     * @param message
     * @throws IOException
     */
    public static void sendMessage(String sessionId ,JSONObject message) throws IOException {
        Session s =  webSocketSet.get(sessionId).session;
        if(null != s){
            try {
                s.getBasicRemote().sendText(message.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 发生错误时调用
     *
     * @OnError
     */
    public void onError(Session session, Throwable error) {
        System.out.println("发生错误");
        error.printStackTrace();
    }

}

注意

private static ConcurrentHashMap webSocketSet = new ConcurrentHashMap();

javax.websocket.Session只会与当前连接的服务进行通信,无法与掐服务器连接。所以不用想着用分布式情况下,进行redis缓存session,单机情况下本地ConcurrentHashMap存储session。【分布式情况暂考虑使用redis发布订阅】

添加登录页面

   @GetMapping("/web/admin/anon/qrLogin")
    public String qrLogin() {

        return "ws/qrLogin.html";
    }


    
    
    


image.png

扫描

   @ResponseBody
    @GetMapping("/web/admin/anon/login2")
    public String login(Model model,String sessionId) {
        String userId = "1";//此处应该从扫描机器获取用户信息
        try {
            TestWebSocket.sendMessage(sessionId, JsonResult.success( "已经扫描"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        //此处应该跳转一个页面
        return "OK000";
    }

扫描之后确认登录

此处应该设计加密规则

   @ResponseBody
    @GetMapping("/web/admin/anon/logined")
    public String logined(Model model,String sessionId) {
        String userId = "1";//此处应该从扫描机器获取用户信息
        try {
            TestWebSocket. sendMessage(sessionId, JsonResult.success( UserUtils.getSysUserById(userId)));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "OK000";
    }

你可能感兴趣的:(Spring Boot分布式系统实践【基础模块构建3.2】集成websocket,做扫码二维码登录)