项目技术: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" onchange="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" onsubmit="return check()">
・・・・・・・・
</form>