前端+后端项目 - 论坛信息管理系统(Web+servlet+MySQL+JDBC)

这篇具有很好参考价值的文章主要介绍了前端+后端项目 - 论坛信息管理系统(Web+servlet+MySQL+JDBC)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🤞目录🤞

💖一. 准备工作

💎1) 创建 web 项目

💎2) 创建目录结构

💎3) 配置 pom.xml

💖二. 数据库操作代码

💎1. 数据库设计

1.1 ER图

1.2 ER图转化为关系模型并优化

1.3 创建数据库/表结构

💎2. 封装数据库

1.  DBUtil 类(JDBC连接数据库)

2. 创建实体类

        2.1 User

        2.2 Section

        2.3 Topic

        2.4 Reply

        2.5 Key

3. 封装对数据库的增删查改类

        3.1 UserDao

        3.2 SectionDao

        3.3 TopicDao

        3.4 ReplyDao

        3.5 KeyDao

💖三. 约定前后端交互接口

💎0. 前端页面

💎1. 实现论坛列表页

1.1约定前后端交互接口

1.2 实现服务器代码

1.3 编写客户端代码

💎2. 实现论坛主贴页

2.1约定前后端交互接口

2.2 实现服务器代码

2.3 编写客户端代码

💎3. 实现论坛回复页

3.1约定前后端交互接口

3.2 实现服务器代码

3.3 编写客户端代码

💎4. 实现论坛个人中心页

4.1约定前后端交互接口

4.2 实现服务器代码

4.3 编写客户端代码

💎5. 实现论坛发布帖子页

5.1约定前后端交互接口

5.2 实现服务器代码

 5.3 编写客户端代码

💎6. 实现论坛登录页

6.1约定前后端交互接口

6.2 实现服务器代码

6.3 编写客户端代码

💎7. 实现论坛注册页

7.1约定前后端交互接口

7.2 实现服务器代码

7.3 编写客户端代码

💎8. 实现论坛注销

8.1实现服务器代码


【大家好,我是爱干饭的猿,如果喜欢这篇文章,点个赞👍,关注一下吧,后续会持续分享其他项目的相关操作和Linux相关知识

上一篇文章:《前端项目 - 论坛信息管理系统(纯页面)》

本篇文章介绍的《论坛信息管理系统》源码链接放在文章末尾了,感兴趣的朋友可以看看。


上一篇文章中我们完成了论坛信息管理系统的前端页面,现在我们可以基于模板的方式,通过服务器把数据渲染到页面中,然后直接返回完整的页面给浏览器。

目前比较主流的开发方式是“前后端分离”的方式,在这种方式下服务端不关注页面的内容,而是网页提供的数据。

网页可以通过ajax的方式和服务器之间交互数据,网页拿到数据之后再根据数据的内容渲染到页面上。

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

此篇文章仅展示重要代码思路过程,项目源码在 gitee 中
链接: 《论坛信息管理系统》

效果展示

论坛列表页:

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

论坛主贴页:

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

论坛回帖页:

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

用户写帖子页:

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

用户个人信息页:

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

论坛登录页:论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

 论坛注册页:

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat


 

一. 准备工作

1) 创建 web 项目

2) 创建目录结构

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

3) 配置 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>forum-inforation-management-system</artifactId>
    <version>1.0-SNAPSHOT</version>
    
    <!-- 指定最终 war 包的名称 -->
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <!-- 加入 servlet 依赖 -->
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.4</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>compile</scope>
        </dependency>

    </dependencies>


</project>

二. 数据库操作代码

1. 数据库设计

1.1 ER图

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

1.2 ER图转化为关系模型并优化

  1. 管理员信息表管理员编号,管理员名称,管理员密码
  2. 用户信息表用户编号,用户名称,用户密码,用户生日,用户性别,用户性别,用户生日,用户职业,用户爱好,用户帖子数,用户等级,用户注册日期
  3. 块信息表版块编号,版主编号,版块名称,版块说明,版块点击次数,版块主题数
  4. 主贴信息表主贴编号主贴板块编号主贴用户编号主贴回复次数主贴标题主贴内容主贴时间主贴回复次数,主贴点击次数
  5. 回复贴信息表回帖编号回帖主题帖子编号回帖的用户编号回帖标题回帖内容回帖时间回帖点击次数

1.3 创建数据库/表结构

根据在ER图中的实体,创建库表结构
db.sql
-- 创建数据库
if exit forum_management_information_system1 drop database `forum_management_information_system1`;
CREATE SCHEMA `forum_management_information_system1` DEFAULT CHARACTER SET utf8 ;

-- 创建管理员信息表
CREATE TABLE `admin` (
  `adminID` int NOT NULL AUTO_INCREMENT COMMENT '管理员编号',
  `adminName` varchar(20) NOT NULL COMMENT '管理员名称',
  `adminPassword` varchar(20) NOT NULL COMMENT '管理员密码',
  PRIMARY KEY (`adminID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='管理员信息表';

-- 创建用户信息表
CREATE TABLE `user` (
  `uID` int NOT NULL AUTO_INCREMENT COMMENT '用户编号',
  `userName` varchar(20) NOT NULL COMMENT '用户昵称',
  `userPassword` varchar(20) NOT NULL COMMENT '用户密码',
  `userSex` varchar(20) NOT NULL COMMENT '用户性别',
  `userAge` int NOT NULL COMMENT '用户生日',
  `userOccupation` varchar(20) NOT NULL COMMENT '用户职业',
  `userHobby` varchar(20) NOT NULL COMMENT '用户爱好',
  `userPoint` int NOT NULL DEFAULT '0' COMMENT '用户积分',
  `userClass` int NOT NULL DEFAULT '0' COMMENT '用户等级',
  `userRegister` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '用户注册时间',
  PRIMARY KEY (`uID`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb3 COMMENT='用户信息表';

-- 板块信息表
CREATE TABLE `section` (
  `sID` int NOT NULL AUTO_INCREMENT COMMENT '板块编号',
  `uID` int NOT NULL COMMENT '版主编号(用户编号)',
  `sName` varchar(50) NOT NULL COMMENT '板块名称',
  `sStatement` text NOT NULL COMMENT '板块说明',
  `sClickCount` int NOT NULL DEFAULT '0' COMMENT '板块点击次数',
  `sTopicCount` int NOT NULL DEFAULT '0' COMMENT '板块主题数',
  PRIMARY KEY (`sID`),
  KEY `s_uID_idx` (`uID`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb3 COMMENT='板块信息表';

-- 主贴信息表
CREATE TABLE `topic` (
  `tID` int NOT NULL AUTO_INCREMENT COMMENT '主贴编号',
  `sID` int NOT NULL COMMENT '主贴板块编号',
  `uID` int NOT NULL COMMENT '主贴用户编号',
  `tTopic` varchar(20) NOT NULL COMMENT '主贴标题',
  `tContent` text NOT NULL COMMENT '主贴内容',
  `tTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '主贴时间',
  `tReplyCount` int NOT NULL DEFAULT '0' COMMENT '主贴回复次数',
  `tClickCount` int NOT NULL DEFAULT '0' COMMENT '主贴点击次数',
  PRIMARY KEY (`tID`),
  KEY `t_uID_idx` (`uID`),
  KEY `t_sID_idx` (`sID`),
  CONSTRAINT `t_sID` FOREIGN KEY (`sID`) REFERENCES `section` (`sID`),
  CONSTRAINT `t_uID` FOREIGN KEY (`uID`) REFERENCES `user` (`uID`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb3 COMMENT='主贴信息表';

-- 回复贴信息表
CREATE TABLE `reply` (
  `rID` int NOT NULL AUTO_INCREMENT COMMENT '回帖编号',
  `tID` int NOT NULL COMMENT '回帖主题帖子编号(主贴信息表)',
  `uID` int NOT NULL COMMENT '回帖的用户编号',
  `rTopic` varchar(20) NOT NULL DEFAULT '回帖' COMMENT '回帖标题',
  `rContent` text NOT NULL COMMENT '回帖内容',
  `rTime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '回帖时间',
  `rClickCount` int NOT NULL DEFAULT '0' COMMENT '回帖点击次数',
  PRIMARY KEY (`rID`)
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8mb3 COMMENT='回复贴信息表';

-- 初始数据 (增加一个用户)
INSERT INTO `forum_management_information_system1`.`user` (`userName`, `userPassword`, `userSex`, `userAge`, `userOccupation`, `userHobby`) VALUES ('管理员', '123456', '男', '18', '管理员', '你猜');

-- 初始化板块数据
INSERT INTO `forum_management_information_system1`.`section` (`uID`, `sName`, `sStatement`) VALUES ('1', '网易云', '小时候枕头上全是口水,长大后枕头上全是泪水;小时候微笑是一个心情,长大后微笑是一种表情;小时候哭着哭着就笑了,长大后笑着笑着就哭了。我们终于到了小时候最羡慕的年龄,但却没有成为小时候最想成为的人。——网易云音乐热评《当我已不再那么年轻》');
INSERT INTO `forum_management_information_system1`.`section` (`uID`, `sName`, `sStatement`) VALUES ('1', '码农', '码农Coding Peasant(s):可以指在程序设计某个专业领域中的专业人士,或是从事软体撰写,程序开发、维护的专业人员。但一般Coder特指进行编写代码的编码员。');
INSERT INTO `forum_management_information_system1`.`section` (`uID`, `sName`, `sStatement`) VALUES ('1', '电影', '电影,也被称为运动画面或动态画面,即“映画”,是作品视觉艺术形式,通过使用移动图像来表达沟通思想,故事,认知,情感,价值观,或各类大气模拟体验。这些图像通常伴随着声音,很少有其他感官刺激。 “电影”一词是电影摄影的缩写,通常用于指代电影制作和电影业,以及由此产生的艺术形式。');
INSERT INTO `forum_management_information_system1`.`section` (`uID`, `sName`, `sStatement`) VALUES ('1', '体育', '( physical education ,缩写 PE 或 P.E. ),是一种复杂的社会文化现象,它是一种以身体与智力活动为基本手段,根据人体生长发育、技能形成和机能提高等规律,达到促进全面发育、提高身体素质与全面教育水平、增强体质与提高运动能力、改善生活方式与提高生活质量的一种有意识、有目的、有组织的社会活动。');
INSERT INTO `forum_management_information_system1`.`section` (`uID`, `sName`, `sStatement`) VALUES ('1', '游戏', '游戏(英文: Game)是所有哺乳类动物,特别是灵长类动物学习生存的第一步。它是一种基于物质需求满足之上的,在一些特定时间、空间范围内遵循某种特定规则的,追求精神世界需求满足的社会行为方式,但同时这种行为方式也是哺乳类动物或者灵长类动物所需的一种降压减排的方式,不管是在出生幼年期,或者发育期,成熟期都会需要的一种行为方式。');
INSERT INTO `forum_management_information_system1`.`section` (`uID`, `sName`, `sStatement`) VALUES ('1', '旅行', '“旅”是旅行,外出,即为了实现某一目的而在空间上从甲地到乙地的行进过程;“游”是外出游览、观光、娱乐,即为达到这些目的所作的旅行。二者合起来即旅游。所以,旅行偏重于行,旅游不但有“行”,且有观光、娱乐含义。');
INSERT INTO `forum_management_information_system1`.`section` (`uID`, `sName`, `sStatement`) VALUES ('1', '明星', ' (拼音míng xīng,注音ㄇㄧㄥˊ ㄒㄧㄥ)汉语 词语 ,古书上指金星;旧时指 交际 场中有名的女子;现指在某个领域内有一定影响力的人物。 泛指有名的 演员 、 歌手 、 艺人 、 运动员 等。');

2. 封装数据库

 1.  DBUtil 类(JDBC连接数据库)

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat
package forum.util;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import lombok.SneakyThrows;

import javax.sql.DataSource;
import java.sql.Connection;

/**
 * @author haomin
 * @date 2022/06/29 17:23
 **/
public class DBUtil {
    private static final DataSource dataSource;

    static {
        MysqlDataSource mysqlDataSource = new MysqlDataSource();
        // 数据库路径要正确
        mysqlDataSource.setUrl("jdbc:mysql:///forum_management_information_system1?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai");
        mysqlDataSource.setUser("root");
        mysqlDataSource.setPassword("123456");
        dataSource = mysqlDataSource;
    }

    @SneakyThrows
    public static Connection connection() {
        return dataSource.getConnection();
    }

}

2. 创建实体类

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat
一般放对象的目录命名为model,根据model目录,其中存放的都是各种对象,例如  User 类、Topic 类、Reply 类。
使用@Data注解在类上时,不用再手动添加get/set等方法了,简化代码

2.1 User

package forum.model;

import lombok.Data;

// 使用@Data注解在类上时,不用再手动添加get/set等方法了,简化代码
@Data
public class User {
    public Integer uID;
    public String username;
    public String password;
    public String userSex;
    public Integer userAge;
    public String userOccupation;
    public String userHobby;
    public Integer userPoint;
    public Integer userClass;
    public String userRegister;
}

2.2 Section

package forum.model;

import lombok.Data;

@Data
public class Section {
    public Integer sID;
    public Integer uID;
    public String sName;
    public String sStatement;
    public Integer sClickCount;
    public Integer sTopicCount;
}

2.3 Topic

package forum.model;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;

import java.util.Date;

@Data
public class Topic {
    public Integer tID;
    public Integer sID;
    public Integer uID;
    public String username;
    public String tTopic;
    public String tContent;
    //@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    public String tTime;
    public Integer tReplyCount;
    public Integer tClickCount;
}

2.4 Reply

package forum.model;

import com.fasterxml.jackson.annotation.JsonFormat;

import java.util.Date;

public class Reply {
    public Integer rID;
    public Integer tID;
    public Integer uID;
    public String username;
    public String rTopic;
    public String rContent;
    public String rTime;
    public Integer rClickCount;
}

2.5 Key

为实现一个搜索功能,新建了一个Keyword实体

package forum.model;

import lombok.Data;

@Data
public class Keyword {
    public String keyword;
}

3. 封装对数据库的增删查改类

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

一般放数据库增删查改的目录命名为dao,根据dao目录,其中存放的都是各种数据库增删查改方法类,例如 UserDao 类 , SectionDao 类。

3.1 UserDao

package forum.dao;

import forum.model.User;
import forum.util.DBUtil;
import lombok.SneakyThrows;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/**
 * @author haomin
 * @date 2022/06/29 17:22
 **/

// 从数据库查找user数据的方法类
public class UserDao {

    // 用户帖子数
    @SneakyThrows
    public int selectPointCountByUid(int uid){
        String sql = "select count(*) from topic where uID = ?";
        try (Connection c = DBUtil.connection()){
            try (PreparedStatement ps = c.prepareStatement(sql)){
                ps.setInt(1,uid);
                try (ResultSet rs = ps.executeQuery()){
                    rs.next();
                    int count = rs.getInt("count(*)");
                    updatePointCountByUid(uid,count);
                    return count;
                }
            }
        }
    }

    // 更新主贴回复数
    @SneakyThrows
    public void updatePointCountByUid(int uID, int count) {
        String sql = "update user set userPoint = ? where uID = ?";
        try (Connection c = DBUtil.connection()) {
            try (PreparedStatement ps = c.prepareStatement(sql)) {
                ps.setInt(1,count);
                ps.setInt(2,uID);

                ps.executeUpdate();
            }
        }
    }

    // 用户等级
    public int selectClassCountByUid(int uid){
        int point = new UserDao().selectPointCountByUid(uid);
        int classCount = 0;
        if(point == 0){
            classCount = 0;
        }else if(point < 5){
            classCount = 1;
        }else if(point < 15){
            classCount = 2;
        }else if(point < 30){
            classCount = 3;
        }else {
            classCount = 4;
        }
        updateClassCountByUid(uid,classCount);
        return classCount;
    }

    @SneakyThrows
    private void updateClassCountByUid(int uID, int classCount) {
        String sql = "update user set userClass = ? where uID = ?";
        try (Connection c = DBUtil.connection()) {
            try (PreparedStatement ps = c.prepareStatement(sql)) {
                ps.setInt(1,classCount);
                ps.setInt(2,uID);

                ps.executeUpdate();
            }
        }

    }

    // 查询用户ByUsernameAndPassword
    @SneakyThrows
    public User selectOneByUsernameAndPassword(String username,String password){
        String sql = "select uID, userSex, userAge,userOccupation, userHobby, userPoint, userClass, userRegister from user where userName = ? and userPassword = ?";
        try (Connection c = DBUtil.connection()){
            try (PreparedStatement ps = c.prepareStatement(sql)){
                ps.setString(1,username);
                ps.setString(2,password);

                System.out.println("DEBUG: " + ps);
                try (ResultSet rs = ps.executeQuery()){
                    if(!rs.next()){
                        return null;
                    }

                    User user = new User();
                    user.uID = rs.getInt("uID");
                    user.username = username;
                    user.password = password;
                    user.userSex = rs.getString("userSex");
                    user.userAge = rs.getInt("userAge");
                    user.userOccupation = rs.getString("userOccupation");
                    user.userHobby = rs.getString("userHobby");
                    user.userPoint = rs.getInt("userPoint");
                    user.userClass = rs.getInt("userClass");
                    String Time = rs.getString("userRegister");
                    user.userRegister = Time.substring(0,Time.length()-5);

                    return user;
                }
            }
        }
    }

    // 查询用户名ByUid
    @SneakyThrows
    public String selectUserNameByUid(int uid){
        String sql = "select username from user where uID = ?";
        try (Connection c = DBUtil.connection()){
            try (PreparedStatement ps = c.prepareStatement(sql)){
                ps.setInt(1,uid);
                try (ResultSet rs = ps.executeQuery()){
                    if(!rs.next()){
                        return null;
                    }
                    String username = rs.getString("username");

                    return username;
                }
            }
        }
    }

    // 新建用户
    @SneakyThrows
    public User insert(String username, String password, String sex, int age, String occupation, String hobby) {
        String sql = "insert into user (username,userPassword,userSex,userAge,userOccupation,userHobby) values (?, ?, ?, ?, ?, ?)";
        try (Connection c = DBUtil.connection()){
            try (PreparedStatement ps = c.prepareStatement(sql)){
                ps.setString(1,username);
                ps.setString(2,password);
                ps.setString(3,sex);
                ps.setInt(4,age);
                ps.setString(5,occupation);
                ps.setString(6,hobby);

                ps.executeUpdate();
                System.out.println("新建用户完成");
                return new UserDao().selectOneByUsernameAndPassword(username,password);
            }
        }
    }
}

3.2 SectionDao

package forum.dao;

import forum.model.Section;
import forum.util.DBUtil;
import lombok.SneakyThrows;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * @author haomin
 * @date 2022/06/30 11:32
 **/
public class SectionDao {

    // 得到板块集合ByUid
    @SneakyThrows
    public List<Section> selectListByUid(){
        List<Section> list = new ArrayList<>();
        String sql = "select sID, uID, sName, sStatement, sClickCount, sTopicCount from section;";
        try (Connection c = DBUtil.connection()) {
            try (PreparedStatement ps = c.prepareStatement(sql)){
                System.out.println("DEBUG: " + ps);
                try (ResultSet rs = ps.executeQuery()){
                    while (rs.next()){
                        Section section = new Section();
                        section.sID = rs.getInt("sID");
                        section.uID = rs.getInt("uID");
                        section.sName = rs.getString("sName");
                        section.sStatement = rs.getString("sStatement");
                        section.sClickCount = rs.getInt("sClickCount");
                        section.sTopicCount = new TopicDao().sTopicCount(section.sID);

                        list.add(section);
                    }
                }
            }
        }
        return list;
    }

    // 得到板块集合ByKeyWord
    @SneakyThrows
    public List<Section> selectSectionListByKeyword(String keyword) {
        List<Section> list = new ArrayList<>();
        String sql = "select * from section where sName like ?;";

        System.out.println(sql);
        try (Connection c = DBUtil.connection()) {
            System.out.println(sql);

            try (PreparedStatement ps = c.prepareStatement(sql)){
                System.out.println(sql);
                String key = "%"+keyword+"%";
                ps.setString(1,key);
                System.out.println(sql);

                try (ResultSet rs = ps.executeQuery()){
                    while (rs.next()){
                        Section section = new Section();
                        section.sID = rs.getInt("sID");
                        section.uID = rs.getInt("uID");
                        section.sName = rs.getString("sName");
                        section.sStatement = rs.getString("sStatement");
                        section.sClickCount = rs.getInt("sClickCount");
                        section.sTopicCount = new TopicDao().sTopicCount(section.sID);

                        list.add(section);
                    }
                }
            }
        }
        return list;
    }

    // 更新浏览次数
    @SneakyThrows
    public void update(int sid) {
        String sql = "update section set sClickCount = sClickCount+1 where sid = ?";
        try (Connection c = DBUtil.connection()) {
            try (PreparedStatement ps = c.prepareStatement(sql)) {
                ps.setInt(1,sid);

                ps.executeUpdate();
            }
        }
    }
}

3.3 TopicDao

package forum.dao;

import forum.model.Section;
import forum.model.Topic;
import forum.model.User;
import forum.util.DBUtil;
import lombok.SneakyThrows;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * @author haomin
 * @date 2022/06/30 16:38
 **/
public class TopicDao {

    // 查询板块帖子数
    @SneakyThrows
    public int sTopicCount(Integer sID) {
        String sql = "select count(*) from topic where sID = ?";
        try (Connection c = DBUtil.connection()){
            try (PreparedStatement ps = c.prepareStatement(sql)){
                ps.setInt(1,sID);
                try (ResultSet rs = ps.executeQuery()){
                    rs.next();
                    int count = rs.getInt("count(*)");

                    updateSTopicCount(sID, count);
                    return count;
                }
            }
        }
    }

    // 更新板块帖子数
    @SneakyThrows
    public void updateSTopicCount(int sID, int count) {
        String sql = "update section set sTopicCount = ? where sID = ?";
        try (Connection c = DBUtil.connection()) {
            try (PreparedStatement ps = c.prepareStatement(sql)) {
                ps.setInt(1,count);
                ps.setInt(2,sID);

                ps.executeUpdate();
            }
        }
    }

    // 得到主贴集合BySid
    @SneakyThrows
    public List<Topic> selectListByUid(int sid){
        List<Topic> list = new ArrayList<>();
        String sql = "select tID, uID, tTopic, tContent, tTime, tReplyCount, tClickCount from topic where sID = ? order by tTime desc";
        try(Connection c = DBUtil.connection()){
            try (PreparedStatement ps = c.prepareStatement(sql)){
                ps.setInt(1,sid);
                System.out.println("DEBUG: " + ps);
                try (ResultSet rs = ps.executeQuery()){
                    while (rs.next()){
                        Topic topic = new Topic();
                        topic.tID = rs.getInt("tID");
                        topic.sID = sid;
                        topic.uID = rs.getInt("uID");
                        topic.username = new UserDao().selectUserNameByUid(topic.uID);
                        topic.tTopic = rs.getString("tTopic");
                        topic.tContent = rs.getString("tContent");
                        String Time = rs.getString("tTime");
                        topic.tTime = Time.substring(0,Time.length()-5);

                        topic.tReplyCount = new ReplyDao().tReplyCount(topic.tID);
                        topic.tClickCount = rs.getInt("tClickCount");

                        list.add(topic);
                    }
                }
            }
        }
        return list;
    }

    // 得到主贴集合ByKeyword
    @SneakyThrows
    public List<Topic> selectTopicListByKeyword(String keyword) {
        List<Topic> list = new ArrayList<>();
        String sql = "select * from topic where tTopic like ?;";

        System.out.println(sql);
        try (Connection c = DBUtil.connection()) {
            System.out.println(sql);

            try (PreparedStatement ps = c.prepareStatement(sql)){
                System.out.println(sql);
                String key = "%"+keyword+"%";
                ps.setString(1,key);
                System.out.println(sql);

                try (ResultSet rs = ps.executeQuery()){
                    while (rs.next()){
                        Topic topic = new Topic();
                        topic.tID = rs.getInt("tID");
                        topic.sID = rs.getInt("sId");
                        topic.uID = rs.getInt("uID");
                        topic.username = new UserDao().selectUserNameByUid(topic.uID);
                        topic.tTopic = rs.getString("tTopic");
                        topic.tContent = rs.getString("tContent");
                        String Time = rs.getString("tTime");
                        topic.tTime = Time.substring(0,Time.length()-5);

                        topic.tReplyCount = new ReplyDao().tReplyCount(topic.tID);
                        topic.tClickCount = rs.getInt("tClickCount");

                        list.add(topic);
                    }
                }
            }
        }

        return list;
    }

    // 查询一个主贴ByTid
    @SneakyThrows
    public Topic selectTopicByTid(int tid) {
        String sql = "select sID, uID, tTopic, tContent, tTime, tReplyCount, tClickCount from topic where tID = ?";
        try(Connection c = DBUtil.connection()){
            try (PreparedStatement ps = c.prepareStatement(sql)){
                ps.setInt(1,tid);

                System.out.println("DEBUG: " + ps);
                try (ResultSet rs = ps.executeQuery()){
                    rs.next();

                    Topic topic = new Topic();
                    topic.tID = tid;
                    topic.sID = rs.getInt("sID");
                    topic.uID = rs.getInt("uID");
                    topic.username = new UserDao().selectUserNameByUid(topic.uID);
                    topic.tTopic = rs.getString("tTopic");
                    topic.tContent = rs.getString("tContent");
                    String Time = rs.getString("tTime");
                    topic.tTime = Time.substring(0,Time.length()-5);

                    topic.tReplyCount = new ReplyDao().tReplyCount(topic.tID);
                    topic.tClickCount = rs.getInt("tClickCount");

                    return topic;
                }
            }
        }
    }

    // 插入主贴
    @SneakyThrows
    public void insert(int sid, Integer uID, String title, String content) {
        String sql = "insert into topic (sID, uID, tTopic, tContent) values (?, ?, ?, ?)";
        try (Connection c = DBUtil.connection()){
            try (PreparedStatement ps = c.prepareStatement(sql)){
                ps.setInt(1,sid);
                ps.setInt(2,uID);
                ps.setString(3,title);
                ps.setString(4,content);

                ps.executeUpdate();
                System.out.println("插入完成");
            }
        }
    }

    // 更新主贴浏览次数
    @SneakyThrows
    public void update(int tid) {
        String sql = "update topic set tClickCount = tClickCount+1 where tid = ?";
        try (Connection c = DBUtil.connection()) {
            try (PreparedStatement ps = c.prepareStatement(sql)) {
                ps.setInt(1,tid);

                ps.executeUpdate();
            }
        }
    }


}

3.4 ReplyDao

package forum.dao;

import forum.model.Reply;
import forum.util.DBUtil;
import lombok.SneakyThrows;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * @author haomin
 * @date 2022/06/30 16:38
 **/
public class ReplyDao {

    // 查询主贴回复数
    @SneakyThrows
    public int tReplyCount(int tid){
        try (Connection c = DBUtil.connection()){
            String sql = "select count(*) from reply where tID = ?;";
            try (PreparedStatement ps = c.prepareStatement(sql)){
                ps.setInt(1,tid);
                try (ResultSet rs = ps.executeQuery()){
                    rs.next();
                    int count = rs.getInt("count(*)");
                    updateTReplyCount(tid,count);
                    return count;
                }
            }
        }
    }

    // 更新主贴回复数
    @SneakyThrows
    public void updateTReplyCount(int tID, int count) {
        String sql = "update topic set tReplyCount = ? where tID = ?";
        try (Connection c = DBUtil.connection()) {
            try (PreparedStatement ps = c.prepareStatement(sql)) {
                ps.setInt(1,count);
                ps.setInt(2,tID);

                ps.executeUpdate();
            }
        }
    }

    // 根据tid查询所有回复
    @SneakyThrows
    public List<Reply> selectListByTid(int tid){
        List<Reply> list = new ArrayList<>();
        String sql = "select rID, uID, rTopic, rContent, rTime, rClickCount from reply where tid = ? order by rTime desc";
        try (Connection c = DBUtil.connection()){
            try (PreparedStatement ps = c.prepareStatement(sql)){
                ps.setInt(1,tid);
                System.out.println("DEBUG: " + ps);

                try (ResultSet rs = ps.executeQuery()){
                    while (rs.next()){
                        Reply reply = new Reply();
                        reply.rID = rs.getInt("rID");
                        reply.tID = tid;
                        reply.uID = rs.getInt("uID");
                        reply.username = new UserDao().selectUserNameByUid(reply.uID);
                        reply.rTopic = rs.getString("rTopic");
                        reply.rContent = rs.getString("rContent");
                        String Time = rs.getString("rTime");
                        reply.rTime = Time.substring(0,Time.length()-5);
                        reply.rClickCount = rs.getInt("rClickCount");

                        list.add(reply);
                    }
                }

            }
        }
        return list;
    }

    // 插入主贴
    @SneakyThrows
    public void insert(int tid, Integer uID, String content) {
        try (Connection c = DBUtil.connection()){
            String sql = "insert into reply (tID,uID,rContent) values (?,?,?)";
            try (PreparedStatement ps = c.prepareStatement(sql)){
                ps.setInt(1,tid);
                ps.setInt(2,uID);
                ps.setString(3,content);

                ps.executeUpdate();
                System.out.println("插入完成");
            }
        }
    }
}

3.5 KeyDao

package forum.dao;

import forum.model.Keyword;
import forum.util.DBUtil;
import lombok.SneakyThrows;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/**
 * @author haomin
 * @date 2022/07/04 10:11
 **/

public class KeyDao {

    // 插入查询的关键字
    @SneakyThrows
    public void insertKey (String keyword){
        String sql = "INSERT INTO `forum_management_information_system`.`key` (`keyword`) VALUES (?);";
        try (Connection c = DBUtil.connection()){
            try (PreparedStatement ps = c.prepareStatement(sql)){
                ps.setString(1,keyword);

                ps.executeUpdate();
                System.out.println("插入完成");
            }
        }
    }

    // 更新主贴回复数
    @SneakyThrows
    public void updateTReplyCount(int tID, int count) {
        String sql = "update topic set tReplyCount = ? where tID = ?";
        try (Connection c = DBUtil.connection()) {
            try (PreparedStatement ps = c.prepareStatement(sql)) {
                ps.setInt(1,count);
                ps.setInt(2,tID);

                ps.executeUpdate();
            }
        }
    }

    // 查询是否存在关键字
    @SneakyThrows
    public String selectKey () {
        String sql = "select keyword from forum_management_information_system.key;";
        try (Connection c = DBUtil.connection()){
            try (PreparedStatement ps = c.prepareStatement(sql)){
                try (ResultSet rs = ps.executeQuery()){
                    if(rs.next()){
                        String keyword = rs.getString("keyword");
                        return keyword;
                    }else {
                        return null;
                    }

                }
            }
        }
    }

    // 删除关键字
    @SneakyThrows
    public void deleteKey () {
        String sql = "DELETE FROM `forum_management_information_system`.`key` WHERE (1 = 1);";
        try (Connection c = DBUtil.connection()){
            try (PreparedStatement ps = c.prepareStatement(sql)){
                ps.executeUpdate();
            }
        }
    }
}

三. 约定前后端交互接口

0. 前端页面

先把前端页面拷贝到当前项目

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

前端页面可见于上一篇博客:《前端项目 - 论坛信息管理系统(纯页面)》

1. 实现论坛列表页

1.1约定前后端交互接口

{
  "currentUser" : {
    "uID" : 17,
    "username" : "张三",
    "password" : "123",
    "userSex" : "男",
    "userAge" : 18,
    "userOccupation" : "大数据开发工程师",
    "userHobby" : "敲代码",
    "userPoint" : 1,
    "userClass" : 1,
    "userRegister" : "2022-07-08 15:01",
    "uid" : 17
  },
  "pointCount" : 1,
  "classCount" : 1,
  "sectionList" : [ {
    "sID" : 12,
    "uID" : 1,
    "sName" : "网易云",
    "sStatement" : "小时候枕头上全是口水,长大后枕头上全是泪水;小时候微笑是一个心情,长大后微笑是一种表情;小时候哭着哭着就笑了,长大后笑着笑着就哭了。我们终于到了小时候最羡慕的年龄,但却没有成为小时候最想成为的人。——网易云音乐热评《当我已不再那么年轻》",
    "sClickCount" : 2,
    "sTopicCount" : 3,
    "uid" : 1,
    "sname" : "网易云",
    "sclickCount" : 2,
    "sstatement" : "小时候枕头上全是口水,长大后枕头上全是泪水;小时候微笑是一个心情,长大后微笑是一种表情;小时候哭着哭着就笑了,长大后笑着笑着就哭了。我们终于到了小时候最羡慕的年龄,但却没有成为小时候最想成为的人。——网易云音乐热评《当我已不再那么年轻》"
    "sid" : 12,
    "stopicCount" : 3
  }, ...]
  "topicList" : null
}

1.2 实现服务器代码

package forum.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import forum.dao.KeyDao;
import forum.model.Keyword;
import forum.model.SectionListResult;
import forum.model.User;
import forum.service.SectionService;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @author haomin
 * @date 2022/06/30 11:21
 **/

@WebServlet("/section-list.json")
public class SectionListJsonServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        User currentUser = null;
        Keyword key = null;
        System.out.println("开始");

        HttpSession session = req.getSession(false);
        if(session != null){
            currentUser = (User) session.getAttribute("currentUser");
        }
        String keyword = new KeyDao().selectKey();

        SectionService sectionService = new SectionService();
        SectionListResult result = null;
        if(keyword == null) {
            result = sectionService.sectionListResult(currentUser);
            System.out.println("执行第一个");
        }else {
            System.out.println(keyword);
            result = sectionService.sectionListResult(currentUser,keyword);
            System.out.println("执行第二个");

        }

        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = objectMapper.writeValueAsString(result);

        resp.setCharacterEncoding("utf-8");
        resp.setContentType("application/json");
        resp.getWriter().printf(jsonString);
    }
}

1.3 编写客户端代码

// 1. request /json/article_list.json
// 2. update dom tree
function renderAuthor(currentUser) {
    document.querySelector('.author-username').textContent = currentUser.username
    document.querySelector('.author-userSex').textContent = currentUser.userSex
    document.querySelector('.author-userAge').textContent = currentUser.userAge
    document.querySelector('.author-userOccupation').textContent = currentUser.userOccupation
    document.querySelector('.author-userHobby').textContent = "爱好:" + currentUser.userHobby
}

function renderCount(pointCount, classCount) {
    document.querySelector('.author-userPoint').textContent = pointCount
    document.querySelector('.author-userClass').textContent = classCount
}

function renderSectionList(sectionList, topicList) {
    console.log(sectionList)
    var container = document.querySelector('.section')
    console.log(container)

    for (var i in sectionList) {
        var section = sectionList[i]
        console.log(section)

        var html = `<li>` +
             `<div class="板块信息">` +
                ` <h3 class="板块名称">${section.sName}</h3>` +
                 `<div class="版主">版块ID: <span class="版主名称">${section.sID}</span></div>` +
                `<p class="板块说明">${section.sStatement}</p>` +

                ` <div class="点击">` +
                     `<div class="数量">` +
                        ` <div>浏览量</div>` +
                        ` <div>${section.sClickCount}</div>` +
                     `</div>` +
                     `<div>` +
                         `<div>主贴数</div>` +
                         `<div>${section.sTopicCount}</div>` +
                     `</div>` +
                 `</div>` +

                 `<div class="查看详情">` +
                     `<a href="detail.html?sid=${section.sID}" target="_self">查看详情>></a>` +
                 `</div>` +

             `</div></li>`


        container.innerHTML += html
    }
}

function renderTopicList(topicList) {
    console.log(topicList)
    var container = document.querySelector('.topic')
    console.log(container)

    for (var i in topicList) {
        var topic = topicList[i]
        console.log(topic)


        var html = `<li>` +
             `<div class="板块信息">` +
                 `<h3 class="板块名称">${topic.tTopic}</h3>` +
                ` <p class="主贴时间">${topic.tTime}</p>` +

                ` <div class="版主">贴主: <span class="版主名称">${topic.username}</span></div>` +

                ` <p class="板块说明">${topic.tContent}</p>` +

                ` <div class="点击">` +
                   `  <div class="数量">` +
                         `<div>浏览量</div>` +
                        ` <div>${topic.tClickCount}</div>` +
                     `</div>` +
                     `<div>` +
                         `<div>回复</div>` +
                         `<div>${topic.tReplyCount}</div>` +
                     `</div>` +
                ` </div>` +

                `<div class="查看回复" style="display: block; margin: 10px auto 0 auto; align-items: center;
                text-align: center;color: black;user-select: none;cursor: pointer;">` +
                  `<a href="reply.html?tid=${topic.tID}" target="_self" style="color: black;text-decoration:
                  none;font-size: 13px;">查看回复>></a>` +
                `</div>` +
             `</div></li>`


        container.innerHTML += html
    }
}

var xhr = new XMLHttpRequest()
xhr.open('get', '/section-list.json')
xhr.onload = function() {
    //alert(this.responseText);
    var data = JSON.parse(this.responseText)
    if(!data.currentUser){
        // 重定向
        // location = '/login.html'
        location.assign('/login.html')
        return
    }

    renderAuthor(data.currentUser)
    renderCount(data.pointCount, data.classCount)
    renderSectionList(data.sectionList)
    renderTopicList(data.topicList)
}
xhr.send()

实现效果:

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

2. 实现论坛主贴页

2.1约定前后端交互接口

{
  "currentUser" : {
    "uID" : 17,
    "username" : "张三",
    "password" : "123",
    "userSex" : "男",
    "userAge" : 18,
    "userOccupation" : "大数据开发工程师",
    "userHobby" : "敲代码",
    "userPoint" : 1,
    "userClass" : 1,
    "userRegister" : "2022-07-08 15:01",
    "uid" : 17
  },
  "pointCount" : 1,
  "classCount" : 1,
  "topicList" : [ {
    "tID" : 16,
    "sID" : 12,
    "uID" : 11,
    "username" : "管理员",
    "tTopic" : "窃取天上三分景",
    "tContent" : "小狐狸想去人间很久了,临行之前,她的姥姥赠她了一件宝物芙蓉面。 小狐狸得了这芙蓉面,欢喜极了,她摸了摸芙蓉面道:“姥姥,我得了芙蓉面也能行走人世吗?” “是啊,只要你戴上芙蓉面,这世上任何人的脸,都可以幻化,可你是妖,就算有了芙蓉面,也得学世人的姿态。” 小狐狸拿着芙蓉面思索半天,",
    "tTime" : "2022-07-08 13:50",
    "tReplyCount" : 4,
    "tClickCount" : 4,
    "uid" : 11,
    "treplyCount" : 4,
    "tclickCount" : 4,
    "ttime" : "2022-07-08 13:50",
    "tid" : 16,
    "tcontent" : "小狐狸想去人间很久了,临行之前,她的姥姥赠她了一件宝物芙蓉面。 小狐狸得了这芙蓉面,欢喜极了,她摸了摸芙蓉面道:“姥姥,我得了芙蓉面也能行走人世吗?” “是啊,只要你戴上芙蓉面,这世上任何人的脸,都可以幻化,可你是妖,就算有了芙蓉面,也得学世人的姿态。” 小狐狸拿着芙蓉面思索半天,",
    "ttopic" : "窃取天上三分景",
    "sid" : 12
  },...]
}

2.2 实现服务器代码

package forum.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import forum.dao.KeyDao;
import forum.model.Keyword;
import forum.model.SectionListResult;
import forum.model.User;
import forum.service.SectionService;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @author haomin
 * @date 2022/06/30 11:21
 **/

@WebServlet("/section-list.json")
public class SectionListJsonServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        User currentUser = null;
        Keyword key = null;
        System.out.println("开始");

        HttpSession session = req.getSession(false);
        if(session != null){
            currentUser = (User) session.getAttribute("currentUser");
        }
        String keyword = new KeyDao().selectKey();

        SectionService sectionService = new SectionService();
        SectionListResult result = null;
        if(keyword == null) {
            result = sectionService.sectionListResult(currentUser);
            System.out.println("执行第一个");
        }else {
            System.out.println(keyword);
            result = sectionService.sectionListResult(currentUser,keyword);
            System.out.println("执行第二个");

        }

        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(result);

        resp.setCharacterEncoding("utf-8");
        resp.setContentType("application/json");
        resp.getWriter().printf(jsonString);
    }
}

2.3 编写客户端代码

// 1. request /json/article_list.json
// 2. update dom tree
function renderAuthor(currentUser) {
    document.querySelector('.author-username').textContent = currentUser.username
    document.querySelector('.author-userSex').textContent = currentUser.userSex
    document.querySelector('.author-userAge').textContent = currentUser.userAge
    document.querySelector('.author-userOccupation').textContent = currentUser.userOccupation
    document.querySelector('.author-userHobby').textContent = "爱好:" + currentUser.userHobby
}

function renderCount(pointCount, classCount) {
    document.querySelector('.author-userPoint').textContent = pointCount
    document.querySelector('.author-userClass').textContent = classCount
}

function renderTopicList(topicList) {
    console.log(topicList)
    var container = document.querySelector('.topic')
    console.log(container)

    for (var i in topicList) {
        var topic = topicList[i]
        console.log(topic)


        var html = `<li>` +
             `<div class="板块信息">` +
                 `<h3 class="板块名称">${topic.tTopic}</h3>` +
                ` <p class="主贴时间">${topic.tTime}</p>` +

                ` <div class="版主">贴主: <span class="版主名称">${topic.username}</span></div>` +

                ` <p class="板块说明">${topic.tContent}</p>` +

                ` <div class="点击">` +
                   `  <div class="数量">` +
                         `<div>浏览量</div>` +
                        ` <div>${topic.tClickCount}</div>` +
                     `</div>` +
                     `<div>` +
                         `<div>回复</div>` +
                         `<div>${topic.tReplyCount}</div>` +
                     `</div>` +
                ` </div>` +

                `<div class="查看回复" style="display: block; margin: 10px auto 0 auto; align-items: center;
                text-align: center;color: black;user-select: none;cursor: pointer;">` +
                  `<a href="reply.html?tid=${topic.tID}" target="_self" style="color: black;text-decoration:
                  none;font-size: 13px;">查看回复>></a>` +
                `</div>` +
             `</div></li>`


        container.innerHTML += html
    }
}

var xhr = new XMLHttpRequest()
xhr.open('get', '/topic-list.json' + location.search)

xhr.onload = function() {
    // 打印 json内容
    alert(this.responseText);
    console.log(this.responseText)
    var data = JSON.parse(this.responseText)
    if(!data.currentUser){
        // 重定向
        // location = '/login.html'
        location.assign('/login.html')
        return
    }

    renderAuthor(data.currentUser)
    renderCount(data.pointCount, data.classCount)
    renderTopicList(data.topicList)

}
xhr.send()

实现效果:

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

3. 实现论坛回复页

3.1约定前后端交互接口

{
  "currentUser" : {
    "uID" : 17,
    "username" : "张三",
    "password" : "123",
    "userSex" : "男",
    "userAge" : 18,
    "userOccupation" : "大数据开发工程师",
    "userHobby" : "敲代码",
    "userPoint" : 1,
    "userClass" : 1,
    "userRegister" : "2022-07-08 15:01",
    "uid" : 17
  },
  "pointCount" : 1,
  "classCount" : 1,
  "replyList" : [ {
    "rID" : 39,
    "tID" : 16,
    "uID" : 17,
    "username" : "张三",
    "rTopic" : "回帖",
    "rContent" : "hello word",
    "rTime" : "2022-07-08 15:04",
    "rClickCount" : 0
  }, {
    "rID" : 32,
    "tID" : 16,
    "uID" : 11,
    "username" : "管理员",
    "rTopic" : "回帖",
    "rContent" : "有些人为了上前排连尊严都不要了,您怎么看呢?父亲?",
    "rTime" : "2022-07-08 13:54",
    "rClickCount" : 0
  }],
  "tid" : 16,
  "topic" : {
    "tID" : 16,
    "sID" : 12,
    "uID" : 11,
    "username" : "管理员",
    "tTopic" : "窃取天上三分景",
    "tContent" : "小狐狸想去人间很久了,临行之前,她的姥姥赠她了一件宝物芙蓉面。 小狐狸得了这芙蓉面,欢喜极了,她摸了摸芙蓉面道:“姥姥,我得了芙蓉面也能行走人世吗?” “是啊,只要你戴上芙蓉面,这世上任何人的脸,都可以幻化,可你是妖,就算有了芙蓉面,也得学世人的姿态。” 小狐狸拿着芙蓉面思索半天,",
    "tTime" : "2022-07-08 13:50",
    "tReplyCount" : 4,
    "tClickCount" : 6,
    "uid" : 11,
    "treplyCount" : 4,
    "tclickCount" : 6,
    "ttime" : "2022-07-08 13:50",
    "tid" : 16,
    "tcontent" : "小狐狸想去人间很久了,临行之前,她的姥姥赠她了一件宝物芙蓉面。 小狐狸得了这芙蓉面,欢喜极了,她摸了摸芙蓉面道:“姥姥,我得了芙蓉面也能行走人世吗?” “是啊,只要你戴上芙蓉面,这世上任何人的脸,都可以幻化,可你是妖,就算有了芙蓉面,也得学世人的姿态。” 小狐狸拿着芙蓉面思索半天,",
    "ttopic" : "窃取天上三分景",
    "sid" : 12
  }
}

3.2 实现服务器代码

package forum.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import forum.dao.TopicDao;
import forum.model.ReplyListResult;
import forum.model.User;
import forum.service.ReplyService;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @author haomin
 * @date 2022/07/01 17:05
 **/

@WebServlet("/reply-list.json")
public class ReplyListServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String tidString = req.getParameter("tid");
        int tid = Integer.parseInt(tidString);

        User currentUser = null;
        HttpSession session = req.getSession(false);
        if(session != null){
            currentUser = (User)session.getAttribute("currentUser");
        }

        // 浏览一次回帖页面,浏览次数加1
        new TopicDao().update(tid);

        ReplyService replyService = new ReplyService();
        ReplyListResult result = replyService.replyListResult(currentUser,tid);
        result.tid = tid;


        ObjectMapper objectMapper = new ObjectMapper();
        String jsonString = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(result);

        resp.setCharacterEncoding("utf-8");
        resp.setContentType("application/json");
        resp.getWriter().println(jsonString);
    }
}

3.3 编写客户端代码

function renderAuthor(currentUser) {
    document.querySelector('.author-username').textContent = currentUser.username
    document.querySelector('.author-userSex').textContent = currentUser.userSex
    document.querySelector('.author-userAge').textContent = currentUser.userAge
    document.querySelector('.author-userOccupation').textContent = currentUser.userOccupation
    document.querySelector('.author-userHobby').textContent = "爱好:" + currentUser.userHobby
}

function renderCount(pointCount, classCount) {
    document.querySelector('.author-userPoint').textContent = pointCount
    document.querySelector('.author-userClass').textContent = classCount
}

function renderDefineTid(tid){
    document.querySelector('.tid').value = tid;
}

function renderReplyList(topic,replyList){
    console.log(replyList)
    var container = document.querySelector('.reply')
    console.log(container)

    // 主贴
    var html = `<li>` +
         `<div class="板块信息1">` +

             `<h3 class="板块名称">${topic.tTopic}</h3>` +
            ` <p class="主贴时间">${topic.tTime}</p>` +

            ` <div class="版主">贴主: <span class="版主名称">${topic.username}</span></div>` +

            ` <p class="板块说明">${topic.tContent}</p>` +

                ` <div class="点击">` +
                   `  <div class="数量">` +
                         `<div>浏览量</div>` +
                        ` <div>${topic.tClickCount}</div>` +
                     `</div>` +
                ` </div>` +

         `</div></li>`


    container.innerHTML += html


    //回帖
    for(var i in replyList){
        var reply = replyList[i]
        console.log(reply)

        var html = `<li>` +
                     `<div class="板块信息">` +
                         `<h3 class="板块名称">${reply.rTopic}</h3>` +
                        ` <p class="主贴时间">${reply.rTime}</p>` +

                        ` <div class="版主"><span class="版主名称">${reply.username}</span></div>` +
                        ` <p class="板块说明">${reply.rContent}</p>` +


                        /*` <div class="点击">` +
                           `  <div class="数量">` +
                                 `<div>点击次数</div>` +
                                ` <div>100</div>` +
                             `</div>` +
                        ` </div>` +*/
                     `</div></li>`

                container.innerHTML += html
    }
}

var xhr = new XMLHttpRequest()
xhr.open('get','/reply-list.json' + location.search)

xhr.onload = function() {
    //alert(this.responseText);
    console.log(this.responseText)
    var data = JSON.parse(this.responseText)
    if(!data.currentUser){
        location.assign('/login.html')
        return
    }

    renderAuthor(data.currentUser)
    renderCount(data.pointCount, data.classCount)
    renderReplyList(data.topic,data.replyList)
    renderDefineTid(data.tid)
}
xhr.send()

实现效果:

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

4. 实现论坛个人中心页

4.1约定前后端交互接口

个人中心的json数据来自于/section-list.json

{
  "currentUser" : {
    "uID" : 17,
    "username" : "张三",
    "password" : "123",
    "userSex" : "男",
    "userAge" : 18,
    "userOccupation" : "大数据开发工程师",
    "userHobby" : "敲代码",
    "userPoint" : 1,
    "userClass" : 1,
    "userRegister" : "2022-07-08 15:01",
    "uid" : 17
  }
}

4.2 实现服务器代码

个人中心的服务器代码来自于/section-list.json,和列表页服务器代码相同,再次不在赘述。

4.3 编写客户端代码

function renderAuthor(currentUser) {
    document.querySelector('.author-username').value = currentUser.username
    document.querySelector('.author-userSex').value = currentUser.userSex
    document.querySelector('.author-userAge').value = currentUser.userAge
    document.querySelector('.author-userOccupation').value = currentUser.userOccupation
    document.querySelector('.author-userHobby').value = currentUser.userHobby
    document.querySelector('.author-userPoint').value = currentUser.userPoint
    document.querySelector('.author-userClass').value = currentUser.userClass
    document.querySelector('.author-userRegister').value = currentUser.userRegister
}

var xhr = new XMLHttpRequest()
xhr.open('get', '/section-list.json')
xhr.onload = function() {
    //alert(this.responseText);
    var data = JSON.parse(this.responseText)
    if(!data.currentUser){
        // 重定向
        // location = '/login.html'
        location.assign('/login.html')
        return
    }

    renderAuthor(data.currentUser)
}
xhr.send()

实现效果:

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

5. 实现论坛发布帖子页

5.1约定前后端交互接口

[请求] post /editor.do

5.2 实现服务器代码

package forum.servlet;

import forum.dao.TopicDao;
import forum.model.User;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @author haomin
 * @date 2022/07/01 19:30
 **/

@WebServlet("/editor.do")
public class EditorDoServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String title = req.getParameter("title");
        String sidString = req.getParameter("type");
        int sid = Integer.parseInt(sidString);
        String content = req.getParameter("editor-markdown-doc");

        User currentUser = null;
        HttpSession session = req.getSession(false);
        if (session != null) {
            currentUser = (User) session.getAttribute("currentUser");
        }

        if (currentUser == null) {
            // 说明没有登录
            resp.sendRedirect("/login.html");
            return;
        }

        TopicDao topicDao = new TopicDao();
        topicDao.insert(sid,currentUser.uID,title,content);

        // 重定向到文章详情页
        resp.sendRedirect("/detail.html?sid=" + sid);
    }
}

 5.3 编写客户端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>写帖子</title>
    <link rel="stylesheet" href="css/navigation bar.css">
    <link rel="stylesheet" href="css/editor.css">
</head>
<body>
    <div class="导航栏">
        <div class="left-logo">
            <div class="logo"><img src="img/系统图标.png" width="45"></div>
            <p>论坛管理信息系统</p>
        </div>

        <div class="占位"></div>

        <div class="right-function">
            <a href="center.html">个人中心</a>
            <a href="list.html">主页</a>
            <a href="editor.html">写帖子</a>
            <a href="logout" target="_self">注销</a>
        </div>
    </div>

    <div class="blog-edit-container">
        <form method="post" action="/editor.do">
            <div class="title">
                <input type="text" placeholder="在这里写下主贴标题" id="title" name="title">
                <input type="text" placeholder="板块编号" id="type" name="type" style="    height: 40px;
    width: 80px;

    text-indent: 10px;
    border-radius: 10px;
    outline: none;
    border: none;
    background-color:rgba(255, 255, 255, 0.8);">

                <button id="submit">发布帖子</button>
            </div>


        <div id="editor" class="编辑器"></div>
        <link rel="stylesheet" href="editor.md/css/editormd.min.css" />
        <script src="js/jquery.min.js"></script>
        <script src="editor.md/lib/marked.min.js"></script>
        <script src="editor.md/lib/prettify.min.js"></script>
        <script src="editor.md/editormd.js"></script>


        </form>
    </div>

    <script>
        var content = '# 在这里写下一篇帖子 ##';
        var config = {
            // 这里的尺寸必须在这里设置. 设置样式会被 editormd 自动覆盖掉.
            width: "100%",
            // 高度 100% 意思是和父元素一样高. 要在父元素的基础上去掉标题编辑区的高度
            height: "100vh",
            // 编辑器中的初始内容
            markdown: content,
            // 指定 editor.md 依赖的插件路径
            path: "editor.md/lib/"
        };
        editormd("editor", config);

    </script>
</body>
</html>

实现效果:

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

6. 实现论坛登录页

6.1约定前后端交互接口

[请求] post /login.do

6.2 实现服务器代码

package forum.servlet;

import forum.dao.UserDao;
import forum.model.User;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @author haomin
 * @date 2022/06/29 17:18
 **/

@WebServlet("/login.do")
public class LoginDoServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println("DEBUG: username = " + username);
        System.out.println("DEBUG: password = " + password);

        UserDao userDao = new UserDao();
        User user = userDao.selectOneByUsernameAndPassword(username,password);
        if(user == null){
            resp.sendRedirect("/login.html");
            return;
        }

        System.out.println(user);

        HttpSession session = req.getSession();
        session.setAttribute("currentUser",user);

        resp.sendRedirect("/");
    }
}

6.3 编写客户端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
    <link rel="stylesheet" href="css/navigation bar.css">
    <link rel="stylesheet" href="css/login.css">
</head>
<body>

    <div class="导航栏">
        <div class="left-logo">
            <div class="logo"><img src="img/系统图标.png" width="45"></div>
            <p>论坛管理信息系统</p>
        </div>

        <div class="占位"></div>

        <div class="right-function">
            <span class="center"></span>
            <a href="list.html">主页</a>
            <a href="editor.html" target="_blank">写帖子</a>
            <a href="logon.html">注册</a>
        </div>
    </div>

    <div class="主体区">
        <div class="登录框">
            <form action="/login.do" method="post">
                <h2>登录</h2>
                <div>
                    <span>用户名</span>
                    <input type="text" class="text" name="username" placeholder="请输入用户名">
                </div>
                <div>
                    <span>密码</span>
                    <input type="password" class="text" name="password" placeholder="请输入密码">
                </div>
                <div>
                    <button class="提交">登录</button>
                </div>
            </form>
        </div>
    </div>

</body>
</html>

 实现效果:

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

7. 实现论坛注册页

7.1约定前后端交互接口

[请求] post /logon.do

7.2 实现服务器代码

package forum.servlet;

import forum.dao.UserDao;
import forum.model.User;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @author haomin
 * @date 2022/07/03 08:34
 **/
@WebServlet("/logon.do")
public class LogonDoServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        String username = req.getParameter("username");
        String sex = req.getParameter("sex");
        String age = req.getParameter("age");
        String occupation = req.getParameter("occupation");
        String hobby = req.getParameter("hobby");
        String password1 = req.getParameter("password1");
        String password2 = req.getParameter("password2");

        UserDao userDao = new UserDao();
        User user = userDao.insert(username,password1,sex,Integer.parseInt(password1),occupation,hobby);

        HttpSession session = req.getSession();
        session.setAttribute("currentUser",user);

        resp.sendRedirect("/");

    }
}

7.3 编写客户端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
    <link rel="stylesheet" href="css/navigation bar.css">
    <link rel="stylesheet" href="css/logon.css">
</head>
<body>

    <div class="导航栏">
        <div class="left-logo">
            <div class="logo"><img src="img/系统图标.png" width="45"></div>
            <p>论坛管理信息系统</p>
        </div>

        <div class="占位"></div>

        <div class="right-function">
            <span class="center"></span>
            <a href="list.html">主页</a>
            <a href="editor.html" target="_blank">写帖子</a>
            <a href="login.html">登录</a>
        </div>
    </div>

    <div class="主体区">
        <div class="注册框">
            <form action="/logon.do" method="post">
                <h2>注册</h2>
                <div>
                    <span>昵称</span>
                    <input type="text" class="text" placeholder="请输入昵称" name="username">
                </div>
                <div>
                    <span>年龄</span>
                    <input type="text" class="text" placeholder="请输入年龄" name="age">
                </div>
                <div>
                    <span>性别</span>
                    <input type="text" class="text" placeholder="请输入性别  男|女" name="sex">

                </div>
                <div>
                    <span>爱好</span>
                    <input type="text" class="text" placeholder="请输入爱好" name="hobby">
                </div>
                <div>
                    <span>职业</span>
                    <input type="text" class="text" placeholder="请输入职业" name="occupation">
                </div>
<!--                <div>-->
<!--                    <span>Email</span>-->
<!--                    <input type="text" class="text" placeholder="请输入Email" name="email">-->
<!--                </div>-->
                <div>
                    <span>密码</span>
                    <input type="password" class="text" placeholder="请输入密码" name="password1">
                </div>
                <div>
                    <span>再次确认密码</span>
                    <input type="password" class="text" placeholder="请再次确认密码" name="password2">
                </div>
                <div>
                    <button class="提交">注册</button>
                </div>
            </form>
        </div>
    </div>

</body>
</html>

实现效果:

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

8. 实现论坛注销

8.1实现服务器代码

package forum.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession(false);
        if (session != null) {
            session.removeAttribute("currentUser");
        }

        resp.sendRedirect("/");
    }
}
package forum.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author haomin
 * @date 2022/06/30 08:43
 **/

@WebServlet("")
public class IndexServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect("/list.html");
    }
}

重定向到论坛主页,但是服务器发现没有用户登录,继而重定向到用户登录页。

实现效果:

论坛管理系统,项目,前端,javascript,服务器,后端,tomcat

 论坛信息管理系统主要重点就介绍到这里了,如果想看看项目源码,可以点击这里:《论坛信息管理系统》

如果你喜欢这篇文章,请点赞加关注吧,或者如果你对与文章有什么困惑,可以私信我。

🏓🏓🏓 文章来源地址https://www.toymoban.com/news/detail-777240.html

到了这里,关于前端+后端项目 - 论坛信息管理系统(Web+servlet+MySQL+JDBC)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 从零开始搭建后端信息管理系统(新手小白比如)

    如果你是新手小白,首先我们要进行一些准备工作,安装一些基础软件, 备注一下:这里安装的vue环境的后台管理系统,不同的后台管理系统,需要安装不同的插件 准备工作: 安装 Visual Studio Code nodejs 配置插件    首先安装开发环境Visual Studio Code 打开官网:下载 Visual Stu

    2024年04月11日
    浏览(61)
  • 数据库管理系统(基于前端+后端+数据库)

      库存管理系统 包括模块: (1)基本信息管理。 (2)商品入库管理。 (3)商品出库管理。 (4)商品查询管理。 (5)查看商品目录。 实训步骤: 开发环境:html , css , js , python,Mysql,pycharm 需求分析: 和其他数据库系统相比, MySQL 有点与众不同,它的架构可以在多种

    2024年02月04日
    浏览(69)
  • 课程项目设计--项目建立--宿舍管理系统--springboot后端

    前要 项目设计–宿舍管理系统 太长了,修改一下 暂时先加上下面依赖,还有的话以后在看 application.yml application-dev.yml 新加一个handler包,用于像mybatis自动填充的处理配置 具体配置mybaits-plus配置 注解 插件bean 这里先只配置分页插件 自动填充bean 这里有2种写法,注释掉的是低

    2024年02月12日
    浏览(42)
  • Spring Boot后端与Vue前端融合:构建高效旅游管理系统

    作者介绍: ✌️大厂全栈码农|毕设实战开发,专注于大学生项目实战开发、讲解和毕业答疑辅导。 🍅 获取源码联系方式请查看文末 🍅  推荐订阅精彩专栏 👇🏻 避免错过下次更新 Springboot项目精选实战案例 更多项目: CSDN主页YAML墨韵 学如逆水行舟,不进则退。学习如赶

    2024年04月28日
    浏览(58)
  • 学生信息管理系统MIS(前端)

    改造HTML文件 创建css文件,提取css代码 创建HTML网页文件 创建css文件

    2024年02月10日
    浏览(42)
  • 【UniApp开发小程序】私聊功能后端实现 (买家、卖家 沟通商品信息)【后端基于若依管理系统开发】

    本文提炼于个人练手项目,其中的实现逻辑不一定标准,实现思路没有参考权威的文档和教程,仅为个人思考得出,因此可能存在较多本人未考虑到的情况和漏洞,因此仅供参考,如果大家觉得有问题,恳请大家指出有问题的地方 如果对客户端的实现感兴趣,可以转身查看【

    2024年02月11日
    浏览(46)
  • 信息系统项目管理师-项目沟通管理

    1.信息系统项目管理师-项目整合管理 2.信息系统项目管理师-项目范围管理 3.信息系统项目管理师-项目进度管理 4.信息系统项目管理师-项目成本管理 5.信息系统项目管理师-项目质量管理 6.信息系统项目管理师-项目资源管理 7.信息系统项目管理师-项目沟通管理 8.信息系统项目

    2023年04月16日
    浏览(78)
  • 信息系统项目管理师:配置管理

    配置管理指的是在一个系统或软件中对配置项的管理,包括对配置项的定义、存储、跟踪和修改等一系列活动。配置项可以是硬件设备、软件组件、系统设置、网络配置等,配置管理旨在确保在不同时间点或环境下系统或软件的配置项的正确性和一致性。通过配置管理,可以

    2024年02月16日
    浏览(63)
  • 毕业设计So Easy:SpringBoot+Vue图书阅读和管理系统(前端+后端+小程序端)

    目录 1、项目概述 2、开发环境 3、前后端配置部署 4、小程序端配置部署 5、项目效果演示 5.1、后端管理平台 5.2、前端阅读平台 5.3、小程序社区平台 很多计算机专业大学生经常和我交流:毕业设计没思路、不会做、论文不会写、太难了...... 针对这些问题,决定分享一些软、

    2024年02月11日
    浏览(49)
  • 【软考高级信息系统项目管理师--第八章:项目整合管理】

    🚀 作者 :“码上有前” 🚀 文章简介 :软考高级–信息系统项目管理师 🚀 欢迎小伙伴们 点赞👍、收藏⭐、留言💬 1、资源分配; 2、平衡竞争性需求; 3、研究各种备选方法; 4、裁减过程以实现各种方法; 5、管理各个项目管理知识领域之间的依赖关系。 编写一份正式批准项

    2024年02月19日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包