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

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

由于最近新学了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传送给服务器保存,更新时也是和服务器中的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" οnsubmit="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




表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
相关推荐
前言 随着计算机技术的发展和普及,各行各业的管理机构需要由计算机处理大量的信息。在我国药品品种繁多,规模甚大,以往的手工记载、查询操作容易出错且工作效率低,已经不能适应时代发展的要求,而且手工管理要浪费许多人力和物力,从管理的角度来看,对管理者会造成诸多的不便,还有可能疏忽一些细节。 利用计算机进行药品管理,堵塞了药品的流失。规范了价格管理,避免了人为的物价损失,从而明显地提高了经济效益。将销售行为纳入规范化、公开化的轨道。21世纪是信息时代,在这个信息时代里竞争异常激烈,手工管理这种传统的管理方法必然被计算机为基础的信息管理所取代,所以实现药品的信息智能化管理特别重要。 因此,本人此次决定选择药品销售管理系统作为数据库课程设计。我在分析和设计这个系统时,参考了大量相关资料,程序设计采用了面向对象设计方法,这种成熟、高效的设计方法为系统开发带来了便利。本设计成功运用了Power Designer、SQL Server开发技术,设计出了药品销售系统。此次设计含有供应商信息,客户信息,药品信息,仓库信息,管理员信息,销售信息,供应信息,供应明细,销售明细,供应商往来账,退货返厂。 本设计实现了对这些信息的查询、插入、修改、删除等操作。 工程概况 2.1 项目题目 药品销售系统数据库设计 2.2 课程设计开发环境 开发的操作系统是Windows XP。硬件、软件要求不高,目前市场上的一般计算机软硬件都能满足系统开发要求。本次系统设计使用的前台开发工具是Power Designer。后台数据库使用的是SQL server2000。 2.3 项目设计背景及意义 开发药店药品销售管理系统能够提高药品销售管理的工作效率、扩大服务范围、增加药店收入、及时获取信息、减少决策失误、减少库存积压、提升员工的素质。能够及时提供药品基本信息、库存信息、销售业务信息和药店财务信息。在此基础上,通过对各种信息的综合分析,以改进药品品种、提高服务质量、满足前来购药顾客的不同要求,使药店管理向高质量、科学化发展。对提高仓储管理的工作效率和对市场的反应能力,能高效益、低库存、保证服务质量的满足药店药品销售日常管理的需要,使其采用现代化管理手段以适应药店药品批发、零售业的发展。 正文 该药品销售系统设计成功运用了Power Designer、SQL Server开发技术,设计出了对药品销售的管理信息。为了方便用户操作,在设置了系统功能,基本信息管理,查询等功能。在基本信息管理项的供应商信息、客户信息、药品信息、仓库信息等,可以进行添加修改删除等操作,在销售明细中可以查询销售信息,另外也可以查询供应信息及退货返厂的信息。 3.1 设计目的和意义 3.1.1 设计目的 通过本次数据库系统概论课程的学习与课程设计的制作,使我熟练掌握了Power Designer、SQL Server技术设计的基本方法,并学会了SQL Server查询分析器和企业管理器的使用以及如何进行数据库的备份还原的基本知识,还学会了Power Designer的制图方法。同时通过两周的数据库课程设计的制作我还了解了数据库间的关系模型及SQL语言的特点,从而学会了如何建立基本表、定义、插入、删除与修改数据。通过该课程设计,使我对课本所学的知识得以巩固,将Power Designer、SQL Server开发技术相结合开发药品销售系统,这次设计使我们将理论知识和实践有机的相结合,达到了学以致用的真正目的。 3.1.2 设计意义
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页