zoukankan      html  css  js  c++  java
  • 在线小说站点的设计与实现(附源代码)

    近期在做一个课程设计。在线小说站点的设计,下面是课题要求。须要项目练手的童鞋能够试试身手。

    因为近期新学了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="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="500px;height:30px"/></td>
        		</tr>
        		
        		<tr>
        			<td>小  说   内   容:</td>
        			 <td style="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




  • 相关阅读:
    图像滤镜艺术---乐高像素拼图特效滤镜的代码实现
    假设你也23
    seajs载入流程图
    android 怎样将主菜单图标改成按安装时间排序
    热力学第一定律的社会学思考
    Django创建数据表
    KeyPress 和KeyDown 、KeyPress之间的区别
    Delphi 制作自定义数据感知控件并装入包(dpk文件)中(与DBText类似的数据感知控件)
    Delphi中的窗体创建与销毁
    Delphi ADOQuery连接数据库的查询、插入、删除、修改
  • 原文地址:https://www.cnblogs.com/llguanli/p/8615209.html
Copyright © 2011-2022 走看看