%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%
%% :Servlets
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\section{Java Servlety} \label{Servlets}

Nejzákladnější technologií pro programování dynamických webových stránek v~Javě jsou \emph{servlety}. Servlet je třída zděděná z~třídy \texttt{HttpServlet} z~balíčku \texttt{javax.servlet.http}. Pro požadované chování musíme přepsané metody \texttt{doGet}, \texttt{doPost},... (ostatní názvy metod se znalostmi HTTP určitě snadno odhadnete). Příklad ukazuje kostru servletu aplikace kurzovního lístku.

\begin{Verbatim}
public class ExchangeListServlet extends HttpServlet \{

    @Override
    protected void doGet(HttpServletRequest request, 
        HttpServletResponse response)
            throws ServletException, IOException \{

    \}
\}
\end{Verbatim}





\subsection{Servlet kontejner}

Servlety v~rámci jedné webové aplikace jsou spravovány tzv. \emph{servlet kontejnerem} (servlet container), který je součástí každého Javovského serveru (Tomcat, JBoss a~další). Servlet kontejner zachytává příchozí HTTP požadavky a~pro každý vybere příslušný servlet, kterým má být ten který požadavek zpracován. Tento výběr probíhá na základě porovnávání celkové URI požadavku. Často bývají webové aplikace navrženy tak, že mají pouze jeden servlet. V~takovém případě pak všechny požadavky směřují pouze na tento jeden servlet. 

Jakmile je známo, kterým servletem má být požadavek zpracován, servlet kontejner sestaví objekty třídy \texttt{HttpServletRequest} a~vyplní jeho atributy na základě tohoto požadavku (název metody, položky hlavičky, tělo, atd.). Dalším objektem, který servlet kontejner vyrobí je instance třídy \texttt{HttpServletResponse}. Ta obsahuje hlavně referenci na proud (stream) pro zapisování odpovědi. Teď už jen stačí zavolat metody \texttt{doGet} pokud byl požadavek typu \texttt{GET} (obdobně pro ostatní HTTP metody) příslušného servletu a~jako parametry předat zmíněné dva objekty.




\subsection{Tisknutí HTML kódu}

Teď se nacházíme v~situaci, kdy byla zavolána metoda \texttt{doGet} servletu. Klasickým tělem metody \texttt{doGet} bývá získání reference na výstupní proud (ten nám připravil servlet kontejner jako součást objektu \texttt{HttpServletResponse}) a~vytisknutí HTML kódu do tohoto proudu. Tištění do výstupního proudu je obdobné, jako tištění do konzole konstrukcí \texttt{System.out.println}. Příklad ukazuje, jak získat objekt výstupního proudu a~vytisknout do něj HTML kód(prozatím statické) stránky. Pro jednoduchost je HTML kód omezen na minimum.

\begin{Verbatim}
public class ExchangeListServlet extends HttpServlet \{

    @Override
    protected void doGet(HttpServletRequest request, 
        HttpServletResponse response)
            throws ServletException, IOException \{

        \codeHighlight{response.setContentType("text/html;charset=UTF-8");}
        \codeHighlight{PrintWriter out = response.getWriter();}
        \codeHighlight{try \{}
        \codeHighlight{    out.println("<html>");}
        \codeHighlight{    out.println("<body>");}
        \codeHighlight{    out.println("<h1>Kurzovní lístek</h1>");}
        \codeHighlight{    out.println("</body>");}
        \codeHighlight{    out.println("</html>");}
        \codeHighlight{\} finally \{ }
        \codeHighlight{    out.close();}
        \codeHighlight{\}}
    \}
\}
\end{Verbatim}




\subsection{Dynamický kód v~servletech}

Nyní přichází na řadu dynamický charakter servletů. Mezi řádky tisknutí obyčejného HTML kódu je možné provádět jakýkoliv kód v~jazyce Java. Také je možné pomocí výstupního proudu tisknout jakékoliv výsledky takového kódu. Příklad ukazuje, jak zavolat přepočet do jiné měny pomocí třídy \texttt{ExchangeList}. Předpokládáme, že HTTP požadavek obsahuje tři query parametry --- \texttt{from} (vstupní měna), \texttt{to} (výstupní měna) a~\texttt{amount} (částka, která se má převést). Tyto parametry lze získat z~objektu \texttt{request} pomocí metody \texttt{getParameter}. Příklad ukazuje, jak parametry přečíst, zpracovat a~jak vytisknout výsledek přepočtu.

\begin{Verbatim}
public class ExchangeListServlet extends HttpServlet \{

    @Override
    protected void doGet(HttpServletRequest request, 
        HttpServletResponse response)
            throws ServletException, IOException \{

        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try \{
            \codeHighlight{String from = request.getParameter("from");}
            \codeHighlight{String to = request.getParameter("to");}
            \codeHighlight{double amount = Double.parseDouble(}
            \codeHighlight{       request.getParameter("amount"));}

            \codeHighlight{ExchangeList exchange = new ExchangeList();}
            \codeHighlight{double result = exchange.calculate(amount, from, to);}

            out.println("<html>");
            out.println("<body>");
            out.println("<h1>Kurzovní lístek</h1>");
            \codeHighlight{out.println("Po přepočtu:");}
            \codeHighlight{out.println(result);}
            \codeHighlight{out.println(to);}
            out.println("</body>");
            out.println("</html>");
        \} finally \{
            out.close();
        \}
    \}
\}
\end{Verbatim}





\subsection{Cyklus servletu}

Na server dorazí HTTP požadavek. Příklad ukazuje požadavek na přepočet 500 českých korun na eura.

\begin{Verbatim}
GET /exchange?amount=500\&from=CZK\&to=EUR HTTP/1.1
Host: www.exchange-list.com
Accept: text/html

\end{Verbatim}

Servlet kontejner si přečte cestu ke zdroji (v~příkladu \emph{/exchange}). Podle ní vybere správný servlet (přiřazení adres k~servletům bude popsáno v~kapitole \ref{Deployement}) a~vytvoří jeho instanci. Dále servlet kontejner sestaví z~požadavku objekt typu \texttt{HttpServletRequest} a~uloží do něj všechny potřebné informace jako pole hlavičky nebo query. Poté se podívá, že HTTP metoda požadavku je \texttt{GET} a~proto na instanci servletu zavolá metodu \texttt{doGet}. Servlet v~těle metody získá instanci výstupního proudu a~začne tisknout. Jakmile je proud uzavřen, odešle server HTTP odpověď uživateli. Celý cyklus ukazuje obrázek \ref{Servlet Cycle Figure}.

\begin{figure}[ht]
  \centerline{\includegraphics[height=80mm]{images/servlet_cycle.png}}
  \caption{Cyklus servletu.}
  \label{Servlet Cycle Figure}
\end{figure}




\subsection{Závěr}

Tvoření dynamických webových stránek pomocí servletů může být velmi pracné, výsledný kód v~Javě pak těžko čitelný. Velké stránky budou obsahovat velké množství textu, který je potřeba všechen ručně vytisknout. Navíc s~velikostí stránky roste šance na chybu v~HTML syntaxi jako je neuzavření párového tagu. Změnit později obsah stránky může být stejně pracné, jako u~statických webových stránek. Dnes již existují lepší přístupy, jak tvořit dynamické stránky, všechny jsou ovšem založeny na technologii servletů. I~když se v~praxi s~kódem servletu nikdy nemusíte setkat, je dobré vědět, jak fungují. Jenom pak můžete snadno a~dobře pochopit, jak fungují technologie jako JSP a~Struts, které si představíme za chvíli.

Použitá literatura:\\
\cite{Java Server Pages} \emph{Java Server Pages}\\
\cite{Programujeme Jakarta Struts} \emph{Programujeme Jakarta Struts}\\

