Reading Time: 7 minutes

Struts framework trong Java là bản triển khai ban đầu của mẫu thiết kế Model-View-Controller và đã phát triển rất nhiều cùng với các cải tiến mới nhất trong Java và các công nghệ Java EE. Bài hướng dẫn Struts này nhằm cung cấp những thông tin cơ bản về Struts 2 và cách chúng ta có thể tạo ứng dụng “Hello World” đầu tiên với Struts 2.

Struts framework trong Java

Struts 2

Apache Struts 2 là một framework mã nguồn mở, tiêu chuẩn công nghiệp, linh hoạt và có thể mở rộng để xây dựng ứng dụng web Java EE. Struts 2 được phát triển dựa trên nền tảng OpenSymphony WebWork.

Struts 2 rất linh hoạt trong phát triển và cấu hình, và chúng ta sẽ thấy việc phát triển một ứng dụng web bằng framework Struts 2 đơn giản như thế nào.

Sơ đồ kiến trúc Struts 2

Sơ đồ dưới đây thể hiện các thành phần khác nhau của Struts 2 trong một ứng dụng web.

Struts 2 Architecture Diagram

Struts 2 Interceptors

Interceptor trong Struts giống như Servlet Filters, được thực thi trước và sau khi xử lý request. Chúng được sử dụng để thực hiện các thao tác chung cho nhiều action khác nhau. Ví dụ như:

  • Ghi log
  • Kiểm tra session
  • Thêm các header chung vào esponse

Struts 2 ValueStack và OGNL

ValueStack là vùng lưu trữ dữ liệu mà Struts 2 sử dụng để lưu trữ dữ liệu ứng dụng trong quá trình xử lý request của client. Dữ liệu được lưu trong các đối tượng ActionContext, sử dụng ThreadLocal để đảm bảo dữ liệu riêng biệt cho mỗi thread xử lý request.

OGNL (Object-Graph Navigation Language) là một ngôn ngữ biểu thức mạnh mẽ, được sử dụng để thao tác dữ liệu được lưu trên ValueStack. Như bạn có thể thấy trong sơ đồ kiến trúc, các interceptor và các trang kết quả đều có thể truy cập dữ liệu trên ValueStack bằng OGNL.

Struts 2 Action

Action trong Struts 2 chịu trách nhiệm xử lý các request từ phía client. Có nhiều cách khác nhau để tạo một lớp Action trong Struts 2:

  • Cài đặt interface com.opensymphony.xwork2.Action.
  • Kế thừa class com.opensymphony.xwork2.ActionSupport thường dùng khi muốn tạo một action đơn giản để chuyển tiếp request.
  • Sử dụng Annotation: đánh dấu class với @Action hoặc @Actions.
  • Theo convention: đặt tên class kết thúc bằng Action và có phương thức execute().

Struts 2 Result

Result component thường là các trang JSP hoặc HTML để tạo phần giao diện phản hồi cho client. Struts 2 cung cấp một tập các Struts Tags có thể sử dụng trong các trang JSP để tạo giao diện.

Kiến trúc khai báo và cách kết nối trong Struts 2

Struts 2 hỗ trợ hai cách để cấu hình các class Action và các trang Result:

  1. File Struts XML:

Chúng ta có một file tên là struts.xml nằm trong thư mục WEB-INF/classes, nơi dùng để cấu hình các lớp ActionResult cho ứng dụng.

  1. Annotation:

Chúng ta có thể sử dụng Java Annotation để cung cấp thông tin metadata cho các lớp. Struts 2 hỗ trợ plugin convention, cho phép chúng ta dùng các annotation như @Action@Result để chú thích trực tiếp trên lớp Java, từ đó tự động cấu hình các lớp action và các trang kết quả liên quan.

Dù bạn dùng cách nào để cấu hình, kết quả cuối cùng đều như nhau.

Hướng dẫn Struts – Ứng dụng Hello World với XML Configuration

Hãy cùng xem cách tạo ứng dụng Hello World với Struts 2 đầu tiên của chúng ta.

Trước tiên, ta cần các file Struts 2 JAR. Tuy nhiên, khi bạn kiểm tra thư mục libs trong gói tải về, bạn sẽ thấy có rất nhiều file .jar không cần thiết cho một ứng dụng đơn giản.

Vì vậy, trong hướng dẫn này, mình sẽ tạo một dự án Maven và chỉ thêm dependency cho struts2-core. Những thư viện phụ thuộc khác sẽ được Maven tự động tải và thêm vào ứng dụng.

Cấu trúc cuối cùng của dự án sẽ giống như hình dưới đây.

Struts 2 Hello World Project

Tạo một Dynamic Web Project mới tên là Struts2XMLHelloWorld trong Eclipse và sau đó chuyển nó thành dự án Maven như hình ảnh bên dưới.

Convert Dynamic Web Application To Maven Project

Bạn sẽ thấy tệp pom.xml được thêm vào thư mục gốc của dự án. Cấu hình dự án trong Eclipse đã sẵn sàng, giờ hãy cùng xem qua các thành phần khác nhau theo thứ tự.

pom.xml

Mở tệp pom.xml và thêm dependency cho Struts core, tệp pom.xml hoàn chỉnh sẽ trông như sau.

<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>Struts2XMLHelloWorld</groupId>
	<artifactId>Struts2XMLHelloWorld</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>
	</dependencies>
	<build>
		<sourceDirectory>src</sourceDirectory>
		<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>

Lưu ý rằng tôi đã ghi đè phần tử finalName để tránh việc số phiên bản bị thêm vào tên file WAR khi thực hiện build bằng Maven. Các phần còn lại được Eclipse tự động thêm vào, dependency duy nhất mà chúng ta cần là struts2-core, với phiên bản hiện tại là 2.3.15.1 (tính đến ngày 10 tháng 9 năm 2013).

Chỉ cần build ứng dụng bằng Maven, bạn sẽ thấy rất nhiều file JAR được thêm vào thư mục lib của ứng dụng và hiển thị trong phần Maven Dependencies của dự án như hình dưới đây.

Struts2 maven dependencies

Cấu hình Struts 2 trong web.xml

Chúng ta cần thêm filter org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter vào file cấu hình web.xml của ứng dụng web. Đồng thời, phải chỉ định URL pattern để xác định những request nào sẽ do Struts xử lý.

File web.xml của chúng ta sẽ trông giống như sau:

<?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>"
	version="3.0">
	<display-name>Struts2XMLHelloWorld</display-name>
	
	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

Đối với Struts 2 phiên bản dưới 2.1.3, lớp filter được sử dụng là org.apache.struts2.dispatcher.FilterDispatcher.

Hướng dẫn Struts – Result Pages

Chúng ta có ba trang JSP sẽ được sử dụng trong ứng dụng, và chúng ta sẽ dùng các thẻ của Struts 2 để xây dựng các trang JSP này. 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>

Lưu ý rằng các trường trong biểu mẫu có tên là namepwd. Chúng ta sẽ thấy cách chúng được sử dụng trong các lớp Action. 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>

Lưu ý thẻ Struts s:property mà chúng ta có thể sử dụng để lấy các thuộc tính từ request; tên thuộc tính này giống với tên được sử dụng trong login.jsp. 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>

Đây là một trang JSP đơn giản, nơi chúng ta hiển thị thông báo lỗi và bao gồm lại trang đăng nhập trong response.

Các lớp Action

Ứng dụng của chúng ta chỉ có một lớp Action, nơi chúng ta triển khai Struts 2 Action interface. LoginAction.java

package com.journaldev.struts2.action;

import com.opensymphony.xwork2.Action;

public class LoginAction implements Action {
	
	@Override
	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;
	}
	
}

Lưu ý rằng lớp action cũng là một Java Bean với các biến trùng tên với những gì đã khai báo trong login.jsp, và có các phương thức getter và setter tương ứng. Struts sẽ tự động mapping các tham số từ request đến các biến trong lớp action này.

Tệp Cấu hình

Vì chúng ta đang sử dụng cấu hình dựa trên XML để kết nối các thành phần trong ứng dụng, nên cần tạo một tệp cấu hình Struts với tên struts.xml và đặt trong thư mục WEB-INF/classes. struts.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"<https://struts.apache.org/dtds/struts-2.3.dtd>">
<struts>

<package name="user" namespace="/User" extends="struts-default">
	<action name="home">
		<result>/login.jsp</result>
	</action>
	<action name="login" class="com.journaldev.struts2.action.LoginAction">
	<result name="SUCCESS">/welcome.jsp</result>
	<result name="ERROR">/error.jsp</result>
	</action>

</package>

</struts>

Đối với action “home”, không có lớp Action nào được định nghĩa, và chỉ có một trang kết quả duy nhất, nên request sẽ được chuyển tiếp trực tiếp đến trang login.jsp.

Còn đối với action “login”, lớp LoginAction sẽ đảm nhận việc xử lý. Nếu phương thức execute() của lớp này trả về “SUCCESS”, yêu cầu sẽ được chuyển đến trang welcome.jsp; ngược lại, nếu trả về “ERROR” thì sẽ được chuyển tiếp đến trang error.jsp.

Thuộc tính namespace=”/User” rất quan trọng vì nó được dùng trong URL để truy cập các lớp action, cho phép chúng ta tách biệt thành các module khác nhau. Ví dụ, để truy cập ứng dụng, ta sẽ dùng URL như sau:

https://localhost:8080/Struts2XMLHelloWorld/User/home.action

Chú ý rằng URL kết thúc bằng .action, đây là hậu tố mặc định cho action trong Struts 2, tương tự như .do trong Struts 1.

Chạy thử ứng dụng Hello World Struts 2

Khi chúng ta chạy ứng dụng, các trang phản hồi sau sẽ hiển thị.

Struts Hello World XML login

Struts Hello World XML Home

Struts Hello World XML Error

0 Bình luận

Đăng nhập để thảo luận

Chuyên mục Hướng dẫn

Tổng hợp các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.

Đăng ký nhận bản tin của chúng tôi

Hãy trở thành người nhận được các nội dung hữu ích của CyStack sớm nhất

Xem chính sách của chúng tôi Chính sách bảo mật.

Đăng ký nhận Newsletter

Nhận các nội dung hữu ích mới nhất