今日目標,網址 room 的請求分發、房間頁面。
我們依然先搞定頁面的部份,再來處理 Controller。
<!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()
,函數實際行為小弟將會在明天定義~~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;
}
resources/static/js
底下建立 room.js
,內容先空著,明天再來實作~~room.html
的 layout: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>
再來處理請求分發。
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今天依然先實現頁面和請求分發,隔天才處理功能串接以及動態的顯示資訊~~