【分享】JFinal WebSocket onOpen 中获取 连接客户端的IP

  1. 新建监听ServletRequest事件,发生在创建WebSocket的session之前

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

public class WebServletRequestListener implements ServletRequestListener {
    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
    }
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        HttpServletRequest request=(HttpServletRequest) sre.getServletRequest();
        HttpSession session=request.getSession();
        //把HttpServletRequest中的IP地址放入HttpSession中,关键字可任取,此处为ClientIP
        session.setAttribute("client-ip", sre.getServletRequest().getRemoteAddr());
    }
}

2. 创建 ServerEndpoint 配置类

import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import javax.websocket.server.ServerEndpointConfig.Configurator;

public class GetHttpSessionConfigurator extends Configurator {
    @Override
    public void modifyHandshake(ServerEndpointConfig sec,
                                HandshakeRequest request, HandshakeResponse response) {
        // TODO Auto-generated method stub
        HttpSession httpSession = (HttpSession) request.getHttpSession();
        sec.getUserProperties().put(HttpSession.class.getName(), httpSession);
        //把HttpSession中保存的ClientIP放到ServerEndpointConfig中,关键字可以跟之前不同
        sec.getUserProperties().put("client-ip", httpSession.getAttribute("client-ip"));
    }

}

3. 创建 WebSocket 主类

import cn.hutool.core.date.DateUtil;
import com.*.*.core.config.GetHttpSessionConfigurator;
import plus.jfinal.entitys.Result;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * /websocket.ws/{id} = /websocket.ws/{登录用户编号}
 */
@ServerEndpoint(value ="/websocket.ws/{id}",configurator= GetHttpSessionConfigurator.class)
public class MainWebSocket {

    private static final Map<String, MainWebSocket> WEBSOCKET = new ConcurrentHashMap<String, MainWebSocket>();

    private Session session;

    private String host;

    private HttpSession httpSession;
    /**
     * 用户登录账号
     */
    private String id;

    @OnOpen
    public void onOpen( Session session,EndpointConfig config,@PathParam("id") String id) {
        this.id = id;
        this.session = session;
        // 这里就获得到IP咯
        System.out.println("客户端请求IP:"+session.getUserProperties().get("client-ip"));
        // ....
    }

    @OnClose
    public void onClose() {
        if (WEBSOCKET != null && WEBSOCKET.containsKey(id)){
            MainWebSocket webSocket = WEBSOCKET.get(id);
            if(webSocket.session.getId().equals(session.getId())){
                WEBSOCKET.remove(id);
            }
        }
        System.out.println("有一连接关闭!当前在线人数为" + WEBSOCKET.size());
    }

    @OnMessage
    public void onMessage(String message, Session session) {
        /* 不接收前端发送的消息 */
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    protected void sendMessage(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 广播
     *
     * @param message
     */
    public static void broadcast(String message) {
        for (Map.Entry<String, MainWebSocket> entry : WEBSOCKET.entrySet()) {
            entry.getValue().sendMessage(message);
        }
    }

    /**
     * 发送消息
     * @param id
     * @param message
     */
    public static void sendMessage(String id,String message){
        WEBSOCKET.get(id).sendMessage(message);
    }

}

4. 配置启动类(任意位置)

public static void main(String[] args) {
    /**
     * 启动前先删除掉之前的进程
     */
    closeProccess(args);
    /**
     *
     */
    UndertowServer.create(ApplicationConfig.class, "config/undertow.txt").configWeb(builder  -> {
        builder.addListener("com.*.*.core.listener.WebServletRequestListener");
        builder.addWebSocketEndpoint("com.*.*.websocket.MainWebSocket");
    }).addHotSwapClassPrefix("com.*").addHotSwapClassPrefix("plus.jfinal").start();
}


评论区

JFinal

2019-12-09 17:03

十分简洁的方案, 谢谢分享,赞

dongcb678

2019-12-12 15:57

不错,简洁有效