Tạo một ứng dụng Java Web đơn giản sử dụng Servlet, JSP và JDBC
Công ty Vĩnh Cửu tuyển dụng lập trình viên Java

1- Giới thiệu

Tài liệu được viết dựa trên:
  • Eclipse 4.5 MARS (ok for Eclipse 4.4 LUNA)

  • Tomcat 8.x

Document History:
  • 12-12-2014: JSP + Servlet + Filter + JSTL
  • 06-08-2015: JSP + Servlet + Filter + JSTL + JDBC
Trong tài liệu này tôi sẽ hướng dẫn từng bước cách tạo một ứng dụng web đơn giản kết hợp Servlet + JSP + Filter + JSP EL + JDBC. Hãy đảm bảo rằng bạn đã nắm vững Servlet, JSP FilterJDBC trước khi bắt đầu. Nếu không, bạn có thể tham khảo tại:

Servlet:

Filter:

JSP:

Thư viện thẻ chuẩn của JSP (JSTL)

JDBC

2- Các nguyên tắc kinh điển khi lập trình Servlet + JSP

Đây là các nguyên tắc mà bạn nên nhớ để có thể xây dựng một ứng dụng Web sử dụng Servlet + JSP thỏa mãn tiêu chí: code đơn giản dễ hiểu và dễ dàng bảo trì.
Các nguyên tắc:
  1. Đừng bao giờ cho phép người dùng truy cập trực tiếp vào trang JSP của bạn.
  2. Chỉ coi JSP là cái để hiển thị giao diện.
  3. Servlet đóng vai trò là người điều khiển luồng đi của ứng dụng và sử lý logic chương trình.
  4. Mở kết nối JDBC và quản lý giao dịch trong Filter (Không bắt buộc).
     

Theo nguyên tắc 1:

Không bao giờ cho phép người dùng truy cập trực tiếp vào trang JSP của bạn, điều đó có nghĩa là mọi request của người dùng thường là:
  • Một nguồn dữ liệu tĩnh (image, css, js,...)
  • Hoặc một servlet.
Như vậy bạn phải cất giấu các file JSP của bạn tại một nơi nào đó mà người dùng không thể truy cập vào. Chẳng hạn đặt trong thư mục WEB-INF hoặc thư mục con của nó. Trong ví dụ này tôi sẽ để các file jsp tại thư mục WEB-INF/views.
Khi request của người dùng tới một Servlet, nó sẽ sử lý yêu cầu của người dùng, chẳng hạn Insert, update và truy vấn dữ liệu, cuối cùng là forward tới trang JSP để hiển thị dữ liệu. Như vậy mỗi servlet có 0 hoặc nhiều trang JSP tương ứng (Thường chỉ cần 1).

Nguyên tắc 2:

Chỉ coi JSP là nơi hiển thị dữ liệu, điều đó có nghĩa là bạn không nên xử lý logic ứng dụng trên JSP, chẳng hạn như update, insert, delete,.., và không điều hướng trên trang JSP.

3- Demo ứng dụng web sẽ làm

Bạn có thể xem trước Demo ứng dụng Web sẽ làm:

4- Chuẩn bị database

Trong tài liệu này tôi hướng dẫn bạn làm việc với một trong 3 cơ sở dữ liệu Oracle, MySQL hoặc SQL Server. Bạn cần chạy các script để tạo một số bảng và dữ liệu cần thiết cho ví dụ này.

ORACLE:

-- Create table
create table USER_ACCOUNT
(
USER_NAME VARCHAR2(30) not null,
GENDER    VARCHAR2(1) not null,
PASSWORD  VARCHAR2(30) not null,
primary key (USER_NAME)
);

-- Create table
create table PRODUCT
(
CODE  VARCHAR2(20) not null,
NAME  VARCHAR2(128) not null,
PRICE FLOAT not null,
primary key (CODE)
) ;

-- Insert data: ---------------------------------------------------------------

insert into user_account (USER_NAME, GENDER, PASSWORD)
values ('tom', 'M', 'tom001');

insert into user_account (USER_NAME, GENDER, PASSWORD)
values ('jerry', 'M', 'jerry001');

insert into product (CODE, NAME, PRICE)
values ('P001', 'Java Core', 100);

insert into product (CODE, NAME, PRICE)
values ('P002', 'C# Core', 90);

-- Commit
Commit;

MYSQL:

-- Create table
create table USER_ACCOUNT
(
USER_NAME VARCHAR(30) not null,
GENDER    VARCHAR(1) not null,
PASSWORD  VARCHAR(30) not null,
primary key (USER_NAME)
);

-- Create table
create table PRODUCT
(
CODE  VARCHAR(20) not null,
NAME  VARCHAR(128) not null,
PRICE FLOAT not null,
primary key (CODE)
) ;

-- Insert data: ---------------------------------------------------------------

insert into user_account (USER_NAME, GENDER, PASSWORD)
values ('tom', 'M', 'tom001');

insert into user_account (USER_NAME, GENDER, PASSWORD)
values ('jerry', 'M', 'jerry001');

insert into product (CODE, NAME, PRICE)
values ('P001', 'Java Core', 100);

insert into product (CODE, NAME, PRICE)
values ('P002', 'C# Core', 90);

SQL SERVER:

-- Create table
create table USER_ACCOUNT
(
USER_NAME VARCHAR(30) not null,
GENDER    VARCHAR(1) not null,
PASSWORD  VARCHAR(30) not null,
primary key (USER_NAME)
);

-- Create table
create table PRODUCT
(
CODE  VARCHAR(20) not null,
NAME  VARCHAR(128) not null,
PRICE FLOAT not null,
primary key (CODE)
) ;

-- Insert data: ---------------------------------------------------------------

insert into user_account (USER_NAME, GENDER, PASSWORD)
values ('tom', 'M', 'tom001');

insert into user_account (USER_NAME, GENDER, PASSWORD)
values ('jerry', 'M', 'jerry001');

insert into product (CODE, NAME, PRICE)
values ('P001', 'Java Core', 100);

insert into product (CODE, NAME, PRICE)
values ('P002', 'C# Core', 90);

5- Tạo WebApp Project

Trên Eclipse chọn:
  • File/New/Other...
Project đã được tạo ra.
Thêm file index.html
index.html
<!DOCTYPE html>
<html>
  <head>
     <meta charset="UTF-8">
     <title>Simple Web Application</title>
  </head>
 
  <body>
 
     <h2>Simple Login Web Application using JSP/Servlet</h2>
     
     <ul>
        <li><a href="home">Home</a></li>
        <li><a href="login">Login</a></li>
        <li><a href="productList">Product  List</a>
     </ul>
     
  </body>
</html>

6- Cấu hình môi trường chạy (Runtime Environment)

Ứng dụng cần chạy trên một WebServer, chẳng hạn Tomcat Server, bạn có thể tham khảo tài liệu hướng dẫn download và khai báo Server Tomcat vào Eclipse tại:
Nhấn phải chuột vào project SimpleWebApp chọn Properties.

7- Chạy ứng dụng lần đầu tiên

Nhấn phải chuột vào Project SimpleWebApp, chọn:
  • Run As/Run on Server
Ứng dụng đã được chạy:
OK, tới đây mọi thứ đều tốt đẹp. Chúng ta sẽ bắt đầu lập trình một ứng dụng Web thực sự.

8- Download và khai báo thư viện JDBC

Bạn cần download thư viện JDBC điều khiển việc kết nối với Database. Trong tài liệu này tôi download cả 3 thư viện JDBC cho cả Oracle, MySQL, SQL Server, trong thực hành bạn chỉ cần thư viện JDBC ứng với loại Database bạn đang sử dụng.
Bạn có thể xem hướng dẫn download JDBC driver tại:
Hoặc download các thư viện JDBC cho MySQL, Sql Server, Oracle tại đây:
Kết quả download được:
Copy các thư viện này vào WEB-INF/lib:

9- Download và khai báo thư viện JSTL

Bạn cần download 2 thư viện JSTL để có thể sử dụng chúng trong JSP:
  • javax.servlet.jsp.jstl-*.jar
  • javax.servlet.jsp.jslt-api-*.jar
Copy 2 file jar bạn vừa download được vào thư mục /WEB-INF/lib:

10- Các class javabeans mô phỏng bảng trong DB

Tạo một số class Javabean, mỗi class mô phỏng một bảng trong database:
UserAccount.java
package org.o7planning.simplewebapp.beans;

public class UserAccount {

   public static final String GENDER_MALE ="M";
   public static final String GENDER_FEMALE = "F";
   
   private String userName;
   private String gender;
   private String password;
   

   public UserAccount() {
       
   }
   
   public String getUserName() {
       return userName;
   }

   public void setUserName(String userName) {
       this.userName = userName;
   }

   public String getGender() {
       return gender;
   }

   public void setGender(String gender) {
       this.gender = gender;
   }

   public String getPassword() {
       return password;
   }

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

}
Product.java
package org.o7planning.simplewebapp.beans;

public class Product {

   private String code;
   private String name;
   private float price;

   public Product() {

   }

   public Product(String code, String name, float price) {
       this.code = code;
       this.name = name;
       this.price = price;
   }

   public String getCode() {
       return code;
   }

   public void setCode(String code) {
       this.code = code;
   }

   public String getName() {
       return name;
   }

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

   public float getPrice() {
       return price;
   }

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

}

11- Các class tiện ích kết nối Database

MySQLConnUtils.java
package org.o7planning.simplewebapp.conn;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class MySQLConnUtils {

public static Connection getMySQLConnection()
        throws ClassNotFoundException, SQLException {
   
    // Chú ý: Thay đổi các thông số kết nối cho phù hợp.
    String hostName = "localhost";
    String dbName = "mytest";
    String userName = "root";
    String password = "12345";
    return getMySQLConnection(hostName, dbName, userName, password);
}

public static Connection getMySQLConnection(String hostName, String dbName,
        String userName, String password) throws SQLException,
        ClassNotFoundException {
    // Khai báo class Driver cho DB MySQL
    // Việc này cần thiết với Java 5
    // Java6 trở lên tự động tìm kiếm Driver thích hợp.
    // Nếu bạn dùng Java > 5, thì ko cần dòng này cũng được.
    Class.forName("com.mysql.jdbc.Driver");

    // Cấu trúc URL Connection dành cho MySQL
    // Ví dụ: jdbc:mysql://localhost:3306/simplehr
    String connectionURL = "jdbc:mysql://" + hostName + ":3306/" + dbName;

    Connection conn = DriverManager.getConnection(connectionURL, userName,
            password);
    return conn;
}
}
OracleConnUtils.java
package org.o7planning.simplewebapp.conn;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class OracleConnUtils {

  public static Connection getOracleConnection()
          throws ClassNotFoundException, SQLException {
     
      // Chú ý: Thay đổi các thông số kết nối cho phù hợp.
      String hostName = "localhost";
      String sid = "db11g";
      String userName = "mytest";
      String password = "12345";

      return getOracleConnection(hostName, sid, userName, password);
  }

  public static Connection getOracleConnection(String hostName, String sid,
          String userName, String password) throws ClassNotFoundException,
          SQLException {

      // Khai báo class Driver cho DB Oracle
      // Việc này cần thiết với Java 5
      // Java6 trở lên tự động tìm kiếm Driver thích hợp.
      // Nếu bạn dùng Java > 6, thì ko cần dòng này cũng được.
      Class.forName("oracle.jdbc.driver.OracleDriver");

      // Cấu trúc URL Connection dành cho Oracle
      // Ví dụ: jdbc:oracle:thin:@localhost:1521:db11g
      String connectionURL = "jdbc:oracle:thin:@" + hostName + ":1521:" + sid;

      Connection conn = DriverManager.getConnection(connectionURL, userName,
              password);
      return conn;
  }
}
SQLServerConnUtils_JTDS.java
package org.o7planning.simplewebapp.conn;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class SQLServerConnUtils_JTDS {

 // Kết nối vào SQLServer.
 // (Sử dụng thư viện điều khiển JTDS)
 public static Connection getSQLServerConnection_JTDS() throws SQLException,
         ClassNotFoundException {
     
     // Chú ý: Thay đổi các thông số kết nối cho phù hợp.
     String hostName = "localhost";
     String sqlInstanceName = "SQLEXPRESS";
     String database = "mytest";
     String userName = "sa";
     String password = "12345";

     return getSQLServerConnection_JTDS(hostName, sqlInstanceName, database,
             userName, password);
 }


 // Trường hợp sử dụng SQLServer.
 // Và thư viện JTDS.
 private static Connection getSQLServerConnection_JTDS(String hostName,
         String sqlInstanceName, String database, String userName,
         String password) throws ClassNotFoundException, SQLException {
     // Khai báo class Driver cho DB SQLServer
     // Việc này cần thiết với Java 5
     // Java6 tự động tìm kiếm Driver thích hợp.
     // Nếu bạn dùng Java > 5, thì ko cần dòng này cũng được.
     Class.forName("net.sourceforge.jtds.jdbc.Driver");

     // Cấu trúc URL Connection dành cho SQLServer
     // Ví dụ:
     // jdbc:jtds:sqlserver://localhost:1433/simplehr;instance=SQLEXPRESS
     String connectionURL = "jdbc:jtds:sqlserver://" + hostName + ":1433/"
             + database + ";instance=" + sqlInstanceName;

     Connection conn = DriverManager.getConnection(connectionURL, userName,
             password);
     return conn;
 }

}
SQLServerConnUtils_SQLJDBC.java
package org.o7planning.simplewebapp.conn;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class SQLServerConnUtils_SQLJDBC {

 // Kết nối vào SQLServer.
 // (Sử dụng thư viện điều khiển SQLJDBC)
 public static Connection getSQLServerConnection_SQLJDBC()
         throws ClassNotFoundException, SQLException {
     
       // Chú ý: Thay đổi các thông số kết nối cho phù hợp.
     String hostName = "localhost";
     String sqlInstanceName = "SQLEXPRESS";
     String database = "mytest";
     String userName = "sa";
     String password = "12345";

     return getSQLServerConnection_SQLJDBC(hostName, sqlInstanceName,
             database, userName, password);
 }



 // Trường hợp sử dụng SQLServer.
 // Và thư viện SQLJDBC.
 private static Connection getSQLServerConnection_SQLJDBC(String hostName,
         String sqlInstanceName, String database, String userName,
         String password) throws ClassNotFoundException, SQLException {
     // Khai báo class Driver cho DB SQLServer
     // Việc này cần thiết với Java 5
     // Java6 tự động tìm kiếm Driver thích hợp.
     // Nếu bạn dùng Java > 5, thì ko cần dòng này cũng được.
     Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");

     // Cấu trúc URL Connection dành cho SQLServer
     // Ví dụ:
     // jdbc:sqlserver://ServerIp:1433/SQLEXPRESS;databaseName=simplehr
     String connectionURL = "jdbc:sqlserver://" + hostName + ":1433"
             + ";instance=" + sqlInstanceName + ";databaseName=" + database;

     Connection conn = DriverManager.getConnection(connectionURL, userName,
             password);
     return conn;
 }

}
ConnectionUtils.java
package org.o7planning.simplewebapp.conn;

import java.sql.Connection;
import java.sql.SQLException;

public class ConnectionUtils {

   public static Connection getConnection()
             throws ClassNotFoundException, SQLException {

       // Ở đây tôi kết nối tới Oracle Database.
       // (Bạn có thể thay đổi sử dụng database khác).
       return OracleConnUtils.getOracleConnection();
       
       // return MySQLConnUtils.getMySQLConnection();
       // return SQLServerConnUtils_JTDS.getSQLServerConnection_JTDS();
       // return SQLServerConnUtils_SQLJDBC.getSQLServerConnection_SQLJDBC();
   }
   
   public static void closeQuietly(Connection conn) {
       try {
           conn.close();
       } catch (Exception e) {
       }
   }

   public static void rollbackQuietly(Connection conn) {
       try {
           conn.rollback();
       } catch (Exception e) {
       }
   }
}

12- Các class tiện ích & thao tác dữ liệu

MyUtils.java
package org.o7planning.simplewebapp.utils;

import java.sql.Connection;

import javax.servlet.ServletRequest;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.o7planning.simplewebapp.beans.UserAccount;

public class MyUtils {

   public static final String ATT_NAME_CONNECTION = "ATTRIBUTE_FOR_CONNECTION";

   private static final String ATT_NAME_USER_NAME = "ATTRIBUTE_FOR_STORE_USER_NAME_IN_COOKIE";

   // Lưu trữ Connection vào một thuộc tính của request.
   // Thông tin lưu trữ chỉ tồn tại trong thời gian yêu cầu (request)
   // cho tới khi dữ liệu được trả về trình duyệt người dùng.
   public static void storeConnection(ServletRequest request, Connection conn) {
       request.setAttribute(ATT_NAME_CONNECTION, conn);
   }

   // Lấy đối tượng Connection đã được lưu trữ trong 1 thuộc tính của request.
   public static Connection getStoredConnection(ServletRequest request) {
       Connection conn = (Connection) request.getAttribute(ATT_NAME_CONNECTION);
       return conn;
   }

   // Lưu trữ thông tin người dùng đã login vào Session
   public static void storeLoginedUser(HttpSession session, UserAccount loginedUser) {
       // Trên JSP có thể truy cập ${loginedUser}
       session.setAttribute("loginedUser", loginedUser);
   }

   // Lấy thông tin người dùng đã login trong session.
   public static UserAccount getLoginedUser(HttpSession session) {
       UserAccount loginedUser = (UserAccount) session.getAttribute("loginedUser");
       return loginedUser;
   }

   // Lưu thông tin người dùng vào Cookie.
   public static void storeUserCookie(HttpServletResponse response, UserAccount user) {
       System.out.println("Store user cookie");
       Cookie cookieUserName = new Cookie(ATT_NAME_USER_NAME, user.getUserName());
       // 1 ngày (Đã đổi ra giây)
       cookieUserName.setMaxAge(24 * 60 * 60);
       response.addCookie(cookieUserName);
   }

   public static String getUserNameInCookie(HttpServletRequest request) {
       Cookie[] cookies = request.getCookies();
       if (cookies != null) {
           for (Cookie cookie : cookies) {
               if (ATT_NAME_USER_NAME.equals(cookie.getName())) {
                   return cookie.getValue();
               }
           }
       }
       return null;
   }

   // Xóa Cookie của người dùng
   public static void deleteUserCookie(HttpServletResponse response) {
       Cookie cookieUserName = new Cookie(ATT_NAME_USER_NAME, null);
       // 0 giây. (Hết hạn ngay lập tức)
       cookieUserName.setMaxAge(0);
       response.addCookie(cookieUserName);
   }

}
DBUtils.java
package org.o7planning.simplewebapp.utils;

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 org.o7planning.simplewebapp.beans.Product;
import org.o7planning.simplewebapp.beans.UserAccount;

public class DBUtils {

  public static UserAccount findUser(Connection conn, String userName, String password) throws SQLException {

      String sql = "Select a.User_Name, a.Password, a.Gender from User_Account a "
              + " where a.User_Name = ? and a.password= ?";

      PreparedStatement pstm = conn.prepareStatement(sql);
      pstm.setString(1, userName);
      pstm.setString(2, password);
      ResultSet rs = pstm.executeQuery();

      if (rs.next()) {
          String gender = rs.getString("Gender");
          UserAccount user = new UserAccount();
          user.setUserName(userName);
          user.setPassword(password);
          user.setGender(gender);
          return user;
      }
      return null;
  }

  public static UserAccount findUser(Connection conn, String userName) throws SQLException {

      String sql = "Select a.User_Name, a.Password, a.Gender from User_Account a " + " where a.User_Name = ? ";

      PreparedStatement pstm = conn.prepareStatement(sql);
      pstm.setString(1, userName);

      ResultSet rs = pstm.executeQuery();

      if (rs.next()) {
          String password = rs.getString("Password");
          String gender = rs.getString("Gender");
          UserAccount user = new UserAccount();
          user.setUserName(userName);
          user.setPassword(password);
          user.setGender(gender);
          return user;
      }
      return null;
  }

  public static List<Product> queryProduct(Connection conn) throws SQLException {
      String sql = "Select a.Code, a.Name, a.Price from Product a ";

      PreparedStatement pstm = conn.prepareStatement(sql);

      ResultSet rs = pstm.executeQuery();
      List<Product> list = new ArrayList<Product>();
      while (rs.next()) {
          String code = rs.getString("Code");
          String name = rs.getString("Name");
          float price = rs.getFloat("Price");
          Product product = new Product();
          product.setCode(code);
          product.setName(name);
          product.setPrice(price);
          list.add(product);
      }
      return list;
  }

  public static Product findProduct(Connection conn, String code) throws SQLException {
      String sql = "Select a.Code, a.Name, a.Price from Product a where a.Code=?";

      PreparedStatement pstm = conn.prepareStatement(sql);
      pstm.setString(1, code);

      ResultSet rs = pstm.executeQuery();

      while (rs.next()) {
          String name = rs.getString("Name");
          float price = rs.getFloat("Price");
          Product product = new Product(code, name, price);
          return product;
      }
      return null;
  }

  public static void updateProduct(Connection conn, Product product) throws SQLException {
      String sql = "Update Product set Name =?, Price=? where Code=? ";

      PreparedStatement pstm = conn.prepareStatement(sql);

      pstm.setString(1, product.getName());
      pstm.setFloat(2, product.getPrice());
      pstm.setString(3, product.getCode());
      pstm.executeUpdate();
  }

  public static void insertProduct(Connection conn, Product product) throws SQLException {
      String sql = "Insert into Product(Code, Name,Price) values (?,?,?)";

      PreparedStatement pstm = conn.prepareStatement(sql);

      pstm.setString(1, product.getCode());
      pstm.setString(2, product.getName());
      pstm.setFloat(3, product.getPrice());

      pstm.executeUpdate();
  }

  public static void deleteProduct(Connection conn, String code) throws SQLException {
      String sql = "Delete Product where Code= ?";

      PreparedStatement pstm = conn.prepareStatement(sql);

      pstm.setString(1, code);

      pstm.executeUpdate();
  }

}

13- Tạo Filter kết nối database

Trong JDBCFilter tôi có kiểm tra xem các request nào thực sự gọi tới một Servlet, để dễ hiểu bạn có thể xem hình dưới đây, nó mô tả quan hệ giữa các khái niệm của Servlet.
JDBCFilter với khai báo url-pattern = /*, điều đó có nghĩa là mọi request của người dùng đều phải đi qua filter này. JDBCFilter sẽ kiểm tra request để đảm bảo chỉ mở kết nối JDBC cho các request cần thiết, chẳng hạn cho Servlet, tránh mở kết nối JDBC đối với các request thông thường như image, css, js, html.
JDBCFilter.java
package org.o7planning.simplewebapp.filter;

import java.io.IOException;
import java.sql.Connection;
import java.util.Collection;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;

import org.o7planning.simplewebapp.conn.ConnectionUtils;
import org.o7planning.simplewebapp.utils.MyUtils;

@WebFilter(filterName="jdbcFilter", urlPatterns = { "/*" })
public class JDBCFilter implements Filter {

   public JDBCFilter() {
   }

   @Override
   public void init(FilterConfig fConfig) throws ServletException {

   }

   @Override
   public void destroy() {

   }

   // Kiểm tra xem request hiện tại là 1 Servlet?
   private boolean needJDBC(HttpServletRequest request) {  
       System.out.println("JDBC Filter");
       //
       // Servlet Url-pattern: /spath/*
       //
       // => /spath
       String servletPath = request.getServletPath();
       // => /abc/mnp
       String pathInfo = request.getPathInfo();

       String urlPattern = servletPath;

       if (pathInfo != null) {
           // => /spath/*
           urlPattern = servletPath + "/*";
       }
       
       // Key: servletName.
       // Value: ServletRegistration
       Map<String, ? extends ServletRegistration> servletRegistrations = request.getServletContext()
               .getServletRegistrations();  

       // Tập hợp tất cả các Servlet trong WebApp của bạn.
       Collection<? extends ServletRegistration> values = servletRegistrations.values();
       for (ServletRegistration sr : values) {
           Collection<String> mappings = sr.getMappings();
           if (mappings.contains(urlPattern)) {
               return true;
           }
       }
       return false;
   }

   @Override
   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
           throws IOException, ServletException {

       HttpServletRequest req = (HttpServletRequest) request;

       //
       // Chỉ mở kết nối đối với các request có đường dẫn đặc biệt cần
       // connection. (Chẳng hạn đường dẫn tới các servlet, jsp, ..)
       //
       // Tránh tình trạng mở connection với các yêu cầu thông thường
       // (chẳng hạn image, css, javascript,... )
       //
       if (this.needJDBC(req)) {
           
           System.out.println("Open Connection for: " + req.getServletPath());
           
           Connection conn = null;
           try {
               // Tạo đối tượng Connection kết nối database.
               conn = ConnectionUtils.getConnection();
               // Sét tự động commit false, để chủ động điều khiển.
               conn.setAutoCommit(false);

               // Lưu trữ vào attribute của request.
               MyUtils.storeConnection(request, conn);

               // Cho phép request đi tiếp.
               chain.doFilter(request, response);

               // Gọi commit() để commit giao dịch với DB.
               conn.commit();
           } catch (Exception e) {
               e.printStackTrace();
               ConnectionUtils.rollbackQuietly(conn);
               throw new ServletException();
           } finally {
               ConnectionUtils.closeQuietly(conn);
           }
       }
       // Với các request thông thường (image,css,html,..)
       // không cần mở connection, cho tiếp tục.
       else {
           // Cho phép request đi tiếp.
           chain.doFilter(request, response);
       }

   }

}

14- Filter đọc Cookie tự động login

Trong trường hợp người dùng đã login và nhớ thông tin trong lần truy cập trước đó (Chẳng hạn hôm trước). Và giờ người dùng quay trở lại, Filter này sẽ kiểm tra thông tin Cookie đã lưu bởi trình duyệt và tự động Login.
CookieFilter.java
package org.o7planning.simplewebapp.filter;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.o7planning.simplewebapp.beans.UserAccount;
import org.o7planning.simplewebapp.utils.DBUtils;
import org.o7planning.simplewebapp.utils.MyUtils;

@WebFilter(filterName = "cookieFilter", urlPatterns = { "/*" })
public class CookieFilter implements Filter {

   public CookieFilter() {
   }

   @Override
   public void init(FilterConfig fConfig) throws ServletException {

   }

   @Override
   public void destroy() {

   }

   @Override
   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
           throws IOException, ServletException {
       HttpServletRequest req = (HttpServletRequest) request;
       HttpSession session = req.getSession();

       UserAccount userInSession = MyUtils.getLoginedUser(session);
       // Đang login.
       if (userInSession != null) {
           session.setAttribute("COOKIE_CHECKED", "CHECKED");
           chain.doFilter(request, response);
           return;
       }

       // Đã được tạo trong JDBCFilter.
       Connection conn = MyUtils.getStoredConnection(request);

       // Có cần kiểm tra Cookie ko?
       String checked = (String) session.getAttribute("COOKIE_CHECKED");
       if (checked == null && conn != null) {
           String userName = MyUtils.getUserNameInCookie(req);
           try {
               UserAccount user = DBUtils.findUser(conn, userName);
               MyUtils.storeLoginedUser(session, user);
           } catch (SQLException e) {
               e.printStackTrace();
           }
           // Đã kiểm tra cookie
           session.setAttribute("COOKIE_CHECKED", "CHECKED");
       }

       chain.doFilter(request, response);
   }

}

CHÚ Ý:

JDBCFilter & CookieFilter có cùng url-pattern =/*, bạn cần phải cấu hình để đảm bảo rằng JDBCFilter được thực thi trước. Do đó cần phải khai báo thứ tự trong web.xml (Không có cách nào khai báo thứ tự bằng Annotation).
<filter-mapping>
    <filter-name>jdbcFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
    <filter-name>cookieFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
web.xml đầ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"
     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>SimpleWebApp</display-name>


   <filter-mapping>
       <filter-name>jdbcFilter</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>
   
   <filter-mapping>
       <filter-name>cookieFilter</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>

 <welcome-file-list>

   <welcome-file>home</welcome-file>
   
   <welcome-file>index.html</welcome-file>
   
 </welcome-file-list>


</web-app>

15- Filter mã hóa ký tự

EncodingFilter.java
package org.o7planning.simplewebapp.filter;

import java.io.IOException;
import java.sql.Connection;
import java.util.Collection;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;

import org.o7planning.simplewebapp.conn.ConnectionUtils;
import org.o7planning.simplewebapp.utils.MyUtils;

@WebFilter(filterName = "encodingFilter", urlPatterns = { "/*" })
public class EncodingFilter implements Filter {

  public EncodingFilter() {
  }

  @Override
  public void init(FilterConfig fConfig) throws ServletException {

  }

  @Override
  public void destroy() {

  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
          throws IOException, ServletException {
      request.setCharacterEncoding("UTF-8");

      chain.doFilter(request, response);
  }

}

16- Các trang tái sử dụng

Một số trang JSP sẽ được sử dụng để nhúng vào các trang khác tại thời điểm Runtime, thông qua việc sử dụng:
<jsp:include page="_header.jsp"></jsp:include>
<jsp:include page="_menu.jsp"></jsp:include>

<jsp:include page="_footer.jsp"></jsp:include>
/WEB-INF/views/_header.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<div style="background: #E0E0E0; height: 55px; padding: 5px;">
  <div style="float: left">
     <h1>My Site</h1>
  </div>

  <div style="float: right; padding: 10px; text-align: right;">

     <!-- User store in session with attribute: loginedUser -->
     Hello <b>${loginedUser.userName}</b>
   <br/>
     Search <input name="search">

  </div>

</div>
/WEB-INF/views/_menu.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>
   
<div style="padding: 5px;">

   <a href="${pageContext.request.contextPath}/">Home</a>
   |
   <a href="${pageContext.request.contextPath}/productList">Product List</a>
   |
   <a href="${pageContext.request.contextPath}/userInfo">My Account Info</a>
   |
   <a href="${pageContext.request.contextPath}/login">Login</a>
   
</div>  
/WEB-INF/views/_footer.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
 
<div
  style="background: #E0E0E0; text-align: center; padding: 5px; margin-top: 10px;">
 
  @Copyright o7planning.org
 
</div>

17- Chức năng trang chủ

Khi gõ đường dẫn mặc định, chẳng hạn gõ tên miền của trang web nó sẽ hiển thị ra trang chủ (Trường hợp contextPath = ""), bạn cần phải khai báo trang chủ trong <welcome-file-list> của web.xml
Đường dẫn dưới đây hiện tại đang hiển thị nội dung của trang index.html
Bạn cần thiết kế một trang chủ là một JSP để có được các thông tin động thay vì một trang html vốn chỉ chứa các thông tin tĩnh.
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"
     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>SimpleWebApp</display-name>


   <filter-mapping>
       <filter-name>jdbcFilter</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>
   
   <filter-mapping>
       <filter-name>cookieFilter</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>

 <welcome-file-list>

   <welcome-file>home</welcome-file>
   
   <welcome-file>index.html</welcome-file>
   
 </welcome-file-list>


</web-app>
Mô hình trang chủ:
HomeServlet.java
package org.o7planning.simplewebapp.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns = { "/home"})
public class HomeServlet extends HttpServlet {
   private static final long serialVersionUID = 1L;

   public HomeServlet() {
       super();
   }

   @Override
   protected void doGet(HttpServletRequest request, HttpServletResponse response)
           throws ServletException, IOException {

       // Forward toi trang /WEB-INF/views/homeView.jsp
       // (Người dùng không bao giờ truy cập trực tiếp được vào các trang JSP
       // đặt trong WEB-INF)
       RequestDispatcher dispatcher = this.getServletContext().getRequestDispatcher("/WEB-INF/views/homeView.jsp");
       
       dispatcher.forward(request, response);
       
   }

   @Override
   protected void doPost(HttpServletRequest request, HttpServletResponse response)
           throws ServletException, IOException {
       doGet(request, response);
   }

}
/WEB-INF/views/homeView.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
  <head>
     <meta charset="UTF-8">
     <title>Home Page</title>
  </head>
  <body>

     <jsp:include page="_header.jsp"></jsp:include>
     <jsp:include page="_menu.jsp"></jsp:include>
   
      <h3>Home Page</h3>
     
      This is demo Simple web application using jsp,servlet &amp; Jdbc. <br><br>
      <b>It includes the following functions:</b>
      <ul>
         <li>Login</li>
         <li>Storing user information in cookies</li>
         <li>Product List</li>
         <li>Create Product</li>
         <li>Edit Product</li>
         <li>Delete Product</li>
      </ul>

     <jsp:include page="_footer.jsp"></jsp:include>

  </body>
</html>
Chạy lại ứng dụng của bạn, và thử 2 đường dẫn:

Chú ý: Nếu vì một lý do gì đó, đường dẫn http://localhost:8080/SimpleWebApp/ vẫn chuyển tới index.html, bạn có thể xóa hoặc đổi tên file index.html, chẳng hạn đổi sang _index.html

18- Chức năng login - LoginServlet

Đây là mô hình chức năng Login:
LoginServlet.java
package org.o7planning.simplewebapp.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns = { "/login"})
public class LoginServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  public LoginServlet() {
      super();
  }

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {

      // Forward toi trang /WEB-INF/views/loginView.jsp
      // (Người dùng không bao giờ truy cập trực tiếp được vào các trang JSP
      // đặt trong WEB-INF)
      RequestDispatcher dispatcher = this.getServletContext().getRequestDispatcher("/WEB-INF/views/loginView.jsp");
     
      dispatcher.forward(request, response);
     
  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      doGet(request, response);
  }

}
DoLoginServlet.java
package org.o7planning.simplewebapp.servlet;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.o7planning.simplewebapp.beans.UserAccount;
import org.o7planning.simplewebapp.utils.DBUtils;
import org.o7planning.simplewebapp.utils.MyUtils;

@WebServlet(urlPatterns = { "/doLogin" })
public class DoLoginServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  public DoLoginServlet() {
      super();
  }

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {

      String userName = request.getParameter("userName");
      String password = request.getParameter("password");
      String rememberMeStr = request.getParameter("rememberMe");
      boolean remember= "Y".equals(rememberMeStr);

     
      UserAccount user = null;
      boolean hasError = false;
      String errorString = null;

      if (userName == null || password == null
               || userName.length() == 0 || password.length() == 0) {
          hasError = true;
          errorString = "Required username and password!";
      } else {
          Connection conn = MyUtils.getStoredConnection(request);
          try {
              // Tìm user trong DB.
              user = DBUtils.findUser(conn, userName, password);
             
              if (user == null) {
                  hasError = true;
                  errorString = "User Name or password invalid";
              }
          } catch (SQLException e) {
              e.printStackTrace();
              hasError = true;
              errorString = e.getMessage();
          }
      }
      // Trong trường hợp có lỗi, forward về trang /WEB-INF/views/login.jsp
      if (hasError) {
          user = new UserAccount();
          user.setUserName(userName);
          user.setPassword(password);
         
          // Ghi các thông tin vào request trước khi forward.
          request.setAttribute("errorString", errorString);
          request.setAttribute("user", user);

          // Chuyển tiếp tới trang /WEB-INF/views/login.jsp
          RequestDispatcher dispatcher //
          = this.getServletContext().getRequestDispatcher("/WEB-INF/views/loginView.jsp");

          dispatcher.forward(request, response);
      }
      // Trường hợp không có lỗi.
      // Lưu thông tin người dùng vào Session.
      // Và chuyển hướng sang trang userInfo.
      else {
          HttpSession session = request.getSession();
          MyUtils.storeLoginedUser(session, user);
         
          // Nếu người dùng chọn lưu thông tin đăng nhập vào Cookie
          if(remember)  {
              MyUtils.storeUserCookie(response,user);
          }
          // Ngược lại xóa Cookie
          else  {
              MyUtils.deleteUserCookie(response);
          }            
         
          // Rồi chuyển hướng sang trang /userInfo.
          response.sendRedirect(request.getContextPath() + "/userInfo");
      }
  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      doGet(request, response);
  }

}
UserInfoServlet.java
package org.o7planning.simplewebapp.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.o7planning.simplewebapp.beans.UserAccount;
import org.o7planning.simplewebapp.utils.MyUtils;

@WebServlet(urlPatterns = { "/userInfo" })
public class UserInfoServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  public UserInfoServlet() {
      super();
  }

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      HttpSession session = request.getSession();

      // Kiểm tra người dùng login chưa
      UserAccount loginedUser = MyUtils.getLoginedUser(session);

      // Chưa login.
      if (loginedUser == null) {
          // Chuyển hướng về trang login.
          response.sendRedirect(request.getContextPath() + "/login");
          return;
      }
      // Ghi thông tin vào request trước khi forward.
      request.setAttribute("user", loginedUser);

      // Đã login rồi thì chuyển tiếp sang /WEB-INF/views/userInfoView.jsp
      RequestDispatcher dispatcher = this.getServletContext().getRequestDispatcher("/WEB-INF/views/userInfoView.jsp");
      dispatcher.forward(request, response);

  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      doGet(request, response);
  }

}
/WEB-INF/views/loginView.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
 <head>
    <meta charset="UTF-8">
    <title>Login</title>
 </head>
 <body>

    <jsp:include page="_header.jsp"></jsp:include>
    <jsp:include page="_menu.jsp"></jsp:include>

    <h3>Login Page</h3>

    <p style="color: red;">${errorString}</p>

    <form method="POST" action="doLogin">
       <table border="0">
          <tr>
             <td>User Name</td>
             <td><input type="text" name="userName" value= "${user.userName}" /> </td>
          </tr>
          <tr>
             <td>Password</td>
             <td><input type="text" name="password" value= "${user.password}" /> </td>
          </tr>
          <tr>
             <td>Remember me</td>
             <td><input type="checkbox" name="rememberMe" value= "Y" /> </td>
          </tr>
          <tr>
             <td colspan ="2">
                <input type="submit" value= "Submit" />
                <a href="${pageContext.request.contextPath}/">Cancel</a>
             </td>
          </tr>
       </table>
    </form>

    <p style="color:blue;">User Name: tom, password: tom001 or jerry/jerry001</p>

    <jsp:include page="_footer.jsp"></jsp:include>

 </body>
</html>
/WEB-INF/views/userInfoView.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
 <head>
    <meta charset="UTF-8">
    <title>User Info</title>
 </head>
 <body>

    <jsp:include page="_header.jsp"></jsp:include>
    <jsp:include page="_menu.jsp"></jsp:include>

    <h3>Hello: ${user.userName}</h3>

    User Name: <b>${user.userName}</b>
    <br />
    Gender: ${user.gender } <br />

    <jsp:include page="_footer.jsp"></jsp:include>

 </body>
</html>
Chạy ứng dụng của bạn:

19- Trang danh sách sản phẩm

Mô hình:
ProductListServlet.java
package org.o7planning.simplewebapp.servlet;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.o7planning.simplewebapp.beans.Product;
import org.o7planning.simplewebapp.utils.DBUtils;
import org.o7planning.simplewebapp.utils.MyUtils;

@WebServlet(urlPatterns = { "/productList" })
public class ProductListServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  public ProductListServlet() {
      super();
  }

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      Connection conn = MyUtils.getStoredConnection(request);

      String errorString = null;
      List<Product> list = null;
      try {
          list = DBUtils.queryProduct(conn);
      } catch (SQLException e) {
          e.printStackTrace();
          errorString = e.getMessage();
      }
      // Lưu thông tin vào request attribute trước khi forward sang views.
      request.setAttribute("errorString", errorString);
      request.setAttribute("productList", list);
     
      // Forward sang /WEB-INF/views/productListView.jsp
      RequestDispatcher dispatcher = request.getServletContext()
              .getRequestDispatcher("/WEB-INF/views/productListView.jsp");
      dispatcher.forward(request, response);
  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      doGet(request, response);
  }

}
/WEB-INF/views/productListView.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>  
<!DOCTYPE html>
<html>
 <head>
    <meta charset="UTF-8">
    <title>Product List</title>
 </head>
 <body>

    <jsp:include page="_header.jsp"></jsp:include>
    <jsp:include page="_menu.jsp"></jsp:include>

    <h3>Product List</h3>

    <p style="color: red;">${errorString}</p>

    <table border="1" cellpadding="5" cellspacing="1" >
       <tr>
          <th>Code</th>
          <th>Name</th>
          <th>Price</th>
          <th>Edit</th>
          <th>Delete</th>
       </tr>
       <c:forEach items="${productList}" var="product" >
          <tr>
             <td>${product.code}</td>
             <td>${product.name}</td>
             <td>${product.price}</td>
             <td>
                <a href="editProduct?code=${product.code}">Edit</a>
             </td>
             <td>
                <a href="deleteProduct?code=${product.code}">Delete</a>
             </td>
          </tr>
       </c:forEach>
    </table>

    <a href="createProduct" >Create Product</a>

    <jsp:include page="_footer.jsp"></jsp:include>

 </body>
</html>
Chạy lại ứng dụng:

20- Chức năng thêm sản phẩm

Mô hình chức năng thêm sản phẩm:
CreateProductServlet.java
package org.o7planning.simplewebapp.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(urlPatterns = { "/createProduct" })
public class CreateProductServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  public CreateProductServlet() {
      super();
  }

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {

      RequestDispatcher dispatcher = request.getServletContext()
              .getRequestDispatcher("/WEB-INF/views/createProductView.jsp");
      dispatcher.forward(request, response);

  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      doGet(request, response);
  }

}
DoCreateProductServlet.java
package org.o7planning.simplewebapp.servlet;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.o7planning.simplewebapp.beans.Product;
import org.o7planning.simplewebapp.utils.DBUtils;
import org.o7planning.simplewebapp.utils.MyUtils;

@WebServlet(urlPatterns = { "/doCreateProduct" })
public class DoCreateProductServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  public DoCreateProductServlet() {
      super();
  }

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      Connection conn = MyUtils.getStoredConnection(request);

      String code = (String) request.getParameter("code");
      String name = (String) request.getParameter("name");
      String priceStr = (String) request.getParameter("price");
      float price = 0;
      try {
          price = Float.parseFloat(priceStr);
      } catch (Exception e) {
      }
      Product product = new Product(code, name, price);

      String errorString = null;

      // Mã sản phẩm phải là chuỗi chữ [a-zA-Z_0-9]
      // Có ít nhất một ký tự.
      String regex = "\\w+";

      if (code == null || !code.matches(regex)) {
          errorString = "Product Code invalid!";
      }

      if (errorString == null) {
          try {
              DBUtils.insertProduct(conn, product);
          } catch (SQLException e) {
              e.printStackTrace();
              errorString = e.getMessage();
          }
      }
     
      // Lưu thông tin vào request attribute trước khi forward sang views.
      request.setAttribute("errorString", errorString);
      request.setAttribute("product", product);

      // Nếu có lỗi forward sang trang edit
      if (errorString != null) {
          RequestDispatcher dispatcher = request.getServletContext()
                  .getRequestDispatcher("/WEB-INF/views/createProductView.jsp");
          dispatcher.forward(request, response);
      }
      // Nếu mọi thứ tốt đẹp.
      // Redirect sang trang danh sách sản phẩm.
      else {
          response.sendRedirect(request.getContextPath() + "/productList");
      }

  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      doGet(request, response);
  }

}
/WEB-INF/views/createProductView.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE html>
<html>
 <head>
    <meta charset="UTF-8">
    <title>Create Product</title>
 </head>
 <body>

    <jsp:include page="_header.jsp"></jsp:include>
    <jsp:include page="_menu.jsp"></jsp:include>
   
    <h3>Create Product</h3>
   
    <p style="color: red;">${errorString}</p>
   
    <form method="POST" action="doCreateProduct">
       <table border="0">
          <tr>
             <td>Code</td>
             <td><input type="text" name="code" value="${product.code}" /></td>
          </tr>
          <tr>
             <td>Name</td>
             <td><input type="text" name="name" value="${product.name}" /></td>
          </tr>
          <tr>
             <td>Price</td>
             <td><input type="text" name="price" value="${product.price}" /></td>
          </tr>
          <tr>
             <td colspan="2">                  
                 <input type="submit" value="Submit" />
                 <a href="productList">Cancel</a>
             </td>
          </tr>
       </table>
    </form>
   
    <jsp:include page="_footer.jsp"></jsp:include>
   
 </body>
</html>

21- Chức năng sửa thông tin sản phẩm

Mô hình chức năng sửa thông tin sản phẩm:
EditProductServlet.java
package org.o7planning.simplewebapp.servlet;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.o7planning.simplewebapp.beans.Product;
import org.o7planning.simplewebapp.utils.DBUtils;
import org.o7planning.simplewebapp.utils.MyUtils;

@WebServlet(urlPatterns = { "/editProduct" })
public class EditProductServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  public EditProductServlet() {
      super();
  }

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      Connection conn = MyUtils.getStoredConnection(request);

      String code = (String) request.getParameter("code");

      Product product = null;

      String errorString = null;

      try {
          product = DBUtils.findProduct(conn, code);
      } catch (SQLException e) {
          e.printStackTrace();
          errorString = e.getMessage();
      }

      // Không có lỗi.
      // Sản phẩm không tồn tại để edit.
      // Redirect sang trang danh sách sản phẩm.
      if (errorString != null && product == null) {
          response.sendRedirect(request.getServletPath() + "/productList");
          return;
      }

      // Lưu thông tin vào request attribute trước khi forward sang views.
      request.setAttribute("errorString", errorString);
      request.setAttribute("product", product);

      RequestDispatcher dispatcher = request.getServletContext()
              .getRequestDispatcher("/WEB-INF/views/editProductView.jsp");
      dispatcher.forward(request, response);

  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      doGet(request, response);
  }

}
DoEditProductServlet.java
package org.o7planning.simplewebapp.servlet;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.o7planning.simplewebapp.beans.Product;
import org.o7planning.simplewebapp.utils.DBUtils;
import org.o7planning.simplewebapp.utils.MyUtils;

@WebServlet(urlPatterns = { "/doEditProduct" })
public class DoEditProductServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  public DoEditProductServlet() {
      super();
  }

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      Connection conn = MyUtils.getStoredConnection(request);

      String code = (String) request.getParameter("code");
      String name = (String) request.getParameter("name");
      String priceStr = (String) request.getParameter("price");
      float price = 0;
      try {
          price = Float.parseFloat(priceStr);
      } catch (Exception e) {
      }
      Product product = new Product(code, name, price);

      String errorString = null;

      try {
          DBUtils.updateProduct(conn, product);
      } catch (SQLException e) {
          e.printStackTrace();
          errorString = e.getMessage();
      }
      // Lưu thông tin vào request attribute trước khi forward sang views.
      request.setAttribute("errorString", errorString);
      request.setAttribute("product", product);

      // Nếu có lỗi forward sang trang edit
      if (errorString != null) {
          RequestDispatcher dispatcher = request.getServletContext()
                  .getRequestDispatcher("/WEB-INF/views/editProductView.jsp");
          dispatcher.forward(request, response);
      }
      // Nếu mọi thứ tốt đẹp.
      // Redirect sang trang danh sách sản phẩm.
      else {
          response.sendRedirect(request.getContextPath() + "/productList");
      }

  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      doGet(request, response);
  }

}
/WEB-INF/views/editProductView.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
 <head>
    <meta charset="UTF-8">
    <title>Edit Product</title>
 </head>
 <body>

    <jsp:include page="_header.jsp"></jsp:include>
    <jsp:include page="_menu.jsp"></jsp:include>

    <h3>Edit Product</h3>

    <p style="color: red;">${errorString}</p>

    <c:if test="${not empty product}">
       <form method="POST" action="doEditProduct">
          <input type="hidden" name="code" value="${product.code}" />
          <table border="0">
             <tr>
                <td>Code</td>
                <td style="color:red;">${product.code}</td>
             </tr>
             <tr>
                <td>Name</td>
                <td><input type="text" name="name" value="${product.name}" /></td>
             </tr>
             <tr>
                <td>Price</td>
                <td><input type="text" name="price" value="${product.price}" /></td>
             </tr>
             <tr>
                <td colspan = "2">
                    <input type="submit" value="Submit" />
                    <a href="${pageContext.request.contextPath}/productList">Cancel</a>
                </td>
             </tr>
          </table>
       </form>
    </c:if>

    <jsp:include page="_footer.jsp"></jsp:include>

 </body>
</html>

22- Chức năng xóa sản phẩm

Mô hình xóa sản phẩm:
DeleteProductServlet.java
package org.o7planning.simplewebapp.servlet;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.o7planning.simplewebapp.utils.DBUtils;
import org.o7planning.simplewebapp.utils.MyUtils;

@WebServlet(urlPatterns = { "/deleteProduct" })
public class DeleteProductServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  public DeleteProductServlet() {
      super();
  }

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      Connection conn = MyUtils.getStoredConnection(request);

      String code = (String) request.getParameter("code");

      String errorString = null;

      try {
          DBUtils.deleteProduct(conn, code);
      } catch (SQLException e) {
          e.printStackTrace();
          errorString = e.getMessage();
      }
     
      // Nếu có lỗi forward sang trang báo lỗi.
      if (errorString != null) {
          // Lưu thông tin vào request attribute trước khi forward sang views.
          request.setAttribute("errorString", errorString);
          //
          RequestDispatcher dispatcher = request.getServletContext()
                  .getRequestDispatcher("/WEB-INF/views/deleteProductErrorView.jsp");
          dispatcher.forward(request, response);
      }
      // Nếu mọi thứ tốt đẹp.
      // Redirect sang trang danh sách sản phẩm.
      else {
          response.sendRedirect(request.getContextPath() + "/productList");
      }

  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      doGet(request, response);
  }

}
/WEB-INF/views/deleteProductErrorView.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
 pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
 <head>
    <meta charset="UTF-8">
    <title>Delete Product</title>
 </head>

 <body>

    <jsp:include page="_header.jsp"></jsp:include>
    <jsp:include page="_menu.jsp"></jsp:include>
   
    <h3>Delete Product</h3>
   
    <p style="color: red;">${errorString}</p>
    <a href="productList">Product List</a>
   
    <jsp:include page="_footer.jsp"></jsp:include>
   
 </body>
</html>