Məzmuna keçLogo

Command Palette

Search for a command to run...

JSP — Java Server Səhifələri

Dərc olundu
13 apr 2025
JSP — Java Server Səhifələri

JSP - JavaServer Pages

Java ekosistemində web application hazırlamaqdan danışarkən, JSP (JavaServer Pages) adı qaçınılmazdır. JSP, dinamik veb səhifələri yaratmaq üçün HTML, XML və ya digər markup dillərinin içərisinə Java kodunu yerləşdirməyə imkan verən bir server-side texnologiyadır. Əsas məqsədi presentation layer-i business logic-dən ayırmağa kömək etməkdir, baxmayaraq ki, bu ayrılığın nə qədər effektiv olması sizin JSP-dən necə istifadə etdiyinizdən çox asılıdır.


Servletlərlə müqayisədə, JSP daha çox frontend developer-lər və ya dizaynerlər üçün rahat bir mühit təmin edir, çünki əsasən HTML-ə bənzəyir və dinamik hissələr xüsusi tags və ya minimal Java kodu ilə əlavə edilir. Amma arxa planda baş verənləri anlamaq hər bir ciddi Java web developer üçün vacibdir.

JSP-nin Arxasında Nə Baş Verir: The Lifecycle

Bir JSP səhifəsi ilk dəfə request alanda və ya web application başladığında (konfiqurasiyadan asılı olaraq) bir lifecycle-dan keçir. Bu prosesi başa düşmək, JSP-nin necə işlədiyini və potensial problemləri anlamaq üçün kritikdir:

  1. Translation Phase: JSP container (məsələn, Tomcat, Jetty içərisindəki Jasper) .jsp faylını oxuyur və onu ekvivalent bir Java Servlet source code faylına (.java) çevirir. Bu mərhələdə bütün JSP elementləri (scriptletlər, expressionlar, directive-lər, action-lar) uyğun Java koduna transformasiya olunur. Statik HTML/markup isə out.println() kimi statements-ə çevrilir.
  2. Compilation Phase: JSP container yaradılmış .java faylını standart Java compiler (javac) vasitəsilə Java bytecode (.class) faylına kompayl edir. Hər hansı bir sintaksis xətası bu mərhələdə ortaya çıxacaq.
  3. Loading Phase: Kompayl edilmiş .class faylı JVM-ə (Java Virtual Machine) yüklənir.
  4. Instantiation Phase: Yüklənmiş class-dan bir instance (obyekt) yaradılır. Hər bir JSP səhifəsi üçün adətən yalnız bir instance yaradılır (lakin fərqli konfiqurasiyalar mümkündür).
  5. Initialization Phase: Container, Servlet specification-da olduğu kimi, jspInit() metodunu çağırır. Bu metod yalnız bir dəfə, instance yaradıldıqdan dərhal sonra çağırılır və database connection-ları açmaq və ya digər one-time setup işləri üçün istifadə edilə bilər. Bunu override etmək üçün JSP declaration elementindən istifadə edə bilərsiniz.
  6. Request Processing Phase: Hər bir client request-i üçün container yeni bir thread yaradır və həmin thread üzərindən _jspService() metodunu çağırır. Sizin JSP faylındakı bütün scriptlet kodu, expression-lar və HTML bu metodun içərisinə yerləşdirilir. Bu metod requestresponse obyektlərini parametr olaraq qəbul edir.
    • ⚠️ Vacib: _jspService() metodu multithreaded mühitdə işlədiyi üçün instance variables (declaration ilə yaradılanlar) istifadə edərkən thread safety məsələlərinə diqqət yetirmək lazımdır. Local variables (scriptlet içində yaradılanlar) isə hər request üçün ayrı olduğundan thread-safe-dir.
  7. Destruction Phase: Web application dayandırıldıqda və ya JSP container shutdown edildikdə, container jspDestroy() metodunu çağırır. Bu metod da yalnız bir dəfə çağırılır və jspInit()də açılmış resources-ları (məsələn, database connection-ları) bağlamaq üçün istifadə edilə bilər.

➡️ Əsas Çıxarış: Hər bir JSP faylı, əslində, arxa planda işləyən bir Servlet-dir! Bu faktı anlamaq, JSP-nin davranışını və Servlet konteksti ilə əlaqəsini dərk etmək üçün fundamentaldır.

JSP Sintaksisi:

Bir JSP səhifəsi statik markup (HTML, XML) və dinamik JSP elementlərinin qarışığından ibarətdir. JSP container bu elementləri emal edərək nəticəni client-ə göndərir.

Scripting Elements (The "Old" Way - Ehtiyatla İstifadə Edin!)

Bu elementlər JSP səhifələrinə birbaşa Java kodu yerləşdirməyə imkan verir. Modern JSP təcrübələrində (EL və JSTL ilə) bunlardan mümkün qədər qaçınmaq tövsiyə olunur, çünki presentation ilə logic-i qarışdırır və kodu oxunmaz hala gətirir. Ancaq onları tanımaq vacibdir:

  • Declarations (<%! ... %>):

    • Generated Servlet class-ının səviyyəsində variables (member variables) və methods elan etmək üçün istifadə olunur.
    • Burada elan edilən variables bütün requests-lər arasında paylaşılır və thread-safe deyil! Çox diqqətli olmaq lazımdır.
    • Metodlar (məsələn, helper methods və ya jspInit/jspDestroyu override etmək) elan etmək üçün daha çox istifadə olunur.
    example/Declarations.jsp
    <%!
        private int counter = 0; // WARNING: Not thread-safe if modified concurrently!
        private String formatData(String data) {
            // Some formatting logic
            return "[" + data + "]";
        }
        public void jspInit() {
            log("My JSP is initializing!");
        }
    %>
  • Scriptlets (<% ... %>):

    • Generated Servlet-in _jspService() metodu içərisinə yerləşdiriləcək Java kod bloklarıdır.
    • İstənilən qədər Java kodu (variable elanları, loops, conditionals, method calls) burada yazıla bilər.
    • Burada elan edilən local variables hər request üçün yenidən yaradılır və thread-safedir.
    • ⚠️ Əsas Problem: HTML markup ilə Java kodunun qarışması (Spaghetti code), oxunaqlılığı və maintainability-ni kəskin şəkildə azaldır. Bundan qaçının!
    example/Scriptlet.jsp
    <%
        String userName = request.getParameter("user");
        if (userName != null && !userName.isEmpty()) {
            for (int i = 0; i < 3; i++) {
                out.println("Hello, " + userName + "! (" + i + ")<br>");
            }
        } else {
            out.println("Hello, Guest!<br>");
        }
        // Accessing a declared method:
        out.println(formatData("Some data"));
    %>
  • Expressions (<%= ... %>):

    • Bir Java expression-ının dəyərini hesablayır, onu String-ə çevirir və birbaşa response output stream-inə (out.print(...) kimi) yazır.
    • Kod blokunun sonunda nöqtəli vergül (;) qoyulmur.
    • Scriptlet-lərdə out.println() istifadə etməkdən daha qısa və oxunaqlıdır.
    HTML5
    example/Expressions.jsp
    <p>Current time is: <%= new java.util.Date() %></p>
    <p>Welcome, <%= request.getParameter("user") != null ? request.getParameter("user") : "Guest" %></p>
    <p>Formatted data: <%= formatData("example") %></p>

Directives (<%@ ... %>)

Directive-lər JSP container-a translation phase-də səhifənin necə emal ediləcəyi barədə təlimatlar verir. Onlar runtime-da birbaşa çıxış yaratmırlar.

  • page Directive: Ən çox istifadə olunan directive-dir və səhifə səviyyəsində müxtəlif atributları təyin edir. Bir səhifədə çoxlu page directive-i ola bilər, amma bəzi atributlar (məsələn, language) yalnız bir dəfə təyin edilə bilər. Əsas atributlar:

    • import="package.Class, package.*, ...": Java class-larını import etmək üçün. Birdən çox import vergüllə ayrılır. java.lang.*, javax.servlet.*, javax.servlet.http.*, javax.servlet.jsp.* paketləri avtomatik import edilir.
    • contentType="mimeType; charset=encoding": Göndərilən response-un MIME type-ını və character encoding-ni təyin edir (məsələn, "text/html; charset=UTF-8"). Düzgün encoding (UTF-8) Azərbaycan hərfləri üçün vacibdir.
    • session="true|false": Bu səhifənin HTTP session-larında iştirak edib-etməyəcəyini müəyyən edir. Default dəyəri truedur. Əgər session-a ehtiyac yoxdursa, false təyin etmək performansı artıra bilər. false olduqda, implicit object session mövcud olmur.
    • errorPage="relativeURL": Səhifədə tutulmamış (uncaught) bir exception baş verdikdə, request-in yönləndiriləcəyi səhifəni göstərir.
    • isErrorPage="true|false": Bu səhifənin başqa bir səhifədən yönləndirilən xətaları qəbul edən bir error page olub olmadığını göstərir. Default falsedur. true olarsa, implicit object exception mövcud olur.
    • buffer="none|sizekb": Output stream (out obyekti) üçün buferləmə ölçüsünü təyin edir. Default adətən 8kb olur. none buferləməni ləğv edir (performansa mənfi təsir edə bilər).
    • autoFlush="true|false": Bufer dolduqda avtomatik olaraq client-ə göndərilib-göndərilməyəcəyini təyin edir. Default truedur. false və bufer dolarsa, exception baş verəcək.
    • language="java": İstifadə olunan scripting language-i təyin edir. Hal-hazırda yalnız "java" dəstəklənir və default-dur.
    directives/page-directive.jsp
    <%@ page contentType="text/html; charset=UTF-8"
             import="java.util.ArrayList, com.example.model.User"
             session="true"
             errorPage="/WEB-INF/jsp/error.jsp" %>
  • include Directive: Başqa bir faylın məzmununu (text, HTML, JSP kodu) cari JSP səhifəsinə translation phasedə statik olaraq daxil edir. Daxil edilən faylın məzmunu sanki əsas faylın bir hissəsiymiş kimi emal olunur. Fayl yolu relative olmalıdır.

    • Fərq: <jsp:include> action-ından fərqli olaraq, bu directive faylı yalnız bir dəfə, kompaylasiyadan əvvəl daxil edir. Əgər daxil edilən fayl dəyişərsə, əsas JSP faylının yenidən kompayl olunması lazımdır.
    • Əsasən headers, footers kimi statik və ya təkrar istifadə olunan kod parçaları üçün .jspf (JSP Fragment) faylları ilə birlikdə istifadə olunur.
    directives/include-directive.jsp
    <%@ include file="/WEB-INF/jspf/header.jspf" %>
    <h1>Main Content</h1>
    <%@ include file="/WEB-INF/jspf/footer.jspf" %>
  • taglib Directive: Custom tag libraries (o cümlədən JSTL) istifadə etmək üçün kitabxananı səhifəyə daxil edir. prefix atributu teqləri istifadə edərkən hansı namespace-dən istifadə ediləcəyini, uri isə Tag Library Descriptor (TLD) faylının yerini və ya known URI-ni göstərir.

    directives/taglib-directives.jsp
    <%@ taglib prefix="c" uri="[<http://java.sun.com/jsp/jstl/core>](<http://java.sun.com/jsp/jstl/core>)" %>
    <%@ taglib prefix="fmt" uri="[<http://java.sun.com/jsp/jstl/fmt>](<http://java.sun.com/jsp/jstl/fmt>)" %>
    <%@ taglib prefix="custom" uri="/WEB-INF/tlds/custom.tld" %>

    (JSTL və custom tags haqqında daha sonra ətraflı danışacağıq.)

JSP Implicit Objects

JSP container hər bir JSP səhifəsi üçün (daha doğrusu, onun _jspService metodu üçün) avtomatik olaraq bir sıra obyektləri əlçatan edir. Bu obyektlər scriptlet və expression-lar daxilində birbaşa istifadə edilə bilər.

  • request (javax.servlet.http.HttpServletRequest): Cari HTTP request-i təmsil edir. Parameters, headers, cookies, attributes, session kimi məlumatları əldə etmək üçün istifadə olunur.
  • response (javax.servlet.http.HttpServletResponse): Cari HTTP response-u təmsil edir. Headers təyin etmək, cookies əlavə etmək, redirect etmək üçün istifadə olunur. Birbaşa output stream-ə yazmaq üçün response.getWriter() istifadə edilsə də, adətən out obyekti daha rahatdır.
  • out (javax.servlet.jsp.JspWriter): Response body-sinə məzmun yazmaq üçün istifadə olunan buferlənmiş writer obyekti. println(), print(), newLine() kimi metodları var.
  • session (javax.servlet.http.HttpSession): Cari client üçün session obyektini təmsil edir. İstifadəçi məlumatlarını requests-lər arasında saxlamaq üçün (setAttribute, getAttribute). Yalnız <%@ page session="true" %> (default) olduqda mövcuddur.
  • application (javax.servlet.ServletContext): Bütün web application üçün context-i təmsil edir. Bütün istifadəçilər və requests-lər arasında paylaşılan məlumatları (application scope attributes), initialization parameters-ı saxlamaq və resource-lara çatmaq üçün istifadə olunur.
  • config (javax.servlet.ServletConfig): Cari JSP səhifəsi (generated Servlet) üçün configuration məlumatlarını saxlayır (məsələn, web.xmldə təyin edilmiş init parameters).
  • pageContext (javax.servlet.jsp.PageContext): Bütün digər implicit objects-ə və müxtəlif scopes-lara (page, request, session, application) proqramatik çıxış təmin edən mərkəzi obyektdir. Həmçinin attribute idarəçiliyi, request forwarding və including üçün metodlar saxlayır. Custom tag handlers içərisində çox istifadə olunur.
  • page (java.lang.Object): Cari JSP səhifəsinin instance-ını təmsil edir (this referansı). Nadir hallarda birbaşa istifadə olunur.
  • exception (java.lang.Throwable): Yalnız error page-lərində (<%@ page isErrorPage="true" %>) mövcuddur və orijinal səhifədə baş vermiş exception-ı saxlayır.

JSP Standard Actions (<jsp:...>)

Standard Actions scripting elements-ə XML-əsaslı alternativlər təqdim edir. Onlar daha oxunaqlıdır, presentation logic-i daha yaxşı ayırır və container tərəfindən idarə olunur.

  • <jsp:useBean>: JavaBeans komponentlərini idarə etmək üçün istifadə olunur. Ya mövcud bir bean-i müəyyən bir scope-da tapır, ya da yenisini yaradır.

    • id: Bean-ə JSP səhifəsi daxilində müraciət etmək üçün istifadə olunacaq variable adı.
    • class: Bean-in tam qualified class name-i (əgər yeni instance yaradılmalıdırsa).
    • scope: Bean-in saxlanılacağı və axtarılacağı scope. Dəyərlər: page (default), request, session, application. Container əvvəlcə göstərilən scope-da id ilə bean-i axtarır, tapmazsa yenisini yaradır (class atributu varsa) və həmin scope-a yerləşdirir.
    actions/useBean.jsp
    <jsp:useBean id="user" class="com.example.model.User" scope="session" />
  • <jsp:setProperty>: <jsp:useBean> ilə tapılmış və ya yaradılmış bean-in property-lərini təyin etmək üçün istifadə olunur.

    • name: Hədəf bean-in <jsp:useBean>dəki idsi.
    • property: Təyin ediləcək property-nin adı. Bean-də uyğun setter metodu (məsələn, setPropertyName()) olmalıdır.
    • property="*": Xüsusi dəyərdir. Request parameters-ın adları ilə bean property-lərinin adlarını uyğunlaşdıraraq avtomatik olaraq bütün uyğun property-ləri təyin etməyə çalışır (type conversion avtomatik edilir). Çox güclü, lakin ehtiyatla istifadə edilməlidir.
    • value: Property-yə təyin ediləcək sabit dəyər (String, expression ola bilər).
    • param: Property-nin dəyərini hansı request parameter-dən götürəcəyini göstərir. Əgər paramvalue göstərilməzsə, property adı ilə eyni adda olan request parameter-dən dəyər götürülür.
    actions/setProperty.jsp
    <jsp:useBean id="product" class="com.example.model.Product" scope="request" />
    
    <%-- Set specific property from a request parameter named 'productName' --%>
    <jsp:setProperty name="product" property="name" param="productName" />
    
    <%-- Set specific property with a fixed value --%>
    <jsp:setProperty name="product" property="category" value="Electronics" />
    
    <%-- Set all matching properties from request parameters --%>
    <jsp:setProperty name="product" property="*" />
  • <jsp:getProperty>: Bean-in property-sinin dəyərini əldə edib output-a yazır (getter metodunu çağırır). Nadir hallarda istifadə olunur, çünki EL (Expression Language) daha rahatdır.

    • name: Bean-in idsi.
    • property: Əldə ediləcək property-nin adı.
    actions/getProperty.jsp
    Product Name: <jsp:getProperty name="product" property="name" /><br/>
    Price: <jsp:getProperty name="product" property="price" />
  • <jsp:include>: Başqa bir resource-u (JSP, Servlet, HTML) cari səhifəyə request timeda dinamik olaraq daxil edir. Daxil edilən resource ayrıca emal olunur və onun nəticəsi əsas səhifənin nəticəsinə əlavə edilir.

    • page: Daxil ediləcək resource-un relative URL-i. Runtime expression ola bilər.
    • flush="true|false": Daxil etməzdən əvvəl əsas səhifənin buferini flush edib-etməyəcəyini göstərir. Default falsedur, ancaq true olması bəzi container-larda daha stabil işləyə bilər.
    • Fərq: <%@ include ... %> directive-dən fərqli olaraq, bu action hər request zamanı işləyir və daxil edilən resource-un ən son versiyasını əlavə edir. Bu, daha çox dinamizm təmin edir.
    • Parametrlər <jsp:param> ilə ötürülə bilər.
    actions/include.jsp
    <p>Including dynamic content:</p>
    <jsp:include page="/jsp/dynamicMenu.jsp">
        <jsp:param name="userRole" value="${currentUser.role}" />
    </jsp:include>
  • <jsp:forward>: Cari request-i başqa bir resource-a (JSP, Servlet, HTML) yönləndirir. Yönləndirmə tamamilə server-sideda baş verir, client browser-in xəbəri olmur (URL dəyişmir). Cari səhifənin output buffer-i təmizlənir və icra forward edildiyi yerdə dayanır.

    • page: Yönləndiriləcək resource-un relative URL-i. Runtime expression ola bilər.
    • Parametrlər <jsp:param> ilə əlavə edilə bilər (orijinal request parameters-a əlavə olunur).
    • Əsasən MVC (Model-View-Controller) arxitekturasında Controller-dən (Servlet) View-a (JSP) yönləndirmək üçün istifadə olunur.
    actions/forward.jsp
    <%-- Forwarding example (less common to do this FROM a JSP) --%>
    <jsp:forward page="/WEB-INF/jsp/detailedView.jsp">
        <jsp:param name="productId" value="123" />
    </jsp:forward>
    <%-- Code below this line will NOT be executed --%>

<jsp:param>

<jsp:include><jsp:forward> actions-ları daxilində istifadə olunaraq daxil edilən və ya yönləndirilən resource-a request parameters əlavə etməyə imkan verir.

  • name: Parametrin adı.
  • value: Parametrin dəyəri.

Expression Language (EL): JSP-ni Sadələşdirmək

Scriptlet-lərin yaratdığı qarışıqlıqdan qaçmaq üçün JSP 2.0 ilə birlikdə Expression Language (EL) təqdim edildi. EL, JSP səhifələrindən JavaBeans properties-inə, collections-a, implicit objects-ə və request parameters-a asan və oxunaqlı şəkildə çatmaq üçün nəzərdə tutulmuşdur. Sintaksisi ${expression} şəklindədir. EL, müasir JSP inkişafının əsasını təşkil edir.

  • Əsas Sintaksis: ${...}

  • JavaBeans Property Access: ${beanName.propertyName} (Arxa planda getBeanName().getPropertyName() çağırır).

  • Collection/Array Access: ${myList[0]}, ${myMap.keyName}, ${myMap['key-with-hyphen']}.

  • Implicit Objects (EL için xüsusi):

    • pageScope, requestScope, sessionScope, applicationScope: Müvafiq scope-dakı attributes-ə birbaşa çatmaq üçün (məsələn, ${requestScope.user}). Əgər scope göstərilməzsə (məsələn, ${user}), EL avtomatik olaraq page, request, session, application scopes-larını bu ardıcıllıqla axtarır.
    • param: Request parameters-ə çatmaq üçün (məsələn, ${param.userId}). request.getParameter()ə ekvivalentdir.
    • paramValues: Eyni adda olan çoxsaylı request parameters-i String massivi olaraq əldə etmək üçün (məsələn, ${paramValues.interests[0]}). request.getParameterValues()a ekvivalentdir.
    • header: HTTP request headers-ə çatmaq üçün (məsələn, ${header['User-Agent']}).
    • headerValues: Eyni adda olan çoxsaylı headers-i String massivi olaraq əldə etmək üçün.
    • cookie: Cookies-ə çatmaq üçün (məsələn, ${cookie.userPref.value}). Adı verilən cookie-nin obyektini qaytarır.
    • initParam: Web application-ın deployment descriptor-ında (web.xml) təyin edilmiş context initialization parameters-ə çatmaq üçün (məsələn, ${initParam.adminEmail}). servletContext.getInitParameter()ə ekvivalentdir.
    • pageContext: PageContext obyektinin özünə çıxış verir (məsələn, ${pageContext.request.contextPath} ilə context path-i əldə etmək).
  • Operators:

    • Arithmetic: +, , , / (və ya div), % (və ya mod).
    • Logical: && (və ya and), || (və ya or), ! (və ya not).
    • Relational: == (və ya eq), != (və ya ne), < (və ya lt), > (və ya gt), <= (və ya le), >= (və ya ge).
    • empty: Bir dəyərin null, boş String, boş collection və ya boş map olub olmadığını yoxlayır (məsələn, ${empty param.search}).
    • Conditional: A ? B : C (məsələn, ${user.isAdmin ? 'Admin' : 'User'}).
  • Nümunələr:

    views/el-examples.jsp
    <p>User Name: ${sessionScope.loggedInUser.name}</p> <%-- Accessing bean in session scope --%>
    <p>Product ID from URL: ${param.productId}</p> <%-- Accessing request parameter --%>
    <p>Shopping Cart is empty: ${empty shoppingCart.items}</p> <%-- Using empty operator --%>
    <p>Context Path: ${pageContext.request.contextPath}</p> <%-- Accessing via pageContext --%>
    <p>Total Price: ${order.price * (1 + initParam.taxRate)}</p> <%-- Calculation with init param --%>
  • EL-i Ignor Etmək: Nadir hallarda lazım olsa da, <%@ page isELIgnored="true" %> directive-i ilə səhifədə EL emalını söndürmək olar.

Servlet və JSP İnteqrasiyası: MVC Rəqsi (Ətraflı İzah)

Daha əvvəl də qeyd etdiyimiz kimi, JSP Servlet-ə çevrilir. Ancaq real dünya tətbiqlərində onlar adətən birlikdə, Model-View-Controller (MVC) arxitekturası çərçivəsində işləyirlər:

  • Model: Tətbiqin məlumatlarını və business logic-i saxlayan obyektlər (JavaBeans, POJOs, Entities).
  • View: Məlumatları istifadəçiyə təqdim edən komponent (Adətən JSP + EL + JSTL). View mümkün qədər az logic saxlamalıdır.
  • Controller: Gələn requests-ləri qəbul edən, istifadəçi girişini emal edən, Model-i yeniləyən və nəticəni göstərmək üçün uyğun View-u seçib ona yönləndirən komponent (Adətən Servlet).

Ən Yayılmış Model: Servlet Controller kimi, JSP View kimi

Bu, standart və ən çox tövsiyə edilən yanaşmadır:

  1. Request Gəlir: Client bir URL-ə request göndərir (məsələn, /users?action=list).

  2. Controller (Servlet) Emal Edir: Deployment Descriptor (web.xml) və ya @WebServlet annotation-ı bu URL pattern-ini müvafiq Servlet-ə yönləndirir.

    • Servlet request-i qəbul edir (doGet, doPost metodları).
    • Request parameters-i oxuyur (request.getParameter("action")).
    • Lazımi business logic-i çağırır (məsələn, UserServicedən istifadəçilərin siyahısını alır).
    • Əldə edilmiş məlumatları (Model) request scopeuna attribute olaraq yerləşdirir: request.setAttribute("userList", listOfUsers);.
  3. Controller View-a Yönləndirir (Forward): Servlet RequestDispatcherdən istifadə edərək request-i məlumatları göstərəcək olan JSP səhifəsinə forward edir:

    controller/UsersServlet.java
    // Inside Servlet's doGet/doPost
    List<User> userList = userService.getAllUsers();
    request.setAttribute("userList", userList);
    RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/jsp/userList.jsp");
    dispatcher.forward(request, response);
  4. View (JSP) Məlumatı Göstərir: JSP səhifəsi request scope-dakı məlumatları EL və JSTL istifadə edərək göstərir:

    HTML5
    WEB-INF/jsp/userList.jsp
    <%-- /WEB-INF/jsp/userList.jsp --%>
    <%@ taglib prefix="c" uri="[<http://java.sun.com/jsp/jstl/core>](<http://java.sun.com/jsp/jstl/core>)" %>
    <html>
    <head><title>User List</title></head>
    <body>
      <h1>Users</h1>
      <table>
        <thead><tr><th>ID</th><th>Name</th><th>Email</th></tr></thead>
        <tbody>
          <c:forEach items="${userList}" var="user">
            <tr>
              <td><c:out value="${user.id}" /></td>
              <td><c:out value="${user.name}" /></td>
              <td><c:out value="${user.email}" /></td>
            </tr>
          </c:forEach>
        </tbody>
      </table>
    </body>
    </html>

➡️ /WEB-INF/ Altında JSP-lər: Diqqət edin ki, JSP faylı (/WEB-INF/jsp/userList.jsp) /WEB-INF qovluğunun altında yerləşdirilib. Bu, təhlükəsizlik üçün vacib bir praktikadır. /WEB-INF altındakı resources-lara client browser-dən birbaşa URL ilə çatmaq mümkün deyil. Yalnız server-side yönləndirmə (forward) ilə çatıla bilər. Bu, istifadəçilərin Controller-i bypass edərək birbaşa View-a çatmağının qarşısını alır və MVC axınını qoruyur.

Daha Az Yayılmış Model: JSP İçərisində Servlet Daxil Etmək

<jsp:include page="/path/to/servlet" /> action-ı ilə bir JSP səhifəsi başqa bir Servlet-in output-unu öz məzmununa daxil edə bilər.

  1. Əsas JSP: Səhifənin əsas hissəsini render edir.
  2. <jsp:include>: Müəyyən bir nöqtədə <jsp:include page="/dynamicFragmentServlet" /> çağırılır.
  3. Daxil Edilən Servlet: Request-i alır (əsas JSP-nin requestresponse obyektləri ilə), öz məntiqini icra edir və nəticəni öz response.getWriter()ına yazır.
  4. Nəticə Birləşir: Daxil edilən Servlet-in output-u əsas JSP-nin həmin nöqtədəki output-una əlavə olunur.

İstifadə Sahələri: Bu yanaşma daha az yayılmışdır. Əsasən, səhifənin müəyyən dinamik hissələrini (məsələn, fərdi reklam bloku, dinamik naviqasiya menyusu) ayrı Servlet-lər tərəfindən idarə etmək və onları müxtəlif JSP-lərə daxil etmək üçün istifadə edilə bilər. Ancaq adətən Controller-in bütün məlumatları hazırlayıb tək bir JSP-yə ötürməsi daha təmiz bir həll hesab olunur. Bəzən JSP Fragments (.jspf)custom tags daha yaxşı alternativlərdir.

Forward vs Redirect (Servlet-dən JSP-yə)

  • forward (RequestDispatcher.forward()):
    • Tamamilə server-sideda baş verir.
    • Browser URL-i dəyişmir.
    • Orijinal request obyekti (və onun attributes-i) yeni resource-a ötürülür.
    • Daha sürətlidir (əlavə network roundtrip yoxdur).
    • Adətən Controller-dən View-a məlumat ötürmək üçün istifadə olunur.
  • redirect (response.sendRedirect()):
    • Server, browser-a 302 status kodu və yeni URL göndərir.
    • Browser yeni URL-ə tamamilə yeni bir request göndərir.
    • Orijinal request obyektləri və attributes-i itirilir. Məlumat ötürmək üçün session scope və ya URL parameters istifadə edilməlidir (daha az effektiv).
    • URL browser-da dəyişir.
    • Post-Redirect-Get (PRG) Pattern: Əsas istifadə yeri, bir POST request-indən (məsələn, forma submission-ı) sonra browser refresh-i ilə eyni POST request-inin təkrar göndərilməsinin qarşısını almaqdır. Controller POST-u emal etdikdən sonra GET request-i ilə nəticə səhifəsinə redirect edir.

Advanced Topics və Best Practices

Error Handling

  • <%@ page errorPage="error.jsp" %><%@ page isErrorPage="true" %> directives-lərindən istifadə edərək səhifə səviyyəsində xəta idarəçiliyi. exception obyektini error page-də istifadə etmək.
  • web.xml<error-page> elementləri ilə HTTP status codes (404, 500) və ya exception types üçün global error pages təyin etmək. Bu, daha mərkəzləşdirilmiş bir yanaşmadır.

Security

  • Scriptletlərdən Qaçınmaq: Əsas qayda! EL və JSTL istifadə edin.
  • XSS Prevention: Həmişə <c:out> və ya ekvivalent escaping mexanizmləri ilə istifadəçi tərəfindən daxil edilmiş və ya dinamik məlumatları escape edin.
  • Input Validation: Həm client-side (JavaScript), həm də (daha vacibi) server-side (Servlet/Service layer) validation tətbiq edin. Heç vaxt yalnız client-side validation-a güvənməyin.
  • /WEB-INF/: Bütün JSP view-larını /WEB-INF altına yerləşdirin.
  • CSRF (Cross-Site Request Forgery) Prevention: Formalara unique tokens əlavə edərək və onları server-side-da yoxlayaraq qorunma tətbiq edin.

Performance

  • JSP Compilation: Anlayın ki, JSP-lər ilk request-də (və ya pre-compile edildikdə) Servlet-ə çevrilir. Bu ilk request bir az ləng ola bilər.
  • Session Management: Əgər bir səhifə session-dan istifadə etmirsə, <%@ page session="false" %> ilə onu deaktiv edin. Bu, lazımsız session yaratma overhead-ini aradan qaldırır.
  • include Directive vs Action: Statik məzmun üçün (headers, footers) <%@ include file="..." %> directive-i <jsp:include> action-ından daha performanslıdır, çünki translation phase-də yalnız bir dəfə işləyir.

JSP Fragments (.jspf)

.jspf uzantılı fayllar adətən tam JSP səhifələri deyil, başqa JSP-lərə <%@ include ... %> directive-i ilə daxil edilmək üçün nəzərdə tutulmuş parçalardır. Bu, təkrar istifadə olunan statik markup və ya JSP kod blokları üçün faydalıdır.

JSP və Modern Web Development

Etiraf etmək lazımdır ki, müasir Single Page Applications (SPA) (React, Angular, Vue) və microservices arxitekturalarının yüksəlişi ilə birlikdə, ənənəvi server-rendered JSP-nin istifadəsi bir qədər azalmışdır. Çox vaxt backend (məsələn, Spring Boot, Jakarta EE REST) JSON API-ləri təqdim edir və frontend bu API-ləri istifadə edən ayrı bir JavaScript application olur.

Ancaq JSP hələ də bir çox mövcud Jakarta EE tətbiqlərində, bəzi yeni layihələrdə (xüsusilə server-side rendering-ə üstünlük verildikdə) və Thymeleaf kimi alternativ template engines ilə birlikdə istifadə olunur.

Nəticə

JSP, Java web development-ın vacib bir parçasıdır. Onun lifecycle-ını, müxtəlif elementlərini (scripting, directives, actions), implicit objects-i və xüsusilə də müasir yanaşmalar olan Expression Language (EL)JSP Standard Tag Library-ni (JSTL) dərindən başa düşmək effektiv və maintainable veb tətbiqlər yaratmaq üçün kritikdir. Servlet-lərlə düzgün inteqrasiya (xüsusilə MVC pattern-i çərçivəsində) və /WEB-INF/ kimi təhlükəsizlik praktikaları da unudulmamalıdır.

Scriptlet-lərdən qaçınmaqEL/JSTL-ə fokuslanmaq sizi daha təmiz, oxunaqlı və idarə edilə bilən presentation layer-ə aparacaq.

Thanks for reading.