diff --git a/build.gradle.kts b/build.gradle.kts index 4d94bfc..403b16d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,7 +1,7 @@ /* - * Spring-boot Examples + * Examples for Spring-boot * - * Copyright (c) 2021. Elex. All Rights Reserved. + * Copyright (c) 2021-2021. Elex. All Rights Reserved. * https://www.elex-project.com/ */ diff --git a/buildSrc/src/main/kotlin/elex-spring-boot.gradle.kts b/buildSrc/src/main/kotlin/elex-spring-boot.gradle.kts index 84907f6..46270ce 100644 --- a/buildSrc/src/main/kotlin/elex-spring-boot.gradle.kts +++ b/buildSrc/src/main/kotlin/elex-spring-boot.gradle.kts @@ -12,7 +12,7 @@ plugins { } dependencies{ - implementation("org.jetbrains:annotations:21.0.1") + //implementation("org.jetbrains:annotations:21.0.1") } diff --git a/mqtt/build.gradle.kts b/mqtt/build.gradle.kts new file mode 100644 index 0000000..7a2636e --- /dev/null +++ b/mqtt/build.gradle.kts @@ -0,0 +1,27 @@ +/* + * Spring-boot Examples + * + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +plugins { + id("elex-spring-boot") + + id("org.springframework.boot") version "2.5.3" + id("io.spring.dependency-management") version "1.0.11.RELEASE" +} + +dependencies { + implementation ("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-mustache") + + implementation ("org.springframework.boot:spring-boot-starter-integration") + implementation ("org.springframework.integration:spring-integration-mqtt") + + compileOnly ("org.projectlombok:lombok") + developmentOnly ("org.springframework.boot:spring-boot-devtools") + annotationProcessor ("org.projectlombok:lombok") + testImplementation ("org.springframework.boot:spring-boot-starter-test") + +} diff --git a/mqtt/src/main/java/kr/pe/elex/examples/Application.java b/mqtt/src/main/java/kr/pe/elex/examples/Application.java new file mode 100644 index 0000000..4adb83e --- /dev/null +++ b/mqtt/src/main/java/kr/pe/elex/examples/Application.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/mqtt/src/main/java/kr/pe/elex/examples/Config.java b/mqtt/src/main/java/kr/pe/elex/examples/Config.java new file mode 100644 index 0000000..8fba7bf --- /dev/null +++ b/mqtt/src/main/java/kr/pe/elex/examples/Config.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import com.samskivert.mustache.Mustache; +import org.springframework.boot.autoconfigure.mustache.MustacheEnvironmentCollector; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +@Configuration +public class Config { + + @Bean + public Mustache.Compiler mustacheCompiler( + Mustache.TemplateLoader templateLoader, + Environment environment) { + + MustacheEnvironmentCollector collector + = new MustacheEnvironmentCollector(); + collector.setEnvironment(environment); + + return Mustache.compiler() + .withLoader(templateLoader) + .withCollector(collector); + } + +} diff --git a/mqtt/src/main/java/kr/pe/elex/examples/HttpController.java b/mqtt/src/main/java/kr/pe/elex/examples/HttpController.java new file mode 100644 index 0000000..e94ef9c --- /dev/null +++ b/mqtt/src/main/java/kr/pe/elex/examples/HttpController.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; + +import java.util.HashMap; +import java.util.Map; + +@Slf4j +@RestController +public class HttpController { + + @Autowired + private MqttPublisher mqtt; + + @GetMapping("/") + public ModelAndView home() { + final Map map = new HashMap<>(); + return new ModelAndView("home", map); + } + + @GetMapping("/publish") + public void publish(@RequestParam String topic, @RequestParam String message) { + log.info("I'll publish a message: {} {}", topic, message); + + mqtt.publish(topic, message); + } +} diff --git a/mqtt/src/main/java/kr/pe/elex/examples/MqttConfig.java b/mqtt/src/main/java/kr/pe/elex/examples/MqttConfig.java new file mode 100644 index 0000000..3c6c3e7 --- /dev/null +++ b/mqtt/src/main/java/kr/pe/elex/examples/MqttConfig.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import org.eclipse.paho.client.mqttv3.MqttAsyncClient; +import org.eclipse.paho.client.mqttv3.MqttConnectOptions; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.integration.annotation.ServiceActivator; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.core.MessageProducer; +import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory; +import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter; +import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler; +import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.MessageHandler; + +/** + * @see "https://docs.spring.io/spring-integration/reference/html/mqtt.html#mqtt" + */ +@Configuration +public class MqttConfig { + private static final String HOST = "tcp://localhost:1883"; + private static final String USERNAME = "elex"; + private static final String PASSWORD = "test"; + private static final String CLIENT_ID = "i-am-a-server"; + + private static final String TOPIC_FILTER = "#"; + private static final String TOPIC_FILTER_2 = "$SYS/#"; + + private MqttConnectOptions connectOptions() { + MqttConnectOptions options = new MqttConnectOptions(); + options.setCleanSession(true); + options.setServerURIs(new String[]{HOST}); + options.setKeepAliveInterval(10); + options.setAutomaticReconnect(true); + options.setUserName(USERNAME); + options.setPassword(PASSWORD.toCharArray()); + return options; + } + + @Bean + public DefaultMqttPahoClientFactory defaultMqttPahoClientFactory() { + DefaultMqttPahoClientFactory clientFactory = new DefaultMqttPahoClientFactory(); + clientFactory.setConnectionOptions(connectOptions()); + return clientFactory; + } + + @Bean + public MessageChannel mqttInputChannel() { + return new DirectChannel(); + } + + @Bean + public MessageProducer inboundChannel(DefaultMqttPahoClientFactory clientFactory) { + MqttPahoMessageDrivenChannelAdapter adapter = + new MqttPahoMessageDrivenChannelAdapter(HOST, CLIENT_ID, clientFactory, + TOPIC_FILTER, TOPIC_FILTER_2); + adapter.setCompletionTimeout(5000); + adapter.setConverter(new DefaultPahoMessageConverter()); + adapter.setQos(1); + adapter.setOutputChannel(mqttInputChannel()); + return adapter; + } + + @Bean + @ServiceActivator(inputChannel = "mqttInputChannel") + public MessageHandler messageHandler() { + return new MqttMessageHandler(); + } + + @Bean + public MessageChannel mqttOutboundChannel() { + return new DirectChannel(); + } + + @Bean + @ServiceActivator(inputChannel = "mqttOutboundChannel") + public MessageHandler mqttOutbound(DefaultMqttPahoClientFactory clientFactory) { + MqttPahoMessageHandler messageHandler = + new MqttPahoMessageHandler(CLIENT_ID + MqttAsyncClient.generateClientId(), + clientFactory); + messageHandler.setAsync(true); + messageHandler.setDefaultQos(1); + return messageHandler; + } + +} diff --git a/mqtt/src/main/java/kr/pe/elex/examples/MqttMessageHandler.java b/mqtt/src/main/java/kr/pe/elex/examples/MqttMessageHandler.java new file mode 100644 index 0000000..52f88ff --- /dev/null +++ b/mqtt/src/main/java/kr/pe/elex/examples/MqttMessageHandler.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.integration.mqtt.support.MqttHeaders; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageHandler; +import org.springframework.messaging.MessagingException; + +@Slf4j +public class MqttMessageHandler implements MessageHandler { + + /** + * 구독 중인 MQTT 메시지는 여기서 받는다. + * + * @param message + * @throws MessagingException + */ + @Override + public void handleMessage(Message message) throws MessagingException { + String topic = (String) message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC); + log.info("MQTT Rx: {} {}", topic, message.getPayload()); + + } +} diff --git a/mqtt/src/main/java/kr/pe/elex/examples/MqttPublisher.java b/mqtt/src/main/java/kr/pe/elex/examples/MqttPublisher.java new file mode 100644 index 0000000..26cbab4 --- /dev/null +++ b/mqtt/src/main/java/kr/pe/elex/examples/MqttPublisher.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import org.springframework.integration.annotation.MessagingGateway; +import org.springframework.integration.mqtt.support.MqttHeaders; +import org.springframework.messaging.handler.annotation.Header; + +@MessagingGateway(defaultRequestChannel = "mqttOutboundChannel") +public interface MqttPublisher { + + /** + * MQTT 메시지는 여기서 발행한다. + * + * @param topic + * @param payload + */ + void publish(@Header(MqttHeaders.TOPIC) String topic, String payload); + +} diff --git a/mqtt/src/main/java/kr/pe/elex/examples/package-info.java b/mqtt/src/main/java/kr/pe/elex/examples/package-info.java new file mode 100644 index 0000000..62cdc15 --- /dev/null +++ b/mqtt/src/main/java/kr/pe/elex/examples/package-info.java @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; diff --git a/mqtt/src/main/resources/application.properties b/mqtt/src/main/resources/application.properties new file mode 100644 index 0000000..0b44a3b --- /dev/null +++ b/mqtt/src/main/resources/application.properties @@ -0,0 +1,4 @@ +# +# Copyright (c) 2021. Elex. All Rights Reserved. +# https://www.elex-project.com/ +# diff --git a/mqtt/src/main/resources/logback-spring.xml b/mqtt/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..5969bfa --- /dev/null +++ b/mqtt/src/main/resources/logback-spring.xml @@ -0,0 +1,19 @@ + + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{15} - %msg%n + + + + + + + + diff --git a/mqtt/src/main/resources/templates/home.mustache b/mqtt/src/main/resources/templates/home.mustache new file mode 100644 index 0000000..0a71267 --- /dev/null +++ b/mqtt/src/main/resources/templates/home.mustache @@ -0,0 +1,15 @@ + + + + + MQTT Spring-boot Integration Examples + + +

MQTT Spring-boot Integration Examples

+
+
Usage
+
/publish?topic=TOPIC&message=MESSAGE
+
+

Copyright $copy; 2021 Elex Project. All Rights Reserved.

+ + diff --git a/mqtt/src/test/java/kr/pe/elex/examples/ApplicationTests.java b/mqtt/src/test/java/kr/pe/elex/examples/ApplicationTests.java new file mode 100644 index 0000000..58df712 --- /dev/null +++ b/mqtt/src/test/java/kr/pe/elex/examples/ApplicationTests.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/restful/build.gradle.kts b/restful/build.gradle.kts new file mode 100644 index 0000000..b6071fc --- /dev/null +++ b/restful/build.gradle.kts @@ -0,0 +1,27 @@ +/* + * Spring-boot Examples + * + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +plugins { + id("elex-spring-boot") + + id("org.springframework.boot") version "2.5.3" + id("io.spring.dependency-management") version "1.0.11.RELEASE" +} + +dependencies { + implementation("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-mustache") + + compileOnly("org.projectlombok:lombok") + developmentOnly("org.springframework.boot:spring-boot-devtools") + + annotationProcessor("org.springframework.boot:spring-boot-configuration-processor") + annotationProcessor("org.projectlombok:lombok") + + testImplementation("org.springframework.boot:spring-boot-starter-test") + +} diff --git a/restful/src/main/java/kr/pe/elex/examples/Application.java b/restful/src/main/java/kr/pe/elex/examples/Application.java new file mode 100644 index 0000000..f4ba9ae --- /dev/null +++ b/restful/src/main/java/kr/pe/elex/examples/Application.java @@ -0,0 +1,13 @@ +package kr.pe.elex.examples; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/restful/src/main/java/kr/pe/elex/examples/MainController.java b/restful/src/main/java/kr/pe/elex/examples/MainController.java new file mode 100644 index 0000000..82fc2b3 --- /dev/null +++ b/restful/src/main/java/kr/pe/elex/examples/MainController.java @@ -0,0 +1,23 @@ +package kr.pe.elex.examples; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.util.MimeType; +import org.springframework.util.MimeTypeUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Random; + +@Slf4j +@RestController +public class MainController { + + @GetMapping(path = "/{name}", produces = {MimeTypeUtils.APPLICATION_JSON_VALUE}) + public ResponseEntity home(@PathVariable String name) { + + return ResponseEntity + .ok(new Person(name, new Random().nextInt())); + } +} diff --git a/restful/src/main/java/kr/pe/elex/examples/Person.java b/restful/src/main/java/kr/pe/elex/examples/Person.java new file mode 100644 index 0000000..ed998d1 --- /dev/null +++ b/restful/src/main/java/kr/pe/elex/examples/Person.java @@ -0,0 +1,14 @@ +package kr.pe.elex.examples; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class Person { + @JsonProperty + private String name; + @JsonProperty + private int age; +} diff --git a/restful/src/main/java/kr/pe/elex/examples/package-info.java b/restful/src/main/java/kr/pe/elex/examples/package-info.java new file mode 100644 index 0000000..18376b4 --- /dev/null +++ b/restful/src/main/java/kr/pe/elex/examples/package-info.java @@ -0,0 +1 @@ +package kr.pe.elex.examples; diff --git a/restful/src/main/resources/application.properties b/restful/src/main/resources/application.properties new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/restful/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/settings.gradle.kts b/settings.gradle.kts index 2262f90..1668e3c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -6,4 +6,5 @@ */ rootProject.name = "spring-boot-examples" -include("file-upload", "security", "security-with-jpa", "validation", "testing") +include("file-upload", "security", "security-with-jpa", "validation", "testing", + "mqtt", "websocket", "restful") diff --git a/websocket/build.gradle.kts b/websocket/build.gradle.kts new file mode 100644 index 0000000..0db011e --- /dev/null +++ b/websocket/build.gradle.kts @@ -0,0 +1,25 @@ +/* + * Spring-boot Examples + * + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +plugins { + id("elex-spring-boot") + + id("org.springframework.boot") version "2.5.3" + id("io.spring.dependency-management") version "1.0.11.RELEASE" +} + +dependencies { + implementation ("org.springframework.boot:spring-boot-starter-web") + implementation("org.springframework.boot:spring-boot-starter-mustache") + + implementation("org.springframework.boot:spring-boot-starter-websocket") + + compileOnly ("org.projectlombok:lombok") + developmentOnly ("org.springframework.boot:spring-boot-devtools") + annotationProcessor ("org.projectlombok:lombok") + testImplementation ("org.springframework.boot:spring-boot-starter-test") +} diff --git a/websocket/src/main/java/kr/pe/elex/examples/Application.java b/websocket/src/main/java/kr/pe/elex/examples/Application.java new file mode 100644 index 0000000..4adb83e --- /dev/null +++ b/websocket/src/main/java/kr/pe/elex/examples/Application.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/websocket/src/main/java/kr/pe/elex/examples/Config.java b/websocket/src/main/java/kr/pe/elex/examples/Config.java new file mode 100644 index 0000000..8fba7bf --- /dev/null +++ b/websocket/src/main/java/kr/pe/elex/examples/Config.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import com.samskivert.mustache.Mustache; +import org.springframework.boot.autoconfigure.mustache.MustacheEnvironmentCollector; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +@Configuration +public class Config { + + @Bean + public Mustache.Compiler mustacheCompiler( + Mustache.TemplateLoader templateLoader, + Environment environment) { + + MustacheEnvironmentCollector collector + = new MustacheEnvironmentCollector(); + collector.setEnvironment(environment); + + return Mustache.compiler() + .withLoader(templateLoader) + .withCollector(collector); + } + +} diff --git a/websocket/src/main/java/kr/pe/elex/examples/HttpController.java b/websocket/src/main/java/kr/pe/elex/examples/HttpController.java new file mode 100644 index 0000000..adf4e19 --- /dev/null +++ b/websocket/src/main/java/kr/pe/elex/examples/HttpController.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.ModelAndView; + +import java.util.HashMap; +import java.util.Map; + +@Slf4j +@RestController +public class HttpController { + + @GetMapping("/") + public ModelAndView home() { + final Map map = new HashMap<>(); + map.put("title", "Websocket Test"); + return new ModelAndView("home", map); + } + +} diff --git a/websocket/src/main/java/kr/pe/elex/examples/WebSocketConfig.java b/websocket/src/main/java/kr/pe/elex/examples/WebSocketConfig.java new file mode 100644 index 0000000..9ec3185 --- /dev/null +++ b/websocket/src/main/java/kr/pe/elex/examples/WebSocketConfig.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.config.annotation.EnableWebSocket; +import org.springframework.web.socket.config.annotation.WebSocketConfigurer; +import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry; + +@Configuration +@EnableWebSocket +@RequiredArgsConstructor +public class WebSocketConfig implements WebSocketConfigurer { + private final WebSocketHandler webSocketHandler; + + @Override + public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { + registry.addHandler(webSocketHandler, "/websocket"); + //.setAllowedOrigins("*") + // .withSockJS(); + } +} diff --git a/websocket/src/main/java/kr/pe/elex/examples/WebSocketHandler.java b/websocket/src/main/java/kr/pe/elex/examples/WebSocketHandler.java new file mode 100644 index 0000000..9cceae0 --- /dev/null +++ b/websocket/src/main/java/kr/pe/elex/examples/WebSocketHandler.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.socket.CloseStatus; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; +import org.springframework.web.socket.handler.TextWebSocketHandler; + +import java.io.IOException; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +@Slf4j +@Component +@RequiredArgsConstructor +public class WebSocketHandler extends TextWebSocketHandler { + private static Set sessions = new ConcurrentHashMap().newKeySet(); + + public static void publish(String message) throws IOException { + for (WebSocketSession item : sessions) { + try { + item.sendMessage(new TextMessage(message)); + } catch (Throwable e) { + log.error("Couldn't send message over websocket.", e); + } + } + } + + @Override + public void afterConnectionEstablished(WebSocketSession session) throws Exception { + super.afterConnectionEstablished(session); + sessions.add(session); + log.info("Client({}) connected.", session.getRemoteAddress()); + } + + @Override + protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { + log.info("Message from client({}):{}", session.getRemoteAddress(), message.getPayload()); + for (WebSocketSession webSocketSession : sessions) { + //if (session == webSocketSession) continue; + String msg = message.getPayload().toUpperCase(); + webSocketSession.sendMessage(new TextMessage(msg)); + } + } + + @Override + public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { + super.afterConnectionClosed(session, status); + sessions.remove(session); + log.info("Client({}) disconnect.", session.getRemoteAddress()); + } + +} diff --git a/websocket/src/main/java/kr/pe/elex/examples/package-info.java b/websocket/src/main/java/kr/pe/elex/examples/package-info.java new file mode 100644 index 0000000..62cdc15 --- /dev/null +++ b/websocket/src/main/java/kr/pe/elex/examples/package-info.java @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; diff --git a/websocket/src/main/resources/application.properties b/websocket/src/main/resources/application.properties new file mode 100644 index 0000000..0b44a3b --- /dev/null +++ b/websocket/src/main/resources/application.properties @@ -0,0 +1,4 @@ +# +# Copyright (c) 2021. Elex. All Rights Reserved. +# https://www.elex-project.com/ +# diff --git a/websocket/src/main/resources/logback-spring.xml b/websocket/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..5969bfa --- /dev/null +++ b/websocket/src/main/resources/logback-spring.xml @@ -0,0 +1,19 @@ + + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{15} - %msg%n + + + + + + + + diff --git a/websocket/src/main/resources/templates/home.mustache b/websocket/src/main/resources/templates/home.mustache new file mode 100644 index 0000000..ac44fea --- /dev/null +++ b/websocket/src/main/resources/templates/home.mustache @@ -0,0 +1,108 @@ + + + + + {{title}} + + + + +
+
+

{{title}}

+ + + + +
+
+ +
+
+ + diff --git a/websocket/src/test/java/kr/pe/elex/examples/ApplicationTests.java b/websocket/src/test/java/kr/pe/elex/examples/ApplicationTests.java new file mode 100644 index 0000000..58df712 --- /dev/null +++ b/websocket/src/test/java/kr/pe/elex/examples/ApplicationTests.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021. Elex. All Rights Reserved. + * https://www.elex-project.com/ + */ + +package kr.pe.elex.examples; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class ApplicationTests { + + @Test + void contextLoads() { + } + +}