Hướng dẫn làm ứng dụng java

Hướng dẫn làm ứng dụng java

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 FilterJDBC 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:

Đâ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ì.

  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).
     

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.

Hướng dẫn làm ứng dụng java

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).

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.

Bạn có thể xem trước bản giới thiệu (Demo) ứng dụng Web sẽ làm:

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.

-- 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;

-- 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);

-- 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);

Hướng dẫn làm ứng dụng java

Hướng dẫn làm ứng dụng java

Hướng dẫn làm ứng dụng java

Hướng dẫn làm ứng dụng java

Hướng dẫn làm ứng dụng java

Hướng dẫn làm ứng dụng java

Simple Web Application

Simple Login Web Application using JSP/Servlet

Ứ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.

Hướng dẫn làm ứng dụng java

Hướng dẫn làm ứng dụng java

Hướng dẫn làm ứng dụng java

Hướng dẫn làm ứng dụng java

Nhấn phải chuột vào Project SimpleWebApp, chọn:

Hướng dẫn làm ứng dụng java

Hướng dẫn làm ứng dụng java

Hướng dẫn làm ứng dụng java

Hướng dẫn làm ứng dụng java

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ự.

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:

  • some-jdbc-drivers.zip (MySQL + SQL Server + Oracle) o7planning link.

Hướng dẫn làm ứng dụng java

Copy các thư viện này vào WEB-INF/lib:

Hướng dẫn làm ứng dụng java

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

Hướng dẫn làm ứng dụng java

Hướng dẫn làm ứng dụng java

Copy 2 file jar bạn vừa download được vào thư mục /WEB-INF/lib:

Hướng dẫn làm ứng dụng java

Tạo một số class Javabean, mỗi class mô phỏng một bảng trong database:

Hướng dẫn làm ứng dụng 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; } }

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; } }

Hướng dẫn làm ứng dụng 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; } }

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; } }

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) { } } }

Hướng dẫn làm ứng dụng 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); } }

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(); } }

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.

Hướng dẫn làm ứng dụng java

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.

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 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); } } }

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.

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); } }

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 /*

SimpleWebApp jdbcFilter /* cookieFilter /* home index.html

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); } }

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:

Hướng dẫn làm ứng dụng java

/WEB-INF/views/_header.jsp

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

My Site

Hello ${loginedUser.userName}
Search

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

/WEB-INF/views/_footer.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
@Copyright o7planning.org

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 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.

SimpleWebApp jdbcFilter /* cookieFilter /* home index.html

Hướng dẫn làm ứng dụng 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:

Hướng dẫn làm ứng dụng java

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

Đây là mô hình chức năng Login:

Hướng dẫn làm ứng dụng 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"); } } }

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); } }

Hướng dẫn làm ứng dụng java

/WEB-INF/views/loginView.jsp

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

Login Page

${errorString}

User Name
Password
Remember me
Cancel

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 }

Hướng dẫn làm ứng dụng java

Hướng dẫn làm ứng dụng java

Hướng dẫn làm ứng dụng 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

${errorString}

Code Name Price Edit Delete
${product.code} ${product.name} ${product.price} Edit Delete
Create Product

Hướng dẫn làm ứng dụng java

Mô hình chức năng thêm sản phẩm:

Hướng dẫn làm ứng dụng java

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

${errorString}

Code
Name
Price
Cancel

Hướng dẫn làm ứng dụng java

Mô hình chức năng sửa thông tin sản phẩm:

Hướng dẫn làm ứng dụng 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

${errorString}

Code ${product.code}
Name
Price
Cancel

Hướng dẫn làm ứng dụng java

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

${errorString}

Product List