درس مثال JSP للمبتدئين

مرحبًا بكم في دليل مثال JSP للمبتدئين. في العدد الأخير من المنشورات، كتبت الكثير عن Java Servlet وحصلنا على استجابة جيدة جدًا من قرائنا. لذا بدأت سلسلة جديدة عن دروس JSP وهذه هي أول مشاركة في السلسلة.

دليل مثال JSP

في هذا الدليل عن مثال JSP، سننظر في أساسيات JSP، ومزايا JSP على السيرفلتات، ودورة حياة JSP، وواجهات وفئات واجهة برمجة التطبيقات JSP وأين يمكننا وضع ملفات JSP في تطبيق الويب. سننظر أيضًا في تعليقات JSP، وسكربتات، وتوجيهات، وتعبير، وإعلان JSP وسمات JSP بتفصيل موجز. بعض هذه المواضيع مهمة للغاية وسننظر فيها بتفصيل أكثر في المشاركات المستقبلية.

دليل JSP

  1. ما هو JSP ولماذا نحتاج إلى JSP؟
  2. مزايا JSP على السيرفلتات؟
  3. دورة حياة صفحة JSP
  4. أساليب دورة حياة JSP
  5. مثال بسيط لـ JSP مع Eclipse و Tomcat
  6. موقع ملفات JSP في ملف تطبيق الويب WAR
  7. واجهات برمجة التطبيقات والفئات JSP
  1. تعليقات JSP

  2. سكريبتات JSP

  3. تعبيرات JSP

  4. توجيهات JSP

  5. إعلان JSP

  6. رمز المصدر وموقع ملف الفئة المحولة لـ JSP في تومكات

  7. معلمات التهيئة لـ JSP

  8. تجاوز طريقة init() لـ JSP

  9. السمات في JSP

  10. ما هو JSP ولماذا نحتاج إلى JSP؟

    JSP (JavaServer Pages) هي تقنية على الجانب الخادم لإنشاء تطبيقات ويب ديناميكية بلغة جافا. يمكن اعتبار JSP تمديدًا لتقنية السيرفلت لأنها توفر ميزات لإنشاء عروض مستخدم بسهولة. تتكون صفحة JSP من كود HTML وتوفر خيارًا لتضمين كود جافا للمحتوى الديناميكي. نظرًا لأن تطبيقات الويب تحتوي على الكثير من شاشات المستخدم، فإن JSP تستخدم كثيرًا في تطبيقات الويب. لسد الفجوة بين كود جافا و HTML في JSP، فإنها توفر ميزات إضافية مثل علامات JSP، لغة التعبيرات، العلامات المخصصة. وهذا يجعل من السهل فهمها ويساعد مطور الويب على تطوير صفحات JSP بسرعة.

  11. ما هي مزايا JSP على السيرفلت؟

    • يمكننا توليد استجابة HTML من السيرفلتات أيضًا ولكن العملية متعبة ومعرضة للأخطاء، عندما يتعلق الأمر بكتابة استجابة HTML معقدة، فإن الكتابة في السيرفلت ستكون كابوسًا. تساعدنا JSP في هذه الحالة وتوفر لنا مرونة في كتابة صفحة HTML عادية وتضمين كود Java الخاص بنا فقط حيث يلزم ذلك.
    • توفر JSP ميزات إضافية مثل مكتبات العلامات، ولغة التعبير، والعلامات المخصصة التي تساعد في تطوير أسرع لعروض المستخدم.
    • صفحات JSP سهلة النشر، فقط نحتاج إلى استبدال الصفحة المعدلة في الخادم ويعتني المحتوى بالنشر. بالنسبة للسيرفلتات، نحتاج إلى إعادة تجميع ونشر المشروع بأكمله. في الواقع، السيرفلتات و JSPs يكملان بعضهما البعض. يجب علينا استخدام السيرفلت كمتحكم في الجانب الخادم وللتواصل مع الطبقات النموذجية بينما يجب استخدام JSPs لطبقة العرض.
  12. دورة حياة صفحة JSP

    يتم إدارة دورة حياة JSP أيضًا بواسطة الحاوية. عادةً ما يحتوي كل حاوية ويب تحتوي على حاوية سيرفلت أيضًا تحتوي على حاوية JSP لإدارة صفحات JSP. مراحل دورة حياة صفحات JSP هي:

    • الترجمة – لا تبدو صفحات JSP مثل فصول جافا العادية، في الواقع تقوم حاوية 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(). فئة تومكات المتماسكة لـ JspWriter هي org.apache.jasper.runtime.JspWriterImpl.

  • صف JspContext المجرد

    يعمل صف JspContext كصنف أساسي لصف PageContext ويجرد جميع المعلومات التي ليست محددة لـ servlets. يوفر JspContext آلية للحصول على JspWriter للإخراج، وآلية للعمل مع السمات وواجهة برمجة التطبيقات لإدارة مختلف أنطمة الأسماء المحددة.

  • فئة السياق لـ 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 وموقع ملف الصف الفئة في تومكات

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 للمبتدئين. آمل أن يساعدك في فهم المفاهيم الأساسية لـ JSPs ويساعدك في البدء. سننظر في ميزات JSP الأخرى في المشاركات المستقبلية.

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