จากข้อกำหนด JSP 1.2 ขอแนะนำให้ใช้ไลบรารีแท็กมาตรฐาน JSP (JSTL) ในเว็บแอปพลิเคชันของคุณเพื่อช่วยลดความต้องการสคริปต์ JSPในหน้าเว็บของคุณ โดยทั่วไปหน้าเว็บที่ใช้ JSTL นั้นง่ายต่อการอ่านและบำรุงรักษา
...
หากเป็นไปได้หลีกเลี่ยงสคริปต์ JSPเมื่อใดก็ตามที่แท็กไลบรารี่มีฟังก์ชันการทำงานที่เทียบเท่า สิ่งนี้ทำให้การอ่านและบำรุงรักษาหน้าง่ายขึ้นช่วยในการแยกตรรกะทางธุรกิจออกจากตรรกะการนำเสนอและจะทำให้หน้าของคุณง่ายขึ้นในการพัฒนาไปสู่หน้าสไตล์ JSP 2.0 (รองรับข้อกำหนด JSP 2.0 แต่เน้นการใช้สคริปต์เล็ก)
...
ด้วยจิตวิญญาณของการใช้รูปแบบการออกแบบ model-view-controller (MVC) เพื่อลดการเชื่อมต่อระหว่างเทียร์การนำเสนอจากตรรกะทางธุรกิจสคริปต์ JSP ไม่ควรใช้สำหรับการเขียนตรรกะทางธุรกิจ แต่สคริปต์ JSP จะถูกใช้หากจำเป็นในการแปลงข้อมูล (หรือที่เรียกว่า "value object") ที่ส่งคืนจากการประมวลผลคำขอของลูกค้าในรูปแบบที่พร้อมสำหรับลูกค้า แม้ว่าจะทำได้ดีกว่าด้วยส่วนควบคุมด้านหน้าหรือแท็กที่กำหนดเอง
หากคุณต้องการเรียกใช้รหัส Java เดียวกันกับทุกคำขอให้น้อยลงหรือน้อยกว่าโดยไม่คำนึงถึงหน้าที่ร้องขอเช่นการตรวจสอบว่าผู้ใช้ลงชื่อเข้าใช้หรือไม่จากนั้นให้ใช้ตัวกรองและเขียนรหัสตามdoFilter()
วิธีการ เช่น:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
if (((HttpServletRequest) request).getSession().getAttribute("user") == null) {
((HttpServletResponse) response).sendRedirect("login"); // Not logged in, redirect to login page.
} else {
chain.doFilter(request, response); // Logged in, just continue request.
}
}
เมื่อทำการแมปบน<url-pattern>
หน้าปกที่เหมาะสมกับหน้าความสนใจของ JSP คุณไม่จำเป็นต้องคัดลอกชิ้นส่วนของหน้า JSP โดยรวมของรหัสเดียวกัน
หากคุณต้องการเรียกใช้โค้ด Java บางตัวเพื่อประมวลผลคำขอล่วงหน้าเช่นการโหลดล่วงหน้าบางรายการจากฐานข้อมูลเพื่อแสดงในบางตารางหากจำเป็นขึ้นอยู่กับพารามิเตอร์เคียวรีบางอย่างจากนั้นให้ใช้servletและเขียนโค้ดตามdoGet()
วิธีการ เช่น:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
List<Product> products = productService.list(); // Obtain all products.
request.setAttribute("products", products); // Store products in request scope.
request.getRequestDispatcher("/WEB-INF/products.jsp").forward(request, response); // Forward to JSP page to display them in a HTML table.
} catch (SQLException e) {
throw new ServletException("Retrieving products failed!", e);
}
}
วิธีนี้จัดการกับข้อยกเว้นง่ายกว่า DB ไม่สามารถเข้าถึงได้ในระหว่างการเรนเดอร์ JSP แต่ก่อนที่จะมีการแสดง JSP คุณยังคงมีความเป็นไปได้ที่จะเปลี่ยนการตอบสนองเมื่อใดก็ตามที่การเข้าถึงฐานข้อมูลเกิดข้อยกเว้น ในตัวอย่างข้างต้นเริ่มต้นข้อผิดพลาด 500 หน้าจะมีการแสดงที่คุณสามารถปรับแต่งอยู่แล้วโดยใน<error-page>
web.xml
หากคุณต้องการเรียกใช้โค้ด Java เพื่อประมวลผลคำขอเช่นประมวลผลการส่งแบบฟอร์มให้ใช้servletและเขียนโค้ดตามdoPost()
วิธีการ เช่น:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userService.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user); // Login user.
response.sendRedirect("home"); // Redirect to home page.
} else {
request.setAttribute("message", "Unknown username/password. Please retry."); // Store error message in request scope.
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response); // Forward to JSP page to redisplay login form with error.
}
}
วิธีนี้จะจัดการกับปลายทางของหน้าผลลัพธ์ที่ต่างกันได้ง่ายขึ้น: การแสดงฟอร์มซ้ำพร้อมข้อผิดพลาดในการตรวจสอบความถูกต้องในกรณีที่เกิดข้อผิดพลาด (ในตัวอย่างนี้คุณสามารถแสดงซ้ำโดยใช้${message}
ในEL ) หรือนำไปยังหน้าเป้าหมายที่ต้องการในกรณีที่ประสบความสำเร็จ
ถ้าคุณต้องการที่จะก่อให้เกิดบางรหัส Java เพื่อควบคุมแผนปฏิบัติการและ / หรือปลายทางของการร้องขอและการตอบสนองจากนั้นใช้servletตามรูปแบบ MVC หน้าของตัวควบคุม เช่น:
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
Action action = ActionFactory.getAction(request);
String view = action.execute(request, response);
if (view.equals(request.getPathInfo().substring(1)) {
request.getRequestDispatcher("/WEB-INF/" + view + ".jsp").forward(request, response);
} else {
response.sendRedirect(view);
}
} catch (Exception e) {
throw new ServletException("Executing action failed.", e);
}
}
หรือเพียงนำเฟรมเวิร์ก MVC เช่นJSF , Spring MVC , Wicketเป็นต้นมาลงเอยด้วยหน้า JSP / Facelets และคลาส JavaBean โดยไม่จำเป็นต้องใช้เซิร์ฟเล็ตแบบกำหนดเอง
หากคุณต้องการเรียกใช้โค้ด Java บางตัวเพื่อควบคุมโฟลว์ภายใน JSP หน้าแล้วคุณจะต้องคว้า (ที่มีอยู่) taglib การควบคุมการไหลเช่นหลัก JSTL เช่นแสดงList<Product>
ในตาราง:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
...
<table>
<c:forEach items="${products}" var="product">
<tr>
<td>${product.name}</td>
<td>${product.description}</td>
<td>${product.price}</td>
</tr>
</c:forEach>
</table>
ด้วยแท็ก XML แบบที่เหมาะสมเป็นอย่างดีในทุกที่ HTML รหัสจะดีกว่าอ่าน (และทำให้ดีขึ้นการบำรุงรักษา) มากกว่าพวงของ scriptlets ต่างๆด้วยการเปิดและปิดวงเล็บ ( "ที่ไหนห่าไม่รั้งปิดนี้เป็นของใคร?" ) ความช่วยเหลือที่ง่ายคือการกำหนดค่าเว็บแอปพลิเคชันของคุณให้มีข้อยกเว้นทุกครั้งสคริปต์ยังคงถูกใช้งานโดยการเพิ่มชิ้นส่วนต่อไปนี้ลงในweb.xml
:
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<scripting-invalid>true</scripting-invalid>
</jsp-property-group>
</jsp-config>
ในFaceletsสืบต่อจาก JSP ซึ่งเป็นส่วนหนึ่งของ Java EE มีให้ MVC กรอบJSFมันมีอยู่แล้วไม่ได้ที่จะใช้scriptlets วิธีนี้คุณถูกบังคับให้ทำสิ่งต่าง ๆ โดยอัตโนมัติ "ทางที่ถูกต้อง"
หากคุณต้องการเรียกใช้โค้ด Java เพื่อเข้าถึงและแสดงข้อมูล "แบ็กเอนด์" ในหน้า JSP คุณต้องใช้ EL (Expression Language) ใน${}
สิ่งเหล่านั้น เช่นการแสดงค่าอินพุตที่ส่งซ้ำ:
<input type="text" name="foo" value="${param.foo}" />
แสดงผลของ${param.foo}
request.getParameter("foo")
หากคุณต้องการเรียกใช้โค้ด Java ของยูทิลิตี้โดยตรงในหน้า JSP (โดยทั่วไปคือpublic static
เมธอด) คุณต้องกำหนดเป็นฟังก์ชัน EL มีมาตรฐานเป็นฟังก์ชั่น taglibใน JSTL แต่คุณยังสามารถสร้างฟังก์ชั่นด้วยตัวคุณเอง นี่คือตัวอย่างว่า JSTL fn:escapeXml
มีประโยชน์ในการป้องกันXSS อย่างไร การโจมตีอย่างไร
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
...
<input type="text" name="foo" value="${fn:escapeXml(param.foo)}" />
โปรดทราบว่าความไว XSS นั้นไม่เกี่ยวข้องกับ Java / JSP / JSTL / EL โดยเฉพาะสิ่งใดก็ตามปัญหานี้ต้องนำมาพิจารณาในทุก ๆเว็บแอปพลิเคชันที่คุณพัฒนา ปัญหาของscriptletsคือมันไม่มีวิธีการป้องกันในตัวอย่างน้อยก็ไม่ได้ใช้ Java API มาตรฐาน Facelets ตัวต่อของ JSP ได้หนี HTML ไปโดยปริยายดังนั้นคุณไม่ต้องกังวลกับช่อง XSS ใน Facelets