Struts Framework 2 – ตัวอย่าง Application ตอนที่ 2

บทความตอนที่แล้ว
Struts Framework 2 – ตัวอย่าง Application ตอนที่ 1

จากตอนที่ 1 เราได้เตรียมตัวพร้อมแล้วสำหรับการเขียน Web board ตอนที่ 2 นี้ก็เริ่มบันทึกข้อมูลลงฐานข้อมูลแล้ว
อย่าลืมลง MySQL แล้วดาวโหลด Driver มาไว้ด้วยนะ ผมใช้ mysql-connector-java-5.1.18

  1. แตก Zip Driver แล้ว Copy ไฟล์ mysql-connector-java-5.1.18-bin.jar ไปไว้ที่ WEB-NF/lib
  2. Copy ไฟล์ error.jsp ของ Project: bookstore มาไว้ที่ WebContent ของ Project: webboard
  3. เปิดไฟล์ main.jsp เพื่อสร้าง Form สำหรับกรอกข้อมูลเพื่อน Post ข้อความดังนี้
    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <%@ taglib prefix="s" uri="/struts-tags"%>
    <html>
    <head>
    <title>Web board</title>
    </head>
    <body>
    	<s:form>
    		<s:textarea name="message" label="ข้อความ" value="" />
    		<s:submit value="Post" align="center" />
    	</s:form>
    </body>
    </html>
    
  4. รันโปรแกรมเพื่อดูว่ามีฟอร์มปรากฏจริงหรือไม่ (ต่อไปถ้ามีการบอกว่าให้รันโปรแกรม ผมจะหมายถึงให้คลิกชื่อ Project แล้วเลือก Run As -> Run on Server) และเพื่อดูว่ามี error หรือไม่ ซึ่งถ้าไม่มีปัญหา จะพบหน้าจอดังรูป
    3 - post form

    ดูเสร็จแล้ว Stop Server ให้เรียบร้อย

  5. สร้างคลาส โดยกำหนดค่าดังนี้

    Package: webboard.dao
    Name: ConnectionManager

    คลาสนี้จะใช้เป็นตัวกลางที่เชื่อมต่อกับฐานข้อมูล ดังนี้

    package webboard.dao;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    
    public class ConnectionManager {
    	public static Connection getStatement() throws Exception {
    		Connection con = null;
    		String userName = "webboard";
    		String password = "webboard";
    		String url = "jdbc:mysql://localhost/webboard";
    		
    		// Load driver
    		Class.forName("com.mysql.jdbc.Driver").newInstance();
    		// Connect
    		con = DriverManager.getConnection(url, userName, password);
    		
    		return con;
    	}
    }
  6. สร้าง User และฐานข้อมูล ให้ข้อมูลในตรงกับข้อมูลในคลาส ConnectionManager.java
    จากนั้นสร้าง Table ที่ชื่อว่า posts รายละเอียดดังนี้

    CREATE  TABLE IF NOT EXISTS `webboard`.`posts` (
      `id` INT(11) NOT NULL AUTO_INCREMENT ,
      `post` VARCHAR(500) NOT NULL ,
      PRIMARY KEY (`id`) )
    ENGINE = InnoDB
    DEFAULT CHARACTER SET = utf8
    
  7. สร้างคลาส โดยกำหนดค่าดังนี้

    Package: webboard.dao
    Name: PostDAO

    คลาสนี้จะทำหน้าที่เป็นคนบันทึกข้อมูลลงฐานข้อมูล ซึ่งเป็นส่วนหนึ่งของ Model ใน MVC Pattern หากจำไม่ได้ให้ลองกลับไปอ่าน https://magickiat.wordpress.com/2010/10/05/struts-framework-the-model-in-mvc/
    โค้ดดังนี้

    package webboard.dao;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    
    
    public class PostDAO {
    	public void save(String post) throws Exception{
    		//Get Connection
    		Connection con = ConnectionManager.getConnection();
    		//Prepare sql to insert
    		PreparedStatement pstmt = con.prepareStatement("insert into posts(post) values(?)");
    		pstmt.setString(1, post);
    		//Method 'executeUpdate' can use Insert, Update, Delete
    		pstmt.executeUpdate();
    		//Close any connection
    		pstmt.close();
    		con.close();
    	}
    }
  8. สร้างคลาส โดยกำหนดค่าดังนี้

    Package: webboard.action
    Name: Post

    โค้ดดังนี้

    package webboard.action;
    
    import webboard.dao.PostDAO;
    
    public class Post {
    	private String message;
    
    	public String getMessage() {
    		return message;
    	}
    
    	public void setMessage(String message) {
    		this.message = message;
    	}
    	
    	public String post() throws Exception{
    		PostDAO postDAO = new PostDAO();
    		postDAO.save(message);
    		return "success";
    	}
    }

    เป็นคลาสที่ใช้ในการบันทึก post ลงฐานข้อมูล
    จุดแตกต่างอย่างหนึ่งของ Struts 2 กับ Struts 1 คือ เราจะไม่มีการสร้างคลาส Form โดยเราจะเอาตัวแปรมาประกาศไว้ในคลาส Action ในที่นี้คือตัวแปร message ก็จะตรงกับตัวแปร TextArea ในหน้า main.jsp
    และจุดที่สองคือ คลาส Action ไม่จำเป็นต้องสืบทอดคลาสอื่นๆ ก็สามารถทำงานได้

  9. ทำการ Config คลาส Action ให้ Struts รู้จัก โดยให้เปิดไฟล์ webboard.xml แล้วก็อปโค้ดนี้ไว้ใน Tag package
    <action name="postMessage" class="webboard.action.Post" method="post">
    	<result name="success">/main.jsp</result>
    </action> 

    เป็นการบอก Struts ว่า ถ้ามีคนร้องขอ postMessage เข้ามา ให้เรียกเมธอด post ของคลาส webboard.action.Post ขึ้นมาทำงาน และถ้าผลลัพท์ที่ได้จากคลาสเป็น String ที่มีค่าเป็น success ให้ส่งต่อไปที่หน้า main.jsp

  10. แก้ไขหน้า main.jsp เล็กน้อย ตรง Tag form ให้เพิ่มส่วนของ action ดังนี้
    <s:form action="postMessage.action"> 
  11. แก้ไขไฟล์ index.html ตรง URL ให้แก้เหลือแค่ index.action
    <META HTTP-EQUIV="Refresh" CONTENT="0;URL=index.action"></li> 
  12. รันโปรแกรมเพื่อทดสอบ ให้กรอกข้อความตามต้องการ แล้วกดปุ่ม Post ถ้าหากเกิด Error ก็จัดการตาม Error ที่พบ คาดว่าถ้าพบก็จะเป็น username/password ของฐานข้อมูลไม่ตรง หรือหา Driver ไม่เจอ หรือชื่อตัวแปร textarea ไม่ตรงกับใน Action
    แต่ถ้ากด Post แล้วหน้าจอนิ่ง ให้ไปตรวจสอบที่ฐานข้อมูล ถ้าพบข้อมูลใน Table posts แสดงว่าโปรแกรมทำงานถูกต้องแล้ว
  13. เนื่องจากเราไม่ทราบว่าโปรแกรมทำการ Insert ข้อมูลได้จริงหรือไม่ และไม่รู้ด้วยว่ามี Post ก่อนหน้านี้หรือไม่ เราจึงต้องทำการแก้ไขโปรแกรมโดยเพิ่มการแสดงผลในหน้า main.jsp ให้เพิ่มโค้ดนี้ต่อท้าย Tag
    <h2>Posts</h2>
    	<table>
    		<tr>
    			<td>ID</td>
    			<td>Message</td>
    		</tr>
    		<s:iterator value="posts" var="post">
    			<tr>
    				<td><s:property value="id" /></td>
    				<td><s:property value="post" /></td>
    			</tr>
    		</s:iterator>
    	</table>
     
  14. สร้างคลาส โดยกำหนดค่าดังนี้

    Package: webboard.dto
    Name: PostDTO

    โค้ดดังนี้

    package webboard.dto;
    
    public class PostDTO {
    	public int id;
    	public String post;
    }
    

    คลาสนี้จะใช้สำหรับการเก็บค่า เป็นเสมือนตัวแทนของแต่ละ Row ใน table post และมีหน้าที่ในการนำข้อมูลนี้ส่งไปมาระหว่าง Model – View – Controller ซึ่งเป็นหน้าที่หลักของ DTO

  15. แก้ไขคลาส PostDAO ให้เพิ่มเมธอดเพื่อดึงรายการ Post ทั้งหมด
    	public List<PostDTO> listPosts() throws Exception{
    		List<PostDTO> posts = new ArrayList<PostDTO>();
    
    		// Get Connection
    		Connection con = ConnectionManager.getConnection();
    		Statement stmt = con.createStatement();
    		//Query posts
    		ResultSet rs = stmt.executeQuery("select id, post from posts");
    		if(rs != null){
    			while(rs.next()){
    				PostDTO post = new PostDTO();
    				post.id = rs.getInt(rs.findColumn("id"));
    				post.post = rs.getString(rs.findColumn("post"));
    				posts.add(post);
    			}
    		}
    		
    		return posts;
    	}
  16. แก้ไขคลาส Post โดยประกาศตัวแปรนี้ และเพิ่ม getter/setter
    private List<PostDTO> posts;
    	
    public List<PostDTO> getPosts() {
    	return posts;
    }
    
    public void setPosts(List<PostDTO> posts) {
    	this.posts = posts;
    }

    ซึ่งชื่อตัวแปรนี้จะตรงกับตัวแปรใน Tag integrator ในหน้า main.jsp
    และแก้ไขเมธอด post เป็นดังนี้

    	public String post() throws Exception{
    		PostDAO postDAO = new PostDAO();
    		postDAO.save(message);
    		posts = postDAO.listPosts();
    		return "success";
    	}

    จุดที่แก้คือเพิ่ม listPosts() ขึ้นมาหลังจาก save()

  17. ให้ลบข้อมูลในฐานข้อมูลที่เคยบันทึกไว้ก่อนหน้านี้ แล้วค่อยรันโปรแกรมเพื่อทดสอบ ถ้าถูกต้อง ควรจะได้ดังรูป
    4 - show posts
  18. ถ้าหากไม่ลบข้อมูลก่อน เวลาที่เรารันโปรแกรมครั้งแรก เราจะไม่พบ post ก่อนหน้าที่บันทึกไปแล้ว วิธีการแก้ไขคือ ให้สร้างเมธอดในคลาส Post ดังนี้
    	public String load() throws Exception{
    		PostDAO postDAO = new PostDAO();
    		posts = postDAO.listPosts();
    		return "success";
    	}

    จากนั้นเปิดไฟล์ struts.xml แล้วแก้ไข action index ให้เป็นดังนี้

    		<action name="index" class="webboard.action.Post" method="load">
    			<result name="success">/main.jsp</result>
    		</action>

    ลองรันโปรแกรมใหม่อีกครั้ง คราวนี้เราก็จะเห็น post ก่อนหน้านี้แล้ว

ดาวโหลด source code ได้ที่ http://www.4shared.com/file/AqLW7Hds/webboard_ch2.html

แหล่งอ้างอิง

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