Учебники

Apache Tapestry — Компоненты

Как обсуждалось ранее, Компоненты и Страницы одинаковы, за исключением того, что Страница является корневым компонентом и включает в себя один или несколько дочерних компонентов. Компоненты всегда находятся внутри страницы и выполняют почти все динамические функции страницы.

Компоненты Tapestry отображают простые HTML-ссылки на сложные функциональные возможности сетки с помощью интерактивного AJAX . Компонент может включать в себя и другой компонент. Компоненты гобелена состоят из следующих предметов —

  • Класс компонента — основной класс Java компонента.

  • Шаблон XML — шаблон XML похож на шаблон страницы. Класс компонента отображает шаблон как окончательный результат. Некоторые компоненты могут не иметь шаблонов. В этом случае выходные данные будут сгенерированы самим классом компонента с использованием класса MarkupWriter .

  • Тело . Компонент, указанный внутри шаблона страницы, может иметь пользовательскую разметку и называется «Тело компонента». Если шаблон компонента имеет элемент <body /> , то элемент <body /> будет заменен телом компонента. Это похоже на макет, обсужденный ранее в разделе шаблона XML.

  • Рендеринг — Рендеринг — это процесс, который преобразует XML-шаблон и тело компонента в фактический вывод компонента.

  • Параметры — используются для создания связи между компонентом и страницами и, тем самым, передачи данных между ними.

  • События — делегирует функциональность от компонентов своему контейнеру / родительскому элементу (страницам или другому компоненту). Он широко используется в навигации по страницам.

Класс компонента — основной класс Java компонента.

Шаблон XML — шаблон XML похож на шаблон страницы. Класс компонента отображает шаблон как окончательный результат. Некоторые компоненты могут не иметь шаблонов. В этом случае выходные данные будут сгенерированы самим классом компонента с использованием класса MarkupWriter .

Тело . Компонент, указанный внутри шаблона страницы, может иметь пользовательскую разметку и называется «Тело компонента». Если шаблон компонента имеет элемент <body /> , то элемент <body /> будет заменен телом компонента. Это похоже на макет, обсужденный ранее в разделе шаблона XML.

Рендеринг — Рендеринг — это процесс, который преобразует XML-шаблон и тело компонента в фактический вывод компонента.

Параметры — используются для создания связи между компонентом и страницами и, тем самым, передачи данных между ними.

События — делегирует функциональность от компонентов своему контейнеру / родительскому элементу (страницам или другому компоненту). Он широко используется в навигации по страницам.

Rendering

Визуализация компонента выполняется в виде ряда заранее определенных этапов. Каждая фаза в системе компонентов должна иметь соответствующий метод, определенный соглашением или аннотацией в классе компонента.

// Using annotaion 
@SetupRender 
void initializeValues() { 
   // initialize values 
}

// using convention 
boolean afterRender() { 
   // do logic 
   return true; 
}

Фазы, название метода и аннотации перечислены ниже.

аннотирование Имена методов по умолчанию
@SetupRender setupRender ()
@BeginRender beginRender ()
@BeforeRenderTemplate beforeRenderTemplate ()
@BeforeRenderBody beforeRenderBody ()
@AfterRenderBody afterRenderBody ()
@AfterRenderTemplate afterRenderTemplate ()
@AfterRender afterRender ()
@CleanupRender cleanupRender ()

Каждый этап имеет определенную цель, и они заключаются в следующем —

SetupRender

SetupRender запускает процесс рендеринга. Обычно он устанавливает параметры компонента.

BeginRender

BeginRender начинает рендеринг компонента. Обычно он отображает начальный / начальный тег компонента.

BeforeRenderTemplate

BeforeRenderTemplate используется для украшения шаблона XML, добавляя специальную разметку вокруг шаблона. Он также предоставляет возможность пропустить рендеринг шаблона.

BeforeRenderBody

BeforeRenderTemplate предоставляет возможность пропустить рендеринг элемента тела компонента.

AfterRenderBody

AfterRenderBody будет вызываться после визуализации тела компонента.

AfterRenderTemplate

AfterRenderTemplate будет вызываться после визуализации шаблона компонента.

AfterRender

AfterRender является аналогом BeginRender и обычно отображает закрывающий тег.

CleanupRender

CleanupRender является аналогом SetupRender. Он освобождает / удаляет все объекты, созданные в процессе рендеринга.

Поток фаз рендеринга не только вперед. Он идет туда-сюда между фазами в зависимости от возвращаемого значения фазы.

Например, если метод SetupRender возвращает false, то рендеринг переходит к фазе CleanupRender и наоборот. Чтобы найти четкое представление о потоке между различными фазами, проверьте поток на диаграмме, приведенной ниже.

Список аннотаций

Простой компонент

Давайте создадим простой компонент Hello, который будет иметь выходное сообщение «Hello, Tapestry». Ниже приведен код компонента Hello и его шаблона.

package com.example.MyFirstApplication.components;  
public class Hello {  
}
<html  
   xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd" 
   xmlns:p = "tapestry:parameter"> 
  
   <div> 
      <p>Hello, Tapestry (from component).</p> 
   </div> 
  
</html>

Компонент Hello может быть вызван в шаблоне страницы как —

<html title = "Hello component test page" 
   xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd" 
   xmlns:p = "tapestry:parameter"> 
<t:hello />  
</html>

Точно так же компонент может визуализировать тот же вывод, используя MarkupWriter вместо шаблона, как показано ниже.

package com.example.MyFirstApplication.components; 
  
import org.apache.tapestry5.MarkupWriter; 
import org.apache.tapestry5.annotations.BeginRender;   

public class Hello { 
   @BeginRender 
   void renderMessage(MarkupWriter writer) { 
      writer.write("<p>Hello, Tapestry (from component)</p>"); 
   } 
}

Давайте изменим шаблон компонента и включим элемент <body />, как показано в блоке кода ниже.

<html>  
   xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd" 
   xmlns:p = "tapestry:parameter"> 
   
   <div> 
      <t:body /> 
   </div> 
</html>

Теперь шаблон страницы может включать тело в разметку компонента, как показано ниже.

<html title = "Hello component test page" 
   xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd" 
   xmlns:p = "tapestry:parameter"> 
   
   <t:hello> 
      <p>Hello, Tapestry (from page).</p> 
   </t:hello> 
</html>

Выход будет следующим:

<html> 
   <div> 
      <p>Hello, Tapestry (from page).</p> 
   </div> 
</html>

параметры

Основное назначение этих параметров — создать связь между полем компонента и свойством / ресурсом страницы. Используя параметры, компонент и соответствующая ему страница связываются и передают данные между собой. Это называется двухсторонним связыванием данных .

Например, компонент текстового поля, используемый для представления возраста на странице управления пользователями, получает свое начальное значение (доступно в базе данных) через параметр. Опять же, после того, как возраст пользователя обновлен и отправлен обратно, компонент отправит обратно обновленный возраст через тот же параметр.

Чтобы создать новый параметр в классе компонентов, объявите поле и укажите аннотацию @Parameter . Этот @Parameter имеет два необязательных аргумента, которые являются —

  • обязательный — делает параметр обязательным. Гобелен выдвигает исключение, если оно не предусмотрено.

  • значение — указывает значение параметра по умолчанию.

обязательный — делает параметр обязательным. Гобелен выдвигает исключение, если оно не предусмотрено.

значение — указывает значение параметра по умолчанию.

Параметр должен быть указан в шаблоне страницы как атрибуты тега компонента. Значение атрибутов должно быть указано с помощью Binding Expression / Expansion, который мы обсуждали в предыдущих главах. Некоторые из расширений, которые мы узнали ранее, —

  • Расширение свойства (prop: «val») — Получить данные из свойства класса страницы.

  • Расширение сообщения (сообщение: «val») — Получить данные из ключа, определенного в файле index.properties.

  • Расширение контекста (context: «val») — Получить данные из папки веб-контекста / src / main / webapp.

  • Расширение актива (asset: «val») — Получить данные из ресурсов, встроенных в jar-файл, / META-INF / assets.

  • Расширение символа (символ: «val») — Получить данные из символов, определенных в AppModule.javafile.

Расширение свойства (prop: «val») — Получить данные из свойства класса страницы.

Расширение сообщения (сообщение: «val») — Получить данные из ключа, определенного в файле index.properties.

Расширение контекста (context: «val») — Получить данные из папки веб-контекста / src / main / webapp.

Расширение актива (asset: «val») — Получить данные из ресурсов, встроенных в jar-файл, / META-INF / assets.

Расширение символа (символ: «val») — Получить данные из символов, определенных в AppModule.javafile.

Гобелен имеет много других полезных дополнений, некоторые из которых приведены ниже —

  • Литеральное расширение (литерал: «val») — буквальная строка.

  • Расширение var (var: «val») — разрешить чтение или обновление переменной рендеринга компонента.

  • Расширение проверки (validate: «val») — специализированная строка, используемая для указания правила проверки объекта. Например, validate: required, minLength = 5.

  • Translate (translate: «val») — используется для указания класса Translator (преобразования клиентской части в представление серверной части) при проверке входных данных.

  • Block (block: «val») — идентификатор элемента блока в шаблоне.

  • Компонент (component: «val») — идентификатор другого компонента в шаблоне.

Литеральное расширение (литерал: «val») — буквальная строка.

Расширение var (var: «val») — разрешить чтение или обновление переменной рендеринга компонента.

Расширение проверки (validate: «val») — специализированная строка, используемая для указания правила проверки объекта. Например, validate: required, minLength = 5.

Translate (translate: «val») — используется для указания класса Translator (преобразования клиентской части в представление серверной части) при проверке входных данных.

Block (block: «val») — идентификатор элемента блока в шаблоне.

Компонент (component: «val») — идентификатор другого компонента в шаблоне.

Все вышеперечисленные расширения доступны только для чтения, за исключением расширения Property и Var. Они используются компонентом для обмена данными со страницей. При использовании раскрытия в качестве значений атрибута не следует использовать $ {…} . Вместо этого просто используйте расширение без символа доллара и скобок.

Компонент, использующий параметр

Давайте создадим новый компонент HelloWithParameter, изменив компонент Hello для динамической визуализации сообщения, добавив параметр имени в класс компонента и изменив соответственно шаблон компонента и шаблон страницы.

  • Создайте новый класс компонента HelloWithParameter.java .

  • Добавьте личное поле и назовите его аннотацией @Parameter . Используйте обязательный аргумент, чтобы сделать его обязательным.

Создайте новый класс компонента HelloWithParameter.java .

Добавьте личное поле и назовите его аннотацией @Parameter . Используйте обязательный аргумент, чтобы сделать его обязательным.

@Parameter(required = true) 
private String name;
  • Добавьте приватное поле, результат с аннотацией @Propery . Свойство результата будет использовано в шаблоне компонента. Шаблон компонента не имеет доступа к полям, аннотированным @Parameter, и может получить доступ только к полям, аннотированным @Property . Переменные, доступные в шаблонах компонентов, называются переменными рендеринга.

Добавьте приватное поле, результат с аннотацией @Propery . Свойство результата будет использовано в шаблоне компонента. Шаблон компонента не имеет доступа к полям, аннотированным @Parameter, и может получить доступ только к полям, аннотированным @Property . Переменные, доступные в шаблонах компонентов, называются переменными рендеринга.

@Property 
 private String result;
  • Добавьте метод RenderBody и скопируйте значение из параметра name в свойство result.

Добавьте метод RenderBody и скопируйте значение из параметра name в свойство result.

@BeginRender 
void initializeValues() { 
   result = name; 
}
  • Добавьте новый шаблон компонента HelloWithParamter.tml и используйте свойство result для отображения сообщения.

Добавьте новый шаблон компонента HelloWithParamter.tml и используйте свойство result для отображения сообщения.

<div> Hello, ${result} </div>
  • Добавьте новое свойство Имя пользователя на тестовой странице (testhello.java).

Добавьте новое свойство Имя пользователя на тестовой странице (testhello.java).

public String getUsername() { 
   return "User1"; 
}
  • Используйте только что созданный компонент в шаблоне страницы и задайте свойство Username в параметре name компонента HelloWithParameter .

Используйте только что созданный компонент в шаблоне страницы и задайте свойство Username в параметре name компонента HelloWithParameter .

<t:helloWithParameter name = "username" /> 

Полный список выглядит следующим образом —

package com.example.MyFirstApplication.components;  

import org.apache.tapestry5.annotations.*;  
public class HelloWithParameter { 
   @Parameter(required = true) 
   private String name; 
     
   @Property 
   private String result; 
   
   @BeginRender 
   void initializeValues() { 
      result = name; 
   } 
}
<html  
   xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd" 
   xmlns:p = "tapestry:parameter"> 
   
   <div> Hello, ${result} </div> 
  
</html>
package com.example.MyFirstApplication.pages;  

import org.apache.tapestry5.annotations.*;  
public class TestHello { 
   public String getUsername() { 
      return "User1"; 
   } 
}
<html title = "Hello component test page" 
   xmlns:t = "https://tapestry.apache.org/schema/tapestry_5_4.xsd" 
   xmlns:p = "tapestry:parameter"> 
   <t:helloWithParameter name = "username" />
   
</html> 

Результат будет следующим:

<div> Hello, User1 </div>

Расширенный параметр

В предыдущих главах мы анализировали, как создать и использовать простой параметр в пользовательском компоненте. Расширенный параметр также может содержать полную разметку. В этом случае разметка должна быть указана внутри тега компонента, такого как подраздел в шаблоне страницы. Встроенный компонент if имеет разметку для условия успеха и сбоя. Разметка для успеха указывается как тело тега компонента, а разметка для отказа указывается с помощью elseparameter .

Давайте посмотрим, как использовать компонент if . Компонент if имеет два параметра —

  • test — простой параметр на основе свойств

  • Else — Расширенный параметр, используемый для указания альтернативной разметки, если условие не выполнено

test — простой параметр на основе свойств

Else — Расширенный параметр, используемый для указания альтернативной разметки, если условие не выполнено

Tapestry проверит значение свойства test, используя следующую логику, и вернет true или false. Это называется Type Coercion , способ преобразования объекта одного типа в другой тип с тем же содержимым.

  • Если тип данных — String , «True», если он не пустой, а не буквальная строка «False» (без учета регистра).

  • Если тип данных Number , True, если не ноль.

  • Если тип данных — Коллекция , True, если не пустой.

  • Если тип данных — Object , True (если он не нулевой).

Если тип данных — String , «True», если он не пустой, а не буквальная строка «False» (без учета регистра).

Если тип данных Number , True, если не ноль.

Если тип данных — Коллекция , True, если не пустой.

Если тип данных — Object , True (если он не нулевой).

Если условие выполняется, компонент отображает свое тело; в противном случае он отображает тело параметра else.

Полный список выглядит следующим образом —

package com.example.MyFirstApplication.pages; 
public class TestIf { 
   public String getUser() { 
      return "User1"; 
   } 
}

<html title = "If Test Page" 
   xmlns:t = "http://tapestry.apache.org/schema/tapestry_5_4.xsd" 
   xmlns:p = "tapestry:parameter">  
   
   <body> 
      <h1>Welcome!</h1>  
      <t:if test = "user"> 
         Welcome back, ${user} 
         <p:else>
            Please <t:pagelink page = "login">Login</t:pagelink>  
         </p:else> 
      </t:if>
   </body>
   
</html>

События компонента / навигация по страницам

Приложение Tapestry представляет собой набор страниц, взаимодействующих друг с другом. До сих пор мы узнали, как создавать отдельные страницы без какой-либо связи между ними. Основным назначением события компонента является обеспечение взаимодействия между страницами (в том числе и внутри страниц) с использованием событий на стороне сервера. Большинство событий компонента происходят из событий на стороне клиента.

Например, когда пользователь щелкает ссылку на странице, Tapestry сама вызывает ту же страницу с целевой информацией вместо вызова целевой страницы и вызывает событие на стороне сервера. Гобеленовая страница будет захватывать событие, обрабатывать информацию о цели и перенаправлять серверную страницу на целевую страницу.

Tapestry следует шаблону разработки Post / Redirect / Get (RPG) для навигации по страницам. В RPG, когда пользователь отправляет запрос, отправив форму, сервер обрабатывает опубликованные данные, но не возвращает ответ напрямую. Вместо этого он выполнит перенаправление на стороне клиента на другую страницу, которая выдаст результат. Шаблон RPG используется для предотвращения дублирования отправки форм с помощью кнопки возврата браузера, кнопки обновления браузера и т. Д. Tapestry предоставляет шаблон RPG, предоставляя следующие два типа запросов.

  • Запрос события компонента — этот тип запроса предназначен для определенного компонента на странице и вызывает события внутри компонента. Этот запрос только перенаправляет и не выводит ответ.

  • Запрос рендеринга — эти типы запросов предназначаются для страницы и направляют ответ обратно клиенту.

Запрос события компонента — этот тип запроса предназначен для определенного компонента на странице и вызывает события внутри компонента. Этот запрос только перенаправляет и не выводит ответ.

Запрос рендеринга — эти типы запросов предназначаются для страницы и направляют ответ обратно клиенту.

Чтобы понять события компонента и навигацию по страницам, нам нужно знать шаблон URL запроса гобелена. Шаблон URL для обоих типов запросов выглядит следующим образом:

  • Запросы событий компонентов

Запросы событий компонентов

/<<page_name_with_path>>.<<component_id|event_id>>/<<context_information>>
  • Запрос рендеринга

Запрос рендеринга

/<<page_name_with_path>>/<<context_information>>

Вот некоторые примеры шаблонов URL:

  • Индексную страницу можно запросить по https: // «домен» / «приложение» / index .

  • Если страница указателя доступна в подпапке admin, ее можно запросить по https: // «домен» / «приложение» / admin / index .

  • Если пользователь щелкает компонент ActionLink с идентификатором test на странице индекса, то URL будет https: // «домен» / «приложение» /index.test .

Индексную страницу можно запросить по https: // «домен» / «приложение» / index .

Если страница указателя доступна в подпапке admin, ее можно запросить по https: // «домен» / «приложение» / admin / index .

Если пользователь щелкает компонент ActionLink с идентификатором test на странице индекса, то URL будет https: // «домен» / «приложение» /index.test .

События

По умолчанию Tapestry вызывает события OnPassivate и OnActivate для всех запросов. Для типа запроса события компонента гобелен вызывает дополнительные одно или несколько событий в зависимости от компонента. Компонент ActionLink вызывает событие Action, а компонент Form вызывает несколько событий, таких как Validate, Success и т. Д.,

События могут быть обработаны в классе страницы, используя соответствующий обработчик метода. Обработчик метода создается либо с помощью соглашения об именовании методов, либо с помощью аннотации @OnEvent . Формат соглашения об именах методов: «EventName» из «ComponentId» .

Событие действия компонента ActionLink с тестом id может быть обработано любым из следующих методов:

void OnActionFromTest() { 
}  
@OnEvent(component = "test", name = "action") 
void CustomFunctionName() { 
} 

Если имя метода не имеет какого-либо конкретного компонента, метод будет вызван для всех компонентов с совпадающими событиями.

void OnAction() { 
} 

Событие OnPassivate и OnActivate

OnPassivate используется для предоставления контекстной информации для обработчика события OnActivate. В общем, Tapestry предоставляет контекстную информацию, и ее можно использовать в качестве аргумента в обработчике OnActivateevent.

Например, если контекстная информация имеет тип 3 типа int, событие OnActivate можно вызвать как —

void OnActivate(int id) { 
} 

В некоторых случаях контекстная информация может быть недоступна. В этой ситуации мы можем предоставить контекстную информацию обработчику события OnActivate через обработчик события OnPassivate. Тип возвращаемого значения обработчика события OnPassivate должен использоваться в качестве аргумента обработчика события OnActivate.

int OnPassivate() { 
   int id = 3; 
   return id; 
} 
void OnActivate(int id) { 
} 

Возвращаемые значения обработчика событий

Tapestry выполняет перенаправление страниц на основе возвращаемых значений обработчика событий. Обработчик события должен возвращать любое из следующих значений.

  • Null Response — Возвращает нулевое значение. Tapestry создаст URL текущей страницы и отправит клиенту в качестве перенаправления.

Null Response — Возвращает нулевое значение. Tapestry создаст URL текущей страницы и отправит клиенту в качестве перенаправления.

public Object onAction() { 
   return null; 
}
  • String Response — Возвращает строковое значение. Tapestry создаст URL-адрес страницы, соответствующий значению, и отправит клиенту в качестве перенаправления.

String Response — Возвращает строковое значение. Tapestry создаст URL-адрес страницы, соответствующий значению, и отправит клиенту в качестве перенаправления.

public String onAction() { 
   return "Index"; 
}
  • Ответ класса — возвращает класс страницы. Tapestry создаст URL-адрес возвращаемого класса страницы и отправит клиенту в качестве перенаправления.

Ответ класса — возвращает класс страницы. Tapestry создаст URL-адрес возвращаемого класса страницы и отправит клиенту в качестве перенаправления.

public Object onAction() { 
   return Index.class 
}
  • Ответ страницы — возвращает поле, помеченное @InjectPage. Tapestry создаст URL внедренной страницы и отправит клиенту в качестве перенаправления.

Ответ страницы — возвращает поле, помеченное @InjectPage. Tapestry создаст URL внедренной страницы и отправит клиенту в качестве перенаправления.

@InjectPage 
private Index index;  

public Object onAction(){ 
   return index; 
}
  • HttpError — Возвращает объект HTTPError. Tapestry выдаст ошибку HTTP на стороне клиента.

HttpError — Возвращает объект HTTPError. Tapestry выдаст ошибку HTTP на стороне клиента.

public Object onAction(){ 
   return new HttpError(302, "The Error message); 
}
  • Ответ ссылки — возвращает экземпляр ссылки напрямую. Tapestry создаст URL из объекта Link и отправит клиенту в качестве перенаправления.

  • Stream Response — возвращает объект StreamResponse . Tapestry отправит поток в ответ непосредственно браузеру клиента. Он используется для генерации отчетов и изображений напрямую и отправки его клиенту.

  • Url Response — Возвращает объект java.net.URL . Гобелен получит соответствующий URL-адрес от объекта и отправит клиенту в качестве перенаправления.

  • Ответ объекта — возвращает любые значения, отличные от указанных выше значений. Гобелен вызовет ошибку.

Ответ ссылки — возвращает экземпляр ссылки напрямую. Tapestry создаст URL из объекта Link и отправит клиенту в качестве перенаправления.

Stream Response — возвращает объект StreamResponse . Tapestry отправит поток в ответ непосредственно браузеру клиента. Он используется для генерации отчетов и изображений напрямую и отправки его клиенту.

Url Response — Возвращает объект java.net.URL . Гобелен получит соответствующий URL-адрес от объекта и отправит клиенту в качестве перенаправления.

Ответ объекта — возвращает любые значения, отличные от указанных выше значений. Гобелен вызовет ошибку.

Контекст события

В общем случае обработчик события может получить контекстную информацию, используя аргументы. Например, если контекстная информация имеет тип 3 типа int, тогда обработчик события будет:

Object onActionFromTest(int id) {  
} 

Tapestry правильно обрабатывает контекстную информацию и предоставляет ее методам через аргументы. Иногда Tapestry может не справиться с этим должным образом из-за сложности программирования. В это время мы можем получить полную контекстную информацию и обработать сами.