Java Servlety

CGI programy jsou ponekud tezkopádné (zvlást v Jave). Proto pro Javu existuje lepsí zpusob - servlety. Jednoduchý servlet:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class HelloWorld extends HttpServlet
{
   public void doGet
      (HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException
   {
      PrintWriter out;
      String title = "Simple Servlet Output";

      response.setContentType("text/html");

      out = response.getWriter();
      out.println("<?xml version=\"1.0\" encoding=\"iso-8859-2\"?>");
      out.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"");
      out.println("    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
      out.println("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
      out.println("<head>");
      out.println("<meta http-equiv=\"content-type\"");
      out.println("    content=\"text/html; charset=iso-8859-2\" />");
      out.println("<title>Sample Servlet</title>");
      out.println("</head>");
      out.println("<body>");
      out.println("<h1>Hello World!</h1>");
      out.println("</body>");
      out.println("</html>");
   }
}
Nyní uz ovsem potrebujeme server, který si s Javou rozumí, napríklad Apache Tomcat. Potom stací zadat http://localhost:8080/HelloWorld a dostaneme patricný výstup.
Ocividne jsme se stále nevyhnuli kostrbaté produkci výstupu. Síla servletu tkví ale jinde. Trídy HttpServletRequest, resp. HttpServletResponse, zapouzdrují data putující od klienta, resp. k nemu. Metoda HttpServletRequest.getParameter vrátí hodnotu parametru (at uz slo o predání dat metodou GET nebo POST). Pro rucní zpracování slouzí metody HttpServletRequest.getQueryString (pro GET) a HttpServletRequest.getReader (pro POST, pokud cekáme textová data) nebo HttpServletRequest.getInputStream (pro POST, pokud cekáme binární data). Pro odeslání textových dat slouzí HttpServletResponse.getWriter, pro odeslání binárních HttpServletResponse.getOutputStream.
Príklad: výpis HTTP hlavicek:
Enumeration headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
   String headerName = (String) headerNames.nextElement();
   out.print("<tr><td>" + headerName + "</td>");
   out.println("<td>" + request.getHeader(headerName) + "</td></tr>");
}
Príklad - výpis príchozích formulárových dat:
Enumeration paramNames = request.getParameterNames();
while (paramNames.hasMoreElements()) {
   String paramName = (String) paramNames.nextElement();
   out.print("<tr>\n<td>" + paramName + "</td>\n<td>");
   String[] paramValues = request.getParameterValues(paramName);
   if (paramValues.length == 1) {
      String paramValue = paramValues[0];
      if (paramValue.length() == 0) out.print("<em>No Value</em>");
      else out.print(paramValue);
   }
   else {
      out.println("\n<ul>");
      for(int i=0; i < paramValues.length; i++) {
         out.println("<li>" + paramValues[i] + "</li>");
      }
      out.println("</ul>");
   }
   out.println("</td></tr>");
}
Samotný zivot servletu má tri fáze: inicializace (metoda init), zpracovávání klientských pozadavku (metody doGet a doPost - ve skutecnosti jsou tyto metody automaticky volány pomocí metody service, kterou muzeme, ale nemusíme, predefinovat) a úklid (metoda destroy). Metoda init je vhodná pro cinnosti jako spojení s databází, otevrení souboru, v metode destroy se obvykle delá opak.

Sessions

Protokol HTTP je bezstavový, tudíz kazdý klientský pozadavek je zcela samostatný a nijak nesouvisí s tím predchozím. Coz je v mnoha prípadech velmi nepríjemné (napr. autentifikace). Resením jsou takzvané HTTP sesssions. Objekt trídy HttpSession vytvoríme metodou HttpServletRequest.getSession, jako parametr jí predáme konstantu true, která zajistí, ze pokud session spojená s tímto klientem neexistuje, bude vytvorena. Poté do promenné typu HttpSession muzeme pomocí retezcového klíce ukládat hodnoty libovolné promenné metodou putAttribute (napr. putAttribute("customer_details", custDetails)) nebo tyto hodnoty zase vyzvedávat (typicky na dalsí stránce nasí webové aplikace) metodou getAttribute - je ovsem treba provést explicitní pretypování: custDetails = (Customer) session.getAttribute("customer_details"). Ke zrusení session (napr. pri odhlásení uzivatele) slouzí metoda invalidate.
Sessions jsou implementovány pomocí cookies. Ty nemusí prohlízec umet nebo je mohl uzivatel zakázat. Existuje i jiná moznost, jak sessions implementovat - predáváním session ID v rámci URL. Pro pouzití tohoto mechanismu je potreba vsechny odkazy prohnat metodou HttpServletResponse.encodeURL.
Bezpecnostním poznámka: session ID je relativne snadno ukradnutelné, pro zvýsení bezpecnosti je výhodnejsí obejít standardní prostredky a implementovat sessions vlastnorucne - speciální tabulkou pro sessions v databázi, kde bude ulozeno session ID, cas posledního prístupu (pro moznost autoexpirace, nekterí uzivatelé povazují tlacítko Logout za zbytecný pedantismus), IP adresu a prípadne dalsí informace; pro samotné predávání session ID lze zvolit bud cookies nebo prídavný parametr v URL (tím se sice nevyhneme moznosti ukradnutí session ID, ale útocník by musel falsovat i IP adresu, coz uz predstavuje výrazne vetsí problém).

Cookies

Trída Cookie obsahuje konstruktor Cookie(String key, String value). Vytvorené cookie lze nastavovat dalsí vlastnosti (casovou platnost, platnost pro konkrétní doménu, prípadne cestu v rámci ní, …). Pro pridání nasí cookie do HTTP hlavicky je potreba zavolat metodu HttpServletResponse.addCookie(Cookie cookie). Naopak k vyzvednutí cookies slouzí metoda HttpServletRequest.getCookies, která vrací Cookies[].