通过servlet设计一个博客系统

news2024/11/16 17:50:20

博客系统

  • 准备工作
    • 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.coloradmin.cn/o/1139314.html

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

相关文章

NCP1256ESN65T1G具有多种保护功能 一款低功率离线电流模式PWM控制器

NCP1256ESN65T1G 包括构建几瓦到几十瓦成本高效开关模式电源所需的一切功能。该零件采用微型 TSOP-6 封装&#xff0c;供电范围高达 30 V&#xff0c;具有带抖动的 65 kHz 或 100 kHz 开关电路&#xff0c;在峰值电流模式控制下运行。当辅助侧功率开始降低时&#xff0c;该控制…

ARP欺骗攻击

ARP协议的概念 地址解析协议&#xff0c;即ARP&#xff08;Address Resolution Protocol&#xff09;&#xff0c;是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到局域网络上的所有主机&#xff0c;并接收返回消息&#xff0c;以此…

邂逅React及React初体验

文章目录 一、React是什么二、React数据对比三、React特点3.1 技术特点3.2 声明式编程3.3 组件化开发3.4 多平台适配 四、React开发依赖4.1 React的开发依赖4.2 Babel和React的关系4.3 React的依赖引入 五、React初体验5.1 Hello World5.2 增加按钮&#xff0c;点击修改文本5.3…

多元数据库时代,如何选择数据库基础设施?

一 多元数据库时代趋势特点 在数据库技术发展、数字化转型应用和信创三大驱动力共同作用下&#xff0c;数据库从单一架构支持多类应用演变为多类架构支持多类应用。这些架构并非替代关系&#xff0c;而是相互共存、共同发展的关系&#xff0c;数据库的多样性成为必然&#xff0…

Oculus开发入门

老是访问官网搭建unity环境太麻烦了&#xff0c;自己记录一下&#xff0c;在国内看。 官网教程连接 Getting Started with Interaction SDK | Oculus Developers Adjust Camera Rig Once you’ve completed the tutorial listed above, you can find Interaction SDK in Unit…

媒介易发稿教程,在人民网投稿的指南与技巧

在当今信息快速传播的时代&#xff0c;网络媒体成为了人们获取信息、表达观点的重要平台。而在这个庞大信息海洋中&#xff0c;人民网作为中国最具影响力的新闻网站之一&#xff0c;扮演着引领舆论、传播价值观念的重要角色。无论是个人经历、社会观察&#xff0c;还是学术研究…

日本汽车弯道超车,意图反超中国汽车和特斯拉,中国汽车另辟蹊径

日本汽车领军者丰田再次宣称固态电池是商用正在加速&#xff0c;已在电池材料技术上取得突破&#xff0c;充电10分钟可行驶1200公里&#xff0c;将在2027年装载于雷克萨斯上&#xff0c;再次引领汽车行业变革&#xff0c;为它在新能源汽车行业的落后鼓气。 丰田与大众可谓汽车行…

使用 IBM HeapAnalyzer 分析堆转储快照文件的

1.打开IBM HeapAnalyzer工具所在文件夹&#xff0c;执行cmd进入命令窗口 java -jar -Xmx1G .\ha456.jarha456.jar 为IBM HeapAnalyzer工具文件名 2、打开需要分析的日志文件

测试人员的设计思维

我们在工作、生活中经常听到别人说设计思维。那么&#xff0c;设计思维是什么&#xff1f;对测试人员来说有什么帮助&#xff1f; 在聊设计思维前&#xff0c;让我们先了解一下思维。思维是人类的重要组成部分&#xff0c;它帮助我们理解复杂的情况&#xff0c;形成深思熟虑的…

Class文件简单解析

一、Class文件 Test.java public class Test{ private int count; public int inc(){ return count;} } vim -b Test.class 输入 :%!xxd 图一 java反编译 javap -v -l -c Test.class 图二 二、Class文件解析 1、Class文件结构 1、魔数 魔数magic是Class文件的标记&…

(免费领源码)java#Springboot#mysql英语自主学习平台的设计与实现35901-计算机毕业设计项目选题推荐

摘 要 随着互联网趋势的到来&#xff0c;各行各业都在考虑利用互联网将自己推广出去&#xff0c;最好方式就是建立自己的互联网系统&#xff0c;并对其进行维护和管理。在现实运用中&#xff0c;应用软件的工作规则和开发步骤&#xff0c;采用Java技术建设英语自主学习平台。 …

【Proteus仿真】【STM32单片机】水箱液位监控系统

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真STM32单片机控制器&#xff0c;使用LCD1602液晶、按键、蜂鸣器、液位传感器、PCF8591 ADC转换器、水泵等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示当前水位、上…

安全和便捷:如何将运营商二要素API应用于实名制管理中

引言 随着互联网的快速发展&#xff0c;数字化身份验证和实名制管理变得越来越重要。在金融、电子商务、社交媒体等领域&#xff0c;确保用户身份的安全和准确性至关重要。运营商二要素核验API成为了实名制管理的有力工具&#xff0c;它不仅能够提供高水平的安全性&#xff0c…

M-LVDS收发器MS2111,可替代SN65MLVD206

MS2111 是多点低压差分 (M-LVDS) 线路驱动器和接收器。经过 优化&#xff0c;可运行在高达 200Mbps 的信号速率下。所有部件均符合 M LVDS 标准 TIA / EIA-899 。该驱动器的输出支持负载低至 30Ω 的多 点总线。 MS2111 的接收器属于 Type-2 &#xff0c; 可在 -1…

特殊类设计[上]

文章目录 1.只能在堆上创建对象的类1.1析构函数私有化1.2析构函数 delete1.3构造函数私有定义拷贝构造私有只声明1.4构造函数私有定义拷贝构造 delete 2.不能被拷贝的类2.1 私有声明不定义拷贝构造函数2. 2拷贝构造函数 delete 3.只能在栈和静态区创建对象的类4.不能被继承的…

Galaxy生信云|新增生存曲线绘制、肿瘤基因通路注释工具

2023-10-26&#xff0c;Galaxy生信云平台 UseGalaxy.cn 新增 2 个工具。 Cancer Research 生存曲线 Kaplan-Meier curve ploter肿瘤通路注释 Gene to oncogenic pathway mapper 部分结果展示 生存曲线 Kaplan-Meier curve ploter 生存曲线-不分层&#xff1a; 生存曲线-分层&am…

封装, 继承, 多态详解

面向对象编程有三大特征&#xff1a;封装、继承和多态 一.封装 思维导图概览&#xff1a; 1. 封装的概念 —— 把抽象出的数据&#xff08;属性&#xff09;和对数据的操作&#xff08;方法&#xff09;封装到一起&#xff0c;数据被保护在内部&#xff0c;程序的其它部分只有…

linux系统 too many open files解决方法

1.遇到的问题 too many open files是Linux系统中常见的错误&#xff0c;从字面意思上看就是说程序打开的文件数过多&#xff0c;不过这里的files不单是文件的意思&#xff0c;也包括打开的通讯链接(比如socket)&#xff0c;正在监听的端口等等&#xff0c;所以有时候也可以叫做…

Python 中的邻接矩阵

Python 中使用图数据结构来表示各种现实生活中的对象,例如网络和地图。 我们可以使用邻接矩阵来表示图。 本文将讨论在 Python 中实现邻接矩阵的不同方法。 创建邻接矩阵 考虑下图。 图中,有 6 个节点,编号为 1 到 6。图中连接节点的边有 7 条; 边 eij 连接节点 i 和节点…