今までのタイマーはほとんどフロントエンドで行っていたので編集を行います
タイマー機能をバックエンドに移行する
- タイマーの状態管理用のエンティティを作成
- タイマー制御用のサービスを作成
- WebSocketを使用してフロントエンドとリアルタイム通信を実装
タイマーのエンティティを作成
package com.example.PomodoroTimer.domain;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import lombok.Data;
@Entity
@Data
public class Timer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private int workDuration; // 作業時間(分)
private int breakDuration; // 休憩時間(分)
private int remainingTime; // 残り時間(秒)
private boolean isRunning; // タイマーが実行中かどうか
private boolean isWorkTime; // 作業時間か休憩時間か
}
タイマー制御用のサービスを作成
package com.example.PomodoroTimer.service;
import com.example.PomodoroTimer.domain.Timer;
import org.springframework.stereotype.Service;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.beans.factory.annotation.Autowired;
@Service
public class TimerService {
@Autowired
private SimpMessagingTemplate messagingTemplate;
private Timer currentTimer;
public TimerService() {
this.currentTimer = new Timer();
this.currentTimer.setWorkDuration(25);
this.currentTimer.setBreakDuration(5);
this.currentTimer.setRemainingTime(25 * 60);
this.currentTimer.setRunning(false);
this.currentTimer.setWorkTime(true);
}
public Timer getCurrentTimer() {
return currentTimer;
}
public void startTimer() {
currentTimer.setRunning(true);
notifyTimerUpdate();
}
public void pauseTimer() {
currentTimer.setRunning(false);
notifyTimerUpdate();
}
public void resetTimer() {
currentTimer.setRemainingTime(currentTimer.isWorkTime() ?
currentTimer.getWorkDuration() * 60 :
currentTimer.getBreakDuration() * 60);
currentTimer.setRunning(false);
notifyTimerUpdate();
}
public void switchMode() {
currentTimer.setWorkTime(!currentTimer.isWorkTime());
currentTimer.setRemainingTime(currentTimer.isWorkTime() ?
currentTimer.getWorkDuration() * 60 :
currentTimer.getBreakDuration() * 60);
currentTimer.setRunning(false);
notifyTimerUpdate();
}
@Scheduled(fixedRate = 1000)
public void updateTimer() {
if (currentTimer.isRunning() && currentTimer.getRemainingTime() > 0) {
currentTimer.setRemainingTime(currentTimer.getRemainingTime() - 1);
notifyTimerUpdate();
if (currentTimer.getRemainingTime() == 0) {
currentTimer.setRunning(false);
switchMode();
}
}
}
private void notifyTimerUpdate() {
messagingTemplate.convertAndSend("/topic/timer", currentTimer);
}
}
WebSocketの設定をする
WebSocket:WebブラウザとWebサーバーの間で、双方向かつ永続的な通信チャネルを確立するための技術
package com.example.PomodoroTimer.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.setAllowedOrigins("http://localhost:8080")
.withSockJS();
}
}
タイマー制御用のコントローラーを作成
package com.example.PomodoroTimer.controller;
import com.example.PomodoroTimer.domain.Timer;
import com.example.PomodoroTimer.service.TimerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/timer")
@CrossOrigin(origins = "http://localhost:8080")
public class TimerController {
@Autowired
private TimerService timerService;
@GetMapping("/current")
public Timer getCurrentTimer() {
return timerService.getCurrentTimer();
}
@PostMapping("/start")
public void startTimer() {
timerService.startTimer();
}
@PostMapping("/pause")
public void pauseTimer() {
timerService.pauseTimer();
}
@PostMapping("/reset")
public void resetTimer() {
timerService.resetTimer();
}
@PostMapping("/switch")
public void switchMode() {
timerService.switchMode();
}
}
主な変更点は以下の4点
- Timerエンティティ:タイマーの状態を管理
- TimerService:タイマーの制御ロジックを実装
- WebSocketConfig:リアルタイム通信の設定
- TimerController:REST APIエンドポイントの提供