成品展示
博客登录页
2.博客预览页
博客详情页
4.博客编写发布页
5.可访问网址
http://43.143.248.172:8080/blog_system/login.html
用户名:zhangsan
密码:123
确认需求
1.1核心功能
1.1.1用户登陆和注销
这一部分需要满足用户的登入和注销操作,同时需要判断用户名和密码的正确性,我们使用JDBC从数据库中拉取数据来实现
1.1.2发布博客
这一部分我们需要引入markdown来进行博客系统的编写页面,并且通过JDBC将发布的博客写入到数据库中
1.1.3删除博客
这一部分我们需要将数据从数据库中将对应的博客进行删除,同时需要跳转到博客预览页
1.1.4浏览博客
这一部分我们通过JDBC将博客的标题和正文一部分展示到博客预览页
具体实现
2.1项目基础设计
2.1.1数据库概要设计
首先我们要先设计数据库,基于我们的系统比较简易,所以只有两张表
博客表(blog)
用户表(user)
然后我们根据这两张表,去创建数据库
--创建数据库并设置字符集为utf8mb4
create database if not exists blog_system charset utf8mb4;
use blog_system;
drop table if exists blog;
create table blog(
blogId int primary key auto_increment,
title varchar(256),
content varchar(1025),
postTime datetime,
userId int
);
create table user(
userId int primary key auto_increment,
username varchar(20),
password varchar(20)
);
由于我们没有实现注册功能,所以我们提前在用户表中插入两条数据
insert into user values(null, "zhangsan", "123");
insert into user values(null, "lisi", "123");
2.1.2引入JDBC依赖
这里我们可以去中央仓库去查找,我这里给出的是5.1.49版本的依赖
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
2.1.3封装数据库的DATaSource
由于数据库中的操作我们会经常使用到,所以我们将其封装成一个类DBUtill
使用JDBC编写结果如下(代码中有详细注释):
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;
/**
* Created with IntelliJ IDEA.
* Description:
* User: 王久实
* Date: 2022-12-23
* Time: 21:01
*/
public class DBUtil {
// 通过单例模式创建数据源
private static DataSource dataSource = null;
private static DataSource getDataSource(){
// 这里的if主要是为了提高程序的运行速率,假如没有这个if,那么就会使后续的线程继续去等待锁,然后进去判断if,再出来,再进去一个,就增大了开销
if(dataSource == null){
// 这里主要是为了加锁,防止多个线程进去创建实例
synchronized (DBUtil.class){
// 这里就是防止多个线程进入了第一层if,等待锁释放后,再进来继续创建实例
if(dataSource == null){
dataSource = new MysqlDataSource();
((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/blog_system_2?characterEncoding=utf8&useSSL=false");
// 这里设置数据库的用户名,一般都填写root
((MysqlDataSource)dataSource).setUser("root");
// 这里填写数据库的密码,没有密码就和我这里一样填空
((MysqlDataSource)dataSource).setPassword("");
}
}
}
return dataSource;
}
// 建立连接
public static Connection getConnection() throws SQLException {
// 这一段代码可以分解来看
// DataSource dataSource = getDataSource();
// dataSource.getConnection();
// 本质就是对上面创建的Datasource获取Connection连接
return getDataSource().getConnection();
}
// 关闭资源
// 注意:这里需要后创建的资源先关闭
public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet){
// 这里不能直接throws,如果用throws,程序抛异常了,就会影响到后面的资源关闭
if(connection != null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(statement != null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
2.1.4创建博客类
很明显,我们需要两个类,一个博客类(Blog)一个用户类(User),这里的类需要和数据库中的元素对应
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
/**
* Created with IntelliJ IDEA.
* Description:
* User: 王久实
* Date: 2022-12-23
* Time: 20:59
*/
public class Blog {
private int blogId;
private String title;
private String content;
private Timestamp postTime;
private int userId;
public int getBlogId() {
return blogId;
}
public void setBlogId(int blogId) {
this.blogId = blogId;
}
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 String getPostTime() {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
return simpleDateFormat.format(postTime);
}
public void setPostTime(Timestamp postTime) {
this.postTime = postTime;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
}
这里有一个小细节,就是我们获取时间的那里,不能直接使用post Time,因为从数据库中获取的postTime是一个时间戳,并不方便用户阅读,所以我们这里使用一个类(SimpleDateFormat)来构造用户能够阅读的时间类型,这里这个类首先实例化的时候,就在构造方法中声明了转换后的类型,后续只需要调用format()方法,即可将postTime转换为我们设置类型的字符串,从而提升用户的体验感
2.1.5创建用户类
User类没啥好说的,只需要和数据库元素对应即可
/**
* Created with IntelliJ IDEA.
* Description:
* User: 王久实
* Date: 2022-12-23
* Time: 20:33
*/
public class User {
private int userId;
private String userName;
private String password;
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 getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
2.1.6针对Blog类进行增删改查
我们设置好实体类之后,就可以通过JDBC对数据库进行增删改查操作了,这里我们将Blog的增删改查进行封装成一个BlogDao类
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* Description:
* User: 王久实
* Date: 2022-12-23
* Time: 21:55
* +-----------------------+
* | Tables_in_blog_system |
* +-----------------------+
* | blog |
* | user |
* +-----------------------+
*/
public class BlogDao {
// 增加一篇博客
public static void insertBlog(Blog blog){
Connection connection = null;
PreparedStatement statement = null;
// sql语句的编写
String sql = "insert into blog values(null,?,?,now(),?)";
try {
// 调用DBUtil中的方法,建立连接
connection = DBUtil.getConnection();
// 将编写好的sql语句进行处理
statement = connection.prepareStatement(sql);
// 对语句中的?进行设置操作
statement.setString(1,blog.getTitle());
statement.setString(2,blog.getContent());
statement.setInt(3,blog.getUserId());
// 执行sql语句
statement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
// 调用DBUtil中的方法,对资源进行释放
DBUtil.close(connection,statement,null);
}
}
// 根据博客Id查询对应的博客
public static Blog selectBlogByBlogId(int blogId){
Connection connection = null;
PreparedStatement statement = null;
// 用来接收查询到的数据
ResultSet resultSet = null;
Blog blog = new Blog();
String sql = "select * from blog where blogId = ?";
try {
connection = DBUtil.getConnection();
statement = connection.prepareStatement(sql);
statement.setInt(1,blogId);
resultSet = statement.executeQuery();
// if判断是否读到数据
if(resultSet == null){
return null;
}
// 将读到的数据设置到实体类中去
blog.setBlogId(blogId);
blog.setUserId(resultSet.getInt("userId"));
blog.setContent(resultSet.getString("content"));
blog.setTitle(resultSet.getString("title"));
blog.setPostTime(resultSet.getTimestamp("postTime"));
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(connection,statement,resultSet);
}
return blog;
}
// 查看所有博客
public static List<Blog> selectAll(){
List<Blog> blogs = new ArrayList<>();
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
String sql = "select * from blog";
try {
connection = DBUtil.getConnection();
statement = connection.prepareStatement(sql);
resultSet = statement.executeQuery();
// 这里和迭代器的用法一样,使用next表示往下一个数据依次执行
while(resultSet.next()){
Blog blog = new Blog();
blog.setBlogId(resultSet.getInt("blogId"));
blog.setTitle(resultSet.getString("title"));
String content = resultSet.getString("content");
if(content.length() > 80){
content = content.substring(0,81) + "...";
}
blog.setContent(content);
blog.setPostTime(resultSet.getTimestamp("postTime"));
blog.setUserId(resultSet.getInt("userId"));
blogs.add(blog);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(connection,statement,resultSet);
}
return blogs;
}
//删除博客
public static void deleteBlog(Blog blog){
Connection connection = null;
PreparedStatement statement = null;
String sql = "delete from blog where blogId = ?";
try {
connection = DBUtil.getConnection();
statement = connection.prepareStatement(sql);
statement.setInt(1,blog.getUserId());
statement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
DBUtil.close(connection,statement,null);
}
}
}
2.1.7对User类进行增删改查
这里和上面的方法基本如出一辙,就不过多赘述
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Created with IntelliJ IDEA.
* Description:
* User: 王久实
* Date: 2022-12-23
* Time: 21:24
*/
public class UserDao {
// 通过用户名查询
public static User selectByName(String userName) {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
// 建立上连接
connection = DBUtil.getConnection();
// 构造sql
String sql = "select * from user where username = ?";
statement = connection.prepareStatement(sql);
statement.setString(1, userName);
// 执行sql
resultSet = statement.executeQuery();
// 遍历写入
User user = new User();
user.setUserId(resultSet.getInt("userId"));
user.setUserName(userName);
user.setPassword(resultSet.getString("password"));
// 返回结果
return user;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(connection, statement, resultSet);
}
return null;
}
// 通过用户Id来查询
public static User selectById(int userId) {
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
connection = DBUtil.getConnection();
String sql = "select from user where userId = ?";
statement = connection.prepareStatement(sql);
statement.setInt(1,userId);
resultSet = statement.executeQuery();
User user = new User();
user.setUserId(userId);
user.setUserName(resultSet.getString("userName"));
user.setPassword(resultSet.getString("password"));
return user;
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(connection,statement,resultSet);
}
return null;
}
}
2.2实现博客预览页
2.2.1接口约定
这里和前端技术人员约定好前后端交互的接口,这里约定的接口如下:
然后根据博客预览页,进行相关代码的编写
这里还有一个点,和前端约定的格式是json格式的,所以我们还需要导入json的依赖和servlet的依赖,通过中央仓库去复制即可
<!-- 这里是servelet的依赖-->
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- 这里是json的依赖-->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.4.1</version>
</dependency>
2.2.2博客预览页后端代码
前端代码我会放到最后
import com.fasterxml.jackson.databind.ObjectMapper;
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.util.ArrayList;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* Description:
* User: 王久实
* Date: 2022-12-29
* Time: 10:54
*/
@WebServlet("/blog")
public class BlogServlet extends HttpServlet {
ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("application/json;charset=utf8");
// 博客列表页
// 创建List集合来接收blog,用BlogDao中的方法去数据库中查询
List<Blog> blogs = BlogDao.selectAll();
// 将查询到的结果返回给前端
resp.getWriter().write(objectMapper.writeValueAsString(blogs));
}
}
2.3实现博客详情页
2.3.1接口约定
这里的请求中加了query string来标识博客的Id
2.3.2博客详情页后端代码
由于这里也使用/blog的GET请求,所以我们就可以在原来的博客预览页代码中加上一个if语句,从而区分博客详情页和博客预览页,这里可以通过blogId是否为null来判断,因为博客列表页发送过来的数据中是不包含query string 的所以这里可以用这个进行一个区分
@WebServlet("/blog")
public class BlogServlet extends HttpServlet {
ObjectMapper objectMapper = new ObjectMapper();
// 这里是和前端约定好的GET请求
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 由于前端约定的格式是json格式的
resp.setContentType("application/json;charset=utf8");
// 从前端发来的请求中获取到blogId
String blogId = req.getParameter("blogId");
// 这里进行判断是博客预览页还是博客详情页
if(blogId == null){
// 博客列表页
List<Blog> blogs = BlogDao.selectAll();
resp.getWriter().write(objectMapper.writeValueAsString(blogs));
}else {
// 博客详情页
Blog blog = BlogDao.selectBlogByBlogId(Integer.parseInt(blogId));
resp.getWriter().write(objectMapper.writeValueAsString(blog));
}
}
}
2.4登陆逻辑
2.4.1接口约定
2.4.2登陆逻辑后端代码
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* Created with IntelliJ IDEA.
* Description:
* User: 王久实
* Date: 2022-11-30
* Time: 20:50
*/
@WebServlet("/login")
public class BlogLoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置接收到请求的类型
req.setCharacterEncoding("utf-8");
// 设置返回的响应的类型
resp.setContentType("text/http;charset=utf8");
// 从前端页面获取用户名和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
// 判断获取到的用户名密码是否为空值
if(username == null || password == null || username.equals("") || password.equals("")){
resp.getWriter().write("用户名或密码为空");
return;
}
User user = new User();
UserDao userDao = new UserDao();
user = userDao.selectByName(username);
// 将获取到的用户名密码和数据库中的用户名密码进行比对
if(user == null || !user.getPassword().equals(password)){
// 这里的前端页面并没有进行设置,所以只是返回一个字符串响应
resp.getWriter().write("用户名或密码错误");
return;
}
// 说明用户名密码验证成功了
// 建立一个会话
// 这里的true表示如果没有会话就创建一个会话,如果存在则返回已拥有的会话
HttpSession session = req.getSession(true);
// 在上一句获取到的会话中保存user对象,当客户端带着这个session进行访问的时候,服务器会根据session返回对应的内容
session.setAttribute("user",user);
// 重定向到博客预览页
resp.sendRedirect("blog_list.html");
}
}
2.4.3强制博客预览页和博客详情页登陆
我们这里限制一下,如果我们在通过网页直接访问博客预览页或者博客详情页的时候,我们需要检查登陆状态必须强制我们已经登陆了,才能 访问
接口的约定
如果未登录,直接返回403进行拒绝访问
后端代码的实现
这里也用 /login,用GET请求,所以和上述代码可以放到同一个类中去
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* Created with IntelliJ IDEA.
* Description:
* User: 王久实
* Date: 2022-11-30
* Time: 20:50
*/
@WebServlet("/login")
public class BlogLoginServlet extends HttpServlet {
@Override
// 对登陆状态进行判定
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取会话,如果没有会话,就返回null
HttpSession session = req.getSession(false);
// 如果session为null,则说明客户端没有带着session进行访问,所以就应该拒绝登录,直接返回403响应
if(session == null){
// 返回403响应,即拒绝登陆
resp.setStatus(403);
return;
}
// 如果有session,判断是否包含user对象
User user = (User) session.getAttribute("user");
// 如果不包含user对象,则返回403
if(user == null){
resp.setStatus(403);
return;
}
// 包含就返回200
resp.setStatus(200);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置接收到请求的类型
req.setCharacterEncoding("utf-8");
// 设置返回的响应的类型
resp.setContentType("text/http;charset=utf8");
// 从前端页面获取用户名和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
// 判断获取到的用户名密码是否为空值
if(username == null || password == null || username.equals("") || password.equals("")){
resp.getWriter().write("用户名或密码为空");
return;
}
User user = new User();
UserDao userDao = new UserDao();
user = userDao.selectByName(username);
// 将获取到的用户名密码和数据库中的用户名密码进行比对
if(user == null || !user.getPassword().equals(password)){
// 这里的前端页面并没有进行设置,所以只是返回一个字符串响应
resp.getWriter().write("用户名或密码错误");
return;
}
// 说明用户名密码验证成功了
// 建立一个会话
// 这里的true表示如果没有会话就创建一个会话,如果存在则返回已拥有的会话
HttpSession session = req.getSession(true);
// 在上一句获取到的会话中保存user对象,当客户端带着这个session进行访问的时候,服务器会根据session返回对应的内容
session.setAttribute("user",user);
// 重定向到博客预览页
resp.sendRedirect("blog_list.html");
}
}
2.5显示用户信息
在我们进行访问博客系统内部页面的时候,首先要确保已经登陆,那么我们就需要检查一下登陆状态,并且把登陆信息展示到状态栏,这里我们访问不同的界面,需要设置不同的方法来实现
2.5.1接口设计
这里接口设计和上面的基本大同小异
2.5.2 后端代码实现
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* Created with IntelliJ IDEA.
* Description:
* User: 王久实
* Date: 2022-12-01
* Time: 10:24
*/
@WebServlet("/userInfo")
public class UserInfoServlet extends HttpServlet {
// 这个是用来转换json数据的,所有设置了json的方式返回的都需要用mapper进行转换
private ObjectMapper mapper = new ObjectMapper();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置响应的类型
resp.setContentType("application/json;charset=utf8");
// 从前端获取博客Id(通过query string传递的)
String blogId = req.getParameter("blogId");
// 判断是博客详情页还是博客预览页
if (blogId == null){
getUserInfoFromSession(req,resp);
}else {
// 这里注意,前端传过来的blogId是字符型的,但是数据库中是int类型的,所以这里需要转成int类型的
getUserInfoFromDB(req,resp,Integer.parseInt(blogId));
}
}
// 博客详情页
private void getUserInfoFromDB(HttpServletRequest req, HttpServletResponse resp,int blogId) throws IOException {
resp.setContentType("application/json;charset=utf8");
BlogDao blogDao = new BlogDao();
// 从数据库中查询blogId对应的博客
Blog blog = blogDao.selectOne(blogId);
if(blog == null){
resp.setStatus(404);
resp.getWriter().write(mapper.writeValueAsString("blogId不存在"));
return;
}
UserDao userDao = new UserDao();
// 根据Blog对象中的userId属性去User表中查找该篇博客的发布者
User user = userDao.selectById(blog.getUserId());
if(user == null){
resp.setStatus(404);
resp.getWriter().write(mapper.writeValueAsString("用户已经不存在"));
return;
}
// 这里是查询到了,我们不因该将密码页发送给客户端,所以置为空
user.setPassword("");
// 将查询到的User信息返回给前端
resp.getWriter().write(mapper.writeValueAsString(user));
}
// 博客预览页
private void getUserInfoFromSession(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("application/json;charset=utf8");
// 获取会话,通过会话中的内容,查询当前登陆的用户
HttpSession session = req.getSession(false);
if(session == null){
resp.setStatus(403);
resp.getWriter().write(mapper.writeValueAsString("当前未登录"));
return;
}
// 存入session中的user对象
User user = (User) session.getAttribute("user");
if(user == null){
resp.setStatus(403);
resp.getWriter().write(mapper.writeValueAsString("当前未登录"));
return;
}
// 将密码置为空
user.setPassword("");
// 返回用户信息
resp.getWriter().write(mapper.writeValueAsString(user));
}
}
2.6注销用户
2.6.1接口约定
注销后,跳转到登陆页面
2.6.2后端代码实现
其实这个很简单,只需要将session中的值进行修改,即可得到未登录状态
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* Created with IntelliJ IDEA.
* Description:
* User: 王久实
* Date: 2022-12-01
* Time: 16:36
*/
@WebServlet("/logout")
public class BlogLoginOutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取会话
HttpSession session = req.getSession(false);
if(session == null){
resp.setStatus(403);
resp.getWriter().write("当前未登录");
return;
}
// 将session中的user对象删除
session.removeAttribute("user");
// 跳转到登陆界面
resp.sendRedirect("login.html");
}
}
2.7发布博客
2.7.1接口约定
发布完成之后,需要重定向到博客预览页
2.7.2后端代码实现
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* Description:
* User: 王久实
* Date: 2022-11-29
* Time: 16:50
*/
@WebServlet("/blog")
public class BlogServlet extends HttpServlet {
ObjectMapper objectMapper = new ObjectMapper();
@Override
//已经完成详情页和列表
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("application/json; charset=utf8");
BlogDao blogDao = new BlogDao();
String blogId = req.getParameter("blogId");
if(blogId == null){
List<Blog> blogs = blogDao.selectAll();
resp.getWriter().write(objectMapper.writeValueAsString(blogs));
}else {
Blog blog = blogDao.selectOne(Integer.parseInt(blogId));
resp.getWriter().write(objectMapper.writeValueAsString(blog));
}
}
// 发布博客
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取会话
HttpSession session = req.getSession(false);
if(session == null){
resp.setStatus(403);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("当前未登录");
return;
}
// 检查user对象是否存在
User user = (User) session.getAttribute("user");
if(user == null){
resp.setStatus(403);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("当前未登录");
return;
}
// 设置字符集
req.setCharacterEncoding("utf8");
// 从前端获取标题和正文
String title = req.getParameter("title");
String content = req.getParameter("content");
// 将新博客设置到blog实例
Blog blog = new Blog();
BlogDao blogDao = new BlogDao();
blog.setTitle(title);
blog.setContent(content);
blog.setUserId(user.getUserId());
// 将新博客设置到数据库中去
blogDao.insert(blog);
// 跳转到博客预览页
resp.sendRedirect("blog_list.html");
}
}
2.8删除博客
2.8.1接口约定
删除失败就返回403,拒绝访问,成功就返回博客预览页
2.8.2后端代码实现
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* Created with IntelliJ IDEA.
* Description:
* User: 王久实
* Date: 2022-12-01
* Time: 17:44
*/
@WebServlet("/blog_delete")
public class BlogDeleteServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取会话
HttpSession session = req.getSession(false);
if(session == null){
resp.setStatus(403);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("当前没有登陆");
return;
}
User user = (User) session.getAttribute("user");
if(user == null ){
resp.setStatus(403);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("当前没有登陆");
return;
}
// 从前端的query string获取到blogId
String blogId =req.getParameter("blogId");
// 判断是否存在blogId参数
if(blogId == null){
resp.setStatus(404);
resp.setContentType("text/html;charset=utf8");
// 如果没有查找到该文章,就直接返回blogId有误
resp.getWriter().write("blogId有误");
return;
}
BlogDao blogDao = new BlogDao();
// 因为blogId
Blog blog = blogDao.selectOne(Integer.parseInt(blogId));
// 查看这个博客是否存在,需要将前端传过来的字符串转换成int类型
if(blog == null){
resp.setStatus(403);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("找不到该博客");
return;
}
// 查看有没有权限去删除这篇博客,即判断当前登陆的用户,是不是和当前的用户相符合
if(user.getUserId() != blog.getUserId()){
resp.setStatus(403);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("当前没有权限删除该博客");
return;
}
// 从数据库中删除该博客
blogDao.delete(Integer.parseInt(blogId));
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("删除博客成功");
// 跳转到博客预览页
resp.sendRedirect("blog_list.html");
}
}
3.将博客系统部署到云服务器
先准备一个云服务器,并且安装Linux系统
安装JDK
首先我们要先给我们的Linux上面安装一个JDK,可以执行
yum list | grep jdk
可以看到,会出现很多版本的JDK,这里我们选择
这里我们使用命令
yum install java-1.8.0-openjdk-devel.i686
这里就进行下载了然后输入y
即可下载成功
然后我们对我们安装是否成功进行测试,只需要输入以下命令行
javac
如果没显示找不到命令,而是给一大段文件,则说明安装成功了
安装Tomcat
这里和上面的操作基本如出一辙,继续使用操作yum list即可
yum list | grep tomcat
我们选择这个进行安装
或者我们将Windows上面下载好的往XShell里面一拖就可以了
这里我们安装好之后,进入tomcat的文件夹,然后进入bin文件夹
就可以看到这个
这个就是我们Tomcat的启动程序
但是我们要先给可执行权限,才可以执行程序
chmod +x *.sh
输入这段代码即可
这时候,看到的sh文件就是绿色的了
然后通过
sh startup.sh
就可以启动Tomcat了
这里我们验证一下,输入下面代码
ps aux | grep tomcat
可以得到如下
这里划红线的是安装的Tomcat地址
或者我们使用
netstat -anp | grep 8080
这里我们就可以看到,8080端口正在使用,而我们的tomcat 正是运行在8080端口上的
安装MySQL
这里直接查看知乎一个大佬的文章,他的文章非常详细
CentOS 7 通过 yum 安装 MariaDB - 知乎 (zhihu.com)
这里我们进入数据库编辑则需要输入
mysql -uroot -p
然后输入密码,接着把博客系统的数据库部分,复制一份进去,别忘了,还需要将源代码中DBUtil中的数据库密码改一下,因为云服务器的数据库密码可能和你电脑自带的数据库密码不同
将博客系统打包,部署到云服务
4.1导入依赖
在博客系统中,我们需要导入一个依赖,从而使打包出来的文件变成war包
<packaging>war</packaging>
<build>
<finalName>blog_system</finalName>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</build>
4.2打包
使用这个对所需要的文件进行打包处理,然后将其拖到
tomcat的webapp目录下即可
到这里我们就完成了一个简易的博客系统,可以进行访问试一下
4.项目源码展示
这里为了方便大家取用,我直接把项目的gitee放在文章末尾
博客系统 · 王久实/JAVA - 码云 - 开源中国 (gitee.com)
前端代码在webapps里面,需要自取