{"id":214,"date":"2025-05-14T23:18:01","date_gmt":"2025-05-14T14:18:01","guid":{"rendered":"https:\/\/suyasuyahirohiro.com\/?p=214"},"modified":"2025-05-14T23:21:22","modified_gmt":"2025-05-14T14:21:22","slug":"%e3%83%90%e3%83%83%e3%82%af%e3%82%a8%e3%83%b3%e3%83%89%e3%81%a7%e3%82%88%e3%82%8ajava%e3%82%92%e4%bd%bf%e7%94%a8%e3%81%99%e3%82%8b","status":"publish","type":"post","link":"https:\/\/suyasuyahirohiro.com\/?p=214","title":{"rendered":"\u30d0\u30c3\u30af\u30a8\u30f3\u30c9\u3067\u3088\u308aJava\u3092\u4f7f\u7528\u3059\u308b"},"content":{"rendered":"\n<p>\u4eca\u307e\u3067\u306e\u30bf\u30a4\u30de\u30fc\u306f\u307b\u3068\u3093\u3069\u30d5\u30ed\u30f3\u30c8\u30a8\u30f3\u30c9\u3067\u884c\u3063\u3066\u3044\u305f\u306e\u3067\u7de8\u96c6\u3092\u884c\u3044\u307e\u3059<br><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u30bf\u30a4\u30de\u30fc\u6a5f\u80fd\u3092\u30d0\u30c3\u30af\u30a8\u30f3\u30c9\u306b\u79fb\u884c\u3059\u308b<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30bf\u30a4\u30de\u30fc\u306e\u72b6\u614b\u7ba1\u7406\u7528\u306e\u30a8\u30f3\u30c6\u30a3\u30c6\u30a3\u3092\u4f5c\u6210<\/li>\n\n\n\n<li>\u30bf\u30a4\u30de\u30fc\u5236\u5fa1\u7528\u306e\u30b5\u30fc\u30d3\u30b9\u3092\u4f5c\u6210<\/li>\n\n\n\n<li>WebSocket\u3092\u4f7f\u7528\u3057\u3066\u30d5\u30ed\u30f3\u30c8\u30a8\u30f3\u30c9\u3068\u30ea\u30a2\u30eb\u30bf\u30a4\u30e0\u901a\u4fe1\u3092\u5b9f\u88c5<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">\u30bf\u30a4\u30de\u30fc\u306e\u30a8\u30f3\u30c6\u30a3\u30c6\u30a3\u3092\u4f5c\u6210<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.PomodoroTimer.domain;\n\nimport jakarta.persistence.Entity;\nimport jakarta.persistence.Id;\nimport jakarta.persistence.GeneratedValue;\nimport jakarta.persistence.GenerationType;\nimport lombok.Data;\n\n@Entity\n@Data\npublic class Timer {\n    @Id\n    @GeneratedValue(strategy = GenerationType.IDENTITY)\n    private Long id;\n    \n    private int workDuration; \/\/ \u4f5c\u696d\u6642\u9593\uff08\u5206\uff09\n    private int breakDuration; \/\/ \u4f11\u61a9\u6642\u9593\uff08\u5206\uff09\n    private int remainingTime; \/\/ \u6b8b\u308a\u6642\u9593\uff08\u79d2\uff09\n    private boolean isRunning; \/\/ \u30bf\u30a4\u30de\u30fc\u304c\u5b9f\u884c\u4e2d\u304b\u3069\u3046\u304b\n    private boolean isWorkTime; \/\/ \u4f5c\u696d\u6642\u9593\u304b\u4f11\u61a9\u6642\u9593\u304b\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u30bf\u30a4\u30de\u30fc\u5236\u5fa1\u7528\u306e\u30b5\u30fc\u30d3\u30b9\u3092\u4f5c\u6210<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.PomodoroTimer.service;\n\nimport com.example.PomodoroTimer.domain.Timer;\nimport org.springframework.stereotype.Service;\nimport org.springframework.scheduling.annotation.Scheduled;\nimport org.springframework.messaging.simp.SimpMessagingTemplate;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n@Service\npublic class TimerService {\n    \n    @Autowired\n    private SimpMessagingTemplate messagingTemplate;\n    \n    private Timer currentTimer;\n    \n    public TimerService() {\n        this.currentTimer = new Timer();\n        this.currentTimer.setWorkDuration(25);\n        this.currentTimer.setBreakDuration(5);\n        this.currentTimer.setRemainingTime(25 * 60);\n        this.currentTimer.setRunning(false);\n        this.currentTimer.setWorkTime(true);\n    }\n    \n    public Timer getCurrentTimer() {\n        return currentTimer;\n    }\n    \n    public void startTimer() {\n        currentTimer.setRunning(true);\n        notifyTimerUpdate();\n    }\n    \n    public void pauseTimer() {\n        currentTimer.setRunning(false);\n        notifyTimerUpdate();\n    }\n    \n    public void resetTimer() {\n        currentTimer.setRemainingTime(currentTimer.isWorkTime() ? \n            currentTimer.getWorkDuration() * 60 : \n            currentTimer.getBreakDuration() * 60);\n        currentTimer.setRunning(false);\n        notifyTimerUpdate();\n    }\n    \n    public void switchMode() {\n        currentTimer.setWorkTime(!currentTimer.isWorkTime());\n        currentTimer.setRemainingTime(currentTimer.isWorkTime() ? \n            currentTimer.getWorkDuration() * 60 : \n            currentTimer.getBreakDuration() * 60);\n        currentTimer.setRunning(false);\n        notifyTimerUpdate();\n    }\n    \n    @Scheduled(fixedRate = 1000)\n    public void updateTimer() {\n        if (currentTimer.isRunning() &amp;&amp; currentTimer.getRemainingTime() > 0) {\n            currentTimer.setRemainingTime(currentTimer.getRemainingTime() - 1);\n            notifyTimerUpdate();\n            \n            if (currentTimer.getRemainingTime() == 0) {\n                currentTimer.setRunning(false);\n                switchMode();\n            }\n        }\n    }\n    \n    private void notifyTimerUpdate() {\n        messagingTemplate.convertAndSend(\"\/topic\/timer\", currentTimer);\n    }\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">WebSocket\u306e\u8a2d\u5b9a\u3092\u3059\u308b<\/h2>\n\n\n\n<p>WebSocket\uff1aWeb\u30d6\u30e9\u30a6\u30b6\u3068Web\u30b5\u30fc\u30d0\u30fc\u306e\u9593\u3067\u3001\u53cc\u65b9\u5411\u304b\u3064\u6c38\u7d9a\u7684\u306a\u901a\u4fe1\u30c1\u30e3\u30cd\u30eb\u3092\u78ba\u7acb\u3059\u308b\u305f\u3081\u306e\u6280\u8853<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.PomodoroTimer.config;\n\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.messaging.simp.config.MessageBrokerRegistry;\nimport org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;\nimport org.springframework.web.socket.config.annotation.StompEndpointRegistry;\nimport org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;\n\n@Configuration\n@EnableWebSocketMessageBroker\npublic class WebSocketConfig implements WebSocketMessageBrokerConfigurer {\n\n    @Override\n    public void configureMessageBroker(MessageBrokerRegistry config) {\n        config.enableSimpleBroker(\"\/topic\");\n        config.setApplicationDestinationPrefixes(\"\/app\");\n    }\n\n    @Override\n    public void registerStompEndpoints(StompEndpointRegistry registry) {\n        registry.addEndpoint(\"\/ws\")\n                .setAllowedOrigins(\"http:\/\/localhost:8080\")\n                .withSockJS();\n    }\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u30bf\u30a4\u30de\u30fc\u5236\u5fa1\u7528\u306e\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30fc\u3092\u4f5c\u6210<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>package com.example.PomodoroTimer.controller;\n\nimport com.example.PomodoroTimer.domain.Timer;\nimport com.example.PomodoroTimer.service.TimerService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\n@RestController\n@RequestMapping(\"\/api\/timer\")\n@CrossOrigin(origins = \"http:\/\/localhost:8080\")\npublic class TimerController {\n\n    @Autowired\n    private TimerService timerService;\n\n    @GetMapping(\"\/current\")\n    public Timer getCurrentTimer() {\n        return timerService.getCurrentTimer();\n    }\n\n    @PostMapping(\"\/start\")\n    public void startTimer() {\n        timerService.startTimer();\n    }\n\n    @PostMapping(\"\/pause\")\n    public void pauseTimer() {\n        timerService.pauseTimer();\n    }\n\n    @PostMapping(\"\/reset\")\n    public void resetTimer() {\n        timerService.resetTimer();\n    }\n\n    @PostMapping(\"\/switch\")\n    public void switchMode() {\n        timerService.switchMode();\n    }\n}<\/code><\/pre>\n\n\n\n<p>\u4e3b\u306a\u5909\u66f4\u70b9\u306f\u4ee5\u4e0b\u306e4\u70b9<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Timer\u30a8\u30f3\u30c6\u30a3\u30c6\u30a3\uff1a\u30bf\u30a4\u30de\u30fc\u306e\u72b6\u614b\u3092\u7ba1\u7406<\/li>\n\n\n\n<li>TimerService\uff1a\u30bf\u30a4\u30de\u30fc\u306e\u5236\u5fa1\u30ed\u30b8\u30c3\u30af\u3092\u5b9f\u88c5<\/li>\n\n\n\n<li>WebSocketConfig\uff1a\u30ea\u30a2\u30eb\u30bf\u30a4\u30e0\u901a\u4fe1\u306e\u8a2d\u5b9a<\/li>\n\n\n\n<li>TimerController\uff1aREST API\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u306e\u63d0\u4f9b<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>\u4eca\u307e\u3067\u306e\u30bf\u30a4\u30de\u30fc\u306f\u307b\u3068\u3093\u3069\u30d5\u30ed\u30f3\u30c8\u30a8\u30f3\u30c9\u3067\u884c\u3063\u3066\u3044\u305f\u306e\u3067\u7de8\u96c6\u3092\u884c\u3044\u307e\u3059 \u30bf\u30a4\u30de\u30fc\u6a5f\u80fd\u3092\u30d0\u30c3\u30af\u30a8\u30f3\u30c9\u306b\u79fb\u884c\u3059\u308b \u30bf\u30a4\u30de\u30fc\u306e\u30a8\u30f3\u30c6\u30a3\u30c6\u30a3\u3092\u4f5c\u6210 package com.example.PomodoroTi &#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-214","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/suyasuyahirohiro.com\/index.php?rest_route=\/wp\/v2\/posts\/214","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/suyasuyahirohiro.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/suyasuyahirohiro.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/suyasuyahirohiro.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/suyasuyahirohiro.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=214"}],"version-history":[{"count":2,"href":"https:\/\/suyasuyahirohiro.com\/index.php?rest_route=\/wp\/v2\/posts\/214\/revisions"}],"predecessor-version":[{"id":217,"href":"https:\/\/suyasuyahirohiro.com\/index.php?rest_route=\/wp\/v2\/posts\/214\/revisions\/217"}],"wp:attachment":[{"href":"https:\/\/suyasuyahirohiro.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=214"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/suyasuyahirohiro.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=214"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/suyasuyahirohiro.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=214"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}