Cvičení Struts

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


Tato stránka obsahuje neaktuální informace a měla by být aktualizována. Berte ji proto prosím s rezervou!

Vytvořte si novou webovou aplikaci jménem WebCviceni5, zvolte Sun Java Application Server a verzi JEE 1.5, a zvolte, že chcete Struts.

V poli parametrů Struts Application Resource změňte hodnotu com.myapp.struts.ApplicationResource na cz.muni.fi.pa165.cv5.Texty.

Tím vznikl package cz.muni.fi.pa165.cv5 a v něm ResourceBundle soubor Texty.properties, přidejte k němu češtinu stejně jako v předešlém cvičení.

Z tohoto ResourceBundle čtou chybová hlášení značky ze Struts knihoven. Abychom mohli používat JSTL Formatting značky, zadáme jim stejný ResourceBundle. Otevřete soubor web.xml, a přidejte do něj inicializační parametry (Context parameters):

 
<web-app version="2.5" ...>
    <context-param>
        <description>lokalizované texty pro JSTL Formatting značky</description>
        <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
        <param-value>cz.muni.fi.pa165.cv5.Texty</param-value>
    </context-param>
    <context-param>
      <description>locale použité pokud se nenajde jiné</description>
      <param-name>javax.servlet.jsp.jstl.fmt.fallbackLocale</param-name>
      <param-value>cs</param-value>
    </context-param>

Smažte obsah stránky index.jsp a nahraďte ho za text, který způsobí přesměrování na první Struts akci.

 
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:redirect url="/seznam.do" />

Model

Vytvořte třídy cz.muni.fi.pa165.cv5.Kartoteka a cz.muni.fi.pa165.cv5.Zaznam, které představují Model.

 
package cz.muni.fi.pa165.cv5;
 
import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
 
public class Kartoteka<T> {
    
    private File soubor;
    private List<T> seznam;
            
    public Kartoteka(String xmlsoubor) throws FileNotFoundException {
        this.soubor = new File(xmlsoubor);
        if(!soubor.exists()) {
            seznam = new ArrayList<T>();
            return;
        }
        XMLDecoder d = new XMLDecoder(new BufferedInputStream(new FileInputStream(soubor)));
        seznam = (List<T>) d.readObject();
        d.close();
    }
    
    public synchronized void pridej(T polozka) throws FileNotFoundException {
        seznam.add(polozka);
        ulozDB();
    }
    
    public synchronized void smaz(T polozka) throws FileNotFoundException {
        seznam.remove(polozka);
        ulozDB();
    }
    
    public List<T> getSeznam() {
        return Collections.synchronizedList(seznam);
    }
    
    private synchronized void ulozDB() throws FileNotFoundException {
        XMLEncoder e = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(soubor)));
        e.writeObject(seznam);
        e.close();
    }   
}
 
package cz.muni.fi.pa165.cv5;
 
public class Zaznam {
    
    public Zaznam() { }
    
    private String jmeno;
    private int pocet;
 
    
    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;
    } 
}

Controller

Vytvořte třídu cz.muni.fi.pa165.cv5.Starter, která inicializuje Model (z MVC) aplikace a uloží do kontextu aplikace:

 
package cz.muni.fi.pa165.cv5;
 
import java.io.FileNotFoundException;
import javax.servlet.ServletException;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.action.PlugIn;
import org.apache.struts.config.ModuleConfig;
 
public class Starter implements PlugIn {
      
    /**
     * Konstanta pro název atributu aplikace s modelem.
     */
    public static final String NAS_MODEL = "NAS_MODEL";
    
    public void destroy() {
    }
 
    public void init(ActionServlet servlet, ModuleConfig config) throws ServletException {
        String souborNaDisku = servlet.getServletContext().getInitParameter("souborNaDisku");
        if(souborNaDisku==null) souborNaDisku = System.getProperty("user.home")+"/kartoteka.xml";
        try {
            servlet.getServletContext().setAttribute(NAS_MODEL,new Kartoteka<Zaznam>(souborNaDisku));
        } catch (FileNotFoundException ex) {
            throw new ServletException(ex);
        }
    }
}


Vytvořte třídu cz.muni.fi.pa165.cv5.PridejAction, která představuje část Controlleru:

 
package cz.muni.fi.pa165.cv5;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.action.DynaActionForm;
 
public class PridejAction extends Action {
    
    public ActionForward execute(ActionMapping mapping, ActionForm  form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        DynaActionForm dynform = (DynaActionForm) form;
        String jmeno = (String) dynform.get("jmeno");
        String pocet = (String) dynform.get("pocet");
        ActionMessages errors = new ActionMessages();
        if(jmeno==null||jmeno.length()==0) {
            errors.add("jmeno", new ActionMessage("musite_zadat_jmeno"));
        }
        int pint=0;
        try {
            pint = Integer.parseInt(pocet);
        } catch (Exception ex) {
            errors.add("pocet", new ActionMessage("musite_zadat_pocet"));
        }
        if(!errors.isEmpty()) {
            saveErrors(request,errors);
            return mapping.findForward("spatne");
        }
        
        Kartoteka<Zaznam> k = (Kartoteka<Zaznam>) getServlet().getServletContext().getAttribute(Starter.NAS_MODEL);
        Zaznam zaznam = new Zaznam();
        zaznam.setJmeno(jmeno);
        zaznam.setPocet(pint);
        k.pridej(zaznam);
        dynform.set("jmeno",null);
        dynform.set("pocet",null);
        return mapping.findForward("dobre");
    }
}

View

Vytvořte stránku seznam.jsp, která představuje View:

 
<%@ page session="true" contentType="text/html;charset=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="h" uri="http://jakarta.apache.org/struts/tags-html" %>
<%@ taglib prefix="l" uri="http://jakarta.apache.org/struts/tags-logic" %>
 
 
<table border="1">
    <tr>
        <th><f:message key="jmeno" /></th>
        <th><f:message key="pocet" /></th>
    </tr>
    <c:forEach var="i" items="${NAS_MODEL.seznam}" >
        <tr>          
            <td><c:out value="${i.jmeno}"/></td>
            <td><c:out value="${i.pocet}"/></td>
        </tr>
    </c:forEach>
</table>
 
<hr>
<l:messagesPresent>
 <!-- chybova hlaseni -->
 <div style="padding: 1em; font-weight: bold; color: red; background: yellow; border: solid 1px red;">
   <h:messages id="msg">
     <c:out value="${msg}"/><br />
   </h:messages>
 </div>
</l:messagesPresent>
 
    <h:form method="post" action="/pridej">
        <table>
            <tr>
                <th><f:message key="jmeno" />:</th>
                <td><h:text size="25" maxlength="30" property="jmeno" /></td>
            </tr>
            <tr>
                <th><f:message key="pocet" />:</th>
                <td><h:text size="25" maxlength="30" property="pocet" /></td>
            </tr> 
        </table>
        <input type="submit" value="<f:message key='odeslat'/>" />
    </h:form>
 

Do Texty_cs.properties doplňte:

jmeno=jm\u00E9no
pocet=po\u010Det
odeslat=odeslat
musite_zadat_jmeno=Vypl\u0148te jm\u00E9no, pros\u00EDm
musite_zadat_pocet=Po\u010Det mus\u00ED b\u00FDt \u010D\u00EDslo

Konfigurace

Soubor struts-config.xml změňte na tvar:

 
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
<struts-config>
    <!-- dynamicky JavaBean pro data ve formulari -->
    <form-beans>
        <form-bean name="zaznamForm" type="org.apache.struts.action.DynaActionForm">
            <form-property name="jmeno" type="java.lang.String" />
            <form-property name="pocet" type="java.lang.String" />
        </form-bean>
    </form-beans>
    <!-- seznam akci -->
    <action-mappings>
        <action path="/seznam" forward="/seznam.jsp"/>    
        <action path="/pridej" type="cz.muni.fi.pa165.cv5.PridejAction" name="zaznamForm"  validate="false" scope="request"  >
            <forward name="dobre" path="/seznam.jsp"/>
            <forward name="spatne" path="/seznam.jsp"/>
         </action>
    </action-mappings>
    <!-- texty pro chybova hlaseni -->
    <message-resources parameter="cz/muni/fi/pa165/cv5/Texty"/>    
    <!-- kachlicky -->
    <plug-in className="org.apache.struts.tiles.TilesPlugin" >
        <set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" />      
    </plug-in>
    <!-- inicializace aplikace -->
    <plug-in className="cz.muni.fi.pa165.cv5.Starter" >       
    </plug-in>   
</struts-config>

Nyní můžete aplikaci přeložit a spustit.

Samostatná cvičení

Samostatné cvičení 1: zajistěte, aby fungovaly české znaky ve formuláři, viz minulé cvičení

Samostatné cvičení 2: přemístěte formulář pro zadání nového záznamu na samostatnou stránku (nápověda: využijte značku <h:link action=""> z knihovny Struts HTML taglib nebo <c:url> z JSTL Core taglib)

Samostatné cvičení 3: přidejte další položky do záznamu

Samostatné cvičení 4: přidejte akce pro smazání a editaci záznamu

  • c:forEach může mít atribut varStatus="promenna", číslo iterace cyklu pak získáte ${promenna.index}
  • varování: pravdivostní položky zobrazené checkboxem potřebují zvláštní zacházení, protože u nezaškrtnutého checkboxu prohlížeč nepošle nic

Samostatné cvičení 5: zkuste využít Tiles