Úvod do webových aplikací: Porovnání verzí

Z FI WIKI
Přejít na: navigace, hledání
m (Úvod: malá úprava větný stavby)
m (Úvod: upřesnění formulace)
Řádka 31: Řádka 31:
 
Při tvorbě aplikací pro širokou veřejnost je dobré vystačit si s čistým HTML, kvůli nevidomým uživatelům, zobrazení na mobilech, případně možnosti tisku stránek.  
 
Při tvorbě aplikací pro širokou veřejnost je dobré vystačit si s čistým HTML, kvůli nevidomým uživatelům, zobrazení na mobilech, případně možnosti tisku stránek.  
  
Poslední dobou je trendem tzv. '''AJAX''', jde o tvorbu aplikací běžících v prohlížeči v JavaScriptu. Chovají se podobně jako desktopové aplikace s GUI. Mají jistě své místo, ale je třeba zvážit, že jdou proti principu WWW, jímž je '''adresovatelnost zdrojů''' pomocí URL.
+
Poslední dobou je trendem tzv. '''AJAX''', jde o tvorbu aplikací běžících v prohlížeči v JavaScriptu. Chovají se podobně jako desktopové aplikace s GUI. Mají jistě své místo, ale je třeba zvážit jejich použití a mít na paměti, že jdou proti principu WWW, jímž je '''adresovatelnost zdrojů''' pomocí URL.
  
 
== Webové aplikace na platformě Java ==
 
== Webové aplikace na platformě Java ==

Verze z 16. 4. 2010, 10:33


Webové aplikace jsou probírány podrobně v předmětu PA165, pro který existují podrobně zpracované materiály pod heslem Kategorie:Webové aplikace.

V předmětu PV168 není prostor probrat webové aplikace dostatečně podrobně. Podobně jako se v semináři probírá JDBC, a ORM nástroje jsou nechány do předmětu PA165, probereme zde jen pevné základy, které se v čase nemění, a různé nadstavby a frameworky, jejichž obliba se mění z roku na rok, ponecháme do PA165.

Tato stránka obsahuje stručnou teorii a tři praktické ukázky, a měla by vystačit na jeden dvouhodinový seminář.

Úvod

Webové aplikace jsou aplikace, kde uživatelským rozhraním je webový prohlížeč. Mají tři obrovské výhody oproti ostatním typům aplikací (desktopové, mobilní, příkazový řádek):

  • uživatel nemusí nic instalovat
  • vývojář se stará jen o jednu verzi aplikace
  • u správně napsaných aplikací existují adresy URL do částí aplikace, např. lze někomu jinému poslat odkaz na stránku s popisem určitého zboží

Sepišme si, co máme k dispozici na straně klienta:

  • ve 100 % případů máme HTML s hyperlinky a formuláři
  • v asi 95 % případů máme JavaScript, a můžeme s ním manipulovat HTML formuláře
  • většinou máme k dispozici Cookies pro ukládání stavu v prohlížeči
  • obvykle máme DOM (Document Object Model) a CSS (Cascading Style Sheets), které lze manipulovat JavaScriptem
  • většinou máme Flash plugin (animovaná vektorová grafika a multimédia, viz YouTube) (98% verze 9)
  • obvykle máme možnost použít Java applety, ale jen na úrovni pokaženého JDK 1.1
  • někdy lze použít Java Web Start pro nastartování desktopové aplikace

Pragmaticky má smysl používat to nejrozšířenější, tj. HTML s CSS a JavaScriptem, zajímavou možností se stává i Flash (s vývojovým nástrojem Flex).

Při tvorbě aplikací pro širokou veřejnost je dobré vystačit si s čistým HTML, kvůli nevidomým uživatelům, zobrazení na mobilech, případně možnosti tisku stránek.

Poslední dobou je trendem tzv. AJAX, jde o tvorbu aplikací běžících v prohlížeči v JavaScriptu. Chovají se podobně jako desktopové aplikace s GUI. Mají jistě své místo, ale je třeba zvážit jejich použití a mít na paměti, že jdou proti principu WWW, jímž je adresovatelnost zdrojů pomocí URL.

Webové aplikace na platformě Java

Platforma Java je pro tvorbu serverové části webových aplikací poměrně vhodná, oproti např. PHP umožňuje psát snadněji udržovatelné aplikace, dobře škáluje, má skvěle zvládnutou internacionalizaci.

Cenou je o něco náročnější učení.

Základem serverové části webových aplikací na platformě Java jsou tzv. Servlety, což jsou třídy obsluhující požadavky HTTP protokolu. Ty tvoří nejnižší vrstvu, nad kterou pak existují další nadstavby. Dalšími vrstvami jsou

  • Java Server Pages (JSP) - obdoba PHP a dalších server-side scripting nástrojů
  • Web Application Frameworks - rámce pro tvorbu složitějsích aplikací
    • rámce pro šablony stránek (Freemarker, WebMacro, Velocity, JSP+JSTL)
    • rámce pro řízení průchodu aplikací (Stripes, Struts)
    • rámce pro tvorbu stránek z komponent (Tapestry, WebWork, JSF)

Rozhraní servletů se časem téměř nemění, naopak webové aplikační rámce podléhají rychlému vývoji i módě.

Managed environment

U servletů se poprvé setkáváme s pojmem managed environment. Servlety nejsou spustitelné aplikace, jak jsme byli dosud zvyklí, ale "žijí" uvnitř určitého prostředí, zvaného servlet container. Podobně například aplikace do mobilních telefonů, tzv. midlety, žijí uvnitř prostředí poskytovaného mobilním telefonem.

Servlet container vytváří instance servletů, při příchodu HTTP požadavků zpracuje příchozí data a volá metody servletů, vygenerovanou odpověd zasílá prohlížeči, a při ukončení aplikace servlety ruší.

Je definováno rozhraní mezi servlet containerem a webovou aplikací tvořenou servlety, tzv. Servlet API, které má různé verze, v současnosti se používají verze 2.4 a 2.5.

Existují různé implementace servlet containerů, např. Apache Tomcat, Jetty, JRun. Dále pak každý server odpovídající specifikaci Java Enterprise Edition musí obsahovat servlet container, např. BEA WebLogic, Oracle Application Server, IBM WebSphere a další.

Díky jednotnému API je možné psát aplikace nezávislé na konkrétním servlet containeru, a tutéž aplikaci používat v servlet containerech různých výrobců.

(Stejně tak je možné psát mobilní aplikace použitelné v každém mobilu podporujícím Midlet API.)

Servlet API

Servletem je každá Java třída, která implementuje interface javax.servlet.Servlet. Protože ale z praktického hlediska má smysl uvažovat pouze servlety obsluhující protokol HTTP, je důležitější vědět, že HTTP servletem je každá třída, která je potomkem třídy javax.servlet.http.HttpServlet.

Obsluha HTTP požadavků servlety je popsána v JavaServlets#Obsluha HTTP pomocí servletů, nemá smysl ji sem opisovat, prosím přečtete si ji tam.

Servlety jsou organizovány do tzv. aplikací, kdy skupina servletů je sdružena v jednom balíčku s příponou .war, což je soubor typu .jar (tedy ZIP archiv). V něm musí být přítomen soubor WEB-INF/web.xml, který popisuje konfiguraci aplikace, zejména mapování URL na servlety.

Podrobnosti viz část JavaServlets#Webová aplikace a kontext servletu, prosím přečtěte si ji.

Důležitá věc, kterou Servlet API poskytuje, je session. Jedná se vlastně o HashMap, do které je možné si ukládat hodnoty mezi jednotlivými požadavky od stejného prohlížeče. Session je udržována pomocí cookies, nebo v případě vypnutých cookies je její identifikátor přidáván do všech generovaných URL.

Praktická ukázka

Teď je asi vhodný čas zkusit si vytvořit servlet.

V NetBeans vytvořte nový projekt typu Web Application (File - New project - Categories: Web - Projects: Web Application). Server zvolte Tomcat 6, Java EE Version zvolte JavaEE 5.

V projektu vytvořte nový servlet zvaný UkazkovyServlet. Pravým tlačítkem klikněte na Source packages, dejte New - Other - Categories: Web - File Types: Servlet, Class Name dejte UkazkovyServlet a package dejte cz.muni.fi.pv168. Je nutné zvolit nějaký package, jinak nebude servlet spustitelný !!! Ponechte nabídnuté nastavení mapování servletu a potvrdte vytvoření servletu.

Naeditujte text do následující podoby:

 
package cz.muni.fi.pv168;
 
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
 
public class UkazkovyServlet extends HttpServlet {
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
 
        try {
            int n = 10;
            String np = request.getParameter("n");
            if(np!=null) n = Integer.parseInt(np);
        
            for(int i=0;i<n;i++) {
                out.println("i="+i+"<br/>");
            }
        } finally {
            out.close();
        }
    } 
    
}

Pozor, NetBeans se snaží skrýt metody doGet() a doPost() do sbaleného bloku, nenechte se tím zmást.

Spusťte aplikaci. Servlet zavoláte na URL http://localhost:8084/WebApplication1/UkazkovyServlet.

Můžete přidat parametr n pomocí http://localhost:8084/WebApplication1/UkazkovyServlet?n=6.

JSP

Psát delší sekvence HTML v servletech je poměrně nepohodlné, proto každý servlet container poskytuje tzv. Java Server Pages - JSP.

Jedná se o psaní servletů naruby - každý soubor s příponou .jsp je před spuštěním konvertován na servlet, který je za běhu překompilován a spuštěn.

Do JSP lze psát přímo Java kód, tzv. scriptlety:

  • běžný kód je možné psát mezi znaky <% a %>, je umístěn do metody service() servletu
  • tisk výrazu lze napsat pomocí <%= a %>, je to ekvivalentní <%out.print(vyraz)%>
  • kód mimo metodu service() lze napsat pomocí <%! a %>.

Podrobná dokumentace viz JSP 1.2 syntax card.

Nejlépe je to vidět na ukázce.

Praktická ukázka

Vymažte ve vytvořeném projektu obsah souboru index.jsp, a nahradte ho následujícím:

 
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
 
<%! //kód mimo metodu service()
   public String prictiJedna(String a) {
       return Integer.toString(Integer.parseInt(a)+1);
   }
%>
<html>
<body>
  <%  //kód uvnitř metody service()
      if(request.getMethod().equals("GET")) {
  %>
  <form method="post">
      Zadejte číslo: <input name="cislo" value="">
      <input type="submit" >
  </form>
  <%
      } else if (request.getMethod().equals("POST")) {
          String cislo = request.getParameter("cislo");
          String plusjedna = prictiJedna(cislo);
   %>
      Výsledek <%out.println(cislo);%> + 1 je <%=plusjedna%> 
  <%
      }
  %>
</body>
</html>

a spusťte aplikaci.

JSTL a knihovny značek

Psaní scriptletů je nedoporučovaný způsob, protože takto vytvořené programy mají stejnou nectnost jako PHP programy - špatně se udržují.

Lepší je rozdělit aplikaci na část zpracovávající data, a část zobrazující data, tzv. MVC architektura. JSP se pak používají pouze pro zobrazení dat, a místo scriptletů se používá knihovna JSTL (JSP Standard Tag Library).

Podrobnosti viz Java Server Pages#Použití JSP.

Praktická ukázka

Přidejte do projektu knihovnu JSTL 1.1. Klikněte pravým tlačítkem na Librarries - Add Library - JSTL 1.1.

Vytvořte v projektu nový servlet, např. UkazkaJSTL.

Upravte ho na následující obsah:

 
package cz.muni.fi.pv168;
 
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
 
public class UkazkaJSTL extends HttpServlet {
    
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
 
        Map<String, Object> m = new TreeMap<String, Object>();
        
        for(Locale l :Locale.getAvailableLocales()) {
            Map<String, Object> v = new HashMap<String, Object>();
            v.put("name", l.getDisplayName());
            v.put("origname", l.getDisplayName(l));
            v.put("loc", l);
 
            m.put(l.toString(), v);
        }
        request.setAttribute("jazyky", m);
        
        request.getRequestDispatcher("/stranka.jsp").forward(request, response);
    } 
 
}

Vytvořte nový soubor stranka.jsp. Klikněte pravým tlačítkem na Web Pages - New - JSP, pozor jméno zadejte bez přípony .jsp !

 
<%@page contentType="text/html;charset=utf-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
    <body>
 
    <table border="1">
    <c:forEach items="${jazyky}" var="j">
        <tr>
            <td><c:out value="${j.key}"/></td>
            <td><c:out value="${j.value.name}"/></td>
            <td><c:out value="${j.value.origname}"/></td>
            <td><c:out value="${j.value.loc.ISO3Language}"/></td>
            
        </tr>    
    </c:forEach>
    </table>
 
    </body>
</html>

Spusťte aplikaci a zavolejte tento nový servlet na URL http://localhost:8084/WebApplication1/UkazkaJSTL

V této ukázce servlet negeneruje žádný výstup, jen připraví data, uloží je do requestu a předá řízení na JSP stránku. JSP stránka si vyzvedne data z requestu, a pomocí značek z JSTL provede cyklus nad všemi položkami předané mapy (jsou typu java.util.Map.Entry). Jazyk EL s tečkovou notací je použit pro zpřístupnění vnořených objektů, tj. např.

${j.value.loc.ISO3Language}

je ve skutečnosti provedeno jako

 
 pageContext.findAttribute("j").getValue().get("loc").getISO3Language()

Domácí úloha

Domácí úlohu dělá každý samostatně, nikoliv ve dvojicích.

Vytvořte webovou aplikaci, obsahující dvě JSP stránky a jeden servlet. První JSP stránka nechť se jmenuje index.jsp a obsahuje HTML formulář pro zadání nějaké entity do vašeho projektu, tj. například auta, zákazníka, jídla do ledničky, hrobu atd. Bude vypadat nějak takto:

 
<%@page contentType="text/html;charset=utf-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 
<html>
    <head>
        <title>Zadání dat</title>
    </head>
    <body>
        <h2>Zadejte auto</h2>
        <c:if test="${not empty chyba}">
            <div style="border: solid 1px red; background-color: yellow; padding: 10px">
                <c:out value="${chyba}"/>
            </div>
        </c:if>
        <form action="${pageContext.request.contextPath}/ZpracovaniServlet" method="post">
        <table>
            <tr>
                <th>SPZ:</th>
                <td><input type="text" name="spz" /></td>
            </tr>
            <tr>
                <th>barva:</th>
                <td><input type="text" name="barva" /></td>
            </tr>
            <tr>
                <th>značka:</th>
                <td><input type="text" name="znacka" /></td>
            </tr>
        </table>    
        <input type="Submit" value="Zadat" />
        </form>    
    </body>
</html>

Nezapomeňte do aplikace přidat knihovnu JSTL 1.1 !

Servlet bude obsahovat kontrolu, že všechna pole formuláře byla vyplněna, a pokud ne, zobrazí opět stránku index.jsp s popisem chyby.

Pokud budou všechna data zadána, servlet zavolá aplikační logiku projektu, uloží nový objekt (auto, jídlo, hrob, atd.), načte všechny objekty a předá řízení na stránku, která je zobrazí. Tj. servlet bude vypadat zhruba takto:

 
package cz.muni.fi.pa168.uloha;
 
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
 
public class ZpracovaniServlet extends HttpServlet {
   
 
    /** 
    * Handles the HTTP <code>POST</code> method.
    * @param request servlet request
    * @param response servlet response
    */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        //aby fungovala cestina z formulare
        request.setCharacterEncoding("utf-8");
 
        String spz = request.getParameter("spz");
        String barva = request.getParameter("barva");
        String znacka = request.getParameter("znacka");
        
        if(spz==null||spz.length()==0
                ||barva==null||barva.length()==0
                ||znacka==null||znacka.length()==0) {
            request.setAttribute("chyba", "Je nutné vyplnit všechny hodnoty !");
            request.getRequestDispatcher("/index.jsp").forward(request, response);
            return;
        }
        
        
        CarRental cr = new CarRental();
        cr.addCar(new Car(spz,barva,znacka));
        
        List<Car> allCars = cr.getAllCars();
        request.setAttribute("cars", allCars);
         
        request.getRequestDispatcher("/seznam.jsp").forward(request, response);
        
    }
}

Stránka zobrazující seznam objektů pak bude vypadat zhruba takto:

 
<%@page contentType="text/html;charset=utf-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
 
<html>
    <head>
        <title>Seznam aut</title>
    </head>
    <body>
        <h2>Seznam aut</h2>
        <table border="1">
        <c:forEach items="${cars}" var="car">
            <tr>
                <td><c:out value="${car.spz}"/></td>
                <td><c:out value="${car.barva}"/></td>
                <td><c:out value="${car.znacka}"/></td>
            </tr>    
        </c:forEach>
        </table>
     </body>
</html>

Spojení na databázi

Až budete shánět spojení do databáze, máte dvě možnosti.

Ta asi jednodušší je do projektu přidat knihovny s ovladačem pro JavaDB a spojení si ručně vytvořit.

Ale v reálných aplikacích poskytuje spojení do databáze TomCat, a tady je návod pro odvážnější:

Do servletu přidejte anotovanou proměnnou, kterou TomCat naplní instancí poolu databázových spojení. Na ní pak stačí zavolat pool.getConnection():

 
package cz.muni.fi.pa168.uloha;
 
import java.io.*;
import java.sql.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.sql.DataSource;
import javax.annotation.Resource;
 
public class ZpracovaniServlet extends HttpServlet {
    
    //dependency injection poolu spojeni na databazi od Tomcatu
    @Resource(name="jdbc/moje")
    private DataSource pool;
 
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    //...
    Connection c = pool.getConnection();
    //...
    }
}

Aby TomCat věděl, kde má DataSource vzít, do souboru WEB-INF/web.xml doplňte následující:

 
  <resource-ref>
     <res-ref-name>jdbc/moje</res-ref-name>
     <res-type>javax.sql.DataSource</res-type>
     <res-auth>Container</res-auth>
  </resource-ref>

a aby TomCat věděl, jaké spojení na databázi použít, do souboru META-INF/context.xml doplňte text aby vypadal zhruba takto (url, jméno a heslo nastavte pochopitelně svoje):

 
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/WebApplication2">
 
    <Resource name="jdbc/moje" auth="Container" type="javax.sql.DataSource"
            driverClassName="org.apache.derby.jdbc.ClientDriver"
            username="makub" password="heslo"
            url="jdbc:derby://localhost:1527/pokus"
    />
 
</Context>

A ted už jenom na příkazovém řádku zkopírujte JDBC ovladač do adresáře kde ho TomCat najde, tj.

$ cp /packages/run/jdk-1.6.0_05/db/lib/derbyclient.jar ~/.netbeans/6.0/apache-tomcat-6.0.14_base/nblib/

a můžete spustit aplikaci.

V rámci výuky jsou dostupné pro vyzkoušení i další aplikační servery Aplikacni servery