[Struts2]從頭開始-簡易CRUD範例實作

開發工具:Eclipse / Maven

AP:Tomcat 6

資料庫:MySQL 5.6

畫面:

Class Diagram:

Sequence Diagram:(僅舉add部份)

先使用 MySQL 建立一張Table

語法:

CREATE TABLE `tbl_user` (

  `userId` int(11) NOT NULL,

  `name` varchar(20) DEFAULT NULL,

  `sex` varchar(10) DEFAULT NULL,

  `age` int(11) DEFAULT NULL,

  PRIMARY KEY (`userId`)

) ENGINE=InnoDB DEFAULT CHARSET=big5;

請順手建立幾筆測試資料!!!!

接著我們準備要用來接取資料的 UserModel

package com.Model;

public class UserModel {

        private int userId;

        private String name;

        private String sex;

        private int age;

        

        public int getUserId() {

                return userId;

        }

        public void setUserId(int userId) {

                this.userId = userId;

        }

        public String getName() {

                return name;

        }

        public void setName(String name) {

                this.name = name;

        }

        public String getSex() {

                return sex;

        }

        public void setSex(String sex) {

                this.sex = sex;

        }

        public int getAge() {

                return age;

        }

        public void setAge(int age) {

                this.age = age;

        }

        

        public int hashCode(){

                final int prime =31;

                int result = 1;

                result = prime * result + userId;

                return result;

        }

        

        public boolean equals(Object obj){

                if(this == obj){

                        return true;

                }

                

                if(obj == null){

                        return false;

                }

                

                if(getClass() != obj.getClass()){

                        return false;

                }

                

                final UserModel other = (UserModel) obj;

                if(userId != other.userId){

                        return false;

                }

                

                return true;

        }

}

我們先準備一個 DataSourceHolder,算是一個中繼點,或是一個Service,讓其幫我們處理與資料庫之間的開啟與中斷。當中使用了BasicDataSource 代替一般的 jdbc (Class.forName(driver)) 設定方式。

package com.util;

import javax.sql.DataSource;

import org.apache.tomcat.dbcp.dbcp.BasicDataSource;

public class DataSourceHolder {

        private BasicDataSource ds = new BasicDataSource();

        

        private DataSourceHolder(){

                //ds.setDriverClassName("org.gjt.mm.mysql.Driver");

                ds.setDriverClassName("com.mysql.jdbc.Driver");

                ds.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=big5");

                ds.setUsername("root");

                ds.setPassword("XXXXXX");

        }

        

        private static class SingletonHolder{

                private static DataSourceHolder instance = new DataSourceHolder();

        }

        

        public static DataSourceHolder getInstance(){

                return SingletonHolder.instance;

        }

        

        public DataSource getDataSources(){

                return ds;

        }

}

裡面因為有考慮到查詢資料時的條件,故我們會需要在編寫一個 UserQueryModel 其繼承自 UserModel用於查詢資料用,於 Dao 中的 getByCondition() Function 會使用到

package com.Model;

public class UserQueryModel extends UserModel {

        private int age2;

        public int getAge2() {

                return age2;

        }

        public void setAge2(int age2) {

                this.age2 = age2;

        }

}

再來編寫Dao的部份:

當中就是使用我們建立好的 DataSourceHolder,當作我們與 db 之間的好朋友。記得 DataSource使用完後,必須要記得關閉其與 DB 之間的連線喔

package com.CRUD;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.ArrayList;

import java.util.List;

import com.Model.UserModel;

import com.Model.UserQueryModel;

import com.util.DataSourceHolder;

public class UserJDBCDao {

        public void create(UserModel user){

                Connection conn = null;

                try {

                        conn= DataSourceHolder.getInstance().getDataSources().getConnection();

                        final String sql = "insert into tbl_user(userId,name,sex,age) values(?,?,?,?)";

                        PreparedStatement ps = conn.prepareStatement(sql);

                        int count =1 ;

                        ps.setInt(count++, user.getUserId());

                        ps.setString(count++, user.getName());

                        ps.setString(count++, user.getSex());

                        ps.setInt(count++, user.getAge());

                        ps.execute();

                        

                        ps.close();

                } catch (Exception e) {

                        e.printStackTrace();

                } finally{

                        try {

                                conn.close();

                        } catch (SQLException e) {

                                e.printStackTrace();

                        }

                }

        }

        

        public void update(UserModel user){

                Connection conn = null;

                try {

                        conn= DataSourceHolder.getInstance().getDataSources().getConnection();

                        final String sql = "update tbl_user set name=?,sex=?,age=? where userId=?";

                        PreparedStatement ps = conn.prepareStatement(sql);

                        int count =1 ;

                        ps.setString(count++, user.getName());

                        ps.setString(count++, user.getSex());

                        ps.setInt(count++, user.getAge());

                        ps.setInt(count++, user.getUserId());

                        ps.execute();

                        

                        ps.close();

                } catch (Exception e) {

                        e.printStackTrace();

                } finally{

                        try {

                                conn.close();

                        } catch (SQLException e) {

                                e.printStackTrace();

                        }

                }

        }

        

        public void delete(int userId){

                Connection conn = null;

                try {

                        conn= DataSourceHolder.getInstance().getDataSources().getConnection();

                        final String sql = "delete from tbl_user where userId=?";

                        PreparedStatement ps = conn.prepareStatement(sql);

                        ps.setInt(1, userId);

                        ps.execute();

                        

                        ps.close();

                } catch (Exception e) {

                        e.printStackTrace();

                } finally{

                        try {

                                conn.close();

                        } catch (SQLException e) {

                                e.printStackTrace();

                        }

                }

        }

        

        public UserModel getSingle(int userId){

                UserModel user = null;

                Connection conn = null;

                try {

                        conn = DataSourceHolder.getInstance().getDataSources().getConnection();

                        final String sql = "select * from tbl_user where userId=?";

                        PreparedStatement ps = conn.prepareStatement(sql);

                        ps.setInt(1, userId);

                        ResultSet rs = ps.executeQuery();

                        if(rs.next()){

                                user = this.rs2Model(rs);

                        }

                        

                        rs.close();

                        ps.close();

                } catch (Exception e) {

                        e.printStackTrace();

                } finally {

                        try {

                                conn.close();

                        } catch (SQLException e) {

                                e.printStackTrace();

                        }

                }

                

                return user;

        }

        

        private UserModel rs2Model(ResultSet rs) throws Exception{

                UserModel user = new UserModel();

                user.setUserId(rs.getInt("userId"));

                user.setName(rs.getString("name"));

                user.setSex(rs.getString("sex"));

                user.setAge(rs.getInt("age"));

                return user;

        }

        

        public List<UserModel> getAll(){

                List<UserModel> list = new ArrayList<UserModel>();

                Connection conn = null;

                try {

                        conn = DataSourceHolder.getInstance().getDataSources().getConnection();

                        final String sql = "select * from tbl_user order by userId";

                        PreparedStatement ps = conn.prepareStatement(sql);

                        ResultSet rs = ps.executeQuery();

                        while(rs.next()){

                                UserModel user = this.rs2Model(rs);

                                list.add(user);

                        }

                        

                        rs.close();

                        ps.close();

                } catch (Exception e) {

                        e.printStackTrace();

                } finally {

                        try {

                                conn.close();

                        } catch (SQLException e) {

                                e.printStackTrace();

                        }

                }

                

                return list;

        }

        

        private String generateWhere (UserQueryModel uqm){

                StringBuffer buffer = new StringBuffer();

                //用戶是否選用用戶編號作為條件

                if(uqm.getUserId()>0){

                        buffer.append(" and userId = ?");

                }

                //用戶是否選用用戶姓名作為條件

                if(uqm.getName()!=null && uqm.getName().trim().length()>0){

                        buffer.append(" and name like ?");

                }

                //用戶是否選用用戶姓性別為條件

                if(uqm.getSex()!=null && uqm.getSex().trim().length()>0){

                        buffer.append(" and sex = ?");

                }

                //用戶是否選用用戶姓年齡最小值為條件

                if(uqm.getAge()>0){

                        buffer.append(" and age >= ?");

                }

                //用戶是否選用用戶姓年齡最大值為條件

                if(uqm.getAge()>0){

                        buffer.append(" and age <= ?");

                }

                

                return buffer.toString();

        }

        

        private void preparePs(UserQueryModel uqm,PreparedStatement ps) throws SQLException{

                int count = 1;

                if(uqm.getUserId()>0){

                        ps.setInt(count++, uqm.getUserId());

                }

                

                if(uqm.getName()!=null && uqm.getName().trim().length()>0){

                        ps.setString(count++, "%" + uqm.getName() + "%" );

                }

                

                if(uqm.getSex()!=null && uqm.getSex().trim().length()>0){

                        ps.setString(count++, uqm.getSex());

                }

                

                if(uqm.getAge()>0){

                        ps.setInt(count++, uqm.getAge());

                }

                

                if(uqm.getAge2()>0){

                        ps.setInt(count++, uqm.getAge2());

                }

        }

        

        public List<UserModel> getByCondition(UserQueryModel uqm){

                List<UserModel> list = new ArrayList<UserModel>();

                Connection conn = null;

                

                try {

                        conn = DataSourceHolder.getInstance().getDataSources().getConnection();

                        final String sql = "select * from tbl_user where 1=1 " +

                                        this.generateWhere(uqm) + " order by userId";

                        PreparedStatement ps = conn.prepareStatement(sql);

                        this.preparePs(uqm, ps);

                        ResultSet rs = ps.executeQuery();

                        while(rs.next()){

                                UserModel user = this.rs2Model(rs);

                                list.add(user);

                        }

                        

                        rs.close();

                        ps.close();

                } catch (Exception e) {

                        e.printStackTrace();

                } finally {

                        try {

                                conn.close();

                        } catch (SQLException e) {

                                e.printStackTrace();

                        }

                }

                

                return list;

        }

}

接著我們可以先把畫面設計好:

index.jsp 就省略不說,裡面就是使用

<s:form action="/crud1/userToList" method="POST">

        <s:submit value="開始" />

</s:form>

跳轉到我們的主畫面中。

再來我們可以看一下,stuts.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>

        <constant name="struts.devMode" value="true" />

        <constant name="struts.locale" value="zh_TW" />

        <constant name="struts.i18n.encoding" value="UTF-8" />

        <!-- 允許使用OGNL -->

        <constant name="struts.ognl.allowStaticMethodAccess" value="true" />

        <!-- 使用struts2 ui -->

        <!-- <constant name="struts.ui.theme" value="simple" /> -->

        <constant name="struts.ui.theme" value="xhtml" />

        

        <package name="crud1" namespace="/crud1" extends="struts-default">

        

                <global-results>

                        <result name="toList">/list.jsp</result>

                </global-results>

                <action name="userToList" class="com.Action.UserAction" method="toList">

                </action>

                <action name="userToAdd" class="com.Action.UserAction" method="toAdd">

                        <result name="toAdd">/add.jsp</result>

                </action>

                <action name="userAdd" class="com.Action.UserAction" method="add" />

                <action name="userToUpdate" class="com.Action.UserAction" method="toUpdate">

                        <result name="toUpdate">/update.jsp</result>

                </action>

                <action name="userUpdate" class="com.Action.UserAction" method="update" />

                <action name="userDelete" class="com.Action.UserAction" method="delete" />

                <action name="userToQuery" class="com.Action.UserAction" method="toQuery">

                        <result name="toQuery">/query.jsp</result>

                </action>

                <action name="userQuery" class="com.Action.UserAction" method="query" />

        </package>

</struts>

用來顯示主要資料的頁面:

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<%@ taglib prefix="s" uri="/struts-tags" %>

<!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>顯示使用者資料</title>

</head>

<body>

<hr>

<table border="1" cellpadding="1" cellspacing="0" align="center">

        <tr>

                <td>編號</td>

                <td>姓名</td>

                <td>性別</td>

                <td>年齡</td>

                <td>操作</td>

        </tr>

<s:iterator value="list">

        <tr>

                <td><s:property value="userId"/></td>

                <td><s:property value="name"/></td>

                <td><s:property value="sex"/></td>

                <td><s:property value="age"/></td>

                <td>

                <!--

                        <a href="/HelloStruts2_CRUD_001/crud1/userToAdd.action">添加用戶</a>|

                         -->

                        <a href="<s:url action='userToAdd'/>">添加用戶</a>|

                        <a href="/HelloStruts2_CRUD_001/crud1/userToUpdate.action?user.userId=<s:property value='userId' />">修改</a>|

                        <a href="javascript:if(confirm('確認刪除嗎?'))window.location.href='/HelloStruts2_CRUD_001/crud1/userDelete.action?user.userId=<s:property value='userId' />'">刪除</a>

                </td>

        </tr>        

</s:iterator>

</table>

<div align="center">

<!--

<a href="/HelloStruts2_CRUD_001/crud1/userToList.action">顯示全部用戶</a>

<a href="/HelloStruts2_CRUD_001/crud1/userToQuery.action">查詢用戶</a>

 -->

        <a href="<s:url action='userToList'/>">顯示全部用戶</a><br />

        <a href="<s:url action='userToQuery'/>">查詢用戶</a>

</div>

</body>

</html>

看到這可能有些頭昏眼花了,當然若是使用 ctrl+C ctrl+V 就不會有這樣的困擾了。

其實在這邊我們畫面跟功能決定後,應該要開始先設計整個 Action

我們可以將不同的Action 功能寫在不同的 Action 類別中,也可以透過指定Method的方式,將相關的功能寫在同一支 Action 類別中。

如下:

UserAction.java

package com.Action;

import java.util.List;

import com.CRUD.UserJDBCDao;

import com.Model.UserModel;

import com.Model.UserQueryModel;

import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport {

        private static final long serialVersionUID = -1651659160635719619L;

        private List<UserModel> list;

        private String[] sexs = new String[]{"男","女"};

        private UserModel user;

        private UserQueryModel uqm;

        /**

         * 主要顯示

         * @return

         * @throws Exception

         */

        public String toList() throws Exception {

                UserJDBCDao dao = new UserJDBCDao();

                list = dao.getAll();

                return "toList";

        }

        

        public String toAdd() throws Exception {

                return "toAdd";

        }

        

        public String add() throws Exception {

                UserJDBCDao dao = new UserJDBCDao();

                dao.create(user);

                return this.toList();

        }

        

        public String toUpdate() throws Exception{

                UserJDBCDao dao = new UserJDBCDao();

                user = dao.getSingle(user.getUserId());

                return "toUpdate";

        }

        

        public String update() throws Exception{

                UserJDBCDao dao = new UserJDBCDao();

                dao.update(user);

                return this.toList();

        }

        

        public String delete() throws Exception{

                UserJDBCDao dao = new UserJDBCDao();

                dao.delete(user.getUserId());

                return this.toList();

        }

        

        public String toQuery() throws Exception{

                return "toQuery";

        }

        

        public String query() throws Exception{

                UserJDBCDao dao = new UserJDBCDao();

                list = dao.getByCondition(uqm);

                return "toList";

        }

        public List<UserModel> getList() {

                return list;

        }

        public void setList(List<UserModel> list) {

                this.list = list;

        }

        

        public String[] getSexs() {

                return sexs;

        }

        

        public void setSexs(String[] sexs) {

                this.sexs = sexs;

        }

        public UserModel getUser() {

                return user;

        }

        public void setUser(UserModel user) {

                this.user = user;

        }

        public UserQueryModel getUqm() {

                return uqm;

        }

        public void setUqm(UserQueryModel uqm) {

                this.uqm = uqm;

        }

}

說明一下程式流程應該會讓想法更清楚一點,我們一開始要點擊按鈕,讓程式導到我們的的Action中 (/crud1/userToList),而這個 Action 我們當初想好就是要用來顯示資料的,所以我們建立一個 ActionSupport 類別,將所要導入的資料 UserModel 帶入,並把相關的資料都設定好 (如:<s:property value="userId"/>),但是這樣只有資料而已,我們還沒有與 Dao 做連結,並向 DB 取得目前存於資料庫中的資料,看一下 struts 中對應的 (/crud1/userToList) 資料,因為我們要將多個 功能 寫進同一個 Action 類別中,所以我們會採用指定 Method 方式,這邊設定我們我指定的 Method 是 toList(),故要在我們的 Action 類別中編寫一個 toList 的方法,而該方法就是藉由 Dao 來取得目前 DB 中所有的資料,並回傳一個 String,該 String 表示該 Action 要切換到哪一個結果,我們將其設定為 toList,也就是在 Struts.xml 的設定檔中,要有一個 <result name="toList">/list.jsp</result> 對應的結果。而這個 list.jsp 的頁面,就是我們設計好的 用來顯示資料的頁面,只是剛開始時,資料是空的,而目前我們藉由與 Dao 連線之後,將資料儲存起來了,再次進入這個畫面時,我們剛剛所設定的 <s:property value="userId"/> 就可以取得對應的資料,並將其顯示出來囉。

第一個功能出來之後,接下來就可以慢慢的將其他 CRUD 的相關功能加上,整個的流程都是相似的,只是要先想好,要顯示什麼樣的資料,而什麼樣的資料是必須要被產出的,畫面與畫面之間要如何做承接的動作。只要把握一個原則,若是跟筆者一樣新手上路,一定都是先求有,再求好!!!!!

以上,其他的部份就不多說了,只是單純的資料面的操作,若是對 Struts Tags 有疑問的,可以去 http://struts.apache.org/release/2.3.x/docs/using-struts-2-tags.html 官方網頁去稍微複習一下,這整個範例並未將Struts 與其他後端的工具做結合,如 Mybatis / Hibernate ,若有需要相關資料,可以求助一下 Google 大神哦。

後面會附上範例的程式碼,其他部份若有信心的也可以自由發揮哦,當然也可以充分利用 ctrl+C ctrl+V 先看看做出來的成果是如何,再來看程式了解吧

原文網址 http://kuoshenghsu.blogspot.tw/2014/08/struts2-crud.html

demo程式(右鍵另開視窗下載)