Danh sách câu hỏi của đề

Câu hỏi: PRJ301 Phát triển ứng dụng Java web – Bộ ôn tập cuối kỳ số 4

50 câu trắc nghiệm kèm lời giải của môn PRJ301 - Phát triển ứng dụng Java web, xếp đúng thứ tự trong đề.

Danh sách câu hỏi

20/50 câuCòn 30
AGET
BPOST
CDELETE
DPUT
Lời giải
Đáp án đúng: "POST". Khi gửi bằng phương thức này, dữ liệu của biểu mẫu nằm trong thân thông điệp yêu cầu nên không hiện trên thanh địa chỉ, không bị lưu vào lịch sử trình duyệt, không rơi vào tiêu đề Referer và cũng không bị ghi nguyên vào nhật ký máy chủ như phần truy vấn; đó là lý do trang đăng nhập luôn dùng nó, dù muốn an toàn thật thì vẫn phải chạy trên HTTPS vì thân yêu cầu không tự được mã hoá. "GET" đặt mọi tham số vào địa chỉ, thành ra mật khẩu hiện công khai và liên kết dễ bị chia sẻ lại nguyên trạng. "DELETE" không phải phương thức để gửi dữ liệu biểu mẫu, nó mang nghĩa yêu cầu xoá tài nguyên và cũng chẳng kín hơn vì vẫn định danh tài nguyên trên địa chỉ. "PUT" dùng để tạo hoặc thay thế tài nguyên tại một địa chỉ cho trước, mà thẻ biểu mẫu trong HTML lại không gửi được phương thức này.
Mở trang câu hỏi này →
ADatabase
BModel
CView
DController
Lời giải
Đáp án đúng: "Database". Mẫu kiến trúc này chỉ gồm ba vai: phần mô hình giữ dữ liệu và nghiệp vụ, phần hiển thị dựng giao diện, phần điều khiển điều phối yêu cầu. Cơ sở dữ liệu là một hệ thống lưu trữ bên ngoài mà phần mô hình kết nối tới qua JDBC hoặc JPA; nó có thể bị thay bằng tệp hay dịch vụ khác mà kiến trúc không đổi, nên nó nằm ngoài ranh giới của mẫu. "Model" là thành phần chuẩn, chính nó mang các lớp thực thể và lớp truy cập dữ liệu. "View" là thành phần chuẩn, đảm nhiệm việc kết xuất HTML từ dữ liệu được truyền sang. "Controller" là thành phần chuẩn, trong Java web chính là servlet đọc tham số, gọi nghiệp vụ rồi chọn trang để forward tới.
Mở trang câu hỏi này →
AgetServletConfig().getInitParameter()
BgetRequestDispatcher()
CgetServletContext().getInitParameter()
DgetParameterValues()
Lời giải
Đáp án đúng: "getServletContext().getInitParameter()". Tham số khởi tạo mức ngữ cảnh được khai bằng thẻ context-param và thuộc về cả ứng dụng, nên phải lấy qua đối tượng ngữ cảnh: servlet gọi getServletContext() rồi đọc theo tên, và mọi servlet, filter hay listener trong cùng ứng dụng đều nhận được giá trị như nhau. "getServletConfig().getInitParameter()" cũng đọc tham số khởi tạo nhưng là tham số riêng của một servlet, khai trong thẻ init-param lồng trong thẻ servlet; gọi nó để tìm cấu hình chung sẽ nhận về null. "getRequestDispatcher()" không liên quan tới cấu hình, nó trả về bộ phân phối để forward hoặc include sang tài nguyên khác. "getParameterValues()" thuộc đối tượng yêu cầu và đọc tham số do người dùng gửi lên, thường là nhóm hộp kiểm trùng tên, chứ không đọc gì trong mô tả triển khai.
Mở trang câu hỏi này →
Đề bài
    <p>${user.name}</p>
</c:forEach>
<p>End of list</p>
AIt will display all user names followed by "End of list".
BIt will throw a NullPointerException because userList is empty.
CIt will only print "End of list".
DThe page will crash due to an iteration error.
Lời giải
Đáp án đúng: "It will only print "End of list".". Thẻ forEach lặp theo số phần tử của tập được truyền vào thuộc tính items, nên danh sách rỗng nghĩa là không có lượt nào và thân thẻ không sinh ra đoạn văn bản nào; dòng nằm sau vòng lặp không phụ thuộc vòng lặp nên vẫn được in bình thường. Lựa chọn "It will display all user names followed by "End of list"." chỉ đúng khi danh sách có phần tử, còn ở đây không có tên nào để hiển thị. Lựa chọn "It will throw a NullPointerException because userList is empty." sai ở hai mức: danh sách rỗng khác với null, và ngay cả khi biến không tồn tại thì biểu thức trả về null còn forEach coi null là tập rỗng nên cũng không ném ngoại lệ. Lựa chọn "The page will crash due to an iteration error." sai vì lặp không phần tử là trạng thái hợp lệ của forEach, trang vẫn dịch được và chạy trọn tới cuối.
Mở trang câu hỏi này →
ASecure connections using HTTPS.
BCookies with enhanced security features (safe cookies).
CURL rewriting for session tracking.
DCookies with an extended expiration time (long cookies).
Lời giải
Đáp án đúng: "URL rewriting for session tracking.". Cách này nhét định danh phiên vào chính địa chỉ, dạng tham số jsessionid nối sau đường dẫn, nên định danh hiện trên thanh địa chỉ, nằm lại trong lịch sử của máy công cộng và bị gửi sang trang khác qua tiêu đề Referer; ai mở lại liên kết đó khi phiên chưa hết hạn là vào thẳng được tài khoản. "Secure connections using HTTPS." không phải cách theo dấu phiên mà là lớp bảo vệ đường truyền, nó chỉ làm tình hình an toàn hơn. "Cookies with enhanced security features (safe cookies)." nói tới cookie bật cờ Secure cùng HttpOnly, cũng là hướng tăng an toàn. "Cookies with an extended expiration time (long cookies)." có rủi ro riêng vì sống qua lần đóng trình duyệt, nhưng đó là cookie bền để ghi nhớ đăng nhập chứ không phải cơ chế theo dấu phiên, và dấu vết nó để lại nằm trong bộ cookie xoá được, không phơi định danh ra ngoài địa chỉ.
Mở trang câu hỏi này →
AJavaFX
BJSP (JavaServer Pages)
CJDBC (Java Database Connectivity)
DJPA (Java Persistence API)
Lời giải
Đáp án đúng: "JSP (JavaServer Pages)". Trang JSP có cặp thẻ hành động jsp:useBean cùng jsp:setProperty; khi thuộc tính property nhận ký hiệu khớp mọi tham số, container tự dò từng tham số của yêu cầu, tìm phương thức đặt giá trị trùng tên trong bean rồi gán sau khi chuyển kiểu, nhờ vậy không phải viết tay từng dòng đọc tham số. Đó chính là cơ chế nạp bean từ tham số mà câu hỏi nói tới. "JavaFX" là bộ công cụ dựng giao diện cho ứng dụng máy tính để bàn, không tham gia xử lý yêu cầu HTTP. "JDBC (Java Database Connectivity)" chỉ lo nối và truy vấn cơ sở dữ liệu, nó nhận vào dữ liệu đã được lấy sẵn chứ không tự đọc tham số của yêu cầu. "JPA (Java Persistence API)" ánh xạ đối tượng sang bảng để lưu trữ, cũng đứng ở tầng dữ liệu và không biết gì về tham số của tầng web.
Mở trang câu hỏi này →
ATo modify the header content before sending it to the client
BTo intercept and manipulate requests and responses
CTo authenticate users before accessing public resources
DTo handle database operations
Lời giải
Đáp án đúng: "To intercept and manipulate requests and responses". Filter đứng giữa container và tài nguyên đích: trong phương thức xử lý, nó xem và sửa được lượt gọi trước khi chuyển đi tiếp theo chuỗi, xem và sửa được phản hồi trên đường về, hoặc chặn hẳn không cho đi tiếp. Nhờ chỗ đứng đó, cùng một filter dùng cho nhiều đường dẫn để làm những việc cắt ngang như đặt bộ ký tự, nén, ghi nhật ký, kiểm tra đăng nhập. Lựa chọn "To modify the header content before sending it to the client" chỉ kể một trường hợp dùng cụ thể, hẹp hơn nhiều so với khả năng của filter. Lựa chọn "To authenticate users before accessing public resources" lệch ở chữ công khai, vì tài nguyên công khai thì không cần xác thực, filter kiểu bảo vệ được ghép trước các đường dẫn hạn chế. Lựa chọn "To handle database operations" đặt sai tầng: truy cập dữ liệu là việc của lớp nghiệp vụ và lớp truy xuất.
Mở trang câu hỏi này →
AIt listens to and records conversations
BIt watches for changes in user sessions, like when someone logs in or out
CIt changes session data
DIt helps users navigate through the application
Lời giải
Đáp án đúng: "It watches for changes in user sessions, like when someone logs in or out". Listener của phiên là một lớp được container thông báo mỗi khi vòng đời phiên chuyển trạng thái: đăng nhập thường kéo theo việc tạo phiên mới và ghi thuộc tính người dùng, còn đăng xuất gọi invalidate, và chính container phát sự kiện tương ứng cho lớp đã khai báo, nên nó quan sát được các mốc đó mà không cần servlet nào gọi tay. "It listens to and records conversations" sai vì phiên ở đây là phiên làm việc HTTP giữa trình duyệt và server, không phải cuộc hội thoại nào để ghi âm. "It changes session data" sai vì listener chỉ được thông báo chứ không phải công cụ để sửa dữ liệu; việc ghi thuộc tính vẫn do servlet thực hiện. "It helps users navigate through the application" sai vì điều hướng do tầng điều khiển quyết định qua forward hoặc sendRedirect, listener không can thiệp vào luồng đi của yêu cầu.
Mở trang câu hỏi này →
AServlet and URL mapping
BInitialization parameters
CDatabase table schema
DFilter configuration
Lời giải
Đáp án đúng: "Database table schema". Deployment descriptor là nơi khai những gì container cần biết để chạy ứng dụng web, còn cấu trúc bảng của cơ sở dữ liệu thuộc về chính cơ sở dữ liệu và được tạo bằng câu lệnh DDL hoặc công cụ migration; container không đọc và cũng không hiểu định nghĩa bảng. "Servlet and URL mapping" là nội dung điển hình của tệp này, cặp khai servlet và mẫu đường dẫn chính là cách container định tuyến yêu cầu. "Initialization parameters" cũng được khai ở đây, dưới dạng tham số riêng của một servlet hoặc tham số chung của toàn ứng dụng, rồi đọc lại bằng getInitParameter(). "Filter configuration" cũng thuộc tệp này: khai lớp filter và mẫu đường dẫn mà nó chặn, thứ tự khai còn quyết định thứ tự các filter nối thành chuỗi.
Mở trang câu hỏi này →
AAt the end of the filter's lifecycle
BBefore each doFilter() method call
CAfter the web application is undeployed
DImmediately after the filter's first invocation
Lời giải
Đáp án đúng: "At the end of the filter's lifecycle". Container gọi init đúng một lần khi đưa đối tượng filter vào hoạt động, gọi doFilter cho từng yêu cầu khớp mẫu, rồi gọi destroy đúng một lần ở cuối đời đối tượng đó, sau khi mọi lời gọi doFilter đang dở đã kết thúc, để filter trả lại những tài nguyên nó giữ như kết nối hay tệp log. "Before each doFilter() method call" sai vì không có móc nào chạy trước từng lần lọc; chính phần đầu của doFilter đóng vai đó. "After the web application is undeployed" sai vì thứ tự ngược lại: container phải gọi destroy trong lúc còn đang dỡ ứng dụng, tức trước khi ứng dụng rời khỏi bộ nhớ, chứ không thể gọi vào một đối tượng đã bị bỏ. "Immediately after the filter's first invocation" sai vì chỉ có một đối tượng filter dùng lại cho mọi yêu cầu, hết lần lọc đầu tiên nó vẫn phải sống để phục vụ tiếp.
Mở trang câu hỏi này →
Ainit(), service(), destroy()
Binitialize(), service(), destroy()
Cinit(), execute(), destroy()
Dinit(), service(), delete()
Lời giải
Đáp án đúng: "init(), service(), destroy()". Container nạp lớp servlet, tạo một thực thể, gọi init() đúng một lần để chuẩn bị, sau đó với mỗi lượt gọi lại gọi service() trên cùng thực thể đó, và khi tháo ứng dụng thì gọi destroy() một lần rồi bỏ thực thể. Ba tên này là hợp đồng trong giao diện Servlet nên container chỉ biết gọi đúng chúng. Lựa chọn "initialize(), service(), destroy()" sai tên mốc đầu: đặt tên như vậy thì phần chuẩn bị của bạn không bao giờ chạy, vì container vẫn gọi init của lớp cha. Lựa chọn "init(), execute(), destroy()" sai mốc phục vụ; execute là tên quen ở các khung hành động, còn ở servlet thì service mới là nơi phân nhánh theo phương thức HTTP sang doGet hay doPost. Lựa chọn "init(), service(), delete()" sai mốc kết thúc, khiến phần giải phóng tài nguyên không được gọi khi ứng dụng dừng.
Mở trang câu hỏi này →
A<c:forEach var="row" items="${dataList}"><c:if test="${row.status eq 'active'}">${row.name}</c:if></c:forEach>
B<c:forEach var="row" items="${dataList}"><c:if test="${row.status.equals("active")}">${row.name}</c:if></c:forEach>
C<c:forEach var="row" items="${dataList}"><c:when test="${row.status == 'active'}">${row.name}</c:when></c:forEach>
D<c:forEach var="dataList" items="${row}"><c:if test="${row.status == 'active'}">${row.name}</c:if></c:forEach>
Lời giải

Đáp án đúng: "<c:forEach

Lời giải
var="row" items="${dataList}"><c:if test="${row.status eq 'active'}">${
  row.name
}

</c:if></c:forEach>". Thuộc tính items nhận tập nguồn còn var đặt tên cho biến phần tử, nên items phải trỏ tới danh sách trong phạm vi request và var là biến từng dòng; trong thân vòng lặp mỗi phần tử là một Map nên biểu thức row.status được EL dịch thành phép tra khoá. Toán tử eq so sánh giá trị chuỗi và chịu được giá trị rỗng, còn thẻ điều kiện c:if đứng một mình hợp lệ. Lựa chọn chứa "<c:

Lời giải
if test="${row.status.equals("active")}">"

vỡ ngay ở pha dịch vì dấu nháy kép lồng vào một giá trị thuộc tính đã mở bằng nháy kép, bộ phân tích đóng thuộc tính sớm. Lựa chọn chứa "<c:when test="${row.status == 'active'}">" đặt thẻ sai chỗ: c:when chỉ hợp lệ khi nằm trực tiếp trong c:choose, đứng lẻ trong vòng lặp sẽ lỗi. Lựa chọn chứa "<c:forEach

Lời giải
var="dataList" items="${row}">"

đảo vai hai thuộc tính, thành ra lặp trên một biến chưa tồn tại và đặt tên biến phần tử trùng tên danh sách, nên không duyệt được gì.

Mở trang câu hỏi này →
A/src/main/java
B/WEB-INF/classes
C/META-INF
D/WEB-INF
Lời giải
Đáp án đúng: "/WEB-INF". Bộ mô tả triển khai phải nằm ngay trong thư mục này, cạnh hai thư mục classes và lib, vì đó đúng là chỗ container tìm đọc khi triển khai ứng dụng; thư mục này còn được bảo vệ đặc biệt, client không thể gõ địa chỉ để tải trực tiếp bất cứ tệp nào bên trong, nhờ vậy cấu hình và lớp đã biên dịch không bị lộ. "/src/main/java" là thư mục mã nguồn theo quy ước của công cụ xây dựng; nội dung trong đó được biên dịch rồi mới đóng gói, không phải vị trí tệp cấu hình lúc chạy. "/WEB-INF/classes" chỉ chứa các lớp đã biên dịch cùng tệp tài nguyên đi kèm của ứng dụng. "/META-INF" là nơi đặt tệp kê khai của gói và tệp context.xml khai tài nguyên cho Tomcat, không phải nơi container tìm bộ mô tả triển khai.
Mở trang câu hỏi này →
A${myList[0]}
B${myList.getFirst()}
C${myList.first}
D${myList.getFirst}
Lời giải

Đáp án đúng: "${myList[0]}". Cách duy nhất EL định nghĩa để lấy phần tử theo vị trí là toán tử ngoặc vuông kèm chỉ số, nên biểu thức này trả về phần tử đầu của danh sách; EL còn tự ép chuỗi số viết trong ngoặc về số nguyên khi tập là danh sách hay mảng. "${

Lời giải
myList.getFirst()
}
"

dựa vào việc gọi một phương thức mang tên đó trên danh sách, trong khi thứ cần ở đây là chỉ số, và danh sách dùng trong JSP không được lấy phần tử đầu theo kiểu gọi phương thức như vậy. "${myList.first}" dùng dấu chấm nên EL hiểu là đọc một thuộc tính tên first theo quy ước bean, tức đi tìm phương thức đọc tương ứng; danh sách không có thuộc tính như thế nên biểu thức báo không tìm thấy thuộc tính. "${myList.getFirst}" còn xa hơn: viết sau dấu chấm nên nó bị hiểu là tên một thuộc tính bắt đầu bằng get, EL sẽ tìm phương thức đọc của chính thuộc tính ấy và cũng không có.

Mở trang câu hỏi này →
AServletContextAttributeListener
BServletRequestListener
CHttpSessionListener
DServletContextListener
Lời giải
Đáp án đúng: "ServletContextListener". Nạp JDBC driver là việc chỉ cần làm một lần cho cả ứng dụng và phải xong trước khi có request đầu tiên, nên đúng chỗ là contextInitialized của giao diện này: container gọi phương thức đó ngay sau khi ngữ cảnh ứng dụng được tạo và trước khi bất kỳ servlet nào phục vụ, còn contextDestroyed là nơi dọn dẹp khi ứng dụng dừng. Lựa chọn "ServletContextAttributeListener" chỉ được gọi khi có thuộc tính của ngữ cảnh ứng dụng bị thêm, thay hoặc xoá; nếu không ai đặt thuộc tính thì nó không chạy lần nào. Lựa chọn "ServletRequestListener" chạy theo từng request, nên driver bị nạp lặp lại vô ích và vẫn muộn hơn thời điểm khởi động ứng dụng. Lựa chọn "HttpSessionListener" gắn với vòng đời phiên người dùng, mà ứng dụng có thể phục vụ nhiều request không tạo phiên nào, khi đó driver có thể không bao giờ được nạp.
Mở trang câu hỏi này →
APlace all user-generated content in a single tier to simplify security protocols.
BDistribute user-generated content across multiple tiers, applying appropriate security measures at each level.
CCentralize all business logic in the presentation tier to control access to user-generated content.
DUtilize a flat architecture to avoid the complexity of multi-tier security.
Lời giải
Đáp án đúng: "Distribute user-generated content across multiple tiers, applying appropriate security measures at each level.". Nguyên tắc nhiều tầng là mỗi tầng tự coi dữ liệu đến từ tầng ngoài là chưa đáng tin và tự đặt chốt kiểm riêng: tầng hiển thị lọc rồi thoát ký tự để nội dung do người dùng gửi không chạy được như mã, tầng nghiệp vụ kiểm quyền và kiểm quy tắc trước khi chấp nhận thao tác, tầng dữ liệu dùng câu lệnh tham số hoá cùng tài khoản kết nối chỉ đủ quyền tối thiểu; nhờ nhiều lớp mà một chốt bị lọt thì vẫn còn chốt sau. "Place all user-generated content in a single tier to simplify security protocols." sai vì gom hết vào một tầng tạo ra đúng một điểm vỡ, lọt một lần là mất tất cả. "Centralize all business logic in the presentation tier to control access to user-generated content." sai vì đưa nghiệp vụ lên tầng hiển thị khiến mọi kiểm soát nằm ở chỗ gần người dùng nhất và có thể bị bỏ qua khi ai đó gọi thẳng tầng dưới. "Utilize a flat architecture to avoid the complexity of multi-tier security." sai vì kiến trúc phẳng xoá luôn các ranh giới tin cậy, tức bỏ đi chính thứ tạo nên chiều sâu phòng thủ.
Mở trang câu hỏi này →
AIt is automatically rolled back
BIt continues with the next statement
CIt is committed regardless of the error
DIt waits for user intervention
Lời giải
Đáp án đúng: "It is automatically rolled back". Giao dịch mang tính nguyên tử: gặp lỗi thì mọi thay đổi chưa commit bị trả về trạng thái trước đó, dù do mã bắt ngoại lệ rồi gọi rollback, hay do kết nối bị đóng và hết thời gian chờ khiến giao dịch đang mở bị huỷ. Vì vậy một chuỗi lệnh ghi trong web phải đặt setAutoCommit(false), commit ở cuối và rollback trong khối catch. Lựa chọn "It continues with the next statement" mô tả cảnh mỗi lệnh tự commit riêng, lúc đó không còn giao dịch chung để nói tới. Lựa chọn "It is committed regardless of the error" phá tính nguyên tử: lưu lại phần đã làm sẽ để dữ liệu nửa vời, ví dụ trừ tiền mà chưa cộng. Lựa chọn "It waits for user intervention" không có trong cơ chế này: không ai giữ giao dịch treo chờ người dùng quyết định, giữ lâu chỉ khoá dữ liệu rồi cuối cùng vẫn bị huỷ.
Mở trang câu hỏi này →
Aweb.xml
Bserver.xml
Ccontext.xml
Dapplication.properties
Lời giải
Đáp án đúng: "web.xml". Đây là mô tả triển khai của một ứng dụng web, nằm trong thư mục WEB-INF và do container đọc lúc dựng ngữ cảnh; trong đó khai thẻ servlet cùng servlet-mapping, filter cùng filter-mapping, listener, context-param, session-config, welcome-file-list, nên nó đúng là nơi cấu hình ứng dụng cùng servlet và filter. "server.xml" là cấu hình của chính máy chủ Tomcat, gồm cổng, bộ nhận kết nối, host và engine, áp cho mọi ứng dụng đang chạy trên đó chứ không thuộc một gói ứng dụng nào. "context.xml" cũng ở mức máy chủ hoặc mức ngữ cảnh triển khai, hay dùng để khai nguồn dữ liệu và thuộc tính của ngữ cảnh, nhưng không phải chỗ khai servlet hay filter. "application.properties" là quy ước cấu hình của Spring Boot, không nằm trong đặc tả servlet nên container không đọc nó để tìm khai báo servlet.
Mở trang câu hỏi này →
AThe container may not detect the change if you don't re-set the attribute.
BYou must always remove the session attribute before updating its contents.
CSession attributes must be immutable.
DUpdates are always automatically replicated.
Lời giải
Đáp án đúng: "The container may not detect the change if you don't re-set the attribute.". Khi lưu một đối tượng khả biến vào phiên rồi sửa trực tiếp trường bên trong nó, container không nhận được tín hiệu nào: nó chỉ biết có thay đổi tại lời gọi setAttribute, và chính lời gọi đó mới kích hoạt bộ lắng nghe thuộc tính cùng cơ chế nhân bản phiên giữa các node trong cụm. Vì thế quy ước an toàn là sửa xong thì đặt lại thuộc tính với cùng khoá. Lựa chọn "You must always remove the session attribute before updating its contents." dựng ra một bước bắt buộc không có thật: gọi setAttribute đè lên là đủ, xoá rồi thêm lại chỉ thêm khoảng trống dễ sinh lỗi. Lựa chọn "Session attributes must be immutable." quá mạnh: yêu cầu thực tế chỉ là đối tượng khả tuần tự hoá khi phiên cần ghi ra ngoài, chứ không cấm đối tượng khả biến. Lựa chọn "Updates are always automatically replicated." nói ngược chính cái bẫy, vì việc nhân bản không tự xảy ra sau một thay đổi tại chỗ.
Mở trang câu hỏi này →
AIncrease the server's hardware capacity to handle more concurrent requests.
BImplement caching mechanisms within the View to store rendered pages.
COptimize database queries within the Model to reduce data retrieval times.
DMinimize the use of MVC architecture and revert to a monolithic design for performance.
Lời giải
Đáp án đúng: "Optimize database queries within the Model to reduce data retrieval times.". Đề yêu cầu cách tối ưu tôn trọng phân vai của MVC, mà trong ứng dụng JSP thì phần chậm thường nằm ở tầng Model: mỗi lần dựng trang đều phải chờ truy vấn trả về. Sửa đúng chỗ đó, bằng cách thêm chỉ mục, bỏ truy vấn lặp trong vòng lặp, chỉ lấy cột cần dùng hay tái dùng kết nối, vừa giảm thời gian chờ vừa không làm nhoè ranh giới giữa các tầng. "Increase the server's hardware capacity to handle more concurrent requests." không phải chiến lược theo nguyên lý MVC mà là mua thêm tài nguyên, nó che bớt triệu chứng rồi tái diễn khi lượng truy cập tăng. "Implement caching mechanisms within the View to store rendered pages." đặt bộ đệm vào tầng chỉ nên lo kết xuất; cache trang đã dựng còn dễ trả nội dung cũ, thậm chí trả dữ liệu của người khác, và khó làm mới khi dữ liệu đổi. "Minimize the use of MVC architecture and revert to a monolithic design for performance." bỏ hẳn ràng buộc mà đề đặt ra, và gộp mã vào trang cũng không làm truy vấn chạy nhanh hơn.
Mở trang câu hỏi này →