栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

博客系统——前后端分离

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

文章目录
  • 准备工作
    • 1.创建maven项目
    • 2. 引入依赖(servlet,jackson,mysql)
    • 3.创建必要的目录
    • 4. 编写代码
    • 5/6. 打包部署程序——直接基于smart Tomcat
      • 如何下载tomcat
      • 如何下载smart Tomcat
    • 7. 在浏览器中验证
  • 编写数据库的操作代码
    • 1.创建数据库/表结构—数据库设计
    • 2. 封装数据库操作
      • 2.1 先创建 DBUtil 封装数据库连接的操作
      • 2.2 创建实体类(使用实体类来表示数据库中的一条记录)
      • 2.3 封装针对数据的增删改查
  • 约定前后端交互接口
    • 1. 实现博客列表
      • 1.1约定前后端交互接口
      • 1.2 实现服务器代码
      • 1.3 编写客户端代码
    • 2. 实现博客详情
      • 2.1 约定前后端交互接口
      • 2.2 实现服务器代码
      • 2.3 实现客户端代码
    • 3. 实现登录
      • 3.1 约定前后端交互接口
      • 3.2 实现服务器代码
      • 3.3 实现客户端代码
    • 实现强制要求登录
      • 约定前后端交互接口
      • 实现服务器代码
      • 实现客户端代码
    • 4. 实现显示用户信息
      • 4.1 约定前后端交互接口
      • 4.2 实现服务器代码
      • 4.3 实现客户端代码
    • 5. 实现注销登录
      • 5.1 约定前后端接口
      • 5.2 实现服务器代码
      • 5.3 实现客户端代码
    • 6. 实现发布博客
      • 6.1 约定前后端接口
      • 6.2 实现服务器代码
      • 6.3 实现客户端代码
    • 7. 实现删除博客
      • 7.1 约定前后端交互接口
      • 7.2 实现服务器代码
      • 7.3 实现客户端代码

引言:

tomcat版本:8.5
开发工具:IDEA
jdk版本:jdk1.8.0_161
此项目是对本博主之前编写的一个纯HTML页面的博客系统进行的一个改进

准备工作 1.创建maven项目

依次点击File→New→Project,选择左侧的Maven项目,点击Next,然后填写项目名称,点击Finish,至此一个maven项目就创建好了。

2. 引入依赖(servlet,jackson,mysql)

去中央仓库搜索下载即可,地址传送门(一般搜索关键字后第一个就是我们所需要的,注意版本)

//这个需要手动敲上去
    
    
    
        javax.servlet
        javax.servlet-api
        
        3.1.0
        
        provided
    
    
    
    
        mysql
        mysql-connector-java
        5.1.47
    
    
    
        com.fasterxml.jackson.core
        jackson-databind
        2.12.6.1
    

引入依赖后记得手动刷新一下,以防万一。(第一次引入的时候时间可能会长一些,要耐心等待,有的时候可能因为网络问题导致引入失败,这时候不要慌,多刷新几次试试)

3.创建必要的目录


web.xml新建的时候选择File选项

web.xml里面填写的内容,直接复制下面的代码即可:



    Archetype Created Web Application

4. 编写代码

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("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("hello");
    }
}
5/6. 打包部署程序——直接基于smart Tomcat 如何下载tomcat

tomcat直接在官网下载即可:官网下载

下载完解压即可,解压的时候最好不要解压到带中文的文件夹里。

如何下载smart Tomcat


然后就按照下面的步骤进行部署⬇️⬇️⬇️

7. 在浏览器中验证

点击上方小绿三角运行,然后在浏览器中输入:http://localhost(也可以是127.0.0.1):8080/blog_system/hello

到这里准备工作算是做完了,接下来就可以执行接下来的步骤了⬇️

编写数据库的操作代码 1.创建数据库/表结构—数据库设计

设计数据库,需要根据当前的需求来进行设计,而我们这个博客页面,一共需要以下几个页面:

  1. 博客列表页,显示博客的列表
  2. 博客详情页,点击博客列表页,上面列出的博客条目,跳转到的页面,显示博客的完整内容
  3. 登录页面
  4. 博客编辑页,基于editor.md搞一个markdown编辑器,基于这个页面来发布博客

我们需要以下需求:

  • 存储博客:当点击发布的时候,博客被发布到服务器上,就要被存起来
  • 存取博客:在博客列表页和博客详情页,能够拿到博客的内容
  • 能够进行登录校验

我们设计表,就需要抓住需求中的实体(关键性的名词)

  1. 博客表:用来存储所有的博客数据
  2. 用户表:用户登录时需要用到

-- 编写建库建表的 sql
create database if not exists blog_system;
use blog_system;
-- 创建一个博客表
drop table if exists blog;
create table blog (
                      blogId int primary key auto_increment,
                      title varchar(1024),
                      content mediumtext,
                      userId int,         -- 文章作者的 id
                      postTime datetime   -- 发布时间
);
-- 给博客插点数据,后面方便我们进行测试
insert into blog values(null,'第一篇博客','好好学习',1,now());
insert into blog values(null,'第二篇博客','天天向上',1,now());
insert into blog values(null,'第三篇博客','明天开始学Java',1,now());
insert into blog values(null,'第四篇博客','努力去见易烊千玺',2,now());
insert into blog values(null,'第五篇博客','累死自己,卷死同学',2,now());

-- 创建一个用户表
drop table if exists user;
create table user (
                      userId int primary key auto_increment,
                      username varchar(128) unique,    -- 后续会使用用户名进行登录, 一般用于登录的用户名都是不能重复的.
                      password varchar(128)
);
insert into user values(null,'panpan','123');
insert into user values(null,'ajiao','123456');

2. 封装数据库操作 2.1 先创建 DBUtil 封装数据库连接的操作
package util;

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

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

//使用这个类和数据库建立连接
public class DBUtil {
    private static final String URL="jdbc:mysql://127.0.0.1:3306/blog_system?characterEncoding=utf8&useSSL=false";
    private static final String USERNAME="root";
    private static final String PASSWORD="root";

    private static volatile DataSource dataSource=null;
    private static DataSource getDataSource(){
        if(dataSource==null){
            synchronized(DBUtil.class){
                if(dataSource==null){
                    dataSource=new MysqlDataSource();
                    ((MysqlDataSource)dataSource).setUrl(URL);
                    ((MysqlDataSource)dataSource).setUser(USERNAME);
                    ((MysqlDataSource)dataSource).setPassword(PASSWORD);
                }
            }
        }
        return dataSource;
    }
    public static Connection getConnection() throws SQLException {
        return getDataSource().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();
            }
        }
    }
}
2.2 创建实体类(使用实体类来表示数据库中的一条记录)

使用实体类来表示数据库中的一条记录,根据数据库创建的表可知我们需要创建 Blog 类和 User 类

Blog 类
package bean;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;


public class Blog {
    private int blogId;
    private String title;
    private String content;
    private int userId;
    private Timestamp postTime;

    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 int getUserId() {
        return userId;
    }

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

//    public Timestamp getPostTime() {
//        return postTime;
//    }
    //把这里的getter方法给改了,不是返回一个时间戳对象,而是返回一个String(格式化好的时间)
    public String getPostTime(){
        //使用SimpleDateFormat来完成时间戳到格式化日期时间的转换
        //这个转换过程,需要在构造方法中指定要转换的格式,然后调用format来进行转换
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return simpleDateFormat.format(postTime);
    }

    public void setPostTime(Timestamp postTime) {
        this.postTime = postTime;
    }
}
User类
package bean;

public class User {
    //先初始化,方便后面判断是否是登陆状态
    private int userId=0;
    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.3 封装针对数据的增删改查

我们把提供了增删改查这样的类,称为 DAO,所以我们可以把实现这类功能的类统一放在一个dao包里面。

BlogDao类
package dao;

import bean.Blog;
import util.DBUtil;

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 insert(Blog blog){
        //JDBC基本代码
        Connection connection=null;
        PreparedStatement statement=null;
        try {
            //1.和数据库建立连接
            connection= DBUtil.getConnection();
            //2.构造SQL语句
            String sql="insert into blog values(null,?,?,?,now())";
            statement= connection.prepareStatement(sql);
            statement.setString(1, blog.getTitle());
            statement.setString(2, blog.getContent());
            statement.setInt(3,blog.getUserId());
            //3.执行SQL语句
            statement.executeUpdate();
            //4.关闭连接,释放资源
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,null);
        }
    }
    //2.能够获取到博客表中的所有博客的信息(用于在博客列表页,此处每篇博客不一定会获取到完整的正文)
    public ListselectAll(){
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        Listblogs=new ArrayList<>();
        try {
            connection=DBUtil.getConnection();
            String sql="select * from blog order by postTime desc";
            statement= connection.prepareStatement(sql);
            resultSet=statement.executeQuery();
            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()>50){
                    content=content.substring(0,50)+"...";
                }
                blog.setContent(content);
                blog.setUserId(resultSet.getInt("userId"));
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                blogs.add(blog);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return blogs;
    }
    //3.能够根据博客id获取到指定的博客内容(用于在博客详情页)
    public Blog selectOne(int blogId){
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            connection=DBUtil.getConnection();
            String sql="select * from blog where blogId=?";
            statement= connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            resultSet=statement.executeQuery();
            //此处我们是使用主键来作为查询条件的,查询结果要么是1要么是0,所以用if即可
            if(resultSet.next()){
                Blog blog=new Blog();
                blog.setBlogId(resultSet.getInt("blogId"));
                blog.setTitle(resultSet.getString("title"));
                blog.setContent(resultSet.getString("content"));
                blog.setUserId(resultSet.getInt("userId"));
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                return blog;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }
    //4.从博客表中,根据博客id删除博客
    public void delete(int blogId){
        Connection connection=null;
        PreparedStatement statement=null;
        try {
            connection=DBUtil.getConnection();
            String sql="delete from blog where blogId=?";
            statement= connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,null);
        }
    }
}
UserDao类
package dao;

import bean.User;
import util.DBUtil;

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


public class UserDao {
    //主要实现
    //1.根据用户名来查找用户信息,会在登录逻辑中使用
    public User selectByName(String username){
        Connection connection=null;
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            connection= DBUtil.getConnection();
            String sql="select * from user where username=?";
            statement= connection.prepareStatement(sql);
            statement.setString(1,username);
            resultSet=statement.executeQuery();
            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) {
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }
    //2.根据用户id来找用户信息
    //博客详情页,就可以根据用户id来查询作者的名字,把作者名字显示出来
    public 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();
            //此处username使用unique约束,要么能查到一个,要么一个都查不到
            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) {
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }
}

到此数据库操作都给准备好了,下面就开始编写前后端的代码了

约定前后端交互接口

在编写前后端代码之前,先把之前纯页面的博客系统全部拷贝到webapp里面

博客系统:码云地址

1. 实现博客列表 1.1约定前后端交互接口
[请求]  GET/blog
[响应] [
   {
        blogId: 1,
        title: "第一篇博客",
        content: "博客正文",
        userId: 1,
        postTime: "2022-06-08 18:08:05"
   },
   {
        blogId: 2,
        title: "第二篇博客",
        content: "博客正文",
        userId: 2,
        postTime: "2022-06-08 18:08:05"
   },
    ...
]

约定浏览器给服务器发送一个 GET /blog 这样的 HTTP 请求, 服务器给浏览器返回了一个 JSON 格式的数据

1.2 实现服务器代码
package servlet;
import bean.Blog;
import com.fasterxml.jackson.databind.ObjectMapper;
import dao.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;

//通过这个类,来处理/blog路径对应的请求
@WebServlet("/blog")
public class BlogServlet extends HttpServlet {
    private ObjectMapper objectMapper=new ObjectMapper();
    //这个方法用来获取到数据库中的博客列表
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //从数据库中查询到博客列表,转成json格式,然后直接返回即可
        BlogDao blogDao=new BlogDao();
        Listblogs=blogDao.selectAll();
        //把blog对象转成JSON格式
        String respJson= objectMapper.writeValueAsString(blogs);
        resp.setContentType("application/json;charset=utf8");
        resp.getWriter().write(respJson);
    }
}
1.3 编写客户端代码



	
	
	
	博客列表
	
	


	
	
	


同学潘 gitHub地址
文章 分类
2 1

效果图如下:

图中的用户名显示的是panpan,而上面的客户端代码中用户名给的是同学潘,这是因为后面我们要实现登录的是哪个用户就显示哪个用户名,因此这里有点差异。

2. 实现博客详情

由于目前点击博客列表页的 “查看全文” , 进入博客详情页后是写死的内容,所以 我们期望能够根据当前的 博客 id 从服务器动态获取博客内容。

2.1 约定前后端交互接口
[请求]
GET /blog?blogId=1 

[响应] {
HTTP/1.1 200OK
Content-Type:application/json;
{
    blogId: 2,
    title: "第二篇博客",
    content: "博客正文",
    userId: 1,
    postTime: "2022-06-08 18:08:05"
},
2.2 实现服务器代码

获取详情页跟获取列表基本相同,所以我们只需要更改一下代码判断是否带参数 blogId,以此来返回是列表页还是详情页。

package servlet;
import bean.Blog;
import com.fasterxml.jackson.databind.ObjectMapper;
import dao.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 javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;

//通过这个类,来处理/blog路径对应的请求
@WebServlet("/blog")
public class BlogServlet extends HttpServlet {
    private ObjectMapper objectMapper=new ObjectMapper();
    //这个方法用来获取到数据库中的博客列表
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //从数据库中查询到博客列表,转成json格式,然后直接返回即可
        //先尝试获取到rep中的blogId参数,如果参数存在,说明是要请求博客详情
        //如果该参数不存在,说明是要请求博客的列表
        BlogDao blogDao=new BlogDao();
        resp.setContentType("application/json;charset=utf8");
        String param=req.getParameter("blogId");
        if(param==null){
            //不存在参数,获取博客列表
            Listblogs=blogDao.selectAll();
            //把blog对象转成JSON格式
            String respJson= objectMapper.writeValueAsString(blogs);
            resp.getWriter().write(respJson);
        }else{
             //存在参数,获取博客详情
            int blogId=Integer.parseInt(param);
            Blog blog=blogDao.selectOne(blogId);
            String respJson=objectMapper.writeValueAsString(blog);
            resp.getWriter().write(respJson);
        }
    }
}
2.3 实现客户端代码



    
    
    
    博客详情页
    
    
    
    






    
	


同学潘 gitHub地址
文章 分类
2 1


效果图如下:

注意:当我们在进行程序验证的时候,要牢记一件事情,浏览器的缓存可能会影响到结果,你可能修改了之后再去同一个浏览器访问的时候,他并没有发生改变,因为浏览器可能把你上次访问的页面给保存到本地了,下次在尝试访问的时候访问的就是本地的内容,所以这个时候我们要按下: Ctrl + F5强制刷新一下

3. 实现登录
  1. 登陆页面提供一个 form 表单,通过 form 的方式把用户名密码提交给服务器
  2. 服务器端验证用户名密码是否正确
  3. 如果密码正确, 则在服务器端创建 Session,并把 sessionId 通过 Cookie 返回给浏览器
3.1 约定前后端交互接口
[请求]
POST /login
Content-Type: application/x-www-form-urlencoded
username=panpan&password=123
[响应]
HTTP/1.1 302 
Location: https://blog.csdn.net/m0_46468731/article/details/blog_list.html//登录成功以后,自动跳转到主页(博客列表页https://blog.csdn.net/m0_46468731/article/details/blog_list.html)
3.2 实现服务器代码
package servlet;

import bean.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import dao.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 {
    private ObjectMapper objectMapper=new ObjectMapper();
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf8");
        resp.setCharacterEncoding("utf8");
        //1.获取到请求中的参数
        String username=req.getParameter("username");
        String password=req.getParameter("password");
        if(username==null||"".equals(username)||password==null||"".equals(password)){
            //请求的内容缺失,肯定是登陆失败!
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前的用户名或密码为空!");
            return;
        }
        //2.和数据库中的内容进行比较
        UserDao userDao=new UserDao();
        User user=userDao.selectByName(username);
        if(user==null||!user.getPassword().equals(password)){
            //用户没有查到或者密码不匹配,也是登录失败!
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("用户名或者密码错误!");
            return;
        }
        //3.如果通过比较,就创建会话
        HttpSession session= req.getSession(true);
        //把刚才的用户信息,存储到会话中
        session.setAttribute("user",user);
        //返回一个重定向报文,跳转到博客列表页
        resp.sendRedirect("https://blog.csdn.net/m0_46468731/article/details/blog_list.html");
    }
}

3.3 实现客户端代码



    
    
    
    登录页面
    
    


    
    


实现强制要求登录

当用户访问 博客列表页 和 博客详情页 时, 如果用户当前尚未登陆, 就自动跳转到登陆页面

这个可以在博客列表页/详情页加载的时候,通过 ajax 访问一下服务器,获取当前的登录状态,看看能不能获取到,如果获取到了,就说明当前确实是已经登陆了,此时就可以留在这个页面;如果没有获取到,说明是未登录的,就会跳转到登录页面让你登录。

约定前后端交互接口
[请求]
GET/login
[响应]
HTTP/1.1 200OK
Content-Type:application/json

{
    userId: 1,
    username: 'panpan',
}

登陆了,就直接返回当前登录的用户信息;如果未登录,则直接返回一个userId 为 0 的对象

实现服务器代码

在LoginServlet中加入以下代码即可:

//这个方法用来让前端检测当前的登陆状态
    @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=new User();
            resp.getWriter().write(objectMapper.writeValueAsString(user));
            return;
        }
        User user=(User)session.getAttribute("user");
        if(user==null){
            //虽然有会话,但是会话里面没有user对象,也视为未登录
            user=new User();
            resp.getWriter().write(objectMapper.writeValueAsString(user));
            return;
        }
        //已经登录的状态
        //注意,此处不要把密码给返回到前端
        user.setPassword("");
        resp.getWriter().write(objectMapper.writeValueAsString(user));
    }
实现客户端代码

在https://blog.csdn.net/m0_46468731/article/details/blog_list.html中加入以下代码即可:

//加上一个逻辑,通过GET/login这个接口来获取下当前的登录状态
		function getUserInfo(){
			$.ajax({
				type:'get',
				url:'login',
				success:function(body){
					//判定此处的body是不是一个有效的user对象(userId是否非0)
					if(body.userId&&body.userId>0){
						//登录成功,不做处理
						console.log("当前用户登录成功!用户名:"+body.username);
					}else{
						//登录失败,让前端页面跳转到blog_login.html
						alert("当前您尚未登录!请登录后再访问博客列表!");
						location.assign('blog_login.html');
					}
				},
				error:function(){
					alert("当前您尚未登录!请登录后再访问博客列表!");
					location.assign('blog_login.html');
				}
			});
		}
		getUserInfo();

博客详情页也可以有这样的功能,把这段代码添加到https://blog.csdn.net/m0_46468731/article/details/blog_detail.html中即可

function getUserInfo(){
			$.ajax({
				type:'get',
				url:'login',
				success:function(body){
					//判定此处的body是不是一个有效的user对象(userId是否非0)
					if(body.userId&&body.userId>0){
						//登录成功,不做处理
						console.log("当前用户登录成功!用户名:"+body.username);
					}else{
						//登录失败,让前端页面跳转到blog_login.html
						alert("当前您尚未登录!请登录后再访问博客详情!");
						location.assign('blog_login.html');
					}
				},
				error:function(){
					alert("当前您尚未登录!请登录后再访问博客列表详情!");
					location.assign('blog_login.html');
				}
			});
		}
		getUserInfo();

效果图如下:

4. 实现显示用户信息

我们期望用户信息可以随着用户的登陆而发生改变,如果当前页面是博客列表页,则显示当前登陆用户的信息;如果当前页面是博客详情页,则显示该博客的作者用户信息。

4.1 约定前后端交互接口

在博客列表页,获取登录用户的用户信息:

[请求]
GET /user
[响应] {
 userId: 1,
 username: test
}

在博客详情页,获取当前文章作者的用户信息:

[请求]
GET /user?blogId=1
[响应] {
 userId: 1,
 username: test
}
4.2 实现服务器代码

主要针对博客详情页:

package servlet;

import bean.Blog;
import bean.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import dao.BlogDao;
import dao.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("/authorInfo")
public class AuthorServlet extends HttpServlet {
    private  ObjectMapper objectMapper=new ObjectMapper();
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf8");
        //通过这个方法,来获取到指定的博客的作者信息
        String param=req.getParameter("blogId");
        if(param==null||"".equals(param)){
            //参数缺少了
            resp.getWriter().write("{"ok":false,"reason":"参数缺失!"}");
            return;
        }
        //根据当前blogId在数据库中进行查找,找到对应的Blog对象,再进一步的根据blog对象,找到作者信息
        BlogDao blogDao=new BlogDao();
        Blog blog=blogDao.selectOne(Integer.parseInt(param));
        if(blog==null){
            resp.getWriter().write("{"ok":false,"reason":"要查询的博客不存在!"}");
            return;
        }
        //根据blog对象,查询到用户对象
        UserDao userDao=new UserDao();
        User author= userDao.selectById(blog.getUserId());
        if(author==null){
            resp.getWriter().write("{"ok":false,"reason":"要查询的用户不存在!"}");
            return;
        }
        //把author返回到浏览器这边
        //不要把密码给返回到前端
        author.setPassword("");
        resp.getWriter().write(objectMapper.writeValueAsString(author));
    }
}
4.3 实现客户端代码

对上述https://blog.csdn.net/m0_46468731/article/details/blog_list.html和https://blog.csdn.net/m0_46468731/article/details/blog_detail.html代码进行修改,实现登录成功过后显示相应的用户名

https://blog.csdn.net/m0_46468731/article/details/blog_list.html
//加上一个逻辑,通过GET/login这个接口来获取下当前的登录状态
		function getUserInfo(){
			$.ajax({
				type:'get',
				url:'login',
				success:function(body){
					//判定此处的body是不是一个有效的user对象(userId是否非0)
					if(body.userId&&body.userId>0){
						//登录成功,不做处理
						console.log("当前用户登录成功!用户名:"+body.username);
						//根据当前用户登录的情况,把当前用户名设置到界面上
						ChangeUserName(body.username);
					}else{
						//登录失败,让前端页面跳转到blog_login.html
						alert("当前您尚未登录!请登录后再访问博客列表!");
						location.assign('blog_login.html');
					}
				},
				error:function(){
					alert("当前您尚未登录!请登录后再访问博客列表!");
					location.assign('blog_login.html');
				}
			});
		}
		getUserInfo();
		function ChangeUserName(username){
			let h3=document.querySelector('.card>h3');
			h3.innerHTML=username;
		}
https://blog.csdn.net/m0_46468731/article/details/blog_detail.html
function ChangeUserName(username){
			let h3=document.querySelector('.card>h3');
			h3.innerHTML=username;
		}
		//从服务器获取一下当前博客的作者信息,并显示到界面上
		//参数user就是刚才从服务器拿到的当前登陆用户的信息
		function getAuthorInfo(user){
			$.ajax({
				type:'get',
				url:'authorInfo'+location.search,
				success:function(body){
					//此处的body,就是服务器返回的User对象,是文章的作者信息
					if(body.username){
						//如果响应中的username存在,就把这个值设置到页面上
						ChangeUserName(body.username);
					}else{
						console.log("获取作者信息失败!"+body.reason);
					}
				}
			});
		}

效果图如下:

总结:

  1. 对于博客列表页,要显示登录用户信息,由于登录用户信息在检测用户是否登录的接口中,就已经拿到了,所以只需要把拿到的用户信息,显示到界面上即可(只需要动前端,后端不必修改)
  2. 对于博客详情页,要显示出文章作者的信息,需要提供一个新的 api ,让客户端传一个博客 id 过去,然后在服务器这里查询到用户信息,查到之后返回给页面

页面和服务器之间的交互,不一定只有一次,大概率是会有多次的。
我们这里写的博客列表页涉及到两次交互:

  1. 从服务器拿到博客列表数据
  2. 从服务器拿到当前的登录用户信息

博客详情页涉及到三次交互:

  1. 从服务器拿到博客的详细内容
  2. 从服务器拿到了当前的登录用户信息
  3. 从服务器拿到了当前文章的作者信息

我们以后可能还会遇到不止两次三次的,有些可能复杂的十几次也是正常的

5. 实现注销登录

就是退出登录状态,在导航栏安排一个"注销"按钮,当用户点击注销之后,就会在服务器上取消登录状态,并且跳回到登录页面,希望在点击之后,能够给服务器发送一个 HTTP 请求,从而触发注销动作(其实就是把会话中的信息给删除掉)

5.1 约定前后端接口
[请求]
GET /https://blog.csdn.net/m0_46468731/article/details/logout
[响应]
HTTP/1.1 302
Location: login.html
5.2 实现服务器代码

从 session 中删除掉保存的 User 对象,响应重定向到 login.html 页面

package servlet;

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("/https://blog.csdn.net/m0_46468731/article/details/logout")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //先找到当前用户的会话
        HttpSession session=req.getSession(false);
        if(session==null){
            //用户没有登录!那么也就谈不上注销
            resp.getWriter().write("当前用户尚未登录!无法注销!");
            return;
        }
        //然后把这个用户的会话中的信息给删除掉就行了!
        session.removeAttribute("user");
        resp.sendRedirect("blog_login.html");
    }
}

5.3 实现客户端代码

只需要把https://blog.csdn.net/m0_46468731/article/details/blog_list.html,https://blog.csdn.net/m0_46468731/article/details/blog_detail.html,https://blog.csdn.net/m0_46468731/article/details/blog_edit.html中a标签中的href属性改为https://blog.csdn.net/m0_46468731/article/details/logout即可❗❗

注销
6. 实现发布博客

在博客编辑页中,当用户输入博客标题和正文之后,点击发布,这个时候就会把博客数据提交到服务器,由服务器存储到数据库中。

6.1 约定前后端接口
[请求]
POST /blog
Content-Type: application/x-www-form-urlencoded
title=标题&content=正文...
[响应]
HTTP/1.1 302
Location: https://blog.csdn.net/m0_46468731/article/details/blog_list.html
6.2 实现服务器代码

在 BlogServlet 里面添加 一个 doPost 方法来处理 post 请求,核心的操作就是读取请求中的标题和正文,构造 Blog 对象,并插入数据库

@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session=req.getSession(false);
        if(session==null){
            //当前用户未登录,不能提交博客!
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前用户未登录,不能提交博客!");
            return;
        }
        User user=(User)session.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设置的属性,主要是title,content,userId(作者信息)
        //postTime和blogId哦都不需要手动指定,都是插入数据的时候自动生成的
        Blog blog=new Blog();
        blog.setTitle(title);
        blog.setContent(content);
        //作者id就是当前提交这个博客的用户的身份信息
        blog.setUserId(user.getUserId());
        BlogDao blogDao=new BlogDao();
        blogDao.insert(blog);
        //重定向到博客列表页
        resp.sendRedirect("https://blog.csdn.net/m0_46468731/article/details/blog_list.html");
    }
6.3 实现客户端代码

需要一个form表单,把这里的内容嵌套上:




    
    
    
    博客编辑页
    
    
    
    






    
    
    

效果图如下:

7. 实现删除博客

删除博客,肯定不是可以随便删除的,约定只有自己能删除自己的博客,不能删除别人的博客❗❗ (此处咱们暂时不考虑管理员)

界面上的处理: 在博客详情页这里,就去进行判定,判定看当前这个博客的作者,是否就是登录的用户。如果是,就在导航栏里显示一个“删除按钮";如果不是,就不显示删除按钮
服务器处理: 用户点击删除按钮,触发一个HTTP请求, HTTP请求就会让服务器删除指定的博客,服务器收到请求之后,就会把这个博客从数据库里给删除掉

7.1 约定前后端交互接口
[请求]
GET /blogDelete?blogId=1
[响应] 
直接跳转到 博客列表页 即可
7.2 实现服务器代码
package servlet;

import bean.Blog;
import bean.User;
import dao.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 javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/blogDelete")
public class BlogDeleteServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.检查当前用户是否登录
        HttpSession session= req.getSession(false);
        if(session==null){
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前尚未登录,不能删除!");
            return;
        }
        User user=(User)session.getAttribute("user");
        if(user==null){
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前尚未登录,不能删除!");
            return;
        }
        //2.获取到参数中的blogId
        String blogId=req.getParameter("blogId");
        if(blogId==null||"".equals(blogId)){
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前blogId的参数不对!");
            return;
        }
        //3.获取要删除的博客信息
        BlogDao blogDao=new BlogDao();
        Blog blog =blogDao.selectOne(Integer.parseInt(blogId));
        if(blog==null){
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前要删除的博客不存在!");
            return;
        }
        //4.再次校验,当前的用户是否就是博客的作者
        if(user.getUserId()!= blog.getUserId()){
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前登录的用户不是作者,没有权限删除!");
            return;
        }
        //5.确认无误,开始删除
        blogDao.delete(Integer.parseInt(blogId));
        //6.重定向到博客列表页
        resp.sendRedirect("https://blog.csdn.net/m0_46468731/article/details/blog_list.html");
    }
}
7.3 实现客户端代码



    
    
    
    博客详情页
    
    
    
    






    
	


gitHub地址
文章 分类
2 1

效果图如下:

目前实现的功能只有这么多,具体其他功能以后随缘实现❗❗❗

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/979292.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号