SBA301DễKỳ 7Chuyên ngành Cập nhật 04/08/2026

Tích hợp ứng dụng trang đơn với Spring Boot - Integrate single page application with Spring Boot

SBA301 - Phát triển ứng dụng trang đơn (Single Page Application) dạy cách dựng một ứng dụng web có hai nửa ghép lại: ReactJS chạy trong trình duyệt và dịch vụ REST viết bằng Spring Boot chạy trên máy chủ. Câu hỏi xuyên suốt là ranh giới giữa hai nửa đó nằm ở đâu, dữ liệu đi qua lại thế nào và ai chịu trách nhiệm phần nào. Nửa trình duyệt bắt đầu từ JSX cùng cách chia giao diện thành component, rồi tới trạng thái: React Hooks với useState, useEffect, useMemo, useCallback, các ràng buộc của Rules of Hooks, và lối giữ state ở component hàm đặt cạnh lối cũ ở component lớp. Bộ component dựng sẵn React-Bootstrap lo phần trình bày. Việc chuyển trang không còn do máy chủ đảm nhận mà do định tuyến phía client với React Router v6, kèm tham số đường dẫn đọc bằng useParams và trang 404 bắt ở cuối bảng route. Để lấy dữ liệu, môn đi qua nền bất đồng bộ của JavaScript gồm Promise và async/await, rồi tới thư viện Axios cho các lời gọi thực tế. Nửa máy chủ mở bằng nền tảng HTTP và nguyên tắc của một REST API, sau đó dựng dịch vụ bằng Spring Boot với các chú giải ánh xạ yêu cầu như RequestBody, PathVariable, RequestParam, cách đặt mã trạng thái và thân phản hồi. Tài liệu cho dịch vụ được sinh sống bằng OpenAPI và Swagger, còn phần kiểm thử dùng bộ khởi tạo spring-boot-starter-test để chạy thử cả tầng web lẫn toàn bộ ứng dụng. Tầng dữ liệu có hai nhánh. Nhánh quan hệ dùng JPA và Hibernate với ánh xạ đối tượng sang bảng, Session và Transaction, khoá lạc quan chống xung đột khi ghi đồng thời, phân trang cùng lựa chọn Slice khi không cần đếm toàn bộ bản ghi, và hbm2ddl sinh lược đồ. Nhánh tài liệu dùng MongoDB với lược đồ linh hoạt, Spring Data MongoDB, MongoTemplate cho truy vấn phức tạp và dịch vụ đám mây MongoDB Atlas. Khép môn là bảo mật với Spring Security, từ xác thực cơ bản và phiên làm việc tới token JWT cho dịch vụ phi trạng thái. Học xong, người học dựng được trọn một ứng dụng trang đơn có đăng nhập, gọi dịch vụ REST, lưu dữ liệu ở cả cơ sở dữ liệu quan hệ lẫn cơ sở dữ liệu tài liệu, và có tài liệu mô tả giao diện lập trình kèm theo.

171Câu hỏi
2Bộ đề
11Chủ đề

Câu hỏi của môn

144/171 câuCòn 27
125How can a server prompt the browser to show a login dialog for Basic Auth?4 lựa chọnDễ100% trả lời đúng
ABy including WWW-Authenticate: Basic realm='RealmName' in a 401 response
BBy sending a Set-Cookie header with a token
CBy returning 403 with Login-Required: true
DBy using JavaScript redirect
Lời giải
Để một máy chủ yêu cầu trình duyệt hiển thị hộp thoại đăng nhập cho Basic Auth, máy chủ cần gửi một phản hồi 401 (Không được phép) với tiêu đề HTTP WWW-Authenticate. Tiêu đề này chứa thông tin về tên miền (realm) mà máy chủ đang yêu cầu. Ví dụ, máy chủ có thể gửi phản hồi 401 với tiêu đề WWW-Authenticate: Basic realm='RealmName'. Điều này sẽ yêu cầu trình duyệt hiển thị hộp thoại đăng nhập cho người dùng, nơi họ có thể nhập tên người dùng và mật khẩu. Sau khi người dùng nhập thông tin đăng nhập, trình duyệt sẽ gửi lại yêu cầu đến máy chủ với tiêu đề Authorization chứa thông tin đăng nhập. Máy chủ sẽ kiểm tra thông tin đăng nhập và trả lại phản hồi 200 nếu thông tin đúng, hoặc tiếp tục trả lại phản hồi 401 nếu thông tin sai.
Mở trang câu hỏi này →
AAuthorization: Bearer (token)
BAuthorization: Basic (base64(username:password))
CAuthorization: Token username:password
DAuth: Basic (JWT)
Lời giải
Trong Basic Authentication, định dạng của tiêu đề Authorization sẽ trông như thế nào? Đây là một dạng xác thực cơ bản sử dụng tiêu đề Authorization để xác thực người dùng. Khi sử dụng Basic Authentication, người dùng sẽ gửi tiêu đề Authorization với nội dung là 'Basic' kèm theo mã hóa base64 của chuỗi 'username:password'. Ví dụ, nếu username là 'user' và password là 'pass', thì tiêu đề Authorization sẽ được gửi dưới dạng 'Authorization: Basic dXNlcjpwYXNzd29yZA=='. Mã hóa base64 được sử dụng để bảo mật thông tin người dùng.
Mở trang câu hỏi này →
127Which HTTP header is commonly used to transmit the session ID?4 lựa chọnTrung bình67% trả lời đúng
AAuthorization
BCookie
CX-Session-Token
DSet-Header
Lời giải
HTTP header được sử dụng phổ biến để truyền tải ID phiên là Cookie. Cookie là một phần của HTTP header được sử dụng để lưu trữ thông tin về phiên làm việc của người dùng. Khi người dùng đăng nhập vào một trang web, trang web sẽ tạo một ID phiên và lưu trữ nó trong Cookie. Mỗi lần người dùng gửi yêu cầu đến trang web, Cookie sẽ được gửi kèm theo yêu cầu và trang web sẽ sử dụng ID phiên để xác thực người dùng. Điều này giúp trang web có thể lưu trữ thông tin về người dùng và cung cấp trải nghiệm cá nhân hóa. Ngoài ra, Cookie cũng được sử dụng để lưu trữ thông tin về các lựa chọn của người dùng, chẳng hạn như ngôn ngữ hoặc kích thước font.
Mở trang câu hỏi này →
128Which of the following is false about Basic Authentication?4 lựa chọnDễ75% trả lời đúng
AIt does not require session on server
BIt is stateless
CIt can be used with REST APIs
DIt is considered more secure than OAuth2
Lời giải
Basic Authentication là một phương thức xác thực cơ bản trong đó người dùng gửi thông tin đăng nhập (tên người dùng và mật khẩu) qua mỗi yêu cầu HTTP. Phương thức này không yêu cầu lưu trữ phiên trên máy chủ, vì vậy nó được coi là một phương thức stateless. Điều này có nghĩa là máy chủ không cần lưu trữ thông tin về phiên hiện tại của người dùng, giúp giảm thiểu khả năng bị tấn công từ chối dịch vụ (DDoS). Ngoài ra, Basic Authentication có thể được sử dụng với các API REST, vì nó cung cấp một cách đơn giản để xác thực người dùng. Tuy nhiên, phương thức này không được coi là an toàn hơn OAuth2. Trên thực tế, Basic Authentication gửi thông tin đăng nhập qua mỗi yêu cầu HTTP, điều này có thể dễ bị bắt trộm và sử dụng bởi kẻ tấn công. Do đó, OAuth2 được coi là một phương thức an toàn hơn vì nó yêu cầu người dùng xác thực thông qua một ứng dụng trung gian và không gửi thông tin đăng nhập qua mỗi yêu cầu.
Mở trang câu hỏi này →
129What does @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) do?4 lựa chọnDễ100% trả lời đúng
AStarts the application with no web environment
BFails the test if no port is provided manually
CDisables the web server
DStarts the embedded server on a random port
Lời giải
Khi sử dụng @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT), Spring Boot sẽ khởi động ứng dụng trong môi trường web ngẫu nhiên. Điều này có nghĩa là ứng dụng sẽ được chạy trên một cổng ngẫu nhiên, thay vì sử dụng cổng mặc định. Mục đích chính của việc này là để tránh xung đột cổng khi chạy nhiều ứng dụng cùng lúc. Ngoài ra, việc sử dụng môi trường web ngẫu nhiên cũng giúp tăng tính bảo mật cho ứng dụng, vì nó làm cho việc đoán cổng của ứng dụng trở nên khó khăn hơn. Khi ứng dụng được khởi động trong môi trường web ngẫu nhiên, Spring Boot sẽ tự động tạo một cổng ngẫu nhiên và cấu hình ứng dụng để sử dụng cổng đó. Điều này giúp đảm bảo rằng ứng dụng có thể được truy cập từ xa mà không cần phải biết cổng cụ thể của ứng dụng.
Mở trang câu hỏi này →
130You want to inject a TestRestTemplate in a @SpringBootTest. What is required?4 lựa chọnDễ80% trả lời đúng
AUse @MockBean
BUse webEnvironment = WebEnvironment.NONE
CUse @WebMvcTest
DUse webEnvironment = WebEnvironment.RANDOM_PORT
Lời giải
Để có thể sử dụng TestRestTemplate trong một @SpringBootTest, bạn cần sử dụng webEnvironment = WebEnvironment.RANDOM_PORT. Điều này cho phép Spring Boot tạo một server tạm thời để phục vụ cho việc kiểm thử. Khi sử dụng RANDOM_PORT, bạn có thể sử dụng TestRestTemplate để gửi yêu cầu đến server tạm thời này. Nếu bạn sử dụng NONE, thì TestRestTemplate sẽ không thể gửi yêu cầu đến server vì server không được tạo. Sử dụng @MockBean hoặc @WebMvcTest sẽ không giúp bạn tạo được server tạm thời để TestRestTemplate có thể gửi yêu cầu.
Mở trang câu hỏi này →
131When used with JUnit 5, which annotation is commonly paired with @SpringBootTest?4 lựa chọnTrung bình60% trả lời đúng
A@MockBean
B@ExtendWith(SpringExtension.class)
C@DataJpaTest
D@TestConfiguration
Lời giải
Khi sử dụng JUnit 5, annotation thường được sử dụng cùng với @SpringBootTest là @ExtendWith(SpringExtension.class). Annotation này cho phép JUnit 5 sử dụng Spring Boot để chạy các test. Nó giúp tạo ra một môi trường thử nghiệm đầy đủ cho ứng dụng Spring Boot, bao gồm cả các tính năng như autowiring và dependency injection. Điều này cho phép các nhà phát triển viết các test đơn giản và hiệu quả hơn. Ngoài ra, @ExtendWith(SpringExtension.class) cũng giúp giảm thiểu số lượng mã cần thiết để cấu hình môi trường thử nghiệm.
Mở trang câu hỏi này →
AwebEnvironment = NONE
BwebEnvironment = MOCK
CuseMockMvc = true
DwebEnvironment = DEFINED_PORT
Lời giải
Để kiểm tra các điểm cuối của controller sử dụng các cuộc gọi HTTP thực tế, bạn cần cấu hình @SpringBootTest để sử dụng môi trường web thực tế. Trong đó, bạn cần thiết lập thuộc tính webEnvironment thành DEFINED_PORT. Điều này cho phép Spring Boot tạo một ứng dụng web thực tế với một cổng cụ thể, và bạn có thể sử dụng các công cụ như Postman hoặc cURL để gửi các yêu cầu HTTP đến ứng dụng này. Điều này giúp bạn kiểm tra các điểm cuối của controller một cách chính xác và hiệu quả hơn.
Mở trang câu hỏi này →
A@Configuration
B@DataJpaTest
C@WebMvcTest
D@EnableAutoConfiguration
Lời giải
Để kiểm tra chỉ lớp web, bạn có thể sử dụng annotation @WebMvcTest thay thế cho @SpringBootTest. Annotation này cho phép bạn kiểm tra lớp web mà không cần phải khởi tạo toàn bộ ứng dụng. @WebMvcTest sẽ tự động tạo một ứng dụng web nhỏ để kiểm tra lớp web của bạn. Điều này giúp bạn kiểm tra các lớp controller, service và repository mà không cần phải khởi tạo toàn bộ ứng dụng.
Mở trang câu hỏi này →
ADisabling security in React.
BConfiguring CORS in Spring Boot.
CUsing server-side rendering exclusively.
DUsing iframes to embed the Spring Boot application.
Lời giải
Để xử lý các yêu cầu có nguồn gốc khác nhau (CORS) giữa React và Spring Boot, có một số cách tiếp cận phổ biến. Một trong số đó là cấu hình CORS trong Spring Boot. Điều này cho phép Spring Boot xác định các nguồn gốc được phép thực hiện các yêu cầu đến ứng dụng của nó, giúp ngăn chặn các yêu cầu không mong muốn. Điều này được thực hiện thông qua việc thêm các tiêu đề HTTP đặc biệt vào các phản hồi của ứng dụng, chẳng hạn như Access-Control-Allow-Origin. Bằng cách cấu hình CORS trong Spring Boot, bạn có thể kiểm soát các yêu cầu có nguồn gốc khác nhau đến ứng dụng của mình và đảm bảo rằng chúng được xử lý một cách an toàn và hiệu quả.
Mở trang câu hỏi này →
AMulti-threading
BBlocking I/O
CEvent-driven, non-blocking I/O
DRelational databases
Lời giải
Node.js là một nền tảng phát triển ứng dụng dựa trên JavaScript, và một trong những tính năng quan trọng giúp nó xử lý hiệu quả các yêu cầu đồng thời là cơ chế I/O không chặn (non-blocking I/O). Điều này cho phép Node.js xử lý nhiều yêu cầu đồng thời mà không cần tạo ra nhiều luồng (thread) như các ngôn ngữ lập trình khác. Thay vào đó, Node.js sử dụng một cơ chế sự kiện (event-driven) để quản lý các yêu cầu và xử lý chúng một cách hiệu quả. Khi một yêu cầu được gửi đến, Node.js sẽ thêm nó vào một danh sách các sự kiện cần được xử lý, và sau đó xử lý các sự kiện khác trong khi chờ đợi kết quả của yêu cầu đó. Điều này giúp Node.js xử lý nhiều yêu cầu đồng thời mà không cần tốn nhiều tài nguyên hệ thống.
Mở trang câu hỏi này →
136Which command is used to create a new branch called "feature-login"?4 lựa chọnDễ71% trả lời đúng
Agit branch create feature-login
Bgit new branch feature-login
Cgit branch feature-login
Dgit checkout feature-login
Lời giải
Để tạo một nhánh mới trong Git, bạn cần sử dụng lệnh 'git branch'. Lệnh này được sử dụng để tạo một nhánh mới từ một điểm cụ thể trong lịch sử commit của dự án. Trong câu hỏi này, bạn cần tạo một nhánh mới có tên là 'feature-login'. Lệnh đúng để tạo nhánh mới là 'git branch feature-login'. Lệnh này sẽ tạo một nhánh mới có tên là 'feature-login' và nó sẽ được tạo từ điểm hiện tại của nhánh hiện tại. Nếu bạn muốn chuyển sang nhánh mới ngay lập tức, bạn cần sử dụng lệnh 'git checkout' sau khi tạo nhánh mới.
Mở trang câu hỏi này →
137Which code snippet correctly creates a React-Bootstrap form select control?4 lựa chọnTrung bình67% trả lời đúng
A<Form.Select> <option>1</option> <option>2</option> </Form.Select>
B<Select> <option>1</option> <option>2</option> </Select>
C<Form.Dropdown> <option>1</option> <option>2</option> </Form.Dropdown>
D<Dropdown> <option>1</option> <option>2</option> </Dropdown>
Lời giải

Để tạo một form select control trong React-Bootstrap, bạn cần sử dụng thẻ <Form.Select>. Thẻ này sẽ tạo một lựa chọn dropdown cho người dùng. Ví dụ, bạn muốn tạo một form select với các lựa chọn là 1 và 2, bạn có thể sử dụng mã sau:

Lời giải
<Form.Select>
  <option>1</option>
  <option>2</option>
</Form.Select>

. Điều này sẽ tạo một form select với hai lựa chọn là 1 và 2. Ngoài ra, bạn cũng có thể sử dụng các thẻ khác như <Select>, <Form.Dropdown>, <Dropdown> nhưng chúng không phải là thẻ chính thức để tạo form select control trong React-Bootstrap.

Mở trang câu hỏi này →
138How do you create navigation links in a React-Bootstrap Navbar?4 lựa chọnDễ100% trả lời đúng
A<NavLink>
B<Nav Link>
C<Link>
D<Anchor>
Lời giải

Để tạo liên kết điều hướng trong Navbar của React-Bootstrap, bạn cần sử dụng thẻ <NavLink>. Thẻ này cho phép bạn tạo liên kết điều hướng với các thuộc tính như href, active, exact, và nhiều thuộc tính khác. Ví dụ, bạn có thể sử dụng <NavLink> như sau: import { NavLink } from 'react-bootstrap'; <NavLink to="/home">Trang chủ</NavLink> Trong ví dụ trên, <NavLink> được sử dụng để tạo liên kết điều hướng đến trang chủ với đường dẫn /home. Ngoài ra, bạn cũng có thể sử dụng thuộc tính active để chỉ định liên kết hiện tại. <NavLink active to="/home">Trang chủ</NavLink> Tóm lại, <NavLink> là một phần quan trọng trong việc tạo liên kết điều hướng trong Navbar của React-Bootstrap.

Mở trang câu hỏi này →
139Which of the following is a valid JSX expression?4 lựa chọnTrung bình63% trả lời đúng
A<div class="my-class">Hello</div>
B<component style="my-style">World</component>
C<for (let i = 0; i < 5; i++)>Loop</for>
D<if (true) {}>
Lời giải

Trong JSX, các biểu thức hợp lệ phải tuân theo các quy tắc sau: - Các thẻ HTML phải được viết theo cú pháp mở và đóng đúng. - Các thuộc tính phải được viết theo cú pháp

Lời giải
<div class="my-class">. -

Các biểu thức JavaScript không được sử dụng trong JSX. - Các biểu thức JSX không được sử dụng trong JavaScript. - Các thẻ không được sử dụng trong JSX. Vậy, trong các lựa chọn trên, chỉ có "<div class="my-class">Hello</div> " là một biểu thức JSX hợp lệ.

Mở trang câu hỏi này →
140How do you show a success message alert in React-Bootstrap?4 lựa chọnTrung bình57% trả lời đúng
A<Alert type="success">Message</Alert>
B<Alert variant="success">Message</Alert>
C<Alert style="success">Message</Alert>
D<SuccessAlert>Message</SuccessAlert>
Lời giải

Để hiển thị thông báo thành công trong React-Bootstrap, bạn cần sử dụng thẻ Alert với thuộc tính variant được đặt thành 'success'. Ví dụ, bạn có thể sử dụng thẻ Alert như sau: <Alert variant="success">Message</Alert>. Điều này sẽ hiển thị một thông báo thành công với nội dung 'Message'. Ngoài ra, bạn cũng có thể sử dụng các thuộc tính khác như type hoặc style để thay đổi màu sắc hoặc kiểu dáng của thông báo, nhưng variant là thuộc tính được khuyến nghị sử dụng trong React-Bootstrap.

Mở trang câu hỏi này →
141Which lifecycle method in React class components is used for side effects?4 lựa chọnDễ100% trả lời đúng
AcomponentDidMount
Brender
Cconstructor
DshouldComponentUpdate
Lời giải
Trong React, lifecycle method được sử dụng để thực hiện các tác vụ phụ (side effects) khi một thành phần thay đổi trạng thái. 'componentDidMount' là một trong những lifecycle method quan trọng nhất, được sử dụng để thực hiện các tác vụ phụ sau khi thành phần được render vào DOM. Ví dụ, bạn có thể sử dụng 'componentDidMount' để tải dữ liệu từ server, hoặc thực hiện các hành động khác khi thành phần được render xong. Ngoài ra, bạn cũng có thể sử dụng 'componentDidUpdate' để thực hiện các tác vụ phụ khi thành phần thay đổi trạng thái.
Mở trang câu hỏi này →
142Which built-in Hook is used to access context values in Functional Components?4 lựa chọnTrung bình67% trả lời đúng
AuseContext()
BuseProps()
CuseValue()
DuseContextValue()
Lời giải
Trong lập trình React, khi sử dụng các thành phần chức năng (Functional Components), chúng ta có thể truy cập vào giá trị của ngữ cảnh (context) bằng cách sử dụng Hook. Hook là một hàm đặc biệt được sử dụng để truy cập vào các giá trị và hành vi của React. Trong trường hợp này, chúng ta cần sử dụng Hook để truy cập vào giá trị của ngữ cảnh. Có một số lựa chọn cho chúng ta: useProps(), useValue(), useContextValue(), useContext(). Tuy nhiên, chỉ có một trong số đó là đúng. Đó là useContext(). Hook useContext() cho phép chúng ta truy cập vào giá trị của ngữ cảnh và sử dụng nó trong thành phần chức năng của mình.
Mở trang câu hỏi này →
143Which hook is an alternative to useState for complex state management?4 lựa chọnTrung bình50% trả lời đúng
AuseMemo
BuseReducer
CuseRef
DuseEffect
Lời giải
Khi sử dụng useState để quản lý trạng thái phức tạp, bạn có thể gặp phải một số vấn đề như trạng thái không được cập nhật đúng cách hoặc trạng thái bị trùng lặp. Trong trường hợp này, bạn có thể sử dụng useReducer như một giải pháp thay thế. useReducer cho phép bạn quản lý trạng thái phức tạp bằng cách sử dụng một hàm reducer để cập nhật trạng thái. Hàm reducer này sẽ nhận vào một trạng thái hiện tại và một hành động, sau đó trả về một trạng thái mới. Điều này giúp bạn có thể quản lý trạng thái phức tạp một cách dễ dàng và hiệu quả.
Mở trang câu hỏi này →
144What is the purpose of a custom Hook?4 lựa chọnDễ100% trả lời đúng
ATo replace built-in Hooks.
BTo share stateful logic between components.
CTo define CSS styles.
DTo manage database connections.
Lời giải
Một Custom Hook là một hàm có thể được sử dụng trong các thành phần React để chia sẻ logic trạng thái giữa các thành phần. Nó cho phép bạn tái sử dụng mã và giảm sự lặp lại trong ứng dụng của mình. Ví dụ, bạn có thể tạo một Custom Hook để quản lý trạng thái người dùng, như lưu trữ thông tin đăng nhập hoặc lưu trữ dữ liệu người dùng. Điều này giúp bạn dễ dàng chia sẻ logic trạng thái giữa các thành phần và làm cho mã của bạn trở nên dễ đọc và dễ bảo trì hơn. Ngoài ra, Custom Hooks cũng cho phép bạn tái sử dụng mã và giảm sự lặp lại trong ứng dụng của mình.
Mở trang câu hỏi này →