Cvičení Stripes

Z FI WIKI
Přejít na: navigace, hledání

Příprava prostředí

Vytvořte si novou webovou aplikaci jménem WebCviceni5, zvolte server Apache TomCat 6.0.13 a verzi JavaEE 1.5.


Přidejte knihovny rámce Stripes. Klikněte pravým tlačítkem ve stromu projektu na Libraries - Add Jar/Folder. Zvolte všechny soubory v adresáři

/packages/run/idea-6.0/stripes-1.4.3/lib
commons-logging.jar
cos.jar
log4j-1.2.13.jar
stripes.jar

Přidejte knihovny JSTL 1.1. Klikněte pravým tlačítkem na Libraries - Add Library, vyberte položku JSTL 1.1 a přidejte ji.

Zkuste aplikaci spustit, ať vidíte, že jede.

Zajistíme jednotný vzhled stránek

Teď zjistíme, jak se zajištuje jednotný vzhled stránek aplikace.

Vytvořte JSP stránku rozvrh.jsp (klikněte pravým tlačítkem na Web Pages, vyberte New - JSP, zadejte jméno rozvrh. Smažte její obsah a nahraďte ho tímto:

 
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ taglib prefix="s" uri="http://stripes.sourceforge.net/stripes.tld" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt" %>
 
<s:layout-definition>
<html>
<head>
  <title><c:out value="${nadpis}" /></title>
  <style type="text/css">
      input.error { background-color: yellow; }
      body { font-family: Helvetica, sans-serif; background-color: azure;}
      h1 { text-align: center; text-decoration: underline; text-shadow: aquamarine; text-transform: capitalize; }
      /*  http://www.alistapart.com/articles/taminglists/ */
     #navigace { width: 120px; border-right: 1px solid #000; padding: 0 0 1em 0; margin-bottom: 1em;
               background-color: #90bade;  color: #333;  }
     #navigace ul { list-style: none;  margin: 0;  padding: 0;  border: none; }
     #navigace li { border-bottom: 1px solid #90bade;  margin: 0; }
     #navigace li a { display: block; padding: 5px 5px 5px 0.5em; border-left: 10px solid #1958b7;
         border-right: 10px solid #508fc4; background-color: #2175bc;  color: #fff; text-decoration: none; width: 100%; }
      html>body #navigace li a { width: auto; }
      #navigace li a:hover { border-left: 10px solid #1c64d1;  border-right: 10px solid #5ba3e0;
          background-color: #2586d7;  color: #fff; }
      /*  http://realworldstyle.com/2col.html */
      #navigace { width: 120px; float: left; margin-left: -1px; }
      #obsah { padding: 10px;  margin-left: 130px; }
  </style>
    <s:layout-component name="hlavicka"/>
</head>
<body>
   <h1><c:out value="${nadpis}" /></h1>
   <div id="navigace">
     <ul>
       <li><s:link href="/index.jsp">Domů</s:link></li>
       <li><s:link href="/praha.jsp">do Prahy</s:link></li>
       <li><s:link href="/podoli.jsp">do Podolí</s:link></li>
       <li><s:link href="/lekarna.jsp">do lékárny</s:link></li>  
     </ul>
   </div>
   <div id="obsah">
       
       <s:layout-component name="telo"/>
       
    </div>
</body>
</html>
 
</s:layout-definition>

Tím jsme vytvořili šablonu rozvržení všech stránek, s nadpisem, navigačním menu a místem pro doplnění obsahu jednotlivých stránek.

Nyní změňte obsah stránky index.jsp na následující:

 
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="s" uri="http://stripes.sourceforge.net/stripes.tld" %>
 
<s:layout-render name="/rozvrh.jsp" nadpis="Hlavní stránka">
    <s:layout-component name="telo">
 
        Tady zatím nic není. Ale je to úvodní stránka aplikace.
 
    </s:layout-component>
</s:layout-render>

Je vidět, že stránka index.jsp se odkazuje na stránku rozvrh.jsp, a její oblast (tag s:layout-component) jménem telo nahrazuje vlastním obsahem. Zároveň definuje atribut nadpis, který je v rozvrh.jsp použit pro titul stránky a nadpis. Spusťte aplikaci.

samostatné cvičení

Vytvořte několik dalších JSP stránek využívajících stejný vzhled a přidejte je do navigačního menu.

Úloha pro pokročilé: změňte index.jsp tak, aby se přidal další obsah hlavičky stránky, ne do těla. Například další definici CSS nebo JavaScript.

Aktivujeme Stripes

Konfigurace

Nejdřív je nutné zkopírovat soubor s lokalizovanými chybovými hlášeními Stripes. Na příkazovém řádku se přepněte do adresáře s třídami a zkopírujte ho, tj.

cd ~/NetBeansProjects/WebApplication5/src/java
cp /packages/run/idea-6.0/stripes-1.4.3/lib/StripesResources.properties .

V NetBeans se soubor objeví v Source packages - default package. Přidejte mu českou a anglickou variantu stejně jako v minulém cvičení (Add Locale - Language Code).


Otevřete soubor web.xml, a změňte ho na:

 
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
         xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd">
    <!-- JSTL fmt: tagy pouziji lokalizovane texty  -->
    <context-param>
      <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
      <param-value>StripesResources</param-value>
    </context-param>
 
    <filter>
        <display-name>Stripes Filter</display-name>
        <filter-name>StripesFilter</filter-name>
        <filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class>
        <init-param>
            <!-- kde hleda action beans -->
            <param-name>ActionResolver.UrlFilters</param-name>
            <param-value>WEB-INF/classes</param-value>
        </init-param>
        <init-param>
            <!-- jaka locale aplikace podporuje -->
            <param-name>LocalePicker.Locales</param-name>
            <param-value>cs:utf-8,en:utf-8</param-value>
        </init-param>
    </filter>
 
    <filter-mapping>
        <filter-name>StripesFilter</filter-name>
        <url-pattern>*.jsp</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>
 
    <filter-mapping>
        <filter-name>StripesFilter</filter-name>
        <servlet-name>StripesDispatcher</servlet-name>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>
 
    <servlet>
        <servlet-name>StripesDispatcher</servlet-name>
        <servlet-class>net.sourceforge.stripes.controller.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
 
    <servlet-mapping>
        <servlet-name>StripesDispatcher</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>
</web-app>


Ještě je vhodné vytvořit soubor log4j.xml s konfigurací logování, abychom viděli, co se děje. Pravým tlačítkem myši na default package dejte New - XML - XML document

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
    <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n"/>
        </layout>
    </appender>
    <category name="org.apache.log4j.xml">
        <priority value="info"/>
    </category>
    <category name="net.sourceforge.stripes">
            <priority value="debug"/>
    </category>
    <root>
        <priority value="info"/>
        <appender-ref ref="STDOUT"/>
    </root>
</log4j:configuration>

Přijímání a kontrola dat z formuláře

Nejdříve vytvoříme nějakou třídu představující data, normální JavaBean. Nezapomeňte vytvořit balík cz.muni.fi.pa165.cv5, do kterého budeme třídy umísťovat.

 
package cz.muni.fi.pa165.cv5;
 
public class Zaznam {
    
    public enum Barva { ZELENA, MODRA, CERVENA }
    
    private long id;
    private String jmeno;
    private int pocet;
    private boolean vybran;
    private Barva barva;
 
    public long getId() { return id; }
    public void setId(long id) { this.id = id; }
    public String getJmeno() { return jmeno;  }
    public void setJmeno(String jmeno) { this.jmeno = jmeno; }
    public int getPocet() { return pocet; }
    public void setPocet(int pocet) { this.pocet = pocet; }
    public boolean isVybran() { return vybran; }
    public void setVybran(boolean vybran) { this.vybran = vybran; }
    public Barva getBarva() { return barva; }
    public void setBarva(Barva barva) { this.barva = barva;  }
    
}

Pak vytvoříme třídu, která implementuje ActionBean, tedy ve Stripes může obsluhovat požadavky od prohlížeče:

 
package cz.muni.fi.pa165.cv5;
 
import java.util.ArrayList;
import java.util.List;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.action.ActionBeanContext;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.UrlBinding;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;
import org.apache.log4j.Logger;
 
@UrlBinding("/zaznam.action")
public class ZaznamActionBean implements ActionBean {
    static Logger log = Logger.getLogger(ZaznamActionBean.class);
    
    private ActionBeanContext ctx;
    public void setContext(ActionBeanContext ctx) { this.ctx = ctx;  }
    public ActionBeanContext getContext() { return ctx;  }
 
    
    public List<Zaznam> getZaznamy() { 
        return (List<Zaznam>) ctx.getRequest().getSession().getAttribute("zaz");
    }
    public void setZaznamy(List<Zaznam> zaznamy) { 
        ctx.getRequest().getSession().setAttribute("zaz", zaznamy);
    }
    
    @ValidateNestedProperties(
        value = {
            @Validate(on = {"pridej","uloz"}, field = "jmeno", required = true),
            @Validate(on = {"pridej","uloz"}, field = "pocet", required = true, minvalue = 1)
        }
    )
    private Zaznam zaznam;
    public Zaznam getZaznam() { return zaznam;  }
    public void setZaznam(Zaznam zaznam) { this.zaznam = zaznam;  }
    
    public Resolution pridej() {
        log.debug("pridej()");
        if(getZaznamy()==null) { setZaznamy(new ArrayList<Zaznam>()); }
        getZaznamy().add(zaznam);
        return new RedirectResolution("/index.jsp");
    }
    
}

Tato třída je mapována na URL končící na /zaznam.action, při vyvolání události pridej zkontroluje, že data v instanci Zaznamu splňují podmínky, a bude vyvolána metoda odpovídající jménu události.


A změníme index.jsp tak, aby vypisovala seznam Zaznamů a obsahovala formulář pro zadání nového.

 
<%@ page pageEncoding="utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="s" uri="http://stripes.sourceforge.net/stripes.tld" %>
 
<s:layout-render name="/rozvrh.jsp" nadpis="Hlavní stránka">
    <s:layout-component name="telo">
 
        <s:useActionBean var="ab" binding="/zaznam.action"/>
        <table border="1">
        <c:forEach var="z" items="${ab.zaznamy}">
            <tr>
                <td><c:out value="${z.jmeno}" /></td>
                <td><c:out value="${z.pocet}" /></td>
                <td><c:out value="${z.vybran?'ano':'ne'}" /></td>
                <td><c:out value="${z.barva}" /></td>
            </tr>    
            </c:forEach>
        </table>
        
        <s:form action="/zaznam.action">
            <fieldset><legend>Nový záznam</legend>
            <s:errors/>
            <table>
                <tr>
                    <td><label for="z1">jméno:</label></td>
                    <td><s:text id="z1" name="zaznam.jmeno" /></td>
                </tr>
                <tr>
                    <td><label for="z2">počet:</label></td>
                    <td><s:text id="z2" name="zaznam.pocet" /></td>
                </tr>
                <tr>
                    <td><label for="z3">vybrán:</label></td>
                    <td><s:checkbox id="z3" name="zaznam.vybran" /></td>
                </tr>
                <tr>
                    <td><label for="z4">barva:</label></td>
                    <td><s:select id="z4" name="zaznam.barva" >
                        <s:options-enumeration enum="cz.muni.fi.pa165.cv5.Zaznam.Barva"/>
                    </s:select></td>
                </tr>
            </table>
            <s:submit name="pridej">Přidej</s:submit>
            </fieldset>
       </s:form>
 
    </s:layout-component>
</s:layout-render>

Spusťte aplikaci a zkuste postupně odeslat formulář s hodnotami, bez hodnot, s textem místo čísla.

Lokalizace do češtiny

Je vidět, že máme tři problémy:

  • chybová hlášení nejsou lokalizovaná do češtiny
  • názvy polí neodpovídají popisům ve stránce
  • názvy barev jsou bez diakritiky, odpovídají identifikátorům enumu

Je proto nutné v souboru StripesResources_cs.properties

  • přeložit chybová hlášení, minimálně ta použitá v našem případě
  • lokalizovat názvy polí formuláře, ve kterých může dojít k chybě
  • definovat lokalizované názvy barev
 #chybova hlaseni
 stripes.errors.header=<div style="color:#b72222; font-weight: bold">Prosím opravte následující chyby:</div><ol>
 validation.required.valueNotPresent=pole {0} musí být vyplněno
 converter.number.invalidNumber=Hodnota "{1}" zadaná do pole {0} musí být číslo

 #nazvy poli
 zaznam.jmeno=jméno
 zaznam.pocet=počet

 #nazvy polozek enumu
 Barva.MODRA=modrá
 Barva.ZELENA=zelená
 Barva.CERVENA=červená
 

Zkuste si spustit aplikaci.

samostatné cvičení

Proveďte lokalizaci do angličtiny a důslednou internacionalizaci. Statické texty nahraďte JSP tagy

 
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt" %>
...
 <f:message key="klic.textu" />