当前位置: 首页 > news >正文

javaweb小项目

一、软件开发流程

  • 需求分析:设计、UI设计、架构设计
  • 开发:前端开发、后端开发
  • 测试:功能测试、性能测试、安全测试
  • 上线:预发布环境、灰度(部分用户试用功能期间)、全量(对所有用户都开放)
  • 多次迭代更新

二、具体过程

1.E-R图设计

E-R图:实体关系图,是一种通过提供实体、属性和联系的方法来描述现实世界的概念模型。

实体:现实世界中的对象,ER图中用矩形表示,矩形框内写明实体名。

属性:实体所具有的某一个特性,ER图中用椭圆形或圆角矩形表示,并用无向边与相应的实体连接。

关系:实体之间的联系,主要有3种类型:一对一联系,一对多联系,多对多联系;ER图中用菱形表示,菱形框内写明联系名,并用无向边与有关实体连接。

以下是该项目的E-R图:

2.数据库设计 

# ************************************************************
# Sequel Pro SQL dump
# Version 4541
#
# http://www.sequelpro.com/
# https://github.com/sequelpro/sequelpro
#
# Host: 127.0.0.1 (MySQL 5.7.12)
# Database: forum
# Generation Time: 2020-06-03 14:00:53 +0000
# ************************************************************


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;


# Dump of table category
# ------------------------------------------------------------

DROP DATABASE IF EXISTS xd_forum ;
CREATE DATABASE xd_forum CHARACTER SET utf8;
use xd_forum ;
SET FOREIGN_KEY_CHECKS=0;

DROP TABLE IF EXISTS `category`;

CREATE TABLE `category` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(128) DEFAULT NULL COMMENT '分类名称',
  `weight` int(11) DEFAULT NULL COMMENT '权重,数字越大权重越高',
  `create_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

LOCK TABLES `category` WRITE;
/*!40000 ALTER TABLE `category` DISABLE KEYS */;

INSERT INTO `category` (`id`, `name`, `weight`, `create_time`)
VALUES
	(1,'黑客和画家',432,'2021-01-01 09:00:00'),
	(2,'前端生活',23,'2021-01-01 09:00:00'),
	(3,'人工智能',342,'2021-01-01 09:00:00'),
	(4,'自动化测试',44,'2021-01-01 09:00:00'),
	(5,'大数据',4,'2021-01-01 09:00:00'),
	(6,'Java进阶',3213,'2021-01-01 09:00:00'),
	(7,'网络安全',3231,'2021-01-01 09:00:00'),
	(8,'后端架构',32431,'2021-01-01 09:00:00');

/*!40000 ALTER TABLE `category` ENABLE KEYS */;
UNLOCK TABLES;


# Dump of table reply
# ------------------------------------------------------------

DROP TABLE IF EXISTS `reply`;

CREATE TABLE `reply` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `topic_id` int(11) DEFAULT NULL,
  `floor` int(11) DEFAULT NULL COMMENT '楼层编号,回复是不能删除的',
  `content` varchar(524) DEFAULT NULL COMMENT '回复内容',
  `user_id` int(11) DEFAULT NULL,
  `username` varchar(64) DEFAULT NULL COMMENT '回复人名称',
  `user_img` varchar(128) DEFAULT NULL COMMENT '回复人头像',
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  `delete` int(11) DEFAULT NULL COMMENT '0是正常,1是禁用',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

LOCK TABLES `reply` WRITE;
/*!40000 ALTER TABLE `reply` DISABLE KEYS */;

INSERT INTO `reply` (`id`, `topic_id`, `floor`, `content`, `user_id`, `username`, `user_img`, `create_time`, `update_time`, `delete`)
VALUES
	(24,22,1,'你以后面试说你5年经验,加班加的',17,'Anna小姐姐','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/14.jpeg','2020-06-03 21:21:31','2020-06-03 21:21:31',0),
	(25,22,2,'身体重要啊,少撸管',17,'张飞','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/13.jpeg','2020-06-03 21:22:44','2020-06-03 21:22:44',0),
	(26,22,3,'加班努力付出',17,'刘备','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/15.jpeg','2020-06-03 21:22:44','2020-06-03 21:22:44',0),
	(27,22,4,'重新找过,年轻怕啥',17,'关羽','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/12.jpeg','2020-06-03 21:22:44','2020-06-03 21:22:44',0),
	(28,22,5,'给多少钱你就去了?',17,'吕布','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/12.jpeg','2020-06-03 21:22:44','2020-06-03 21:22:44',0),
	(29,22,6,'重新找过,年轻怕啥',17,'关羽','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/12.jpeg','2020-06-03 21:22:44','2020-06-03 21:22:44',0),
	(30,22,7,'来我这边把,大量招聘',17,'曹操','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/12.jpeg','2020-06-03 21:22:44','2020-06-03 21:22:44',0),
	(31,21,8,'真逗啊,你这样发问题',17,'曹操','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/12.jpeg','2020-06-03 21:22:44','2020-06-03 21:22:44',0),
	(32,22,8,'加班多久呢? 我这边也加班',18,'大当家','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/13.jpeg','2020-06-03 21:38:23','2020-06-03 21:38:23',0),
	(33,22,9,'66666',18,'大当家','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/13.jpeg','2020-06-03 21:39:13','2020-06-03 21:39:13',0),
	(34,36,1,'我这边买了很多小滴课堂,有没交流群',18,'大当家','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/13.jpeg','2020-06-03 21:40:23','2020-06-03 21:40:23',0);

/*!40000 ALTER TABLE `reply` ENABLE KEYS */;
UNLOCK TABLES;


# Dump of table topic
# ------------------------------------------------------------

DROP TABLE IF EXISTS `topic`;

CREATE TABLE `topic` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `c_id` int(11) DEFAULT NULL COMMENT '分类',
  `title` varchar(128) DEFAULT NULL COMMENT '标题',
  `content` varchar(1024) DEFAULT NULL COMMENT '内容',
  `pv` int(11) DEFAULT NULL COMMENT '浏览量',
  `user_id` int(11) DEFAULT NULL,
  `username` varchar(64) DEFAULT NULL,
  `user_img` varchar(128) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  `hot` int(2) DEFAULT '0' COMMENT '是否热门 1是热门',
  `delete` int(11) DEFAULT '0' COMMENT '0是未删除,1是已经删除',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

LOCK TABLES `topic` WRITE;
/*!40000 ALTER TABLE `topic` DISABLE KEYS */;

INSERT INTO `topic` (`id`, `c_id`, `title`, `content`, `pv`, `user_id`, `username`, `user_img`, `create_time`, `update_time`, `hot`, `delete`)
VALUES
	(20,1,'我是传统IT公司,想转行互联网公司怎么办?','以前是传统IT公司,想转行互联网公司怎么办?谁可以告诉我',3,17,'Anna小姐姐','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/14.jpeg','2020-06-03 21:09:52','2020-06-03 21:09:52',0,0),
	(21,1,'DDOS流量攻击怎么防止','网络带宽被别人占据了,没法上网',44,1,'二当家小D','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/13.jpeg','2020-06-03 21:09:52','2020-06-03 21:09:52',0,0),
	(22,1,'你对加班的是怎么看的?','自己也会合理评估工作,提高个人工作效率',6,17,'刘备','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/14.jpeg','2020-06-03 21:09:52','2020-06-03 21:09:52',0,0),
	(23,1,'被压在五指山上了咋办','我被别人压在五指山上了,怎么救我,我免费教你打怪',32,17,'孙悟空','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/16.jpeg','2020-06-03 21:09:52','2020-06-03 21:09:52',0,0),
	(24,6,'拿到面试通知,互联网公司都有多轮面试,怎么准备','谁有简历模板',33,4,'小明','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/12.jpeg','2020-06-03 21:09:52','2020-06-03 21:09:52',0,0),
	(25,1,'社招流程是怎么样的','明天要参加社招,流程是咋样的',42,4,'中山大学-西欧','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/12.jpeg','2020-06-03 21:09:52','2020-06-03 21:09:52',0,0),
	(26,6,'技术现场面试','如果同城一般直接现场面试吗',32,4,'路飞','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/12.jpeg','2020-06-03 21:09:52','2020-06-03 21:09:52',0,0),
	(27,6,'网站被人挖矿了怎么办','电脑被人安装挖矿程序了,谁知道怎么解决啊',2,17,'张飞','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/16.jpeg','2020-06-03 21:09:52','2020-06-03 21:09:52',0,0),
	(28,1,'被压在五指山上了咋办','我被别人压在五指山上了,怎么救我,我免费教你打怪',32,17,'隔壁老王','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/17.jpeg','2020-06-03 21:09:52','2020-06-03 21:09:52',0,0),
	(29,1,'要求有3年经验,可是我只有1~2年怎么办?','只能靠加班吗',32,4,'雅力士','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/12.jpeg','2020-06-03 21:09:52','2020-06-03 21:09:52',0,0),
	(30,6,'内推的岗位多种,实习和非实习(正式工作)','谁可以帮我内推',33,4,'小明','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/12.jpeg','2020-06-03 21:09:52','2020-06-03 21:09:52',0,0),
	(31,6,'要有礼貌,保持头脑清晰','要有礼貌,保持头脑清晰有帮助吗',33,4,'小明','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/12.jpeg','2020-06-03 21:09:52','2020-06-03 21:09:52',0,0),
	(32,1,'为什么说会被技术官完虐,怎样避免','校招+社招考查点很多,记不住',3,17,'刘冰','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/15.jpeg','2020-06-03 21:09:52','2020-06-03 21:09:52',0,0),
	(33,1,'为什么从上个公司离职?','不能说不好的,比如公司混乱、勾心斗角、负面情',3,17,'还珠格格','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/12.jpeg','2020-06-03 21:09:52','2020-06-03 21:09:52',0,0),
	(34,6,'做下简单的自我介绍?','尽量介绍和专业相关的,毕业、工作经历等',33,4,'小明','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/12.jpeg','2020-06-03 21:09:52','2020-06-03 21:09:52',0,0),
	(35,1,'要求本科,但我是大专学历不符合怎么办?','大专学历不符合怎么办?',3,17,'关羽','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/12.jpeg','2020-06-03 21:09:52','2020-06-03 21:09:52',0,0),
	(36,1,'我这边想学javaweb课程','谁有教程,我看小滴课堂有很多,谁买了',2,18,'大当家','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/13.jpeg','2020-06-03 21:39:52','2020-06-03 21:39:52',0,0),
	(37,3,'正确实现用 spring 扫描自定义的 annotation','我要学习',1,17,'Anna小姐姐','https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/14.jpeg','2020-06-03 21:55:11','2020-06-03 21:55:11',0,0);

/*!40000 ALTER TABLE `topic` ENABLE KEYS */;
UNLOCK TABLES;


# Dump of table user
# ------------------------------------------------------------

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `phone` varchar(32) DEFAULT NULL,
  `pwd` varchar(128) DEFAULT NULL,
  `sex` int(2) DEFAULT NULL COMMENT '0是女,1是男,2未知',
  `img` varchar(128) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `role` int(11) DEFAULT NULL COMMENT '1是普通用户,2是管理员',
  `username` varchar(128) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `phone` (`phone`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

LOCK TABLES `user` WRITE;
/*!40000 ALTER TABLE `user` DISABLE KEYS */;

INSERT INTO `user` (`id`, `phone`, `pwd`, `sex`, `img`, `create_time`, `role`, `username`)
VALUES
	(15,'123','202CB962AC59075B964B07152D234B70',2,'https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/14.jpeg','2020-06-03 21:07:59',1,'二当家小D'),
	(16,'23432','202CB962AC59075B964B07152D234B70',1,'https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/11.jpeg','2020-06-03 21:08:24',1,'小滴课堂-老王'),
	(17,'111','202CB962AC59075B964B07152D234B70',2,'https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/14.jpeg','2020-06-03 21:08:48',1,'Anna小姐姐'),
	(18,'888','202CB962AC59075B964B07152D234B70',1,'https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/13.jpeg','2020-06-03 21:37:52',1,'大当家');

/*!40000 ALTER TABLE `user` ENABLE KEYS */;
UNLOCK TABLES;



/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

3.创建项目环境

创建maven项目

设置java根目录

配置tomcat

在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>net.xdclass</groupId>
  <artifactId>xd_forum</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>xd_forum Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>

<!--单元测试-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>


    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>


<!--mysql驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.41</version>
    </dependency>

    <!-- JSP -->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.2</version>
      <scope>provided</scope>
    </dependency>


    <!--工具类: https://mvnrepository.com/artifact/commons-dbutils/commons-dbutils -->
    <dependency>
      <groupId>commons-dbutils</groupId>
      <artifactId>commons-dbutils</artifactId>
      <version>1.7</version>
    </dependency>

    <!--数据库连接池:https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-dbcp2</artifactId>
      <version>2.7.0</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
    <dependency>
      <groupId>commons-beanutils</groupId>
      <artifactId>commons-beanutils</artifactId>
      <version>1.9.4</version>
    </dependency>





    <!-- https://mvnrepository.com/artifact/taglibs/standard -->
    <dependency>
      <groupId>taglibs</groupId>
      <artifactId>standard</artifactId>
      <version>1.1.2</version>
    </dependency>


    <!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>


  </dependencies>

  <build>

    <!--专门用于打包配置文件到类路径-->
    <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.properties</include>
          <include>**/*.xml</include>
        </includes>
        <filtering>true</filtering>
      </resource>
    </resources>



    <finalName>xd_forum</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>

创建包结构

常见的src目录结构

controller 存放控制器;service 存放业务接口;impl 存放业务接口或数据访问接口实现类;

dao 存放数据访问接口;domain 存放实体类;util 存放工具类;listener 存放监听器

filter 存放过滤器;config 存放配置

4.开发实体类

即开发domain层,根据数据库表结构创建实体类,alt+insert可生成getter与setter方法

Category类

package net.xdclass.forum.domain;


import java.util.Date;

public class Category {

    private int id;
    private String name;

    private int weight;

    private Date createTime;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    @Override
    public String toString() {
        return "Category{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", weight=" + weight +
                ", createTime=" + createTime +
                '}';
    }
}

Reply类

package net.xdclass.forum.domain;

import java.util.Date;

/*
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `topic_id` int(11) DEFAULT NULL,
  `floor` int(11) DEFAULT NULL COMMENT '楼层编号,回复是不能删除的',
  `content` varchar(524) DEFAULT NULL COMMENT '回复内容',
  `user_id` int(11) DEFAULT NULL,
  `username` varchar(64) DEFAULT NULL COMMENT '回复人名称',
  `user_img` varchar(128) DEFAULT NULL COMMENT '回复人头像',
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  `delete` int(11) DEFAULT NULL COMMENT '0是正常,1是禁用',

 */
public class Reply {

    private int id;
    private int topicId;

    private int floor;

    private String content;

    private int userId;

    private String username;

    private String userImg;

    private Date createTime;

    private Date updateTime;

    private int delete;

    @Override
    public String toString() {
        return "Reply{" +
                "id=" + id +
                ", topicId=" + topicId +
                ", floor=" + floor +
                ", content='" + content + '\'' +
                ", userId=" + userId +
                ", username='" + username + '\'' +
                ", userImg='" + userImg + '\'' +
                ", createTime=" + createTime +
                ", updateTime=" + updateTime +
                ", delete=" + delete +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getTopicId() {
        return topicId;
    }

    public void setTopicId(int topicId) {
        this.topicId = topicId;
    }

    public int getFloor() {
        return floor;
    }

    public void setFloor(int floor) {
        this.floor = floor;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getUserImg() {
        return userImg;
    }

    public void setUserImg(String userImg) {
        this.userImg = userImg;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    public int getDelete() {
        return delete;
    }

    public void setDelete(int delete) {
        this.delete = delete;
    }
}

Topic类

package net.xdclass.forum.domain;

import java.util.Date;

/*

CREATE TABLE `topic` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `c_id` int(11) DEFAULT NULL COMMENT '分类',
  `title` varchar(128) DEFAULT NULL COMMENT '标题',
  `content` varchar(1024) DEFAULT NULL COMMENT '内容',
  `pv` int(11) DEFAULT NULL COMMENT '浏览量',
  `user_id` int(11) DEFAULT NULL,
  `username` varchar(64) DEFAULT NULL,
  `user_img` varchar(128) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  `hot` int(2) DEFAULT '0' COMMENT '是否热门 1是热门',
  `delete` int(11) DEFAULT '0' COMMENT '0是未删除,1是已经删除',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

 */
public class Topic {


    private int id;

    private int cId;

    private String title;

    private String content;

    private int pv;


    private int userId;

    private String username;

    private String userImg;

    private Date createTime;

    private Date updateTime;

    private int hot;

    private int delete;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getcId() {
        return cId;
    }

    public void setcId(int cId) {
        this.cId = cId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public int getPv() {
        return pv;
    }

    public void setPv(int pv) {
        this.pv = pv;
    }

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getUserImg() {
        return userImg;
    }

    public void setUserImg(String userImg) {
        this.userImg = userImg;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    public int getHot() {
        return hot;
    }

    public void setHot(int hot) {
        this.hot = hot;
    }

    public int getDelete() {
        return delete;
    }

    public void setDelete(int delete) {
        this.delete = delete;
    }

    @Override
    public String toString() {
        return "Topic{" +
                "id=" + id +
                ", cId=" + cId +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", pv=" + pv +
                ", userId=" + userId +
                ", username='" + username + '\'' +
                ", userImg='" + userImg + '\'' +
                ", createTime=" + createTime +
                ", updateTime=" + updateTime +
                ", hot=" + hot +
                ", delete=" + delete +
                '}';
    }
}

User 类

package net.xdclass.forum.domain;


import java.util.Date;

/**
 * 小滴课堂 开发者论坛  user类
 * @Author 二当家小D
 *
 */
public class User {


    private int id;

    private String phone;

    private String pwd;

    private int sex;

    private String img;

    private Date createTime;

    private int role;

    private String username;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public int getSex() {
        return sex;
    }

    public void setSex(int sex) {
        this.sex = sex;
    }

    public String getImg() {
        return img;
    }

    public void setImg(String img) {
        this.img = img;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public int getRole() {
        return role;
    }

    public void setRole(int role) {
        this.role = role;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", phone='" + phone + '\'' +
                ", pwd='" + pwd + '\'' +
                ", sex=" + sex +
                ", img='" + img + '\'' +
                ", createTime=" + createTime +
                ", role=" + role +
                ", username='" + username + '\'' +
                '}';
    }
}

 5.开发工具类

  • 配置数据连接池工具

database.properties中配置

driverClassName = com.mysql.jdbc.Driver
url = jdbc:mysql://127.0.0.1:3306/forum?useUnicode=true&characterEncoding=utf-8&useSSL=false
username = root
password = xdclass.net
initialSize=10
maxActive=30

 DataSourceUtil类

package net.xdclass.forum.util;

import org.apache.commons.dbcp2.BasicDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.util.Properties;

/**
 * 数据库连接池工具类
 */
public class DataSourceUtil {


    private static DataSource dataSource;



    static {

        try{

            InputStream in = DataSourceUtil.class.getClassLoader().getResourceAsStream("database.properties");
            Properties p = new Properties();
            p.load(in);
            dataSource = BasicDataSourceFactory.createDataSource(p);
        }catch (Exception e){
            e.printStackTrace();
            throw new ExceptionInInitializerError("初始化DBPC失败");
        }
    }


    /**
     * 获取连接池
     * @return
     */
    public static DataSource getDataSource(){
        return dataSource;
    }



}
  • 配置加密工具
package net.xdclass.forum.util;

import java.security.MessageDigest;

//MD5加密工具类
public class CommonUtil {

    public static String MD5(String data)  {
        try {
            java.security.MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] array = md.digest(data.getBytes("UTF-8"));
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
            }
            return sb.toString().toUpperCase();
        } catch (Exception exception) {
        }
        return null;
    }
}

6.开发业务逻辑

Controller层

编写servlet代码:编写通用servlet(BaseServlet,即父类servlet),当子类的Servlet被访问,会调用service方法,若子类没有重写,那么就会调用父类service方法,这样可以简化在每个子类Servlet中重写doget、dopost方法的麻烦。

 BaseServlet方法

package net.xdclass.forum.controller;

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;
import java.lang.reflect.Method;

@WebServlet(name = "BaseServlet")
public class BaseServlet extends HttpServlet {


    /**
     * 子类的Servlet被访问,会调用service方法,子类没有重写,那么就会调用父类service方法
     *
     * @param req
     * @param resp
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        req.setCharacterEncoding("UTF-8");

        //获取请求方法
        String method = req.getParameter("method");

        if(method!=null){
            try{
                //获得当前被访问对象的字节码对象,和字节码对象里面指定的方法
                Method targetMethod = this.getClass().getMethod(method,HttpServletRequest.class,HttpServletResponse.class);

                //执行对应的方法:this相当于子类servlet,targetMethod是子类的方法
                targetMethod.invoke(this,req,resp);

            }catch (Exception e){
                e.printStackTrace();
            }


        }
    }
}

子类CategoryServlet中的方法要通过service层来实现

package net.xdclass.forum.controller;

import net.xdclass.forum.domain.Category;
import net.xdclass.forum.service.CategoryService;
import net.xdclass.forum.service.impl.CategoryServiceImpl;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;


@WebServlet(name = "categoryServlet",urlPatterns = {"/category"})
public class CategoryServlet extends BaseServlet {


    private CategoryService categoryService = new CategoryServiceImpl();


    /**
     * 返回全部分类
     * http://localhost:8080/category?method=list
     */
    public void list(HttpServletRequest request, HttpServletResponse response){

        List<Category> list =  categoryService.list();

        System.out.println(list.toString());

       //将查询结果存入request对象中,前端页面发送请求时就可获取数据
        request.setAttribute("caregoryList",list);


    }



}

 前端页面可访问caregoryList获取list中的Category信息,

同理,前端可通过pageContext.request.contextPath来获取上下文路径,并拼接servlet的urlPattern指定访问方法将数据提交给对应的controller类。

service层

service层要通过Dao层来实现

service接口:CategoryService

package net.xdclass.forum.service;

import net.xdclass.forum.domain.Category;

import java.util.List;

public interface CategoryService {

    /**
     * 全部分类
     * @return
     */
    List<Category> list();

}

接口对应的实现类:CategoryServiceImpl

package net.xdclass.forum.service.impl;

import net.xdclass.forum.dao.CategoryDao;
import net.xdclass.forum.domain.Category;
import net.xdclass.forum.service.CategoryService;

import java.util.List;

public class CategoryServiceImpl implements CategoryService {

    
    //实例化dao对象,对象的调用方法来获取数据库中的数据
    private CategoryDao categoryDao = new CategoryDao();

    @Override
    public List<Category> list() {
        return categoryDao.list();
    }
}

dao层

CategoryDao类

package net.xdclass.forum.dao;

import net.xdclass.forum.domain.Category;
import net.xdclass.forum.util.DataSourceUtil;
import org.apache.commons.dbutils.*;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.sql.SQLException;
import java.util.List;

public class CategoryDao {


    //通过数据库连接池工具类来,获取queryRunner对象
    private QueryRunner queryRunner = new QueryRunner(DataSourceUtil.getDataSource());

    //开启驼峰映射:将数据库中的下划线命名的字段,映射为驼峰命名的属性
    private BeanProcessor beanProcessor = new GenerousBeanProcessor();
    private RowProcessor processor = new BasicRowProcessor(beanProcessor);


    /**
     * 根据id找分类
     * @param id
     * @return
     */
    public Category findById(int id){
        
        //编写sql语句
        String sql = "select * from category where id=?";

        //实例化category对象来接收查询结果
        Category category = null;
        try {
            //执行sql语句:BeanHandler将查询结果映射为对象,processor开启驼峰映射,id为占位符的值
             category  = queryRunner.query(sql,new BeanHandler<>(Category.class,processor),id);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return category;//返回查询结果

    }


    /**
     * 返回分类列表
     * @return
     */
    public List<Category> list(){

        String sql = "select * from category order by weight desc";

        List<Category> list  = null;
        try {
            list  = queryRunner.query(sql,new BeanListHandler<>(Category.class,processor));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list;

    }




}

 7.具体业务模块

开发分页模块

PageDTO:存放分页信息

package net.xdclass.forum.dto;

import java.util.List;

/**
 * 泛型
 * 分页对象
 */

//数据传输对象
public class PageDTO<T> {//存放分页信息


    /**
     * 当前页码
     */
    private int pageNumber;


    /**
     * 每页显示的记录数
     */
    private int pageSize;

    /**
     * 总条数
     */
    private int totalRecord;


    /**
     * 总页数
     */
    private int totalPage;

    /**
     * 数据集合
     */
    private List<T> list;




    public PageDTO(int pageNumber, int pageSize, int totalRecord){//更新分页信息

        this.pageNumber = pageNumber;
        this.pageSize = pageSize;

        this.totalRecord = totalRecord;

        //计算总页数
        if( totalRecord % pageSize == 0){

            totalPage = totalRecord/pageSize;

        }else {
            totalPage = totalRecord/pageSize + 1;
        }

    }




    public int getPageNumber() {
        return pageNumber;
    }

    public void setPageNumber(int pageNumber) {
        this.pageNumber = pageNumber;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public int getTotalRecord() {
        return totalRecord;
    }

    public void setTotalRecord(int totalRecord) {
        this.totalRecord = totalRecord;
    }

    public int getTotalPage() {
        return totalPage;
    }

    public void setTotalPage(int totalPage) {
        this.totalPage = totalPage;
    }

    public List<T> getList() {
        return list;
    }

    public void setList(List<T> list) {
        this.list = list;
    }

    @Override
    public String toString() {
        return "PageDTO{" +
                "pageNumber=" + pageNumber +
                ", pageSize=" + pageSize +
                ", totalRecord=" + totalRecord +
                ", totalPage=" + totalPage +
                ", list=" + list +
                '}';
    }
}

servlet层开发:TopicServlet页面

package net.xdclass.forum.controller;


import net.xdclass.forum.domain.Reply;
import net.xdclass.forum.domain.Topic;
import net.xdclass.forum.domain.User;
import net.xdclass.forum.dto.PageDTO;
import net.xdclass.forum.service.CategoryService;
import net.xdclass.forum.service.TopicService;
import net.xdclass.forum.service.impl.CategoryServiceImpl;
import net.xdclass.forum.service.impl.TopicServiceImpl;

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

@WebServlet(name = "topicServlet",urlPatterns = {"/topic"})
public class TopicServlet extends BaseServlet {



    private TopicService topicService = new TopicServiceImpl();


    private CategoryService categoryService = new CategoryServiceImpl();

    /**
     * 默认分页大小
     */
    private static final int pageSize = 5;

    /**
     * http://localhost:8080/topic?method=list&c_id=2&page=2
     *
     * topic分页接口
     * @param request
     * @param response
     */
    public void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //获取并更新分页信息
        int cId = Integer.parseInt(request.getParameter("c_id"));//前端传过来的信息

        //默认第一页
        int page=1;

        String currentPage = request.getParameter("page");

        if(currentPage !=null && currentPage !=""){
            page = Integer.parseInt(currentPage);
        }



        //获取分页数据:通过调用service层实现的业务方法来实现
        PageDTO<Topic> pageDTO =  topicService.listTopicPageByCid(cId,page,pageSize);

        System.out.println(pageDTO.toString());


        //更新数据
        request.getSession().setAttribute("categoryList",categoryService.list());

        request.setAttribute("topicPage" ,pageDTO);

        //将数据转发给index.jsp页面
        request.getRequestDispatcher("/index.jsp").forward(request,response);

    }

        //获得topic分页数据:通过调用service层实现的业务方法来实现
        Topic topic = topicService.findById(topicId);

        PageDTO<Reply> pageDTO =  topicService.findReplyPageByTopicId(topicId,page,pageSize);


        System.out.println(pageDTO.toString());

         //更新数据
        request.setAttribute("topic" ,topic);
        request.setAttribute("replyPage",pageDTO);

         //将数据转发给topic_detail.jsp页面
        request.getRequestDispatcher("/topic_detail.jsp").forward(request,response);
    }
}

service层:在接口编写业务逻辑,在实现类中实现业务逻辑

TopicService接口

package net.xdclass.forum.service;


import net.xdclass.forum.domain.Reply;
import net.xdclass.forum.domain.Topic;
import net.xdclass.forum.domain.User;
import net.xdclass.forum.dto.PageDTO;

public interface TopicService  {//在接口编写业务逻辑,在实现类中实现业务逻辑


    //分页查询
    PageDTO<Topic> listTopicPageByCid(int cId, int page, int pageSize);

    //根据id查询
    Topic findById(int topicId);
}

 TopicServiceImpl实现类:通过dao层的方法来获取数据库中的数据

package net.xdclass.forum.service.impl;

import net.xdclass.forum.dao.CategoryDao;
import net.xdclass.forum.dao.ReplyDao;
import net.xdclass.forum.dao.TopicDao;
import net.xdclass.forum.domain.Category;
import net.xdclass.forum.domain.Reply;
import net.xdclass.forum.domain.Topic;
import net.xdclass.forum.domain.User;
import net.xdclass.forum.dto.PageDTO;
import net.xdclass.forum.service.TopicService;

import java.util.Date;
import java.util.List;

public class TopicServiceImpl implements TopicService {
//实现具体的业务逻辑


    //实例化dao对象,调用对象的方法来获取数据库中的数据
    private TopicDao topicDao = new TopicDao();

    private ReplyDao replyDao = new ReplyDao();

    private CategoryDao categoryDao = new CategoryDao();

    @Override
    public PageDTO<Topic> listTopicPageByCid(int cId, int page, int pageSize) {

        //查询总记录数
        int totalRecordNum = topicDao.countTotalTopicByCid(cId);

        int from = (page-1) * pageSize;//起始位置

        //分页查询
        List<Topic> topicList =  topicDao.findListByCid(cId,from,pageSize);

        PageDTO<Topic> pageDTO = new PageDTO<>(page,pageSize,totalRecordNum);

        pageDTO.setList(topicList);

        return pageDTO;
    }

    @Override
    public Topic findById(int topicId) {

        return topicDao.findById(topicId);
    }

    @Override
    public PageDTO<Reply> findReplyPageByTopicId(int topicId, int page, int pageSize) {

        //查询总的回复
        int totalRecordNum = replyDao.countTotalReplyByCid(topicId);

        int from = (page-1) * pageSize;//设置起始位置

        //分页查询
        List<Reply> replyList =  replyDao.findListByTopicId(topicId,from,pageSize);

        PageDTO<Reply> pageDTO = new PageDTO<>(page,pageSize,totalRecordNum);

        pageDTO.setList(replyList);

        return pageDTO;

    }

}

dao层:

package net.xdclass.forum.dao;

import net.xdclass.forum.domain.Topic;
import net.xdclass.forum.util.DataSourceUtil;
import org.apache.commons.dbutils.*;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.sql.SQLException;
import java.util.List;

public class TopicDao {


    //由数据库连接池获取实例化queryRunner对象
    private QueryRunner queryRunner = new QueryRunner(DataSourceUtil.getDataSource());

    //开启驼峰映射:数据库字段和java属性的映射,实现数据库字段的下划线会被去掉,并且首字母大写
    private BeanProcessor beanProcessor = new GenerousBeanProcessor();
    private RowProcessor processor = new BasicRowProcessor(beanProcessor);


    /**
     * 根据cid查询总行数
     * @param cId
     * @return
     */
    public int countTotalTopicByCid(int cId) {

        //
        String sql = "select count(*) from topic where c_id=? and `delete`=0";
        Long count = null;
        try {
             count =  (Long)queryRunner.query(sql,new ScalarHandler<>(),cId);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return count.intValue();
    }


    /**
     * 分页查询
     * @param cId
     * @param from
     * @param pageSize
     * @return
     */
    public List<Topic> findListByCid(int cId, int from, int pageSize) {

        String sql = "select * from topic where c_id=? and `delete`=0 order by update_time desc limit ?,?";

        List<Topic> list = null;
        try{
            //查询结果集:BeanListHandler 结果集映射成一个对象的集合,processor:开启驼峰映射,cId:占位符的值,from:起始位置,pageSize:每页的记录数
            list = queryRunner.query(sql,new BeanListHandler<>(Topic.class,processor),cId,from,pageSize);
        }catch (Exception e){
            e.printStackTrace();
        }

        return list;
    }


    public Topic findById(int topicId) {

        String sql = "select * from topic where id = ?";

        Topic topic = null;

        try{

            topic = queryRunner.query(sql,new BeanHandler<>(Topic.class,processor),topicId);

        }catch (Exception e){
            e.printStackTrace();
        }
        return  topic;

    }
}

登录注册模块

  • service接口
package net.xdclass.forum.service;

import net.xdclass.forum.domain.User;

public interface UserService {

    int register(User user);

    User login(String phone, String pwd);
}
  • 接口实现类
package net.xdclass.forum.service.impl;

import net.xdclass.forum.dao.UserDao;
import net.xdclass.forum.domain.User;
import net.xdclass.forum.service.UserService;
import net.xdclass.forum.util.CommonUtil;

import java.util.Date;
import java.util.Random;

public class UserServiceImpl implements UserService {

    private UserDao userDao = new UserDao();



    @Override
    public int register(User user) {

        user.setRole(1);
        user.setCreateTime(new Date());
        user.setImg(getRandomImg());

        user.setPwd( CommonUtil.MD5(user.getPwd()) );//加密

        try {
           return userDao.save(user);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return 0;
    }

    @Override
    public User login(String phone, String pwd) {

        String md5pwd = CommonUtil.MD5(pwd);

        User user = userDao.findByPhoneAndPwd(phone,md5pwd);

        return user;
    }


    /**
     * 放在CDN上的随机头像
     */
    private static final String [] headImg = {
            "https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/12.jpeg",
            "https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/11.jpeg",
            "https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/13.jpeg",
            "https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/14.jpeg",
            "https://xd-video-pc-img.oss-cn-beijing.aliyuncs.com/xdclass_pro/default/head_img/15.jpeg"
    };

    private String getRandomImg(){
        int size =  headImg.length;
        Random random = new Random();
        int index = random.nextInt(size);
        return headImg[index];
    }
}
  • 数据库访问接口dao层
package net.xdclass.forum.dao;

import net.xdclass.forum.domain.User;
import net.xdclass.forum.util.DataSourceUtil;
import org.apache.commons.dbutils.*;
import org.apache.commons.dbutils.handlers.BeanHandler;

public class UserDao {


    private QueryRunner queryRunner = new QueryRunner(DataSourceUtil.getDataSource());

    //开启驼峰映射
    private BeanProcessor beanProcessor = new GenerousBeanProcessor();
    private RowProcessor processor = new BasicRowProcessor(beanProcessor);


    public int save(User user) throws Exception {

        String sql = "insert into user (phone,pwd,sex,img,create_time,role,username) values(?,?,?,?,?,?,?)";
        Object[] params = {
          user.getPhone(),user.getPwd(),user.getSex(),user.getImg(),user.getCreateTime(),user.getRole(),user.getUsername()
        };

        int i ;
        try{
            i = queryRunner.update(sql,params);
        }catch (Exception e){
            e.printStackTrace();
            throw new Exception();
        }
        return i;
    }


    public User findByPhoneAndPwd(String phone, String md5pwd) {

        String sql = "select * from user where phone=? and pwd=?";

        User user = null;

        try{

            user = queryRunner.query(sql,new BeanHandler<>(User.class,processor),phone,md5pwd);

        }catch (Exception e){
            e.printStackTrace();
        }

        return user;
    }
}
  • servlet控制层

获得前端提交的数据,并实现页面跳转 

package net.xdclass.forum.controller;

import net.xdclass.forum.domain.User;
import net.xdclass.forum.service.UserService;
import net.xdclass.forum.service.impl.UserServiceImpl;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

@WebServlet(name = "userServlet",urlPatterns = {"/user"})
public class UserServlet extends BaseServlet {


    private UserService userService = new UserServiceImpl();


    /**
     *
     * http://localhost:8080/user?method=login
     *
     * @param request
     * @param response
     */
    public void login(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException {

        String phone = request.getParameter("phone");
        String pwd = request.getParameter("pwd");

        User user = userService.login(phone,pwd);

        if(user != null){

            request.getSession().setAttribute("loginUser",user);
            //跳转页面
            response.sendRedirect("/topic?method=list&c_id=1");

        }else {

            request.setAttribute("msg","用户名或者密码不正确");
            request.getRequestDispatcher("/user/login.jsp").forward(request,response);

        }

    }


    /**
     *  http://localhost:8080/user?method=logout
     * 退出登录
     * @param request
     * @param response
     */
    public void  logout(HttpServletRequest request,HttpServletResponse response) throws IOException {

        request.getSession().invalidate();

        response.sendRedirect("/topic?method=list&c_id=1");
    }






    /**
     * http://localhost:8080/user?method=register
     * @param request
     * @param response
     */
    public void register(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        User user = new User();

        Map<String,String[]> map = request.getParameterMap();

        try {
            BeanUtils.populate(user,map);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        int i = userService.register(user);

        if(i>0){
            //注册成功,跳转到登录界面
            request.getRequestDispatcher("/user/login.jsp").forward(request,response);
        }else {
            //注册失败,跳转到注册页面
            request.getRequestDispatcher("/user/register.jsp").forward(request,response);
        }


    }

}

 获取全部分类

  •  service接口
package net.xdclass.forum.service;

import net.xdclass.forum.domain.Category;

import java.util.List;

public interface CategoryService {

    /**
     * 全部分类
     * @return
     */
    List<Category> list();

}
  • 接口对应的实现类
package net.xdclass.forum.service.impl;

import net.xdclass.forum.dao.CategoryDao;
import net.xdclass.forum.domain.Category;
import net.xdclass.forum.service.CategoryService;

import java.util.List;

public class CategoryServiceImpl implements CategoryService {


    //实例化dao对象,对象的调用方法来获取数据库中的数据
    private CategoryDao categoryDao = new CategoryDao();

    @Override
    public List<Category> list() {
        return categoryDao.list();
    }
}
  • 数据库访问接口
package net.xdclass.forum.dao;

import net.xdclass.forum.domain.Category;
import net.xdclass.forum.util.DataSourceUtil;
import org.apache.commons.dbutils.*;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.sql.SQLException;
import java.util.List;

public class CategoryDao {


    //通过数据库连接池工具类来,获取queryRunner对象
    private QueryRunner queryRunner = new QueryRunner(DataSourceUtil.getDataSource());

    //开启驼峰映射:将数据库中的下划线命名的字段,映射为驼峰命名的属性
    private BeanProcessor beanProcessor = new GenerousBeanProcessor();
    private RowProcessor processor = new BasicRowProcessor(beanProcessor);



    /**
     * 返回分类列表
     * @return
     */
    public List<Category> list(){

        String sql = "select * from category order by weight desc";

        List<Category> list  = null;
        try {
            list  = queryRunner.query(sql,new BeanListHandler<>(Category.class,processor));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return list;

    }




}
  • 控制层

将查询数据存入请求中,供前端使用

package net.xdclass.forum.controller;

import net.xdclass.forum.domain.Category;
import net.xdclass.forum.service.CategoryService;
import net.xdclass.forum.service.impl.CategoryServiceImpl;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;


@WebServlet(name = "categoryServlet",urlPatterns = {"/category"})
public class CategoryServlet extends BaseServlet {


    private CategoryService categoryService = new CategoryServiceImpl();


    /**
     * 返回全部分类
     * http://localhost:8080/category?method=list
     */
    public void list(HttpServletRequest request, HttpServletResponse response){

        List<Category> list =  categoryService.list();

        System.out.println(list.toString());

        //将查询结果存入request对象中,前端页面发送请求时就可获取数据
        request.setAttribute("caregoryList",list);


    }



}

其它功能模块也同理开发。

8.前端页面部署

环境部署 

前端页面技术 bootstrap + jsp,参考地址:Bootstrap中文网

  • 项目结构

 去官网添加js与css依赖

  • 前端页面基础

引用样式文件和响应式布局

<%--声明相关的引入--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
<head>
    <title>开发者论坛</title>

    <meta name="viewport" content="width=device-width, initial-scale=1">

<%-- contextPath获取当前web应用的上下文路径,用于动态生成url资源访问路径--%>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/static/bootstrap.min.css">

    <script src="${pageContext.request.contextPath}/static/bootstrap.min.js"></script>

    <script src="${pageContext.request.contextPath}/static/jquery.min.js"></script>

</head>
  • pom.xml文件添加
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
     <groupId>taglibs</groupId>
     <artifactId>standard</artifactId>
     <version>1.1.2</version>
</dependency>
​
​
<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>
  •  在web.xml文件中修改版本
<web-app  version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

 前端页面开发

前端样式可去Bootstrap官网复制,项目结构:

主题列表开发

 index.jsp

<%--导航栏:将分类信息遍历显示--%>
    <ul class="nav nav-tabs">
     <c:forEach items="${categoryList}" var="category">
        <li>
            <a href="${pageContext.request.contextPath}/topic?method=list&c_id=${category.id}"> ${category.name}</a>
        </li>
     </c:forEach>


<%-- 注册登录页面跳转--%>
        <c:choose>
            <c:when test="${empty loginUser}">
                <li style="float: right"> <a href="${pageContext.request.contextPath}/user/register.jsp"> 注册</a> </li>
                <li style="float: right"> <a href="${pageContext.request.contextPath}/user/login.jsp"> 登录</a> </li>
            </c:when>

<%-- 登录成功页面跳转 --%>
            <c:otherwise>
                <li style="float: right"> <a href="${pageContext.request.contextPath}/user?method=logout">注销</a> </li>

                <li style="float: right"> <a href="#">${loginUser.username}</a> </li>

                <li style="float: right"> 
                    <img src="${loginUser.img}" class="img-circle" width="25px" height="25px" style="margin-top: 8.5px">
                </li>

                <li style="float: right"> <a href="${pageContext.request.contextPath}/publish.jsp">发布主题</a> </li>
            </c:otherwise>
        </c:choose>
    </ul>

通过后端传入请求中的数据信息,实现前端数据展示

通过动态生成url路径执行对应方法或者跳转对应页面

效果图

index.js内容详情展示

<table class="table table-striped">

        <thead>
        <tr>
            <th>标题</th>
            <th>内容</th>
            <th>作者</th>
            <th>发布时间</th>
            <th>操作</th>

        </tr>
        </thead>

        <tbody>
        <c:forEach items="${topicPage.list}" var="topic">

            <tr>
                <td>${topic.title}</td>
                <td>${topic.content}</td>
                <td>${topic.username}</td>
                <td>${topic.createTime}</td>
                <td>
                    <a href="${pageContext.request.contextPath}/topic?method=findDetailById&topic_id=${topic.id}" >详情</a>
                </td>

            </tr>
        </c:forEach>
        </tbody>

    </table>

    <ul class="pagination">

        <li><a href="#">&laquo;</a> </li>

        <c:if test="${topicPage.totalPage>0}">

            <c:forEach var="i" begin="0" end="${topicPage.totalPage-1}" step="1">
                <li>
                    <a href="${pageContext.request.contextPath}/topic?method=list&c_id=${param.c_id}&page=${i+1}">${i+1} </a>
                </li>
            </c:forEach>

        </c:if>


        <li><a href="#">&raquo;</a> </li>

    </ul>

 效果

登录前

登录后 

登录页面

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
<head>
    <title>小滴课堂开发者论坛</title>

    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" href="${pageContext.request.contextPath}/static/bootstrap.min.css">

    <script src="${pageContext.request.contextPath}/static/bootstrap.min.js"></script>

    <script src="${pageContext.request.contextPath}/static/jquery.min.js"></script>

</head>
<body>

<%--头部目录--%>
<div class="container">
    <ul class="nav nav-tabs">
        <c:forEach items="${categoryList}" var="category">
            <li>
                <a href="${pageContext.request.contextPath}/topic?method=list&c_id=${category.id}">${category.name}</a>
            </li>
        </c:forEach>
    </ul>
</div>




<div style="margin-top: 100px">

    <form class="form-horizontal" role="form" action="/user?method=login" method="post">




        <div class="form-group">
            <label class="col-sm-2 control-label">手机号</label>
            <div class="col-lg-3">
                <input type="text" class="form-control" name="phone" placeholder="手机号">
            </div>
        </div>



        <div class="form-group">
            <label class="col-sm-2 control-label">密码</label>
            <div class="col-lg-3">
                <input type="password" class="form-control" name="pwd"
                       placeholder="密码">
            </div>
        </div>



        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                <button type="submit" class="btn btn-default">登录</button>
            </div>
        </div>



        <div class="form-group">
            <div class="col-lg-3">
                ${msg}
            </div>
        </div>

    </form>



</div>




</body>
</html>

其他页面也同理,实现数据传递与跳转。 

9.项目部署

项目打包

maven实现:在terminal中输入mvn install

部署到外部tomcat

可参考博文

https://blog.csdn.net/2301_76371717/article/details/146506397?spm=1001.2014.3001.5501

 三、小结

整个项目开发流程:

从数据库设计------->后端环境搭建----------->前端环境搭建---------->打包部署

http://www.dtcms.com/a/105128.html

相关文章:

  • 贡献法(C++)
  • w2ui 水平滚动移动 虚拟列 数据丢失
  • 建筑长明灯、长流水成难题?楼宇自控系统来破局
  • forms实现贪吃蛇
  • Python打包大模型文件以及使用Docker进行运行镜像
  • 六、Linux系统 DRM调试工具modetest
  • 【C++】vector的模拟实现和相关接口介绍
  • 通过通道扩展实现 NI-DAQmx 的同步与触发
  • Python FastAPI + Celery + RabbitMQ 分布式图片水印处理系统
  • 软件工程-UML
  • DEBUG:工具简介
  • Python----机器学习(线性回归:自求导的方法实现)
  • Redis 的哨兵模式
  • 蓝桥杯 01游戏
  • 数据结构 哈希表 字符串哈希
  • VMware安装Ubuntu实战分享
  • 【算法学习计划】贪心算法(下)
  • 在ensp进行OSPF+RIP+静态网络架构配置
  • [GESP202503 C++六级题解]:P11963:环线
  • 关于VMware Tools 不再随旧版客户机操作系统的 VMware Workstation 一起提供。
  • 高级java每日一道面试题-2025年3月22日-微服务篇[Nacos篇]-Nacos的主要功能有哪些?
  • TBKDVR硬盘录像机device.rsp命令执行漏洞
  • CISCO路由器配置DHCP中继
  • YOLOv12即插即用-Pconv(风车卷积)
  • QT自定义信号与槽
  • NHANES指标推荐:TyG-BMI
  • 自然语言处理|如何用少样本技术提升低资源语言处理?
  • acwing 5438. 密接牛追踪2
  • MaxEnt物种分布建模全流程;R+ArcGIS+MaxEnt模型物种分布模拟、参数优化方法、结果分析制图与论文写作
  • Minimind 训练一个自己专属语言模型