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




  • 相关阅读:
    Struts2SpringHibernate整合示例,一个HelloWorld版的在线书店(项目源码+详尽注释+单元测试)
    Java实现蓝桥杯勇者斗恶龙
    Java实现 LeetCode 226 翻转二叉树
    Java实现 LeetCode 226 翻转二叉树
    Java实现 LeetCode 226 翻转二叉树
    Java实现 LeetCode 225 用队列实现栈
    Java实现 LeetCode 225 用队列实现栈
    Java实现 LeetCode 225 用队列实现栈
    Java实现 LeetCode 224 基本计算器
    Java实现 LeetCode 224 基本计算器
  • 原文地址:https://www.cnblogs.com/llguanli/p/8615209.html
Copyright © 2011-2022 走看看