Struts Framework – ตัวอย่าง Application ง่ายๆ

มาพบกันอีกรอบ กับบทความเกี่ยวกับ Struts Framework ฉบับภาษาไทย ตอนที่ 3 หล่ะ

คราวนี้ เพื่อช่วยให้เห็นภาพการทำงานของ Struts แบบคร่าวๆ
ผมจึงได้สร้างตัวอย่างโปรแกรมง่ายๆ ขึ้นมาหนึ่งตัว
ผมตั้งชื่อว่า mini book store
การทำงานง่ายๆ ทำได้แค่ค้นหารายการหนังสือแค่นั้นเอง
โดยค้นหาจากชื่อหนังสือ หรือ หมายเลข isbn

รายการไฟล์ที่ผมต้องการครับ

index.jsp
เก็บโค้ด jsp สำหรับหน้าแรกของโปรแกรม Mini Book Store
และมีลิงก์ไปหน้าค้นหาหนังสือ

search.jsp
เก็บโค้ด jsp สำหรับการค้นหาหนังสือและแสดงผลลัพท์การค้นหา

SearchForm.java
เป็นคลาสในส่วนของ View ที่ใช้เก็บและเคลื่อนย้ายข้อมูลจากหน้าค้นหา

SearchAction.java
เป็นคลาสในส่วนของ Controller ที่ประมวลผลคำขอจากหน้าค้นหา

BookSearchService.java
เป็นคลาสในส่วนของ Model ที่ห่อหุ้ม (Encapsulate) business logic
และ ข้อมูลต่างๆ ที่เกี่ยวข้องกับการค้นหาหนังสือ

Book.java
เป็นคลาสในส่วนของ Model ที่ใช้แทนข้อมูล
และห่อหุ้ม (Encapsulate) ข้อมูลของหนังสือ

MessageResources.properties
ใช้เก็บข้อความที่สามารถแก้ไข้ได้โดยไม่ต้อง Compile โปรแกรมใหม่

struts-config.xml
ได้มาจากการวางโครง Struts
ซึ่งเอาไว้เก็บ config ของ Struts
ถ้าได้อ่านบทความ struts hello world ก็คงคุ้นหน้ากันดี

โครงสร้างของโปรเจคมีดังนี้

1 - project structure

ทีนี้ก็เป็นโค้ดของแต่ละไฟล์
index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
<!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=UTF-8">
<title><bean:message key="label.app.name" /></title>
</head>
<body>
<h3><bean:message key="label.book.portal" /></h3>
<hr width="100%" noshade="noshade" />
<ul>
	<li><html:link forward="search">Search book</html:link></li>
</ul>
</body>
</html>

รูปของหน้า index.jsp

2 - index

ก็เป็น html ธรรมดาๆ ที่เพิ่ฒ jsp taglib เข้าไป
ในการจะใช้ taglib เราต้องทำสิ่งที่เรียกว่า การ import taglib ก่อน
ซึ่งก็คือ

<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>

ในหน้านี้มีเรียกใช้ taglib สามที่
แต่ผมขอยกสองตัวมาอธิบาย เพราะอีกอันทำหน้าที่ซ้ำกัน

<title><bean:message key="label.app.name" /></title>

เป็นการเรียกค่าของคีย์ที่ชื่อ label.app.name จากไฟล์ MessageResources.properties

<html:link forward="search">Search book</html:link>

เป็นการสร้างลิงก์โดยอ่านจาก struts-config.xml
ซึ่งต้องระบุว่า forward นี้จะให้ไปหน้าใหน
ดังนี้

<global-forwards>
  <forward name="search" path="/search.jsp"/>
</global-forwards>

search.jsp
เมื่อทำการคลิกลิงก์จากหน้า index.jsp
ก็จะแสดงหน้านี้

3 - search form

เมื่อมีการค้นหา ตัว Struts Control ก็จะประมวลผล
แล้วกลับมาแสดงที่หน้านี้อีกครับ

4 - search result

หากไม่ได้กรอกข้อมูลแล้วทำการกดปุ่มค้นหา
ระบก็จะแสดงข้อความดังนี้

5 - search wrong criteria

โค้ดของไฟล์ search.jsp มีดังนี้

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%>
<!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=UTF-8">
<title><bean:message key="label.app.name" /></title>
<style type="text/css">
fieldset ul,fieldset li {
	border: 0;
	margin: 0;
	padding: 0;
	list-style: none;
}

fieldset li {
	clear: both;
	list-style: none;
	padding-bottom: 10px;
}

fieldset input {
	float: left;
}

fieldset label {
	width: 100px;
	float: left;
}

#notfound {
	font-weight: bold;
	color: red;
}
#showresult{
	border-width: 1px;
	border-style: solid;
	border-color: #600;
	border-collapse: separate;
}
#showresult td{
    border-width: 1px;
    border-style: solid;
    margin: 0;
    padding: 4px;
    background-color: #FFC;
}
</style>
</head>
<body>
<h3><bean:message key="label.book.portal" /></h3>
<hr width="100%" noshade="noshade" />

<html:errors />

<html:form action="/search">
	<fieldset><legend>Search Form</legend>
	<ul>
		<li><label for="name"><bean:message
			key="label.search.book.name" /></label><html:text property="name" /></li>
	</ul>
	----- <bean:message key="label.search.or" /> -----<br />
	<ul>
		<li><label for="isbn"><bean:message
			key="label.search.book.isbn" /></label><html:text property="isbn" /></li>
	</ul>
	</fieldset>
	<html:submit />
</html:form>

<logic:present name="searchForm" property="results">
	<hr width="100%" noshade="noshade" />
	<bean:size id="size" name="searchForm" property="results" />

	<logic:equal name="size" value="0">
		<div id="notfound"><bean:message
			key="message.search.book.not.found" /></div>
	</logic:equal>

	<logic:greaterThan name="size" value="0">
		<table id="showresult">
			<tr>
				<th>Name</th>
				<th>ISBN</th>
			</tr>
			<logic:iterate id="result" name="searchForm" property="results">
				<tr>
					<td><bean:write name="result" property="name" /></td>
					<td><bean:write name="result" property="isbn" /></td>
				</tr>
			</logic:iterate>
		</table>
	</logic:greaterThan>
</logic:present>
</body>
</html>

ในไฟล์นี้มีการใช้ taglib 3 ตัวคือ

<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%>

แท็กที่น่าสนใจมีดังนี้

<html:errors />

ในใช้การแสดงผลข้อผิดพลาดจากการตรวจสอบคำที่ใช้ในการค้นหา

<bean:message key="label.search.book.name" />

ใช้ในการดึงข้อความจากไฟล์ MessageResources.properties
ซึ่งเก็บในรูปแบบ key/value

<html:text property="name" />

property ที่มีค่าเท่ากับ name นี้
เมื่อแสดงผลเป็น html แล้วจะได้

<input type="text" name="name"/>

สอดคล้องกับตัวแปร name ในคลาส SearchForm
หมายความว่า หากตัวแปร name ใน SearchForm มีค่าอะไร
ค่าของ input นี้ก็จะเปลี่ยนตาม
หรือเมื่อมีการกรอกค่าใน input นี้
ตัวแปร name ก็จะเป็นคนเก็บค่าไว้

<html:form action="/search">

เมื่อแสดงผลเป็น html แล้วก็จะได้ tag form ทั่วไป
ที่กำหนด action ไปที่ /search

และส่วนสุดท้ายที่สำคัญคือสนส่วน logic tag
และ tag ที่ใช้ในการแสดงผลลัพท์

<logic:present name="searchForm" property="results">

ใช้ในการตรวจสอบว่ามีตัวแปร results ใน searchForm มีค่าหรือไม่
searchForm ได้มาจากการ config SearchForm ใน struts-config.xml
หากไม่มีค่า ก็จะไม่มีการทำงานต่อภายในแท็กนี้

<bean:size id="size" name="searchForm" property="results" />

แท็ก size คือ การดึงค่าขนาดของตัวแปรจาก searchForm ที่ชื่อว่า results
ซึ่งเป็น ArrayList ของผลลัพท์การค้นหาหนังสือ
มาเก็บไว้ในตัวแปรที่ชื่อ size

<logic:equal name="size" value="0">

เป็นการเปรียบเทียบค่าตัวแปรที่เราสร้างไว้จากแท็กด้านบน
ก็คือตัวแปร size ว่าเท่ากับศูนย์หรือไม่
ความหมายคือ มีผลลัพท์การค้นหาหนังสือหรือไม่
ถ้ามีก็ให้เข้าไปทำงานในแท็ก equals
ซึ่งก็คือแสดงข้อความว่า No book found

<logic:greaterThan name="size" value="0">

คล้ากับแท็กด้านคือ แต่เป็นการเปรียบเทียบว่า
ค่า size มีค่ามากกว่า 0 หรือไม่

<logic:iterate id="result" name="searchForm" property="results">

สรุปง่ายๆ คือเป็นการวนลูปค่าตัวแปร results ใน searchForm
ซึ่งชื่อตัวแปรนี้ได้มาจากตอนลงทะเบียน SearchForm.java ใน struts-config.xml
โดยมีตัวแปร result (ไม่มีตัว s) มารับค่าของแต่ละ Element ใน Arraylist

<bean:write name="result" property="name" />

อย่าสับสนกับแท็ก bean:message นะครับ
แท็ก bean:write เอาไว้แสดงผลสำหรับ Object ครับ
จากตัวอย่างนี้คือ แสดงผลตัวแปร name ใน Object ที่ชื่อ result
ซึ่งตัวแปร result ก็ได้จากการประกาศแท็ก iterate ก่อนหน้านี้

SearchForm.java
เป็น View class ที่ใช้ในการเก็บค่าและส่งค่าจากหน้า Search
เมื่อหน้า Search ถูก submit ตัว ActionServlet ของ Struts ก็จะอัพเดทค่าให้เอง
ซึ่งหน้า Form นี้จะเป็นการ map แบบ หนึ่งตือหนึ่ง
คือหนึ่ง Form class ต่อหนึ่ง Page
โดยตัวแปรใน From ต้องมี getter/setter
และคนที่สามารถอัพเดทค่าให้ Form คือ Action class
ซึ่งคลาสของเราก็คือ SearchAction

โค้ดที่อยู่ข้างใน SearchForm.java

package com.minibook;

import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;

import com.minibook.dao.Book;

public class SearchForm extends ActionForm {
	
	private String name;
	private String isbn;
	private List<Book> results;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getIsbn() {
		return isbn;
	}
	public void setIsbn(String isbn) {
		this.isbn = isbn;
	}
	public List<Book> getResults() {
		return results;
	}
	public void setResults(List<Book> results) {
		this.results = results;
	}
	
	@Override
	public void reset(ActionMapping mapping, HttpServletRequest request) {
		name = null;
		isbn = null;
		results = null;
	}
	
	@Override
	public ActionErrors validate(ActionMapping mapping,
			HttpServletRequest request) {
		
		ActionErrors errors = new ActionErrors();
		boolean nameEntered = false;
		boolean isbnEntered = false;
		
		if(name != null && name.trim().length() > 0) {
			nameEntered = true;
		}
		
		if(isbn != null && isbn.trim().length() > 0){
			isbnEntered = true;
		}
		
		if(!nameEntered && !isbnEntered){
			errors.add("", new ActionMessage("error.search.criteria.missing"));
		}
		
		return errors;
	}
	
}

SearchForm ต้องสืบทอด ActionForm
(ยกเว้นเราเขียนคลาสขึ้นมาใหม่แล้วเราไปสืบทอดต่ออีกที)
จะเห็นได้ว่า SearchForm ก็เป็น java bean ธรรมดา
ที่เพิ่มเมธอด reset() และ validate()
ซึ่งเป็นเมธอดของ Struts ที่ทำงานเหมือนชื่อของเมธอดเลย
คือ เมธอด reset() ก็ใช้ในการ reset ค่า หรือ clear ค่าของ ActionForm
โดยเมธอดนี้จะถูกเรียกทุกครั้งที่มี request เข้ามา
ตัว Struts จะทำการ reuse instance ของ ActionForm แทนที่จะสร้างใหม่ ทุกๆ request
เมธอด reset() จำเป็นในการทำให้มั่นใจว่า
ข้อมูลของแต่ละ request จะไม่ผสมกันมั่ว

เมธอด validate() ทำหน้าที่ใหนการ validate พื้นฐานที่ส่งมาจาก form ของหน้า html
ซึ่งในที่นี้ ได้ทำการตรวจสอบว่า มีการกรอกชื่อหนังสือ หรือ isbn มาหรือไม่
หรือถ้าไม่กรอกทั้งสองมา ก็แจ้ง error ออกไป
ย้ำอีกทีว่า เมธอด validate() นี้ใช้สำหรับการ validate ขั้นพื้นฐานเท่านั้น
ไม่เหมาะสำหรับการ validate ระดับ business เช่น
สมมุติว่าระบบนี้เพิ่มเติมการสมัครสมาชิก
แล้วต้องทำการตรวจสอบหมายเลขบัตรประชาชนกับข้อมูลใน database ว่าหรือการสมัครไว้ก่อนหน้าหรือยัง
อันนี้คือ Business-level validation.
เพราะมันต้องไปตรวจสอบที่ Model class

เมธอด validate() จะ return object ของคลาส ActionErrors
ซึ่งในกรณีที่การ validate ไม่ผ่าน เราสามารถส่งข้อความที่จะแสดงหน้าผ่านทาง object นี้
โดยหน้า search.jsp ของเราจะมีแท็ก

<html:errors/>

ไว้แสดงผลของการ validate อยู่แล้ว
วิธีการส่ง error มาที่หน้าจอคือ
สร้าง instance ของ ActionErrors
จากนั้นก็ใช้เมธอด add()
โดยพารามิเตอร์คือ key ที่อ้างอิง error นี้และ Message ที่ต้องการแสดง
ประโยชน์ของการใช้ key ก็คือ
ในกรณีที่เราต้องการแสดง error เฉพาะจุด เช่นหลัง textfield
เราก็จะสามารถอ้างอิงผ่าน key นี้ได้
จากโค้ดตัวอย่างของเรา
errors.add(“”, new ActionMessage(“error.search.criteria.missing”));
จะเห็นได้ว่าไม่ได้ระบุ key ไว้ แสดงว่า ไม่สามารถระบุตำแหน่ง แสดง error ที่จุดอื่นได้
และ message ด้านหลังคือ key ที่เก็บไว้ในไฟล์ MessageResources.properties

SearchAction.java
เป็นส่วนของ Controller ที่ใช้ประมวลผลการค้นหาของหน้า search
มีโค้ดดังนี้

package com.minibook;

import java.util.ArrayList;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.minibook.dao.Book;
import com.minibook.service.BookSearchService;

public class SearchAction extends Action {
	@Override
	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		
		SearchForm searchForm = (SearchForm)form;
		BookSearchService service = new BookSearchService();
		ArrayList<Book> results = new ArrayList<Book>();
		
		String name = searchForm.getName();
		if(name != null && name.trim().length() > 0){
			results = service.searchByName( name.trim() );
		}else{
			String isbn = searchForm.getIsbn();
			if(isbn != null && isbn.trim().length() > 0){
				results = service.searchByIsbn( isbn.trim() );
			}			
		}
		
		searchForm.setResults(results);
		
		return mapping.getInputForward();
	}
}

SearchAction สืบทอดมาจากคลาส Action
แล้วทำการ override เมธอด execute()
ซึ่งเมธอดนี้จะถูกเรียกโดย ActionServlet (สั้นๆ คือ struts เป็นคนเรียกเอง)
ซึ่งเป็นเมธอดเดียวเท่านั้นที่ ActionServlet จะเรียกได้
หากเคยเขียน Servlet มาจะรู้สึกคุ้นๆ เหมือนกับเมธอด doGet(), doPost()
เพียงแต่มีการเพิ่มส่วนของ Struts ขึ้นมาคือ ActionMapping และ ActionForm
instance ของ ActionForum ก็คือ instance ของหน้า SearchForm ของเรา
ส่วน instance ของ ActionMapping จะเก็บ config ทั้งหมดของ struts-config.xml เฉพาะที่เกี่ยวข้องกับ Action นี้

การทำงานของคลาสนี้คือ
มีการสร้าง object บางตัว
แล้วทำการตรวจสอบรูปแบบการค้นหาว่า เป็นการค้นหาด้วยชื่อหนังสือ หรือ isbn
โดยดูว่า หากกรอก name เข้ามา หมายถึงต้องการค้นหาด้วยชื่อหนังสือ
ซึ่งในตอนนี้ผมไม่ได้ทำให้สามารถค้นหาได้แบบที่กรอกทั้ง name และ isbn

BookSearchService.java
เป็นคลาส Model ที่ทำการ encapsulate ส่วนของ business logic
และการเข้าถึง data ที่ใช้ในการค้นหาหนังสือ
เมื่อทำการค้นหาหนังสือเสร็จแล้วก็จะส่งข้อมูลไปให้ในส่วน View

โค้ดมีดังนี้

package com.minibook.service;

import java.util.ArrayList;

import com.minibook.dto.Book;

public class BookSearchService {
	//hard-coded book data
	private static Book[] books = {
		new Book("jsp1", "11111111"),
		new Book("ebj1", "22222222"),
		new Book("servlet1", "33333333"),
		new Book("jquery1", "44444444"),
		new Book("hibernate1", "55555555"),
		new Book("struts1", "66666666"),
		new Book("spring1", "77777777"),
		new Book("jsp2", "111111112"),
		new Book("ebj2", "222222223"),
		new Book("servlet3", "333333334"),
		new Book("jquery2", "444444445"),
		new Book("hibernate3", "555555556"),
		new Book("struts4", "666666667"),
		new Book("spring5", "777777778")
	};
	
	public ArrayList<Book> searchByName(String name){
		return searchBook("name", name);
	}
	
	public ArrayList<Book> searchByIsbn(String isbn){
		return searchBook("isbn", isbn);
	}
	
	private ArrayList<Book> searchBook(String type, String searchData){
		ArrayList<Book> results = new ArrayList<Book>();
		
		for (Book book : books) {
			String bookData = null;
			if(type.equals("name")){
				bookData = book.getName().toLowerCase();
			}else{//by isbn
				bookData = book.getIsbn().toLowerCase();
			}
			
			if(bookData.contains( searchData.toLowerCase() )){
				results.add(book);
			}
		}
		
		return results;
	}
}

เนื่องจากต้องการให้โปรแกรมนี้ให้เข้าใจง่าย
จึงไม่ได้ทำการเขียนให้ติดต่อกับแหล่งเก็บข้อมูลจริง (เช่น database)
จึงได้ทำการ hard-code ลงไปในนี้เลย

Book.java
เป็นคลาสสำหรับการ Encapsulate ข้อมูลของหนังสือ
เป็น java bean ธรรมดา มีโค้ดดังนี้

package com.minibook.dto;

public class Book {
	private String name;
	private String isbn;
	
	public Book(String name, String isbn) {
		this.name = name;
		this.isbn = isbn;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getIsbn() {
		return isbn;
	}
	public void setIsbn(String isbn) {
		this.isbn = isbn;
	}
}

คลาสนี้ถูกใช้โดย BookSearchService
ในการขนส่งข้อมูลผลลัพธ์การค้นหาหนังสือ
จาก Model (BookSearchService) ไปยังส่วน View (search.jsp)
บ่อยครั้งเราจะได้ยินชื่อว่า DTO (Data Transfer Object)
หรือ VO (Value Object)

struts-config.xml
น่าจะเรียกได้ว่า เป็นศูนย์กลางของ Struts เลยก็ว่าได้
เพราะว่าเก็บ config ทุกอย่างของ Struts ไว้ที่นี่
ซึ่งถูกใช้โดย Actionservlet
ซึ่ง config ที่เราใช้ในโปรแกรมค้นหาหนังสือมีดังนี้

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
          "http://struts.apache.org/dtds/struts-config_1_3.dtd">

<struts-config>

<!-- ================================================ Form Bean Definitions -->

    <form-beans>
		<form-bean name="searchForm" type="com.minibook.SearchForm"/>
    </form-beans>

	
<!-- ========================================= Global Exception Definitions -->

    <global-exceptions>
    </global-exceptions>


<!-- =========================================== Global Forward Definitions -->

    <global-forwards>
        <forward name="search" path="/search.jsp"/>
    </global-forwards>


<!-- =========================================== Action Mapping Definitions -->

    <action-mappings>
            
		<action path="/search"
			type="com.minibook.SearchAction"
			name="searchForm"
			scope="request"
			validate="true"
			input="/search.jsp"
			/>
			
    </action-mappings>


<!-- ======================================== Message Resources Definitions -->

    <message-resources parameter="MessageResources" />


<!-- =============================================== Plug Ins Configuration -->

  <!-- ======================================================= Tiles plugin -->
  
  <!-- =================================================== Validator plugin -->

  <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
    <set-property
        property="pathnames"
        value="/org/apache/struts/validator/validator-rules.xml,
               /WEB-INF/validation.xml"/>
  </plug-in>

</struts-config>

มาดูทีละส่วนกัน

	<form-beans>
		<form-bean name="searchForm" type="com.minibook.SearchForm"/>
    </form-beans>

เป็นส่วนของ config Form Bean
ซึ่ง Form Bean ทั้งหมดในโปรเจคจะต้องมาลงทะเบียนที่นี่
จึงจะใช้งาน Form Bean นั้นได้
จากตัวอย่างก็อ่านชัดเจนคือ ตั้งชื่อว่า searchForm และคลาสที่ใช้คือ com.minibook.SearchForm

	<global-forwards>
        <forward name="search" path="/search.jsp"/>
    </global-forwards>

คือรายการ forward ที่ระบบของเรามี
ซึ่ง forward เป็นกระบวนการในการตั้งชื่อให้กับหน้า page ปลายที่เราต้องการ
จากตัวอย่างคือ ตั้งชื่อว่า search โดยปลายทางคือหน้า search.jsp

	<action-mappings>
            
		<action path="/search"
			type="com.minibook.SearchAction"
			name="searchForm"
			scope="request"
			validate="true"
			input="/search.jsp"
			/>
			
    </action-mappings>

ส่วนนี้ใช้ในการลงทะเบียนคลาส Action กับ path ที่ต้องการ
โดยใน web.xml ที่เราทำการ copy มาจากไฟล์ struts-blank-1.3.10.war
ระบุไว้ว่า URL ทุกอันที่ลงท้ายด้วย .do จะถูกจัดการด้วยคลาส ActionServlet
ซึ่งการกำหนด path เป็น “/search” ให้กับ action นี้ก็คือ
ถ้ามีการ request “/search.do” ก็จะถูกจัดการโดย SearchAction
โดย Struts จะทำการลบ .do ออกจาก request url (ก็จะเหลือแค่ /search)
จากนั้นก็จะไปดูใน struts-config.xml เพื่อนที่จะดูว่ามี Action ใหนลงทะเบียนกับ url นี้
เพื่อที่จะได้เรียกขึ้นมาทำงาน
type ซึ่งก็คือคลาส Action ที่ต้องการให้ทำงาน
name คือชื่อของ Form Bean ที่ต้องการใช้
scope และ validate เป็นส่วนที่ใช้กำหนดการทำงานของ Form Bean
โดย scope จะกำหนด scope ของ Form Bean เช่น
request ก็คือ request scope
session ก็คือ session scope
เป็นต้น
ส่วน validate คือกำหนดว่า Form Bean ที่ใช้ใน action นี้ (Form Bean ที่ใช้ก็คือที่ระบุใน name)
เมธอด validate() จะถูกเรียกหลังจากทำการอัพเดทค่าของฟอร์มเสร็จแล้ว
ส่วนสุดท้ายคือ input ใช้ในการระบุว่าหน้า page ที่เป็น input ข้อมูลให้ action นี้
ตัว Struts จะทำการ forward ไปหน้าที่ระบุไว้ใน input กรณีที่ผลการ validate ไม่ผ่าน

<message-resources parameter="MessageResources" />

เคยพูดไปตอนโปรแกรม Struts Framework – Hello world ภาษาอังกฤษ/ภาษาไทย
คือระบุตำแหน่งที่เก็บไฟล์ MessageResources.properties

MessageResources.properties
ข้อความมีดังนี้

#–label–
label.app.name=Mini Book Store
label.book.portal=Book Portal
label.search.book.name=Book name
label.search.book.isbn=ISBN
label.search.or=or

#–message–
message.search.book.not.found=No book found

#–error–
errors.header=

    errors.footer=

errors.prefix=

  • errors.suffix=
  • error.search.criteria.missing=Search Criteria Missing

    6 thoughts on “Struts Framework – ตัวอย่าง Application ง่ายๆ

    1. สอบถามการใช้ input เป็นภาษาไทย อะครับ ไม่ทราบต้องตั้งค่าอย่างไร
      พอดีลองนำ Application นี้ไปใช้ดู แต่ไม่สนับสนุนภาษาไทยทั้งที่ภายในตั้งชื่อหนังสือภาษาไทยได้
      โชว์ค่า ภาษาไทยได้ แต่ตอนใส่ input ภาษาไทย กลับหาไม่เจอ

      รบกวนด้วยครับ

    2. ไม่ทราบว่าได้ลองสั่งแสดงค่า input ที่รับจากหน้าจอหรือยังครับว่า เป็นภาษาไทยที่อ่านออก ไม่ได้เป็นภาษาต่างดาว

    Leave a Reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out / Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out / Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out / Change )

    Google+ photo

    You are commenting using your Google+ account. Log Out / Change )

    Connecting to %s