【JavaEE初阶】博客系统后端

这篇具有很好参考价值的文章主要介绍了【JavaEE初阶】博客系统后端。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一. 创建项目 引入依赖

创建blog_system项目.将之前写的博客系统前端代码复制到webapp目录下.
【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java
pom.xml中引入Servlet mysql jackson三个依赖:
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>org.example</groupId>
    <artifactId>blog_system</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>

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


        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.14.2</version>
        </dependency>

    </dependencies>
</project>

二. 设计数据库

结合之前的需求,在当前博客系统中,主要涉及到两个实体.即 用户博客.
经过分析我们可以得到,用户博客之间是一对多的关系.即一个用户可以拥有多篇博客.
所以我们可以创建两张表,来表示用户和博客.
blog(blogId,title,content,postTime,userId)
user(userId,userName,password)

三. 编写数据库代码

把一些基本的数据库操作,先封装好.
【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java
需要手动粘贴至MySQL

-- 这个文件主要用来写 建库建表 语句

create database if not exists javaee_blog_system;
use javaee_blog_system;

-- 删除旧表,重新建表
drop table if exists user;
drop table if exists blog;

-- 创建表
create table blog(
    blogId int primary key auto_increment,
    title varchar(128),
    content varchar(4096),
    postTime datetime,
    userId int
);

create table user(
    userId int primary key auto_increment,
    username varchar(20) unique,-- 要求用户名和别人的不重复
    password varchar(20)
);

接下来是封装数据库的连接操作:
DBUtil:

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

import javax.sql.DataSource;
import java.sql.*;

public class DBUtil {
    private static DataSource dataSource = new MysqlDataSource();

    static {
        ((MysqlDataSource)dataSource).setUrl("jdbc:mysql://127.0.0.1:3306/javaee_blog_system?characterEncoding=utf8&useSSL=false");
        ((MysqlDataSource)dataSource).setUser("root");
        ((MysqlDataSource)dataSource).setPassword("0828");
    }

    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }
    public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

四. 创建实体类

实体类就是和表中的记录对应的类:
blog表 =>Blog类对应Blog的一个对象,就对应表中的一条记录.
user表 =>User类对应User的一个对象,就对应表中的一个记录.
实体类有哪些属性,都是和当前表中的列是密切相关的.
User:


public class User {
  private int userId;
  private String username;

    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;
    }

    private String password;
}

Blog:

import java.sql.Timestamp;

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 Timestamp getPostTime() {
        return postTime;
    }

    public void setPostTime(Timestamp postTime) {
        this.postTime = postTime;
    }

    public int getUserId() {
        return userId;
    }

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

五. 封装数据库的增删查改

针对博客表,创建BlogDao;(Data Access Object)
针对用户表,创建UserDao.
上述Dao用来提供一些方法.来进行增删查改.
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;

//通过这个类,封装针对 博客表 的基本操作
//修改:删除+新增(不考虑)
public class BlogDao {
    //1.新增博客
    public void add(Blog blog){
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            //1.和数据库建立连接
            connection = DBUtil.getConnection();
            //2.构造SQL
            String sql = "insert into blog values(null,?,?,?,?)";
            statement = connection.prepareStatement(sql);
            statement.setString(1,blog.getTitle());
            statement.setString(2, blog.getContent());
            statement.setTimestamp(3,blog.getPostTime());
            statement.setInt(4,blog.getUserId());
            //3.执行SQL
            statement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            DBUtil.close(connection,statement,null);
        }
    }

    //2.根据博客id来查询指定博客(博客详情页)
    public Blog selectById(int blogId){
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            //1.与数据库建立连接
            connection = DBUtil.getConnection();
            //2.构造sql
            String sql = "select * from blog where blogId = ?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            //3.执行sql
            resultSet = statement.executeQuery();
            //4.遍历结果集合
            if(resultSet.next()){
                Blog blog = new Blog();
                blog.setBlogId(resultSet.getInt("blogId"));
                blog.setTitle(resultSet.getString("title"));
                blog.setContent(resultSet.getString("content"));
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                blog.setUserId(resultSet.getInt("userId"));
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            //5.释放资源
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }

    //3.查询数据库中所有的博客列表(用于博客列表页)
    public List<Blog> selectAll(){
        List<Blog> blogs = new ArrayList<>();
        
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            //1.与数据库建立连接
            connection = DBUtil.getConnection();
            //2.构造sql语句
            String sql = "select * from blog";
            statement = connection.prepareStatement(sql);
            //3.执行sql
            resultSet = statement.executeQuery();
            //4.遍历结果集合
            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() >= 100){
                    content = content.substring(0,100) +"...";
                }
                blog.setContent(content);
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                blog.setUserId(resultSet.getInt("userId"));
                blogs.add(blog);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return blogs;
    }

    //4.删除指定博客
    public void delect(int blogId){
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            //1.与数据库建立连接
            connection = DBUtil.getConnection();
            //2.构造sql语句
            String sql = "delete from blog where bolgId = ?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            //3.执行sql
            statement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            //4.关闭资源
            DBUtil.close(connection,statement,null);
        }
    }
}

UserDao:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

//针对用户表提供的基本操作
public class UserDao {
    //1.根据 userId 来查用户信息
    public User selectById(int userId){
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            //1.与数据库建立连接
            connection = DBUtil.getConnection();
            //2.构造sql
            String sql = "select * from user where userId = ?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,userId);
            //3.执行SQL
            resultSet = statement.executeQuery();
            //4.遍历结果集合
            if(resultSet.next()){
                User user = new User();
                user.setUserId(resultSet.getInt("userId"));
                user.setUsername(resultSet.getString("username"));
                user.setPassword(resultSet.getString("password"));
                return user;
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            //5.释放资源
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }
    //2.根据username来查找用户信息.
    public User selectByUsername(int username){
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            //1.与数据库建立连接
            connection = DBUtil.getConnection();
            //2.构造sql
            String sql = "select * from user where userId = ?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,username);
            //3.执行SQL
            resultSet = statement.executeQuery();
            //4.遍历结果集合
            if(resultSet.next()){
                User user = new User();
                user.setUserId(resultSet.getInt("userId"));
                user.setUsername(resultSet.getString("username"));
                user.setPassword(resultSet.getString("password"));
                return user;
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            //5.释放资源
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }
}

六. 具体功能书写

1. 博客列表页

【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java
当前博客列表页上的数据都是写死的.正确的做法,应该是通过数据库读取数据显示到页面上.
此处就需要打通前后端交互的操作.
让博客列表页,在加载的时候,通过ajax给服务器发一个请求服务器查数据库获取到博客列表数据,返回给浏览器,浏览器再根据数据构造页面内容.这样的交互过程,也称为“前后端分离"
前端只向后端请求数据,而不请求具体的页面,后端也仅仅是返回数据.这样的设定的目的就是为了前端和后端更加解耦,由浏览器进行具体的页面渲染.减少了服务器的工作量.

上述进行实现博客列表页的基本思路

接下来需要:

  1. 约定前后端交互接口
  2. 开发后端代码
  3. 开发前端代码
  1. 约定前后端交互接口
    请求:GET /blog
    响应:使用json格式的数据来组织
[
	{
		blogId:1,
		title:"这是第一篇博客",
		content:"从今天开始,我要认真学习",
		postTime:"2023-08-01 09:40:45",
		userId:1
	}
	{
		blogId:1,
		title:"这是第一篇博客",
		content:"从今天开始,我要认真学习",
		postTime:"2023-08-01 09:40:45",
		userId:1
	}
	{
		blogId:1,
		title:"这是第一篇博客",
		content:"从今天开始,我要认真学习",
		postTime:"2023-08-01 09:40:45",
		userId:1
	}
]
  1. 开发后端代码
    BlogServlet:
package api;

import com.fasterxml.jackson.databind.ObjectMapper;
import model.Blog;
import model.BlogDao;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

public class BlogServlet extends HttpServlet {

    private ObjectMapper objectMapper = new ObjectMapper();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        BlogDao blogDao = new BlogDao();
        List<Blog> blogs = blogDao.selectAll();
        //需要把blogs转成符合要求的 json 格式字符串
        String respJson = objectMapper.writeValueAsString(blogs);
        resp.setContentType("application/json;charset = utf8");
        resp.getWriter().write(respJson);
    }
}

【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java
此处注意文件所在位置.model是管理数据/操作数据的部分.

  1. 开发前端代码
    在博客列表页加载过程中,触发ajax,访问服务器中的数据.再把拿到的数据构造到页面中.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>博客列表页</title>
    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/blog_list.css">
</head>
<body>
    <!-- 导航栏 -->
    <div class="nav">
        <img src="image/logo2.jpg" alt="">
        <span class="title">我的博客系统</span>
        <!-- 用于占位,将a标签挤到右侧去 -->
        <div class="spacer"></div>
        <a href="#">主页</a>
        <a href="#">写博客</a>
        <a href="#">注销</a>
    </div>
    <!-- 页面主体部分 -->
    <div class="container">
        <!-- 左侧信息 -->
        <div class="container-left">
            <!-- 使用.card表示用户信息 -->
            <div class="card">
                <!-- 用户头像 -->
                <img src="image/touxiang.jpg" alt="">
                <!-- 用户名 -->
                <h3>xxxflower</h3>
                <a href="#">github地址</a>
                <div class="counter">
                    <span>文章</span>
                    <span>分类</span>
                </div>
                <div class="counter">
                    <span>2</span>
                    <span>1</span>
                </div>
            </div>
        </div>
        <!-- 右侧信息 -->
        <div class="container-right">
        </div>
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
    <script>
        // 在页面加载时, 向服务器发起请求, 获取博客列表数据
        function getBlogs() {
            $.ajax({
                type: 'get',
                url: 'blog',
                success: function(body) {
                    // 响应的正文 是一个 json 字符串, 此处已经被 jquery 自动解析成 js 对象数组了. 
                    // 直接 for 循环遍历即可. 
                    let containerRight = document.querySelector('.container-right');
                    for (let blog of body) {
                        // 构造页面内容, 参考之前写好的 html 代码
                        // 构造整个博客 div
                        let blogDiv = document.createElement('div');
                        blogDiv.className = 'blog';
                        // 构造标题
                        let titleDiv = document.createElement('div');
                        titleDiv.className = 'title';
                        titleDiv.innerHTML = blog.title;
                        blogDiv.appendChild(titleDiv);
                        // 构造发布时间
                        let dateDiv = document.createElement('div');
                        dateDiv.className = 'date';
                        dateDiv.innerHTML = blog.postTime;
                        blogDiv.appendChild(dateDiv);
                        // 构造 博客 摘要
                        let descDiv = document.createElement('div');
                        descDiv.className = 'desc';
                        descDiv.innerHTML = blog.content;
                        blogDiv.appendChild(descDiv);
                        // 构造查看全文按钮
                        let a = document.createElement('a');
                        a.innerHTML = '查看全文 &gt;&gt;';
                        // 期望点击之后能跳转到博客详情页. 为了让博客详情页知道是点了哪个博客, 把 blogId 给传过去
                        a.href = 'blog_detail.html?blogId=' + blog.blogId;
                        blogDiv.appendChild(a);

                        // 把 blogDiv 加到父元素中
                        containerRight.appendChild(blogDiv);
                    }
                }
            });
        }

        // 要记得调用
        getBlogs();
        </script>
</body>
</html>

效果如下图所示:
【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java
但是我们发现这里的时间显示有问题:
我们需要使用SimpleDateFormat类.注意该类使用时的书写格式!
【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java
【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java

2. 博客详情页

关于博客详情页,点击查看全文按钮,就能跳转到博客详情页中.跳转过去之后,在博客详情页中发起一个ajax,从服务器获取到当前的博客的具体内容.再进行显示.

分为以下几个步骤:

  1. 约定前后端交互接口
  2. 实现后端代码
  3. 实现前端代码
  1. 约定前后端交互接口
    请求:GET/blog?blogId = 1
    响应:
    HTTP/1.1 200 OK
    {
    blogId:1,
    title:“这是第一篇博客”,
    content:“从今天开始我要认真学习”,
    postTime:“2023-08-01 17:00:00”,
    userId:1
    }

  2. 实现后端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>博客详情页</title>
    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/blog_detail.css">
</head>
<body>
     <!-- 导航栏 -->
     <div class="nav">
        <img src="image/logo2.jpg" alt="">
        <span class="title">我的博客系统</span>
        <!-- 用于占位,将a标签挤到右侧去 -->
        <div class="spacer"></div>
        <a href="#">主页</a>
        <a href="#">写博客</a>
        <a href="#">注销</a>
    </div>
    <!-- 页面主体部分 -->
    <div class="container">
        <!-- 左侧信息 -->
        <div class="container-left">
            <!-- 使用.card表示用户信息 -->
            <div class="card">
                <!-- 用户头像 -->
                <img src="image/touxiang.jpg" alt="">
                <!-- 用户名 -->
                <h3>xxxflower</h3>
                <a href="#">github地址</a>
                <div class="counter">
                    <span>文章</span>
                    <span>分类</span>
                </div>
                <div class="counter">
                    <span>2</span>
                    <span>1</span>
                </div>
            </div>
        </div>
        <!-- 右侧信息 -->
        <div class="container-right">
            <!-- 博客标题 -->
            <h3 class="title"></h3>
            <!-- 博客发布时间 -->
            <div class="date"></div>
            <!-- 博客正文, 为了配合 editormd 进行格式转换, 此处务必改成 id  -->
            <div id="content">
                
            </div>
        </div>
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.3/jquery.min.js"></script>
    <!-- 要保证这几个 js 的加载在 jquery 之后. editor.md 依赖了 jquery -->
    <script src="editor.md/lib/marked.min.js"></script>
    <script src="editor.md/lib/prettify.min.js"></script>
    <script src="editor.md/editormd.js"></script>
    <script>
        $.ajax({
            type: 'get',
            url: 'blog' + location.search,
            success: function(body) {
                // 处理响应结果, 此处的 body 就是表示一个博客的 js 对象. 
                // 1. 更新标题
                let titleDiv = document.querySelector('.container-right .title');
                titleDiv.innerHTML = body.title;
                // 2. 更新日期
                let dateDiv = document.querySelector('.date');
                dateDiv.innerHTML = body.postTime;
                // 3. 更新博客正文
                // 此处不应该直接把博客正文填充到这个标签里
                editormd.markdownToHTML('content', { markdown: body.content });
            }
        })
    </script>
</body>
</html>
  1. 开发后端代码
package api;

import com.fasterxml.jackson.databind.ObjectMapper;
import model.Blog;
import model.BlogDao;

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.List;

@WebServlet("/blog")
public class BlogServlet extends HttpServlet {

    private ObjectMapper objectMapper = new ObjectMapper();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        BlogDao blogDao = new BlogDao();
        String blogId = req.getParameter("blogId");
        if(blogId == null){
            List<Blog> blogs = blogDao.selectAll();
            //需要把blogs转成符合要求的 json 格式字符串
            String respJson = objectMapper.writeValueAsString(blogs);
            resp.setContentType("application/json;charset = utf8");
            resp.getWriter().write(respJson);
        }else{
            // queryString 存在, 说明本次请求获取的是指定 id 的博客.
            Blog blog = blogDao.selectById(Integer.parseInt(blogId));
            if (blog == null) {
                System.out.println("当前 blogId = " + blogId + " 对应的博客不存在!");
            }
            String respJson = objectMapper.writeValueAsString(blog);
            resp.setContentType("application/json; charset=utf8");
            resp.getWriter().write(respJson);
        }
    }
}

【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java
这是因为浏览器自身也有缓存机制.
浏览器从服务器这边获取页面,这个操作是通过网络传输完成的,速度是比较慢的.浏览器就会把页面给缓存到本地(客户端电脑的硬盘上).后续再访问同一个页面,就直接读缓存.但是这样做有一些问题,即客户端命中缓存之后就不一定能及时感知到变化.
解决方法:强制刷新.(无视缓存,100%重新访问服务器)Ctrl + f5
【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java

3. 博客登录页

【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java
在此处输入用户名和密码,点击登录,就会触发一个http请求.
服务器验证用户名和密码,然后就可以根据结果,判定是否登录成功.

分为以下几个步骤:

  1. 约定前后端交互接口
  2. 实现前端代码
  3. 实现后端代码
  1. 约定前后端交互接口
    请求:
    POST/login
    username = zhangsan&password = 123
    响应:
    HTTP/1.1 302
    Location:blog_list.html

注意:
此处的响应应是from表单(本身就会触发页面跳转),响应是302才能够进行页面跳转.
如果是ajax请求(本身不会触发),响应是302,此时是无法进行跳转的.

  1. 实现前端代码
    往页面上加入from表单,使得点击登录操作能够触发请求.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>博客登录页</title>
    <link rel="stylesheet" href="css/common.css">
    <link rel="stylesheet" href="css/login.css">
</head>
<body>
     <!-- 导航栏 -->
     <div class="nav">
        <img src="image/logo2.jpg" alt="">
        <span class="title">我的博客系统</span>
        <!-- 用于占位,将a标签挤到右侧去 -->
        <div class="spacer"></div>
        <a href="#">主页</a>
        <a href="#">写博客</a>
    </div>
    <!-- 正文部分 -->
    <!-- 贯穿整个页面的容器 -->
    <div class="login-container">
        <!-- 垂直水平登录的对话框 -->
        <div class="login-dialog">
            <form action="login" method="post">
            <h3>登录</h3>
            <div class="row">
                <span>用户名:</span>
                <input type="text" id="username" placeholder="手机号/邮箱号" name="username">
            </div>
            <div class="row">
                <span>密码:</span>
                <input type="password" id="password" placeholder="请输入密码" name="password">
            </div>
            <div class="row">
                <input type="submit" id="submit" value="登录">
            </div>
            </form>
        </div>
    </div>
</body>
</html>

【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java
注意此处对应的关系:
【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java
3. 修改后端代码

package api;

import model.User;
import model.UserDao;

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;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置请求的编码,使用 utf8 理解请求
        req.setCharacterEncoding("utf8");
        //设置响应的编码,使用 utf8 构造响应
        //resp.setCharacterEncoding("utf8");
        resp.setContentType("text/html;charset=utf8");
        //1.读取参数中的用户名和密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if(username == null ||"".equals(username) || password == null ||"".equals(password)){
            //登录失败
            String html = "<h3>登录失败!用户名/密码为空!</h3>";
            resp.getWriter().write(html);
            return;
        }
        //2.读取数据库,查看用户名是否存在.密码是否匹配
        UserDao userDao = new UserDao();
        User user =userDao.selectByUsername(username);
        if(user == null){
            //用户不存在
            String html = "<h3>登录失败!用户名或密码错误</h3>";
            resp.getWriter().write(html);
            return;
        }
        if(!password.equals(user.getPassword())){
            String html = "<h3>登录失败!用户名或密码错误</h3>";
            resp.getWriter().write(html);
            return;
        }
        //3.用户名密码验证通过,登录成功,接下来就创建会话,使用该会话保存用户信息
        HttpSession session = req.getSession();
        session.setAttribute("user",user);
        //4.重定向,跳转到博客列表页
        resp.sendRedirect("blog_list.html");
    }
}

【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java

4. 检测登录状态

实现让页面强制要求登录,
当用户访问博客列表页/详情页/编辑页,要求用户必须是已经登录的状态.如果用户还没登录,就会强制跳转到登录页面.

实现思路:
在页面加载的时候,专门发起一个新的 ajax . (一个页面里可以发N个ajax请求)以博客列表页为例,先会发一个请求获取博客列表,再发个ajax获取用户的登录状态,如果用户已登录,相安无事.如果未登录,则页面跳转到登录页.

  1. 约定前后端交互接口
  2. 实现前端代码
  3. 实现后端代码
  1. 约定前后端交互接口
    请求:GET/login
    响应:
    HTTP/1.1 200 OK
    {
    userId:1,
    username:‘xxxflower’
    }

响应就把当前登录的用户信息返回回来了,如果未登录,就返回一个userld0user 对象

  1. 实现后端代码
@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json; charset=utf8");
        // 使用这个方法来获取到用户的登录状态.

        // 如果用户未登录, 这里的会话就拿不到!!
        HttpSession session = req.getSession(false);
        if (session == null) {
            // 未登录, 返回一个空的 user 对象
            User user = new User();
            String respJson = objectMapper.writeValueAsString(user);
            resp.getWriter().write(respJson);
            return;
        }
        User user = (User) session.getAttribute("user");
        if (user == null) {
            user = new User();
            String respJson = objectMapper.writeValueAsString(user);
            resp.getWriter().write(respJson);
            return;
        }
        // 确实成功取出了 user 对象, 就直接返回即可.
        String respJson = objectMapper.writeValueAsString(user);
        resp.getWriter().write(respJson);
    }
  1. 开发后端代码:
function checkLogin() {
            $.ajax({
                type: 'get',
                url: 'login',
                success: function(body) {
                    if (body.userId && body.userId > 0) {
                        // 登录成功!!
                        console.log("当前用户已经登录!!");
                        h3.innerHTML = body.username;
                    } else {
                        // 当前未登录
                        // 强制跳转到登录页. 
                        location.assign('login.html');
                    }
                }
            });
        }
        checkLogin();

将此代码粘贴至博客列表页
则效果如下:
【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java

5. 实现显示用户信息的功能

【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java
此处我们是写死的,我们希望这个地方可以动态生成.

  1. 如果是博客列表页,此处显示登陆用户的信息
  2. 如果此处是博客详情页,此时显示的是该文章的作者
  1. 约定前后端接口
    博客列表页:(复用监测登录状态的接口)
    请求:
    GET /login
    响应:
    HTTP/1.1 200 OK
    {
    userId:1,
    username:‘huang’,
    password:‘234’
    }
    由于是在监测登录的接口中直接写,所以后端代码不变,只需要微调前端代码即可
    【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java
    登录可以看到:
    【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java
    博客详情页:
  2. 前后端交互接口
    请求:
    GET/author?blogId = 1
    响应:
    HTTP/1.1 200 OK
    {
    userId:1,
    username:‘huang’,
    password:‘234’
    }
  3. 后端代码:
package api;

import com.fasterxml.jackson.databind.ObjectMapper;
import model.Blog;
import model.BlogDao;
import model.User;
import model.UserDao;

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;

@WebServlet("/author")
public class AuthorServlet extends HttpServlet {
    private ObjectMapper objectMapper = new ObjectMapper();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String blogId = req.getParameter("blogId");
        if(blogId == null){
            resp.setContentType("text/html;charset = utf8");
            resp.getWriter().write("参数非法,缺少blogId!");
            return;
        }
        //根据 blog 查询Blog对象
        BlogDao blogDao = new BlogDao();
        Blog blog = blogDao.selectById(Integer.parseInt("blogId"));
        if(blog == null){
            resp.setContentType("text/html;charset = utf8");
            resp.getWriter().write("没有找到指定博客");
            return;
        }
        //根据BLog中UserId 获取到对应的用户信息
        UserDao userDao = new UserDao();
        User author = userDao.selectById(blog.getUserId());
        String respJson = objectMapper.writeValueAsString(author);
        resp.setContentType("application/json;charset=utf8");
        resp.getWriter().write(respJson);
    }
}

  1. 前端代码:
function getAuthor(){
            $.ajax({
                type:'get',
                url:'author' + location.search,
                success: function(body){
                    //将username设置到页面上
                    let h3 = document.querySelector('.container-left .card h3');
                    h3.innerHTML = body.userId;
                }
            })
        }
        getAuthor();

【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java

6. 退出登录状态

判断登录状态:

  1. 看是否能查到http session对象
  2. session对象里面有没有user

【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java

实现退出登录:

  1. 处理HttpSession
    getSession能够创建/获取会话,但是没有删除会话的方法.但是我们可以通过设置过期时间来达到类似效果
  2. 处理user(推荐) 可以通过removeAttribute来处理
  1. 约定前后端接口
    请求:
    GET/logout
    响应:
    HTTP/1.1 302
    Location:login.html

  2. 实现后端代码:

package api;

import model.User;

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;

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession httpSession = req.getSession(false);
        if(httpSession == null){
            //未登录,直接出错
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前未登录!");
            return;
        }
        httpSession.removeAttribute("user");
        resp.sendRedirect("login.html");
    }
}

  1. 实现前端代码
    修改博客列表页 ,博客编辑页的前端代码:
    【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java
    【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java

7. 发布博客

  1. 约定前后端交互接口
    使用form表单:页面中更多了form标签,同时让form里面能够感知到博客的内容.
    请求:POST/blog
    title=标题&content=正文
    响应:HTTP/1.1 302
    Location:blog_list.html
  2. 编写服务器代码
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 发布博客
        // 读取请求, 构造 Blog 对象, 插入数据库中即可!!
        HttpSession httpSession = req.getSession(false);
        if (httpSession == null) {
            resp.setContentType("text/html; charset=utf8");
            resp.getWriter().write("当前未登录, 无法发布博客!");
            return;
        }
        User user = (User) httpSession.getAttribute("user");
        if (user == null) {
            resp.setContentType("text/html; charset=utf8");
            resp.getWriter().write("当前未登录, 无法发布博客!");
            return;
        }
        // 确保登录之后, 就可以把作者给拿到了.

        // 获取博客标题和正文
        req.setCharacterEncoding("utf8");
        String title = req.getParameter("title");
        String content = req.getParameter("content");
        if (title == null || "".equals(title) || content == null || "".equals(content)) {
            resp.setContentType("text/html; charset=utf8");
            resp.getWriter().write("当前提交数据有误! 标题或者正文为空!");
            return;
        }

        // 构造 Blog 对象
        Blog blog = new Blog();
        blog.setTitle(title);
        blog.setContent(content);
        blog.setUserId(user.getUserId());
        // 发布时间, 在 java 中生成 / 数据库中生成 都行
        blog.setPostTime(new Timestamp(System.currentTimeMillis()));
        // 插入数据库
        BlogDao blogDao = new BlogDao();
        blogDao.add(blog);

        // 跳转到博客列表页
        resp.sendRedirect("blog_list.html");

    }
  1. 客户端代码:
    <!-- 编辑区的容器 -->
    <div class="blog-edit-container">
        <form action="blog" method="post" style="height: 100%;">
            <!-- 博客标题编辑区 -->
            <div class="title">
                <input type="text" id="title" placeholder="输入文章标题" name="title">
                <input type="submit" id="submit" value="发布文章">
            </div>
            <!-- 博客编辑器, 这里用 id 是为了和 markdown 编辑器对接, 而设置的 -->
            <div id="editor">
                <textarea name="content" style="display:none"></textarea>
            </div>
        </form>
    </div>

【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java
后续点击submit就能自动提交
display:none是隐藏元素.
【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java
【JavaEE初阶】博客系统后端,JavaEE初阶,java-ee,java文章来源地址https://www.toymoban.com/news/detail-624914.html

到了这里,关于【JavaEE初阶】博客系统后端的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Java EE初阶十七】网络原理(二)

    2.2.2 关于可靠传输 4.滑动窗口         前面的三个机制,都是在保证 tcp 的可靠性;         TCP 的可靠传输,是会影响传输的效率的.(多出了一些等待 ack 的时间,单位时间内能传输的数据就少了);         滑动窗口,就让可靠传输对性能的影响,更少一些.TCP 只要引入了可

    2024年02月20日
    浏览(43)
  • 【Java EE初阶十六】网络原理(一)

            在网络原理中主要学习TCP/IP四层模型中的重点网络协议         应用层是和程序员接触最密切的;         应用程序:在应用层这里,很多时候都是程序员自定义应用层协议(步骤:1、根据需求,明确要传输的信息,2、约定好信息按照什么样的格式来组织)的

    2024年02月20日
    浏览(38)
  • 【Java EE初阶六】多线程案例(单例模式)

            单例模式是一种设计模式,设计模式是我们必须要掌握的一个技能;         设计模式是软性的规定,且框架是硬性的规定,这些都是技术大佬已经设计好的;         一般来说设计模式有很多种,且不同的语言会有不同的设计模式,(同时 设计模式也可

    2024年02月03日
    浏览(42)
  • 【Java EE 初阶】TCP协议的安全效率机制

    目录 1.应用层协议 2.传输层协议 3.UDP协议格式 4.TCP协议格式 5.TCP的安全效率机制 1.确认应答机制 2.超时重传机制 但是,主机A未收到B发来的确认应答,也可能是因为ACK丢失了; 3.连接管理机制 ​编辑 面试题:会不会有可能变成三次挥手? 面试题:第二个FIN丢包了如何处理?

    2024年02月09日
    浏览(45)
  • 【Java EE初阶三 】线程的状态与安全(下)

             线程安全 : 某个代码,不管它是单个线程执行,还是多个线程执行,都不会产生bug,这个情况就成为“线程安全”。          线程不安全 : 某个代码,它单个线程执行,不会产生bug,但是多个线程执行,就会产生bug,这个情况就成为 “线程不安全”,或者

    2024年02月03日
    浏览(45)
  • 【JavaEE基础学习打卡03】Java EE 平台有哪些内容?

    📜 本系列教程适用于Java Web初学者、爱好者,小白白。我们的天赋并不高,可贵在努力,坚持不放弃。坚信量最终引发质变,厚积薄发。 🚀 文中白话居多,尽量以小白视角呈现,帮助大家快速入门。 🎅 我是 蜗牛老师 ,之前网名是 Ongoing蜗牛 ,人如其名,干啥都慢,所以

    2024年02月12日
    浏览(47)
  • 【JavaEE基础学习打卡02】是时候了解Java EE了!

    📜 本系列教程适用于 Java Web 初学者、爱好者,小白白。我们的天赋并不高,可贵在努力,坚持不放弃。坚信量最终引发质变,厚积薄发。 🚀 文中白话居多,尽量以小白视角呈现,帮助大家快速入门。 🎅 我是 蜗牛老师 ,之前网名是 Ongoing蜗牛 ,人如其名,干啥都慢,所

    2024年02月12日
    浏览(48)
  • 【Java EE初阶八】多线程案例(计时器模型)

            计时器类似闹钟,有定时的功能,其主要是到时间就会执行某一操作,即可以指定时间,去执行某一逻辑(某一代码)。         在java标准库中,提供了Timer类,Timer类的核心方法是schedule( 里面包含两个参数,一个是要执行的任务代码,一个是设置多久之后

    2024年01月21日
    浏览(46)
  • 【Java EE初阶二十二】https的简单理解

             当前网络上,主要都是 HTTPS 了,很少能见到 HTTP.实际上 HTTPS 也是基于 HTTP.只不过 HTTPS 在 HTTP 的基础之上, 引入了\\\"加密\\\"机制;引入 HTTPS 防止你的数据被黑客篡改 ;         HTTPS 就是一个重要的保护措施.之所以能够安全, 最关键的在于\\\"加密”;         明文:

    2024年02月22日
    浏览(53)
  • 【Java EE初阶二十一】http的简单理解(二)

            Referer 描述了当前页面是从哪个页面跳转来的,如果是直接在地址栏输入 url(或者点击收藏夹中的按钮) 都是没有 Referer。如下图所示:         HTTP 最大的问题在于\\\"明文传输”,明文传输就容易被第三方获取并篡改.         HTTPS 针对 HTTP 数据进行了加密 (h

    2024年02月22日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包