Создание проекта Struts 2 на основе аннотаций
Development | Комментировать запись
В этом туториале мы разберем, как с помощью аннотаций или соглашении об именах обойтись без файла конфигурации Struts 2.
Конвенции в Struts 2
Для определения классов action и result в Struts 2 есть два способа. Для каждого способа нужен API-плагин struts2-convention-plugin. Если у вас есть обычное веб-приложение, можете скачать его jar-файл и поместить в каталог lib вашего приложения. Для maven проектов можно просто добавить зависимость, как показано ниже:
<dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-convention-plugin</artifactId> <version>2.3.15.1</version> </dependency>
Первый метод – сканирование. В этом методе нужно указать пакет, который необходимо сканировать на наличие action классов. Для фильтра Struts 2 конфигурация должна быть выполнена в web.xml:
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> <init-param> <param-name>actionPackages</param-name> <param-value>com.journaldev.struts2.actions</param-value> </init-param> </filter>
Struts 2 находит action классы следующими методами:
- Любой класс, аннотированный при помощи @Action или @Actions.
- Любой класс, реализующий интерфейс Action или расширяющий класс ActionSupport.
- Любой класс, название которого заканчивается на Action и который содержит метод execute(). Для этих классов соглашение об именах используется для определения action и result.
Также Struts 2 поддерживает соглашение об именах. Это работает так. Struts 2 автоматически создаст action для классов, названия которых заканчиваются на Action. Название action определяется путем удаления суффикса Action и конвертации первой буквы в нижний регистр. Итак, если название класса HomeAction, то action будет home. Если эти классы не аннотированы с помощью @Result для вывода результата, то страницы результата нужно искать в каталоге WEB-INF/content, при этом название должно быть {action}-{return_string}.jsp. Поэтому если action класс HomeAction возвращает success, то запрос будет перенаправлен на страницу WEB-INF/content/home-success.jsp. Использование одного только соглашения об именах может вызвать путаницу в работе и мы не сможем использовать ту же JSP-страницу для других action классов. Поэтому нужно стараться избегать этого и использовать конфигурацию на основе аннотаций.
Теперь у нас все готово для создания приложения Hello World в Struts 2 с аннотациями и без файла конфигурации Struts 2. Мы создадим динамический веб-проект в Eclipse Struts2AnnotationHelloWorld и конвертируем его в проект maven. Ниже показано, как выглядит финальный проект.
Конфигурация maven
Мы добавили зависимости struts2-core и struts2-convention-plugin в pom.xml. Получившийся код pom.xml будет таким:
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>Struts2AnnotationHelloWorld</groupId> <artifactId>Struts2AnnotationHelloWorld</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>wa</packaging> <dependencies> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-core</artifactId> <version>2.3.15.1</version> </dependency> <dependency> <groupId>org.apache.struts</groupId> <artifactId>struts2-convention-plugin</artifactId> <version>2.3.15.1</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>2.3</version> <configuration> <warSourceDirectory>WebContent</warSourceDirectory> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> <finalName>${project.artifactId}</finalName> </build> </project>
Конфигурация дескриптора развертывания
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>Struts2AnnotationHelloWorld</display-name> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> <init-param> <param-name>actionPackages</param-name> <param-value>com.journaldev.struts2.actions</param-value> </init-param> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
Обратите внимание на элемент init-param, в котором мы предоставляем пакет action классов.
Страницы результатов
В приложении есть три страницы результатов.
1: login.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd"> <%-- Using Struts2 Tags in JSP --%> <%@ taglib uri="/struts-tags" prefix="s"%> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <title>Login Page</title> </head> <body> <h3>Welcome User, please login below</h3> <s:form action="login"> <s:textfield name="name" label="User Name"></s:textfield> <s:textfield name="pwd" label="Password" type="password"></s:textfield> <s:submit value="Login"></s:submit> </s:form> </body> </html>
2: error.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <title>Error Page</title> </head> <body> <h4>User Name or Password is wrong</h4> <s:include value="login.jsp"></s:include> </body> </html>
3: welcome.jsp
<%@ page language="java" contentType="text/html; charset=US-ASCII" pageEncoding="US-ASCII"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII"> <title>Error Page</title> </head> <body> <h4>User Name or Password is wrong</h4> <s:include value="login.jsp"></s:include> </body> </html>
Теперь создадим Action классы, которые мы будем аннотировать для настройки страниц action и result.
Action классы с аннотациями
package com.journaldev.struts2.actions; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Actions; import org.apache.struts2.convention.annotation.Namespace; import org.apache.struts2.convention.annotation.Namespaces; import org.apache.struts2.convention.annotation.Result; import com.opensymphony.xwork2.ActionSupport; /** * An empty class for default Action implementation for: * * <action name="home"> * <result>/login.jsp</result> * </action> * HomeAction class will be automatically mapped for home.action * Default page is login.jsp which will be served to client * @author pankaj * */ @Namespaces(value={@Namespace("/User"),@Namespace("/")}) @Result(location="/login.jsp") @Actions(value={@Action(""),@Action("home")}) public class HomeAction extends ActionSupport{ }
Обратите внимание, что HomeAction — это пустой класс, у него одна задача — переадресовать запрос на страницу login.jsp.
package com.journaldev.struts2.actions; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Namespace; import org.apache.struts2.convention.annotation.Namespaces; import org.apache.struts2.convention.annotation.Result; /** * Notice the @Action annotation where action and result pages are declared * Also notice that we don't need to implement Action interface or extend ActionSupport * class, only we need is an execute() method with same signature * @author pankaj * */ @Action(value = "login", results = { @Result(name = "SUCCESS", location = "/welcome.jsp"), @Result(name = "ERROR", location = "/error.jsp") }) @Namespaces(value={@Namespace("/User"),@Namespace("/")}) public class LoginAction { public String execute() throws Exception { if("pankaj".equals(getName()) && "admin".equals(getPwd())) return "SUCCESS"; else return "ERROR"; } //Java Bean to hold the form parameters private String name; private String pwd; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } }
Обратите внимание на аннотации @Action, @Actions, @Result, @Namespace и @Namespaces, их использование не требует пояснений. Теперь при запуске приложения мы в качестве ответа получим следующие страницы.
Скачать пример проекта, разработанного на основе аннотаций Struts2, можно здесь.
Читайте также: Основы работы Spring: аннотация @Configuration