JSP action tagy

V této části si ukážeme JSP action tagy. Jedná se o tagy, které slouží k provedení nějakého specifického úkolu. Můžeme je brát jako již předdefinované custom tagy, jelikož v podstatě fungují stejně. Akorát si je nemusíme v JSP souboru definovat prostřednictvím taglib direktivy a mají vždy prefix "jsp". Custom tagy jsou uživatelsky definované tagy o kterých se dozvíte v další části. Tato část se zaměřuje na action tagy (takové již předdefinované custom tagy), takže si je tu postupně projdeme.

Syntaxy pro action tagy ukazuje následující ukázka. Pokud máme více atributů, tak je můžeme oddělit mezerou. Pokud má nějaký tag obsah, tak je potřeba jej uzavřít použitím uzavíracího tagu.

<!-- samouzavírací tag -->
<jsp:nazev atribut="hodnota" />

<!-- tag s uzavíracím tagem -->
<jsp:nazev atribut="hodnota">
    nějaký obsah
</jsp:nazev>

jsp:forward

Action tag jsp:forward slouží k předání requestu do jiné JSP stránky nebo servletu. Je to podobné jako metoda forward request dispatcheru. Můžeme pro request provést nějakou akci a předat request dále ke zpracování do jiné stránky.

Pro ukázku si založíme nový projekt a vytvoříme si dvě JSP stránky. První můžeme pojmenovat jako stranka1.jsp. V této stránce použijeme jsp:forward tag a přesměrujeme na stránku stranka2.jsp, kterou potom vytvoříme. Následující ukázka ukazuje kód stránky. Kromě použití jsp:forward tagu na stránce vypisujeme i text, abychom viděli, že se vůbec nezobrazí. Akorát se spustí Java kód, který je umístěný před použitím jsp:forward tagu. Kód umístěný za jsp:forward tagem se již vůbec nespustí.

  • src
    • main
      • java
      • resources
      • webapp
    • test
      • java
      • resources
  • target
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>io.github.jirkasa</groupId>
    <artifactId>forward-action-tag</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>forward-action-tag</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>17</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>
<%@ page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Stránka 1</title>
</head>
<body>
    <p>Tento text se nezobrazí.</p>
    <% System.out.println("Toto se v konzoli vypíše"); %>
    
    <!-- Předání requestu ke zpracování do jiné stránky. -->
    <jsp:forward page="./stranka2.jsp" />
    
    <% System.out.println("Toto se v konzoli nevypíše"); %>
    <p>Tento text se také nezobrazí. Nic z této stránky se nezobrazí.</p>
</body>
</html>

Teď můžeme vytvořit stránku na kterou předáváme request. Pojmenujeme ji jako stranka2.jsp a jen v ní zobrazíme nějaký text.

  • src/main/webapp
<%@ page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Stránka 2</title>
</head>
<body>
    <p>Obsah stránky 2.</p>
</body>
</html>

Po spuštění aplikace a otevření první stránky (http://localhost:8080/forward-action-tag/stranka1.jsp) můžete vidět, že se vám namísto obsahu první stránky (stranka1.jsp) zobrazil obsah druhé stránky (stranka2.jsp). Žádný obsah z první stránky se ve výsledné stránce nepoužil.

Stránka stranka2.jsp

Abychom si ukázali, že kód umístěný před jsp:forward tagem se spouští ale ten za ním již ne, vypisujeme text do konzole. První text se do konzole vypíše, ale ten druhý již ne.

Toto se v konzoli vypíše

jsp:include

Pomocí jsp:include tagu můžeme do stránky přidat obsah z jiného souboru. Je to stejné jako direktiva include, až na to že jsp:include tag nepřidává obsah ze souboru při překladu na servlet, ale pokaždé když přijde request.

Následující ukázka kódu ukazuje, jak bychom mohli jsp:include tag použít. Jedná se o přepsaný kód z minulé části, kde jsme namísto action tagu používali include direktivu.

<%@ page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>jsp:include action tag</title>
</head>
<body>
    <jsp:include page="./header.jsp" />
    <p>Obsah stránky...</p>
    <jsp:include page="./footer.jsp" />
</body>
</html>

jsp:useBean

Action tag jsp:useBean slouží k nalezení nebo vytvoření instance bean třídy. Pokud je bean objekt bean třídy již vytvořený, tak se nevytvoří nová instance. Pokud ale bean objekt ještě není vytvořen, tak se vytvoří nová instance.

Co je Java Bean

Možná si říkáte co je to bean. Není to nic složitého. Pouze se jedná o třídu, která dodržuje následující pravidla:

  • má konstruktor bez parametrů
  • implementuje java.io.Serializable rozhraní
  • poskytuje metody pro získání a nastavení vlastností (gettery a settery)

Následují ukázka ukazuje příklad bean třídy.

import java.io.Serializable;

public class User implements Serializable {
    private int id;
    private String name;

    public void setId(int id) { this.id = id; }
    public int getId() { return id; }

    public void setName(String name) { this.name = name; }
    public String getName() { return name; }
}

Atributy jsp:useBean tagu

Následující tabulka popisuje atributy, které můžeme v jsp:useBean tagu použít.

AtributHodnotaPopis
ididentifikátor (název) beanuNastavuje jedinečný identifikátor beanu v určitém rozsahu nastaveného prostřednictvím scope atributu.
scopepage | request | session | applicationNastavuje do jakého rozsahu bean patří (defaultní je page).
classbean třídaNastavuje třídu, podle které se má bean vytvořit.
typedatový typNastavuje datový typ pro vytvořenou instanci bean třídy. Měl by být kompatibilní s třídou definovanou v atributu class. Pokud type atribut není specifikovaný, tak se automaticky odvodí podle atributu class.
beanNameOmlouvám se, ale toto je nad moje chápání. Pokud vás zajímá k čemu to slouží, tak si to budete muset zjistit někde jinde.

Beany se vytváří v určitém rozsahu definovaném prostřednictvím scope atributu. Může platit pro aktuální stránku (page), pro aktuální request (request), pro session, nebo celou aplikaci - všechny uživatele (application). Klidně tedy můžeme mít beany se stejnými identifikátory ale v jiném rozsahu. Defaultní scope je page.

Ukázka použití jsp:useBean tagu

Pro ukázku použití jsp:useBean tagu si založíme nový projekt a poté Java třídu, kterou můžeme pojmenovat jako Uzivatel. Bude představovat bean třídu, kterou si zkusíme v jsp:useBean tagu použít. Pro třídu si vytvořte nějaký java balíček a umístěte ji do něj, jelikož k defaultnímu balíčku bychom neměli z JSP souboru přístup. Následující ukázka ukazuje kód třídy. Aby se jednalo o bean třídu, tak implementuje Serializable rozhraní a obsahuje vlastnosti, pro které má gettery a settery.

  • src
    • main
      • java
      • resources
      • webapp
    • test
      • java
      • resources
  • target
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>io.github.jirkasa</groupId>
    <artifactId>use-bean-action-tag</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>use-bean-action-tag</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>17</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>
package io.github.jirkasa;

import java.io.Serializable;

public class Uzivatel implements Serializable {
    private String jmeno;
    private String prijmeni;
    
    public void setJmeno(String jmeno) {
        this.jmeno = jmeno;
    }
    public String getJmeno() {
        return jmeno;
    }
    
    public void setPrijmeni(String prijmeni) {
        this.prijmeni = prijmeni;
    }
    public String getPrijmeni() {
        return prijmeni;
    }
}

Teď si vytvoříme JSP stránku, kterou můžeme pojmenovat třeba jako "stranka.jsp". Na této stránce naši vytvořenou bean třídu použijeme a pomocí jsp:useBean tagu si vytvoříme její instanci (bean objekt). Pouze si bean objekt vytvoříme, nastavíme do něj data a na stránce si je poté vypíšeme. Následující ukázka ukazuje kód stránky.

  • src/main/webapp
<%@page contentType="text/html" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>jsp:useBean tag</title>
</head>
<body>
    <!-- Vytvoření bean objektu uzivatel, pokud ještě není vytvořený (v našem případě není) -->
    <jsp:useBean id="uzivatel" class="io.github.jirkasa.Uzivatel" />
    
    <%
    // vytvořený bean objekt můžeme klidně používat ve scripletech
    uzivatel.setJmeno("Jiří");
    uzivatel.setPrijmeni("Satora");
    %>
    
    <p>Uživatel: <%= uzivatel.getJmeno() %> <%= uzivatel.getPrijmeni() %></p>
</body>
</html>

Po spuštění aplikace a navštívení http://localhost:8080/use-bean-action-tag/stranka.jsp uvidíte stránku, kterou ukazuje následující obrázek.

vygenerovaná stránka

Proč se beany používají

Ve webovém vývoji se beany používají hlavně proto, že se jedná o znovupoužitelnou softwarovou komponentu, která reprezentuje data. V části o MVC vzoru se naučíme něco o tom, jak strukturovat naše webové aplikace. Zjistíte, že populární vzor pro strukturování webových aplikací se skládá ze tří částí: model, view a controller. Beany by v tomto případě představovali modely.

jsp:setProperty

Pomocí jsp:setProperty tagu můžeme nastavovat vlastnosti beanu.

Atributy jsp:setProperty tagu

Následující tabulka ukazuje atributy jsp:setProperty tagu.

AtributHodnotaPopis
nameidentifikátor beanuNastavuje identifikátor beanu, pro který chceme nastavovat vlastnost(i).
propertyjméno vlastnosti nebo "*" pro nastavení všech vlastnostíNastavuje, která vlastnost se má nastavit.
paramjméno parametru v HTTP requestuNastavuje parametr z HTTP requestu, který se má použít pro nastavení vlastnosti.
valuehodnotaNastavuje hodnotu, která se má vlastnosti nastavit.

Podle toho zda nastavíme atribut value se budou nebo nebudou vlastnosti beanu nastavovat podle parametrů předávaných v HTTP requestu. Následující ukázka ukazuje pár příkladů použití jsp:setProperty tagu.

<!-- Nastavení vlastností beanu podle parametrů z HTTP requestu
(parametry se musejí jmenovat stejně jako vlastnosti) -->
<jsp:setProperty name="mujBean" property="*" />

<!-- Nastavení vlastnosti email podle parametru email z HTTP requestu -->
<jsp:setProperty name="mujBean" property="email" />

<!-- Nastavení vlastnosti email na hodnotu "test@test.com" -->
<jsp:setProperty name="mujBean" property="email" value="test@test.com" />

Ukázka použití jsp:setProperty tagu

Pro ukázku použití jsp:setProperty tagu si založíme nový projekt a pro začátek si vytvoříme bean třídu, kterou budeme používat. Je to stejná třída jako z ukázky použití jsp:useBean tagu, takže si ji můžete zkopírovat. Abyste ji mohli v JSP používat, tak ji vložte do nějakého Java balíčku.

  • src
    • main
      • java
      • resources
      • webapp
    • test
      • java
      • resources
  • target
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>io.github.jirkasa</groupId>
    <artifactId>set-property-action-tag</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>set-property-action-tag</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>17</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>
package io.github.jirkasa;

import java.io.Serializable;

public class Uzivatel implements Serializable {
    private String jmeno;
    private String prijmeni;
    
    public void setJmeno(String jmeno) {
        this.jmeno = jmeno;
    }
    public String getJmeno() {
        return jmeno;
    }
    
    public void setPrijmeni(String prijmeni) {
        this.prijmeni = prijmeni;
    }
    public String getPrijmeni() {
        return prijmeni;
    }
}

V našem projektu budeme mít dvě JSP stránky. Na jedné stránce se bude nacházet formulář, kde uživatel zadá jméno a příjmení a formulář odešle na druhou stránku. Na té se vytvoří bean třídy Uzivatel a pomocí tagu jsp:setProperty se do něj nastaví hodnoty.

Začneme se stránkou s formulářem, kterou můžeme pojmenovat třeba jako "formular.jsp". Inputy formuláře musejí mít jako name atributy nastavené jména vlastností naší bean třídy, jelikož budeme chtít našemu bean objektu vlastnosti nastavit automaticky. Následující ukázka ukazuje kód stránky.

  • src/main/webapp
<%@page contentType="text/html" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>jsp:setProperty tag</title>
</head>
<body>
    <form action="./vysledek.jsp" method="POST">
        <label for="jmeno">Jméno:</label>
        <input type="text" id="jmeno" name="jmeno" />
        <br><br>
        <label for="prijmeni">Příjmení:</label>
        <input type="text" id="prijmeni" name="prijmeni" />
        <br><br>
        <button>Odeslat</button>
    </form>
</body>
</html>

Po spuštění aplikace a navštívení http://localhost:8080/set-property-action-tag/formular.jsp si vytvořenou stránku s formulářem můžete prohlédnout.

stránka s formulářem

Teď vytvoříme stránku "vysledek.jsp", na kterou náš vytvořený formulář směřuje. Na této stránce vytvoříme bean objekt třídy Uzivatel, naplníme jej daty z formuláře za použití jsp:setProperty tagu a nakonec vlastnosti bean objektu vypíšeme na stránku.

  • src/main/webapp
<%@page contentType="text/html" pageEncoding="UTF-8" %>

<!-- Je to otrava, ale je důležité na requestu nastavit kódování,
abychom data z formuláře dostali ve správném formátu. -->
<%
request.setCharacterEncoding("UTF-8");
%>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>jsp:setProperty tag</title>
</head>
<body>
    <!-- Vytvoření bean objektu uzivatel -->
    <jsp:useBean id="uzivatel" class="io.github.jirkasa.Uzivatel" />
    
    <!-- Nastavení vlastností beanu podle parametrů z HTTP requestu (formuláře) -->
    <jsp:setProperty name="uzivatel" property="*" />
    
    <!-- Vypsání vlastností beanu na stránku -->
    <p>Uživatel: <%= uzivatel.getJmeno() %> <%= uzivatel.getPrijmeni() %></p>
</body>
</html>

Naše ukázka je hotová. Když teď formulář vyplníte a odešlete, tak se vám zobrazí stránka se jménem a příjmením, které jste zadali.

vygenerovaná stránka

jsp:getProperty

Action tag jsp:getProperty se používá k získání vlastnosti z beanu.

Pro ukázku si upravíme předchozí projekt, kde přepíšeme vypisování vlastností beanu přes expression tagy na použití jsp:getProperty tagů. Následující ukázka ukazuje upravený kód souboru "vysledek.jsp".

  • src/main/webapp
<%@page contentType="text/html" pageEncoding="UTF-8" %>

<!-- Je to otrava, ale je důležité na requestu nastavit kódování,
abychom data z formuláře dostali ve správném formátu. -->
<%
request.setCharacterEncoding("UTF-8");
%>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>jsp:setProperty tag</title>
</head>
<body>
    <!-- Vytvoření bean objektu uzivatel -->
    <jsp:useBean id="uzivatel" class="io.github.jirkasa.Uzivatel" />
    
    <!-- Nastavení vlastností beanu podle parametrů z HTTP requestu (formuláře) -->
    <jsp:setProperty name="uzivatel" property="*" />
    
    <!-- Vypsání vlastností beanu na stránku -->
    <p>Uživatel: <jsp:getProperty name="uzivatel" property="jmeno" /> <jsp:getProperty name="uzivatel" property="prijmeni" /></p>
</body>
</html>

Pokud si stránku zkusíte otevřít, tak se zobrazí stejně jako předtím.

jsp:param

Action tag jsp:param se většinou používá v kombinaci s tagy jako je jsp:forward nebo jsp:include. Slouží pro předání parametru. Je to jen alternativa k metodě request.setParameter.

Pro vyzkoušení si upravíme náš ukázkový projekt pro jsp:forward tag. Na stránce "stranka1.jsp" předáme parametr pomocí jsp:param tagu, který vložíme do jsp:forward tagu. Vlastně předáme text, který následně na stránce "stranka2.jsp" zobrazíme. Upravený kód souboru "stranka1.jsp" ukazuje následující ukázka. Tag jsp:param má atribut name, přes který nastavujeme název parametru, a atribut value, přes který nastavujeme hodnotu parametru.

  • src/main/webapp
<%@ page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Stránka 1</title>
</head>
<body>
    <p>Tento text se nezobrazí.</p>
    <% System.out.println("Toto se v konzoli vypíše"); %>
    
    <!-- Zase musíme nastavit kódování... -->
    <% request.setCharacterEncoding("UTF-8"); %>
    
    <!-- Předání requestu ke zpracování do jiné stránky. -->
    <jsp:forward page="./stranka2.jsp">
        <jsp:param name="text" value="Toto je můj text." />
    </jsp:forward>
    
    <% System.out.println("Toto se v konzoli nevypíše"); %>
    <p>Tento text se také nezobrazí. Nic z této stránky se nezobrazí.</p>
</body>
</html>

Na stránce "stranka2.jsp" můžeme parametr získat a vypsat jej na stránku. Následující ukázka ukazuje upravený kód.

  • src/main/webapp
<%@ page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Stránka 2</title>
</head>
<body>
    <!-- Vypsání hodnoty parametru na stránku -->
    <p><%= request.getParameter("text") %></p>
</body>
</html>

Po otevření stránky "stranka1.jsp" (http://localhost:8080/forward-action-tag/stranka1.jsp) můžete vidět, že se parametr předal a zobrazil se na stránce.

vygenerovaná stránka

Ostatní action tagy

Kromě tagů, které jsme si v této části ukázali, existuje ještě pár dalších action tagů, u kterých popravdě ani nevím k čemu slouží. Proto jsem se rozhodl je tu jen vypsat. Pokud by vás zajímali, tak si o nich budete muset vyhledat informace někde jinde.

  • jsp:body
  • jsp:element
  • jsp:plugin
  • jsp:text
  • jsp:fallback
  • jsp:attribute
  • jsp:output

Pro tuto část je to vše. Jak jste viděli, tak action tagy nám poskytují takovou snažší cestu, jak provést nějaký úkol. Obešli bychom se i bez nich. V příští části se naučíme o uživatelsky definovaných action tagách.