基于Servlet实现技术问答网站系统
这一篇博客将详细介绍一个基于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" style="text-align: left ;">标题</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" style="text-align: left ;"> <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" style="height: 1px ;"></div> <div class="cell-1"> <input type="submit" value="提问" class="u-btn u-btn-c4"> </div> </div> </div> <!-- 提问区域 结束 --> </form> #else <div style="text-align:center ; min-height: 400px ; line-height: 400px ;"> 登录以后才能发起提问,请<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> <h3>$topic.title</h3> <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> <h3>$topic.title</h3> <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 style="margin-left:320px;"> <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 style="margin-left:320px;"> <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" style="color:blue; margin-top:60px;">加入爱问社区,为您答疑解惑</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" style="text-align: left;"> <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" style="text-align: left;"> <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" style="text-align: left;"> <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" style="text-align: center;"> <img src="$path/verify/regist.do" onclick="myrefersh(this)"> </span> </div> <div class="form-row" style="border: none;"> <span class="cell-6" style="text-align: left"> <input type="reset" value="重置"> </span> <span class="cell-6" style="text-align:right;"> <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" style="height: 55px"> <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;
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: Mysql字符串字段判断是否包含某个字符串的2种方法
下一篇: java初学者必须理解这几个问题
推荐阅读
-
基于Servlet实现技术问答网站系统
-
[ZT]基于LVS的Linux负载均衡技术实现 博客分类: 系统 LinuxPHPBBS.netBlog
-
[ZT]基于LVS的Linux负载均衡技术实现 博客分类: 系统 LinuxPHPBBS.netBlog
-
基于jsp+servlet实现的简单博客系统实例(附源码)
-
基于jsp+servlet实现的简单博客系统实例(附源码)
-
基于JSP和Servlet技术实现的Java Web的注册和登录的功能
-
ssm弹幕视频网站系统:使用SSM/springboot框架实现,前段技术使用html+js+css+layui+jsp实现,数据库采用mysql,实现了前后端分离视频管理网站