项目技术:Jsp+javascript+html
准备工作
创建数据库:BBS_database.
表的创建
1.编辑字段:1.id(帖子及回复编号,设主键) 2.pid (当前帖子的父id,即被回复的帖子的id,原创则设为0)3.rootid (即原创的帖子id) 4.title (帖子的标题) 5.cont (帖子的内容) 6.pdate (帖子提交的时间) 7.isleaf (是否是叶子节点,是为0,不是为1)
2.构建假数据。
1.新建1个web project
1)新建一个JSP页面(ShowArticleTree.jsp),利用递归实现文件树的呈现,列出已有的帖子的id及标题。
1.连接数据库
导入需要的jar包
代码实现部分:
Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost/bbs?user=root&password=123456"; Connection conn = DriverManager.getConnection(url);
使用递归算法遍历原创的回复帖子。
代码实现部分:
<%!
String str = ""; //用来存储数据。
private void tree(Connection conn, int id, int level) {
try { stmt = conn.createStatement(); rs = stmt.executeQuery(sql);
while (rs.next()) {
str += “此部分为html标签及要显示的数据”;
if (rs.getInt("isleaf") != 0) { //判断该帖子是否为叶子节点 tree(conn, rs.getInt("id"), level+1); }
}
}
过程中遇到的问题
*浏览器运行该页面时,刷新页面时,str里装的内容会重复显示。
解决方法
在str里的内容显示之后,把str置空。
知识原理:
服务器启动后只会产生一个servlet实例
2)新建一个JSP文件(ShowArticleDetail.jsp),用于点击标题的链接时显示详细内容
利用递归算法遍历回复的帖子,代码参考ShowArticleTree.jsp文件
利用链接传值
例:<a href="Reply.jsp?id=<%= rs.getInt("id")%>&rootid=<%= rs.getInt("rootid") %>">回复</a>
3)新建一个JSP文件(Reply.jsp),用于在网页输入评论并提交。
在页面显示一个文本框及一个文本编辑区域。
内容提交到ReplyOK.jsp。
4)新建一个JSP文件(ReplyOK.jsp),用于接收回复帖子以及存入数据库
接收数据格式:String title = request.getParameter("title"); //该方法返回数据类型为Sring,若需int类型则需要强制转换。
文本输入换行问题:cont = cont.replaceAll("\n", "<br>");
提交内容含中文乱码问题:request.setCharacterEncoding("gbk");
使用PreparedStatement批量执行语句
例子:String sql = "insert into article value(null,?,?,?,?,now(),0)"; PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1,id); pstmt.setInt(2,rootId); pstmt.setString(3,title); pstmt.setString(4,cont); pstmt.executeUpdate();
pstmt.close();
更新父帖的isleaf字段。
更新数据时应放在一个transaction(事务,事务是恢复和并发控制的基本单位)里,代码实现:
conn.setAutoCommit(false);
·····
conn.commit(); conn.setAutoCommit(true); //恢复现场
5)新建一个JSP文件(Delete.jsp),用于删除帖子。
连接数据库。
使用递归算法删除子帖,并判断要删除的帖子父帖有无子帖,若无,则更新父帖的isleaf字段。
判断父帖有无子帖方法:
Statement stmt = conn.createStatement(); ResultSet rs =
stmt.executeQuery("select count(*) from article where pid = " + pid); rs.next(); int count = rs.getInt(1);
rs.close();
if (count <= 0) { Statement stmtUpdate = conn.createStatement(); stmtUpdate.executeUpdate("update article set isleaf = 0 where id = " + pid); stmtUpdate.close(); }
6) 新建一个Jsp文件(Post.jsp),用于发新帖子
连接数据库。
本文件将数据提交自身处理方法:
<form name="post" action="Post.jsp" method="post"> <input type="hidden" name="action" value="post"> //设置隐藏提交,在文件开始验证是否是本身文件提交数据
</form>
文件开始验证代码:
String action = request.getParameter("action"); //接受form提交的信息
if (action != null && action.equals("post")) {
·······
}
怎样确定帖子rootid(由于rootid即帖子本身id,帖子id由数据库本身自增控制,在帖子插入前 无法得到本身id)方法如下:
执行sql语句时:
String sql = "insert into article value(null,0,?,?,?,now(),0)";
PreparedStatement pstmt =
conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
先设置rootid为
pstmt.setInt(1,-1);
得到新生成的id
ResultSet rsKey = pstmt.getGeneratedKeys(); rsKey.next(); int Key = rsKey.getInt(1); rsKey.close();
然后更改帖子的rootid就可以了。
7) 新建一个jsp文件(Login.jsp),用于后台管理员登录页面。
8) 新建一个jsp文件(ShowArticleFlat.jsp),用于普通用户访问界面(只提供登录,浏览,发帖,回复功能,实现分页技术)
实现分页步骤:
1.确定1页显示数据量pageSize;
2.确定数据总量totalRecords:
ResultSet rsCount = stmtCount.executeQuery("select count(*) from article where pid = 0"); rsCount.next(); int totalRecords = rsCount.getInt(1);
3.确定页数:
int totalPages = totalRecords % pageSize == 0 ? totalRecords / pageSize : totalRecords / pageSize + 1;
4.确定数据起始位置:
int startPos = (pageNo - 1) * pageSize;
5.sql语言分页:
select * from article where pid = 0 order by pdate desc limit startPos ,pageSize
6.分别使用下拉列表,输入目标页数和连接实现翻页查看
下拉列表实现代码:
<form name="form1" action="ShowArticleFlat.jsp"> <select name="pageNo" οnchange="document.form1.submit()"> <% for(int i=1; i<=totalPages; i++) { %> <option value=<%= i%> <%= (i == pageNo) ? "selected" : "" %>>第<%=i%>页</option> <% } %> </select> </form>
目标定向翻页实现代码:
<form name="form2" action="ShowArticleFlat.jsp"> <input type="text" size="4" name="pageNo" value=<%= pageNo %> /> <input type="submit" value="go"/> </form>
超链接实现代码:
<a href="ShowArticleFlat.jsp?pageNo=1">首页</a> <a href="ShowArticleFlat.jsp?pageNo=<%= pageNo - 1%>">上一页</a> <a href="ShowArticleFlat.jsp?pageNo=<%= pageNo + 1%>">下一页</a> <a href="ShowArticleFlat.jsp?pageNo=<%= totalPages%>">末页</a>
解决关于通过地址访问修改数据方法:
通过session存放数据用于验证是否正常访问。
例: session.setAttribute("admin","true");
在需要控制的页面上添加如下代码:
String admin = (String) session.getAttribute("admin"); //out.println(admin); if (admin != null && admin.equals("true")){ login = true; } else { out.println("当前网页不可访问,请登录之后再做操作"); return;
}
注:return作用:停止页面进行下去。
关于校验提交内容是否为空实现代码
<script language="javascript"> <!-- //javascript去除空格函数 function LTrim(str) { //去除字符串的 头空格 var i; for(i=0; i<str.length; i++){ if(str.charAt(i) != " ") break; } str = str.substring(i,str.length); return str; } function RTrim(str) { var i; for(i=str.length-1; i>=0; i--){ if(str.charAt(i) != " " && str.charAt(i) != " "){ break; } } str = str.substring(0,i+1); return str; } function Trim(str){ return LTrim(RTrim(str)); } function check() { if(Trim(document.post.title.value) == "") { alert("请输入标题"); document.post.title.focus(); return false; } if(Trim(document.post.cont.value) == "") { alert("请输入内容"); document.post.cont.focus(); return false; } return true; } --> </script>
<form name="post" action="Post.jsp" method="post" οnsubmit="return check()">
········
</form>