웹사이트 검색

주석이 있고 struts.xml 파일이 없는 Struts 2 Hello World 예제


이것은 Struts 2 Tutorials 시리즈의 두 번째 기사입니다. 직접 오셨다면 이전 포스팅도 보시는 것을 추천드립니다. Struts 2 Beginners Tutorial 지난 튜토리얼에서 우리는 Struts 2 아키텍처와 구성 요소를 살펴보고 XML 기반 구성(struts.xml)을 사용하여 간단한 Struts 2 웹 애플리케이션을 구축했습니다. 이 튜토리얼에서는 어노테이션이나 명명 규칙을 사용하여 struts 구성 파일을 완전히 피할 수 있는 방법을 볼 것입니다.

Struts 2 컨벤션 개념

Struts 2는 두 가지 방법론을 사용하여 액션 클래스와 결과 클래스를 찾습니다. 이러한 방법론을 사용하려면 struts2-convention-plugin API를 사용해야 합니다. 일반 웹 애플리케이션이 있는 경우 jar 파일을 다운로드하여 웹 애플리케이션 lib 디렉토리에 넣을 수 있습니다. Maven 프로젝트의 경우 아래와 같이 간단하게 종속성을 추가할 수 있습니다.

<dependency>
	<groupId>org.apache.struts</groupId>
	<artifactId>struts2-convention-plugin</artifactId>
	<version>2.3.15.1</version>
</dependency>
  1. Scanning: In this method, we specify package which needs to be scanned for action classes. The configuration needs to be done in web.xml for Struts 2 filter, like below.

    <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 will find action classes by following methods.

    • Any class annotated with @Actions annotations.
    • Any class implementing Action interface or extending ActionSupport class.
    • Any class whose name ends with Action and contains execute() method. For these classes, naming convention is used to determine action and results.
  2. Naming Convention: Struts 2 will automatically create action for classes name ending with Action. The action name is determined by removing the Action suffix and converting first letter to lowercase. So if class name is HomeAction, then action will be “home”. If these classes are not annotated with @Result to provide the result, then result pages are looked into WEB-INF/content directory and name should be {action}-{return_string}.jsp. So if HomeAction action class is returning “success”, the request will be forwarded to WEB-INF/content/home-success.jsp page. Using naming convention alone can be very confusing and we can’t use same JSP page for other action classes. So we should try to avoid this and use annotation based configuration.

메이븐 구성

pom.xml에 struts2-core 및 struts2-convention-plugin 종속성을 추가했으며 최종 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>war</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>

struts 2에서 스캔할 작업 클래스 패키지를 제공하는 init-param 요소에 주목하십시오.

결과 페이지

애플리케이션에는 세 개의 결과 페이지가 있습니다. 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>

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>

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>Welcome Page</title>
</head>
<body>
<h3>Welcome <s:property value="name"></s:property></h3>
</body>
</html>

이제 작업 및 결과 페이지를 구성하기 위해 주석을 추가할 작업 클래스를 만들어 보겠습니다.

주석이 있는 작업 클래스

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;
	}
}

Struts2 주석 예제 프로젝트 다운로드