Simulacrum, từ simulacrum Latin, là một sự bắt chước, giả mạo hoặc hư cấu. Khái niệm này được liên kết với mô phỏng, đó là hành động mô phỏng .Một...
Tạo một ứng dụng Java Web đơn giản sử dụng Servlet, JSP và JDBC
1- Giới thiệu
Tài liệu được viết dựa trên :
- Eclipse 4.5 MARS
- Tomcat 8.x
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 và Filter và JDBC trước khi bắt đầu. Nếu không, bạn có thể tham khảo tại:
Chú ý: Trong bài viết này tôi chỉ giới thiệu về chức năng CRUD, “Login” và chức năng “Remember Me”. Và không xử lý bảo mật các trang, nếu bạn muốn có một ứng dụng bảo mật các trang hãy tham khảo thêm bài viết dưới đây:
- Tạo một ứng dụng Login đơn giản và bảo mật với Java Servlet Filter
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 :
- Đừ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.
- Chỉ coi JSP là cái để hiển thị giao diện.
- 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.
- 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 :
- 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.
Không khi nào được cho phép người dùng truy vấn 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à : Như vậy bạn phải cất giấu những file JSP của bạn tại một nơi nào đó mà người dùng không hề truy vấn vào. Chẳng hạn đặt trong thư mụchoặc thư mục con của nó. Trong ví dụ này tôi sẽ để những filetại thư mục
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à chuyển tiếp (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ị tài liệu, điều đó có nghĩa là bạn không nên giải quyết và xử lý logic ứng dụng trên JSP, ví dụ điển hình 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 hoàn toàn có thể xem trước bản ra mắt ( 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
Simple Web Application
Simple Login Web Application using JSP/Servlet
- Home
- Login
- Product List
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ẽ mở màn 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 hoàn toàn có thể xem hướng dẫn tải về JDBC driver tại :
Hoặc tải về những thư viện JDBC cho MySQL, Sql Server, Oracle tại đây :
- some-jdbc-drivers.zip (MySQL + SQL Server + Oracle) o7planning link.
Kết quả tải về đượ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 lớp 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 lớp 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 {
Class.forName("com.mysql.jdbc.Driver");
// Cấu trúc URL Connection đối với 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 = "db12c";
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 {
Class.forName("oracle.jdbc.driver.OracleDriver");
// Cấu trúc URL Connection đối với Oracle
// Ví dụ:
// jdbc:oracle:thin:@localhost:1521:db11g
// jdbc:oracle:thin:@//HOSTNAME:PORT/SERVICENAME
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);
}
// Kết nối tới SQL Server sử dụng thư viện JTDS.
private static Connection getSQLServerConnection_JTDS(String hostName, //
String sqlInstanceName, String database, String userName, String password)
throws ClassNotFoundException, SQLException {
Class.forName("net.sourceforge.jtds.jdbc.Driver");
// Cấu trúc URL Connection đối với SQL Server:
// 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 SQL Server.
// (Sử dụng thư việ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);
}
// Kết nối tới SQLServer, sử dụng thư viện SQLJDBC.
private static Connection getSQLServerConnection_SQLJDBC(String hostName, //
String sqlInstanceName, String database, String userName, String password)//
throws ClassNotFoundException, SQLException {
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 OracleConnUtils.getOracleConnection();
// return MySQLConnUtils.getMySQLConnection();
// return SQLServerConnUtils_JTDS.getSQLServerConnection_JTDS();
// return SQLServerConnUtils_SQLJDBC.getSQLServerConnection_SQLJDBC();
// return PostGresConnUtils.getPostGresConnection();
}
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 lớp 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 attribute của request.
// Thông tin lưu trữ này 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 attribute 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 thông qua ${loginedUser}
session.setAttribute("loginedUser", loginedUser);
}
// Lấy thông tin người dùng lưu trữ 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. (Cookie này sẽ hết hiệu lực 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 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 list = new ArrayList();
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 From Product where Code= ?";
PreparedStatement pstm = conn.prepareStatement(sql);
pstm.setString(1, code);
pstm.executeUpdate();
}
}
13- Tạo Servlet 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 mục tiêu của 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 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 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ở connection (kết nối) đối với các request có đường dẫn đặc biệt.
// (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ữ đối tượng Connection vào attribute của request.
MyUtils.storeConnection(request, conn);
// Cho phép request đi tiếp.
// (Đi tới Filter tiếp theo hoặc đi tới mục tiêu).
chain.doFilter(request, response);
// Gọi phương thức commit() để hoàn thành 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.
else {
// Cho phép request đi tiếp.
// (Đi tới Filter tiếp theo hoặc đi tới mục tiêu).
chain.doFilter(request, response);
}
}
}
14- Servlet Filter đọc Cookie để tự động đăng nhập
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);
//
if (userInSession != null) {
session.setAttribute("COOKIE_CHECKED", "CHECKED");
chain.doFilter(request, response);
return;
}
// Connection đã được tạo trong JDBCFilter.
Connection conn = MyUtils.getStoredConnection(request);
// Cờ (flag) để kiểm tra Cookie.
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();
}
// Đánh dấu đã 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).
jdbcFilter
/*
cookieFilter
/*
web.xml đầy đủ:
web.xml
SimpleWebApp
jdbcFilter
/*
cookieFilter
/*
home
index.html
15- Servlet Encoding Filter
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 những trang khác tại thời gian Runtime, trải qua việc sử dụng :
/ WEB-INF / views / _header. jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
My Site
Hello ${loginedUser.userName}
Search
/ WEB-INF / views / _menu. jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
Home
|
Product List
|
My Account Info
|
Login
/ WEB-INF / views / _footer. jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
@Copyright o7planning.org
17- 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
Đườ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
SimpleWebApp
jdbcFilter
/*
cookieFilter
/*
home
index.html
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"%>
Home Page
Home Page
This is demo Simple web application using jsp,servlet & Jdbc.
It includes the following functions:
- Login
- Storing user information in cookies
- Product List
- Create Product
- Edit Product
- Delete Product
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- Trang đăng nhập – LoginServlet
Đây là quy mô tính năng Login :
LoginServlet. 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 = { "/login" })
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LoginServlet() {
super();
}
// Hiển thị trang Login.
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Forward tới trang /WEB-INF/views/loginView.jsp
// (Người dùng không thể truy cập trực tiếp
// vào các trang JSP đặt trong thư mục WEB-INF).
RequestDispatcher dispatcher //
= this.getServletContext().getRequestDispatcher("/WEB-INF/views/loginView.jsp");
dispatcher.forward(request, response);
}
// Khi người nhập userName & password, và nhấn Submit.
// Phương thức này sẽ được thực thi.
@Override
protected void doPost(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 (chuyển hướng) tới /WEB-INF/views/login.jsp
if (hasError) {
user = new UserAccount();
user.setUserName(userName);
user.setPassword(password);
// Lưu các thông tin vào request attribute trước khi forward.
request.setAttribute("errorString", errorString);
request.setAttribute("user", user);
// Forward (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 tính năng "Remember me".
if (remember) {
MyUtils.storeUserCookie(response, user);
}
// Ngược lại xóa Cookie
else {
MyUtils.deleteUserCookie(response);
}
// Redirect (Chuyển hướng) sang trang /userInfo.
response.sendRedirect(request.getContextPath() + "/userInfo");
}
}
}
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 đã đăng nhập (login) chưa.
UserAccount loginedUser = MyUtils.getLoginedUser(session);
// Nếu chưa đăng nhập (login).
if (loginedUser == null) {
// Redirect (Chuyển hướng) tới trang login.
response.sendRedirect(request.getContextPath() + "/login");
return;
}
// Lưu thông tin vào request attribute trước khi forward (chuyển tiếp).
request.setAttribute("user", loginedUser);
// Nếu người dùng đã login thì forward (chuyển tiếp) tới trang
// /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"%>
Login
Login Page
USD { errorString }
User Name : tom, password : tom001 or jerry / jerry001
/ WEB-INF / views / userInfoView. jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
User Info
Hello: ${user.userName}
User Name: ${user.userName}
Gender: ${user.gender }
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 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" %>
Product List
Product List
USD { errorString }
Code
Name
Price
Edit
Delete
${product.code}
${product.name}
${product.price}
Edit
Delete
Create Product
Chạy lại ứng dụng :
20- Thêm sản phẩm
Mô hình tính năng thêm loại sản phẩm :
CreateProductServlet. 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 = { "/createProduct" })
public class CreateProductServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public CreateProductServlet() {
super();
}
// Hiển thị trang tạo sản phẩm.
@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);
}
// Khi người dùng nhập các thông tin sản phẩm, và nhấn Submit.
// Phương thức này sẽ được gọi.
@Override
protected void doPost(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 (chuyển tiếp) 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 (chuyển hướng) sang trang danh sách sản phẩm.
else {
response.sendRedirect(request.getContextPath() + "/productList");
}
}
}
/ 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"%>
Create Product
Create Product
USD { errorString }
21- Sửa thông tin sản phẩm
Mô hình tính năng sửa thông tin mẫu 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();
}
// Hiển thị trang sửa sản phẩm.
@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);
}
// Sau khi người dùng sửa đổi thông tin sản phẩm, và nhấn Submit.
// Phương thức này sẽ được thực thi.
@Override
protected void doPost(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");
}
}
}
/ 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"%>
Edit Product
Edit Product
USD { errorString }
22- 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 (chuyển tiếp) sang trang thông 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 (chuyển hướng) 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"%>
Delete Product
Delete Product
USD { errorString }
Product List
Source: https://vh2.com.vn
Category : Tin Học