实现博客系统

news2024/9/20 18:25:52

目录

一、博客系统简介

二、准备工作 

三、设计实现数据库 

四、封装数据库 

创建User类和Blog类

使用JDBC连接数据库

创建BlogDAO类操作数据库中的Blog表 

创建UserDAO类操作数据库中的user表 

五、实现具体功能 

1、实现博客列表页

约定前后端交互接口

服务器端 

客户端 

2、实现博客详情页 

约定前后端交互接口

服务器端 

客户端 

 3、实现登录页

 约定前后端交互接口

服务器端 

客户端 

4、实现强制要求登陆 

约定前后端交互接口 

服务器端 

客户端 

5、实现显示用户信息 

约定前后端交互接口 

服务器端

客户端

6、实现发布博客 

实现前后端交互接口

服务器端 

客户端 

7、删除博客 

约定前后端交互接口

服务器端 

客户端 

8、实现注销功能 

约定前后端交互接口

服务器端 

客户端 

六、效果展示 


一、博客系统简介

现进行登录确认身份,登录成功后进入博客列表页,在博客列表页可以选择查看全文,如果是自己写的博客也可以选择删除。

二、准备工作 

创建一个maven项目,在pom.xml中引入Mysql依赖、Servlet依赖以及Jackson依赖。

<dependencies>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <!-- 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>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.13.5</version>
        </dependency>
    </dependencies>

创建目录结构,并将前端页面文件添加到目录中。 

 web.xml文件的内容如下:

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>
</web-app>

三、设计实现数据库 

创建blog_system数据库。

 create database blog_system ;

创建blog表,有blogId(博客编号) 、title(博客标题)、content(博客内容)、userId(作者编号)、postTime(发布时间)这些属性。

create table blog
(
    blogId  int primary key auto_increment,
    title varchar(1024),
    content mediumtext,
    userId  int,
    postTime    datetime
);

向blog表中插入一些数据。

insert into blog values(null, '这是第一篇博客', '从今天开始, 我要认真学 Java', 1, now());
insert into blog values(null, '这是第二篇博客', '从昨天开始, 我要认真学 Java', 1, now());
insert into blog values(null, '这是第三篇博客', '从前天开始, 我要认真学 Java', 1, now());
insert into blog values(null, '这是第一篇博客', '从今天开始, 我要认真学 C++', 2, now());
insert into blog values(null, '这是第二篇博客', '从昨天开始, 我要认真学 C++', 2, now());

创建user表,有userId(用户编号)、userName(用户名)、password(密码)这些属性。

create table user(
    userId int primary key auto_increment,
    userName varchar(100) unique ,
    password varchar (100)
);

同样也向user表中插入一些数据。

insert into user values(null,'zhangyi','1234');
insert into user values(null,'zhanger','1234');
insert into user values(null,'zhangsan','1234');

四、封装数据库 

创建User类和Blog类

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

    public Blog(int blogId, String title, String content, int userId, Timestamp postTime) {
        this.blogId = blogId;
        this.title = title;
        this.content = content;
        this.userId = userId;
        this.postTime = 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 String getPostTime() {
       SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
       return simpleDateFormat.format(postTime);
    }

    public void setPostTime(Timestamp postTime) {
        this.postTime = postTime;
    }
}
public class User {
    private int userId;
    private String userName;
    private String password;

    public User(int userId, String userName, String password) {
        this.userId = userId;
        this.userName = userName;
        this.password = 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;
    }
}

使用JDBC连接数据库

创建DBUtil连接数据库以及相关资源的关闭。

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 user = "root";
    private static final String password = "1234";
    private static volatile DataSource dataSource;
    private static  DataSource getDataSource(){
         if(dataSource == null){
             synchronized (DBUtil.class){
                 if (dataSource == null){
                     dataSource = new MysqlDataSource();
                     ((MysqlDataSource)dataSource).setURL(url);
                     ((MysqlDataSource)dataSource).setUser(user);
                     ((MysqlDataSource)dataSource).setPassword(password);
                 }
             }
         }
         return dataSource;
    }
    public static Connection getConnection() throws SQLException {
        return (Connection) getDataSource().getConnection();
    }
    public static void closeResource(Connection connection, PreparedStatement statement, ResultSet resultSet)  {
        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();
            }
        }
    }
}

创建BlogDAO类操作数据库中的Blog表 

public class BlogDAO {
    //获取博客表中的所有博客信息
    public List<Blog> getAllBlogs()  {
        List<Blog> list = new LinkedList<>();
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        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"));
                String content = resultSet.getString("content");
                if(content.length() > 50){
                    content = content.substring(0,50);
                }
                blog.setContent(content);
                blog.setTitle(resultSet.getString("title"));
                blog.setUserId(resultSet.getInt("userId"));
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                list.add(blog);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtil.closeResource(connection,statement,resultSet);
        }
        return list;
    }
    //获取指定id的博客
    public Blog getBlog(int blogId)  {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            connection = DBUtil.getConnection();
            String sql = "select * from blog where userId = ?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            resultSet = statement.executeQuery();
            Blog blog = new Blog();
            if(resultSet.next()) {
                blog.setBlogId(resultSet.getInt("blogId"));
                blog.setContent(resultSet.getString("content"));
                blog.setTitle(resultSet.getString("title"));
                blog.setUserId(resultSet.getInt("userId"));
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                return blog;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.closeResource(connection,statement,resultSet);
        }
        return null;
    }
    //插入一篇博客
    public void addBlog(Blog blog) throws SQLException {
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            connection = DBUtil.getConnection();
            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());
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.closeResource(connection,statement,null);
        }

    }
    //删除一篇博客
    public void deleteBlog(int blogId) throws SQLException {
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            connection = DBUtil.getConnection();
            String sql = "delete from blog where userId = ?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.closeResource(connection,statement,null);
        }
    }
}

创建UserDAO类操作数据库中的user表 

public class UserDAO {
    //通过用户名查询用户信息
    public User getUserByName(String name){
        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,name);
            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.closeResource(connection,statement,resultSet);
        }
        return null;
    }
    //通过id查询用户信息
    public User getUserById(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();
            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.closeResource(connection,statement,resultSet);
        }
        return null;
    }
    //删除用户
    public void deleteUser(int userId) throws SQLException {
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            connection = DBUtil.getConnection();
            String sql = "delete from user where userId = ?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,userId);
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.closeResource(connection,statement,null);
        }
    }
}

五、实现具体功能 

1、实现博客列表页

约定前后端交互接口

//请求
GET/blog
//响应
{
    {
        blogId:xx;
        title:xxx;
        content:xxxx;
        userId:xx;
        postTime:xxx;
    },
    {
        blogId:xx;
        title:xxx;
        content:xxxx;
        userId:xx;
        postTime:xxx;
    },
    ……
}

服务器端 

重写doGet方法来获取数据库中的博客列表,设置响应格式为Json,字符集为utf8,先定义一个Json对象objectMapper,然后利用blogDAO对象从数据库中获取到所有的博客,并将其存到List中,然后利用Json对象将其转换成字符串,并写进响应中。

//获取数据库中的博客列表
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        //设置响应格式
        resp.setContentType("application/json;charset=utf8");
        BlogDAO blogDAO = new BlogDAO();
        List<Blog> blogs = blogDAO.getAllBlogs();
        //将blogs对象装成Json格式的字符串
        String respJson = objectMapper.writeValueAsString(blogs);
        resp.getWriter().write(respJson);
    }

客户端 

页面加载的时候利用ajax访问服务器,获取到数据库中的博客列表,因为博客列表的数目不确定,就需要构造div,对body进行遍历,向div中添加各种元素。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>blog-list</title>
    <link rel="stylesheet" href="common.css">
    <link rel="stylesheet" href="container.css">
</head>
<body>
    <div class="nav">
        <img src="logo.jpg">
        <span class="name">博客系统</span>
        <span class="blank"></span>
        <a href="#">主页</a>
        <a href="#">写博客</a>
        <a href="#">注销</a>
    </div>
    <div class="container">
        <div class="left">
        <div class="card">
            <img class="avatar" src="x.jpg" >
            <h3>小郭同学</h3>
            <a class="gitee" href="#"> gitee地址</a>
            <div class="counter">
                <span>文章</span>
                <span>专栏</span>
            </div>
            <div class="counter">
                <span>6</span>
                <span>2</span>
            </div>
        </div>
        </div>
        <div class="right">
        <!--<div class="blog">
            <div class="title">&lt;!&ndash;第一篇博客&ndash;&gt;</div>
            <div class="time">&lt;!&ndash;2022-6-09&ndash;&gt;</div>
           <div class="desc">&lt;!&ndash; Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium error esse impedit magni placeat possimus repellendus veniam, veritatis voluptas? Cum deserunt explicabo neque non placeat quaerat quam? At, blanditiis, non!&ndash;&gt;</div>
            <a  class="a" href="#">查看全文</a>
        </div>-->
        </div>
    </div>
    <script src="https://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
    <script>
        //在页面加载的时候,利用ajax向服务器发送请求,获取到博客列表信息后,在页面进行显示
        function getBlogList(){
            $.ajax({
                type:'get',
                url:'blog',
                success:function(body){
                    //获取到的body是JS对象的数组,因为数组大小每次可能都不一样,就需要构造div
                    let rightDiv = document.querySelector('.right');
                    for(let blog of body){
                        let blogDiv = document.createElement('div');
                        blogDiv.className = 'blog';
                        let titleDiv = document.createElement('div');
                        titleDiv.className = 'title';
                        titleDiv.innerHTML = blog.title;
                        blogDiv.appendChild(titleDiv);
                        let postTimeDiv = document.createElement('div');
                        postTimeDiv.className = 'postTime';
                        postTimeDiv.innerHTML = blog.postTime;
                        blogDiv.appendChild(postTimeDiv);
                        let descDiv = document.createElement('div');
                        descDiv.className = 'desc';
                        descDiv.innerHTML = blog.content;
                        blogDiv.appendChild(descDiv);
                        let a = document.createElement('a');
                        a.innerHTML = '查看全文';
                        a.href = 'blog-detail.html?blogId='+blog.blogId;
                        blogDiv.appendChild(a);
                        rightDiv.appendChild(blogDiv);
                    }
                },
                error:function(){
                    alert('获取博客列表失败')
                }
            })
        };
        getBlogList();
    </script>
</body>
</html>

2、实现博客详情页 

约定前后端交互接口

//请求
GET/blog?blogId=1
//响应
HTTP/1.1 200 OK
Content-Type:application/json
 {
        blogId:xx;
        title:xxx;
        content:xxxx;
        userId:xx;
        postTime:xxx;
  }

服务器端 

可以在实现博客列表详情页列表的服务器端代码进行扩充,首先查看请求参数中是否有blogId,若有则表示是指定一篇博客,就利用BlogDAO对象获取到指定的博客,然后写到响应中。

@WebServlet("/blog")
public class BlogServlet extends HttpServlet {
    //获取数据库中的博客列表
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        //设置响应格式
        resp.setContentType("application/json;charset=utf8");
        BlogDAO blogDAO = new BlogDAO();
        String result = req.getParameter("blogId");
        if(result == null){
            List<Blog> blogs = blogDAO.getAllBlogs();
            //将blogs对象装成Json格式的字符串
            String respJson = objectMapper.writeValueAsString(blogs);
            resp.getWriter().write(respJson);
        }else{
            Blog blog = blogDAO.getBlog(Integer.parseInt(result));
            String respJson = objectMapper.writeValueAsString(blog);
            resp.getWriter().write(respJson);
        }
    }
}

客户端 

查看全文时就会跳转到博客详情页,利用ajax来处理响应,对于content由于在编辑博客时用的markdown字符串进行编辑的,但是展示时需要渲染后的结果,就需要利用引入editor依赖来完成。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Blog-detail</title>
    <link rel="stylesheet" href="common.css">
    <link rel="stylesheet" href="container.css">
    <!-- 引入 editor.md 的依赖 -->
    <link rel="stylesheet" href="editor.md/css/editormd.min.css" >
    <script src="js/jquery.min.js"></script>
    <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>
</head>
<body>
<div class="nav">
    <img src="logo.jpg">
    <span class="name">博客系统</span>
    <span class="blank"></span>
    <a href="#">主页</a>
    <a href="#">写博客</a>
    <a href="#">注销</a>
</div>
<div class="container">
    <div class="left">
        <div class="card">
            <img class="avatar" src="x.jpg" >
            <h3>小郭同学</h3>
            <a class="gitee" href="#"> gitee地址</a>
            <div class="counter">
                <span>文章</span>
                <span>专栏</span>
            </div>
            <div class="counter">
                <span>6</span>
                <span>2</span>
            </div>
        </div>
    </div>
    <div class="right">
        <div class="blog">
            <h3 class="title"></h3>
            <div class="postTime"></div>
            <div id="desc">
            </div>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
    function getBlog(){
        //在页面加载的时候,利用ajax向服务器发送请求,获取到博客列表信息后,在页面进行显示
       $.ajax({
           type:'get',
           //表示blog=blogId
           url:'blog'+location.search,
           success:function(body){
                let h3 = document.querySelector(".blog>h3");
                h3.innerHTML = body.title;
                let postTime = document.querySelector(".postTime");
                postTime.innerHTML = body.postTime;
                //由于在编辑博客时用的markdown字符串进行编辑的,但是展示时需要渲染后的结果
               // let content = document.querySelector('.desc');
               // content.innerHTML = body.content;
               editormd.markdownToHTML('desc', {
                   markdown: body.content
               });
           },
           error:function(){
               alert("查看全文失败!");
           }
       });

    }
    getBlog();
</script>

</body>
</html>

 3、实现登录页

 约定前后端交互接口

使用form表单来进行提交

//请求
POST/login
Content-Type:application/x-www-form-urlencoded
username=?&password=?
//响应
HTTP/1.1 302
Location:blog_list.html

服务器端 

先将请求和响应都按照utf8进行解析避免出现乱码,然后获取到请求中的userName和password判断是否与数据库匹配,若匹配就创建会话跳转到博客列表页。

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf8");
        resp.setCharacterEncoding("utf8");
        resp.setContentType("text/html;charset=utf8");
        String userName = req.getParameter("userName");
        String password = req.getParameter("password");
        if(userName == null || "".equals(userName) || password == null || "".equals(password)){
            resp.getWriter().write("用户名或密码不能为空");
            return;
        }
        UserDAO userDAO = new UserDAO();
        User user = userDAO.getUserByName(userName);
        if(user != null && user.getPassword().equals(password)){
            //创建会话
            HttpSession session = req.getSession(true);
            //将信息存储到绘画中
            session.setAttribute("user",user);
            //返回重定向报文,跳转到详情页
            resp.sendRedirect("blog-list.html");
        }else{
            resp.getWriter().write("用户名或密码错误");
        }
    }
}

客户端 

利用form表单进行提交。

<form action="login" method="post">
    <div class="row">
        <span>用户名</span>
        <span><input  class="input" type="text" name="userName"></span>
    </div>
    <div class="row">
        <span>密码</span>
        <span><input  class="input" type="password" name="password"></span>
    </div>
    <div class="submit">
        <input type="submit" id="submit" value="提交">
    </div>
</form>

4、实现强制要求登陆 

对于博客列表页和博客详情页等都需要在登录成功的基础上来进行后序的操作。

约定前后端交互接口 

登录状态就返回当前用户的信息,未登录就返回userId为0的对象。

//请求
GET/login
//响应
HTTP/1.1 200 OK
Content-Type:application/json
{
    userId:xx,
    userName
}

服务器端 

先判断是否创建会话,再判断会话中是否存在user对象,两种情况等都满足表示已经登录,否则就是未登录状态。

//获取当前的登录状态
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        resp.setContentType("application/json;charset=utf8");
        HttpSession session = req.getSession(false);
        User user = new User();
        if(session == null){
            //未创建会话,表示未登录
            resp.getWriter().write(objectMapper.writeValueAsString(user));
            return;
        }
        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));
    }

客户端 

在博客列表页和详情页等加入该方法来判断是否登录,若未登录就跳转到登录页面进行登录。

//获取当前登录状态
        function getUserInfo(pageName){
            $.ajax({
                type:'get',
                url:'login',
                success:function(body){
                    //判定body中的user对象是否有效
                    if(body.userId && body.userId > 0){
                        //表示登录成功,暂时不做处理
                    }else{
                        alert("您当前尚未登录");
                        //跳转到登录页
                        location.assign('blog-login.html');
                    }
                },
                error:function(){
                    alert("您当前尚未登录");
                    //跳转到登录页
                    location.assign('blog-login.html');
                }
            });
        }

5、实现显示用户信息 

在登录之后,博客详情页能显示当前作者的个人信息。 

进入博客详情页之后能显示作者的个人信息。  

约定前后端交互接口 

//请求
GET/user
//响应
{
    userId:xx,
    userName:xxx
    
}
//请求
GET/user?userId=xx
//响应
{
    userId:xx,
    userName:xxx
    
}

服务器端

在数据库中先得到当前博客的id,再获取到其作者信息。

@WebServlet("/authorInfo")
public class AuthorServlet extends HttpServlet {
    @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;
        }
        BlogDAO blogDAO = new BlogDAO();
        Blog blog = blogDAO.getBlog(Integer.parseInt(param));
        if(blog == null){
            resp.getWriter().write("{\"ok\":false,\"reason:\":\"要查询的博客不存在!\"}");
            return;
        }
        UserDAO userDAO = new UserDAO();
        User author = userDAO.getUserById(blog.getUserId());
        if(author == null){
            resp.getWriter().write("{\"ok\":false,\"reason:\":\"要查询的用户不存在!\"}");
            return;
        }
        ObjectMapper objectMapper = new ObjectMapper();
        author.setPassword("");
        resp.getWriter().write(objectMapper.writeValueAsString(author));
    }
}

客户端

只需要在登录成功时将用户名改成当前登录的用户名。

function changeUserName(userName){
        let h3 = document.querySelector('.card>h3');
        h3.innerHTML = userName;
    }

在进入博客列表详情页时显示作者名。 

 function getAuthorInfo(user){
        $.ajax({
            type:'get',
            url:'authorInfo'+location.search,
            success:function(body){
                if(body.userName){
                    changeUserName(body.userName);
                }else{
                    alert("获取作者信息失败")
                }
            },
            error:function(){
                alert("获取作者信息失败")
            }
        });
    }

6、实现发布博客 

实现前后端交互接口

//请求
POST/blog
Content-Type:application/x-www-form-urlencoded
//响应
HTTP/1.1 302
Location:blog_list.html

服务器端 

先确保用户是登录状态,然后再确认发表的博客标题和内容都不能为空,然后将发表的博客插入到数据库中,页面跳转到博客列表页。

//发表博客
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf8");
        resp.setCharacterEncoding("utf8");
        resp.setContentType("text/html;charset=utf8");
        ObjectMapper objectMapper = new ObjectMapper();
        HttpSession session = req.getSession(false);
        if(session == null){
            resp.getWriter().write("用户未登录");
            return;
        }
        User user = (User)session.getAttribute("user");
        if(user == null){
            resp.getWriter().write("用户未登录");
            return;
        }
        String title = req.getParameter("title");
        String content = req.getParameter("content");
        if(title == null || "".equals(title) || content == null || "".equals(title)){
            resp.getWriter().write("提交博客失败,缺少博客标题或内容");
            return;
        }
        Blog blog = new Blog();
        blog.setUserId(user.getUserId());
        blog.setTitle(title);
        blog.setContent(content);
        BlogDAO blogDAO = new BlogDAO();
        try {
            blogDAO.addBlog(blog);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        resp.sendRedirect("blog-list.html");
    }

客户端 

利用form表单将内容进行提交。

<form action="blog" method="post" style="height:100%">
            <div class="title">
                <input type="text" placeholder="在此处输入标题" name="title" id="title">
                <!-- <button>发布文章</button> -->
                <input type="submit" value="发布文章" id="submit">
            </div>
            <!-- 放置 md 编辑器 -->
            <div id="editor">
                <!-- 为了进行 form 的提交, 此处搞一个 textarea 多行编辑框, 借助这个编辑框来实现表单的提交 -->
                <!-- 可以设置 editor.md, 让编辑器把 markdown 内容也同步的保存到这个隐藏的 textarea 中, 从而可以进行 form 提交 -->
                <textarea name="content" style="display:none"></textarea>
            </div>
</form>

7、删除博客 

约定前后端交互接口

//请求
GET/user?blogId=x
//响应
{
userId:xx;
userName:xxx;
isYourBlog: 1,  // 1 表示当前博客就是登陆者的博客. 0 表示当前博客不是登陆者的博客. 
}

服务器端 

先判断当是否为登录状态,然后判断当前作者与登录用户是否一致,若相同则在数据库中删除该博客,然后将页面跳转到博客列表页。

@WebServlet("/blogDelete")
public class DeleteBlogServlet extends HttpServlet {
    @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){
            resp.getWriter().write("用户未登录");
            return;
        }
        User user = (User)session.getAttribute("user");
        if (user == null) {
            resp.getWriter().write("用户未登录");
            return;
        }
        String blogId = req.getParameter("blogId");
        if(blogId == null || "".equals(blogId)){
            resp.getWriter().write("博客编号有误");
            return;
        }
        BlogDAO blogDAO = new BlogDAO();
        Blog blog = blogDAO.getBlog(Integer.parseInt(blogId));
        if(blog == null || "".equals(blog)){
            resp.getWriter().write("待删除的博客不存在");
            return;
        }
        if(user.getUserId() != blog.getUserId()){
            resp.getWriter().write("不是本博客的作者,无法删除");
            return;
        }
        try {
            blogDAO.deleteBlog(Integer.parseInt(blogId));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        resp.sendRedirect("blog-list.html");
    }
}

客户端 

在列表详情页如果判断当前的作者是正在登录的用户,就新增一个删除超链接,可以进行删除。

function getAuthorInfo(user){
        $.ajax({
            type:'get',
            url:'authorInfo'+location.search,
            success:function(body){
                if(body.userName){
                    changeUserName(body.userName);
                    if(body.userName == user.userName){
                        let navDiv = document.querySelector('.nav');
                        let a = document.createElement('a');
                        a.innerHTML='删除';
                        a.href = 'blogDelete' +location.search;
                        navDiv.appendChild(a);
                    }
                }else{
                    alert("获取作者信息失败")
                }
            },
            error:function(){
                alert("获取作者信息失败")
            }
        });
    }

8、实现注销功能 

约定前后端交互接口

//请求
GET/logout
//响应
HTTP/1.1 302
Location:login.html

服务器端 

先确认是否创建会话以确保登录状态,然后删除会话信息,并将登录的用户从数据库中删除,注销后跳转到登录页面。

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    @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){
            resp.getWriter().write("用户未登录");
            return;
        }
        User user = (User)session.getAttribute("user");
        //删除会话信息
        session.removeAttribute("user");
        UserDAO userDAO = new UserDAO();
        try {
            userDAO.deleteUser(user.getUserId());
            System.out.println(user.getUserId());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        resp.sendRedirect("blog-login.html");
    }
}

客户端 

 将注销超链接的href修改为logout。

<a href="logout">注销</a>

六、效果展示 

 

 

 

 

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

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

相关文章

安全运维之mysql基线检查

版本加固 选择稳定版本并及时更新、打补丁。 稳定版本&#xff1a;发行6-12个月以内的偶数版本。 检查方法&#xff1a; 使用sql语句:select version(); 检查结果&#xff1a; 存在问题&#xff1a;当前数据库版本较老需要更新 解决方案&#xff1a;前往http://www.mysql…

2023备战金三银四,Python自动化软件测试面试宝典合集(十四)

15.8 App 的性能测试 内容要点&#xff1a;指标&#xff1a;cpu&#xff0c;内存&#xff0c;电量&#xff0c;流量&#xff0c;FPS&#xff0c;怎么测? cpu&#xff0c;内存&#xff0c;流量 android studiocpu 不能超过 10-20% 普通业务要求在 10%左右&#xff0c;核心的业务…

链表:反转链表、快慢指针、删除链表【零神基础精讲】

来源0x3f&#xff1a;https://space.bilibili.com/206214 文章目录反转链表[206. 反转链表](https://leetcode.cn/problems/reverse-linked-list/)[92. 反转链表 II](https://leetcode.cn/problems/reverse-linked-list-ii/)[25. K 个一组翻转链表](https://leetcode.cn/proble…

新生儿住月子中心20天患败血症 什么是败血症?有哪些危害

12月7日&#xff0c;四川眉山市民唐先生说&#xff0c;他刚出生的儿子在妇产医院分娩中心住了20天后感染了败血症。据唐先生介绍&#xff0c;哈子出院时各项指标正常。他在分娩中心住了半个月左右&#xff0c;孩子喝牛奶异常易怒&#xff0c;第二天开始发烧。当天&#xff0c;在…

(十一)、用户中心页面【uniapp+uinicloud多用户社区博客实战项目(完整开发文档-从零到完整项目)】

1,个人中心页面 1.1 新建个人中心页面 1.2 纯净版个人中心页面代码&#xff1a; <template><view class"user"><view class"top"><view class"group"><view class"userinfo"><!-- 顶部 左侧 头像 …

Unreal Engine07:Actor的物理特性

写在前面 UE4作为物理引擎&#xff0c;其中一大功能就是能够赋予物体以物理特性。这里将简单介绍一下Actor常用的一些物理特性设置。 一、基本操作 这里介绍一些UE4的Editor基本操作&#xff1b; 1. Actor的变换 将Actor类拖动到地图中&#xff0c;生成实例&#xff1b;鼠…

408强化(二)线性表纯享版

目录 一、顺序表&#xff08;数组&#xff09;和链表总览 二、考情分析 2.1 从历年考情可以看出&#xff0c;如果一个方法出现了第2次&#xff0c;一般是以下情况&#xff1a; 2.2 没有考过的地方 三、 共同操作或考法 3.1 多指针后移 3.2 逆置 3.3 空间换时间的操作 3.…

一分钟了解微信公众号服务器配置自动回复

1、建一个web服务工程 2、开放任意一个接口&#xff0c; 比如 /aaa/bbb/ccc 把接口路径配置在这里&#xff0c;ip为公网ip或域名&#xff0c;其他的参数默认&#xff0c;对入门选手没啥用 3、该接口允许get和post两种方式访问&#xff0c;接口需要对于访问方式编写两套逻辑…

ubuntu下如何使用wireshark抓包,保姆级教程

Wireshark&#xff08;前称Ethereal&#xff09;是一个网络封包分析软件。网络封包分析软件的功能是截取网络封包&#xff0c;并尽可能显示出最为详细的网络封包资料。Wireshark使用WinPCAP作为接口&#xff0c;直接与网卡进行数据报文交换。 一、安装wireshark 打开终端&…

教育行业如何高效使用知识库?

在线知识库的有效性在商业世界中是众所周知的。知识库通常用于客户支持&#xff0c;或管理员工的内部知识。在教育系统中&#xff0c;知识库的优势鲜为人知。知识库是可用于各种应用程序的多功能软件。特别是考虑到当前网络影响我们所有人生活的环境&#xff0c;教育越来越多地…

数据结构<堆>

&#x1f387;&#x1f387;&#x1f387;作者&#xff1a; 小鱼不会骑车 &#x1f386;&#x1f386;&#x1f386;专栏&#xff1a; 《数据结构》 &#x1f393;&#x1f393;&#x1f393;个人简介&#xff1a; 一名专科大一在读的小比特&#xff0c;努力学习编程是我唯一…

字符串匹配 - 模式预处理:朴素算法(Naive)(暴力破解)

朴素的字符串匹配算法又称为暴力匹配算法&#xff08;Brute Force Algorithm&#xff09;&#xff0c;最为简单的字符串匹配算法。算法简介朴素的字符串匹配算法又称为暴力匹配算法&#xff08;Brute Force Algorithm&#xff09;&#xff0c;它的主要特点是&#xff1a;没有预…

功率放大器科普知识(晶体管功率放大器的注意事项)

虽然功率放大器是电子实验室的常用仪器&#xff0c;但是很多人对于它却没有清晰的认识&#xff0c;下面就让安泰电子来为大家介绍功率放大器的科普内容以及使用注意事项&#xff0c;希望大家可以对功率放大器有清晰的认识。功率放大器可以把输入信号的功率放大&#xff0c;以满…

NFT Insider #86:A16z 领投,YGG 获得 1380 万美元融资,The Sandbox与《北斗神拳》合作

引言&#xff1a;NFT Insider由NFT收藏组织WHALE Members、BeepCrypto联合出品&#xff0c;浓缩每周NFT新闻&#xff0c;为大家带来关于NFT最全面、最新鲜、最有价值的讯息。每期周报将从NFT市场数据&#xff0c;艺术新闻类&#xff0c;游戏新闻类&#xff0c;虚拟世界类&#…

智能小车红外循迹原理

循迹电路循迹电路由收发一体的红外收发管P1&#xff0c;P2&#xff1b;电位器R18&#xff0c;R29&#xff1b;发光二极管D6&#xff0c;D7和芯片LM324等组成。一共有两路&#xff0c;对应的红外电位器用于调节灵敏度。LM234用于信号的比较&#xff0c;并产生比较结果输出给单片…

MySQL8.0 optimizer_switch变化

Optimizer_switch变量是支持对优化器行为的控制。是一组值标志&#xff0c;每个标志都有一个on或off的值&#xff0c;以指示是否启用或禁用相应的行为。 MySQL8.0里除了熟悉的hash join重大变化之外&#xff0c;其他方面也有优化。 mysql> SHOW VARIABLES LIKE OPTIMIZER_…

14 基数排序(桶排序)

文章目录1 基数排序基本思想2 基数排序的代码实现2.1 java2.2 scala3 基数排序总结1 基数排序基本思想 1) 基数排序&#xff08;radix sort&#xff09;属于“分配式排序”&#xff08;distribution sort&#xff09;&#xff0c;又称“桶子法”&#xff08;bucket sort&#…

【Python】循环语句(while,for)、运算符、字符串格式化

一、while循环Python 编程中 while 语句用于循环执行程序&#xff0c;即在某条件下&#xff0c;循环执行某段程序&#xff0c;以处理需要重复处理的相同任务。其基本形式为&#xff1a;while 判断条件(condition)&#xff1a;执行语句(statements)执行语句可以是单个语句或语句…

Git、小乌龟、Gitee的概述与安装应用超详细(组长与组员多人开发版本)

目录 一、概述 1.什么是Git&#xff1f; 2.Git历史来源 3.Git的优点? 4.什么是版本控制&#xff1f; 5.版本控制工具种类&#xff1f; 6.Git工作机制 7.Git、小乌龟、Gitee、凭据管理器的简单介绍 二、Git下载安装 下载Git 安装Git 安装完成后查看版本 三、下载小…

防水蓝牙耳机评测,值得入手的四款蓝牙耳机分享

提到蓝牙耳机&#xff0c;大家第一反应是音质跟佩戴舒适度要好&#xff0c;其实除了这两个功能&#xff0c;还有就是防水性能不能少&#xff0c;而且防水等级越高&#xff0c;耳机寿命也就越长&#xff0c;那么&#xff0c;我们该如何 选购一款好用的蓝牙耳机呢&#xff1f;下面…