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 thi lại số 3

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
APOST
BGET
CDELETE
DPATCH
Lời giải
Đáp án đúng: "POST". Theo đặc tả HTTP, đây là phương thức mang dữ liệu trong thân yêu cầu để máy chủ tạo ra một tài nguyên mới, và nó không idempotent: gửi hai lần thì sinh hai bản ghi, nên biểu mẫu đăng ký hay thêm bản ghi đều khai method này và servlet xử lý trong doPost. "GET" là phương thức an toàn và idempotent, chỉ để đọc: tham số nằm lộ trên URL, bị lưu vào lịch sử trình duyệt và bị cache, lại giới hạn độ dài, nên không dùng để tạo dữ liệu. "DELETE" dùng để xoá tài nguyên đang tồn tại ở địa chỉ được trỏ tới, tức ngược hẳn với việc tạo. "PATCH" dùng để sửa một phần tài nguyên đã có, nên tiền đề của nó là tài nguyên tồn tại sẵn rồi, không phải tạo mới.
Mở trang câu hỏi này →
2What is the correct way to forward a request4 lựa chọncó code
Đề bài
using RequestDispatcher? RequestDispatcher rd = request.getRequestDispatcher("dashboard.jsp");
Ard.forward(response, request);
Brd.include(request, response);
Crd.forward(request, response);
Dresponse.sendRedirect("dashboard.jsp");
Lời giải

Đáp án đúng: "rd.forward(request, response); ". Phương thức forward nhận đúng thứ tự tham số là request rồi mới tới phần trả về, và nó chuyển hẳn quyền xử lý sang tài nguyên đích ngay trong cùng một lượt request, nên mọi thuộc tính đã đặt vào request vẫn dùng được ở trang đích và thanh địa chỉ của trình duyệt không đổi. Lựa chọn "rd.forward(response, request); " đảo thứ tự hai tham số nên không khớp chữ ký phương thức và mã không biên dịch được. Lựa chọn "rd.include(request, response); " là lời gọi hợp lệ nhưng khác nghĩa: nó chèn kết quả của tài nguyên kia vào chỗ đang xử lý rồi trả điều khiển về servlet gọi, không phải chuyển tiếp. Lựa chọn "response.sendRedirect("dashboard.jsp"); " không dùng tới bộ điều phối request: nó trả mã chuyển hướng cho trình duyệt, sinh một request mới, URL đổi và dữ liệu trong phạm vi request cũ mất.

Mở trang câu hỏi này →
AIt is faster than RequestDispatcher.forward()
BIt keeps the original request and response objects
CIt changes the URL in the browser
DIt does not involve client-side communication
Lời giải
Đáp án đúng: "It changes the URL in the browser". Phương thức này trả cho trình duyệt một phản hồi chuyển hướng mang mã 302 cùng header Location, rồi chính trình duyệt phát yêu cầu thứ hai tới địa chỉ mới, vì vậy thanh địa chỉ đổi theo và đích đến thậm chí có thể nằm ở ứng dụng hay máy chủ khác. "It is faster than RequestDispatcher.forward()" sai vì nó thêm hẳn một vòng đi về qua mạng, trong khi forward được xử lý nội bộ ngay trong máy chủ nên nhanh hơn. "It keeps the original request and response objects" sai vì yêu cầu thứ hai đi kèm một cặp request và response hoàn toàn mới: mọi thứ đặt bằng setAttribute trước đó biến mất, chỉ còn dữ liệu nào được gắn trên URL hoặc lưu trong phiên. "It does not involve client-side communication" sai vì cơ chế này dựa hoàn toàn vào việc trình duyệt tự đi lại; thứ không cần phía client tham gia mới chính là forward của RequestDispatcher.
Mở trang câu hỏi này →
ATo define the structure of a webpage
BTo style web content
CTo collect user input
DTo display images
Lời giải
Đáp án đúng: "To collect user input". Thẻ form gom các ô nhập rồi gửi lên server theo phương thức và đường dẫn đã khai: trình duyệt đóng gói dữ liệu thành các cặp tên và giá trị, còn phía servlet đọc lại đúng bằng tên ô qua phương thức lấy tham số của request, nên form chính là cầu đưa dữ liệu từ người dùng vào mã Java. Lựa chọn "To define the structure of a webpage" là việc của HTML nói chung với các thẻ bố cục; form chỉ là một phần nhỏ nằm trong bố cục đó. Lựa chọn "To style web content" là việc của CSS, form không quy định màu sắc, phông chữ hay khoảng cách. Lựa chọn "To display images" là việc của thẻ ảnh; form có thể chứa ô chọn tệp để tải ảnh lên nhưng bản thân nó không hiển thị ảnh nào.
Mở trang câu hỏi này →
AMoves to first row
BReturns null
CThrows exception
DCloses the connection
Lời giải
Đáp án đúng: "Moves to first row". Ngay sau khi truy vấn trả về, con trỏ của tập kết quả nằm trước dòng đầu tiên, nên lần gọi next đầu tiên đẩy con trỏ xuống dòng đầu và trả về true nếu có dữ liệu, false nếu kết quả rỗng; đó là lý do mã đọc dữ liệu luôn mở bằng một lần gọi next hoặc một vòng lặp lấy next làm điều kiện. Lựa chọn "Returns null" sai kiểu: next trả về giá trị luận lý chứ không trả về đối tượng, còn giá trị từng cột mới lấy bằng các phương thức đọc theo tên hoặc số thứ tự cột. Lựa chọn "Throws exception" chỉ xảy ra khi tập kết quả hay câu lệnh đã bị đóng, không phải hành vi thường của lần gọi đầu. Lựa chọn "Closes the connection" nhầm hẳn vai: đóng kết nối là việc của lời gọi đóng, và chính vì next không đóng gì nên ta phải tự giải phóng tài nguyên sau khi đọc xong.
Mở trang câu hỏi này →
Adestroy()
Bstop()
Cend()
Ddispose()
Lời giải
Đáp án đúng: "destroy()". Vòng đời servlet do container điều khiển gồm ba mốc: init() một lần khi nạp, service() cho mỗi request, và destroy() một lần duy nhất trước khi thực thể bị loại khỏi dịch vụ, thường lúc ứng dụng bị tháo hoặc server tắt. Container gọi destroy() sau khi các luồng đang chạy trong service() kết thúc, nên đây là chỗ để đóng kết nối cơ sở dữ liệu, dừng luồng nền, ghi nhật ký kết thúc. Lựa chọn "stop()" không thuộc giao diện Servlet; tên này quen từ applet và từ việc dừng luồng, container không bao giờ gọi nó. Lựa chọn "end()" cũng không có trong hợp đồng vòng đời, viết một phương thức tên như vậy thì nó chỉ là phương thức thường và không được gọi tự động. Lựa chọn "dispose()" là quy ước giải phóng tài nguyên của các thư viện giao diện đồ hoạ, không nằm trong API servlet.
Mở trang câu hỏi này →
Aapplication.xml
Bweb.xml
Cconfig.xml
Dserver.xml
Lời giải
Đáp án đúng: "web.xml". Mô tả triển khai của một ứng dụng web được quy định mang tên web.xml và nằm trong thư mục WEB-INF; container đọc tệp này khi nạp ứng dụng để biết các servlet, filter, listener, trang lỗi và thời gian chờ phiên. Lựa chọn "application.xml" là mô tả triển khai ở mức gói ứng dụng doanh nghiệp gồm nhiều module, không phải tệp cấu hình của một ứng dụng web đơn lẻ. Lựa chọn "config.xml" không phải tên tệp nào được quy định, nên container không tìm đến nó và nội dung trong đó không có tác dụng. Lựa chọn "server.xml" là tệp cấu hình riêng của máy chủ ở mức toàn server, chứa khai báo cổng và vùng chứa ứng dụng, nên sửa nó là sửa cho mọi ứng dụng đang chạy chứ không phải sửa mô tả triển khai của một ứng dụng.
Mở trang câu hỏi này →
Amanifest.txt
Bsettings.xml
Cweb.xml
Dconfig.properties
Lời giải
Đáp án đúng: "web.xml". Tệp này nằm trong WEB-INF và là chỗ container tìm đến để lấy thông tin cấu hình cùng thông tin triển khai của ứng dụng: khai báo servlet và mẫu URL tương ứng, filter cùng thứ tự ánh xạ, listener, tham số ngữ cảnh, trang chào và thời gian chờ phiên. Lựa chọn "manifest.txt" không phải tệp cấu hình của ứng dụng web; siêu dữ liệu của một gói thư viện nằm trong tệp khác và cũng không khai báo servlet. Lựa chọn "settings.xml" là cấu hình của công cụ xây dựng trên máy lập trình viên, container không đọc nó lúc chạy. Lựa chọn "config.properties" chỉ là tệp tham số dạng khoá và giá trị do chính mã ứng dụng tự đọc, container không hiểu nó là mô tả triển khai nên không nạp servlet nào từ đó.
Mở trang câu hỏi này →
Đề bài
public class ShowParamsServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        ServletContext ctx = getServletContext();
        PrintWriter out = response.getWriter();
        Enumeration<String> paramNames = ctx.getInitParameterNames();
        while(paramNames.hasMoreElements()) {
            String name = paramNames.nextElement();
            out.println(name + ": " + ctx.getInitParameter(name));
        }
    }
}

If web.xml has the following entries:

Đề bài
<context-param>
    <param-name>settingOne</param-name>
    <param-value>foo</param-value>
</context-param>
<context-param>
    <param-name>settingTwo</param-name>
    <param-value>bar</param-value>

</context-param> What will the servlet output?

Afoo bar
BsettingOne: foo settingTwo: bar
CsettingTwo: bar settingOne: foo
DsettingOne settingTwo
Lời giải

Đáp án đúng: "settingOne: foo settingTwo: bar". Vòng lặp đi qua Enumeration do ctx.getInitParameterNames() trả về, và mỗi lần lặp out.println() in ra chuỗi được nối từ name, dấu hai chấm kèm khoảng trắng, rồi ctx.getInitParameter(name); vì vậy mỗi dòng mang cả tên tham số lẫn giá trị của nó, lần lượt theo thứ tự hai phần tử context-param được khai trong web.xml. Lưu ý getInitParameter() ở đây gọi trên ServletContext nên đọc tham số dùng chung cho toàn ứng dụng, khác với tham số riêng của từng servlet. Lựa chọn "foo bar" bỏ mất phần name và dấu hai chấm mà biểu thức nối chuỗi luôn in kèm. Lựa chọn "settingTwo: bar settingOne: foo" đảo thứ tự so với thứ tự khai trong tệp cấu hình mà vòng lặp đi theo. Lựa chọn "settingOne settingTwo" chỉ in tên, tức là kết quả của việc in name mà không gọi getInitParameter().

Mở trang câu hỏi này →
AOnly during the initialization phase.
BOnly during the destruction phase.
CWhenever a client sends a request to the servlet.
DAfter the init() method and before the destroy() method.
Lời giải
Đáp án đúng: "Whenever a client sends a request to the servlet.". Vòng đời servlet có ba mốc: container nạp lớp rồi gọi init một lần, gọi service cho từng request đến, và gọi destroy một lần trước khi tháo servlet. Chính service là điểm vào của mỗi lượt phục vụ, nó đọc phương thức HTTP của request rồi điều tới doGet, doPost hay phương thức tương ứng. Lựa chọn "Only during the initialization phase." nhầm service với init, mà init chạy một lần và không nhận request nào. Lựa chọn "Only during the destruction phase." nhầm sang destroy, thời điểm servlet đã ngừng phục vụ. Lựa chọn "After the init() method and before the destroy() method." nêu đúng khoảng thời gian mà service có thể được gọi, nhưng đó là điều kiện khung chứ không trả lời điều câu hỏi cần biết là cái gì kích hoạt lời gọi; trong khoảng ấy service chỉ chạy khi thực sự có request tới.
Mở trang câu hỏi này →
Đề bài
public class HelloServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html");
        response.getWriter().println("<h1>Hello from @WebServlet!</h1>");
    }
}
AIt configures cookies and sessions
BIt replaces the XML servlet declaration in web.xml
CIt disables servlet loading at startup
DIt defines the servlet’s security policy
Lời giải
Đáp án đúng: "It replaces the XML servlet declaration in web.xml". Annotation này mang đúng những thông tin mà trước đây phải viết thành khối khai báo servlet cộng khối ánh xạ servlet trong mô tả triển khai: thuộc tính name đặt tên servlet, thuộc tính mẫu URL nêu đường dẫn mà container sẽ gọi tới lớp này, nhờ vậy lớp trong ví dụ phục vụ được đường dẫn của nó mà không cần thêm dòng nào vào tệp cấu hình. Lựa chọn "It configures cookies and sessions" không thuộc phần việc của annotation này; cookie và phiên được tạo cùng đọc trong mã, còn thời gian chờ phiên khai ở mô tả triển khai. Lựa chọn "It disables servlet loading at startup" hiểu sai: việc nạp sớm do một thuộc tính riêng quyết định, ở ví dụ này thuộc tính đó không xuất hiện, và mặc định là nạp khi có request đầu tiên chứ không phải bị tắt. Lựa chọn "It defines the servlet’s security policy" là việc của annotation bảo mật riêng hoặc của khối ràng buộc bảo mật.
Mở trang câu hỏi này →
ATo store data that can be shared across multiple servlets within the same request.
BTo store data that can be shared only within the same servlet.
CTo store data that can be shared across multiple servlets in the same session.
DTo store data that can be accessed by any servlet in the application.
Lời giải
Đáp án đúng: "To store data that can be shared across multiple servlets within the same request.". Attribute của request là ô chứa dữ liệu gắn với đúng một đối tượng HttpServletRequest: servlet đặt dữ liệu bằng setAttribute() rồi forward sang servlet hay trang JSP khác, nơi đó đọc lại bằng getAttribute() vì vẫn là cùng một yêu cầu; hết yêu cầu thì đối tượng bị bỏ và dữ liệu mất, nhờ vậy không có chuyện dữ liệu của người này lẫn sang người khác. "To store data that can be shared only within the same servlet." bó hẹp quá mức, nếu chỉ dùng trong một servlet thì biến cục bộ đã đủ và không cần tới attribute. "To store data that can be shared across multiple servlets in the same session." là mô tả phạm vi phiên, dữ liệu ở đó sống qua nhiều yêu cầu của cùng người dùng. "To store data that can be accessed by any servlet in the application." là mô tả phạm vi ứng dụng, dữ liệu ở đó dùng chung cho mọi người dùng.
Mở trang câu hỏi này →
Đề bài
<servlet-mapping>
  <servlet-name>ServletA</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>ServletB</servlet-name>
  <url-pattern>/bservlet.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>ServletC</servlet-name>
  <url-pattern>*.servletC</url-pattern>
</servlet-mapping>
<servlet-mapping>
  <servlet-name>ServletD</servlet-name>
  <url-pattern>/dservlet/*</url-pattern>
</servlet-mapping>

Given that a user enters the following into thier browser, which (if any) of the mapped servlets will execute? (Choose one.) http://mywebserver:8081/mywebapp

AServletA
BServletB
CServletC
DServletD
Lời giải
Đáp án đúng: "ServletA". Địa chỉ người dùng gõ chỉ tới đúng gốc ứng dụng mywebapp, nên phần đường dẫn bên trong ứng dụng là rỗng và được container quy về gốc. Khi so khớp, container thử lần lượt theo thứ tự: khớp chính xác, rồi khớp theo tiền tố, rồi khớp theo đuôi mở rộng, cuối cùng mới tới servlet mặc định được khai bằng một dấu gạch chéo đơn; ở đây không khai báo nào khớp chính xác nên servlet mặc định nhận yêu cầu. "ServletB" chỉ chạy khi đường dẫn đúng bằng chuỗi bservlet.html, trong khi yêu cầu này không hề có phần đó. "ServletC" chỉ chạy khi đường dẫn kết thúc bằng đuôi servletC, nhưng đường dẫn ở đây rỗng nên không có đuôi nào. "ServletD" chỉ nhận những đường dẫn bắt đầu bằng đoạn dservlet, cũng không khớp với một đường dẫn rỗng.
Mở trang câu hỏi này →
AYou can freely call getWriter() or getOutputStream() without issues.
BYou should avoid setting content type, flushing, or resetting the buffer directly in JSP.
CIt cannot be used to send headers because JSPs block response modification.
DIt is a Tomcat-specific object, not part of the JSP specification.
Lời giải
Đáp án đúng: "You should avoid setting content type, flushing, or resetting the buffer directly in JSP.". Trang JSP được dịch thành servlet ghi nội dung qua luồng xuất có bộ đệm riêng do container quản, còn kiểu nội dung thì nên khai bằng chỉ thị trang; tự đặt kiểu nội dung, tự đẩy đệm hay xoá đệm giữa trang sẽ đụng với cơ chế đó, chẳng hạn đã đẩy đệm đi rồi mới chuyển tiếp hay xoá đệm thì gặp lỗi trạng thái không hợp lệ. Lựa chọn "You can freely call getWriter() or getOutputStream() without issues." sai vì trang đang dùng luồng ghi ký tự của JSP, xin thêm luồng ghi nhị phân là xung đột và bị báo lỗi trạng thái. Lựa chọn "It cannot be used to send headers because JSPs block response modification." sai vì vẫn đặt được header hay thêm cookie, miễn là phần đầu của phản hồi chưa bị gửi đi. Lựa chọn "It is a Tomcat-specific object, not part of the JSP specification." sai vì đây là một trong các đối tượng ẩn chuẩn của JSP, có trên mọi container.
Mở trang câu hỏi này →
A<%@ page language="java" %>
B<%! private int count = 0; %>
C<%= "Hello World" %>
D<% int x = 10; %>
Lời giải

Đáp án đúng: "<%! private int count = 0; %>". Khối mở đầu bằng dấu chấm than là khai báo: nội dung của nó được đặt thành thành viên của lớp servlet sinh ra từ trang, nằm ngoài phương thức phục vụ, nên biến count tồn tại suốt đời thể hiện servlet và mọi lượt request dùng chung nó. Lựa chọn "<%@ page language="java" %>" là chỉ thị trang, nó cấu hình pha dịch trang chứ không khai báo thành viên nào. Lựa chọn "<%= "Hello World" %>" là biểu thức, giá trị của nó được tính rồi ghi thẳng ra luồng xuất, và đặt dấu chấm phẩy vào đó còn gây lỗi lúc dịch. Lựa chọn "<% int x = 10; %>" là scriptlet, mã bên trong rơi vào thân phương thức phục vụ nên biến ở đó chỉ là biến cục bộ, sinh lại ở mỗi request và không phải một khai báo.

Mở trang câu hỏi này →
ADirect SQL commands
BJavaScript code
CArbitrary Java code
DHTML tags only
Lời giải
Đáp án đúng: "Arbitrary Java code". Scriptlet là khối mã mà pha dịch trang chép thẳng vào thân phương thức phục vụ của servlet sinh ra từ trang JSP, nên bên trong viết được câu lệnh Java tuỳ ý, dùng luôn các đối tượng ẩn như request hay luồng xuất, và cũng chính vì vậy nó trộn logic vào trang hiển thị. Lựa chọn "Direct SQL commands" sai vì câu lệnh SQL không tự chạy trong trang: muốn truy vấn vẫn phải viết mã Java gọi JDBC, nên SQL chỉ là chuỗi truyền cho tầng khác. Lựa chọn "JavaScript code" nhầm bên thực thi, vì mã đó nằm trong phần HTML gửi về và chạy ở trình duyệt, không phải nội dung của scriptlet chạy trên server. Lựa chọn "HTML tags only" nhầm sang phần khuôn trang vốn nằm ngoài scriptlet; nếu scriptlet chỉ chứa thẻ HTML thì nó chẳng để làm gì.
Mở trang câu hỏi này →
Arequest
Bresponse
Csession
Dapplication
Lời giải
Đáp án đúng: "request". Đối tượng request đại diện cho lượt gọi của trình duyệt nên nó mang theo mọi thứ do trình duyệt gửi lên: các phương thức đọc header và danh sách tên header, phương thức lấy mảng cookie đi kèm, cùng tham số, phương thức HTTP và đường dẫn. Lựa chọn "response" đi chiều ngược lại, nó đặt header và thêm cookie để gửi về chứ không đọc được thứ trình duyệt gửi đến. Lựa chọn "session" chỉ giữ dữ liệu phía server gắn với một người dùng qua nhiều lượt gọi; nó dựa vào cookie định danh phiên nhưng không cho đọc header hay danh sách cookie. Lựa chọn "application" là phạm vi ngữ cảnh ứng dụng dùng để chia sẻ dữ liệu cho mọi người dùng, hoàn toàn không gắn với một lượt gọi HTTP cụ thể nào.
Mở trang câu hỏi này →
Aparams
Brequest
Cinput
DgetParameters
Lời giải
Đáp án đúng: "request". Tham số gửi tới trang, dù nằm trong query string của một liên kết hay trong body của form gửi theo POST, đều do container gom vào đối tượng yêu cầu; trong JSP đối tượng đó lộ ra dưới tên request và đọc bằng getParameter() cho một giá trị hoặc getParameterValues() cho nhiều giá trị cùng tên, mọi giá trị trả về đều là chuỗi nên muốn số thì phải tự chuyển kiểu. "params" không phải đối tượng ngầm định của JSP; trong Expression Language có một map tên gần giống để tra tham số, nhưng đó là biến của biểu thức chứ không phải đối tượng ngầm định như câu hỏi nói tới. "input" không tồn tại trong JSP, đây là tên thẻ nhập liệu bên HTML. "getParameters" là tên nghe như một phương thức chứ không phải một đối tượng, và cũng không có phương thức nào tên như vậy để lấy tham số.
Mở trang câu hỏi này →
ALoading the appropriate JDBC driver
BEstablishing a database connection
CWriting SQL queries to manipulate data
DParsing HTML forms
Lời giải
Đáp án đúng: "Parsing HTML forms". Đọc dữ liệu người dùng gửi lên là việc của tầng servlet qua phương thức lấy tham số của request, vì container đã phân tích phần thân và phần truy vấn giúp ta; chuỗi công việc của JDBC chỉ bắt đầu khi đã có dữ liệu và ta muốn nói chuyện với cơ sở dữ liệu. Lựa chọn "Loading the appropriate JDBC driver" là bước thật, nạp lớp driver để nó tự đăng ký vào bộ quản lý driver. Lựa chọn "Establishing a database connection" cũng là bước thật, mở kết nối từ chuỗi kết nối hoặc lấy từ nguồn dữ liệu dùng chung. Lựa chọn "Writing SQL queries to manipulate data" là bước thật kế tiếp, phát câu lệnh qua đối tượng câu lệnh rồi đọc tập kết quả, nên cả ba đều nằm trong luồng JDBC.
Mở trang câu hỏi này →
Astmt.getAffectedRows()
Bstmt.countRows()
Cstmt.getRowCount()
Dstmt.executeUpdate()
Lời giải
Đáp án đúng: "stmt.executeUpdate()". Với các câu lệnh làm thay đổi dữ liệu như INSERT, UPDATE hay DELETE, JDBC dùng executeUpdate() và chính nó trả về một số nguyên là số dòng bị ảnh hưởng, nên không cần hỏi thêm phương thức nào khác; executeQuery() thì dành cho SELECT và trả về ResultSet, còn execute() trả về boolean cho biết kết quả là bảng dữ liệu hay là số đếm. "stmt.getAffectedRows()" không tồn tại trong giao diện Statement, số dòng đã nằm ngay trong giá trị trả về của lệnh thực thi. "stmt.countRows()" cũng không có; muốn đếm dòng trong bảng thì phải tự viết một câu SELECT COUNT chứ không có phương thức sẵn. "stmt.getRowCount()" là tên nghe hợp lý nhưng không thuộc giao diện Statement; con số dòng đọc được của một ResultSet cũng phải tự đếm khi duyệt.
Mở trang câu hỏi này →