Создание проекта Struts 2 на основе аннотаций

В этом туториале мы разберем, как с помощью аннотаций или соглашении об именах обойтись без файла конфигурации 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

Добавить комментарий