Thứ Hai, 21 tháng 7, 2014

Login Using JSF

Đầu tiên ta tạo một project và chọn framework JavaServer Faces.
Sau đó tạo ra hai trang JSF là index.xhtml và home.xhtml. Tiếp tục ta viết vào trogn trang index.xhtml như dưới đây.


<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h:form>
            <h:inputText value="#{login.username}" required="" requiredMessage="Bạn phải nhập username"></h:inputText><br></br>
            <h:inputSecret value="#{login.password}" required="" requiredMessage="Bạn phải nhập password"></h:inputSecret><br></br>
            <h:commandButton action="#{login.checkLogin}" value="Login"/>
        </h:form>
    </h:body>
</html>

Tiếp đó để có thể kết nối vào cơ sở dữ liệu ta sẽ tạo một lớp DataAccess như dưới:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package luj.db;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Nguyen Minh An
 */
public class DataAccess {
    public static Connection getConnection() throws SQLException {
        String url = "jdbc:sqlserver://localhost:1433;databaseName=LOGIN_DEMO";
        String username = "LUCKY";
        String password = "123456";

        try {
            Connection conn = null;
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            conn = DriverManager.getConnection(url, username, password);
            return conn;
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
}

Tiếp theo ta tạo tiếp một lớp Java với tên là AccountManagement để xử lý nghiệp vụ như sau:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package luj.bussiness;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import luj.db.DataAccess;

/**
 *
 * @author Nguyen Minh An
 */
public class AccountManagement {

    public boolean checkLogin(String username, String password) {
        if ("".equals(username) || "".equals(password)) {
            return false;
        } else {
            try {
                Connection conn = DataAccess.getConnection();
                PreparedStatement ps = conn.prepareCall("SELECT * FROM ACCOUNT WHERE username like '" + username + "' and passwords like '" + password + "'");
                ResultSet res = ps.executeQuery();
                while (res.next()) {
                    return true;
                }
            } catch (SQLException ex) {
                Logger.getLogger(AccountManagement.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return false;
    }
}

Và cuối cùng ta tạo một lớp JSF Managed Bean với tên là Login như dưới đây:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package luj.task;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import luj.bussiness.AccountManagement;

/**
 *
 * @author Nguyen Minh An
 */
@ManagedBean
@RequestScoped
public class Login {
    private String username;
    private String password;
    
    public Login() {
    }
    
    public String checkLogin(){
        boolean res = new AccountManagement().checkLogin(username, password);
        if (res == true) {
            return "home?faces-redirect=true";
        }else{
            return "index?faces-redirect=true";
        }
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
    
    
    
}


Code dễ hiểu, dễ làm, nhanh, tuy nhiên độ trong suốt không cao.


Search Product By Name Using JSF

Đầu tiên ta sẽ tạo một project và sử dụng framework như dưới:


Đầu tiên để truy xuất vào cơ sở dữ liệu ta cần import sqljdbc4.jar sau đó tạo một class DataAccess đặt trong package "spbn.db" như dưới:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package spbnj.connection;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Nguyen Minh An
 */
public class DataAccess {

    public static Connection getConnection() throws SQLException {
        String url = "jdbc:sqlserver://localhost:1433;databaseName=DEMO_JSF";
        String username = "LUCKY";
        String password = "123456";

        try {
            Connection conn = null;
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            conn = DriverManager.getConnection(url, username, password);
            return conn;
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }
}

Tiếp đó ta sẽ tạo một trang jsf (xhtml) với tên index.xhtml như dưới:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
    <h:head>
        <title>Facelet Title</title>
    </h:head>
    <h:body>
        <h:form>
            <h:inputText value="#{searchBean.keyword}"></h:inputText>
            <h:commandButton action="#{searchBean.searchByName}" value="Search"></h:commandButton>
            <ui:repeat value="#{searchBean.listproduct}" var="l">
                <h:outputLabel value="#{l.id}"></h:outputLabel>
                <h:outputLabel value="#{l.name}"></h:outputLabel>
                <h:outputLabel value="#{l.price}"></h:outputLabel>
            </ui:repeat>
        </h:form>

    </h:body>
</html>


Ta tạo một lớp Product với các thuộc tính và các phương thức get, set như dưới:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package spbnj.entity;

/**
 *
 * @author Nguyen Minh An
 */
public class Product {
    private int id;
    private String name;
    private String price;

    public Product(int id, String name, String price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }
    
    
}

Tiếp đó ta tạo một lớp ProductManagement và phương thức để làm việc search dữ liệu trong database:

package spbnj.bussiness;

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 java.util.logging.Level;
import java.util.logging.Logger;
import spbnj.connection.DataAccess;
import spbnj.entity.Product;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
/**
 *
 * @author Nguyen Minh An
 */
public class ProductManagement {

    public List<Product> listProduct;

    public List<Product> searchByName(String keyword) {
        try {
            listProduct = new ArrayList<>();
            Connection conn = DataAccess.getConnection();
            PreparedStatement ps = conn.prepareCall("SELECT * FROM PRODUCT WHERE name like '%" + keyword + "%'");
            ResultSet res = ps.executeQuery();
            while (res.next()) {                
                int id = res.getInt("id");
                String name = res.getString("name");
                String price = res.getString("price");
                Product p = new Product(id, name, price);
                listProduct.add(p);
            }
            return listProduct;
        } catch (SQLException ex) {
            Logger.getLogger(ProductManagement.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

}

Tiếp đó ta tạo một lớp ManagedJSF Bean với tên là SearchBean như bên dưới.

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package spbnj.searchbean;

import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import spbnj.bussiness.ProductManagement;
import spbnj.entity.Product;

/**
 *
 * @author Nguyen Minh An
 */
@ManagedBean
@RequestScoped
public class SearchBean {

    private List<Product> listproduct;
    private String keyword;

    public SearchBean() {

    }

    public void searchByName() {
        listproduct = new ProductManagement().searchByName(keyword);
    }

    public List<Product> getListproduct() {
        return listproduct;
    }

    public void setListproduct(List<Product> listproduct) {
        this.listproduct = listproduct;
    }

    public String getKeyword() {
        return keyword;
    }

    public void setKeyword(String keyword) {
        this.keyword = keyword;
    }

}

Các bạn có thể tải Source Code ở đây

Nhận xét:
Mô hình khá đơn giản, dễ học, dễ hiểu, các thẻ có tên dễ dùng (tên biểu thị việc làm ví dụ như secret là input dưới type là mật khẩu, hay repeat thì là foreach).



Thứ Bảy, 19 tháng 7, 2014

Làm shopping cart dùng Struts 2

Module 3.
Đầu tiên ta tạo một trang index.jsp với form cho phép nhận dữ liệu vào từ người dùng như dưới:
<%-- 
    Document   : Search
    Created on : Jul 19, 2014, 11:36:41 PM
    Author     : Nguyen Minh An
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <h2>Enter the key</h2>
        <div>
            <form action="search" method="get">
                <input type="text" name="keyword"/>
                <input type="submit" value="Search"/>
            </form>
        </div>
        
    </body>
</html>
Tiếp đó ta tạo một 3 trang nữa là. Recommended.jsp, SearchingResult.jsp và SearchingResult2.jsp như dưới.
                                                   Recommended.jsp
<%-- 
    Document   : Recomment
    Created on : Jul 19, 2014, 11:48:33 PM
    Author     : Nguyen Minh An
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <h2>Tìm kiếm nâng cao:</h2>
        <form action="searchdetail">
            Title: <input type="text" name="title"/><br>
            Author: <input type="text" name="author"/><br>
            Price: <input type="text" name="price"/><br>
            <input type="submit" value="Search"/>
        </form>
        <a href="back">Back</a>
    </body>
</html>
                                        
                                                 SearchingResult.jsp
<%-- 
    Document   : SearchResult
    Created on : Jul 19, 2014, 11:50:14 PM
    Author     : Nguyen Minh An
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Search - Result</title>
    </head>
    <body>

        <h2>Kết quả tìm thấy:</h2>
        <table border="1">
            <s:iterator value="list">
                <tr>
                    <td>Title: <s:property value="title"/></td>
                    <td>Author: <s:property value="author"/></td>
                    <td>Price: <s:property value="price"/></td>
                </tr>
            </s:iterator>
        </table>
        <a href="back">Back</a>
    </body>
</html>

 và SearchingResult2.jsp

<%-- 
    Document   : SearchResult2
    Created on : Jul 20, 2014, 1:02:34 AM
    Author     : Nguyen Minh An
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <h2>Kết quả tìm thấy:</h2>
        <table border="1">
            <s:iterator value="lists">
                <tr>
                    <td>Title: <s:property value="title"/></td>
                    <td>Author: <s:property value="author"/></td>
                    <td>Price: <s:property value="price"/></td>
                </tr>
            </s:iterator>
        </table>
        <a href="back">Back</a>
    </body>
</html>


Tiếp đó đến phần xử lý nghiệp vụ ta tạo ra một lớp java với tên BookManagement.java như dưới:


/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package obrc.bussiness;

import db.connection.DataAccess;
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 java.util.logging.Level;
import java.util.logging.Logger;
import obrc.entity.Book;

/**
 *
 * @author Nguyen Minh An
 */
public class BookManagement {

    public List<Book> searchByName(String name) {
        List<Book> list = new ArrayList<>();
        try {
            Connection conn = DataAccess.getConnection();
            PreparedStatement ps = conn.prepareCall("select * from BOOK WHERE title like %'" + name + "'%");
            ResultSet res = ps.executeQuery();
            while (res.next()) {                
                int id = res.getInt("id");
                String title = res.getString("title");
                String author = res.getString("author");
                String price = res.getString("price");
                Book b = new Book(id, title, author, price);
                list.add(b);
            }
        } catch (Exception ex) {
            Logger.getLogger(BookManagement.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;

    }


public ArrayList<Book> getBookByAdvanceSearch(String title, String author, String price) {
        try {
            ArrayList<Book> bl = new ArrayList<>();
            Connection conn = DataAccess.getConnection();
            PreparedStatement ps = conn.prepareCall("select * from Book where title like ? or author like ? or price like ?");
            ps.setString(1, "%" + title + "%");
            ps.setString(2, "%" + author + "%");
            ps.setString(3, "%" + price + "%");
            ResultSet rs = ps.executeQuery();
            while (rs.next()) {
                int id = rs.getInt("id");
                String titles = rs.getString("title");
                String authors = rs.getString("author");
                String prices = rs.getString("price");
                Book b = new Book(id, titles, authors, prices);
                bl.add(b);
            }
            return bl;
        } catch (SQLException ex) {
            Logger.getLogger(BookManagement.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;

    }


}

Cấu hình cho file Struts.xml:

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

<struts>
    <!-- Configuration for the default package. -->
    <package name="default" extends="struts-default">
        <action name="search" class="obrc.ui.SearchAction" method="execute">
            <result name="success">SearchResult.jsp</result>
            <result name="error">Recomment.jsp</result>
        </action>
        <action name="searchdetail" class="obrc.ui.AdvanceSearching" method="execute">
            <result name="success">SearchResult2.jsp</result>
            <result name="error">Recomment.jsp</result>
        </action>
        <action name="back" class="obrc.ui.Back">
            <result name="success">Search.jsp</result>
        </action>
    </package>
</struts>

Tạo đối tượng Book.

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package obrc.entity;

/**
 *
 * @author Nguyen Minh An
 */
public class Book {
    
    private int id;
    private String title;
    private String author;
    private String price;

    public Book(int id, String title, String author, String price) {
        this.id = id;
        this.title = title;
        this.author = author;
        this.price = price;
    }

    public Book(int aInt, String string, String string0) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }
    
    
    
}

Tạo tiếp Action cho việc search.

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package obrc.ui;

import com.opensymphony.xwork2.ActionSupport;
import java.util.ArrayList;
import java.util.List;
import obrc.bussiness.BookManagement;
import obrc.entity.Book;

/**
 *
 * @author Nguyen Minh An
 */
public class SearchAction extends ActionSupport {

    private String keyword;
    private List<Book> list;

    public SearchAction() {
    }

    public String execute() throws Exception {
        if (!"".equals(keyword)) {
            list = new BookManagement().searchByName(keyword);
            if (list.size() > 0) {
                list = new BookManagement().searchByName(keyword);
                return SUCCESS;
            } else {
                return ERROR;
            }
        }
        return ERROR;
    }

    public String getKeyword() {
        return keyword;
    }

    public void setKeyword(String keyword) {
        this.keyword = keyword;
    }

    public List<Book> getList() {
        return list;
    }

    public void setList(List<Book> list) {
        this.list = list;
    }

}

Tiếp theo là tạo Action cho Advance Search.

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package obrc.ui;

import com.opensymphony.xwork2.ActionSupport;
import java.util.List;
import obrc.bussiness.BookManagement;
import obrc.entity.Book;

/**
 *
 * @author Nguyen Minh An
 */
public class AdvanceSearching extends ActionSupport {

    private String title;
    private String author;
    private String price;
    private List<Book> lists;

    public AdvanceSearching() {
    }

    public String execute() throws Exception {
        lists = new BookManagement().getBookByAdvanceSearch(title, author, price);
        if (lists.size() > 0) {
            return SUCCESS;
        }else{
            return ERROR;
        }
    }

    public List<Book> getLists() {
        return lists;
    }

    public void setLists(List<Book> lists) {
        this.lists = lists;
    }

    

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

}

Tiếp tới cái quan trọng nhất là tạo lớp kết nối xuống cơ sở dữ liệu.

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package db.connection;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.logging.Level;

import java.util.logging.Logger;

/**
 *
 * @author Nguyen Minh An
 */
public class DataAccess {

    public static Connection getConnection() throws SQLException {
        String url = "jdbc:sqlserver://localhost:1433;databaseName=READER_CLUB";
        String username = "LUCKY";
        String password = "123456";
        
        try {
            Connection conn = null;
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            conn = DriverManager.getConnection(url, username, password);
            return conn;
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(DataAccess.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;

    }
}
Các bạn có thể download Source Code ở đây.

Develop Authorization using interceptor in Struts2

Ta sẽ áp dụng interceptor để làm chức năng login cho assignment.
Việc đầu tiên ta cần làm là tạo một trang index.jsp với form đăng nhập như code phía dưới.

<a href="#" id="color_lg">Đăng nhập</a>
                                    <ul id="ul_login">
                                        <form action="login" method="post">
                                            <li><input class="required" type="text" name="username" maxlength="100" placeholder="Tên đăng nhập. . . . "/></li>
                                            <li><input class="required" type="password" name="password" maxlength="50" placeholder="Mật khẩu. . . ."/></li>
                                            <li id="li_Login"><input type="submit" value="Đăng nhập" id="btnLogin" /></li>
                                            <span></span>
                                            <label class="passerror"></label>
                                        </form>
                                    </ul>

Như ta nhìn thấy chữ login được bôi đậm trong thuộc tính action của form. Điều tiếp theo cần làm là ta sẽ tạo một lớp java và implements ActionSupport với tên là Login.java để xử lý request và kiểm tra username và password.


package ass.ui;

import ass.bussiness.AccountManagement;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

/**
 *
 * @author Nguyen Minh An
 */
public class Login extends ActionSupport {

    private String username;
    private String password;

    @Override
    public String execute() throws Exception {
        String session = ActionContext.getContext().getSession().toString();
        if ("".equals(session)) {
            int result = new AccountManagement().checkUserRole(session);
            if (result == 1) {
                return "GUIDE";
            }
            if (result == 2) {
                return "TRAVELLER";
            } else {
                return LOGIN;
            }
        }
        int res = new AccountManagement().checkLogin(username, password);
        if (res == 2) {
            ActionContext.getContext().getSession().put("username", username);
            return "GUIDE";
        }
        if (res == 3) {
            ActionContext.getContext().getSession().put("username", username);
            return "TRAVELLER";
        } else {
            return LOGIN;
        }
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}

Tiếp đó ta tạo một class java thường với tên AccountManagement để kiểm tra thông tin người dùng nhập vào có khớp với thông tin trong cơ sở dữ liệu hay không.

public int checkLogin(String username, String password) {
        boolean check = Validation.checkLoginValidation(username, password);
        if (check == false) {
            return 1;
        }
        if (check == false) {
            return 1;
        }
        if (check != false) {
        } else {
            return 1;
        }
        if (check == false) {
            return 1;
        }
        if (check == false) {
            return 1;
        } else {
            try {
                String password2 = Encrypt.Encode(password);
                Connection conn = DataAccess.getConnection();

                PreparedStatement ps = conn.prepareCall("SELECT * FROM ACCOUNT WHERE aUsername like '" + username + "' and aPassword like '" + password2 + "'");
                ResultSet res = ps.executeQuery();
                while (res.next()) {
                    conn.close();
                    Connection conn2 = DataAccess.getConnection();
                    PreparedStatement ps2 = conn2.prepareCall("SELECT * FROM ACCOUNT WHERE aUsername like '" + username + "' and aPassword like '" + password2 + "' and aRole=1");
                    ResultSet res2 = ps2.executeQuery();
                    if (res2.next()) {
                        return 2;
                    } else {
                        return 3;
                    }
                }
            } catch (Exception ex) {
                Logger.getLogger(AccountManagement.class.getName()).log(Level.SEVERE, null, ex);
            }
            return 1;
        }
    }


Tiếp đến ta sẽ khai báo trong file struts.xml cho action login ở trên.

<action name="login" class="ass.ui.Login" method="execute">
            <result name="TRAVELLER"  type="redirect">travellerhomepage</result>
            <result name="GUIDE"  type="redirect">guidehomepage</result>
        </action>

<action name="guidehomepage" class="ass.ui.GuideHomePage" method="execute">
            <result name="success">GuideHomePage.jsp</result>
        </action>
        
        <action name="travellerhomepage" class="ass.ui.TravellerHomePage" method="execute">
            <result name="success">TravellerHomePage.jsp</result>

        </action>

<interceptors>
            <interceptor name="authorization" class="ass.controller.Authorization" />
            <interceptor-stack name="myStack">
                <interceptor-ref name="servletConfig" />
                <interceptor-ref name="params" />
                <interceptor-ref name="authorization" />
                <interceptor-ref name="prepare" />
                <interceptor-ref name="modelDriven" />
                <interceptor-ref name="fileUpload" />
                <interceptor-ref name="staticParams" />
                <interceptor-ref name="conversionError" />
                <interceptor-ref name="validation" />
                <interceptor-ref name="workflow" />
            </interceptor-stack>
        </interceptors>
        
        <default-interceptor-ref name="myStack"/>
        
        <global-results>
            <result name="login">/</result>

        </global-results>

Cuối cùng ta tạo một lớp với tên Authorization.java để làm nhiệm vụ lọc request và đưa chúng đến nơi cần đến.

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ass.controller;

import ass.ui.Login;
import ass.ui.PlaceSearching;
import ass.ui.SearchResult;
import ass.ui.SearchingError;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.interceptor.Interceptor;


/**
 *
 * @author Nguyen Minh An
 */
public class Authorization implements Interceptor {

    @Override
    public void destroy() {

    }

    @Override
    public void init() {

    }

    @Override
    public String intercept(ActionInvocation ai) throws Exception {
        Object user = ActionContext.getContext().getSession().get("username");
        if (ai.getAction() instanceof Login || user != null) {
            return ai.invoke();
        }
        if (ai.getAction() instanceof PlaceSearching) {
            return ai.invoke();
        }
        if (ai.getAction() instanceof SearchResult) {
            return ai.invoke();
        }
        if (ai.getAction() instanceof SearchingError) {
            return ai.invoke();
        }
        return ActionSupport.LOGIN;
    }

}

Các bạn có thể tải source code ở đây 


Nhận xét: 

Ưu điểm.
- Intercepter đóng vai trò như filter trong javaservlet, thật vậy nó chính là một controller để nhằm lọc các request đến server và gửi request đến action để xử lý.
- Việc sử dụng interceptor khá tiết kiệm thời gian, và không cần viết nhiều code.

Nhược điểm
- Ban đầu khi mới tìm hiểu thì khó khăn trong việc hiểu và sử dụng, do code không trong suốt

Thứ Sáu, 18 tháng 7, 2014

Struts 2/ MVC Architecture, Advantage and Disadvantage

I. Mô hình hoạt động của Struts2 framework.


Đầu tiên khi có request từ phía client, request sẽ đi qua một controller, controller ở đây đầu tiên là một Dispatcher Filter và sau đó là một loạt các intercepter, tuỳ ở trong config (struts.xml) chúng ta config như thế nào với request đó thì nó sẽ được controller chuyển đến một action tương ứng và gọi ra phương thức execute để tiến hành xử lý. Sau khi xử lý xong thì sẽ trả về giá trị dưới dạng chuỗi String cho intercepter, lúc này sau khi đã có giá trị trả về thì controller sẽ xem xét nó thuộc về loại nào và tiến hành forward đến nơi mà request cần đến. Nó có thể là một action hay là một trang jsf, jsp....

Để hiểu rõ hơn ta quan sát ở dưới đây:

<form action="Searchword">
            Nhập tên sách: <input type="text" name="name">
            <input type="submit" value="search">
        </form>

ở trên là một form input cho phép nhận thông tin do người dùng nhập vào. Sau khi nhận được thông tin và người dùng gửi đi thì controller sẽ dựa vào action của form để xác định request trong file config. với form như trên ta sẽ có 1 action đã được viết sẵn trong struts.xml như dưới.

<action method="execute" class="Struts.SearchWord" name="Searchword">
            <result name="success">Result.jsp</result>
            <result name="error">Error.jsp</result>
        </action>

Sau khi đi qua bước này thì controller đã xác định được nơi nào để xử lý request và sẽ chuyển đến nơi đó. Trong trường hợp này là action Searchword như dưới đây

if ("".equals(name) || name.trim().isEmpty()) {
            return ERROR;
        } else {
            books = new BookBean().getBookByName(name);
            return SUCCESS;
        }

như ta thấy thì sau khi action xử lý xong sẽ trả về giá trị dưới dạng chuỗi. và sau đó các result được khai báo sẵn trong file struts.xml sẽ có nhiệm vụ xác định phải trả về cái gì. Trong trường hợp này khi trả về SUCCESS thì server sẽ chuyển hướng request đến trang Result.jsp và đến trang Error.jsp nếu như giá trị trả về là ERROR. Sau khi hoàn tất lớp View sẽ tiến hành kéo dữ liệu về và hiển thị cho người dùng.

II. Ưu điểm của Struts 2 framework.

- POJO forms and POJO actions : Struts2 đã làm đi với các hình thức hành động đó là một phần của khung Struts. Với Struts2, bạn có thể sử dụng bất kỳ POJO để nhận các hình thức đầu vào. Tương tự như vậy, bây giờ bạn có thể thấy bất kỳ POJO như một lớp học hành động. 

- Hỗ trợ thẻ :  Struts2 đã được cải thiện các thẻ hình thức và các thẻ mới cho phép các nhà phát triển viết mã ít hơn. 

- Hỗ trợ Ajax :  Struts 2 hỗ trợ việc dùng các thẻ Ajax giúp cho việc xử lý mạnh hơn rất nhiều và tuyệt vời khi Struts 2 hỗ trợ Web 2.0.

- Easy Integration : Struts 2 đã trở nên dễ dàng khi mà hỗ trợ tích hợp 
Tích hợp với các khuôn khổ khác như Spring, Tiles và SiteMesh giờ là dễ dàng hơn với nhiều tích hợp sẵn với Struts2. 

- Template Support :  Hỗ trợ để tạo ra quan điểm sử dụng các template

- Plugin Support : Các hành vi cốt lõi Struts2 có thể được tăng cường và bổ sung bằng việc sử dụng các plugin. Một số bổ sung có sẵn cho Struts2. 

- Profiling : Struts2 cung cấp hồ sơ hợp để gỡ lỗi và hồ sơ của ứng dụng. Thêm vào đó, Struts cũng cung cấp tích hợp gỡ lỗi với sự giúp đỡ của xây dựng trong công cụ gỡ lỗi. 

- Easy to modify tags : Tag đánh dấu trong Struts2 có thể được sửa đổi một cách dễ dàng bằng cách sử dụng các mẫu Freemarker. Điều này không cần yêu cầu bạn phải biết về JSP hoặc kiến thức java. HTML cơ bản, XML và kiến ​​thức CSS là đủ để sửa đổi các thẻ một cách nhanh chóng 

III. Nhược điểm.

- Mất nhiều thời gian để tìm hiểu về framework này vì nó khá khó dùng, khó nắm bắt. 

- Khó debug khi gặp lỗi.

- Tài liệu không nhiều.

Nhận xét.

- Code config của struts 2 ít hơn rất nhiều so với Struts 1

- Làm Tag dễ dàng

- Ta có thể đo thông tin của ứng dụng chạy như thế nào

- Tích hợp các công cụ để phát triển (Plugin..)

- Thứ hay nhất trong struts2 đó là do việc tách project ra thành các module riêng biệt nên rất dễ mở rộng, tái sử dụng (Struts 2 có tích hợp template và tích hợp một số thành phần khác).

- Hỗ trợ Ajax để làm web 2.0 rất hiệu quả và đẹp.

Cơ chế hoạt động của struts 2 tương tự như mô hình mvc của struts 1 nhưng điểm khác biệt đó là pull. dữ liệu được kéo từ model lên trực tiếp trên view chứ không phải theo kiểu push của MVC.