JSP

JSP và Servlet

Về mặt kiến trúc mà nói, ta có thể xem JSP là một trừu tượng ở mức độ cao của servlet, một phần mở rộng thực thi của Servlet 2.1 API. Cả hai, servlet và, đều nguyên do công ty Sun Microsystems tạo dựng. Bắt đầu từ phiên bản 1.2 đặc tả của JSP, JavaServer Pages đã được xây dựng do Tiến trình cộng đồng Java (Java Community Process). JSR 53 - Java Specification Requests hay "Yêu cầu đặc tả cho Java" - định nghĩa bản đặc tả của cả hai, JSP 1.2 và Servlet 2.4, và JSR 152 định nghĩa bản đặc tả JSP 2.0. Tại thời điểm năm 2006 bản đặc tả JSP 2.1 được xây dựng trên nền của yêu cầu JSR 245.

Dữ liệu tĩnh

Vì dữ liệu tĩnh được viết ra trong phần hồi âm HTTP (HTTP response) cũng giống như nó được viết trong tập tin nhận vào (input file), cho nên dữ liệu nhập hợp lệ của JSP thường là một trang HTML bình thường, không có mã java hoặc hành động JSP nhúng trong đó. Với dữ liệu tĩnh này, bất cứ lúc nào trình chủ web hồi âm, trình chủ web cũng sẽ gửi cùng một dữ liệu sang trang trình khách.

jsp:include

<html>
<head></head>
<body>
<jsp:include page="mycommon.jsp" >
    <jsp:param name="extraparam" value="myvalue" />
</jsp:include>
name:<%=request.getParameter("extraparam")%>
</body></html>

jsp:forward

<jsp:forward page="subpage.jsp" >
   <jsp:param name="forwardedFrom" value="this.jsp" />
</jsp:forward>
Trong ví dụ tiếp tới này, yêu cầu được chuyển về phía trước tới "subpage.jsp". Thao tác xử lý yêu cầu không quay trở lại trang này.

jsp:plugin

<jsp:plugin type=applet height="100%" width="100%"
      archive="myjarfile.jar,myotherjar.jar"
      codebase="/applets"
      code="com.foo.MyApplet" >
  <jsp:params>
     <jsp:param name="enableDebug" value="true" />
  </jsp:params>
  <jsp:fallback>
    Trình duyệt web của bạn không hỗ trợ những applet này.
  </jsp:fallback>
</jsp:plugin>
Ví dụ plugin trên minh họa một phương pháp đồng bộ để nhúng applet trong một trang web. Trước khi thẻ <OBJECT> được tạo ra, chưa có một phương pháp chung nào cho phép người ta nhúng các applet cả. Thiết kế của thẻ này tương đối nghèo nàn. Hy vọng những đặc tả của nó trong tương lai sẽ cho phép những cái như đặc tính năng động (dynamic attributes) (height="${param.height}", code="${chart}" v.v.) và thông số năng động (dynamic parameters). Hiện này, thẻ jsp:plugin không cho phép dùng những applet khởi động một cách năng động. Chẳng hạn, nếu chúng ta có một applet biểu hiện đồ thị và nó cần có các dữ liệu về tọa độ được truyền cho nó thông qua các thông số, chúng ta không thể dùng jsp:params, trừ phi số điểm tọa độ là một số cố định. Chúng ta không thể, ví dụ, luân chuyển qua danh sách loạt kết quả (ResultSet) để kiến tạo các thẻ jsp:param. Chúng ta phải tự tính toán cho từng cái thẻ jsp:param một. Đương nhiên, mỗi một thẻ jsp:param ấy có thể có một cái tên và một giá trị tùy định.

Quốc tế hóa

Quốc tế hóa trong JSP có thể được thực hiện tương tự như phương pháp làm trong các trình ứng dụng Java thông thường, nghĩa là bằng cách dùng gói tài nguyên (resource bundle). Việc thay đổi ngôn ngữ thể hiện trên các trang web được thực hiện một cách đơn giản thông qua việc thay đổi đơn vị locale. Bằng cách đó, lập trình viên có thể thực hiện thay đổi nội dung, ngôn ngữ... thông qua thay đổi các resource bundle này chứ không cần trực tiếp tác động lên code của trang JSP hay code của taglib.

Mẫu hình MVC

Sun khuyến cáo việc sử dụng mẫu hình MVC (Model-View-Controller - tạm dịch là "Mô hình dữ liệu - giao diện người dùng - lôgic điều khiển", có thể gọi ngắn là "mô hình - giao diện - điều khiển") cho các tập tin JSP để có thể tách biệt phần trình bày (presentation) khỏi phần xử lý yêu cầu (request processing) và lưu trữ dữ liệu (data storage). Hoặc là các servlets thông thường hoặc là các tập tin JSP phải được sử dụng để xử lý yêu cầu. Sau khi đã hoàn thành việc xử lý yêu cầu, quyền điều khiển được chuyển sang cho một trang JSP khác. Trang này chỉ được dùng để tạo xuất liệu, tức là hiển thị ở đầu ra. Hiện nay có một vài hệ nền (platforms) được tạo dựa trên nền của nguyên lý mẫu hình MVC cho các tầng máy web (web tiers) (chẳng hạn như Struts và cơ cấu Spring (Spring framework))

Ví dụ

Mặc dầu bộ biên dịch JSP kiến tạo mã nguồn Java cho servlet hoặc phát ra mã byte của Java (byte code) trực tiếp, chúng ta cũng nên hiểu quá trình bộ biên dịch JSP biến đổi một trang JSP trở thành một servlet của Java như thế nào. Chẳng hạn, chúng ta thử cân nhắc những dữ liệu nhập của JSP sau đây, và kết quả Java Servlet mà nó sinh tạo.
Trang JSP nhập vào

 <%@ page errorPage="myerror.jsp" %>
 <%@ page import="com.foo.bar" %>

 <html>
 <head>
 <%! int serverInstanceVariable = 1;%>
...
 <% int localStackBasedVariable = 1; %>
 <table>
 <tr><td><%= toStringOrBlank("expanded inline data"  + 1) %></td></tr>
...
Kết quả servlet được sinh tạo

 package jsp_servlet;
 import java.util.*;
 import java.io.*;
 import javax.servlet.*;
 import javax.servlet.http.*;
 import javax.servlet.jsp.*;
 import javax.servlet.jsp.tagext.*;

 import com.foo.bar; //nhập nội do kết quả của dòng <%@ page import="com.foo.bar" %>
 import...

 class _myserlvet implements javax.servlet.Servlet, javax.servlet.jsp.HttpJspPage {
     //được chèn thêm vào  
     //do kết quả của dòng <%! int serverInstanceVariable = 1;%>
     int serverInstanceVariable = 1; 
...

     public void _jspService(javax.servlet.http.HttpServletRequest request,
                              javax.servlet.http.HttpServletResponse response)
       throws javax.servlet.ServletException,
              java.io.IOException
     {
         javax.servlet.ServletConfig config =...;//lấy cấu hình của servlet vào
         Object page = this;
         PageContext pageContext =...;//lấy ngữ cảnh của trang đối với yêu cầu này 
         javax.servlet.jsp.JspWriter out = pageContext.getOut();
         HttpSession session = request.getSession(true);
         try {
             out.print("<html>\r\n");
             out.print("<head>\r\n");
     ...
             //sinh ra từ dòng <% int localStackBasedVariable = 1; %>
             int localStackBasedVariable = 1; 
     ...
             out.print("<table>\r\n");
             out.print("   <tr><td>");
             //để ý, toStringOrBlank() đổi biểu thức thành chuỗi ký tự hoặc 
             // nếu biểu thức không tồn tại (null), dùng chuỗi ký tự trống rỗng (empty string) thay thế.
             //từ dòng <%= "expanded inline data " + 1 %>
             out.print(toStringOrBlank("expanded inline data " + 1));
             out.print("   </td></tr>\r\n");
     ...
         } catch (Exception _exception) {
             //dọn dẹp sạch sẽ và chuyển hướng điều khiển tới trang báo lỗi như trong dòng <%@ page errorPage="myerror.jsp" %>
         }
    }
 }