V predchádzajúcej časti sme načali problematiku spolupráce servletov medzi sebou navzájom a medzi servletmi a ostatnými zdrojmi webovej aplikácie. Zaoberali sme sa špeciálnym typom filtrovania a reťazenia servletov a presmerovaním odpovede na iný servlet či stránku JSP. Na koniec sme si ukázali niektoré častejšie používané typy stavových HTTP kódov. Dnes budeme v načatej problematike pokračovať.

Request dispatching

Keď vytvárate aplikáciu pre web, často je užitočné používať mechanizmus, ktorý zabezpečí predanie spracovania požiadavky na iný servlet, alebo ktorý zahrnie výstup z iného servletu do svojej vlastnej odpovede. Práve na tento účel sa môže využiť rozhranie javax.servlet.RequestDispatcher definujúce objekt, ktorý obdrží požiadavku od klienta a pošle ju inému zdroju na ďalšie spracovanie.

Rovnako ako pri mechanizme presmerovaní odpovede aj tu musí byť URL požadovaného zdroja pre servlet dostupné. Objekt implementujúci vyššie uvedené rozhranie môžete získať cez ServletContext prostredníctvom metódy getRequestDispatcher("URL"). Táto metóda vyžaduje parameter začínajúci na „/“ predstavujúci relatívnu cestu k požadovanému aktívnemu zdroju (servlet alebo JSP).

Objekt RequestDispatcher môžeme použiť dvoma spôsobmi:

  1. RequestDispatcher:forward(request, response)
    Metóda forward() akceptuje dva parametre – požiadavku a odpoveď. Tieto objekty sú predané externému zdroju na ďalšie spracovanie. Inými slovami táto metóda odovzdáva zodpovednosť za spracovanie požiadavky a vytvorenie odpovede inému servletu či JSP. Podľa špecifikácie je nesprávne použiť túto metódu vtedy, ak už bol vytvorený odkaz na objekt PrintWriter, ktorý je zodpovedný za odoslanie odpovede. Určitou črtou tejto metódy je, že servlet (JSP), ktorému predávame riadenie môže nastaviť vlastné hlavičky v odpovedi klientovi.
  2. RequestDispatcher:include(request, response)
    Metóda include() zabezpečí vloženie odozvy zavolaného zdroja (servletu) do vlastnej odpovede. Je to strašne krkolomne povedané, ale rýchlo to pochopíte z príkladov. Na rozdiel od predchádzajúcej metódy forward(), je možné mať „otvorený“ objekt PrintWriter vopred (viď príklad). Tiež platí, že volaný servlet nemôže nastaviť vlastné hlavičky, za to je zodpovedný východzí servlet.

V oboch prípadoch použitia objektu RequestDispatcher, zostáva objekt request predstavujúci požiadavku od klienta, k dispozícii volanému zdroju. Je dôležité si zapamätať, že v prípade použitia metódy forward() musíte každý zápis na výstup (do objektu response) vykonať až v zdroji, ktorému ste predali riadenie. Ak použijete druhú metódu, môžete zapisovať v oboch objektoch, ale hlavičky je možné nastaviť len v prvom z nich.

Vytvorme si niekoľko ukážkových príkladov na použitie obidvoch metód. V prvom výpise je servlet, ktorý je volaný zo stránky JSP alebo HTML po vyplnení formulára. Po obdržaní požiadavky je ďalšie spracovanie presmerované na druhý servlet v poradí. V reálnej aplikácii by ste mohli napríklad najprv načítať niektorý parameter (request.getParameter("string")) a následne na základe jeho hodnoty presmerovať riadenie na konkrétny zdroj.

FormDispatcherForward.java

package interval;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class FormDispatcherForward extends HttpServlet {
  public void doPost(HttpServletRequest req, HttpServletResponse res)
                             throws ServletException, IOException {
      RequestDispatcher rd = getServletContext().getRequestDispatcher
                             („/servlet/interval.DispatcherForward„);
      rd.forward(req, res);
  }
}

DispatcherForward.java

package interval;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class DispatcherForward extends HttpServlet {
  public void doGet(HttpServletRequest req, HttpServletResponse res)
                             throws ServletException, IOException {
      res.setContentType(„text/html“);<
      PrintWriter out = res.getWriter();
      out.println(„<HTML><BODY>Start of FORWARDED request“);
      out.println(„<P>Hi “ + req.getParameter(„firstname“));
      out.println(„<BR>I see you are a “ + req.getParameter(„title“));
      out.println(„<P>End of request</BODY></HTML>“);
      out.close();
  }
}

Druhý príklad v poradí ilustruje použitie metódy include(). Všimnite si, že v príklade sú dodržané pravidlá, ktoré som spomenul v súvislosti s použitím tejto metódy (nastavenie hlavičiek a zápis na výstup).

FormDispatcherInclude.java

package interval;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class FormDispatcherInclude extends HttpServlet {
  public void doPost(HttpServletRequest req, HttpServletResponse res)
                             throws ServletException, IOException {
      res.setContentType(„text/html“);
      PrintWriter out = res.getWriter();
      out.println(„<HTML><BODY>Start of INCLUDED request“);
      out.println(„<P>Hi “ + req.getParameter(„firstname“));
      out.flush();
      RequestDispatcher rd = getServletContext().getRequestDispatcher
                             („/servlet/interval.DispatcherInclude„);
      rd.include(req, res);
      out.println(„<P>End of request</BODY></HTML>“);
      out.close();
  }
}

Pred začlenením externého zdroja, ktorý zapisuje na výstup, musíte „vyprázdniť“ objekt out metódou flush().

DispatcherInclude.java

package interval;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class DispatcherInclude extends HttpServlet {
  public void doGet(HttpServletRequest req, HttpServletResponse res)
                             throws ServletException, IOException {
      PrintWriter out = res.getWriter();
      out.println(„<HR>I see you are a “ + req.getParameter(„title“));
      out.println(„<P>End of include<HR>“);
  }
}

Využitie externých zdrojov – priamy prístup

Pri request dispatchingu môžeme presmerovať riadenie iba na iný aktívny zdroj webovej aplikácie (servlety a JSP). To všetko v prípade ak chceme a potrebujeme využiť objekty request a response. Môžeme však presmerovať užívateľa aj na pasívny zdroj, teda na HTML stránku. Niekedy alebo niekomu však môže vyhovovať možnosť pristupovať k externým zdrojom priamo.

Do verzie Java Servlets API 2.0 vrátane bolo možné pristupovať priamo aj k servletom z iných servletov. Bola na to určená metóda ServletContext:getServlet("string"). Od verzie API 2.1 je táto metóda deprecated bez náhrady. Znamená to, že k servletom nie je možné pristupovať priamo. Ak tú metódu použijete, vráti vám NULL.

Priamo pristupovať však môžete k HTML stránkam prostredníctvom objektu ServletContext. Tento objekt to umožňuje dvoma spôsobmi: cez getResource() a getResourceAsStream().

  1. getResource(java.lang.String path)
    Táto metóda vráti objekt typu java.net.URL ukazujúci na zdroj mapovaný pod definovanou cestou (path). Použitie ukážem na príklade.
  2. getResourceAsStream(java.lang.String path)
    Metóda vráti objekt typu java.io.InputStream. Následne s ním môžeme priamo manipulovať pričom použitie bude ukázané na príklade.

V príklade servletu, ktorý som nazval ExternalResource ukážem ako môžeme využiť objekt ServletContext. V uvedenom príklade pristupujeme k súboru HTML, ktorého výpis je uvedený nižšie. Na súbor sa odkazujeme cez objekt URL prostredníctvom metódy getResource() a použijeme tiež metódu getResourceAsStream().

ExternalResource.java

package interval;
import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ExternalResource extends HttpServlet {
  public void doGet(HttpServletRequest req, HttpServletResponse res)
                             throws ServletException, IOException {
      res.setContentType(„text/html“);
      PrintWriter out = res.getWriter();
      out.println(„<HTML><TITLE>ExternalResource</TITLE></BODY>“);
      out.println(„<H2>Servlet Example – ExternalResource</H2><HR>“);
      ServletContext sc = getServletContext();
      URL url = sc.getResource(„Resource.html“);
      out.println(„URL name: “ + url.getFile());
      out.println(„<HR>Now the input file html:“);
      BufferedReader in = new BufferedReader(new
            InputStreamReader(sc.getResourceAsStream(„Resource.html“)));
      String str;
      while ((str = in.readLine()) != null)
            out.println(str);
      in.close();
      out.println(„<HR></BODY></HTML>“);
      out.close();
  }
}

Resource.html

<HTML>
<HEAD>
  <TITLE>Servlet Examples – ResourceHandlerHTML</TITLE>
</HEAD>
<BODY>
  <H4>Hello everybody. I’m external resource HTML.</H4>
</BODY>
</HTML>

To by bolo z dnešnej časti všetko. Pozreli sme sa bližšie na servlet dispatching. Pri tomto mechanizme riadenia aplikácie je treba zachovať niekoľko zásad ohľadom vytvárania hlavičiek a zapisovania na výstup. V druhej časti sme načrtli možnosti priameho prístupu k statickým HTML zdrojom webovej aplikácie. V budúcej časti si možnosti interakcie a zdieľania objektov a zdrojov dokončíme.

Žádný příspěvek v diskuzi

Odpovědět