通过servlet设计一个博客系统

博客系统

这里贴一个链接,大家可以看看成品http://115.159.31.84:8080/blog_system/blog_list.html
用户名是zhangsan或者lisi,密码是123

准备工作

通过ideal创建一个maven文件 在pom.xml中引入依赖

servlrt依赖

java 复制代码
<!-- 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>

mysql依赖

java 复制代码
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.49</version>
</dependency>

jackson依赖

java 复制代码
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.14.2</version>
</dependency>

接下来要进行的操作,分为两个大的方面

服务器和数据库的交互

设计数据库/数据表

在main中创建一个dp.sql文件,在这里面编写SQL完成建库建表操作

java 复制代码
在这里插入代码片//编写SQL完成建库建表操作
//建库
create database if not exists blog_system charset utf8;
//建表,使用一个表表示博客,另一个表表示用户
use blog_system;
drop table if exists user;
drop table if exists blog;
create table blog(
    blogId int primary key auto_increment,
    title varchar(256),
    content varchar(4096),
    userId int,
    postTime datetime
);
create table user(
    userId int primary key auto_increment,
    username varchar(64) unique,
    password varchar(64)
);

通过封装JDBC代码,来实现基础的数据库操作,因为在咱们的程序里,是需要针对blog表和user表进行一些增删查改的

首先,我们在Java这个包中再创建一个dao包(data access object

数据访问对象),在里面写一些类,通过这些类里的方法封装了数据库,之后的数据库就是通过这样的对象来访问的

封装DBUtil,实现建立连接和断开连接

在dao包中创建一个类,通过这个类,把数据库建立连接和断开连接的逻辑进行封装

java 复制代码
package dao;

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 volatile DataSource dataSource = null;

    //此处需要为单例模式
    private static DataSource getDataSource() {
        if (dataSource == null) {
            synchronized (DBUtil.class) {
                if (dataSource == null) {
                    dataSource = new MysqlDataSource();
                    ((MysqlDataSource) dataSource).setURL("jdbc:mysql://127.0.0.1:3306/blog_system?useSSL=false&characterEncoding=utf8");
                    ((MysqlDataSource) dataSource).setUser("root");
                    ((MysqlDataSource) dataSource).setPassword("111111");
                }
            }
        }
        return dataSource;
    }
    //提供一个方法,和数据库建立连接
    public static Connection getConnection(){
        try {
            return getDataSource().getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
    //提供一个方法,和数据库断开连接
    public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet) throws SQLException {
        if (resultSet!=null){
            resultSet.close();
        }
        if (statement!=null){
            statement.close();
        }
        if (connection!=null){
            connection.close();
        }
    }
}

创建实体类

此处的实体类,就是要和数据库的表有对应关系,每个表都需要有一个实体类(不绝对),然后就可以使用这个类的对象来表示这个表里的一条记录了(因此,就要求这个对象的属性,能和表里的属性一一对应)

后续数据库操作是围绕实体类来展开的

同样的,我们需要在dao这个包里面创建blog类和user类

blog

java 复制代码
package dao;
import java.sql.Timestamp;
//通过这个类的一个对象,来表示一条blog表中的记录
//这个类的属性,要和表中的列一致
public class blog {
    private int blogId;
    private String title;
    private String content;
    private int userId;
    //SQL里面有Timestamp类型(4个字节,2038年就不够用了),还有 datetime类型
    //使用SQL时,推荐使用datetime
    private Timestamp postTime;

    public int getBlogId() {
        return blogId;
    }

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }

    public int getUserId() {
        return userId;
    }

       public String getPostTime() {
        //此处需要把时间戳转换为格式化时间
        //先构造一个对象,构造的时候,指定具体的格式.
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        return format.format(postTime);
    }

    public void setBlogId(int blogId) {
        this.blogId = blogId;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setContent(String content) {
        this.content = content;
    }

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

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

    @Override
    public String toString() {
        return "blog{" +
                "blogId=" + blogId +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", userId=" + userId +
                ", postTime=" + postTime +
                '}';
    }
}

user

java 复制代码
package dao;

public class user {
    private int userId;
    private String username;
    private String password;

    public int getUserId() {
        return userId;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "user{" +
                "userId=" + userId +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

编写Dao类

通过实现Dao类,来封装对实体类(数据表)的增删查改

BlogDao

java 复制代码
package dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

//通过这个类,封装对blog表的增删查改
public class BlogDao {
    //1.新增一个blog
    //调用insert的时候,需要先构造一个blog对象
    //作为参数,传递给insert,再由insert内部完成数据库的插入操作
    public void insert(blog blog) throws SQLException {
        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();
      }catch (SQLException e){
          e.printStackTrace();
      } finally{
          //4.关闭连接,释放资源
          DBUtil.close(connection,statement,null);
      }
    }
    //2.查询blog表里的所有的博客
    public List<blog>getblogs() throws SQLException {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet =null;
        List<blog>blogs = new ArrayList<>();
        try{
            //1.建立连接
            connection = DBUtil.getConnection();
            //2.构造一个SQL语句
            String sql = "select * from blog";
            statement = connection.prepareStatement(sql);
            //3.执行语句
            resultSet = statement.executeQuery();
            //4.遍历结果集合
            while(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"));
                blogs.add(blog);
            }
            return blogs;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtil.close(connection,statement,resultSet);
        }
        return null;
    }
    //3.指定blogId,查询某一个博客
    public blog getblog(int blogId) throws SQLException {
        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(sql);
            //4.获取blog
            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.指定blogId进行删除
    public void delete(int blogId) throws SQLException {
        Connection connection = null;
        PreparedStatement statement = null;
        try{
            //1.建立连接
            connection = DBUtil.getConnection();
            //2.创建SQL语句
            String sql = "delete from blog where blogId=?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            //3.执行sql语句
            statement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBUtil.close(connection, statement, null);
        }
    }
}

UserDao

java 复制代码
package dao;

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

public class UserDao {
    //1.根据userId来查询用户信息(后续根据博客查询出作者详情)
    public user getuserById(int userId) throws SQLException {
        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.close(connection,statement,resultSet);
        }
        return null;
    }
    //2.根据username来查询用户信息(实现登录功能)
    public user getuserByName(String username) throws SQLException {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try{
            connection = DBUtil.getConnection();
            String sql = "select * from 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;
    }
}

前端和服务器的交互

接下来,就可以进行一些前后端交互的逻辑的实现了 接下来以功能点 为维度进行展开

针对每个功能点,分别进行"设计前后端交互接口","开发后端代码","开发前端代码","调试"

功能一:博客列表页

让博客列表页能够加载出博客列表内容

1.发起一个http请求,向后端索要博客列表数据

2.后端收到请求之后查询数据库获取到数据库中的博客列表,并返回给前端

3.前端拿到响应之后,就依据响应中的内容,构造出html片段,最终显示出来 在进行这三个操作之前,还需要约定好前后端交互接口,后续前端和后端要进行很多种不同的数据交互,每一种数据交互都需要发送不同的请求,返回不同的响应,此处就需要把请求和响应具体都约定好

首先创建一个名为api的包,用来存放一些前后端交互的代码,也就是一些重要的servlet,这些servlet给前端提供功能支持,也可以理解为服务器给前端提供的api(编程接口),也可以叫做Controller

约定格式

以下是一种典型的约定方式

请求:

方法: GET

路径: blog

响应: HTTP/1.1 200 OK

Content-Type:application/json json格式如下:

java 复制代码
[
  {
    blogId:1,
    title:"西游记",
    content:"三打白骨精",
    userId:1,
    postTime:"2023-09-25 12:00:00"
  }
  {
    blogId:2,
    title:"水浒传",
    content:"武松打虎",
    userId:1,
    postTime:"2023-09-25 12:00:00"
  }
]

后端代码

后端要做的事,就是当收到一个上述约定的请求的时候,构造并返回一个约定的响应数据即可

在api这个包种创建一个BlogServlet

java 复制代码
package api;

import com.fasterxml.jackson.databind.ObjectMapper;
import dao.BlogDao;
import dao.blog;

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.sql.SQLException;
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 {
        //查询数据库,获取到数据后,构造成要求的json格式并返回
        BlogDao blogDao = new BlogDao();
        List<blog>blogs = null;
        try {
            blogs = blogDao.getblogs();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        String respJson = objectMapper.writeValueAsString(blogs);
        //jackson看到blogs是一个List,就会构造出一个json数组[],针对List种的每个blog对象,分别构造出json对象
        //具体构造的过程,也就是根据blog的属性来的,属性的名字,就是json的key,属性的值,就是json的value
        resp.setContentType("application/json;charset=utf8");
        resp.getWriter().write(respJson);
    }
}

前端代码

让页面通过js ajax的方式发起一个http请求,来获取到刚才服务器这里的数据

这里需要先引入jquery的依赖:

java 复制代码
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>

创建一个script标签,在里面编写前端代码

java 复制代码
<script>
        //编写js代码
        //构造http请求,获取到博客列表数据,并展示到页面上
        function getBlogs(){
            $.ajax({
                type:'get',
                url:'blog',
                success:function(body){
                    //根据响应的内容,构造出html片段,展示到页面上
                    //由于服务器在响应种已经设置了content-type为application/json,此时
                    //jQuery就能够自动 的把此处响应的内容给解析成js对象数组
                    let container = document.querySelector('.container-right');
                    for(let blog of body){
                        //相当于Java中的for each
                        //根据当前这个blog来构造出一个html片段
                        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.href = "blog_detail.html?blogId="+blog.blogId;
                        a.innerHTML = '查看全文 &gt;&gt;';
                        blogDiv.appendChild(a);
                        container.appendChild(blogDiv);
                    }
                }
            });
        }
        getBlogs();

功能二:实现博客详情页

约定格式

请求:

方法: GET

路径: blog?query string

此处与博客列表页访问的是同一个路径,通过请求中是否携带query string来区分两个业务

响应: HTTP/1.1 200 OK

Content-Type:application/json json格式如下:

java 复制代码
 {
    blogId:1,
    title:"西游记",
    content:"三打白骨精",
    userId:1,
    postTime:"2023-09-25 12:00:00"
  }

这里的数据格式和博客列表页返回的非常相似,这里是一条记录,博客列表则是一个数组

后端代码

java 复制代码
package api;

import com.fasterxml.jackson.databind.ObjectMapper;
import dao.Blog;
import dao.BlogDao;
import dao.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;
import java.sql.SQLException;
import java.sql.Timestamp;
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 {
        // 查询数据库, 获取到数据之后, 构造成要求的 json 格式并返回.
        // 先尝试获取下 blogId 这个参数, 看看能不能获取到.
        BlogDao blogDao = new BlogDao();
        String blogId = req.getParameter("blogId");
        if (blogId == null) {
            // 此时说明是获取博客列表. 没有 blogId 参数
            List<Blog> blogs = null;
            blogs = blogDao.getBlogs();
            String respJson = objectMapper.writeValueAsString(blogs);
            resp.setContentType("application/json; charset=utf8");
            resp.getWriter().write(respJson);
        } else {
            // 此时说明是获取博客详情. 有 blogId 参数.
            Blog blog = null;
            blog = blogDao.getBlog(Integer.parseInt(blogId));
            if (blog == null) {
                // 返回一个 id 为 0 的 blog 对象. 前端再根据这里进行判定.
                blog = new Blog();
            }
            String respJson = objectMapper.writeValueAsString(blog);
            resp.setContentType("application/json; charset=utf8");
            resp.getWriter().write(respJson);
        }
    }
}

前端代码

java 复制代码
function getBlog() {
            $.ajax({
                url: 'blog' + location.search,
                type: 'get',
                success: function(body) {
                    // 根据拿到的响应数据, 构造页面内容. 
                    let h3 = document.querySelector('.container-right h3');
                    h3.innerHTML = body.title;
                    let dateDiv = document.querySelector('.container-right .date');
                    dateDiv.innerHTML = body.postTime;
                    editormd.markdownToHTML('content', { markdown: body.content });
                }
            });
        }
        getBlog();

这里为了使用markdown编辑器来渲染博客,因此需要引入markdown的依赖

java 复制代码
 <link rel="stylesheet" href="editor.md/css/editormd.min.css" />
    <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>

注意:这里的markdown的依赖是建立在jQuery中引入的前提下的,因此我们需要先引入jQuery,再引入markdown

功能三:实现登录功能

约定格式:

请求:

方法: post

路径: login

Content-Type:application/x-www-form-urlencoded(使用form表单的形式提交)

username=zhangsan&password=123

响应: HTTP/1.1 200 OK

Location:blog_list_html

后端代码

java 复制代码
package api;

import dao.User;
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 {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.请求中的用户名和密码
        //给请求对象设置字符集,保证请求中的用户名或者密码为中文的情况下也是可以的
        req.setCharacterEncoding("utf8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if (username == null || password == null || "".equals(username) || "".equals(password)) {
            //提交的密码有误
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("当前传过来的username或者password为空");
        }
        //2.和数据库的数据进行对比,看是否匹配
        UserDao userDao = new UserDao();
        User user = userDao.getUserByName(username);
        if (user==null){
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("您的用户名或者密码错误");
            return;
        }
        //当前用户名正确,看密码是否正确
        if (!password.equals(user.getPassword())){
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("您的用户名或者密码错误");
            return;
        }
        //3.创建会话
        HttpSession session = req.getSession(true);
        //把当前用户的登录信息保存到session中,方便后续进行获取
        session.setAttribute("user",user);
        //4.跳转到博客列表页
        resp.sendRedirect("blog_list_html");
    }
}

前端代码

java 复制代码
<form action="login" method="post">
                <div class="row">
                    <span>用户名</span>
                    <input type="text" id="username" name="username">
                </div>
                <div class="row">
                    <span>密码</span>
                    <input type="password" id="password" name="password">
                </div>
                <div class="row">
                    <input type="submit" id="submit" value="登录">
                </div>
            </form>

功能四:强制检查登录

如果用户在未登录的情况下,访问博客详情列/列表页/编辑页,就会自动的跳转到登录页

在博客详情列/列表页/编辑页,再发起一个get的ajax,询问服务器看当前是否已经登录

约定格式

请求:

方法: get

路径: login

响应: HTTP/1.1 200 OK(已登录)

HTTP/1.1 403 Forbidden(未登录)

后端代码

前端代码

java 复制代码
  @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //会话不存在,就是未登录
        HttpSession session = req.getSession(false);
        if (session==null){
            //未登录
            resp.setStatus(403);
            return;
        }
        //不仅仅是看session对象本身是否存在,还需要看user对象是否存在(为了后续实现退出登录的功能)
        User user = (User) session.getAttribute("user");
        if (user==null){
            resp.setStatus(403);
            return;
        }
        //返回200表示已登录
        resp.setStatus(200);
    }

前端代码

java 复制代码
function checkLogin() {
    $.ajax({
        type: 'get',
        url: 'login',
        success: function(body) {

        },
        error: function(body) {
            location.assign('login.html');
        }
    });
}

功能五:实现显示用户信息

在当前博客列表页中,显示出当前登录的用户的个人信息,在博客详情页中,显示出这个文章的作者

让博客详情列表页和详情页分别发起ajax请求,博客列表中.就需要获取到当前登录的用户的信息

博客详情页中,就需要获取到当前文章作者的信息

约定格式

博客列表页

请求:

方法: get

路径: user

响应:

HTTP/1.1 200 OK
json格式

{

userId:1,

username:'zhangsan'

}

博客详情页

请求:

方法: get

路径: user?blogId=

响应:

HTTP/1.1 200 OK
json格式

{

userId:1,

username:'zhangsan'

}

后端代码

java 复制代码
package api;

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

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

public class UserServlet 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){
            //说明是博客列表页
            HttpSession session = req.getSession(false);
            if (session==null){
                User user = new User();
                String respJson = objectMapper.writeValueAsString(user);
                resp.setContentType("application/json;charset=utf8");
                resp.getWriter().write(respJson);
                return;
            }
            User user = (User) session.getAttribute("user");
            if (user==null){
                user = new User();
                String respJson = objectMapper.writeValueAsString(user);
                resp.setContentType("application/json;charset=utf8");
                resp.getWriter().write(respJson);
                return;
            }
            String respJson = objectMapper.writeValueAsString(user);
            resp.setContentType("application/json;charset=utf8");
            resp.getWriter().write(respJson);
        }else {
            //博客详情页
            //需要查询数据库
            BlogDao blogDao = new BlogDao();
            Blog blog = blogDao.getBlog(Integer.parseInt(blogId));
            if (blog==null){
                User user = new User();
                String respJson = objectMapper.writeValueAsString(user);
                resp.setContentType("application/json;charset=utf8");
                resp.getWriter().write(respJson);
                return;
            }
            UserDao userDao = new UserDao();
            User user = userDao.getUserById(blog.getUserId());
            if (user==null){
                user = new User();
                String respJson = objectMapper.writeValueAsString(user);
                resp.setContentType("application/json;charset=utf8");
                resp.getWriter().write(respJson);
                return;
            }
            String respJson = objectMapper.writeValueAsString(user);
            resp.setContentType("application/json;charset=utf8");
            resp.getWriter().write(respJson);
        }
    }
}

后端代码

java 复制代码
function getUser() {
            $.ajax({
                type: 'get',
                url: 'user',
                success: function(body) {
                    // body 就是解析后的 user 对象了. 
                    let h3 = document.querySelector('.card h3');
                    h3.innerHTML = body.username;
                }
            })
        }
        getUser();
java 复制代码
function getUser() {
            $.ajax({
                type: 'get',
                url: 'user' + location.search,
                success: function(body) {
                    // body 就是解析后的 user 对象了. 
                    let h3 = document.querySelector('.card h3');
                    h3.innerHTML = body.username;
                }
            })
        }
        getUser();

功能六:退出登录(注销)

判定登录状态逻辑中,

1.会话存在

2.会话中存储的user对象存在

两个条件同时具备,才认为用户是已经登录了

破坏上述的任何一个条件,都可以达成注销这样的效果

但是servlet中,并没有直接提供一个api来删除会话

但是有api能够删除会话中的user(attribute)

约定格式

请求:

方法: get

路径: logout

响应:

HTTP/1.1 302

location:login.html

后端代码

java 复制代码
package api;

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

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.sendRedirect("login.html");
            return;
        }
        //之前在登录成功之后,就会给session中存储user这样的attribute
        //现在需要将其删除
        session.removeAttribute("user");
        resp.sendRedirect("login.html");
    }
}

前端代码

java 复制代码
    <a href="logout">注销</a>

通过点击a标签就能实现退出登录

功能七:发布博客

这里本质上和登录非常相似

核心都是通过form表单,把页面中用户的内容,给提交到服务器这边,服务器就可以把内容保存到数据中即可

约定格式

请求:

方法:post

路径:blog

Content-Type:application/x-www-form-urlencoded

body:title=xxxxx&content=xxxx

响应:

HTTP/1.1 302

location:blog_list.html

提交成功后,跳转到博客列表页,来到列表页之后,就能够看到刚才发布的博客了

后端代码

java 复制代码
    @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("未登录");
        }
        User user = (User) session.getAttribute("user");
        if (user==null){
            resp.setContentType("text/html;charset=utf8");
            resp.getWriter().write("未登录");
        }
        //获取到请求中传递过来的内容
        req.setCharacterEncoding("utf8");
        String title = req.getParameter("title");
        String content = req.getParameter("content");
        if(title==null||content==null||"".equals(title)||"".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());
        //由于在sql中插入数据的时候,已经使用sql自带的now获取到当前的时间,不需要此处代码中手动设置时间了
//        blog.setPostTime(new Timestamp(System.currentTimeMillis()));
        BlogDao blogDao = new BlogDao();
        blogDao.insert(blog);
        resp.sendRedirect("blog_list.html");
    }
}

前端代码

java 复制代码
 <form action="blog" method="post">
            <!-- 标题编辑区 -->
            <div class="title">
                <input type="text" id="title-input" name="title">
                <input type="submit" id="submit">
            </div>
            <!-- 博客编辑器 -->
            <!-- 把 md 编辑器放到这个 div 中 -->
            <div id="editor">
                <textarea name="content" style="display: none;"></textarea>
                //此处是editor.md文档上给出的解决方案,在此处写一个隐藏的text area(多行编辑框),就可以实现form表单的提交了,在这里就可以指定name的值了
            </div>
        </form>
相关推荐
weixin_5375904515 小时前
《Java编程入门官方教程》第八章练习答案
java·开发语言·servlet
Ttang232 天前
Tomcat原理(4)——尝试手动Servlet的实现
java·开发语言·servlet·java-ee·tomcat·intellij-idea
loop lee2 天前
计算机网络 - HTTP 协议和万维网
java·网络协议·servlet·tomcat
不修×蝙蝠3 天前
搭建Tomcat(四)---Servlet容器
java·服务器·servlet·tomcat·搭建resquest
像污秽一样3 天前
简易记事本开发-(SSM+Vue)
java·vue.js·spring boot·spring·servlet·maven·mybatis
计算机学无涯5 天前
Servlet学习中遇到的一些问题及解决
servlet
测试工程师成长之路5 天前
解锁 Jenkins 搭建全攻略
运维·servlet·jenkins
进击的编程浪人5 天前
jsp中的四个域对象(Spring MVC)
servlet
怒放de生命20105 天前
jenkins 出现 Jenkins: 403 No valid crumb was included in the request
java·servlet·jenkins
爱小黄6 天前
从Servlet到Spring MVC,从Spring MVC到Spring BootC
spring·servlet·mvc