iT邦幫忙

2022 iThome 鐵人賽

DAY 21
0

今日目標,網址 room 的請求分發、房間頁面。

頁面

我們依然先搞定頁面的部份,再來處理 Controller。

  1. 在 templates 底下建立一個 HTML file,名稱為 room,內容為:
    <!DOCTYPE html>
    <html lang="en" xmlns="http://www.w3.org/1999/xhtml"
        xmlns:th="http://www.thymeleaf.org"
        xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
        layout:decorate="~{layout.html}"
    >
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div layout:fragment="content" class="card game-window">
        <input id="my-username" type="hidden" th:value="${username}">
        <div class="text-center">
            <div class="card page-title">
                <div class="h3">房號</div>
                <div class="h3" id="room-id"></div>
            </div>
            <button type="button" class="btn btn-danger float-right back-button" id="quit-room-button">
                <i class="bi bi-box-arrow-right"></i>
            </button>
        </div>
        <div class="card-deck" id="room" style="margin: 20px 40px;">
            <div class="card text-center"></div>
            <div class="card text-center"></div>
            <div class="card text-center"></div>
            <div class="card text-center"></div>
        </div>
        <div class="text-center">
            <button type="button" class="btn btn-success" id="ready" onclick="ready()" style="font-size: 25px; width: 150px;">準備</button>
        </div>
    </div>
    
    <div layout:fragment="js-and-css">
        <!-- websockets -->
        <script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.js"
                integrity="sha512-tL4PIUsPy+Rks1go4kQG8M8/ItpRMvKnbBjQm4d2DQnFwgcBYRRN00QdyQnWSCwNMsoY/MfJY8nHp2CzlNdtZA=="
                crossorigin="anonymous"
                referrerpolicy="no-referrer"></script>
    
        <!-- custom -->
        <script type="text/javascript" th:src="@{/js/WebSockets.js}"></script>
    </div>
    </body>
    </html>
    
    • 準備的按鈕先綁定 ready(),函數實際行為小弟將會在明天定義~~
  2. 再來我們先添加 css 檔案,在 resources/static/css 底下建立 room.css,內容為:
    .close-button {
        display: flex;
        margin: -21px -20px -20px auto;
        background-color: #fff !important;
        border-radius: 100%;
        font-size: 40px;
        color: #dc3545;
        opacity: 1 !important;
        z-index: 999;
    }
    .close-button:hover {
        color: #C72334;
    }
    
    .back-button {
        position: absolute;
        top: 20px;
        right: 20px;
        font-size: 40px;
    }
    
  3. 再來我們先準備好 JavaScript 的檔案,在 resources/static/js 底下建立 room.js,內容先空著,明天再來實作~~
  4. 修改 room.htmllayout:fragment="js-and-css" 區塊,將剛才的 css 和 js 檔案引入:
    <div layout:fragment="js-and-css">
        <!-- websockets -->
        <script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.js"
                integrity="sha512-tL4PIUsPy+Rks1go4kQG8M8/ItpRMvKnbBjQm4d2DQnFwgcBYRRN00QdyQnWSCwNMsoY/MfJY8nHp2CzlNdtZA=="
                crossorigin="anonymous"
                referrerpolicy="no-referrer"></script>
    
        <!-- custom -->
        <script type="text/javascript" th:src="@{/js/WebSockets.js}"></script>
        <script type="text/javascript" th:src="@{/js/room.js}"></script>
        <link th:href="@{/css/room.css}" rel="stylesheet">
    </div>
    

Controller

再來處理請求分發。
/images/emoticon/emoticon13.gif

  1. 在 RoomController 內添加 viewRoomPage(),發現紅字的話記得檢查有沒有注入實例,完整內容為:
    package com.example.room;
    
    import com.example.user.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import java.util.HashMap;
    import java.util.Map;
    
    @Controller
    public class RoomController {
        @Autowired
        private UserService userService;
    
        @Autowired
        private UserStatus userStatus;
    
        @Autowired
        private RoomService roomService;
    
        @Autowired
        private RoomList roomList;
    
        @GetMapping("/rooms")
        public String viewAllRoomsPage(Model model) {
            if (userService.isLogin()) {
                String username = userService.getUsername();
                if (this.userStatus.containsUser(username) && this.userStatus.isUserInRoom(username)) {
                    return "redirect:/room/" + this.userStatus.getUserRoomId(username);
                }
                this.userStatus.initialize(username);
            }
            model.addAttribute("disableJoinRoomButton", !userService.isLogin());
            return "rooms";
        }
    
        @GetMapping("/room/{roomId}")
        public String viewRoomPage(@PathVariable("roomId") String roomId, Model model) {
            // 如果房號不存在
            if (!this.roomList.containRoomId(roomId)) {
                return "redirect:/rooms";
            }
    
            // 使用者必須先登入
            if (userService.isLogin()) {
                String username = userService.getUsername();
                model.addAttribute("username", username);
                // 如果使用者有狀態,而且儲存的房號跟網址相同
                if (this.userStatus.containsUser(username) && this.userStatus.getUserRoomId(username).equals(roomId)) {
                    return "room";
                }
    
                // 否則,讓使用者加入該房間
                if (roomService.joinInRoom(username, roomId)) {
                    return "room";
                }
            }
    
            // 沒有登入的話,就不給進
            return "redirect:/rooms";
        }
    
        @PostMapping("/api/room/join")
        @ResponseBody
        public ResponseEntity<Map<String, Object>> joinRoomProcess(UserJoinRoomMessage userJoinRoomMessage) {
            Map<String, Object> response = new HashMap<>();
            HttpStatus httpStatus;
            String message;
            if (!userService.isLogin()) {
                httpStatus = HttpStatus.FORBIDDEN;
                message = "未登入";
                response.put("message", message);
                return ResponseEntity.status(httpStatus).body(response);
            }
    
            String username = userService.getUsername();
            String action = userJoinRoomMessage.getAction();
            String roomId = userJoinRoomMessage.getRoomId();
            if (action.equals("create") && roomService.createRoom(username)) {
                httpStatus = HttpStatus.OK;
                message = "建立成功";
            }
            else if (action.equals("join") && roomService.joinInRoom(username, roomId)) {
                httpStatus = HttpStatus.OK;
                message = "加入成功";
            }
            else {
                httpStatus = HttpStatus.BAD_REQUEST;
                message = "Error";
            }
    
            if (httpStatus == HttpStatus.OK) {
                this.roomService.broadcastRoomList();
                roomId = this.userStatus.getUserRoomId(username);
            }
            else {
                roomId = "";
            }
            response.put("message", message);
            response.put("roomId", roomId);
            return ResponseEntity.status(httpStatus).body(response);
        }
    }
    
    • @GetMapping("/room/{roomId}"):指定網址 room 後面要帶一組變數代表房號(變數名稱為 roomId),之後在 viewRoomPage() 的參數才能使用
    • @PathVariable("roomId"):說明會使用到網址給定的變數 roomId,後面 String roomId 是宣告變數 roomId 和指定型態 String
  2. 再來就去頁面登入 -> 創建房間 -> 挑轉房間頁面,再來就會看到如下圖的 醜醜 頁面,至於房間內容,小弟將在明天使用 WebSocket 接收並顯示出來,到時候就比較好看了~~

今天依然先實現頁面和請求分發,隔天才處理功能串接以及動態的顯示資訊~~ /images/emoticon/emoticon01.gif


上一篇
Day 19 - 即時顯示房間列表的資料
下一篇
Day 21 - 即時更新房間資訊
系列文
Spring Boot... 深不可測31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言