[ Java / Socket ] 서버/클라이언트 통신 및 토스트 메세지 띄워보기
2024. 6. 29. 13:21ㆍ· LANGUAGE/└ Java
환경 : DBeaver, Spring Tool Suite4
챗봇처럼 서버와 클라이언트의 유기적인 통신을 구현하기 위해 테이블을 먼저 생성하고 더미 데이터를 삽입하겠습니다.
- DB 생성
-- 테이블 및 시퀀스 생성
-- 챗봇에서 가장 중요한 건 질문에 대한 답변
create table chatbot (
chatbot_no number primary key, -- 번호
chatbot_question varchar2(300) not null, --질문
chatbot_answer varchar2(300) not null --답변
);
create sequence chatbot_seq;
-- 더미데이터 생성
insert into chatbot(chatbot_no, chatbot_question, chatbot_answer)
values(chatbot_seq.nextval, '원숭이 엉덩이는', '빨개');
insert into chatbot(chatbot_no, chatbot_question, chatbot_answer)
values(chatbot_seq.nextval, '빨가면', '사과');
insert into chatbot(chatbot_no, chatbot_question, chatbot_answer)
values(chatbot_seq.nextval, '사과는', '맛있어');
insert into chatbot(chatbot_no, chatbot_question, chatbot_answer)
values(chatbot_seq.nextval, '맛있으면', '바나나');
insert into chatbot(chatbot_no, chatbot_question, chatbot_answer)
values(chatbot_seq.nextval, '바나나는', '길어');
insert into chatbot(chatbot_no, chatbot_question, chatbot_answer)
values(chatbot_seq.nextval, '길면', '기차');
insert into chatbot(chatbot_no, chatbot_question, chatbot_answer)
values(chatbot_seq.nextval, '기차는', '빨라');
insert into chatbot(chatbot_no, chatbot_question, chatbot_answer)
values(chatbot_seq.nextval, '빠르면', '비행기');
insert into chatbot(chatbot_no, chatbot_question, chatbot_answer)
values(chatbot_seq.nextval, '비행기는', '높아');
insert into chatbot(chatbot_no, chatbot_question, chatbot_answer)
values(chatbot_seq.nextval, '높으면', '백두산');
commit;
DB와 JAVA 연결
- ChatbotDto.java
@Data @Builder @NoArgsConstructor @AllArgsConstructor
public class ChatbotDto {
private int chatbotNo;
private String chatbotQuestion;
private String chatbotAnswer;
}
- chatbot-mapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="chatbot">
<select id="list" resultType="ChatbotDto">
select chatbot_no, chatbot_question
from chatbot order by chatbot_no asc
</select>
<select id="find" resultType="ChatbotDto">
select * from chatbot where chatbot_no = #{chatbotNo}
</select>
</mapper>
- ChatbotDao.java
@Repository
public class ChatbotDao {
@Autowired
private SqlSession sqlSession;
public List<ChatbotDto> selectList(){
return sqlSession.selectList("chatbot.list");
}
public ChatbotDto selectOne(int chatbotNo) {
return sqlSession.selectOne("chatbot.find", chatbotNo);
}
}
서버 생성
- ChatbotWebSocketServer.java
@Slf4j
@Service
public class ChatbotWebSocketServer extends TextWebSocketHandler{
@Autowired
private ChatbotDao chatbotDao;
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
//사용자가 접속하면 모든 질문 목록을 사용자에게 전송
//(모든 질문 목록 → List<ChatbotDto> → JSON)
//목록 조회
List<ChatbotDto> list = chatbotDao.selectList();
//목록으로 JSON 문자열 생성(수동)
ObjectMapper mapper = new ObjectMapper();//JSON 변환도구
String json = mapper.writeValueAsString(list);
//메세지 객체 생성
TextMessage message = new TextMessage(json);
//전송
session.sendMessage(message);//질문목록이담긴 메세지객체를 전송
}
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
//사용자가 보내는 메세지를 받아서 처리하는 메소드
//- 사용자는 질문번호를 보낸다
//- 질문번호를 받아서 상세조회한 뒤 나오는 정보를 전송하면 된다
int chatbotNo = Integer.parseInt(message.getPayload());
ChatbotDto chatbotDto = chatbotDao.selectOne(chatbotNo);
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(chatbotDto);//JSON 변환
TextMessage response = new TextMessage(json);//포장
session.sendMessage(response);//전송
}
}
(+) 질문 목록을 전송시 JSON으로 변환하고 포장하는 과정이 필요하다.
- WebSocketServerConfiguration.java
/**
* 웹소켓과 관련된 설정을 작성하는 파일
* 이미 등록해둔 웹소켓 서버들을 가져와서 추가적인 설정을 한 뒤 활성화
* */
@EnableWebSocket//웹소켓을 사용할 것임을 표시(활성화)
@Configuration//설정파일임을 표시
public class WebSocketServerConfiguration implements WebSocketConfigurer {
@Autowired
private ChatbotWebSocketServer chatbotWebSocketServer;
@Override
public void registerWebSocketHandlers (WebSocketHandlerRegistry registry) {
//매개 변수로 주어진 registry에 웹소켓 서버를 등록
//- 반드시 웹페이지처럼 주소가 부여되어야 함
//- (중요)절대로 다른 주소와 겹치면 안된다.
registry.addHandler(chatbotWebSocketServer, "/ws/chatbot");
}
}
페이지 생성
- PageController.java
@Controller
@RequestMapping("/page")
public class PageController {
@RequestMapping("/chatbot")
public String chatbot() {
return "chatbot";
}
}
- chatbot.jsp
라이브러리 : https://apvarun.github.io/toastify-js/
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!-- javascript toast library -->
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css">
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/toastify-js"></script>
<h1>챗봇 예제</h1>
<button class="btn-connect">연결</button>
<button class="btn-disconnect">종료</button>
<hr>
<div class="question-wrapper"></div>
<div class="answer-wrapper"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
$(".btn-connect").click(function(){
window.socket = new WebSocket("ws://localhost:8080/ws/chatbot");
//웹소켓을 생성하고 나서 예상되는 각종 상황에 대해 미리 콜백함수를 정의
//- onopen(연결완료시), onclose(연결종료시), onerror(오류발생시)
//- onmessage(메세지수신시)
window.socket.onmessage = function(e){
//console.log(e.data);//서버에서 전송된 내용(문자열)
var json = JSON.parse(e.data);//자바스크립트 스타일로 해석
//console.log(json);
if(Array.isArray(json)){ //배열이라면
//json에 들어있는 데이터 개수만큼 버튼을 생성하여 추가
$(".question-wrapper").empty();
$(json).each(function(){
var button = $("<button>").text(this.chatbotQuestion)
.attr("data-no", this.chatbotNo)
.addClass("btn-question");
$(".question-wrapper").append(button);
});
}
else {//배열이 아니라면(지금 상황에선 객체)
//$(".answer-wrapper").text(json.chatbotAnswer);
Toastify({
text: json.chatbotAnswer,
duration: 3000,
//destination: "https://github.com/apvarun/toastify-js",
newWindow: true, //false 시 창 하나에 계속 뜸
close: true,
gravity: "top", // `top` or `bottom`
position: "right", // `left`, `center` or `right`
stopOnFocus: true, // Prevents dismissing of toast on hover
style: {
background: "linear-gradient(to right, #00b09b, #96c93d)",
},
onClick: function(){} // Callback after click
}).showToast();
}
};
});
$(".btn-disconnect").click(function(){
window.socket.close();
});
//문서 내에 존재하는 .btn-question에 클릭 이벤트를 예약
$(document).on("click", ".btn-question", function(){
var chatbotNo = $(this).data("no");//버튼에 있는 번호(data-no) 추출
window.socket.send(chatbotNo);//서버로 전송
});
});
</script>
(+) toast library를 사용하기 위해 라이브러리 cdn을 추가하여 준 후 사용해야 한다.
(+) toast library를 사용하지 않아도 무관, 사용 시 각각의 변수 값을 원하는대로 수정하여 사용하면 된다.
- 출력결과
개인 공부 기록용입니다:)
728x90
'· LANGUAGE > └ Java' 카테고리의 다른 글
Heartbeat, Live Ping (0) | 2024.06.29 |
---|---|
[ Java / Socket ] 접속자 제어 및 브로드캐스팅(그룹채팅 구현) (0) | 2024.06.29 |
[ Java / Socket ] 웹 소켓 서버 생성 / 접속 / 접속종료 (0) | 2024.06.29 |
[ Java ] 내장객체로 비.암(비밀번호 암호화 하기) (0) | 2024.06.25 |
[ Java ] MimeMessage - 이메일 전송하기 (0) | 2024.06.25 |