您好,登錄后才能下訂單哦!
這一篇博客將詳細介紹一個基于Servlet的問答網站的實現,有詳細的代碼。
可能篇幅較長,以代碼為主,有興趣的童鞋看完可以嘗試動手搭建一個屬于自己的問答社區。
工具:Eclipse,數據庫用到了MySQL,這次項目中未使用jsp,全部以Servlet注解的方式連接HTML和Servlet,JDK最好使用1.8,tomcat使用8.0。(注解方式為JDK1.5后的特性,最低要求1.5+,本項目使用JDK1.8)。
在這篇博客中可以學習到:
1,Servlet中關于注解的使用,本項目沒有使用到傳統的Servlet配置web.xml,全部使用注解的形式。
2,了解Font Awesome這一矢量圖標庫的使用,他基本提供了項目中所要使用到的所有圖標,方便,快捷。
3,了解simditor這一富文本編輯器的使用,網站中直接嵌入富文本編輯器,再也不用為讀取出來的文字格式不對發愁了。
4,關于項目中如何加入驗證碼,數據庫查詢之前先進行驗證碼驗證。
5,關于MVC框架顯示層——Velocity技術的使用。
先看一下大體項目圖(由于主要做后臺,前臺可能略丑,大家可以自行找網站模板)
登錄界面:
注冊界面:
首頁,展示了大家的提問:
解答界面,點擊別人的提問后進入解答界面,使用了富文本編輯器。
我的解答界面,展示了我回答的歷史:
我的提問界面,展示了我提問的所有問題:
提問界面:進入網站點擊我要提問,加入當前頁編輯問題:
下面介紹主要代碼(代碼中加入了詳細注釋,所以不再做說明)
主頁列表Servlet:
@WebServlet( "/list.do" ) public class ListServlet extends HttpServlet { private static final long serialVersionUID = 810339694607399128L; @Override protected void service( HttpServletRequest request , HttpServletResponse response ) throws ServletException, IOException { String question=request.getParameter("quest"); System.out.println(question); if(StringHelper.notEmpty(question)){ final String SQL = "SELECT id , title ,content, publish_time , publish_ip , user_id FROM t_topic where title =? " ; ResultSet rs = JdbcHelper.query( SQL,question ); // 創建一個 List 對象,用來保存一批 Topic 對象 final List<Topic> topics = new ArrayList<>(); try { // 每循環一次,光標下移一行,如果該行有數據返回 true while( rs.next() ){ Topic t = new Topic(); // 創建對象 t.setId( rs.getInt( 1 ) ); // 將 結果集 中的 該行數據 封裝到 t 對象的 id 屬性中 t.setTitle( rs.getString( 2 ) ); t.setContent(rs.getString(3)); t.setPublishTime( rs.getTimestamp( 4 )); t.setPublishIp( rs.getString( 5 ) ); User u = new User(); // 創建 一個 User 對象 u.setId( rs.getInt( 6 ) ); // 將 t_topic 表中的 user_id 放入到 User 對象的 id 屬性中 t.setUser( u ); // 將 User 對象 設置到 Topic 對象上 /** 將 本次循環 創建的對象(已經封裝數據) 添加到 List 集合中 */ topics.add( t ); } } catch (SQLException e) { e.printStackTrace(); } JdbcHelper.release( rs ); // 關閉 結果集,釋放相關的資源 /**** 為每個問題尋找提問者 ***********************************/ //for( int i = 0 ; i < topics.size() ; i++ ){ for( int i = 0 , len = topics.size() ; i < len ; i++ ){ Topic t = topics.get( i ) ; // 獲得 題目 User u = t.getUser(); // 獲得當前題目的User對象 ( 該對象中只有 id 沒有其它數據 ) // 根據 用戶對象的 id 來查詢 用戶的信息 String querySQL = "SELECT id , username , password FROM t_user WHERE id = ? " ; ResultSet userRs = JdbcHelper.query( querySQL , u.getId() ); try { if( userRs.next() ) { // 如果查詢到用戶信息 // 注意,這里應該使用 userRs u.setUsername( userRs.getString( 2 ) ); // 將 username 列的值設置到 用戶對象的 username 屬性中 u.setPassword( userRs.getString( 3 )); // 將 password 列的值設置到 用戶對象的 password 屬性中 } } catch (SQLException e) { e.printStackTrace(); } JdbcHelper.release( userRs ); // 關閉 結果集,釋放相關的資源 } ServletContext application = request.getServletContext(); /** 將這些數據保存到 application **/ application.setAttribute( "topics" , topics ); System.out.println( "問題列表: " + topics ); // 去 list.html 頁面 response.sendRedirect( request.getContextPath() + "/list.html"); }else{ /**** 查詢數據庫中的所有問題 ***********************************/ final String SQL = "SELECT id , title ,content ,publish_time , publish_ip , user_id FROM t_topic ORDER BY publish_time DESC" ; ResultSet rs = JdbcHelper.query( SQL ); // 創建一個 List 對象,用來保存一批 Topic 對象 final List<Topic> topics = new ArrayList<>(); try { // 每循環一次,光標下移一行,如果該行有數據返回 true while( rs.next() ){ Topic t = new Topic(); // 創建對象 t.setId( rs.getInt( 1 ) ); // 將 結果集 中的 該行數據 封裝到 t 對象的 id 屬性中 t.setTitle( rs.getString( 2 ) ); t.setContent(rs.getString(3)); t.setPublishTime( rs.getTimestamp( 4 )); t.setPublishIp( rs.getString( 5 ) ); User u = new User(); // 創建 一個 User 對象 u.setId( rs.getInt( 6) ); // 將 t_topic 表中的 user_id 放入到 User 對象的 id 屬性中 t.setUser( u ); // 將 User 對象 設置到 Topic 對象上 /** 將 本次循環 創建的對象(已經封裝數據) 添加到 List 集合中 */ topics.add( t ); } } catch (SQLException e) { e.printStackTrace(); } JdbcHelper.release( rs ); // 關閉 結果集,釋放相關的資源 /**** 為每個問題尋找提問者 ***********************************/ //for( int i = 0 ; i < topics.size() ; i++ ){ for( int i = 0 , len = topics.size() ; i < len ; i++ ){ Topic t = topics.get( i ) ; // 獲得 題目 User u = t.getUser(); // 獲得當前題目的User對象 ( 該對象中只有 id 沒有其它數據 ) // 根據 用戶對象的 id 來查詢 用戶的信息 String querySQL = "SELECT id , username , password FROM t_user WHERE id = ? " ; ResultSet userRs = JdbcHelper.query( querySQL , u.getId() ); try { if( userRs.next() ) { // 如果查詢到用戶信息 // 注意,這里應該使用 userRs u.setUsername( userRs.getString( 2 ) ); // 將 username 列的值設置到 用戶對象的 username 屬性中 u.setPassword( userRs.getString( 3 )); // 將 password 列的值設置到 用戶對象的 password 屬性中 } } catch (SQLException e) { e.printStackTrace(); } JdbcHelper.release( userRs ); // 關閉 結果集,釋放相關的資源 } ServletContext application = request.getServletContext(); /** 將這些數據保存到 application **/ application.setAttribute( "topics" , topics ); System.out.println( "問題列表: " + topics ); // 去 list.html 頁面 response.sendRedirect( request.getContextPath() + "/list.html"); } } }
主頁列表顯示界面代碼:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>首頁</title> <link rel="stylesheet" href="$path/styles/general.css"> <link rel="stylesheet" href="$path/styles/cell.css"> <link rel="stylesheet" href="$path/styles/wen.css"> </head> <body> ## 登錄狀態欄 開始 <div class="login-status-container auto-height"> <span class="welcome cell-8"> ## 在 $ 之后 表達式之前使用 ! 表示 安靜模式 ( 靜默模式 ) <b>歡迎$!user.username來到愛問社區</b> </span> <span class="login-operation cell-4"> #if( $user ) <a href="$path/ask.html">提問</a> <em>|</em> <a href="$path/myQuestion.do">我的提問</a> <em>|</em> <a href="$path/logout.do">注銷</a> #else <a href="$path/login.html">登錄</a> <em>|</em> <a href="$path/regist.html">注冊</a> #end </span> </div> ## 登錄狀態欄 結束 ## 標志區域 <div class="brand-container auto-height"> <div class="cell-2"> <a href="$path"></a> </div> <div class="slogan cell-10"> <div> 愛問社區,這里可放logo </div> </div> </div> ## 列表區域 <div class="topic-list-container clear"> <!-- 問題列表的標題 --> <div class="topic-list-header row clear"> <span class="topic-item-index cell-1">序號</span> <span class="topic-item-title cell-5" >標題</span> <span class="topic-item-time cell-3">提問時間</span> <span class="topic-item-user cell-2">提問者</span> <span class="topic-item-operation cell-1"> #if( $user ) 解答問題 #end </span> </div> ## 問題列表開始 ## 每循環一次從 $topics 集合中取出一個 Topic 對象 放到 $topic 中 #foreach( $topic in $topics ) <div class="topic-item row clear odd"> <span class="topic-item-index cell-1">$topic.id</span> <span class="topic-item-title cell-5" > <a href="$path/detail.do?id=$topic.id">$topic.title</a> </span> <span class="topic-item-time cell-3"> $topic.publishTime </span> <span class="topic-item-user cell-2"> $topic.user.username</span> <span class="topic-item-operation cell-1"> #if( $user ) <a href="$path/answer.do?id=$topic.id">解答</a> #end </span> </div> #end ## 問題列表結束 </div>## 列表區域結束 <div class="line"></div> <div class="container link-container"> <a href="$path/ask.html" >發起新問題</a> | <a href="$path/index.html" >返回首頁</a> </div> <div class="container copyright-container"> © 2017 愛問社區版權所有 </div> </body> </html>
提問前臺界面代碼:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>提問</title> <link rel="stylesheet" href="$path/styles/general.css"> <link rel="stylesheet" href="$path/styles/cell.css"> <link rel="stylesheet" href="$path/styles/wen.css"> <link rel="stylesheet" href="$path/styles/btn.css"> <!-- 鏈接 simditor 的樣式庫 --> <link rel="stylesheet" href="$path/simditor/styles/simditor.css" type="text/css"> <!-- 導入 simditor 的 JavaScript 庫 --> <script type="text/javascript" src="$path/simditor/scripts/jquery.min.js"></script> <script type="text/javascript" src="$path/simditor/scripts/module.js"></script> <script type="text/javascript" src="$path/simditor/scripts/hotkeys.js"></script> <script type="text/javascript" src="$path/simditor/scripts/uploader.js"></script> <script type="text/javascript" src="$path/simditor/scripts/simditor.min.js"></script> </head> <body> ## 登錄狀態欄 開始 <div class="id="topnav" class="f_r"> <span class="welcome cell-8"> ## 在 $ 之后 表達式之前使用 ! 表示 安靜模式 ( 靜默模式 ) <b>歡迎$!user.username來到愛問社區</b> </span> <span class="login-operation cell-4"> #if( $user ) <a href="$path/ask.html">提問</a> <em>|</em> <a href="$path/myQuestion.do">我的提問</a> <em>|</em> <a href="$path/logout.do">注銷</a> #else <a href="$path/login.html">登錄</a> <em>|</em> <a href="$path/regist.html">注冊</a> #end </span> </div> ## 登錄狀態欄 結束 <div class="brand-container auto-height"> <div class="cell-2"> <a href="$path"></a> </div> <div class="slogan cell-10"> <div> 愛問社區,這里可以logo </div> </div> </div> <div class="container message-container"> <!-- 顯示提示信息的地方 --> #if( $askFail ) $askFail $scope.remove( $session , 'askFail' ) #end </div> #if( $user ) <!-- 提問表單 提交給 ask.do 對應的 Servlet 處理 --> <form action="$path/ask.do" method="post" > <!-- 提問區域 開始 --> <div class="container topic-ask-container clear shadow-outside auto-height" > <!-- 問題的標題 和 提問按鈕 --> <div class="container title-container"> <div class="cell-11"> <input type="text" name="title" placeholder="請輸入你要提問的問題的標題" class="u-ipt"> </div> <div class="cell-1"> <input type="submit" value="提問" class="u-btn u-btn-c4"> </div> </div> <div class="line"></div> <!-- 問題的內容 --> <div> <textarea name="content" id="contentEditor" ></textarea> <script type="text/javascript" > var editor = new Simditor( { textarea : $('#contentEditor'), placeholder : '請在這里輸入問題的內容...', toolbar : true } ); </script> </div> <div class="line"></div> <!-- 最底部的提問按鈕 --> <div class="container title-container"> <div class="cell-11" ></div> <div class="cell-1"> <input type="submit" value="提問" class="u-btn u-btn-c4"> </div> </div> </div> <!-- 提問區域 結束 --> </form> #else <div > 登錄以后才能發起提問,請<a href="$path/login.html" >登錄</a> </div> #end <div class="line"></div> <div class="container link-container"> <a href="$path/list.do" >問題列表</a> | <a href="$path/index.html" >返回首頁</a> </div> <div class="container copyright-container"> © 2017 愛問社區版權所有 </div> </body> </html>
回答Servlet處理代碼:
@WebServlet("/answer.do") public class AnswerServlet extends HttpServlet { private static final long serialVersionUID = 8578962149437664830L; @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 從 請求中獲得請求參數的值 String id = request.getParameter("id"); if (StringHelper.notEmpty(id)) { try { int topicId = Integer.parseInt(id); // 將字符串按照 十進制 解析問 int 類型數值 // 根據得到的 問題的 主鍵 查詢數據庫,得到 詳細信息 final String SQL = "SELECT id , title , content , publish_time , publish_ip , user_id FROM t_topic WHERE id = ? "; ResultSet rs = JdbcHelper.query(SQL, topicId); Topic t = null; int userId = -1; if (rs.next()) { // 當 根據 問題的主鍵 獲取到 問題信息時 t = new Topic(); // 創建 Topic 對象 t.setId(rs.getInt(1)); // 將 結果集 中的 該行數據 封裝到 t 對象的 id 屬性中 t.setTitle(rs.getString(2)); t.setContent(rs.getString(3)); t.setPublishTime(rs.getTimestamp(4)); t.setPublishIp(rs.getString(5)); userId = rs.getInt(6); } JdbcHelper.release(rs); // 關閉結果集 // 獲得提問者 final String getUserSQL = "SELECT id , username , password FROM t_user WHERE id = ? "; rs = JdbcHelper.query(getUserSQL, userId); if (userId != -1 && rs.next()) { User u = new User(); // 封裝數據 u.setId(rs.getInt(1)); u.setUsername(rs.getString(2)); u.setPassword(rs.getString(3)); // 將獲取到的用戶數據設置到 Topic 對象的 user 屬性中 t.setUser(u); } HttpSession session = request.getSession(); session.setAttribute("topic", t); response.sendRedirect(request.getContextPath() + "/answer.html"); return; // 讓方法立即結束 } catch (NumberFormatException e) { e.printStackTrace(); // response.sendRedirect( request.getContextPath() + "/list.do" ); } catch (SQLException e) { e.printStackTrace(); // response.sendRedirect( request.getContextPath() + "/list.do" ); } } else { // response.sendRedirect( request.getContextPath() + "/list.do" ); } response.sendRedirect(request.getContextPath() + "/list.do"); } }
回答前臺代碼:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>解答: $topic.title</title> <link rel="stylesheet" href="$path/styles/general.css"> <link rel="stylesheet" href="$path/styles/cell.css"> <link rel="stylesheet" href="$path/styles/wen.css"> <!-- 鏈接 simditor 的樣式庫 --> <link rel="stylesheet" href="$path/simditor/styles/simditor.css" type="text/css"> <!-- 導入 simditor 的 JavaScript 庫 --> <script type="text/javascript" src="$path/simditor/scripts/jquery.min.js"></script> <script type="text/javascript" src="$path/simditor/scripts/module.js"></script> <script type="text/javascript" src="$path/simditor/scripts/hotkeys.js"></script> <script type="text/javascript" src="$path/simditor/scripts/uploader.js"></script> <script type="text/javascript" src="$path/simditor/scripts/simditor.min.js"></script> </head> <body> ## 登錄狀態欄 開始 <div class="login-status-container auto-height"> <span class="welcome cell-8"> ## 在 $ 之后 表達式之前使用 ! 表示 安靜模式 ( 靜默模式 ) <b>歡迎$!user.username來到愛問社區</b> </span> <span class="login-operation cell-4"> #if( $user ) <a href="$path/ask.html">提問</a> <em>|</em> <a href="">我的提問</a> <em>|</em> <a href="$path/logout.do">注銷</a> #else <a href="$path/login.html">登錄</a> <em>|</em> <a href="$path/regist.html">注冊</a> #end </span> </div> ## 登錄狀態欄 結束 ## 標志區域 <div class="brand-container auto-height"> <div class="logo cell-2"> <a href="$path"></a> </div> <div class="slogan cell-10"> <div> 解答問題 </div> </div> </div> <div> <h4>$topic.title</h4> <div class="line"></div> <div> $topic.content </div> <div> 提問時間: $topic.publishTime / 提問者: $topic.user.username </div> </div> <!-- 解答的內容 --> <form action="$path/explain.do" method="post" > <input type="hidden" name="id" value="$topic.id" > <div> <textarea name="content" id="contentEditor" ></textarea> <script type="text/javascript" > var editor = new Simditor( { textarea : $('#contentEditor'), placeholder : '請在這里輸入問題的內容...', toolbar : true } ); </script> </div> <input type="submit" value="提交解答"> </form> $scope.remove( $session , 'topic' ); <div class="line"></div> <div class="container link-container"> <a href="$path/ask.html" >發起新問題</a> | <a href="$path/index.html" >返回首頁</a> </div> <div class="container copyright-container"> © 2017 愛問社區版權所有 </div> </body> </html>
以下是使用simditor的方法,需要引入simditor中的css和js樣式。simditor下載地址
<textarea name="content" id="contentEditor" ></textarea> <script type="text/javascript" > var editor = new Simditor( { textarea : $('#contentEditor'), placeholder : '請在這里輸入問題的內容...', toolbar : true } ); </script>
解答問題Servlet處理,這里需要獲取提問者,提問問題以及該問題的已有答案,已有答案回答者。
@WebServlet("/detail.do") public class DetailServlet extends HttpServlet { private static final long serialVersionUID = -3202278077673657729L; @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 從 請求中獲得請求參數的值 String id = request.getParameter("id"); if (StringHelper.notEmpty(id)) { try { int topicId = Integer.parseInt(id); // 將字符串按照 十進制 解析問 int 類型數值 // 根據得到的 問題的 主鍵 查詢數據庫,得到 詳細信息 final String SQL = "SELECT id , title , content , publish_time , publish_ip , user_id FROM t_topic WHERE id = ? "; ResultSet rs = JdbcHelper.query(SQL, topicId); Topic t = null; /*int userId = -1;*/ if (rs.next()) { // 當 根據 問題的主鍵 獲取到 問題信息時 t = new Topic(); // 創建 Topic 對象 t.setId(rs.getInt(1)); // 將 結果集 中的 該行數據 封裝到 t 對象的 id 屬性中 t.setTitle(rs.getString(2)); t.setContent(rs.getString(3)); t.setPublishTime(rs.getTimestamp(4)); t.setPublishIp(rs.getString(5)); User user = new User(); user.setId(rs.getInt(6)); t.setUser(user); } JdbcHelper.release(rs); // 關閉結果集 // 獲得提問者 final String getUserSQL = "SELECT id , username , password FROM t_user WHERE id = ? "; rs = JdbcHelper.query(getUserSQL, t.getUser().getId()); if(rs.next()) { User u = new User(); // 封裝數據 u.setId(rs.getInt(1)); u.setUsername(rs.getString(2)); u.setPassword(rs.getString(3)); // 將獲取到的用戶數據設置到 Topic 對象的 user 屬性中 t.setUser(u); System.out.println("message username:" + rs.getString(2)); } JdbcHelper.release(rs); // 關閉結果集 // 獲得當前的問題的所有解答 String explainSQL = "SELECT id , content , explain_time , explain_ip , user_id from t_explain where topic_id = ? "; rs = JdbcHelper.query(explainSQL, topicId); @SuppressWarnings("unused") int explainerId = -1; List<Explain> explains = new ArrayList<>(); while (rs.next()) { Explain e = new Explain(); e.setId(rs.getInt(1)); e.setContent(rs.getString(2)); e.setExplainTime(rs.getTimestamp(3)); e.setExplainIp(rs.getString(4)); User user=new User(); user.setId(rs.getInt(5)); e.setUser(user); explains.add(e); System.out.println("explain userID:" + rs.getInt(5)); } // 獲得解答者 List<Explain>explainList = new ArrayList(); for(int i=0;i<explains.size();i++) { Explain explain1 = explains.get(i); final String getExplainerSQL = "SELECT id , username , password FROM t_user WHERE id = ? "; rs = JdbcHelper.query(getExplainerSQL, explain1.getUser().getId()); if (rs.next()) { User u = new User(); // 封裝數據 u.setId(rs.getInt(1)); u.setUsername(rs.getString(2)); u.setPassword(rs.getString(3)); // 將獲取到的用戶數據設置到 Topic 對象的 user 屬性中 explain1.setUser(u); explainList.add(explain1); System.out.println("explain username:" + rs.getString(2)); } JdbcHelper.release(rs); // 關閉結果集 /*t.setExplains(explains); // 將解答設置到 Topic 對象上 */ } t.setExplains(explainList); /*** 為 所有的解答,獲取解答者的詳細信息 ***/ HttpSession session = request.getSession(); session.setAttribute("topic", t); response.sendRedirect( request.getContextPath() + "/detail.html" ); return; // 讓方法立即結束 } catch (NumberFormatException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } else { } response.sendRedirect(request.getContextPath() + "/list.do"); } }
解答問題前臺顯示界面代碼;
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>$topic.title</title> <link rel="shortcut icon" href="$path/images/icon.png" type="image/png"> <link rel="stylesheet" href="$path/styles/general.css"> <link rel="stylesheet" href="$path/styles/cell.css"> <link rel="stylesheet" href="$path/styles/wen.css"> </head> <body> ## 登錄狀態欄 開始 <div class="login-status-container auto-height"> <span class="welcome cell-8"> ## 在 $ 之后 表達式之前使用 ! 表示 安靜模式 ( 靜默模式 ) <b>歡迎$!user.username來到問道</b> </span> <span class="login-operation cell-4"> #if( $user ) <a href="$path/ask.html">提問</a> <em>|</em> <a href="">我的提問</a> <em>|</em> <a href="$path/logout.do">注銷</a> #else <a href="$path/login.html">登錄</a> <em>|</em> <a href="$path/regist.html">注冊</a> #end </span> </div> ## 登錄狀態欄 結束 ## 標志區域 <div class="brand-container auto-height"> <div class="logo cell-2"> <a href="$path"></a> </div> <div class="slogan cell-10"> <div> </div> </div> </div> <div> <h4>$topic.title</h4> <div class="line"></div> <div> $topic.content </div> <div> 提問時間: $topic.publishTime / 提問者: $topic.user.username </div> </div> <div> #foreach( $ex in $topic.explains) <div> $ex.content </div> <div class="line"></div> #end </div> $scope.remove( $session , 'topic' ); <div class="line"></div> <div class="container link-container"> <a href="$path/ask.html" >發起新問題</a> | <a href="$path/index.html" >返回首頁</a> </div> <div class="container copyright-container"> © 2017 愛問社區版權所有 </div> </body> </html>
我的解答Servlet處理代碼:
@WebServlet("/myAnswer.do") public class MyAnswerServlet extends HttpServlet { private static final long serialVersionUID = -3020889403557912216L; @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); User user = (User) session.getAttribute( "user" ); // 在登錄時將 User 對象放入了 會話 中 Explain ex=null; final List<Explain> exp = new ArrayList<>(); if( user != null ) { int myid=user.getId(); final String SQL = "SELECT id ,content ,explain_time , explain_ip , user_id ,topic_id FROM t_explain WHERE user_id = ? "; ResultSet rs = JdbcHelper.query(SQL, myid); //Topic t=null; //final List<Explain> explains = new ArrayList<>(); @SuppressWarnings("unused") int topicId=-1; try { while( rs.next() ) { ex=new Explain(); ex.setId(rs.getInt(1)); ex.setContent(rs.getString(2)); ex.setExplainTime(rs.getTimestamp( 3 )); ex.setExplainIp(rs.getString(4)); ex.setUser(user); Topic to=new Topic(); to.setId(rs.getInt(6)); ex.setTopic(to); topicId=rs.getInt(6); exp.add(ex); } JdbcHelper.release(rs); // 關閉結果集 for(int i = 0 , len = exp.size() ; i < len ; i++) { Explain explain=exp.get(i); Topic tid=explain.getTopic(); final String tSQL = "SELECT id , title , content , publish_time , publish_ip , user_id FROM t_topic WHERE id = ? "; ResultSet trs = JdbcHelper.query(tSQL, tid.getId()); while(trs.next()) { Topic t=new Topic(); t.setId(1); t.setTitle(trs.getString(2)); t.setContent(trs.getString(3)); t.setPublishTime(trs.getTimestamp(4)); t.setPublishIp(trs.getString(5)); ex.setTopic(t); // explains.add(ex); System.out.println( "我的tid: " + tid.getId()); } JdbcHelper.release(trs); // 關閉結果集 } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } session.setAttribute("explains", exp); System.out.println( "我的解答列表: " + exp ); System.out.println( "我的id: " + myid); response.sendRedirect( request.getContextPath() + "/myAnswer.html"); } } }
我的解答前臺展示頁面代碼:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>解答</title> <link rel="stylesheet" href="$path/styles/top.css"> </head> <body> <div > <nav id="topnav" class="f_r"> <ul> <a href="$path/index.html"">首頁</a> <a href="$path/myQuestion.do" >我的提問</a> <a href="$path/ask.html" >提問</a> <a href="$path/logout.do">注銷</a> </ul> </nav> </div> #if( $user ) $user.username的所有回答: #end #foreach( $ex in $explains) <div class="blogs"> <ul> <p>$ex.content</p> <div class="content_time"> <p> 解答時間:<span class="dtime f_l"> $ex.explainTime</span></p> </div> <div class="line"></div> </ul> </div> #end </body> </html>
我的提問Servlet處理:
@WebServlet("/myQuestion.do") public class MyQuestionServlet extends HttpServlet { private static final long serialVersionUID = -4110483126223561394L; @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); User user = (User) session.getAttribute( "user" ); // 在登錄時將 User 對象放入了 會話 中 if( user != null ) { int myid=user.getId(); final String SQL = "SELECT id , title , content, publish_time , publish_ip FROM t_topic WHERE user_id = ? "; ResultSet rs = JdbcHelper.query(SQL, myid); final List<Topic> qtopics = new ArrayList<>(); try { while( rs.next() ){ Topic t=new Topic(); t.setId(rs.getInt(1)); t.setTitle(rs.getString(2)); t.setContent(rs.getString(3)); t.setPublishTime(rs.getTimestamp(4)); t.setPublishIp(rs.getString(5)); qtopics.add(t); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } session.setAttribute("qtopics", qtopics); System.out.println( "我的提問列表: " + qtopics ); System.out.println( "我的id: " + myid); response.sendRedirect( request.getContextPath() + "/myQuestion.html"); } } }
我的提問展示代碼:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>$user.username的提問 </title> <link rel="stylesheet" href="$path/styles/general.css"> <link rel="stylesheet" href="$path/styles/cell.css"> <link rel="stylesheet" href="$path/styles/wen.css"> <link rel="stylesheet" href="$path/styles/top.css"> </head> <body> <div > <ul> #if($user) <nav id="topnav" class="f_r"> <ul> <a href="$path/index.html">首頁</a> <a href="$path/myAnswer.do" >我的解答</a> <a href="$path/ask.html">提問</a> <a href="$path/logout.do" >注銷</a> </ul> </nav> #else <li class="presentation"><a href="$path/login.html" id="link" title="提問">登錄</a></li> <li class="presentation"><a href="$path/regist.do" id="tools" title="exit">注冊</a></li> #end </ul> </div> #if( $user ) $user.username的所有提問: #end #foreach( $qto in $qtopics) <div class="blogs"> <ul> <p>$qto.content</p> <p class="autor"><span class="lm f_l"><a>提問者:$user.username</a></span> <span class="dtime f_l">$qto.publishTime</span></p> </ul> </div> #end </body> </html>
驗證碼處理的Servlet代碼:
@WebServlet(urlPatterns= { "/verify/login.do" , "/verify/regist.do" } ) public class VerifyCodeServlet extends HttpServlet { private static final long serialVersionUID = 3398560501558431737L; @Override protected void service( HttpServletRequest request , HttpServletResponse response ) throws ServletException, IOException { // 獲得 當前請求 對應的 會話對象 HttpSession session = request.getSession(); // 從請求中獲得 URI ( 統一資源標識符 ) String uri = request.getRequestURI(); System.out.println( "hello : " + uri ); final int width = 180 ; // 圖片寬度 final int height = 40 ; // 圖片高度 final String imgType = "jpeg" ; // 指定圖片格式 (不是指MIME類型) final OutputStream output = response.getOutputStream(); // 獲得可以向客戶端返回圖片的輸出流 (字節流) // 創建驗證碼圖片并返回圖片上的字符串 String code = GraphicHelper.create( width, height, imgType, output ); System.out.println( "驗證碼內容: " + code ); // 建立 uri 和 相應的 驗證碼 的關聯 ( 存儲到當前會話對象的屬性中 ) session.setAttribute( uri , code ); System.out.println( session.getAttribute( uri ) ); } }
注冊前臺界面,有驗證碼驗證功能:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>注冊愛問社區</title> <link rel="stylesheet" href="$path/styles/general.css"> <link rel="stylesheet" href="$path/styles/cell.css"> <link rel="stylesheet" href="$path/styles/form.css"> <link rel="stylesheet" href="$path/awesome/css/font-awesome.min.css"> <script type="text/javascript" src="$path/js/wen.js"></script> <style type="text/css" > .logo-container { margin-top: 50px ; } .logo-container img { width: 100px ; } .message-container { height: 80px ; } .link-container { height: 40px ; line-height: 40px ; } .link-container a { text-decoration: none ; } </style> </head> <body> <div class="container title-container" >加入愛問社區,為您答疑解惑</div> <div class="container form-container"> <form action="$path/regist.do" method="post"> <div class="form"> <!-- 注冊表單開始 --> <div class="form-row"> <span class="cell-1"> <i class="fa fa-user"></i> </span> <span class="cell-11" > <input type="text" name="username" placeholder="請輸入用戶名"> </span> </div> <div class="form-row"> <span class="cell-1"> <i class="fa fa-key"></i> </span> <span class="cell-11" > <input type="password" name="password" placeholder="請輸入密碼"> </span> </div> <div class="form-row"> <span class="cell-1"> <i class="fa fa-keyboard-o"></i> </span> <span class="cell-11" > <input type="password" name="confirm" placeholder="請確認密碼"> </span> </div> <div class="form-row"> <span class="cell-7"> <input type="text" name="verifyCode" placeholder="請輸入驗證碼"> </span> <span class="cell-5" > <img src="$path/verify/regist.do" onclick="myRefersh(this)"> </span> </div> <div class="form-row" > <span class="cell-6" > <input type="reset" value="重置"> </span> <span class="cell-6" > <input type="submit" value="注冊"> </span> </div> </div> <!-- 注冊表單結束 --> </form> </div> <div class="container message-container"> <!-- 顯示提示信息的地方 --> #if( $registFail ) $registFail $scope.remove( $session , 'registFail' ) #end </div> <div class="container link-container"> <a href="$path/login.html" > 已注冊愛問帳號,點擊這里登錄</a> | <a href="$path/index.html" >返回首頁</a> </div> <div class="container copyright-container"> © 2017 愛問社區版權所有 </div> </body> </html>
Servlet處理注冊,實現驗證碼驗證:
@WebServlet("/regist.do") public class RegistServlet extends HttpServlet { private static final long serialVersionUID = 7493633832455111617L; @Override protected void service( HttpServletRequest request , HttpServletResponse response ) throws ServletException, IOException { // 獲得來自 頁面 表單上的數據 String verifyCode = request.getParameter( "verifyCode" ) ; // 獲得由用戶輸入的那個驗證碼 String username = request.getParameter( "username" ) ; String password = request.getParameter( "password" ) ; String confirm = request.getParameter( "confirm" ) ; System.out.println( "username : " + username ); System.out.println( "password : " + password ); System.out.println( "confirm : " + confirm ); System.out.println( "verifyCode : " + verifyCode ); HttpSession session = request.getSession(); // 獲得 在 會話 中存儲的那個 為登錄進行驗證的 驗證碼 final String code = (String)session.getAttribute( "/wendao/verify/regist.do" ); System.out.println( "session code : " + code ); // 比較驗證碼 if( StringHelper.equals( verifyCode , code ) ){ // 要保證 用戶名 不為空 、密碼不能為空 、兩次輸入的密碼必須一致 if( StringHelper.notEmpty( username ) && StringHelper.notEmpty( password ) && StringHelper.equals( password , confirm) ) { // 可以保存了 String SQL = "INSERT INTO t_user ( username , password ) VALUES ( ? , ? ) " ; int n = JdbcHelper.insert( SQL , false , username , StringHelper.MD5(password)); if( n > 0 ) { // 如果 insert 返回 大于 0 的數字 , 則表示 插入成功 // 保存成功以后,應該去一個新的頁面 ( 比如去 登錄頁面 ) response.sendRedirect( request.getContextPath() + "/login.html" ); } else { // 回到注冊頁面去 session.setAttribute( "registFail" , "注冊失敗,可能是用戶名被占用了" ); response.sendRedirect( request.getContextPath() + "/regist.html" ); } } else { // 回到注冊頁面去 session.setAttribute( "registFail" , "用戶名或密碼為空,或者密碼不一致" ); response.sendRedirect( request.getContextPath() + "/regist.html" ); } } else { // 如果驗證碼不一致,設置提示信息后回到注冊頁面去 session.setAttribute( "registFail" , "驗證碼輸入錯誤,請重新輸入" ); response.sendRedirect( request.getContextPath() + "/regist.html" ); } } }
登錄Servlet處理代碼:
@WebServlet("/login.do") public class LoginServlet extends HttpServlet { private static final long serialVersionUID = 18854422651747352L; @Override protected void service( HttpServletRequest request , HttpServletResponse response ) throws ServletException, IOException { // 獲得來自 頁面 表單上的數據 String username = request.getParameter( "username" ) ; String password = StringHelper.MD5(request.getParameter( "password" )) ; System.out.println( "username : " + username ); System.out.println( "password : " + password ); HttpSession session = request.getSession(); // 登錄 : 根據 用戶名 和 密碼 從數據庫中查詢數據,如果都正確,就將這些數據放入到會話中,最后進入到指定頁面( list.html ) String SQL = "SELECT id , username , password FROM t_user WHERE username = ? and password = ? " ; ResultSet rs = JdbcHelper.query( SQL, username , password ) ; try{ // 如果查詢到數據,就包裝到一個對象中 if( rs.next() ) { User user = new User(); // 創建對象 // 封裝數據 user.setId( rs.getInt( 1 ) ); user.setUsername( rs.getString( 2 )); user.setPassword( rs.getString( 3 ) ) ; //System.out.println("測試"+MD5.convertMD5(MD5.convertMD5(password))); /** 將 User 對象 放入到 會話中 **/ session.setAttribute( "user" , user ); // 重定向到 list.do ( list.do 會先查詢數據后 再 重定向到 list.html ) response.sendRedirect( request.getContextPath() + "/list.do" ); } else { // 如果 用戶名 或 密碼 錯誤,重新返回到 登錄頁面 session.setAttribute( "loginFail" , "用戶名或密碼錯誤" ); response.sendRedirect( request.getContextPath() + "/login.html" ); } } catch ( SQLException e ){ e.printStackTrace(); } } }
登錄前臺展示界面代碼;
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>登錄</title> <link rel="stylesheet" href="styles/general.css"> <link rel="stylesheet" href="styles/cell.css"> <link rel="stylesheet" href="styles/form.css"> <link rel="stylesheet" href="awesome/css/font-awesome.min.css"> <link rel="stylesheet" type="text/css" href="css/login.css"> <script type="text/javascript" src="js/wen.js"></script> </head> <body> <div class="logina-logo" > <div id="venusLogo"><p><span>愛問社區</span></p></div> </div> <div class="logina-main main clearfix"> <div class="tab-con"> <form action="$path/login.do" method="post"> <div id='login-error' class="error-tip"></div> <table border="0" cellspacing="0" cellpadding="0"> <tbody> <tr> <th>賬戶</th> <td width="245"> <input type="text" name="username" id="username" placeholder="昵稱" /> <td> </td> </tr> <tr> <th>密碼</th> <td width="245"> <input type="password" name="password" id="password" placeholder="密碼" /> </td> <td> </td> </tr> <tr> <th></th> <td width="245"><input class="confirm" type="submit" value="登 錄"></td> <td></td> </tr> </tbody> </table> </form> </div> <div class="reg"> <p>還沒有賬號?<br>趕快免費注冊一個吧!</p> <a class="reg-btn" href="regist.html">立即免費注冊</a> </div> </div> <div id="footer"> <div class="copyright">Copyright © 愛問社區 版權所有</div> </div> </body> </html>
好啦,基本的代碼就展示完了,還有比較通用的POJO類和jdbc連接數據庫的類就不做展示了,貼上數據庫SQL代碼,需要的可以根據字段來寫
DROP TABLE IF EXISTS `t_explain`; CREATE TABLE `t_explain` ( `id` int(11) NOT NULL AUTO_INCREMENT, `content` text, `explain_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, `explain_ip` varchar(50) DEFAULT NULL, `user_id` int(8) DEFAULT NULL, `topic_id` int(8) DEFAULT NULL, PRIMARY KEY (`id`), KEY `ex_id` (`user_id`), KEY `t_id` (`topic_id`), CONSTRAINT `ex_id` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`), CONSTRAINT `t_id` FOREIGN KEY (`topic_id`) REFERENCES `t_topic` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for t_topic -- ---------------------------- DROP TABLE IF EXISTS `t_topic`; CREATE TABLE `t_topic` ( `id` int(10) NOT NULL AUTO_INCREMENT, `title` varchar(255) DEFAULT NULL, `content` text, `publish_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `publish_ip` varchar(100) DEFAULT NULL, `user_id` int(10) DEFAULT NULL, PRIMARY KEY (`id`), KEY `cid` (`user_id`), CONSTRAINT `cid` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for t_user -- ---------------------------- DROP TABLE IF EXISTS `t_user`; CREATE TABLE `t_user` ( `id` int(10) NOT NULL AUTO_INCREMENT, `username` varchar(20) NOT NULL, `password` varchar(255) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8;
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。