מדריך לדוגמאות JSP עבור מתחילים

ברוכים הבאים למדריך הדוגמה של JSP עבור מתחילים. בפוסטים האחרונים, כתבתי הרבה על Java Servlet וקיבלתי מענה טוב מקוראינו. לכן התחלתי סדרה חדשה על מדריכי JSP וזהו הפוסט הראשון בסדרה.

מדריך דוגמה של JSP

במדריך דוגמה זה של JSP, נתעסק ביסודות של JSP, היתרונות של JSP מעל Servlets, מחזור החיים של JSP, ממשקי API של JSP ומחלקות, והיכן ניתן לשים קבצי JSP ביישום האינטרנט. נבחן גם את ההערות של JSP, Scriptlets, כוויות, ביטוי, הצהרה ומאפייני JSP בפרטים קצרים. חלק מהנושאים האלה הם חשובים מאוד ונבחן אותם בעומק בפוסטים הבאים.

מדריך JSP

  1. מה זה JSP ולמה אנו צריכים JSP?
  2. יתרונות של JSP מעל Servlets?
  3. מחזור החיים של דף JSP
  4. שיטות מחזור החיים של JSP
  5. דוגמה פשוטה ל-JSP עם Eclipse ו-Tomcat
  6. מיקום קבצי JSP בתוך קובץ WAR של אפליקציית האינטרנט
  7. ממשקים ומחלקות API של JSP
  1. הערות JSP

  2. סקריפטים JSP

  3. ביטויים JSP

  4. הוראות JSP

  5. הכרזה JSP

  6. קוד מקור של Servlet שהומר מ-JSP ומיקום של קובץ מחלקה ב-Tomcat

  7. פרמטרי הפעלה של JSP

  8. דריסת שיטת init() של JSP

  9. מאפיינים ב-JSP

  10. מהו JSP ולמה אנו זקוקים ל-JSP?

    JSP (JavaServer Pages) הוא טכנולוגיית צד שרת המשמשת ליצירת יישומי רשת Java דינמיים. ניתן לראות ב-JSP כהרחבה של טכנולוגיית servlet, מכיוון שהיא מספקת תכונות המקלות על יצירת תצוגות משתמש בצורה פשוטה. עמוד JSP מורכב מקוד HTML ומספק אפשרות לכלול קוד Java לתוך התוכן הדינמי. מאחר ויישומי הרשת מכילים הרבה מסכים שונים, JSP נעשה בהם שימוש נרחב. כדי לחבר בין קוד Java ו-HTML ב-JSP, היא מספקת תכונות נוספות כמו תגי JSP, שפת ביטויים, ותגים מותאמים אישית. כל זה יוצר חווית פיתוח יעילה ומהירה למפתחי רשת.

  11. יתרונות של JSP על Servlets?

    • אנו יכולים ליצור תגובת HTML מ- servlets גם, אך התהליך מעיק ומסוכן לשגיאות. כאשר מדובר בכתיבת תגובת HTML מורכבת, כתיבה ב- servlet תהיה תורם קושי. JSP עוזרת במצב כזה ומספקת לנו גמישות לכתוב דף HTML רגיל ולכלול את קוד ה-Java שלנו רק במקומות בהם זה נדרש.
    • JSP מספקת תכונות נוספות כמו ספריות תגיות, שפת ביטוי, תגיות מותאמות אישית שעוזרות בפיתוח מהיר יותר של תצוגות משתמש.
    • דפי JSP קלים להפצה, אנו רק צריכים להחליף את הדף המודפס בשרת והתקן יטפל בהפצה. ב- servlets, אנו צריכים להידרדר ולהפיץ מחדש את כל הפרויקט. למעשה Servlet ו- JSPs מתואמים זה עם זה. עלינו להשתמש ב- Servlet כבקר בצד השרת ולתקשר עם מחלקות המודל, בעוד ש-JSPs יש להשתמש בשכבת ההצגה.
  12. מחזור חיי עמוד JSP

    מחזור החיים של JSP ניהול גם על ידי המעטפת. כל תפקיד אינטרנטי שמכיל את מעטפת הסרבלט מכיל גם מעטפת JSP לניהול עמודי JSP. שלבי מחזור החיים של עמודי JSP הם:

    • תרגום – עמודי JSP אינם נראים כמו מחלקות Java רגילות, למעשה מעטפת ה-JSP מפענחת את עמודי ה-JSP ומתרגמת אותם כדי ליצור קוד מקור סרבלט תואם. אם שם הקובץ של עמוד ה-JSP הוא home.jsp, לרוב יש קובץ מתאים בשם home_jsp.java.
    • הידור – אם התרגום הצליח, אז המעטפת מהדהדת את קובץ המקור שנוצר של הסרבלט כדי ליצור קובץ מחלקה.
    • טעינת מחלקה – לאחר ש-JSP מהודר כמחלקת סרבלט, המחזור החיים שלו דומה לסרבלט והוא מוטען לזיכרון.
    • יצירת מופע – לאחר שמחלקת JSP מוטענת לזיכרון, מופעה מופעל על ידי המעטפת.
    • איתחול – מחלקת ה-JSP אז מתבצע איתחול והיא משתנה ממחלקה רגילה לסרבלט. לאחר האיתחול, אובייקטי ServletConfig ו-ServletContext מתגשמים למחלקת JSP.
    • עיבוד בקשה – לכל בקשת לקוח, נוצרת תהליך חדש עם ServletRequest ו-ServletResponse לעיבוד ויצירת תגובת HTML.
    • הרס – השלב האחרון של מחזור חיי ה-JSP שבו הוא מוסר לאחסון בזיכרון.
  13. שיטות מחזור החיים של JSP

    שיטות מחזור החיים של JSP הן:

    1. jspInit() מוגדר בממשק JspPage. השיטה הזו נקראת רק פעם אחת במחזור החיים של JSP כדי לאתחל פרמטרי תצורה.
    2. _jspService(HttpServletRequest request, HttpServletResponse response) מוגדר בממשק HttpJspPage ומטפל בבקשות מלקוח תגובה.
    3. jspDestroy() מוגדר בממשק JspPage כדי לזרוק את ה-JSP מהזיכרון.
  14. דוגמה פשוטה של JSP עם Eclipse ו-Tomcat

We can use Eclipse IDE for building dynamic web project with JSPs and use Tomcat to run it. Please read [Java Web Applications](/community/tutorials/java-web-application-tutorial-for-beginners#first-web-app-servlet) tutorial to learn how can we easily create JSPs in Eclipse and run it in tomcat. A simple JSP example page example is: `home.jsp`

```
<%@ page language="java" contentType="text/html; charset=US-ASCII"
    pageEncoding="US-ASCII"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>First JSP</title>
</head>
<%@ page import="java.util.Date" %>
<body>
<h3>Hi Pankaj</h3><br>
<strong>Current Time is</strong>: <%=new Date() %>

</body>
</html>
```

If you have a simple JSP that uses only JRE classes, we are not required to put it as WAR file. Just create a directory in the tomcat webapps folder and place your JSP file in the newly created directory. For example, if your JSP is located at apache-`tomcat/webapps/test/home.jsp`, then you can access it in browser with URL `https://localhost:8080/test/home.jsp`. If your host and port is different, then you need to make changes in URL accordingly.
  1. מיקום של קבצי JSP בקובץ WAR של אפליקציה אינטרנטית

We can place JSP files at any location in the WAR file, however if we put it inside the WEB-INF directory, we wont be able to access it directly from client. We can configure JSP just like servlets in web.xml, for example if I have a JSP example page like below inside WEB-INF directory: `test.jsp`

```
<%@ page language="java" contentType="text/html; charset=US-ASCII"
    pageEncoding="US-ASCII"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Test JSP</title>
</head>
<body>
Test JSP Page inside WEB-INF folder.<br>
Init Param "test" value =<%=config.getInitParameter("test") %><br>
HashCode of this object=<%=this.hashCode() %>
</body>
</html>
```

And I configure it in web.xml configuration as:

```
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>FirstJSP</display-name>
  
  <servlet>
  <servlet-name>Test</servlet-name>
  <jsp-file>/WEB-INF/test.jsp</jsp-file>
  <init-param>
  	<param-name>test</param-name>
  	<param-value>Test Value</param-value>
  </init-param>
  </servlet>
  
  <servlet-mapping>
  <servlet-name>Test</servlet-name>
  <url-pattern>/Test.do</url-pattern>
  </servlet-mapping>
  
  <servlet>
  <servlet-name>Test1</servlet-name>
  <jsp-file>/WEB-INF/test.jsp</jsp-file>
  </servlet>
  
  <servlet-mapping>
  <servlet-name>Test1</servlet-name>
  <url-pattern>/Test1.do</url-pattern>
  </servlet-mapping>
</web-app>
```

Then I can access it with both the URLs https://localhost:8080/FirstJSP/Test.do and https://localhost:8080/FirstJSP/Test1.do Notice that container will create two instances in this case and both will have their own servlet config objects, you can confirm this by visiting these URLs in browser. For Test.do URI, you will get response like below.

```
Test JSP Page inside WEB-INF folder.
Init Param "test" value =Test Value
HashCode of this object=1839060256
```

For Test1.do URI, you will get response like below.

```
Test JSP Page inside WEB-INF folder.
Init Param "test" value =null
HashCode of this object=38139054
```

Notice the init param value in second case is null because it's not defined for the second servlet, also notice the hashcode is different. If you will make further requests, the hashcode value will not change because the requests are processed by spawning a new thread by the container. Did you noticed the use of **config** variable in above JSP example but there is no variable declared, it's because its one of the 9 implicit objects available in JSP page, read more about them at [**JSP Implicit Objects**](/community/tutorials/jsp-implicit-objects "JSP Implicit Objects with Examples").
  1. ממשקים וכיתות של API של JSP

All the core JSP interfaces and classes are defined in `javax.servlet.jsp` package. Expression Language API interfaces are classes are part of `javax.servlet.jsp.el` package. JSP Tag Libraries interfaces and classes are defined in `javax.servlet.jsp.tagext` package. Here we will look into interfaces and classes of Core JSP API.
  • ממשק JspPage

    הממשק JspPage מרחיב את ממשק Servlet ומצהיר על שיטות מחזור החיים jspInit() ו-jspDestroy() של דפי ה-JSP.

  • ממשק HttpJspPage

    הממשק HttpJspPage מתאר את האינטראקציה שדף JSP חייב לעמוד בה עם כיתת המימוש שלו בעת שימוש בפרוטוקול HTTP. הממשק הזה מצהיר על שיטת השירות של דף JSP עבור פרוטוקול HTTP כ־public void _jspService(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException.

  • מחלקת JspWriter המופשטת

    דומה ל-PrintWriter בסרבלטים עם יכולת נוספת של תמיכה בבפרורה. זו אחת מהמשתנים הנדמים באופן משתמש בדף JSP בשם "out". מחלקה זו מרחיבה את java.io.Writer והמחלקה המכוף מספקת במימוש ייחודי שלה ומשתמשת בו בעת תרגום הדף JSP לסרבלט. ניתן לקבל את אובייקטה באמצעות השיטה PageContext.getOut(). מחלקת הסרבלט הקונקרטית של Apache Tomcat ל-JspWriter היא org.apache.jasper.runtime.JspWriterImpl.

  • מחלקת JspContext המופשטת

    מחלקת JspContext משמשת כמחלקת בסיס עבור מחלקת PageContext ומפשטת את כל המידע שאינו specifik ל-Servlets. מחלקת JspContext מספקת מנגנון לקבלת JspWriter לפלט, מנגנון לעבוד עם מאפיינים ו- API לניהול של יישות שונות במרחבי השמות.

  • מחלקת PageContext המופשטת

    מחלקת PageContext מרחיבה את JspContext כדי לספק מידע קשור כאשר JSP משמש ליישומי אינטרנט. מופע של PageContext מספק גישה לכל השמות המשוייכים לדף JSP, גישה למספר מאפייני דף, וכן שכבה מעל פרטי היישום. אובייקטים רמוזים נוספים נוספים ל-pageContext באופן אוטומטי.

  • מחלקת JspFactory המופשטת

    ה־JspFactory היא מחלקה מופשטת המגדירה מספר של מתודות מפענחות זמינות לדף JSP בזמן ריצה למטרת יצירת מופעים של ממשקים ומחלקות שונות המשמשות לתמיכה במימוש של JSP.

  • מחלקת JspEngineInfo המופשטת

    ה־JspEngineInfo היא מחלקה מופשטת הספקת מידע על המנוע JSP הנוכחי.

  • מחלקה סופית של ErrorData

    מכילה מידע על שגיאה, לעמודי שגיאות.

  • מחלקת JspException

    שגיאה גנרית ידועה למנוע ה-JSP, דומה ל-ServletException. אם עמודי ה-JSP זורקים חריגת JspException, אז מנגנון דף השגיאות משמש להצגת מידע על השגיאה למשתמש.

  • מחלקת JspTagException

    חריגה המשמשת על ידי טיפול בתג כדי לציין שגיאה בלתי מחזורית מסוימת.

  • מחלקת SkipPageException

    חריגה המציינת כי הדף הקורא חייב להפסיק את הערך. זרק על ידי טיפול בתג פשוט כדי לציין ששאר הדף אינו ייערך. לא צריך לזרוק חריגה זו באופן ידני בדף JSP.

  1. הערות JSP

Since JSP is built on top of HTML, we can write comments in JSP file like html comments as `<-- This is HTML Comment -->` These comments are sent to the client and we can look it with view source option of browsers. We can put comments in JSP files as: `<%-- This is JSP Comment--%>` This comment is suitable for developers to provide code level comments because these are not sent in the client response.
  1. סקריפטים JSP

Scriptlet tags are the easiest way to put java code in a JSP page. A scriptlet tag starts with `<%` and ends with `%>`. Any code written inside the scriptlet tags go into the `_jspService()` method. For example:

```
<%
Date d = new Date();
System.out.println("Current Date="+d);
%>
```
  1. ביטוי JSP

Since most of the times we print dynamic data in JSP page using _out.print()_ method, there is a shortcut to do this through JSP Expressions. JSP Expression starts with `<%=` and ends with `%>`. `<% out.print("Pankaj"); %>` can be written using JSP Expression as `<%= "Pankaj" %>` Notice that anything between `<%= %>` is sent as parameter to `out.print()` method. Also notice that scriptlets can contain multiple java statements and always ends with semicolon (;) but expression doesn't end with semicolon.
  1. הפניות JSP

JSP Directives are used to give special instructions to the container while JSP page is getting translated to servlet source code. JSP directives starts with `<%@` and ends with `%>` For example, in above JSP Example, I am using _page_ directive to to instruct container JSP translator to import the Date class.
  1. הכרזת JSP

JSP Declarations are used to declare member methods and variables of servlet class. JSP Declarations starts with `<%!` and ends with `%>`. For example we can create an int variable in JSP at class level as `<%! public static int count=0; %>`
  1. קוד מקור של סרבל JSP המומר ומיקום קובץ המחלקה בתוך Tomcat

Once JSP files are translated to Servlet source code, the source code (.java) and compiled classes both are place in **Tomcat/work/Catalina/localhost/FirstJSP/org/apache/jsp** directory. If the JSP files are inside other directories of application, the directory structure is maintained. For JSPs inside WEB-INF directory, its source and class files are inside **Tomcat/work/Catalina/localhost/FirstJSP/org/apache/jsp/WEB\_002dINF** directory. Here is the source code generated for above test.jsp page. `test_jsp.java`

```
/*
 * Generated by the Jasper component of Apache Tomcat
 * Version: Apache Tomcat/7.0.32
 * Generated at: 2013-08-21 03:40:59 UTC
 * Note: The last modified time of this file was set to
 *       the last modified time of the source file after
 *       generation to assist with modification tracking.
 */
package org.apache.jsp.WEB_002dINF;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class test_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static final javax.servlet.jsp.JspFactory _jspxFactory =
          javax.servlet.jsp.JspFactory.getDefaultFactory();

  private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.tomcat.InstanceManager _jsp_instancemanager;

  public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
    return _jspx_dependants;
  }

  public void _jspInit() {
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
  }

  public void _jspDestroy() {
  }

  public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
        throws java.io.IOException, javax.servlet.ServletException {

    final javax.servlet.jsp.PageContext pageContext;
    javax.servlet.http.HttpSession session = null;
    final javax.servlet.ServletContext application;
    final javax.servlet.ServletConfig config;
    javax.servlet.jsp.JspWriter out = null;
    final java.lang.Object page = this;
    javax.servlet.jsp.JspWriter _jspx_out = null;
    javax.servlet.jsp.PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html; charset=US-ASCII");
      pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\n");
      out.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"https://www.w3.org/TR/html4/loose.dtd\">\n");
      out.write("<html>\n");
      out.write("<head>\n");
      out.write("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=US-ASCII\">\n");
      out.write("<title>Test JSP</title>\n");
      out.write("</head>\n");
      out.write("<body>\n");
      out.write("Test JSP Page inside WEB-INF folder.<br>\n");
      out.write("Init Param \"test\" value =");
      out.print(config.getInitParameter("test") );
      out.write("<br>\n");
      out.write("HashCode of this object=");
      out.print(this.hashCode() );
      out.write("\n");
      out.write("</body>\n");
      out.write("</html>");
    } catch (java.lang.Throwable t) {
      if (!(t instanceof javax.servlet.jsp.SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try { out.clearBuffer(); } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else throw new ServletException(t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}
```

Notice following points in above servlet code;
-   The package of class starts with org.apache.jsp and if JSPs are inside other folders, it includes directory hierarchy too. Usually we dont care about it.
-   The generates servlet class is final and can't be extended.
-   It extends `org.apache.jasper.runtime.HttpJspBase` that is similar to HttpServlet except that it's internal to Tomcat JSP Translator implementation. HttpJspBase extends HttpServlet and implements HttpJspPage interface.
-   Notice the local variables at the start of \_jspService() method implementation, they are automatically added by JSP translator and available for use in service methods, i.e in scriptlets.As a java programmer, sometimes it helps to look into the generated source for debugging purposes.
  1. פרמטרים יישום של JSP

We can define init parameters for the JSP page as shown in above example and we can retrieve them in JSP using **config** implicit object, we will look into implicit objects in JSP in more detail in future posts.
  1. התעלמות משיטת init() של JSP

We can override JSP init method for creating resources to be used by JSP service() method using JSP Declaration tags, we can override jspInit() and jspDestroy() or any other methods also. However we should never override \_jspService() method because anything we write in JSP goes into service method.
  1. מאפיינים ב-JSP

Apart from standard servlet attributes with request, session and context scope, in JSP we have another scope for attributes, i.e Page Scope that we can get from pageContext object. We will look it's importance in custom tags tutorial. For normal JSP programming, we don't need to worry about page scope.

זה הכל לדוגמא של JSP עבור מתחילים. אני מקווה שזה יעזור לך להבין את המושגים הבסיסיים של JSP ויסייע לך להתחיל. נבדוק תכונות אחרות של JSP בפוסטים עתידיים.

Source:
https://www.digitalocean.com/community/tutorials/jsp-example-tutorial-for-beginners