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="#">«</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="#">»</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
三、小结
整个项目开发流程:
从数据库设计------->后端环境搭建----------->前端环境搭建---------->打包部署