JSP/Servlet 實現(xiàn)簡單的留言板系 統(tǒng) 概 述 一個簡單的留言板所實現(xiàn)的功能有:用戶注冊,、用戶登錄,、查看留言信息和留言四個功能。在學習了JSP/Servlet后編寫的 一個簡單的實例,,雖然簡單,,卻擁有一個完整系統(tǒng)的必要功能,所以可以讓自己初步了解使用JSP/Servlet技術開發(fā)系統(tǒng)的一般步驟,。
系統(tǒng)功能簡介: 用戶注冊:當用戶注冊一個新用戶時,,就是向數(shù)據(jù)庫user_table表中添加一條記錄。 當用戶輸入注冊信息后,,將用戶的的注冊信息提交到服務端負責處理注冊信息的Servlet,。當Servlet成功處理完用戶的信息后, 客戶端自動跳轉(zhuǎn)到【登錄界面】進行登錄,。 用戶登錄:當用戶輸入用戶名,、密碼和驗證碼時,。系統(tǒng)將信息提交的處理登錄信息的Servlet,。Servlet則調(diào)用服務器控制器里 的方法來處理用戶登錄。當用戶登錄成功時,,客戶端自動跳轉(zhuǎn)到【留言板】,。 留言板:調(diào)用數(shù)據(jù)庫中的留言信息,,顯示在頁面上。同時用戶可以通過【留言】按鈕,,跳轉(zhuǎn)到【留言】界面,,留言功能和注冊功能 類似,向數(shù)據(jù)庫ly_table表中添加一條記錄,。
數(shù)據(jù)庫的設計: 對于該系統(tǒng)來說有兩個表【user_table】和【ly_table】,。 【user_table】如下:
【ly_table】如下:
實現(xiàn)系統(tǒng)的基礎類: 實現(xiàn)在注冊、登錄系統(tǒng)中使用的一些重要的類:連接和操作數(shù)據(jù)庫的DB類,、存儲用戶的User類,、 存儲留言信息的LeaveMessageTable類和實現(xiàn)圖形驗證碼的ValidationCode類。 連接和操作數(shù)據(jù)庫的DB類中具體包括如下方法: public User checkUser(String username , String password) :檢查用戶時候存在,,存在就返回一個User對象,,否則返回null 。 public boolean checkValidationCode(HttpServletRequest request ,String validationCode) :檢測驗證碼是否正確,。 public boolean addInfo(LeaveMessageTable ly) : 向數(shù)據(jù)庫插入留言,。 public boolean insertUser(String username,String password) :向數(shù)據(jù)庫存入用戶。 public ArrayList findLyInfo() : 從數(shù)據(jù)庫中導出留言,,返回一個ArrayList對象,。 private ResultSet execSQL(String sql , Object ...args) : 執(zhí)行SQL語句。
在DB類的構造函數(shù)中連接數(shù)據(jù)庫,。這樣有Servlet類創(chuàng)建DB對象時,,便在創(chuàng)建過程中進行數(shù)據(jù)庫的連接,。
package com.cnblogs.jbelial.DBServlet; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.*; import javax.servlet.http.HttpServletRequest; import Common.Encrypter; import Common.LeaveMessageTable; import Common.User; public class DB{ // 定義數(shù)據(jù)庫連接變量 private Connection connection ; // 定義參數(shù) private String sql_driver = "com.mysql.jdbc.Driver" ; private String sql_url = "jdbc:mysql://localhost:3306/web_ly_table" ; private String sql_username = "root" ; private String sql_password = "hezuoan" ; public DB() { try { //建立數(shù)據(jù)庫的連接 Class.forName(sql_driver) ; connection = DriverManager.getConnection(sql_url,sql_username,sql_password) ; } catch(Exception e) { e.printStackTrace() ; } } // 用于執(zhí)行各種SQL語句的方法 private ResultSet execSQL(String sql , Object ...args) throws SQLException { PreparedStatement pstmt = connection.prepareStatement(sql) ; // 為PreparedStatement對象設置SQL參數(shù) for (int i = 0 ; i < args.length ; ++ i) { pstmt.setObject(1 + i, args[i]) ; } // 運行 pstmt.execute() ; return pstmt.getResultSet(); } // 核對用戶輸入的驗證碼是否正確 public boolean checkValidationCode(HttpServletRequest request , String validationCode) { String validationCodeSession = (String) request.getSession().getAttribute("validationCode") ; if(validationCodeSession == null) { // 給result.jsp設置信息 request.setAttribute("info" , "驗證碼過期") ; // 給login.jsp設置信息 request.setAttribute("codeError", "驗證碼過期") ; return false ; } if(!validationCode.equalsIgnoreCase(validationCodeSession)) { request.setAttribute("info","驗證碼錯誤") ; request.setAttribute("codeError", "驗證碼錯誤") ; return false ; } return true; } // 檢查用戶登錄信息 public User checkUser(String username , String password) { try { String sql = "select * from user_table where username = ? and password = ?" ; ResultSet rs = execSQL(sql,username,password) ; User user = new User() ; while (rs.next()) { user.setId(rs.getInt("id")) ; user.setUsername(rs.getString("username")) ; user.setPassword(rs.getString("password")) ; return user ; } return null ; } catch(Exception e) { e.printStackTrace(); return null ; } } // 插入留言 public boolean addInfo(LeaveMessageTable ly){ try{ String sql = "insert into ly_table(userId,data,title,content) values(?,?,?,?)" ; execSQL(sql , ly.getUserId(), ly.getDate(),ly.getTitle(),ly.getContent()); return true; }catch(Exception e){ e.printStackTrace(); return false; } } // 插入用戶 public boolean insertUser(String username,String password){ try{ String sql = "insert into user_table(username,password) values(?,?)" ; execSQL(sql ,username , password) ; return true; }catch(Exception e){ e.printStackTrace(); return false; } } // 獲取留言信息,。 public ArrayList findLyInfo() { ArrayList arrayList = new ArrayList() ; try { String sql = "select * from ly_table" ; ResultSet rs = execSQL(sql) ; while(rs.next()) { LeaveMessageTable ly = new LeaveMessageTable() ; ly.setId(rs.getInt("id")) ; ly.setUserId(rs.getInt("userId")) ; ly.setDate(rs.getDate("data")) ; ly.setTitle(rs.getString("title")) ; ly.setContent(rs.getString("content")) ; arrayList.add(ly) ; } return arrayList ; } catch(Exception e) { e.printStackTrace() ; return null ; } } // 獲取用戶名 public String getUserName(int id) { String username = null; try{ String sql = "select username from user_table where id = ?" ; ResultSet rs= execSQL(sql , new Object[]{id}); while(rs.next()){ username=rs.getString(1); } return username; }catch(Exception e){ e.printStackTrace(); return null; } } }
User類和LeaveMessageTable類: User類中則包含Id、用戶名和密碼三個屬性,。同時包含各個屬性的set和get方法,。
package Common; public class User { // 用戶的id private int id ; // 用戶名 private String username ; // 用戶密碼 private String password ; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
LeaveMessageTable類:包含了如下屬性Id、留言用戶Id,、留言標題,、留言時間、留言類容屬性,。同時也包含了各個屬性的 set和get方法,。
package Common; import java.sql.Date; public class LeaveMessageTable { private int id ; private int userId ; private Date date ; private String title ; private String content ; public int getId() { return id; } public void setId(int id) { this.id = id; } public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } }
實現(xiàn)圖形驗證碼: 實現(xiàn)圖形驗證碼大致分為5步上來完成: 1,、建立圖形緩沖區(qū),; 2、在圖形緩沖區(qū)用隨機顏色填充背景,。 3,、在圖形緩沖區(qū)上輸出驗證碼,。 4、將驗證碼保存在HttpSession對象中,。 5,、向客戶端輸出圖形驗證碼。 通過ValidationCode類來實現(xiàn)驗證碼功能,,該類也是Servlet類,,在客戶端只要像訪問普通Servlet一樣訪問ValidationCode類即可。
package com.cnblogs.jbelial.Validation; import java.awt.*; import java.awt.image.BufferedImage; import java.io.* ; import java.util.Random; import javax.imageio.ImageIO; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @SuppressWarnings("serial") public class ValidationCode extends HttpServlet { // 圖形驗證碼的字符集合,,系統(tǒng)通過隨機從這些字符串中選擇一些字符作為驗證碼 private static String codeChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTYVWXYZ" ; // 返回一個隨機顏色 private static Color getRandomColor(int minColor , int maxColor) { Random random = new Random() ; if (minColor > 255) minColor = 255 ; if (maxColor > 255) maxColor = 255 ; // 獲取顏色的隨機值 int red = minColor + random.nextInt(maxColor - minColor) ; int green = minColor + random.nextInt(maxColor - minColor) ; int blue = minColor + random.nextInt(maxColor - minColor) ; return new Color(red,green,blue) ; } public void doGet (HttpServletRequest request , HttpServletResponse response) throws IOException { // 獲取驗證碼集合的長度,。 int charsLength = codeChars.length() ; // 關閉瀏覽器緩沖區(qū) response.setHeader("ragma", "No-cache") ; response.setHeader("Cache-Control", "no-cache") ; response.setDateHeader("Expires", 0) ; // 設置圖片傳送的格式。 response.setContentType("image/jpeg"); // 設置圖形驗證碼的長和寬度 int width = 90 ; int height = 20 ; // 建立圖形緩沖區(qū) BufferedImage image = new BufferedImage(width , height, BufferedImage.TYPE_INT_RGB) ; // 獲取用于輸出文字的Graphics對象 Graphics graphics = image.getGraphics() ; Random random = new Random() ; // 設置要填充的顏色 graphics.setColor(getRandomColor(180 , 250)) ; // 填充圖形背景 graphics.fillRect(0, 0, width, height) ; // 設置初始字體和顏色 graphics.setFont(new Font("Time New Roman" , Font.ITALIC, height)) ; graphics.setColor(getRandomColor(120,180)) ; // 保存驗證碼 StringBuilder validationCode = new StringBuilder() ; // 驗證碼的隨機字體 String[] fontNames = {"Times New Roman" , "Book antiqua" , "Arial" } ; // 隨機生成驗證碼 for (int i = 0 ; i < 4 ; ++ i) { // 設置當前驗證碼字符的字體 graphics.setFont(new Font(fontNames[random.nextInt(3)] , Font.ITALIC , height)) ; // 隨機獲得驗證碼的字符 char codeChar = codeChars.charAt(random.nextInt(charsLength)) ; validationCode.append(codeChar) ; graphics.setColor(getRandomColor(20,120)) ; // 在圖形上輸出驗證碼字符 graphics.drawString(String.valueOf(codeChar), 16*i+random.nextInt(7), height - random.nextInt(6) ) ; } // 獲得Session對象,,并設置Session對象為3分鐘 HttpSession session = request.getSession(); session.setMaxInactiveInterval(5*60) ; // 將驗證碼放入session對象中. session.setAttribute("validationCode",validationCode.toString() ) ; // 關閉graphics對象,。 graphics.dispose() ; // 向客戶端發(fā)送圖形驗證碼 ImageIO.write(image,"JPEG" ,response.getOutputStream()) ; } public void doPost (HttpServletRequest request , HttpServletResponse response) throws IOException { doGet(request , response) ; } }
實現(xiàn)注冊系統(tǒng): 包括一個register.jsp、result.jsp和RegisterServlet類,。 RegisterServlet類負責處理處理用戶的提交的注冊信息,。 RegisterServlet類在處理用戶注冊信息之前,創(chuàng)建DB類對象來連接數(shù)據(jù)庫,。然后通過調(diào)用DB類的方法來判斷驗證碼是否正確和用戶名是否被注冊,。 當一系列的判斷都通過時,則向數(shù)據(jù)庫中插入用戶記錄,。 RegisterServlet類的最后不管是否向數(shù)據(jù)庫中插入用戶記錄,,都會跳轉(zhuǎn)到result.jsp頁面。
package com.cnblogs.jbelial.Register; import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import Common.User; import com.cnblogs.jbelial.DBServlet.DB; public class RegisterServlet extends HttpServlet { /** * The doGet method of the servlet. <br> * * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 設置字符集編碼 request.setCharacterEncoding("UTF-8") ; response.setContentType("UTF-8"); // 判斷是否跳到【登錄】 if (request.getParameter("login") != null) { response.sendRedirect("login.jsp") ; return ; } DB db = new DB() ; String username = null ; // 設置result頁面要跳轉(zhuǎn)的頁面 String page = "login.jsp" ; try { // 獲取界面的用戶名和密碼參數(shù) username = request.getParameter("username") ; String password = request.getParameter("password") ; String validationCode = request.getParameter("validationCode") ; // 核對驗證碼 if (!db.checkValidationCode(request, validationCode)) return ; User user = db.checkUser(username,password) ; if (user != null) { request.setAttribute("info", username + "已被使用,!") ; page = "register.jsp" ; } else if (db.insertUser(username , password)) { // 定義result.jsp中使用的消息 request.setAttribute("info" , "用戶注冊成功") ; } request.setAttribute("page", page) ; } catch(Exception e) { } finally { // 跳轉(zhuǎn)到result.jsp RequestDispatcher rd = request.getRequestDispatcher("/result.jsp") ; rd.forward(request, response) ; } } /** * The doPost method of the servlet. <br> * * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response) ; } }
register.jsp則負責顯示注冊頁面: <%@ page language="java" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>用戶注冊</title> <script type="text/javaScript"> function refresh() { var img = document.getElementById("imgValidationCode") ; img.src = "ValidationCode"+Math.random() ; } function checkRegister() { var username = document.getElementById("username") ; if(username.value == "" ) { alert("請輸入用戶名,!") ; //把焦點放到username輸入文本上 username.focus() ; return ; } var password = document.getElementById("password") ; if(password.value == "" ) { alert("請輸入密碼!"); password.focus() ; return ; } var re_password = document.getElementById("re_password") ; if(re_password.value != password.value) { alert("輸入的密碼不一致,!") ; re_password.focus() ; return ; } var validationCode = document.getElementById("validationCode") ; if(validatoinCode.value == "") { alert("請輸入驗證碼,!"); validatoinCode.focus() ; return ; } register_form.submit() ; } </script> </head> <body> <center> <h2>用戶注冊</h2> <form name = "register_form" action = "RegisterServlet" method = "post"> <table> <tr> <td> 用戶名: </td> <td> <input type = "text" id = "username" name = "username" size = "25"> </td> </tr> <tr> <td> 密碼: </td> <td> <input type = "password" id = "password" name = "password" size = "25"> </td> </tr> <tr> <td> 再次輸入密碼: </td> <td> <input type = "password" id = "re_password" name = "re_password" size = "25"> </td> </tr> <tr> <td> 驗證碼: </td> <td> <input type = "text" id = "validationCode" name = "validationCode" style = "width:60px;margin-top:10px"/> <img id = "imgValidationCode" src = "ValidationCode"/> <input type = "button" value = "刷新" onclick = "refresh()"/> </td> </tr> </table> <input type = "button" value = "注冊" onclick = "checkRegister()"/> <input type = "submit" value = "登錄" name = "login"> </form> </center> </body> </html>
result.jsp頁面則負責顯示結果:
實現(xiàn)登錄系統(tǒng): 登錄系統(tǒng)和注冊系統(tǒng)類似,包含login.jsp和LoginServlet類,。 LoginServlet類負責處理用戶提交的登錄信息,。通過創(chuàng)建DB對象來連接數(shù)據(jù)庫,再調(diào)用DB中的方法來判斷用戶提交的驗證碼和用戶名,、密碼 的真確性,,如果都正確則跳轉(zhuǎn)到main.jsp,否則返回到login.jsp并顯示提示消息,;
package com.cnblogs.jbelial.Login; import java.io.IOException; import java.util.ArrayList; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import Common.User; import com.cnblogs.jbelial.DBServlet.DB; public class LoginServlet extends HttpServlet { /** * The doGet method of the servlet. <br> * * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 設置字符集編碼 request.setCharacterEncoding("UTF-8") ; response.setContentType("UTF-8"); // 判斷是否跳到【注冊】 if (request.getParameter("register") != null) { response.sendRedirect("register.jsp") ; return ; } DB db = new DB() ; // 設置跳轉(zhuǎn)界面 String page = "login.jsp" ; String username = null ; try { // 獲取請求頁面的參數(shù) username = request.getParameter("username") ; String password = request.getParameter("password") ; String validationCode = request.getParameter("validationCode") ; // 驗證碼檢測 if (!db.checkValidationCode(request, validationCode)) return ; User user = db.checkUser(username,password) ; if (user == null) request.setAttribute("userError", "用戶名或密碼錯誤") ; if (user != null) { // 如果根據(jù)檢查,,user不為空,表示用戶名正確和密碼正確,,進行下一步操作,。 ArrayList arrayList = new ArrayList() ; arrayList = db.findLyInfo() ; request.setAttribute("arrayList", arrayList) ; // 設置跳轉(zhuǎn)到主界面 page = "main.jsp" ; request.getSession().setAttribute("user", user) ; } } catch(Exception e){} finally { request.setAttribute("username", username) ; RequestDispatcher rd = request.getRequestDispatcher("/"+page) ; rd.forward(request, response) ; } } /** * The doPost method of the servlet. <br> * * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request,response) ; } }
login.jsp則負責顯示登錄界面 <%@ page language="java" pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>用戶登錄</title> </head> <script type="text/javaScript"> function refresh() { var img = document.getElementById("imgValidationCode") ; img.src = "ValidationCode" ; } function checkLogin() { var username = document.getElementById("username_id"); if (username.value == "" ) { alert("請輸入用戶名!") ; username.focus() ; return ; } var password = document.getElementById("password_id") ; if (password.value == "") { alert("密碼不能為空"); password.focus() ; return ; } var validationCode = document.getElementById("validationCode_id") ; if ( validationCode.value == "") { alert("驗證嗎不能為空") ; validationCode.focus() ; return ; } login_form.submit() ; } </script> <body> <center> <h2>用戶登錄</h2> <form name = "login_form" action = "LoginServlet" method = "post" > <table> <tr> <td> 用戶名: </td> <td> <input type = "text" id = "username_id" value = "${requestScope.username}" name = "username" size = "25" />${requestScope.userError} </td> </tr> <tr> <td> 密 碼: </td> <td> <input type="password" id="password_id" name="password" size="25"> </td> </tr> <tr> <td> 驗證碼: </td> <td> <input type = "text" id = "validationCode_id" name = "validationCode" style = "width:60px;margin-top:10px"/> <img id = "imgValidationCode" src = "ValidationCode"/> <input type = "button" value = "刷新" onclick = "refresh()"/> ${requestScope.codeError} </td> </tr> </table> <input type = "button" value = "登錄" onclick = "checkLogin()"> <input type = "submit" value = "注冊" name = "register"> </form> </center> </body> </html>
實現(xiàn)留言系統(tǒng): 留言系統(tǒng)包括負責顯示用戶留言的main.jsp頁面,、用戶寫留言的LeaveMessage.jsp頁面和處理用戶提交留言的addMessageServlet類 。 addMessageServlet類就是把用戶提交的留言信息提取出來,,然后存入數(shù)據(jù)庫,。 main.jsp則在用戶登錄后,自動跳轉(zhuǎn)到顯示留言的界面,。
|
|