🌀 스프링 소켓이란?
Spring Socket는 Spring Framework에서 제공하는 WebSocket 프로토콜을 지원하는 기능이다. 실시간 양방향 통신을 위한 프로토콜로, 서버와 클라이언트 간에 지속적인 연결을 유지하고 데이터를 실시간으로 주고받을 수 있게 해준다.
스프링에서 소켓을 다루기 전 JSP 에서 소켓을 만들어본다.
JSP 에서 작업함.
지난 시간 서버 측 작성
ChatServer.java - 서버
package websocket;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/ChatingServer") // 서버명
public class ChatServer {
private static Set<Session> clients = Collections.synchronizedSet(new HashSet<Session>());
@OnOpen // 클라이언트 접속 시 실행
public void onOpen(Session session) {
clients.add(session);
System.out.println("웹소켓 연결 :" + session.getId());
}
@OnMessage // 메세지를 받으면 실행
public void onOMessgae(String message,Session session) throws IOException {
System.out.println("메시지 전송 : " + session.getId() + ":" + message);
synchronized(clients) {
for(Session client : clients) { //모든 클라이언트에게 메세지 전달
if(!clients.equals(session)) {
client.getBasicRemote().sendText(message); }
}
}
}
@OnClose // 클라이언트와 연결의 끊기면 실행
public void onClose(Session session) {
clients.remove(session);
System.out.println("웹소켓 종료 :" + session.getId());
}
@OnError // 에레 발생 시 실행
public void onError(Throwable e) {
System.out.println("에러 발생");
e.printStackTrace();
}
}
web.xml 에서
<!-- 웹소켓 채팅 서버 -->
<context-param>
<param-name>CHAT_ADDR</param-name>
<param-value>http://localhost:9999/WebSocketProject</param-value>
</context-param>
위 정보를 추가해줘야 한다.
추가된 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
<display-name>FristJsp</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.jsp</welcome-file>
<welcome-file>default.htm</welcome-file>
</welcome-file-list>
<context-param>
<param-name>INIT_PARAM</param-name>
<param-value>web.xl에 저장한 초기화 매개 변수</param-value>
</context-param>
<!-- 오라클 설정 정보 -->
<!-- 지금 우리는 드라이버 정보를 초기화 시켜놓았다. 코드에 노출 시키지 않았으며, 앞으로도 이 방법을 쓸 것이다. -->
<context-param>
<param-name>OracleDriver</param-name>
<param-value>oracle.jdbc.driver.OracleDriver</param-value>
</context-param>
<context-param>
<param-name>OracleURL</param-name>
<param-value>jdbc:oracle:thin:@localhost:1522:orcl1</param-value>
</context-param>
<context-param>
<param-name>OracleId</param-name>
<param-value>musthave</param-value>
</context-param>
<context-param>
<param-name>OraclePwd</param-name>
<param-value>1234</param-value>
</context-param>
<!-- 머스트 해브 -->
<!-- <context-param>
<param-name>OracleId2</param-name>
<param-value>musthave</param-value>
</context-param> -->
<!-- 페이징 정보 -->
<context-param>
<param-name>POSTS_PER_PAGE</param-name>
<param-value>10</param-value>
</context-param>
<!-- 한 페이지에 출력할 갯수 -->
<context-param>
<param-name>PAGES_PER_BLOCK</param-name>
<param-value>5</param-value>
</context-param>
<!-- 페이지 목록의 수 -->
<!-- 첨부 파일 최대 용량 설정(예제 14-8) -->
<context-param>
<param-name>maxPostSize</param-name>
<param-value>1024000</param-value>
</context-param>
<!-- 웹소켓 채팅 서버 -->
<context-param>
<param-name>CHAT_ADDR</param-name>
<param-value>http://localhost:9999/WebSocketProject</param-value>
</context-param>
<filter>
<filter-name>SetCharEncoding</filter-name>
<filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>SetCharEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
웹소켓으로 채팅 구현 시 사용하는 5가지 어노테이션
@ServerEndpoint
@OnOpen
@OnMessage
@OnClose
@OnError
💡 웹소켓 주소 구성 : ws://호스트명:포드번호/컨텍스트(프로젝트명)/서버명 ws://http://localhost:9999/WebSocketProject/WEB-INF/classes/websocket/ChatServer.java
MutiChatMain.jsp - 실행시킬 화면
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script>
function chatWinOpen() {
let id = document.getElementById("chatId");
if (id.value == "") {
alert("대화명을 입력 후 채팅창을 열어주세요");
id.focus();
return;
}
window.open("ChatWindow.jsp?chatId=" + id.value, "",
"width=350, height=400");
id.value = "";
}
</script>
</head>
<body>
<h2>웹소켓 채팅 - 대화명 적용해서 채팅창 띄워주기</h2>
대화명 :
<input type="text" id="chatId" />
<button onclick="chatWinOpen();">채팅 참여</button>
</body>
</html>
ChatWindow.jsp - 채팅 화면이 보여지는 곳
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script>
// 서버에 접속
let webSocket = new WebSocket("<%=application.getInitParameter("CHAT_ADDR")%>/ChatingServer");
// 필요한 값 가지고 오기
window.onload = function() {
chatWindow = document.getElementById("chatWindow");
chatMessage = document.getElementById("chatMessage");
chatId = document.getElementById("chatId").value;
}
// 소켓 끊기
function disconnect(){
webSocket.close();
}
//메세지 전송
function sendMessage() {
chatWindow.innerHTML += "<div class='myMsg'>" + chatMessage.value + "</div>";
webSocket.send(chatId + '|' + chatMessage.value);
chatMessage.value = "";
// 메세지가 많아지면 스크롤처리
chatWindow.scrollTop = chatWindow.scrollHeight;
}
function enterKey() {
if (window.event.keyCode == 13){
sendMessage();
}
}
// 소켓이 서버로 가서 동작하는 메소드
// 웹소켓이 서버에 연결되면 실행, 이 속성의 함수는 자동으로 실행
webSocket.onopen = function(event) {
chatWindow.innerHTML += "웹소켓 서버에 연결되었습니다.<br/>";
}
webSocket.onclose = function(event){
chatWindow.innerHTML += "웹소켓 서버가 종료되었습니다.<br/>";
}
webSocket.onmessage = function(event){
// message를 배열 형식으로 받는다
let message = event.data.split("|");
let sender = message[0];
let content = message[1];
if (content != null) {
chatWindow.innerHTML += "<div>" + sender + ":" + content + "</div>";
}
// 메세지가 많아지면 스크롤처리
chatWindow.scrollTop = chatWindow.scrollHeight;
}
</script>
<style type="text/css">
#chatWindow {
border: 1px solid black;
width: 270px;
height: 310px;
overflow: scroll;
padding: 5px;
}
#chatMessage {
width: 236px;
height: 30px;
}
#sendBtn {
height: 30px;
position: relative;
top: 2px;
left: -2px;
}
#closeBtn {
margin-bottom: 3px;
position: relative;
top: 2px;
left: -2px;
}
#chatId {
width: 158px;
height: 24px;
border: 1px solid #AAAAAA;
background-color: #EEEEEE;
}
.myMsg {
text-align: right;
}
</style>
</head>
<body>
<!-- 나의 아이디를 묶어 보내야 한다 chatId,chatWindow,chatMessage 사용 -->
대화명 :
<input type="text" id="chatId" value="${param.chatId }" readonly>
<button id="closeBtn" onclick="disconnect();">채팅 종료</button>
<!-- 채팅이 표시되는 공간 -->
<div id="chatWindow"></div>
<div>
<input type="text" id="chatMessage" onkeyup="enterKey();" />
<button id="sendBtn" onclick="sendMessage()">전송</button>
</div>
</body>
</html>
창을 여러 개 띄워 메세지를 주고 받을 수 있다.
윈도우는 터미널에서 ipconfig를 치면 본인의 ip 주소를 확인할 수 있다.
서버는 ip주소를 뿌리고 클라이언트는 서버의 ip 주소를 받으면 클라이언트끼리 채팅이 가능하다.
추가로 실험해본 채팅창의 색을 바꾸기(색 전송하기) 반 성공..
ChatWindow.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script>
// 서버에 접속
let webSocket = new WebSocket("<%=application.getInitParameter("CHAT_ADDR")%>/ChatingServer");
// 필요한 값 가지고 오기
window.onload = function() {
chatWindow = document.getElementById("chatWindow");
chatMessage = document.getElementById("chatMessage");
chatId = document.getElementById("chatId").value;
}
// 소켓 끊기
function disconnect(){
webSocket.close();
}
//메세지 전송
function sendMessage() {
chatWindow.innerHTML += "<div class='myMsg'>" + chatMessage.value + "</div>";
webSocket.send(chatcolor + chatId + '|' + chatMessage.value);
chatMessage.value = "";
// 메세지가 많아지면 스크롤처리
chatWindow.scrollTop = chatWindow.scrollHeight;
}
function enterKey() {
if (window.event.keyCode == 13){
sendMessage();
}
}
function changeColor() {
let color = "tomato";
webSocket.send("colorChange|" + color);
}
// 소켓이 서버로 가서 동작하는 메소드
// 웹소켓이 서버에 연결되면 실행, 이 속성의 함수는 자동으로 실행
webSocket.onopen = function(event) {
chatWindow.innerHTML += "웹소켓 서버에 연결되었습니다.<br/>";
}
webSocket.onclose = function(event){
chatWindow.innerHTML += "웹소켓 서버가 종료되었습니다.<br/>";
}
webSocket.onmessage = function(event){
// message를 배열 형식으로 받는다
let message = event.data.split("|");
let sender = message[0];
let content = message[1];
if (messageType === "colorChange") {
chatWindow.style.backgroundColor = content;
} else if (content != null) {
chatWindow.innerHTML += "<div>" + sender + ":" + content + "</div>";
}
// 메세지가 많아지면 스크롤처리
chatWindow.scrollTop = chatWindow.scrollHeight;
}
</script>
<style type="text/css">
#chatWindow {
border: 1px solid black;
width: 270px;
height: 310px;
overflow: scroll;
padding: 5px;
}
#chatMessage {
width: 236px;
height: 30px;
}
#sendBtn {
height: 30px;
position: relative;
top: 2px;
left: -2px;
}
#closeBtn {
margin-bottom: 3px;
position: relative;
top: 2px;
left: -2px;
}
#chatId {
width: 158px;
height: 24px;
border: 1px solid #AAAAAA;
background-color: #EEEEEE;
}
.myMsg {
text-align: right;
}
</style>
</head>
<body>
<!-- 나의 아이디를 묶어 보내야 한다 chatId,chatWindow,chatMessage 사용 -->
대화명 :
<input type="text" id="chatId" value="${param.chatId }" readonly>
<button id="closeBtn" onclick="disconnect();">채팅 종료</button>
<!-- 채팅이 표시되는 공간 -->
<div id="chatWindow"></div>
<div>
<input type="text" id="chatMessage" onkeyup="enterKey();" />
<button id="sendBtn" onclick="sendMessage()">전송</button>
<button id="colorBtn" onclick="changeColor();">토마토</button>
</div>
</body>
</html>
문제는 내 채팅창에 색은 바뀌지 않는다..
다시 스프링으로 넘어온다.
본격적으로 스프링 프레임 워크 사용해보기
스프링에서 오류가 났을 때 이런 메세지를 볼 수 있는데
💡 java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/action-servlet.xml]
이건 action-servlet.xml 이라는 파일을 찾는다는 뜻이다.
action-servlet.xml는 핸들러, 컨트롤러, 뷰리저버 정보를 가지고 있는 파일이다.
property ⇒ 맵 구조
(모든 객체의 구조 알아보기)
최종적인 파일 구조
'2024_UIUX 국비 TIL' 카테고리의 다른 글
UIUX _국비과정 0724 [검색기능, 파일업로드, 제이슨 형식으로 반환받기] (0) | 2024.08.21 |
---|---|
UIUX _국비과정 0723 [스프링 컨트롤러 사용하기] (0) | 2024.08.19 |
UIUX _국비과정 0719 [스프링 model2방식 웹만들기] (0) | 2024.07.30 |
UIUX _국비과정 0718 [스프링 model1방식 웹만들기] (0) | 2024.07.30 |
UIUX _국비과정 0717 [스프링 3대 요소, AOP] (0) | 2024.07.29 |