반응형
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);
}
아무것도 모르고 시작한 본인은 하다보니 뭐... 별 무리없이 코드를 써내려가긴했었다.
코드의 좋고 나쁨을 아는 분은 조언 부탁드립니다.~
반응형
'WebSocket' 카테고리의 다른 글
[WebSocket] Interceptor 사용 및 검증 절차 방법 /HttpSessionHandShakeInterceptor 사용 (0) | 2021.02.01 |
---|---|
[WebSocket] Simple한 WebSocket Server구축하기-SPRING BOOT (0) | 2020.12.29 |
[WebSocket] Websocket 파라미터 전달하기(Custom Header관련) (0) | 2020.12.29 |
[WebSocket] WebSocket이란? (0) | 2020.12.29 |