通过servlet设计一个博客系统

博客系统

  • 准备工作
    • servlrt依赖
    • mysql依赖
    • jackson依赖
  • 服务器和数据库的交互
    • 设计数据库/数据表
    • 封装DBUtil,实现建立连接和断开连接
    • 创建实体类
      • blog
      • user
    • 编写Dao类
      • BlogDao
      • UserDao
  • 前端和服务器的交互
    • 功能一:博客列表页
      • 约定格式
      • 后端代码
      • 前端代码
    • 功能二:实现博客详情页
      • 约定格式
      • 后端代码
      • 前端代码
    • 功能三:实现登录功能
      • 约定格式:
      • 后端代码
      • 前端代码
    • 功能四:强制检查登录
      • 约定格式
      • 后端代码
      • 前端代码
      • 前端代码
    • 功能五:实现显示用户信息
      • 约定格式
        • 博客列表页
        • 博客详情页
      • 后端代码
      • 后端代码
    • 功能六:退出登录(注销)
      • 约定格式
      • 后端代码
      • 前端代码
    • 功能七:发布博客
      • 约定格式
      • 后端代码
      • 前端代码

准备工作

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

servlrt依赖

<!-- 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依赖

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

jackson依赖

<!-- 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完成建库建表操作

在这里插入代码片//编写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包中创建一个类,通过这个类,把数据库建立连接和断开连接的逻辑进行封装

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

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

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

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

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格式如下:

[
  {
    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
在这里插入图片描述

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的依赖:

<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>

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

<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格式如下:

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

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

后端代码

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

前端代码

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的依赖

 <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

后端代码

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

前端代码

<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(未登录)

后端代码

前端代码

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

前端代码

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

后端代码

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

后端代码

function getUser() {
            $.ajax({
                type: 'get',
                url: 'user',
                success: function(body) {
                    // body 就是解析后的 user 对象了. 
                    let h3 = document.querySelector('.card h3');
                    h3.innerHTML = body.username;
                }
            })
        }
        getUser();
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

后端代码

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

前端代码

    <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
提交成功后,跳转到博客列表页,来到列表页之后,就能够看到刚才发布的博客了

后端代码

    @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");
    }
}

前端代码

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CAD需要学c语言嘛?

CAD需要学c语言嘛&#xff1f; AutoCAD 和 C 语言没有关系的。 如果非要说是 AutoCAD 和哪个编程语言有关系&#xff0c;那应该是 VBA, 可以通过 VBA 编程&#xff0c;最近很多小伙伴找我&#xff0c;说想要一些c语言资料&#xff0c;然后我根据自己从业十年经验&#xff0c;熬…

MySQL扩展语句和约束条件

MySQL扩展语句 create TABLE if not exists ky32 (id int(4) zerofill primary key auto_inc rement&#xff0c; #表示该字段可以自增长&#xff0c;默认从1开始每条记录会自动递增1name varchar(10) not null,cradid int(10) not null unique key,hobby varchar (50))&#x…

自学C语言的最恐怖的地方是什么?

自学C语言的最恐怖的地方是什么&#xff1f; 当年在网吧学C&#xff0c;人家在玩游戏&#xff0c;我在敲代码&#xff0c;基本上从9点敲到1点&#xff0c;然后再开始玩游戏。。。当时不是装逼&#xff0c;就是觉得有意思&#xff0c;而且当时计算机的确是一门很高大上的职业。…

磁盘管理(初始化,引导块,坏块管理,固态硬盘)

目录 1.磁盘初始化2.引导块3.坏块的管理1.坏块检查2.坏块链表3.扇区备用 4.固态硬盘&#xff08;SSD&#xff09;1.原理2.组成3.读写性能特性4.与机械硬盘相比5.磨损均衡技术 1.磁盘初始化 ①进行低级格式化&#xff08;物理格式化&#xff09;&#xff0c;将磁盘的各个磁道划分…

负载均衡策略 LVS

一、集群功能分类 1、LB (1) 概念&#xff1a; LB&#xff1a;负载均衡 (Load Balancing) 是一种分发网络流量的技术&#xff0c;LB 负载均衡的基本原理是将传入的网络流量分发到多个后端服务器&#xff0c;以确保这些服务器都承担相似的工作负载&#xff0c;从而避免某一台…

分类预测 | Matlab实现KOA-CNN-BiLSTM-selfAttention多特征分类预测(自注意力机制)

分类预测 | Matlab实现KOA-CNN-BiLSTM-selfAttention多特征分类预测&#xff08;自注意力机制&#xff09; 目录 分类预测 | Matlab实现KOA-CNN-BiLSTM-selfAttention多特征分类预测&#xff08;自注意力机制&#xff09;分类效果基本描述程序设计参考资料 分类效果 基本描述 1…

Spring AOP源码解读

今天我们来分析Spring中AOP的源码&#xff0c;主要是关于SpringAOP是如何发挥作用的。 前期准备 首先我们需要有一个Spring AOP项目&#xff0c;添加好了SpringAOP的依赖。 <dependency><groupId>org.springframework</groupId><artifactId>spring-co…

在重生奇迹MU中如何选择最佳的挂机点?

如何寻找最适合自己的挂机地点呢&#xff1f;小编建议玩家朋友从以下几点着手加以抉择。 怪物的等级不能过高 你的最佳挂机点要结合自己的实际情况来定&#xff0c;如果你刷怪比较吃力的话&#xff0c;那么此游戏地图并不适合你挂机&#xff0c;一旦挂机过程中&#xff0c;你…

0028Java程序设计-智能农场监控报警系统设计与实现

文章目录 摘要目 录系统设计开发环境 摘要 我国是一个以农业为主的国家&#xff0c;在当今社会信息化迅速发展的背景下&#xff0c;将信息技术与农业相融合是必然的趋势。现代信息技术在农业生产中的运用&#xff0c;主要体现在两个领域&#xff1a;一是传感器技术&#xff1b…

一文了解什么是JWT 与sessions

​session 和 JSON Web 令牌 (JWT) 是在调用之间维护此身份验证状态的两种最流行的方法。两者各有利弊&#xff0c;在它们之间进行选择需要了解这些权衡以及它们与应用程序的特定需求之间的关系。 一、基于session的身份验证 在基于session的身份验证&#xff08;也称为基于 c…

DbVisualizer和DBeaver启动不来,启动报错

启动报错 大多数启动报错都是因为你没有用管理员身份运行程序&#xff0c;提示的错误都是八竿子打不着的什么jdk、jvm问题。 比如DbVisualizer提示什么jvm配置参数&#xff0c;实际dbvis.exe 用管理员身份打开即可&#xff08;右键 dbvis.exe->属性->兼容性->勾上 “…

vue2+antd——实现动态菜单路由功能——基础积累

vue2antd——实现动态菜单路由功能——基础积累 实现的需求&#xff1a;效果图&#xff1a;登录接口处添加以下代码loadRoutes方法内容如下&#xff1a; 最近在写后台管理系统&#xff0c;遇到一个需求就是要将之前的静态路由改为动态路由&#xff0c;使用的后台框架是&#xf…

QMI8658A_QMC5883L(9轴)-EVB 评估板

1. 描述 QMI8658A_QMC5883L(9轴)-EVB 评估板是一款功能强大的9轴IMU传感器&#xff0c;它利用了QMA8658A 内置的3轴加速度计和3轴陀螺仪&#xff0c;同时结合QMC5883L的3轴地磁数据&#xff0c;来测量物体在三维空间中的角速度和加速度&#xff08;严格意义上的IMU只为用户提供…

linux驱动开发-点亮第一个led灯

linux驱动开发-点亮第一个led灯 一.背景知识二.如何写驱动程序三.实战演练3.1 查询原理图3.2 配置引脚为gpio模式3.3 配置引脚为输出模式3.4 DR寄存器 四.代码实例4.1 驱动层4.2 应用层 一.背景知识 我们这里使用的是百问网的imx_6ullpro的开发板。这里和裸机不同的是&#xf…

【Java】电子病历编辑器源码(云端SaaS服务)

电子病历编辑器极具灵活性&#xff0c;它既可嵌入到医院HIS系统中&#xff0c;作为内置编辑工具供多个模块使用&#xff0c;也可以独立拿出来&#xff0c;与第三方业务厂商展开合作&#xff0c;为他们提供病历书写功能&#xff0c;充分发挥编辑器的功能。 电子病历基于云端SaaS…

1300*C. Social Distance(贪心构造)

Problem - 1367C - Codeforces 解析&#xff1a; 统计出所有连续0序列&#xff0c;并且记录其左右两侧有没有1&#xff0c;然后对于四种情况分别判断即可。 #include<bits/stdc.h> using namespace std; int t,n,k; signed main(){scanf("%d",&t);while(…

论坛搭建.

目录 一.配置软件仓库 二.安装http php miriadb 三.配置数据库 四.源码拖拽并解压 五.防火墙通过 六.浏览器安装测试 七.界面参数设置 一.配置软件仓库 1.进入仓库目录 cd /etc/yum.repos.d 2.创建仓库文件 vim local.repo 3.在 local.repo中写入:(粘贴的时候注意位…

栈队列OJ练习题(C语言版)

目录 一、括号匹配问题 思路&#xff1a; 完整版C语言代码&#xff1a; 讲解&#xff1a; 二、用队列实现栈 思路&#xff1a; 完整版C语言代码&#xff1a; 讲解&#xff1a; 三、用栈实现队列 思路&#xff1a; 完整版C语言代码&#xff1a; 讲解&#xff1a…

任正非说:扩张必须踩在坚实的基础上,擅自扩张只能是自杀。

嗨&#xff0c;你好&#xff01;这是华研荟【任正非说】系列的第23篇文章&#xff0c;让我们继续聆听任正非先生的真知灼见&#xff0c;学习华为的管理思想和管理理念。 一、要想赢&#xff0c;要么在剑法上高于人&#xff0c;要么在盾牌上坚于人。若果剑不如人&#xff0c;就要…

虚拟机上的linux centos7无法连接ssh

1、排查有没有安装 openssh-server&#xff0c;在终端中输入 yum list installed | grep openssh-server此处显示已经安装了 openssh-server&#xff0c;如果又没任何输出显示表示没有安装 openssh-server&#xff0c;通过输入 yum install openssh-server进行安装 2、找到了…
最新文章