샘플앱 spring-talk

Jmnote (토론 | 기여)님의 2016년 10월 11일 (화) 17:46 판 (Jmnote님이 SpringTalk 문서를 Spring-talk 문서로 이동했습니다)
SpringTalk

1 Message.java

package com.example.springtalk;

import lombok.Data;

@Data
public class Message {
	private String username;
    private String content;
}

2 MessageController.java

package com.example.springtalk;

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;

@Controller
public class MessageController {

    @MessageMapping("/message")
    @SendTo("/topic/messages")
    public Message transfer(Message message) throws Exception {
        Thread.sleep(200);
        return message;
    }
}

3 WebScoketConfig.java

package com.example.springtalk;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/websocket-endpoint").withSockJS();
    }
}

4 index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>SpringTalk</title>
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="main.css">
<script src="/webjars/jquery/jquery.min.js"></script>
<script src="/webjars/sockjs-client/sockjs.min.js"></script>
<script src="/webjars/stomp-websocket/stomp.min.js"></script>
<script src="/app.js"></script>

<script src='//cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/core-min.js'></script>
<script src='//cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/md5-min.js'></script>
<script src="//rawgit.com/stewartlord/identicon.js/master/pnglib.js"></script>
<script src="//rawgit.com/stewartlord/identicon.js/master/identicon.js"></script>
<script src='//cdn.rawgit.com/zenozeng/color-hash/master/dist/color-hash.js'></script>
</head>

<body>
	<div class="container">
		<div>
			이름: <input id='username' type='text'>
		</div>
	</div>
	<div id="main-content" class="container">
		<div class="row">
			<div id="conversation"></div>
		</div>
		<div class="row">
			<form class="form-inline">
				<div class="col-xs-9">
					<input type="text" style='width: 100%' id="content"
						class="form-control">
				</div>
				<div class="col-xs-3">
					<button id="send" style='width: 100%' class="btn btn-default"
						type="submit">보내기</button>
				</div>
			</form>
		</div>
	</div>
</body>
</html>

5 app.js

var stompClient = null;
var username = null;
var last_sender = null;

function randomUsername() {
	var text = "";
	var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
	for( var i=0; i < 5; i++ ) text += possible.charAt(Math.floor(Math.random() * possible.length));
	return text;
}

function connect() {
	var socket = new SockJS('/websocket-endpoint');
	stompClient = Stomp.over(socket);
	stompClient.connect({}, function (frame) {
		console.log('Connected: ' + frame);
		stompClient.subscribe('/topic/messages', function (message) {
			showMessage(JSON.parse(message.body));
		});
	});
}

function send() {
	if( $("#content").val() == '' ) return;
	stompClient.send("/app/message", {}, JSON.stringify({
		'username': $("#username").val(),
		'content': $("#content").val()
	}));
}

function showMessage(message) {
	var hash = CryptoJS.MD5(message.username).toString();
	var img_data = new Identicon(hash, 50).toString();
	var colorHash = new ColorHash({
	      lightness: 0.5,
	      saturation: 0.7
	    });
    var color = colorHash.hex(message.username);
    var initial = message.username.charAt(0);
	    
	var message_class = ( $("#username").val() == message.username )? 'message-mine' : 'message-others';
	var sender_class = ( last_sender == message.username )? 'sender-hidden' : 'sender-show';
	$("#conversation")
	.append("<div class='message "+message_class+" "+sender_class+"'>" +
			//"<div class='photobox'><img class='photo' src='data:image/png;base64," + img_data + "'></div>" +
			"<div class='photobox'><div class='photo lavatar' style='background:" + color + "'>" + initial + "</div></div>" +
			"<div class='textbox'>" +
			"<div class='username'>"+message.username+"</div>" +
			"<div><span>" + message.content + "</span></div></div></div>");
	$("#conversation")[0].scrollTop = $("#conversation")[0].scrollHeight;
	last_sender = message.username;
}

$(function () {
	$("form").on('submit', function (e) { e.preventDefault(); });
	connect();
	$( "#username" ).val( randomUsername() );
	$( "#send" ).click(function() { send(); });
});

6 main.css

#conversation {
	display: block;
	width: 100%;
	height: 350px;
	background: #9bbbd4;
	vertical-align: top;
	padding: 8px;
	overflow-y: scroll;
	float: left;
}

::-webkit-scrollbar {
	width: 14px;
	height: 18px;
}

::-webkit-scrollbar-thumb {
	height: 6px;
	border: 4px solid rgba(0, 0, 0, 0);
	background-clip: padding-box;
	background-color: rgba(0, 0, 0, 0.2);
	-webkit-border-radius: 7px;
	-webkit-box-shadow: inset -1px -1px 0px rgba(0, 0, 0, 0.05), inset 1px
		1px 0px rgba(0, 0, 0, 0.05);
}

::-webkit-scrollbar-button {
	width: 0;
	height: 0;
	display: none;
}

::-webkit-scrollbar-corner {
	background-color: transparent;
}

.sender-show {
	clear: both;
	margin-top: 20px !important;
}

.sender-hidden .username {
	display: none;
}

.sender-hidden .photobox {
	display: none;
}

.message {
	margin: 7px;
}

.photo {
	object-fit: cover;
	object-position: top;
	border-radius: 50%;
}

.lavatar {
	width: 48px;
	height: 48px;
	line-height: 48px;
	font-size: 24px;
	text-align: center;
	color: #fff;
}

.message span {
	padding: 4px;
	margin: 2px;
	border-radius: 3px;
}

.textbox {
	margin: 0 70px;
}

.message-mine {
	text-align: right;
}

.message-mine .photobox {
	float: right;
}

.message-mine span {
	background: #fef01b;
}

.message-others span {
	background: #ffffff;
}

.message-others .photobox {
	float: left;
}

7 같이 보기

8 참고 자료

문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}