在線小說站點的設計與實現(附源代碼)
阿新 • • 發佈:2018-03-21
bold nsf 子節點 water page exists 匹配 AD tst
項目的大致結構如圖:
小說展示,管理。添加,刪除,更新的代碼處理:
小說評論展示,管理,添加,刪除,更新的代碼處理:
小說分類展示。更新。添加,刪除的代碼處理:
前臺主要頁面展示:(略醜)
小說公布的實現細節,引入了wangEditor:
近期在做一個課程設計。在線小說站點的設計,下面是課題要求。須要項目練手的童鞋能夠試試身手。
因為近期新學了JavaEE,所以採用了jsp+servlet來寫,前端部分用了少量的js和jQuery處理。數據庫用了MySQL。開發平臺是myeclipse。
公布文章時直接插入數據庫會沒有分段。這裏的解決的方法是引入第三方工具wangEditor(wangEditor 是一款基於javascript和css開發的html富文本編輯器,開源免費。產品第一版公布於2014年11月。關於該編輯器:http://www.kancloud.cn/wangfupeng/wangeditor2/113961)
首先數據庫的設計結構:
/* Navicat MySQL Data Transfer Source Server : blog Source Server Version : 50528 Source Host : localhost:3306 Source Database : novel Target Server Type : MYSQL Target Server Version : 50528 File Encoding : 65001 Date: 2016-12-31 16:04:07 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for admin -- ---------------------------- DROP TABLE IF EXISTS `admin`; CREATE TABLE `admin` ( `id` int(11) NOT NULL AUTO_INCREMENT, `adminName` varchar(255) NOT NULL, `adminPassword` varchar(255) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for author -- ---------------------------- DROP TABLE IF EXISTS `author`; CREATE TABLE `author` ( `id` int(11) NOT NULL AUTO_INCREMENT, `authorName` varchar(255) NOT NULL, `authorPassword` varchar(255) NOT NULL, `authorEmail` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for comment -- ---------------------------- DROP TABLE IF EXISTS `comment`; CREATE TABLE `comment` ( `id` int(11) NOT NULL AUTO_INCREMENT, `context` text, `createdTime` datetime DEFAULT NULL, `readerName` varchar(255) DEFAULT NULL, `novelId` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=67 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for genre -- ---------------------------- DROP TABLE IF EXISTS `genre`; CREATE TABLE `genre` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `sort` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for novel -- ---------------------------- DROP TABLE IF EXISTS `novel`; CREATE TABLE `novel` ( `id` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(255) NOT NULL, `context` text NOT NULL, `createdTime` datetime DEFAULT NULL, `genreId` int(11) DEFAULT NULL, `voteNumber` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=160 DEFAULT CHARSET=utf8; -- ---------------------------- -- Table structure for reader -- ---------------------------- DROP TABLE IF EXISTS `reader`; CREATE TABLE `reader` ( `id` int(11) NOT NULL AUTO_INCREMENT, `readerName` varchar(255) NOT NULL, `readerPassword` varchar(255) NOT NULL, `readerEmail` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8;
項目的大致結構如圖:
因為功能有點多。這裏先介紹後臺的實現,管理後臺和前臺互不交涉。
登錄界面
後臺主頁:
1,小說管理
2,作者管理:
3,添加分類
後臺其它導航頁面基本雷同,這裏不做一一介紹。
後臺管理員登錄處理代碼:
public class Admin { Conn conn=new Conn(); /** * 推斷登陸用戶是否合法 * @param adminName * @param adminPassword * @return * @throws SQLException */ public boolean isExist(String adminName,String adminPassword)throws SQLException{ boolean result=false; AdminInfo ainfo=new AdminInfo(); String sql="select * from admin a where adminName=‘"+adminName+"‘and adminPassword=‘"+adminPassword+"‘"; System.out.println(sql); ResultSet rs=conn.executeQuery(sql); if(rs.next()){ ainfo.setAdminName(rs.getString("adminName")); ainfo.setAdminPassword(rs.getString("adminPassword")); result=true; } conn.close(); return result; } }
小說展示,管理。添加,刪除,更新的代碼處理:
public class Novel { Conn conn=new Conn(); /** * 獲取小說列表 * @param keyword * @return * @throws SQLException */ public List<NovelInfo>getList(String keyword)throws SQLException{ List<NovelInfo> list=new ArrayList<NovelInfo>(); String sql="select n.*,g.name as genreName from novel n left join genre g on n.genreId=g.id"; if(DataValidator.isNullOrEmpty(keyword)){ sql=sql+ " order by id desc"; }else{ sql=sql+" where n.title like ‘%"+keyword+"%‘ order by id desc"; } ResultSet rs=conn.executeQuery(sql); while(rs.next()){ NovelInfo ninfo=new NovelInfo(); ninfo.setId(rs.getInt("Id")); ninfo.setTitle(rs.getString("Title")); ninfo.setContext(rs.getString("Context")); ninfo.setCreatedTime(rs.getDate("CreatedTime")); ninfo.setGenreId(rs.getInt("GenreId")); ninfo.setGenreName(rs.getString("genreName")); ninfo.setVoteNumber(rs.getInt("voteNumber")); list.add(ninfo); } conn.close(); return list; } /** * 獲取某分類下的小說列表 * @param classId * @return * @throws SQLException */ public List<NovelInfo> getListBygenreId(int genreId) throws SQLException{ List<NovelInfo> list=new ArrayList<NovelInfo>(); String sql="select n.*,g.name as genreName from novel n left join genre g on n.genreId=g.id" + " where n.genreId="+genreId+" order by id desc"; ResultSet rs=conn.executeQuery(sql); while(rs.next()){ NovelInfo info=new NovelInfo(); info.setId(rs.getInt("Id")); info.setTitle(rs.getString("Title")); info.setContext(rs.getString("Context")); info.setCreatedTime(rs.getDate("CreatedTime")); info.setGenreId(rs.getInt("GenreId")); info.setGenreName(rs.getString("genreName")); info.setVoteNumber(rs.getInt("voteNumber")); list.add(info); } conn.close(); return list; } /** * 依據ID獲取小說 * @param id * @return * @throws SQLException */ public NovelInfo getNovelInfo(int id) throws SQLException{ NovelInfo info=new NovelInfo(); String sql="select n.*,g.name as genreName from novel n left join genre g on n.genreId=g.id where n.id="+id+""; ResultSet rs=conn.executeQuery(sql); while(rs.next()){ info.setId(rs.getInt("Id")); info.setTitle(rs.getString("Title")); info.setContext(rs.getString("Context")); info.setCreatedTime(rs.getDate("CreatedTime")); info.setGenreId(rs.getInt("GenreId")); info.setGenreName(rs.getString("genreName")); info.setVoteNumber(rs.getInt("voteNumber")); } conn.close(); return info; } /** * 寫入新小說 * * @param info * @return */ public int insert(NovelInfo info){ String sql="insert into novel(title,conText,createdTime,genreId,voteNumber)values"; sql=sql+"(‘"+info.getTitle()+"‘,‘"+info.getContext()+"‘,now(),‘"+info.getGenreId()+"‘,"+info.getVoteNumber()+")"; int result=0; System.out.println(sql); result=conn.executeUpdate(sql); conn.close(); return result; } /** *更新小說 * @param info * @return */ public int update(NovelInfo info){ String sql="update novel set "+" Title=‘"+info.getTitle()+"‘,Context=‘"+info.getContext()+"‘," + "genreId=‘"+info.getGenreId()+"‘where id="+info.getId()+""; int result=0; System.out.println(sql); result=conn.executeUpdate(sql); conn.close(); return result; } /** * 刪除小說 * @param id * @return */ public int delete(int id){ String sql="delete from novel where id="+id+""; int result=0; result=conn.executeUpdate(sql); conn.close(); return result; } /** * 添加票數 * @return */ public int addVote(int num){ return 0; } }
小說評論展示,管理,添加,刪除,更新的代碼處理:
public class Comment { Conn conn=new Conn(); /** * 獲取評論列表 * @return * @throws SQLException */ public List<CommentInfo> getList() throws SQLException{ List<CommentInfo> list=new ArrayList<CommentInfo>(); String sql="select * from comment order by id desc"; ResultSet rs=conn.executeQuery(sql); while(rs.next()){ CommentInfo info=new CommentInfo(); info.setId(rs.getInt("Id")); info.setContext(rs.getString("Context")); info.setNovelId(rs.getInt("NovelId")); info.setCreatedTime(rs.getDate("CreatedTime")); info.setReaderName(rs.getString("ReaderName")); list.add(info); System.out.print(list); } conn.close(); return list; } /** * * @param classId * @return * @throws SQLException */ public CommentInfo getCommentInfo(int id)throws SQLException{ CommentInfo info=new CommentInfo(); String sql="select * from Comment c where id="+id+""; ResultSet rs=conn.executeQuery(sql); while(rs.next()){ info.setId(rs.getInt("Id")); info.setContext(rs.getString("Context")); info.setNovelId(rs.getInt("NovelId")); info.setCreatedTime(rs.getDate("CreatedTime")); info.setReaderName(rs.getString("ReaderName")); } conn.close(); return info; } /** * 獲取某小說下的評論 * @param id * @return * @throws SQLException */ public List<CommentInfo> getListByNovelId(int novelid) throws SQLException{ List<CommentInfo> list=new ArrayList<CommentInfo>(); String sql="select * from comment where novelId="+novelid+" order by id desc"; ResultSet rs=conn.executeQuery(sql); while(rs.next()){ CommentInfo info=new CommentInfo(); info.setId(rs.getInt("Id")); info.setContext(rs.getString("Context")); info.setNovelId(rs.getInt("NovelId")); info.setCreatedTime(rs.getDate("CreatedTime")); info.setReaderName(rs.getString("ReaderName")); list.add(info); } conn.close(); return list; } /** * 插入評論 * @param info * @return */ public int insert(CommentInfo info){ String sql="insert into Comment(Context,CreatedTime,readerName,novelId)values"; sql=sql+"(‘"+info.getContext()+"‘,now(),‘"+info.getReaderName()+"‘,"+info.getNovelId()+")"; int result=0; System.out.println(sql); result=conn.executeUpdate(sql); conn.close(); return result; } /** * 更新評論 * @param info * @return */ public int update(CommentInfo info){ String sql="update Comment set "+" Context=‘"+info.getContext()+"‘,novelId=‘"+info.getNovelId()+"‘," + "CreatedTime=‘"+info.getCreatedTime()+"‘,readerName=‘"+info.getReaderName()+"‘ where id="+info.getId()+""; int result=0; System.out.println(sql); result=conn.executeUpdate(sql); conn.close(); return result; } /** * 刪除評論 * @param id * @return */ public int delete(int id){ String sql="delete from Comment where id="+id+""; int result=0; result=conn.executeUpdate(sql); System.out.println(sql); conn.close(); return result; } }
小說分類展示。更新。添加,刪除的代碼處理:
public class Genre { Conn conn=new Conn(); /** * 獲取分類列表 * @return * @throws SQLException */ public List<GenreInfo> getList()throws SQLException{ List<GenreInfo> list=new ArrayList<GenreInfo>(); String sql="select * from genre order by Sort asc"; ResultSet rs=conn.executeQuery(sql); while(rs.next()){ GenreInfo info=new GenreInfo(); info.setId(rs.getInt("Id")); info.setName(rs.getString("Name")); info.setSort(rs.getInt("Sort")); list.add(info); } conn.close(); return list; } /** * * @param id * @return * @throws SQLException */ public GenreInfo getGenreInfo(int id)throws SQLException{ GenreInfo info=new GenreInfo(); String sql="select * from genre g where id="+id+""; ResultSet rs=conn.executeQuery(sql); while(rs.next()){ info.setId(rs.getInt("Id")); info.setName(rs.getString("Name")); info.setSort(rs.getInt("Sort")); } conn.close(); return info; } /** * 添加分類 * @param info * @return */ public int insert(GenreInfo info){ String sql="insert into genre(Name,Sort) values"; sql=sql+"(‘"+info.getName()+"‘,‘"+info.getSort()+"‘)"; int result=0; result=conn.executeUpdate(sql); conn.close(); return result; } /** * 更新分類 * * @param info * @return */ public int update(GenreInfo info){ String sql="update genre set "+" Name=‘"+info.getName()+"‘,Sort= ‘"+info.getSort()+"‘ where id="+info.getId()+""; int result=0; result=conn.executeUpdate(sql); return result; } public int delete(int id){ String sql="delete from genre where id="+id+""; int result=0; result=conn.executeUpdate(sql); conn.close(); return result; } }
前臺主要頁面展示:(略醜)
作者公布小說界面:
讀者評論界面:
為小說投票,投票功能的前端設計代碼:
function getElemensByClassName(className){ // 通過class獲取 var classArr = new Array(); var tags = document.getElementsByTagName("*"); //獲取全部節點 for(var item in tags){ if(tags[item].nodeType == 1){ if(tags[item].getAttribute("class") == className){ classArr.push(tags[item]); //收集class匹配的節點 } } } return classArr; } function delete_FF(element){ // 在FireFox中刪除子節點為空的元素 var childs = element.childNodes; for(var i=0;i<childs.length;i++){ var pattern = /\s/; //模式匹配,內容為空 if(childs[i].nodeName == "#text" && pattern.test(childs[i].nodeValue)){ //處理 //alert(childs[i].nodeName); element.removeChild(childs[i]); //刪除FF中獲取的空節點 } } } function $(obj){return document.getElementById(obj);} window.onload = function(){ onload1(); onload2(); }; function onload2(){ var persons = getElemensByClassName("person"); // alert(persons); for(var item in persons){ //遍歷全部person。為它們綁定投票事件 (function(_item){ //匿名函數傳入item, 防止因作用域問題導致item總為最後一個 delete_FF(persons[_item]); //出去FF中空行代表的子節點 persons[_item].setAttribute("id","person"+(parseInt(_item)+1)); //賦上id var childs = persons[_item].childNodes; for(var i = 0;i<childs.length;i++){ //alert(childs[i].nodeName); if(childs[i].nodeName == "BUTTON"){ //點擊按鈕投票 var oButton = childs[i]; } if(childs[i].nodeName == "P"){ //投票結果更新 var oP = childs[i]; var oSpan = oP.getElementsByTagName("span")[0]; } } if(oButton != null){ oButton.onclick = function(){ //事件綁定 var num = oSpan.innerHTML; //獲取票數 oSpan.innerHTML = (++num); //票數更新 // 這時一般我們可能就須要把這個票數num傳送給server保存。更新時也是和server中的num同步 this.setAttribute("disabled","true"); // 一般僅僅能投票一次的吧 alert("投票成功,謝謝您的支持"); }; } })(item); // 傳入各項person } }
小說公布的實現細節,引入了wangEditor:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@page import="org.common.*" %> <%@page import="org.model.*" %> <%@page import="org.dal.*" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!-- 公布小說 --> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>小說編輯公布界面</title> <script type="text/javascript" src="js/jquery-1.10.1.js"></script> <link rel="stylesheet" type="text/css" href="css/edit.css"> <link rel="stylesheet" type="text/css" href="css/wangEditor.min.css"> <script type="text/javascript" src="js/wangEditor.min.js"></script> </head> <body> <% request.setCharacterEncoding("utf-8"); Genre cls=new Genre(); List<GenreInfo>list=cls.getList(); Novel novel=new Novel(); NovelInfo ninfo=new NovelInfo(); if("fabu".equals(request.getParameter("action"))) { ninfo.setTitle(request.getParameter("txtTitle")); ninfo.setContext(request.getParameter("content")); ninfo.setGenreId(DataConverter.toInt(request.getParameter("selClass"))); novel.insert(ninfo); out.println("<script>alert(‘公布成功‘);</script>"); } %> <div class="header"> <h2>當前位置:小說編輯</h2> </div> <a class="wel">歡迎您:<%=Utilty.readCookie(request, "user")%></a> <div class="context" > <form id="form1" name="form1" method="post" action="novel/novel-edit.jsp?action=fabu" onsubmit="return check(this)"> <table> <tr> <td>小說所屬分類:</td> <td> <select name="selClass" id="selClass" style="width:300px;height:30px;"> <% for(GenreInfo cinfo:list){ %> <option value="<%=cinfo.getId() %>"> <%if(cinfo.getId()==ninfo.getId()) %> <%=cinfo.getName() %></option> <% } %> </select> </td> </tr> <tr> <td>小??說???標???題:</td> <td><input type="text" name="txtTitle" id="txtTitle" style="width:500px;height:30px"/></td> </tr> <tr> <td>小??說???內???容:</td> <td style="width:1000px;"><textarea rows="25" name="content" id="content"></textarea> </td> </tr> <tr> <td colspan="2" class="inp"> <input class="submit" type="submit" name="button" id="button" value="提交" style="color:#FFFFFF"/> <input class="submit" type="reset" name="button2" id="button2" value="重置"style="color:#FFFFFF" /> </td> </tr> </table> </form> </div> </body> <script type="text/javascript"> var editor = new wangEditor(‘content‘); editor.config.menus = [ ‘bold‘, ‘underline‘, ‘italic‘, ‘strikethrough‘, ‘eraser‘, ‘forecolor‘, ‘bgcolor‘, ‘|‘, ‘link‘, ‘unlink‘, ‘table‘, ‘emotion‘, ‘|‘, ‘img‘, ‘video‘, ‘location‘, ]; editor.create(); </script> </html>? 好吧,因為代碼段較多,這裏不能一一介紹,興許直接介紹一下這個項目開發過程中的錯誤細節,完好之後把源代碼上傳到資源那裏,這個項目實現起來較簡單,童鞋們能夠依據設計要求試試身手哦!
源代碼地址:https://github.com/guodalin8/novel
在線小說站點的設計與實現(附源代碼)