익명 채팅방
package kh.spring.controller;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* Handles requests for the application home page.
*/
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "home";
}
}
package kh.spring.chat;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.RemoteEndpoint.Basic;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/chat")
public class WebChat {
private static Set<Session> clients = new HashSet<>();
@OnOpen
public void onConnect(Session client) {
System.out.println(client.getId()+" 클라이언트가 접속했습니다.");
clients.add(client);
}
@OnMessage
public void onMessage(Session session, String message) {
for(Session client : clients) {
if(!client.getId().contentEquals(session.getId())) {
Basic basic = client.getBasicRemote();
try {
basic.sendText(message);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
@OnClose
public void onClose(Session session) {
clients.remove(session);
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<style>
.chat-box {
width: 500px;
height: 500px;
float: left;
}
.message-area {
width: 100%;
height: 90%;
border: 1px solid #616161;
overflow-y: auto;
word-break: break-all;
}
.input-area {
width: 100%;
height: 10%;
border: 1px solid #616161;
overflow-y: auto;
}
</style>
<script>
$(function() {
var ws = new WebSocket("ws://localhost/chat")
ws.onmessage = function(e){
console.log(e.data);
var line = $("<div>");
line.append(e.data);
$(".message-area").append(line);
}
$(".input-area").on("keydown", function(e) {
if (e.keyCode == 13) {
e.preventDefault();
var text = $(".input-area").html();
var line = $("<div>");
line.append("글쓴이 : " + text);
$(".message-area").append(line);
$(".input-area").html("");
ws.send(text);
$('.message-area').scrollTop($('.message-area')[0].scrollHeight);
return false;
}
})
})
</script>
</head>
<body>
<div class="chat-box">
<div class="message-area"></div>
<div class="input-area" contenteditable="true"></div>
</div>
</body>
</html>
<!-- 웹소캣 라이브러리 추가 -->
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
</dependency>
HTTP 프로토콜이 아니라 웹소캣으로 접속하기 때문에
ip 주소와 웹 정보를 가져올수없음
session configurator
HTTPSessionConfigurator
object형을 리턴하기에 캐스팅 해줘야함
Map 방식
WebChat의 @ServerEndpoint 인자값 추가, 만든 httpSessionConfigurator 자료형 추가
핸드쉐이크로 만들어진 값이 config로 들어옴
다른 메서드에서도 쓸수 있도록
HomeController에서 session 사용 가능
서버에서 접속 url 수정 가능
package kh.spring.chat;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import javax.servlet.http.HttpSession;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.RemoteEndpoint.Basic;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import kh.spring.config.HTTPSessionConfigurator;
@ServerEndpoint(value="/chat",configurator = HTTPSessionConfigurator.class)
public class WebChat {
private static Set<Session> clients = new HashSet<>();
private HttpSession session;
@OnOpen
public void onConnect(Session client, EndpointConfig config) {
System.out.println(client.getId()+" 클라이언트가 접속했습니다.");
clients.add(client);
this.session = (HttpSession) config.getUserProperties().get("session");
}
@OnMessage
public void onMessage(Session session, String message) {
String id = (String)this.session.getAttribute("loginId");
for(Session client : clients) {
if(!client.getId().contentEquals(session.getId())) {
Basic basic = client.getBasicRemote();
try {
basic.sendText(id+ " : "+message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@OnClose
public void onClose(Session session) {
clients.remove(session);
}
}
package kh.spring.config;
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 HTTPSessionConfigurator extends Configurator{
@Override
public void modifyHandshake(
ServerEndpointConfig sec,
HandshakeRequest request,
HandshakeResponse response) {
HttpSession session = (HttpSession)request.getHttpSession();
sec.getUserProperties().put("session", session);
}
}
package kh.spring.controller;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class HomeController {
@Autowired
private HttpSession session;
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
this.session.setAttribute("loginId", "Jack");
return "home";
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<style>
.chat-box {
width: 500px;
height: 500px;
float: left;
}
.message-area {
width: 100%;
height: 90%;
border: 1px solid #616161;
overflow-y: auto;
word-break: break-all;
}
.input-area {
width: 100%;
height: 10%;
border: 1px solid #616161;
overflow-y: auto;
}
</style>
<script>
$(function() {
var ws = new WebSocket("ws://192.168.60.7/chat")
ws.onmessage = function(e){
console.log(e.data);
var line = $("<div>");
line.append(e.data);
$(".message-area").append(line);
}
$(".input-area").on("keydown", function(e) {
if (e.keyCode == 13) {
e.preventDefault();
var text = $(".input-area").html();
var line = $("<div>");
line.append("글쓴이 : " + text);
$(".message-area").append(line);
$(".input-area").html("");
ws.send(text);
$('.message-area').scrollTop($('.message-area')[0].scrollHeight);
return false;
}
})
})
</script>
</head>
<body>
<div class="chat-box">
<div class="message-area"></div>
<div class="input-area" contenteditable="true"></div>
</div>
</body>
</html>
동시성 오류
동기화 작업 필요
HashSet 에 동기화 작업을 할 수 있도록 업그레이드
일반 HashSet은 동시성에 대한 취약성이 있다.
에러 처리
연결 끊어버리기
@OnError
public void onError(Session session, Throwable t) {
clients.remove(session);
}
메세지를 보내는 중 한명이 나갈경우
for문이 도는 동안 정지
없는 사람에게 보낼 수 없음
@OnMessage
public void onMessage(Session session, String message) {
String id = (String)this.session.getAttribute("loginId");
synchronized(clients){
for(Session client : clients) {
if(!client.getId().contentEquals(session.getId())) {
Basic basic = client.getBasicRemote();
try {
basic.sendText(id+ " : "+message);
} catch (IOException e) {}
}
}
}
}
굳이 나간 사람 때문에 발생한 에러 메시지를 출력할 필요 없음
'디지털 컨버전스 > Spring' 카테고리의 다른 글
[spring mvc] 이메일인증 (0) | 2020.06.22 |
---|---|
[Spring MVC] 게시판 파일 경로 생성 못하는 문제 해결 (0) | 2020.06.15 |
[Spring Framework] WebChat - 익명채팅 (0) | 2020.06.12 |
[Spring Framework] AOP:around - 로그인 체크 (0) | 2020.06.12 |
[Spring Framework] AOP:before , AOP:around (0) | 2020.06.11 |