小说网站|基于Springboot+Vue实现在线小说阅读网站

本文涉及的产品
函数计算FC,每月15万CU 3个月
简介: 小说网站|基于Springboot+Vue实现在线小说阅读网站

项目编号:BS-PT-116

一,环境介绍

语言环境:Java:  jdk1.8

数据库:Mysql: mysql5.7

应用服务器:Tomcat:  tomcat8.5.31

开发工具:IDEA或eclipse

开发技术:Springboot+Vue

二,项目简介

本项目基于Springboot+Vue开发实现了一个在线小说阅读网站平台。系统设计用户主要有三类:读者、作者、管理员。用户注册时以读者身分进入平台,可以自己修改身分为作者。读者登录系统可以查看并在线阅读发布的小说章节内容,并在线评论、点赞和举报处理,同时可以查看平台发布的小说新闻和平台公告新闻。。作者登录平台除了可以查看小说外,还可以在线发布小说和内容,进行在线创作。所有的信息由平台管理员进行管理操作,包含人员管理、小说管理、章节管理、类型管理、举报管理、评论管理、新闻管理、系统管理(轮播图管理、超链接管理)等。

三,系统展示

系统首页

小说列表

小说阅读-点赞-举报

资讯信息查看

个人中心

草稿箱

个人评论管理

个人资料管理

管理员登录系统

作者管理

小说分类管理

小说管理

评论-举报-点赞管理

平台新闻管理和分类管理

系统管理

四,核心代码展示

package com.spring.controller;
import com.spring.util.DESUtil;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
 * 验证码控制器
 */
@Controller
public class CaptchaController extends BaseController {
    /**
     * 输出验证码图片,并记录session “random” 里等待登录时写入
     */
    @RequestMapping("/captcha")
    public String Index() {
        // 把验证码字符串写入session 中,保存待下次验证时使用
        String sRand = createRandomString(4);
        try {
            // 输出渲染好的内容到前端浏览器
            if (isAjax()) {
                String result = null;
                do {
                    try {
                        result = DESUtil.encrypt("CaptchControllerPassword", sRand);
                    } catch (Exception e) {
                        result = null;
                    }
                    if (result != null) {
                        if (!sRand.equals(DESUtil.decrypt("CaptchControllerPassword", result))) {
                            result = null; // 解不出来所以出错
                        }
                    }
                } while (result == null);
                assign("url", "/randtocaptch?captchToken=" + urlencode(result));
                assign("token", result);
                return json();
            } else {
                //byte[] img = xxx;
                response.setContentType("image/jpeg"); // 定义输出类型为 图片
                response.setHeader("Pragma", "No-cache"); // 设置为无缓存
                response.setHeader("Cache-Control", "no-cache"); // 设置为无缓存
                response.setDateHeader("Expires", 0); // 设置缓存时间为0秒后过期
                request.getSession().setAttribute("random", sRand);
                ServletOutputStream stream = response.getOutputStream();
                createCaptch(sRand, stream);
                stream.flush();
                stream.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "success";
    }
    /**
     * url 编码,中文要进行编码输出
     * @param str
     * @return
     */
    public static String urlencode(Object str) {
        try {
            return java.net.URLEncoder.encode(String.valueOf(str), "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str.toString();
    }
    /**
     * 使用上面的加密字符串生成验证码
     * @return
     */
    @RequestMapping("/randtocaptch")
    public String getCaptch() throws IOException {
        String captchToken = request.getParameter("captchToken");
        String sRand = DESUtil.decrypt("CaptchControllerPassword", captchToken);
        HttpSession session = request.getSession();
        {
            //byte[] img = xxx;
            response.setContentType("image/jpeg"); // 定义输出类型为 图片
            response.setHeader("Pragma", "No-cache"); // 设置为无缓存
            response.setHeader("Cache-Control", "no-cache"); // 设置为无缓存
            response.setDateHeader("Expires", 0); // 设置缓存时间为0秒后过期
            ServletOutputStream stream = response.getOutputStream();
            createCaptch(sRand, stream);
            stream.flush();
            stream.close();
        }
        return "success";
    }
    private String createRandomString(int len) {
        // 生成随机数类
        Random random = new Random();
        String result = "";
        for (int i = 0; i < len; i++) {
            String rand = String.valueOf(random.nextInt(10));
            result += rand;
        }
        return result;
    }
    private void createCaptch(String randomstr, OutputStream stream) {
        int width = 60, height = 20; // 定义图片宽为 60  高度为 20
        // 创建图片缓冲区
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 获取渲染画板
        Graphics g = image.getGraphics();
        // 生成随机数类
        Random random = new Random();
        // 设置颜色
        g.setColor(getRandColor(200, 250));
        // 绘制矩形
        g.fillRect(0, 0, width, height);
        // 设置字体信息
        g.setFont(new Font("Times New Roman", Font.PLAIN, 18));
        // 设置颜色信息
        g.setColor(getRandColor(160, 200));
        // 写入干扰线
        for (int i = 0; i < 155; i++) {
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int xl = random.nextInt(12);
            int yl = random.nextInt(12);
            g.drawLine(x, y, x + xl, y + yl);
        }
        // 写入验证码字符串
        for (int i = 0; i < randomstr.length(); i++) {
            String rand = randomstr.substring(i, i + 1); //String.valueOf(random.nextInt(10));
            g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
            g.drawString(rand, 13 * i + 6, 16);
        }
        g.dispose(); // 释放画板
        try {
            // 输出渲染好的内容到前端浏览器
            ImageIO.write(image, "JPEG", stream);
            stream.flush();
            stream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 获取随机颜色
     * @param fc
     * @param bc
     * @return
     */
    protected Color getRandColor(int fc, int bc) {
        Random random = new Random();
        if (fc > 255) fc = 255;
        if (bc > 255) bc = 255;
        int r = fc + random.nextInt(bc - fc);
        int g = fc + random.nextInt(bc - fc);
        int b = fc + random.nextInt(bc - fc);
        return new Color(r, g, b);
    }
}
package com.spring.controller;
import com.jntoo.db.*;
import com.jntoo.db.utils.*;
import com.spring.dao.*;
import com.spring.entity.*;
import com.spring.service.*;
import com.spring.util.*;
import com.spring.util.Info;
import java.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import tk.mybatis.mapper.entity.Example;
/**
 * 点赞 */
@Controller
public class DianzanController extends BaseController {
    @Autowired
    private DianzanMapper dao;
    @Autowired
    private DianzanService service;
    @Autowired
    private PinglunService serviceRead;
    /**
     *  后台列表页
     *
     */
    @RequestMapping("/dianzan_list")
    public String list() {
        // 检测是否有登录,没登录则跳转到登录页面
        if (!checkLogin()) {
            return showError("尚未登录", "./login.do");
        }
        String order = Request.get("order", "id"); // 获取前台提交的URL参数 order  如果没有则设置为id
        String sort = Request.get("sort", "desc"); // 获取前台提交的URL参数 sort  如果没有则设置为desc
        int pagesize = Request.getInt("pagesize", 12); // 获取前台一页多少行数据
        Example example = new Example(Dianzan.class); //  创建一个扩展搜索类
        Example.Criteria criteria = example.createCriteria(); // 创建一个扩展搜索条件类
        String where = " 1=1 "; // 创建初始条件为:1=1
        where += getWhere(); // 从方法中获取url 上的参数,并写成 sql条件语句
        criteria.andCondition(where); // 将条件写进上面的扩展条件类中
        if (sort.equals("desc")) { // 判断前台提交的sort 参数是否等于  desc倒序  是则使用倒序,否则使用正序
            example.orderBy(order).desc(); // 把sql 语句设置成倒序
        } else {
            example.orderBy(order).asc(); // 把 sql 设置成正序
        }
        int page = request.getParameter("page") == null ? 1 : Integer.valueOf(request.getParameter("page")); // 获取前台提交的URL参数 page  如果没有则设置为1
        page = Math.max(1, page); // 取两个数的最大值,防止page 小于1
        List<Dianzan> list = service.selectPageExample(example, page, pagesize); // 获取当前页的行数
        // 将列表写给界面使用
        assign("totalCount", request.getAttribute("totalCount"));
        assign("list", list);
        assign("orderby", order); // 把当前排序结果写进前台
        assign("sort", sort); // 把当前排序结果写进前台
        return json(); // 将数据写给前端
    }
    public String getWhere() {
        _var = new LinkedHashMap(); // 重置数据
        String where = " ";
        // 判断URL 参数pinglunid是否大于0
        if (Request.getInt("pinglunid") > 0) {
            // 大于0 则写入条件
            where += " AND pinglunid='" + Request.getInt("pinglunid") + "' ";
        }
        // 以下也是一样的操作,判断是否符合条件,符合则写入sql 语句
        if (!Request.get("dianzanren").equals("")) {
            where += " AND dianzanren LIKE '%" + Request.get("dianzanren") + "%' ";
        }
        return where;
    }
    /**
     * 评论人列表
     */
    @RequestMapping("/dianzan_list_pinglunren")
    public String listpinglunren() {
        // 检测是否有登录,没登录则跳转到登录页面
        if (!checkLogin()) {
            return showError("尚未登录", "./login.do");
        }
        String order = Request.get("order", "id"); // 获取前台提交的URL参数 order  如果没有则设置为id
        String sort = Request.get("sort", "desc"); // 获取前台提交的URL参数 sort  如果没有则设置为desc
        int pagesize = Request.getInt("pagesize", 12); // 获取前台一页多少行数据
        Example example = new Example(Dianzan.class); //  创建一个扩展搜索类
        Example.Criteria criteria = example.createCriteria(); // 创建一个扩展搜索条件类
        // 初始化一个条件,条件为:评论人=当前登录用户
        String where = " pinglunren='" + request.getSession().getAttribute("username") + "' ";
        where += getWhere();
        criteria.andCondition(where); // 将条件写入
        if (sort.equals("desc")) { // 注释同list
            example.orderBy(order).desc(); // 注释同list
        } else {
            example.orderBy(order).asc(); // 注释同list
        }
        int page = request.getParameter("page") == null ? 1 : Integer.valueOf(request.getParameter("page")); // 注释同list
        page = Math.max(1, page); // 注释同list
        List<Dianzan> list = service.selectPageExample(example, page, pagesize);
        assign("totalCount", request.getAttribute("totalCount"));
        assign("list", list);
        assign("orderby", order);
        assign("sort", sort);
        return json(); // 将数据写给前端
    }
    /**
     * 点赞人列表
     */
    @RequestMapping("/dianzan_list_dianzanren")
    public String listdianzanren() {
        // 检测是否有登录,没登录则跳转到登录页面
        if (!checkLogin()) {
            return showError("尚未登录", "./login.do");
        }
        String order = Request.get("order", "id"); // 获取前台提交的URL参数 order  如果没有则设置为id
        String sort = Request.get("sort", "desc"); // 获取前台提交的URL参数 sort  如果没有则设置为desc
        int pagesize = Request.getInt("pagesize", 12); // 获取前台一页多少行数据
        Example example = new Example(Dianzan.class); //  创建一个扩展搜索类
        Example.Criteria criteria = example.createCriteria(); // 创建一个扩展搜索条件类
        // 初始化一个条件,条件为:点赞人=当前登录用户
        String where = " dianzanren='" + request.getSession().getAttribute("username") + "' ";
        where += getWhere();
        criteria.andCondition(where); // 将条件写入
        if (sort.equals("desc")) { // 注释同list
            example.orderBy(order).desc(); // 注释同list
        } else {
            example.orderBy(order).asc(); // 注释同list
        }
        int page = request.getParameter("page") == null ? 1 : Integer.valueOf(request.getParameter("page")); // 注释同list
        page = Math.max(1, page); // 注释同list
        List<Dianzan> list = service.selectPageExample(example, page, pagesize);
        assign("totalCount", request.getAttribute("totalCount"));
        assign("list", list);
        assign("orderby", order);
        assign("sort", sort);
        return json(); // 将数据写给前端
    }
    @RequestMapping("/dianzan_add")
    public String add() {
        _var = new LinkedHashMap(); // 重置数据
        int id = Request.getInt("id"); // 根据id 获取 评论模块中的数据
        Pinglun readMap = serviceRead.find(id);
        // 将数据行写入给前台jsp页面
        assign("readMap", readMap);
        return json(); // 将数据写给前端
    }
    @RequestMapping("/dianzan_updt")
    public String updt() {
        _var = new LinkedHashMap(); // 重置数据
        int id = Request.getInt("id");
        // 获取行数据,并赋值给前台jsp页面
        Dianzan mmm = service.find(id);
        assign("mmm", mmm);
        assign("updtself", 0);
        return json(); // 将数据写给前端
    }
    /**
     * 添加内容
     * @return
     */
    @RequestMapping("/dianzaninsert")
    public String insert() {
        _var = new LinkedHashMap(); // 重置数据
        String tmp = "";
        Dianzan post = new Dianzan(); // 创建实体类
        // 设置前台提交上来的数据到实体类中
        post.setPinglunid(Request.getInt("pinglunid"));
        post.setBiao(Request.get("biao"));
        post.setBiaoid(Request.getInt("biaoid"));
        post.setBiaoti(Request.get("biaoti"));
        post.setPingfen(Request.get("pingfen"));
        post.setPinglunneirong(Request.get("pinglunneirong"));
        post.setPinglunren(Request.get("pinglunren"));
        post.setDianzanren(Request.get("dianzanren"));
        post.setPinglunid(Request.getInt("pinglunid"));
        Dianzan dz = DB.name(Dianzan.class).where("pinglunid" , post.getPinglunid()).where("dianzanren" , post.getDianzanren()).find();
        if(dz!= null){
            DB.name(Dianzan.class).delete(dz.getId());
            return jsonResult(-1);
        }
        service.insert(post); // 插入数据
        int charuid = post.getId().intValue();
        Query.execute("update pinglun set dianzanshu=dianzanshu+1 where id='" + request.getParameter("pinglunid") + "'");
        if (isAjax()) {
            return jsonResult(post);
        }
        return showSuccess("保存成功", Request.get("referer").equals("") ? request.getHeader("referer") : Request.get("referer"));
    }
    /**
     * 更新内容
     * @return
     */
    @RequestMapping("/dianzanupdate")
    public String update() {
        _var = new LinkedHashMap(); // 重置数据
        // 创建实体类
        Dianzan post = new Dianzan();
        // 将前台表单数据填充到实体类
        if (!Request.get("pinglunid").equals("")) post.setPinglunid(Request.getInt("pinglunid"));
        if (!Request.get("biao").equals("")) post.setBiao(Request.get("biao"));
        if (!Request.get("biaoid").equals("")) post.setBiaoid(Request.getInt("biaoid"));
        if (!Request.get("biaoti").equals("")) post.setBiaoti(Request.get("biaoti"));
        if (!Request.get("pingfen").equals("")) post.setPingfen(Request.get("pingfen"));
        if (!Request.get("pinglunneirong").equals("")) post.setPinglunneirong(Request.get("pinglunneirong"));
        if (!Request.get("pinglunren").equals("")) post.setPinglunren(Request.get("pinglunren"));
        if (!Request.get("dianzanren").equals("")) post.setDianzanren(Request.get("dianzanren"));
        post.setId(Request.getInt("id"));
        service.update(post); // 更新数据
        int charuid = post.getId().intValue();
        if (isAjax()) {
            return jsonResult(post);
        }
        return showSuccess("保存成功", Request.get("referer")); // 弹出保存成功,并跳转到前台提交的 referer 页面
    }
    /**
     *  删除
     */
    @RequestMapping("/dianzan_delete")
    public String delete() {
        _var = new LinkedHashMap(); // 重置数据
        if (!checkLogin()) {
            return showError("尚未登录");
        }
        int id = Request.getInt("id"); // 根据id 删除某行数据
        Map map = Query.make("dianzan").find(id);
        service.delete(id); // 根据id 删除某行数据
        Query.execute("update pinglun set dianzanshu=dianzanshu-1 where id='" + map.get("pinglunid") + "'");
        return showSuccess("删除成功", request.getHeader("referer")); //弹出删除成功,并跳回上一页
    }
}

五,相关作品展示

基于Java开发、Python开发、PHP开发、C#开发等相关语言开发的实战项目

基于Nodejs、Vue等前端技术开发的前端实战项目

基于微信小程序和安卓APP应用开发的相关作品

基于51单片机等嵌入式物联网开发应用

基于各类算法实现的AI智能应用

基于大数据实现的各类数据管理和推荐系统

相关实践学习
【文生图】一键部署Stable Diffusion基于函数计算
本实验教你如何在函数计算FC上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。函数计算提供一定的免费额度供用户使用。本实验答疑钉钉群:29290019867
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
相关文章
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
111 62
|
2天前
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
32 13
|
10天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
69 2
|
1月前
|
JavaScript NoSQL Java
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
CC-ADMIN后台简介一个基于 Spring Boot 2.1.3 、SpringBootMybatis plus、JWT、Shiro、Redis、Vue quasar 的前后端分离的后台管理系统
39 0
|
21天前
|
JavaScript API 开发者
Vue是如何进行组件化的
Vue是如何进行组件化的
|
23天前
|
JavaScript 前端开发 开发者
vue 数据驱动视图
总之,Vue 数据驱动视图是一种先进的理念和技术,它为前端开发带来了巨大的便利和优势。通过理解和应用这一特性,开发者能够构建出更加动态、高效、用户体验良好的前端应用。在不断发展的前端领域中,数据驱动视图将继续发挥重要作用,推动着应用界面的不断创新和进化。
|
24天前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱前端的大一学生,专注于JavaScript与Vue,正向全栈进发。博客分享Vue学习心得、命令式与声明式编程对比、列表展示及计数器案例等。关注我,持续更新中!🎉🎉🎉
27 1
vue学习第一章
|
24天前
|
JavaScript 前端开发 索引
vue学习第三章
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中的v-bind指令,包括基本使用、动态绑定class及style等,希望能为你的前端学习之路提供帮助。持续关注,更多精彩内容即将呈现!🎉🎉🎉
24 1
vue学习第三章
|
25天前
|
缓存 JavaScript 前端开发
vue学习第四章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript与Vue的大一学生。本文介绍了Vue中计算属性的基本与复杂使用、setter/getter、与methods的对比及与侦听器的总结。如果你觉得有用,请关注我,将持续更新更多优质内容!🎉🎉🎉
35 1
vue学习第四章