简易项目:servlet实现个人博客(超级详细)

news2024/9/29 13:27:47

成品展示

  1. 博客登录页

2.博客预览页

  1. 博客详情页

4.博客编写发布页

5.可访问网址

http://43.143.248.172:8080/blog_system/login.html

用户名:zhangsan

密码:123

  1. 确认需求

1.1核心功能

1.1.1用户登陆和注销

这一部分需要满足用户的登入和注销操作,同时需要判断用户名和密码的正确性,我们使用JDBC从数据库中拉取数据来实现

1.1.2发布博客

这一部分我们需要引入markdown来进行博客系统的编写页面,并且通过JDBC将发布的博客写入到数据库中

1.1.3删除博客

这一部分我们需要将数据从数据库中将对应的博客进行删除,同时需要跳转到博客预览页

1.1.4浏览博客

这一部分我们通过JDBC将博客的标题和正文一部分展示到博客预览页

  1. 具体实现

2.1项目基础设计

2.1.1数据库概要设计

首先我们要先设计数据库,基于我们的系统比较简易,所以只有两张表

  1. 博客表(blog)

  1. 用户表(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系统

  1. 安装JDK

首先我们要先给我们的Linux上面安装一个JDK,可以执行

yum list | grep jdk

可以看到,会出现很多版本的JDK,这里我们选择

这里我们使用命令

yum install java-1.8.0-openjdk-devel.i686

这里就进行下载了然后输入y

即可下载成功

然后我们对我们安装是否成功进行测试,只需要输入以下命令行

javac

如果没显示找不到命令,而是给一大段文件,则说明安装成功了

  1. 安装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端口上的

  1. 安装MySQL

这里直接查看知乎一个大佬的文章,他的文章非常详细

CentOS 7 通过 yum 安装 MariaDB - 知乎 (zhihu.com)

这里我们进入数据库编辑则需要输入

mysql -uroot -p

然后输入密码,接着把博客系统的数据库部分,复制一份进去,别忘了,还需要将源代码中DBUtil中的数据库密码改一下,因为云服务器的数据库密码可能和你电脑自带的数据库密码不同

  1. 将博客系统打包,部署到云服务

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里面,需要自取

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/370883.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【ArcGIS Pro二次开发】(8):图层(Layer)的基本操作

在ArcGIS中&#xff0c;图层(Layer)是地理数据的集合。可以在 ArcGIS Pro中将很多不同类型的数据表示为图层。 图层通常包含矢量&#xff08;要素&#xff09;或栅格数据。 图层的类型取决于您拥有的数据类型、其基础结构以及其他一些变量。 一、图层(Layer)的基本操作示例 以…

华为OD机试题,用 Java 解【矩阵最大值】问题

最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…

python-在macOS上安装python库 xlwings失败的解决方式

问题&#xff1a;python库 xlwings安装失败 今天&#xff0c;看到网上有wlwings库&#xff0c;可以用来处理excel表格&#xff0c;立刻想试一试。结果&#xff0c;安装这个python库失败了。经过排查&#xff0c;问题解决。 安装过程和错误提示&#xff1a; 我用最简单直接的…

【linux】进程间通信——system V

system V一、system V介绍二 、共享内存2.1 共享内存的原理2.2 共享内存接口2.2.1 创建共享内存shmget2.2.2 查看IPC资源2.2.3 共享内存的控制shmctl2.2.4 共享内存的关联shmat2.2.5 共享内存的去关联shmdt2.3 进程间通信2.4 共享内存的特性2.5 共享内存的大小三、消息队列3.1 …

【Virtualization】Windows11安装VMware Workstation后异常处置

安装环境 Windows 11 专业版 22H2 build 22621.1265 VMware Workstation 17 Pro 17.0.0 build-20800274 存在问题 原因分析 1、BIOS未开启虚拟化。 2、操作系统启用的虚拟化与Workstation冲突。 3、操作系统启用内核隔离-内存完整性保护。 处置思路 1、打开“资源管理器”…

MyBatis学习笔记(六) —— MyBatis的各种查询功能

6、MyBatis的各种查询功能 6.1、查询一个实体类对象 SelectMapper.java接口 /*** 根据用户id查询用户信息* param id* return*/ User getUserById(Param("id") int id);SelectMapper.xml <!--User getUserById(Param("id") int id)--> <selec…

第十三届蓝桥杯国赛 C++ B 组 J 题——搬砖(AC)

目录1.搬砖1.题目描述2.输入格式3.输出格式4.样例输入5.样例输出6.数据范围7.原题链接2.解题思路3.Ac_code1.搬砖 1.题目描述 这天&#xff0c;小明在搬砖。 他一共有 nnn 块砖, 他发现第 iii 砖的重量为 wiw_{i}wi​, 价值为 viv_{i}vi​ 。他突然想从这些 砖中选一些出来从…

JVM的内存结构

一.引言 1.什么是 JVM &#xff1f; 1&#xff09;定义&#xff1a; Java Virtual Machine - java 程序的运行环境&#xff08;java 二进制字节码的运行环境&#xff09; 2&#xff09;好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收功能…

在服务器上指定GPU跑代码

一、准备工作 查看GPU状态和信息&#xff0c;找到空闲的GPU&#xff1a; nvidia-smi 二、指定单GPU 从图中 Processes 表格我们可以发现0、1、2号GPU均是可以利用的。于是我们可以在python文件中加入以下代码&#xff0c;表示使用0号GPU&#xff1a; import os os.environ…

【数通网络交换基础梳理2】三层设备、网关、ARP表、VLAN、路由表及跨网段路由下一跳转发原理

一、不同网段如何通讯 同网段可以依靠二层交换机通讯&#xff0c;网络中存在多个网段192.168.1.1/24 172.16.1.1/24 173.73.1.1/24情况下如何互相通讯&#xff1f;上节留一下的问题&#xff0c;这节继续讲解。 1、这里以Ping命令讲解&#xff0c;PC1 ping173.73.1.2&#xf…

2023中职组网络安全技能竞赛——代码审计解析(超级详细)

代码审计:需求环境可私信博主 任务环境说明: 服务器场景:PYsystem0035服务器场景操作系统:未知服务器场景用户名:未知 密码:未知在渗透机Kali Linux中访问靶机服务器Web页面,注册账号并登陆,找到存在XSS执行漏洞的页面,将该页面中存在XSS执行漏洞的对象名作为FLAG提…

关于永中Office(永中办公软件)不认Windows系统安装的字体的解决办法

一位网友的电脑最近安装了永中Office软件&#xff0c;在使用过程中发现无法使用方正小标宋简体、仿宋GB2312等字体&#xff0c;这些字体在之前所用的微软Office中可以正常使用。他根据网上查到的一些的资料&#xff0c;将这些字体文件复制到C:\Program Files\Yozosoft\Yozo_Off…

【Java】CAS锁

一、什么是CAS机制&#xff08;compare and swap&#xff09; 1.概述 CAS的全称为Compare-And-Swap&#xff0c;直译就是对比交换。是一条CPU的原子指令&#xff0c;其作用是让CPU先进行比较两个值是否相等&#xff0c;然后原子地更新某个位置的值。经过调查发现&#xff0c;…

测试——基本概念

概念 测试和调试有以下几点区别&#xff1a; 测试是测试人员进行的工作&#xff0c;调试是开发人员调试是发现并解决问题&#xff0c;测试只是发现问题测试贯穿于整个项目的生命周期&#xff0c;而调试主要在编码阶段 测试人员一般有如下的工作&#xff1a; 需求分析&#x…

Spring MVC 源码- ViewResolver 组件

ViewResolver 组件ViewResolver 组件&#xff0c;视图解析器&#xff0c;根据视图名和国际化&#xff0c;获得最终的视图 View 对象回顾先来回顾一下在 DispatcherServlet 中处理请求的过程中哪里使用到 ViewResolver 组件&#xff0c;可以回到《一个请求响应的旅行过程》中的 …

进程地址空间(虚拟地址空间)

目录 引入问题 测试代码 引入地址空间 故事1&#xff1a; 故事二&#xff1a; 解决问题 为什么有虚拟地址空间 扩展 扩展1&#xff08;没有地址空间&#xff0c;OS如何工作&#xff09; 扩展2 &#xff08;代码只读深入了解&#xff09; 扩展3&#xff08;malloc本质…

0 初识Kotlin

0 基本介绍 相信很多开发者对Kotlin还是比较陌生的。 Kotlin是一种新型的编程语言&#xff0c;由JetBrains公司开发与设计&#xff0c;在2012年开源&#xff0c; 但没引起什么注意。 直到2017年google宣布将Kotlin作为Android开发的首选语言&#xff0c;Kotlin才开始大放异彩。…

基于MATLAB的MIMO预编码设计:优化迫零算法(附完整代码与分析)

目录 一.介绍 二. 对比本方案优化后的迫零算法与原始的迫零算法 三. 源代码 四. 运行结果及分析 4.1 天线数为8 4.2 天线数为128 一.介绍 图中“RF Chain” 全称为Radio Frequency Chain&#xff0c;代表射频链路。 此MIMO预编码包含了基带预编码W&#xff08;改变幅度和…

NVIDIA GPU开源驱动编译学习架构分析

2022年5月&#xff0c;社区终于等到了这一天&#xff0c;NVIDIA开源了他们的LINUX GPU 内核驱动&#xff0c; Linux 内核总设计师 Linus Torvalds 十年前说过的一句话&#xff0c;大概意思是英伟达是LINUX开发者遇到的硬件厂商中最麻烦的一个&#xff0c;说完这句话之后&#x…

20230225英语学习

Is Your Phone Heavier When It’s Full of Data? We’ve Done the Math 从数学角度看&#xff0c;充满数据的手机会更重吗&#xff1f; Here’s a weird question: does your phone weigh more when it’s “full” than when it’s “empty”?It sounds almost ridiculou…