Giới thiệu về Struts 2

https://codersontrang.com/2014/01/09/gioi-thieu-ve-struts-2/

Struts2 là một trong những framework được sử dụng để phát triển các ứng dụng web. Tương tự với Spring MVC, Struts2 cũng tuân theo mô hình xử lý MVC mà ở đó bản thân nó có chứa đầy đủ các thành phần giúp các lập trình viên định nghĩa một cách rõ ràng Model, View và Controller. Struts2 cũng là một sự cải thiện so với phiên bản trước của nó là Struts1, với Struts2 việc định nghĩa ra các thành phần nói trên sẽ trở nên dễ dàng và sáng sủa hơn rất nhiều so với người anh em của nó là Struts1.

Bài viết này sẽ giới thiệu về Struts2 và các thành phần chính của nó. Bài viết sẽ dùng một ví dụ đơn giản để minh họa cho cơ chế hoạt động của framework này. Trước tiên bài viết sẽ nêu ra một cái nhìn tổng quan về các thành phần của Struts2 cùng với những ánh xạ tương ứng sang các thành phần trong mô hình MVC.

Model: là các lớp java định nghĩa các đối tượng để chứa dữ liệu (hay còn gọi là các POJO). Trong các lớp này chỉ đơn thuần định nghĩa ra các thuộc tính của đối tượng và getter, setter tương ứng với chúng.

View: là các trang *.jsp, dùng để hiển thị dữ liệu đến người dùng. Việc lấy dữ liệu từ model để hiển thị lên view được thực hiện nhờ thành phần của Struts2 có tên là OGNL (Object-Graph Navigation Language) với các thẻ hay còn gọi là custom tag của nó được sử dụng trên các trang *.jsp

Controller : là phần xử lý logic, trong Struts2 thì Controller còn được gọi là Action. Mỗi Action sẽ là một lớp java có chứa tham chiếu đến model, và từ đó có thể truy cập trực tiếp dự liệu từ model. Dữ liệu lấy từ model sẽ được lấy ra và xử lý bên trong các phương thức của lớp đó. Mỗi phương thức sau khi xử lý dữ liệu xong sẽ cập nhật lại những thay đổi vào model và sau đó chuyển hướng đến một View tương ứng để hiển thị kết quả của sự xử lý đến người dùng.

Để cụ thể hóa những thành phần đã nói ở trên, chúng ta sẽ tạo ra một ví dụ cụ thể để minh họa. Dùng Eclipse IDE để tạo ra một Web Project với cấu trúc như hình dưới đây:

strut2demo_1

Để sử dụng Struts2, ta phải cấu hình trong file web.xml như hình dưới đây:

web.xml

 <?xml version="1.0" encoding="UTF-8"?>  
 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">  
  <display-name>Struts2Demo</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>

Tương tự như các framewwork cài đặt pattern Front Servlet, mọi request đến ứng dụng web có sử dụng Struts2 đều phải đi qua một điểm và ở đây là một filter có kiểu org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter. Filter này dựa vào file cấu hình của struts để từ đó biết được sẽ phải chuyển tiếp request đó đến Action nào cho việc xử lý tiếp theo. Ta có nhắc đến file cấu hình của struts, đó là file struts.xml như hình dưới đây:

struts.xml

 <?xml version="1.0" encoding="UTF-8" ?>  
 <!DOCTYPE struts PUBLIC  
 "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
 "http://struts.apache.org/dtds/struts-2.0.dtd">  
 <struts>  
      <package name="base-package" namespace="/" extends="struts-default">  
      </package>  
      <!-- ===== Include Configuration For Particular Modules===== -->       
      <include file="struts-student.xml"/>  
 </struts>  

File cấu hình struts.xml cho phép định nghĩa ra với một request được submit lên một url, thì request đó sẽ được chuyển tiếp đến phương thức nào của Action nào cho việc xử lý tiếp theo. Tiếp đó, file cấu hình này cũng chỉ ra View nào sẽ được dùng để hiển thị kết quả trả về sau khi việc xử lý request từ phía Action đã hoàn thành. Nội dung cấu hình sẽ được định nghĩa bên trong thẻ <struts>, bên trong sẽ là các thẻ <package>, <action>, <result> mà chúng ta sẽ nói cụ thể hơn với ví dụ ở đoạn sau.

Như chúng ta biết, một ứng dụng web bao giờ cũng có rất nhiều phần (modules), mỗi phần thực hiện một hay một số các nghiệp vụ nào đó có liên quan đến nhau. Nếu việc cấu hình cho tất cả các phần đều được khai báo trong file struts.xml thì file này dần sẽ trở nên rất dài và khó để quản lý về sau. Chính vì vậy, trong thực tế, file struts.xml chỉ dùng để khai báo những thông tin cấu hình chung cho toàn bộ ứng dụng web. Còn những thông tin cấu hình cho từng phần riêng biệt sẽ được khai báo ở file cấu hình (.xml) riêng, rồi sau đó sẽ được gộp vào file struts.xml bằng việc sử dụng thẻ <include>. Ở ví dụ của của bài viết này, ta có một phần cho việc xử lý các nghiệp vụ liên quan đến sinh viên, vì thế ta có một file là struts-student.xml để định nghĩa các thông tin cấu hình cụ thể cho phần này.

struts-student.xml

 <?xml version="1.0" encoding="UTF-8" ?>  
 <!DOCTYPE struts PUBLIC  
 "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"  
 "http://struts.apache.org/dtds/struts-2.0.dtd">  
 <struts>  
      <package name="student-package" namespace="

/student

" extends="base-package"> <action name="

student-authentication

" class="

struts2demo.action.StudentAction

" method="

showAuthentication

"> <result name="success">/WEB-INF/jsp/student/authentication-index.jsp</result> </action> <action name="

student-authentication-submit

" class="

struts2demo.action.StudentAction

" method="

authenicateStudent

"> <result name="input">/WEB-INF/jsp/student/authentication-index.jsp</result> <result name="success">/WEB-INF/jsp/student/authentication-success.jsp</result> <result name="error">/WEB-INF/jsp/student/authentication-error.jsp</result> </action> </package> </struts>

Mỗi một package sẽ định nghĩa ra một namespace cho một tập hợp các Action, mỗi action sẽ có tên để nhận ra bản thân nó bên trong package đó. Namespace của package và tên của Action sẽ tạo ra một phần của URL mà chúng ta sử dụng để submit request lên ứng dụng theo mẫu như sau:

URL = protocol://hostname:portnumber/servlet context/package namespace/action name

Như trên file cấu hình trên ta thấy ta có một package có tên là student-package với namespace là /student. Bên trong package này là định nghĩa hai Action có tên lần lượt là student-authenticationstudent-authentication-submit. Như vậy đối chiếu với mẫu bên trên, ta sẽ có hai URL được khai báo trong ứng dụng như sau:

http://localhost:8080/Struts2Demo/student/student-authentication
http://localhost:8080/Struts2Demo/student/student-authentication-submit

Trong thẻ <action> có thuộc tính classmethod chỉ ra phương thức thuộc lớp nào sẽ được gọi tới để xử lý request được submit lên URL tương ứng với Action. Trong ví dụ, khi ta submit một request lên URL http://localhost:8080/Struts2Demo/student/student-authentication-submit, thì phương thức authenicateStudent() trong lớp struts2demo.action.StudentAction sẽ được gọi để xử lý.

Phương thức authenicateStudent() trả về một String để nhận ra trang jsp (view) nào sẽ được gọi đển hiện thị kết quả xử lý. Việc ánh xạ từ String mà phương thức trong Action trả về với trang jsp sẽ được khai báo bằng thẻ <result>. Như file cấu hình ở trên chỉ ra, phương thức authenicateStudent() có thể trả về một trong ba giá trị là “input“, “success“, “error” tương ứng với việc ứng dụng sẽ hiển thị một trong 3 trang jsp là authentication-index.jsp, authentication-success.jsp, authentication-error.jsp đến sau khi request được xử lý xong.

Chúng ta có thể nhìn rõ ràng hơn những gì đã nói ở trên khi nhìn vào Action xử lý các request trong ví dụ như dưới đây:

StudentAction.java

 package struts2demo.action;  
 import struts2demo.model.StudentModel;  
 import com.opensymphony.xwork2.ActionSupport;  
 import com.opensymphony.xwork2.ModelDriven;  
 public class StudentAction extends ActionSupport implements ModelDriven<StudentModel>{  
      private StudentModel model = new StudentModel();  
      @Override  
      public StudentModel getModel() {  
           return model;  
      }  
      public String 

showAuthentication

(){ return SUCCESS; } public String

authenicateStudent

(){ String studentId = model.getStudent().getId(); if(studentId == null || studentId.trim().isEmpty()){ return INPUT; } if(!"codersontrang".equals(studentId)){ return ERROR; } return SUCCESS; } }

Mọi Action của Struts2 cài đặt interface là com.opensymphony.xwork2.Action. Tuy nhiên trong ví dụ, StudentAction kế thừa từ lớp com.opensymphony.xwork2.ActionSupport là một cài đặt của interface com.opensymphony.xwork2.Action mà struts2 cung cấp sẵn. ActionSupport cung cấp một số các hằng tiện ích như INPUT, SUCCESS, ERROR tương ứng với các giá trị “input“, “success“, “error” để ta có thể dùng làm giá trị trả về cho các phương thức trong Action. Chú ý một điều là các phương thức trong Action không nhất thiết phải là một 3 giá trị nêu trên mà nó có thể là bất kì giá trị kiểu String nào. Chỉ là khi chúng ta trả về một giá trị nào đó, thì giá trị đó phải được khai báo trong thẻ <result> trong file cấu hình của struts.

StudentAction cũng cài đặt một interface là com.opensymphony.xwork2.ModelDriven để định nghĩa ra model sẽ liên kết với Action này, model cũng sẽ là nơi mà Action lấy ra dữ liệu được submit lên từ phía View (jsp) để cho các xử lý tiếp sau. Trong ví dụ, StudentAction sẽ lấy dữ liệu từ model là một đối tượng thuộc kiểu struts2demo.model.StudentModel. Interface ModelDriven có một phương thức getModel() mà Action sẽ phải cài đặt để trả về đối tượng của model đi cùng với Action đó.

Dưới đây sẽ là định nghĩa của hai lớp StudentModelStudent. Chúng đều là các POJO (Plain Old Java Object) bình thường gồm có các thuộc tính và getter, setter cho các thuộc tính đó.

StudentModel.java

 package struts2demo.model;  
 public class StudentModel {  
      private Student student = new Student();  
      public Student getStudent() {  
           return student;  
      }  
      public void setStudent(Student student) {  
           this.student = student;  
      }  
 }  

Student.java

 package struts2demo.model;  
 public class Student {  
      private String id;  
      public String getId() {  
           return id;  
      }  
      public void setId(String id) {  
           this.id = id;  
      }  
 }  

Luồng logic xử lý bên trong StudentAction gồm hai luồng tương ứng với hai phương thức xử lý của nó là showAuthentication()authenicateStudent(). Khi có một request trên địa chỉ http://localhost:8080/Struts2Demo/student/student-authentication, phương thức showAuthentication() trong StudentAction được gọi và trả về giá trị là “success“. Nhìn lại vào file cấu hình struts-student.xml ta có thể thấy “success” được khai báo để trả về một trang jsp là authentication-index.jsp.

authentication-index.jsp

 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"  
   pageEncoding="ISO-8859-1"%>  
 <%@taglib uri="/struts-tags" prefix="s"%>  
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
 <html>  
 <head>  
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">  
 <title>Student Authentication</title>  
 </head>  
 <body>  
      <s:form action="/student/student-authentication-submit" method="post" theme="simple">  
           Please enter your student ID to authenticate:   
           

<s:textfield name="student.id"/>

<s:submit value="Authenticate"/> </s:form> </body> </html>

Lúc đó trên trình duyệt sẽ hiển thị lên nội dung của trang này như sau:

strut2demo_2

Khi nhập một giá trị cho Student ID và bấm vào nút Authenticate, lúc đó sẽ có một request đến URL http://localhost:8080/Struts2Demo/student/student-authentication-submit. Lúc này phương thức authenicateStudent() của StudentAction sẽ được gọi. Việc lấy dữ liệu từ trang jsp sau đó gán vào model được struts2 làm một cách tự động, bên trong các phương thức của Action chỉ việc lấy chúng ra từ model và xử lý. Trở lại với ví dụ, student ID được nhập từ màn hình sẽ được lấy ra từ model.getStudent().getId(). Chúng ta sẽ có câu hỏi tại sao lại có thể lấy ra từ đây ? Hãy để ý trên trang authentication-index.jsp, ta sử dụng thẻ <s:textfield name="student.id"/> là một thẻ mà struts2 cung cấp mà nhờ vào thuộc tính name của nó, struts2 có thể biết được giá trị được nhập trên màn hình phải được lưu lại ở đâu trên model để cho các xử lý tiếp theo.

Trở lại với phương thức authenicateStudent(), sau khi lấy được student ID, ta kiểm tra người dùng đã thực sự nhập giá trị cho nó trước khi bấm Authenticate hay chưa, nếu chưa thì trả về INPUT, và trang authication-index.jsp sẽ được hiện lên để người dùng nhập lại một student ID. Nếu người dùng đã nhập giá trị cho student ID thì ta kiểm tra giá trị này có phải là “codersontrang” hay không, nếu không phải thì sẽ trả về ERROR có nghĩa là trang authentication-error.jsp sẽ được hiện ra như dưới đây:

authentication-error.jsp

 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"  
   pageEncoding="ISO-8859-1"%>  
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
 <html>  
 <head>  
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">  
 <title>Authentication Fail</title>  
 </head>  
 <body>  
      <span style="text-transform:uppercase; color:red;">  
           Student failed to authenticate !   
      </span>  
 </body>  
 </html>  

strut2demo_3

Nếu giá trị của student ID nhập vào từ màn hình là “codersontrang“, thì giá trị SUCCESS được trả về, trang authentication-success.jsp được hiện ra như dưới đây:

authentication-success.jsp

 <%@ page language="java" contentType="text/html; charset=ISO-8859-1"  
   pageEncoding="ISO-8859-1"%>  
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
 <html>  
 <head>  
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">  
 <title>Authentication Success</title>  
 </head>  
 <body>  
      <span style="text-transform:uppercase; color:blue">  
           Student authenticates successfully !  
      </span>  
 </body>  
 </html>  

strut2demo_4

Như vậy trong bài viết đã giới thiệu đến bạn đọc về Struts2 và các thành phần cơ bản của nó trong việc sử dụng để tạo ra các ứng dụng web theo mô hình thiết kế MVC. Struts2 với cách thức cấu hình đơn giản và sáng sủa đã hoàn toàn thay thế phiên bản tiền nhiệm là Struts1 và bản thân nó đã và đang là một trong số các framework được sử dụng phổ biến trong quá trình phát triển ứng dụng web. Struts2 còn rất nhiều các thành phần với các tính năng khác mà chúng ta sẽ có cơ hội đề cập đến trong các bài viết sau.

Good luck!

Chia sẻ bài viết

Thích bài này:

Thích

Đang tải…