在线小说网站的设计与实现(附源码)

欢迎转载,请注明出处:http://blog.csdn.net/weixin_36380516

最近在做一个课程设计,在线小说网站的设计,以下是课题要求,需要项目练手的童鞋可以试试身手。

由于最近新学了JavaEE,所以采用了jsp+servlet来写,前端部分用了少量的js和jQuery处理,数据库用了MySQL,开发平台是myeclipse。

发布文章时直接插入数据库会没有分段,这里的解决办法是引入第三方工具wangEditor(wangEditor 是一款基于JavaScript和css开发的html富文本编辑器,开源免费。产品第一版发布于2014年11月。关于该编辑器:http://www.kancloud.cn/wangfupeng/wangeditor2/113961)

首先数据库的设计结构:

[sql] view plain copy
print?在CODE上查看代码片派生到我的代码片

/*  
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,增加分类

后台其他导航页面基本雷同,这里不做一一介绍。

后台管理员登录处理代码:

[java] view plain copy
print?在CODE上查看代码片派生到我的代码片

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;  
    }  
}  

小说展示,管理,增加,删除,更新的代码处理:

[java] view plain copy
print?在CODE上查看代码片派生到我的代码片

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;  
          
    }  
}  

小说评论展示,管理,增加,删除,更新的代码处理:

[java] view plain copy
print?在CODE上查看代码片派生到我的代码片

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;  
    }  
}  

小说分类展示,更新,增加,删除的代码处理:

[java] view plain copy
print?在CODE上查看代码片派生到我的代码片

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;  
    }  
      
}  

前台主要页面展示:(略丑)

作者发布小说界面:

读者评论界面:

为小说投票,投票功能的前端设计代码:

[javascript] view plain copy
print?在CODE上查看代码片派生到我的代码片

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传送给服务器保存,更新时也是和服务器中的num同步  
      this.setAttribute("disabled","true"); // 一般只能投票一次的吧  
      alert("投票成功,谢谢您的支持");  
    };  
  }  
})(item); // 传入各项person  
  }  
}  

小说发布的实现细节,引入了wangEditor:

[plain] view plain copy
print?在CODE上查看代码片派生到我的代码片

<%@ 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>  

好吧,由于代码段较多,这里不能一一介绍,后续直接介绍一下这个项目开发过程中的错误细节,完善之后把源码上传到资源那里,这个项目实现起来较简单,童鞋们可以根据设计要求试试身手哦!

源码地址:http://download.csdn.NET/download/weixin_36380516/9728880

展开阅读全文

没有更多推荐了,返回首页