■ Chat
@Slf4j
@RestController
public class RestSseController {
private static final Map<String, SseEmitter> clients = new HashMap<>();
@GetMapping(value="/api/sse/subscribe")
public SseEmitter subscribe( @RequestParam(name="id") String id) {
SseEmitter emitter = new SseEmitter( 1000L * 1200 );
clients.put(id, emitter);
emitter.onTimeout(() -> clients.remove(id));
emitter.onCompletion(() -> clients.remove(id));
return emitter;
}
@GetMapping(value="/api/sse/publish")
public void publish(@RequestParam(name="message") String message) {
for (String id : clients.keySet()) {
try {
SseEmitter emitter = clients.get(id);
emitter.send(message, MediaType.APPLICATION_JSON);
}
catch(Exception e) {
clients.remove(id);
}
}
}
}
- RestController폴더에 RestSseController.java를 생성한다.
- map을 사용하여 접속하는 클라이언트의 정보를 보관할 변수를 생성한다.
- 클라이언트 접속했을때 수행하기 위해 see객체를 생성하여 접속시간을 정해준다.
- 클라이언트 연결 중지 및 완료되면 clients변수에서 정보를 제거한다.
- 클라이언트가 전송했을때 map에 보관된 개수만큼 값을 꺼낸다. 그 키값으로 value값을 꺼내어 클라이언트로 메시지 전송한다.
■ ChatController
@Slf4j
@Controller
public class ChatController {
@GetMapping(value="/chat.do")
public String chatGET() {
return "/chat";
}
}
■ chat.html
<body>
<h3>chat</h3>
<div>
<input type="text" id="input"/>
<button id="send" onclick="sendMessage()">send</button>
<div id="messages" style="border:1px solid #cccccc;"></div>
</div>
<script>
const id = `ds200_${new Date().getTime()}`;
const eventSource = new EventSource(`/ROOT/api/sse/subscribe?id=${id}`);
eventSource.onopen = (e) => {
console.log('onopen', e);
};
eventSource.onmessage = (e) => {
const div = document.querySelector('#messages');
div.innerHTML = `${e.data}<br />` + div.innerHTML;
console.log('onmessage',e.data);
};
eventSource.onerror = (e) => {
console.log('onerror', e);
};
const sendMessage = () => {
const msg = document.querySelector('#input').value;
fetch(`/ROOT/api/sse/publish?message=${msg}`);
};
</script>
</body>
- 다른 곳에서 전송을 해도 전송한 값을 받아와 콘솔에 출력한다.
■ Scheduler
@Component
@Slf4j
@RequiredArgsConstructor
public class MyScheduler {
final Board1Repository board1Repository;
// cron tab
// 초, 분, 시간, 일, 월, 요일
// */5 * * * * * 5초 간격으로 동작
// */20 * * * * * 20초 간격
// 0 * * * * * 0초가 될 때마다 (1분 간격)
@Scheduled(cron = "*/5 * * * * *")
public void printDate(){
log.info("{}", new Date().toString());
List<Board1> list = board1Repository.findAll();
log.info("{}", list.toString());
}
}
- scheduler 폴더를 생성하여 MyScheduler.java를 생성한다.
@EnableScheduling
@ComponentScan(basePackages = {
...
"com.example.scheduler" })
- Boot20230427Application.java에 위 코드를 추가한다.
- 5초마다 board1Repository의 값이 출력된다.
- // @Scheduled(cron = "/5 * * * *") 이렇게 주석처리를 하면 더이상 출력되지 않는다.