WebSocket

[WebSocket] WebSocket Channeling(채널링) Java-Spring

Jeong Jeon
반응형

Java- SpringFramework 환경에서 WebSocket 채널링을 구현해보자

  • 채널링을 위한 HashMap을 생성한다
  • 본인은 가맹점 별 채널링을 구현하였다. 코드는 일부만 정리
	//회사별 접속한  소켓 세션 리스트 map
    public static HashMap<String,ArrayList<String>> companyChannelsessionListMap = new HashMap<String,ArrayList<String>>();

 

  • Interceptor를 만들어 Socket서버 접속 전 소켓서버에서 사용할 정보를 attribute에 담을수있다.
  • 추가로 로그인된 계정만 소켓 서버 접속할 수 있도록 접근제어를 걸수있는 점 ! 확인~
public class WebSocketHandShakeInterceptor extends HttpSessionHandshakeInterceptor {

    @Resource(name="redisTemplateDataBase0")
    private ValueOperations<String, Object> valueOps;

    @Resource(name="redisTemplateDataBase0")
    private HashOperations<String, String, Object> hashOpsDataBase0;

    /**
     * @desc 웹소켓 접속 직전 브라우저로 부터 전달받은 sid 값으로 redis 를 뒤저서 로그인 여부를 체크 하고
     * 로그인이 된 회원에 한해서 sid 값을 저장한다.
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
            Map<String, Object> attributes) throws Exception {
        // TODO Auto-generated method stub
        if (request instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest servletServerRequest = (ServletServerHttpRequest) request;
            HttpServletRequest servletRequest = servletServerRequest.getServletRequest();

            HashMap<String,String> queryMap = StringTool.getQueryMap(servletRequest.getQueryString());

            String token = queryMap.get("sid");
            int companyId =0;
            companyId = Integer.parseInt(queryMap.get("companyId"));

            System.out.println("SocketInterceptor = token : "+token+" / companyId : "+companyId+");
           
            if(StringUtils.isEmpty(token)) {
                return false;
            }
            //로그인 된 회원 여부 체크
            AccountVo accountVo = (AccountVo)valueOps.get(token);

            if(StringUtils.isEmpty(accountVo)) {
                return false;
            }else {
                //로그인 처리 되어 있는 경우에 세션아이디 어트리뷰트를 넣어줌.
                attributes.put("sid", token);
                return super.beforeHandshake(request, response, wsHandler, attributes);
            }
        }else{
            return false;
        }
    }

    /**
     * @desc 웹소켓 핸드쉐이크 후 호출 메소드
     */
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
            Exception ex) {
        // TODO Auto-generated method stub
        super.afterHandshake(request, response, wsHandler, ex);
    }



}

 

  • Socket 접속시 채널생성
    • 본인은 Redis에 Caching 되어있는 로그인한 계정의 정보를 끌고와서 현재 hashMap에 채널이 있는지 없는지를 판단하여 없으면 채널을만들고 SessionId를 넣고, 채널이 있으면 바로 SessionId를 넣는것으로 구현하였다.
 @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    	System.out.println("afterConnectionEstablished");
    	//
    	String sid = (String) session.getAttributes().get("sid");
    	//관리자Browser
    		AccountVo accountVo = (AccountVo)valueOpsDataBase0.get(sid);
    		//현재 접속한 회원의 회사 채널이 없을경우 빈 채널 생성
	    	if(StringUtils.isEmpty(companyChannelsessionListMap.get(String.valueOf(accountVo.getCompanyId())))) {
	    		companyChannelsessionListMap.put(String.valueOf(accountVo.getCompanyId()), new ArrayList<String>());
	    	}
	    	sessionMap.put(session.getId(), session);
	    	ArrayList<String> companyChannelSessionIdList = companyChannelsessionListMap.get(String.valueOf(accountVo.getCompanyId()));
	    	companyChannelSessionIdList.add(session.getId());

	    	super.afterConnectionEstablished(session);
	}

 

  • Socket 종료시 채널에 등록되어있는 Session정보 삭제 => 로그아웃이라고 보면 된다.
@Override
    public void afterConnectionClosed(WebSocketSession session,CloseStatus status) throws Exception {
    	System.out.println("afterConnectionClosed");
    	companyChannelsessionListMap.values().forEach((value) -> value.remove(session.getId()));
    	sessionMap.remove(session.getId());
    	super.afterConnectionClosed(session, status);
    }

 

아무것도 모르고 시작한 본인은 하다보니 뭐... 별 무리없이 코드를 써내려가긴했었다.

코드의 좋고 나쁨을 아는 분은 조언 부탁드립니다.~

반응형