Представление OGNL

Без понимания того, как данные хранятся внутри Struts2, невозможно построить качественное приложение, в котором между действиями необходимо передавать не только отдельные параметры, но и целые масивы. В этой статье рассмотрим использование OGNL для вывода данных и ValueStack для их хранения.

Так что же означает аббревиатура OGNL (Object-Graph Navigation Language)?. В переводе на русский означает "Язык навигации по объектам-графам". Проще говоря, OGNL - это язык выражений, определяющий, как представлять данные в Struts2.

На странице Действия actions приведен пример приветствия пользователя, в котором необходимо ввести свое имя, чтобы попасть на страницу Wellcome.jsp. В данном примере имя пользователя определяется на странице Entry.jsp, а на странице приветствия отображается в теге

<s:property value="name" />

Это и есть простейшее OGNL выражение. Struts2 позволяет строить намного более сложные OGNL выражения. Данный фреймворк прекрасно понимает, что Вы передаете на вход тегу - строку или OGNL выражение.

В случаях, когда строка более уместна, но Вам по каким-либо причинам надо передать выражение, то нет проблем. Используйте конструкции вида %{выражение}, и Struts2 будет их сначала определять, а уже потом передавать как текст.

На странице Интернационализации рассмотрен пример работы с выражениями OGNL при выборе языка локализации.

Хранилище ValueStack

Но как Struts2 хранит и извлекает данные? Чтобы понять это, необходимо рассмотреть объект ValueStack, которое представляет собой хранилище. Т.е., если в action-классе определить отдельное свойство и массив объектов, то все эти данные будут сохранены в ValueStack, из которого можно их извлекать с использованием OGNL.

Представление данных

Таким образом, OGNL - это мощный язык выражений, который используется для обращения к ValueStack для извлечения и обработки данных.

Рассмотрим несложный пример представления списка пользователей на странице.

Листинг action-класса UserShow.java

package examples.ognl; 
  
public class UserShow extends ActionSupport 
{ 
    private String caption; 
    private List <User> userList; 
  
    public String execute() throws Exception 
    { 
        caption = "Список пользователей"; 
        return Action.SUCCESS; 
    } 
    // ... get/set методы 
} 

В данном классе в качестве свойств определен строковой заголовок caption и список пользователей userList. Для упрощения методы get/set, а также импортируемые пакеты (import ...) в листинге не представлены.

Допустим объект User включает свойства name, login, email. Описание класса User представлено на странице Использование сессий.

Отобразим список пользователей на странице UserShow.jsp

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8" language="java" %> 
<%@ taglib prefix="s" uri="/struts-tags" %> 
  
<html>
    <head>
        <title>Список пользователей</title>
    </head>

    <body>
        <h1><s:property value="caption"/></h1>
        <table border="1" width="100%">
            <tr><tn>Имя пользователя/><tn>Login</tn><tn>Email</tn></tr> 
            <s:iterator value="userList" status="stat">
               <tr>
                    <td><s:property value="userList [#stat.index].name" /></td>
                    <td><s:property value="userList [#stat.index].login" /></td>
                    <td><s:property value="userList [#stat.index].email" /></td>
               </tr>
            </s:iterator>
    </body> 
</html> 

Смысл тегов <s:property/> и <s:iterator> достаточно очевиден - это вывод значения и итерация по массиву данных.

Для того, чтобы это все сработало, необходимо в файле конфигурации struts.xml описать действие UserShow:

<package name="Default" namespace="/" extends="struts-default">
    ... 
    <action name="UserShow" class="examples.ognl.UserShow">
        <result name="success">/UserShow.jsp</result>
    </action> 
    ... 
</package>

Таким образом, при вызове действия UserShow фреймворк выполняет action-класс с одноименным названием и открывает страницу UserShow.jsp, на которой отображает значение свойства caption и в табличном виде параметры пользователей.

Доступ к свойствам объектов OGNL

Для доступа к внутренним свойствам объектов в OGNL используется синтаксис идентичный JSP EL. Если, например у нас есть объект OrderItem со свойством product типа Product, у которого есть свойства name, manufacturer и т.д., то получить значения свойств объекта можно, используя выражения либо orderItem.product.name, либо orderItem.product.manufacturer.

Элементы массивов и списков

Для последовательного доступа к отдельным элементам списка необходимо использовать тег <s:iterate/>. Чтобы вывести отдельный элемент из списка необходимо использовать синтаксис object[index]. Например, если необходимо вывести только второй элемент заказа, то можно использовать следующие выражения :

<h2>Второй элемент заказа:</h2>
    Производитель <s:property value="order.items[1].product.manufacturer"/>
    Товар         <s:property value="order.items[1].product.name"/> 
    Цена          <s:property value="order.items[1].price"/>
    Количество    <s:property value="order.items[1].amount"/> 
    Сумма         <s:property value="order.items[1].total"/>
  Рейтинг@Mail.ru