1. 需求分析
本项目需要实现一个简易的博客系统,其中功能包括: 1)注册新用户 2)登陆已有用户 3)显示博客列表,包括文章的作者和文章的内容 4)点击文章就会跳转到文章详情 5)发布新博客 6)删除自己的博客
2. 数据库设计
设计当前代码中需要用到数据库的几张表,每张表上都有哪些字段,每个表之间有什么关联关系
1)提取出需求中的“实体”有哪些 【用户】【文章】 确定了有两张表:User表 和 Article表
2)确定实体需要的属性 用户:【名字,密码】 文章:【标题,内容】
3)确定实体和实体之间的关系 用户和文章应该是【一对多】的关系,在“多”的表中加上外键 (需要在user表中加入userId字段,表示身份标识 在Article表中加入一个userId字段,表示该文章是由哪个用户发的)
drop database if exists blogdemo;
create database blogdemo;
use blogdemo;
drop table if exists article;
create table user(
userId int primary key auto_increment,
name varchar(50) unique,
password varchar(50)
);
drop table if exists article;
create table article(
articleId int primary key auto_increment,
title varchar(255),
content text,
userId int ,
foreign key(userId) references user(userId)
);
创建完成的数据库如下:
3. 开始写代码
a)创建一个类来管理数据库的连接(JDBC)
package model;
//管理数据库连接
//1.建立连接
//2.断开连接
//JDBC使用DataSourcr来管理连接
//DBUtil相当于是对DataSource再稍微包装一层
//因为 DataSource 应该是每个应用程序只应该有一个实例
//DBUtil本质上就是实现了一个单例模式,管理了一个唯一的DataSource实例
//单例模式的实现,有两种风格
//1.饿汉模式
//2.懒汉模式(在这里实现的)_______主要问题:线程不安全
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class DBUtil {
private static volatile DataSource dataSource = null;
private static final String URL = "jdbc:mysql://127.0.0.1:3306/blogdome?characterEncoding=utf-8&useSSL=true";
private static final String USERNAME = "root";
private static final String PASSWORD = "09050797";
public static DataSource getDataSource(){
if (dataSource == null) {
synchronized (DBUtil.class) {
if (dataSource == null){
dataSource = new MysqlDataSource();
//需要给DataSource设置一些属性
((MysqlDataSource)dataSource).setURL(URL);
((MysqlDataSource)dataSource).setUser(USERNAME);
((MysqlDataSource)dataSource).setPassword(PASSWORD);
}
}
}
return dataSource;
}
//通过这个方法来获取连接
public static Connection getConnection(){
try {
return getDataSource().getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
//通过这个方法断开连接
public static void close(Connection connection, PreparedStatement statement,
ResultSet resultSet){
try {
if (resultSet != null){
resultSet.close();
}
if (statement != null){
statement.close();
}
if (connection != null){
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
b)创建实体类 创建一个user类和article类,这俩类的属性要和数据库结构是相关联的
package model;
public class User {
private int userId;
private String name;
private String password;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package model;
public class Article {
private int articleId;
private String title;
private String content;
private int userId;
public int getArticleId() {
return articleId;
}
public void setArticleId(int articleId) {
this.articleId = articleId;
}
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 getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
}
c)实现数据库的增删改查
package model;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
//Dao表示数据访问层
public class UserDao {
//1.新增用户(注册)
// 把一个User对象插入到数据库中
void add(User user){
//1.获取带数据库连接
Connection connection = DBUtil.getConnection();
//2.拼装sql语句
String sql = "insert into user values (null,?,?)";
PreparedStatement statement = null;
try {
statement = connection.prepareStatement(sql);
statement.setString(1,user.getName());
statement.setString(2,user.getPassword());
//3.执行sql语句
int ret = statement.executeUpdate();
if(ret != 1){
//插入失败
System.out.println("插入新用户失败!");
return;
}
System.out.println("插入新用户成功!");
} catch (SQLException e) {
e.printStackTrace();
}finally {
//4.释放数据库连接
DBUtil.close(connection,statement,null);
}
}
//2.按照名字查找(登录)
public User selectByName(String name){
//1.和数据库建立连接
Connection connection = DBUtil.getConnection();
//2.拼装SQL
String sql = "select * from user where name = ?";
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
statement = connection.prepareStatement(sql);
statement.setString(1,name);
//3.执行SQL
resultSet = statement.executeQuery();
//4.遍历结果集合
if (resultSet.next()){
User user = new User();
user.setUserId(resultSet.getInt("userId"));
user.setName(resultSet.getString("name"));
user.setPassword(resultSet.getString("password"));
return user;
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//5.释放数据库连接
DBUtil.close(connection,statement,resultSet);
}
return null;
}
}
package model;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class ArticleDao {
//1.新增文章(发布博客)
public void add(Article article){
//1.获取数据库连接
Connection connection = DBUtil.getConnection();
//2.构造sql
String sql = "insert into article value (null,?,?,?)";
PreparedStatement statement = null;
try {
statement = connection.prepareStatement(sql);
statement.setString(1,article.getTitle());
statement.setString(2,article.getContent());
statement.setInt(3,article.getUserId());
//3.执行sql
int ret = statement.executeUpdate();
if (ret != 1){
System.out.println("插入文章操作失败!");
return;
}
System.out.println("插入文章操作成功!");
} catch (SQLException e) {
e.printStackTrace();
}finally {
//4.释放连接
DBUtil.close(connection,statement,null);
}
}
//2.查看文章(把所有的文章信息都查出来)
public List<Article> selectAll(){
List<Article> articles = new ArrayList<>();
Connection connection = DBUtil.getConnection();
String sql = "select article,title,userId from article";
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
statement = connection.prepareStatement(sql);
resultSet = statement.executeQuery();
while (resultSet.next()){
Article article = new Article();
article.setArticleId(resultSet.getInt("articleId"));
article.setTitle(resultSet.getString("title"));
article.setUserId(resultSet.getInt("userId"));
articles.add(article);
}
return articles;
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(connection,statement,resultSet);
}
return null;
}
//3.查看指定的文章详情
public Article selectById(int articleId){
Connection connection = DBUtil.getConnection();
String sql = "select * from where articleId = ?";
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
statement = connection.prepareStatement(sql);
statement.setInt(1,articleId);
resultSet = statement.executeQuery();
if (resultSet.next()){
Article article = new Article();
article.setArticleId(resultSet.getInt("articleId"));
article.setTitle(resultSet.getString("title"));
article.setContent(resultSet.getString("content"));
article.setUserId(resultSet.getInt("userId"));
return article;
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(connection,statement,resultSet);
}
return null;
}
//4.删除指定文章
public void delete(int articleId){
Connection connection = DBUtil.getConnection();
String sql = "delete from article where articleId = ?";
PreparedStatement statement = null;
try {
statement = connection.prepareStatement(sql);
statement.setInt(1,articleId);
int ret = statement.executeUpdate();
if (ret != 1){
System.out.println("删除文章失败!");
return;
}
System.out.println("删除文章成功!");
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(connection,statement,null);
}
}
}
4. 前后端接口设计
5. 开始实现接口
1) 实现注册页面
register.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>注册</title>
</head>
<body>
<form action="register" method="post">
<input type="text" name="name" placeholder="请输入密码">
<br/>
<input type="text" name="password" placeholder="请输入密码">
<br/>
<input type="submit" value="注册">
</form>
</body>
</html>
RegisterServlet
package api;
import model.User;
import model.UserDao;
import view.HtmlGenerator;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RegisterServlet extends HttpServlet {
//浏览器是通过POST方法来提交数据的
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
//1.获取到前端提交的数据(用户名,密码)校验是否合法
String name = req.getParameter("name");
String password = req.getParameter("password");
if(name == null || "".equals(name)||password==null||"".equals(password)){
String html = HtmlGenerator.getMessagePage("用户名或者密码为空","register.html");
resp.getWriter().write(html);
return;
}
//2.拿着用户名在数据库中查一下,看看当前用户是否已经存在,如果存在,认为注册失败
UserDao userDao = new UserDao();
User existUser = userDao.selectByName(name);
if (existUser != null){
//说明已经存在,提示用户注册失败,用户名重复
String html = HtmlGenerator.getMessagePage("用户名重复!请换个名字!","register.html");
resp.getWriter().write(html);
return;
}
//3.根据前端提交的数据构造user对象,并插入到数据库中
User user = new User();
user.setName(name);
user.setPassword(password);
userDao.add(user);
//4.返回一个结果页面,提示当前注册成功
String html = HtmlGenerator.getMessagePage("注册成功!点击这里跳转到登陆页面!","login.html");
resp.getWriter().write(html);
}
}
HtmlGenerator
package view;
public class HtmlGenerator {
//通过字符串拼接的形式,构造出来HTML格式出来
public static String getMessagePage(String message, String nextUrl) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<html>");
stringBuilder.append("<head>");
stringBuilder.append("<meta charset=\"utf-8\">");
stringBuilder.append("<title>提示页面</title>");
stringBuilder.append("</head>");
stringBuilder.append("<body>");
stringBuilder.append("<h3>");
stringBuilder.append(message);
stringBuilder.append("</h3>");
stringBuilder.append(String.format("<a href=\"%s\"> 点击这里跳转 </a>",nextUrl));
stringBuilder.append("</body>");
stringBuilder.append("</html>");
return stringBuilder.toString();
}
}
配置web.xml文件
2) 实现登录功能
login.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>登录</title>
</head>
<body>
<form action="login" method="post">
<input type="text" name="name" placeholder="请输入用户名">
<br/>
<input type="password" name="password" placeholder="请输入密码">
<br/>
<input type="submit" value="登录">
</form>
</body>
</html>
loginServlet
package api;
import model.User;
import model.UserDao;
import view.HtmlGenerator;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class loginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
//1.获取到用户名和密码,并进行简单的校验
String name = req.getParameter("name");
String password = req.getParameter("password");
if (name == null || "".equals(name) || password==null || "".equals(password)){
String html = HtmlGenerator.getMessagePage("用户名或密码为空","login.html");
resp.getWriter().write(html);
return;
}
//2.数据库中查找,看看用户是否存在
//3.对比密码是否匹配
UserDao userDao = new UserDao();
User user = userDao.selectByName(name);
if (user==null || !password.equals(user.getPassword())){
//用户名不存在
String html = HtmlGenerator.getMessagePage("用户名或密码错误","login.html");
resp.getWriter().write(html);
return;
}
//4.匹配成功则认为登陆成功,创建一个session
HttpSession httpSession = req.getSession(true);
httpSession.setAttribute("user",user);
//5.返回一个登陆成功的页面
String html = HtmlGenerator.getMessagePage("登陆成功","article");
resp.getWriter().write(html);
}
}
3) 实现文章功能
ArticleServlet
package api;
import model.Article;
import model.ArticleDao;
import model.User;
import model.UserDao;
import view.HtmlGenerator;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;
public class ArticleServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
//1.验证用户是否已经登陆了,如果尚未登陆提示用户登录
HttpSession httpSession = req.getSession(false);
if (httpSession == null){
//当前是未登录状态
String html = HtmlGenerator.getMessagePage("请先登录","login.html");
resp.getWriter().write(html);
return;
}
User user = (User)httpSession.getAttribute("user");
//2.判断请求中是否存在articleId参数
String articleIdStr = req.getParameter("articleId");
if (articleIdStr == null){
//a)没有这个参数就去执行获取文章列表的操作
getAllArticle(user, resp);
}else {
//b)有这个参数就去执行获取文章详情的操作
getOneArticle(Integer.parseInt(articleIdStr),user,resp);
}
}
private void getOneArticle(int articleId, User user, HttpServletResponse resp) throws IOException {
//1.查找数据库
ArticleDao articleDao = new ArticleDao();
Article article = articleDao.selectById(articleId);
if (article == null){
//文章未找到
String html = HtmlGenerator.getMessagePage("文章不存在","article");
resp.getWriter().write(html);
return;
}
//根据作者ID。找到作者信息,进一步得到作者姓名
UserDao userDao = new UserDao();
User author = userDao.selectById(article.getUserId());
//2.构造页面
String html = HtmlGenerator.getArticleDetailPage(article,user,author);
resp.getWriter().write(html);
}
private void getAllArticle(User user, HttpServletResponse resp) throws IOException {
//1.查找数据库
ArticleDao articleDao = new ArticleDao();
List<Article> articles = articleDao.selectAll();
//2.构造页面
String html = HtmlGenerator.getArticleListPage(articles, user);
resp.getWriter().write(html);
}
}
HtmlGenerator
package view;
import model.Article;
import model.User;
import java.util.List;
public class HtmlGenerator {
//通过字符串拼接的形式,构造出来HTML格式出来
public static String getMessagePage(String message, String nextUrl) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<html>");
stringBuilder.append("<head>");
stringBuilder.append("<meta charset=\"utf-8\">");
stringBuilder.append("<title>提示页面</title>");
stringBuilder.append("</head>");
stringBuilder.append("<body>");
stringBuilder.append("<h3>");
stringBuilder.append(message);
stringBuilder.append("</h3>");
stringBuilder.append(String.format("<a href=\"%s\"> 点击这里跳转 </a>",nextUrl));
stringBuilder.append("</body>");
stringBuilder.append("</html>");
return stringBuilder.toString();
}
public static String getArticleListPage(List<Article> articles, User user) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<html>");
stringBuilder.append("<head>");
stringBuilder.append("<meta charset=\"utf-8\">");
stringBuilder.append("<title>提示页面</title>");
stringBuilder.append("<style>");
stringBuilder.append("a{"+
"color: #333;"+
"text-decoration: none;"+
"}");
stringBuilder.append("a{"+
"color: white"+
"background-color: orange;"+
"}");
stringBuilder.append("</style>");
stringBuilder.append("</head>");
stringBuilder.append("<body>");
stringBuilder.append("<h3> 欢迎您!"+ user.getName()+"</h3>");
stringBuilder.append("<hr>");
//要有一个文章列表,显示每个文章的标题
for (Article article : articles){
stringBuilder.append(String.format("<div style=\"width: 200px;height: 50px\"><a href=\"article?articleId=%d\"> %s </div>",
article.getArticleId(),article.getTitle()));
}
stringBuilder.append("<hr>");
stringBuilder.append(String.format("<div>当前共有博客 %d 篇 </div>",articles.size()));
stringBuilder.append("</body>");
stringBuilder.append("</html>");
return stringBuilder.toString();
}
public static String getArticleDetailPage(Article article, User user, User author) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<html>");
stringBuilder.append("<head>");
stringBuilder.append("<meta charset=\"utf-8\">");
stringBuilder.append("<title>提示页面</title>");
stringBuilder.append("<style>");
stringBuilder.append("a{"+
"color: #333;"+
"text-decoration: none;"+
"}");
stringBuilder.append("a{"+
"color: white"+
"background-color: orange;"+
"}");
stringBuilder.append("</style>");
stringBuilder.append("</head>");
stringBuilder.append("<body>");
stringBuilder.append("<h3> 欢迎您!"+ user.getName()+"</h3>");
stringBuilder.append("<hr>");
stringBuilder.append(String.format("<h1>%s</h1>",article.getTitle()));
stringBuilder.append(String.format("<h4>作者:%s</h4>",author.getName()));
stringBuilder.append(String.format("<div>%s</div>",article.getContent()));
stringBuilder.append("</body>");
stringBuilder.append("</html>");
return stringBuilder.toString();
}
}
3) 实现删除文章
package api;
import model.Article;
import model.ArticleDao;
import model.User;
import view.HtmlGenerator;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class DeleteArticleServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
// 1. 验证用户的登陆状态, 如果未登陆, 肯定不能删除.
HttpSession httpSession = req.getSession(false);
if (httpSession == null) {
String html = HtmlGenerator.getMessagePage("您尚未登陆!",
"login.html");
resp.getWriter().write(html);
return;
}
User user = (User) httpSession.getAttribute("user");
// 2. 读取请求内容, 获取到要删除的文章 id
String articleIdStr = req.getParameter("articleId");
if (articleIdStr == null || "".equals(articleIdStr)) {
String html = HtmlGenerator.getMessagePage("要删除的文章 id 有误",
"article");
resp.getWriter().write(html);
return;
}
// 3. 根据文章 id 查找到该文章的作者. 当前用户如果就是作者, 才能删除, 否则删除失败.
ArticleDao articleDao = new ArticleDao();
Article article = articleDao.selectById(Integer.parseInt(articleIdStr));
if (article.getUserId() != user.getUserId()) {
String html = HtmlGenerator.getMessagePage("您只能删除自己的文章!",
"article");
resp.getWriter().write(html);
return;
}
// 4. 真正执行数据库删除操作
articleDao.delete(Integer.parseInt(articleIdStr));
// 5. 返回一个 "删除成功" 的页面.
String html = HtmlGenerator.getMessagePage("删除成功!",
"article");
resp.getWriter().write(html);
}
}