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

Lesson12:博客系统(基于模板引擎)

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

Lesson12:博客系统(基于模板引擎)

目录

一、准备工作

1.1 基本环境的搭建

1.2 对博客系统的分析

二、数据库

2.1 数据库设计

2.2 封装数据库相关操作并验证

2.2.1 创建相关的类

2.2.2 封装数据库的相关操作

三、Thymeleaf的相关操作

3.1 Thymeleaf初始化的优化

3.2 编写模板文件

四、实现登录页面、强制登录功能和注册页面

4.1 实现登录页面

4.2 实现强制登录功能

4.3 实现注册页面

五、实现博客详情页

5.1 博客详情展示

5.2 评论的显示

5.3 评论功能

5.4 提问功能

5.5 问题删除功能

5.6 注意

⑤如何将页面按照markdown的形式显示。

5.7 前端代码

六、博客删除页

七、实现博客编辑页

7.1 前端页面的设计

7.2 后端实现逻辑

八、实现博客修改页

九、实现上传头像功能

十、实现问题回答页

10.1 前端页面设计

10.2 后端设计

十一、实现注销功能

 十二、实现博客列表页

12.1 实现流程

12.2 生成模板

12.3 博客的内容太多,超过设置的背景

12.4 完成Servlet的代码,实现整个页面的渲染


一、准备工作

1.1 基本环境的搭建

主要分为7个步骤:

创建maven项目、引入依赖、创建目录结构、写一个测试代码、打包、部署、验证

具体操作见博客Lesson9:Tomcat 和 Servlet(基础篇)_刘减减的博客-CSDN博客中的第三小节。

1.2 对博客系统的分析

主要包含三个部分的逻辑:

①处理数据库的部分 M(Model)

②处理前端请求的部分 C(controller)

③前端展示的细节部分 V(View)

这三个部分称为MVC,是一个通用的概念,可以使用该框架开发web程序。

二、数据库

2.1 数据库设计

主要包含四个部分的数据:博客数据、用户数据、评论数据、问题数据

2.2 封装数据库相关操作并验证

2.2.1 创建相关的类

分别创建Blog、User、Comment、Question四个类,类中的成员变量和数据库中保持一致,生成成员变量的get、set和toString方法。以创建Blog类为例:

public class Blog {
    private int blogId;
    private String blogTitle;
    private String blogContent;
    private Timestamp blogTime;
    private int blogAuthor;
    private int visitCount;
    private int commentCount;

    public int getVisitCount() {
        return visitCount;
    }

    public void setVisitCount(int visitCount) {
        this.visitCount = visitCount;
    }

    public int getCommentCount() {
        return commentCount;
    }

    public void setCommentCount(int commentCount) {
        this.commentCount = commentCount;
    }

    public int getBlogId() {
        return blogId;
    }

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

    public String getBlogTitle() {
        return blogTitle;
    }

    public void setBlogTitle(String blogTitle) {
        this.blogTitle = blogTitle;
    }


    public String getBlogContent() {
        return blogContent;
    }

    public void setBlogContent(String blogContent) {
        this.blogContent = blogContent;
    }

    public Timestamp getBlogTime() {
        return blogTime;
    }

    public void setBlogTime(Timestamp blogTime) {
        this.blogTime = blogTime;
    }

    public int getBlogAuthor() {
        return blogAuthor;
    }

    public void setBlogAuthor(int blogAuthor) {
        this.blogAuthor = blogAuthor;
    }

    @Override
    public String toString() {
        return "Blog{" +
                "blogId=" + blogId +
                ", blogTitle='" + blogTitle + ''' +
                ", blogContent='" + blogContent + ''' +
                ", blogTime=" + blogTime +
                ", blogAuthor=" + blogAuthor +
                ", visitCount=" + visitCount +
                ", commentCount=" + commentCount +
                '}';
    }
}

2.2.2 封装数据库的相关操作

DBUtil:封装数据库的连接

BlogDao:实现对博客的增删改查。

        insert方法:增加一个博客

        delete方法:删除一个博客

        selectOne方法:根据博客Id查找博客。用户博客详情页。

        selectAll方法:查找所有的博客。用户博客列表页的展示。

        updateBlog方法:修改博客的内容和标题。用于博客修改页。

        updateVisistCount:更新博客的访问次数。在用户的信息卡片上展示。

        updateCommentCount:更新博客的评论次数。在用户的信息卡片上展示。

        selectVisitAllCount:根据用户Id查找用户的总访问次数。在用户的信息卡片上展示。

        selectVisitCount:根据博客Id查找博客的总访问次数。在用户的信息卡片上展示。

        main方法:测试以上方法是否正确

UserDao:实现用户信息的增删改查

        login:注册。注意在注册十,只需要输入用户名和密码,用户的其他属性可以通过其他方法增加。

        getBlogCount:根据用户Id,得到用户总的博客数量。用户信息卡片的展示会用到。

        selectByName:根据用户名 查找用户。登录时使用的是用户名密码登录,因此需要实现该功能。

        uploadImages:上传头像。用户可以修改自己的头像。

        changeBlogCount:修改用户的博客数量。新增一篇博客时会用到该方法。

        deleteUser:删除用户。

        main方法:测试以上方法是否正确

CommentDao:实现评论的增加、删除和选择。

        insert:新增一个评论。

        delete:删除一个评论。

        selelctAll:查找该博客的所有评论。

QuestionDao:实现问题的增加、删除和选择。

        insert:新增一个问题。

        delete:删除一个问题。

        selelctAll:查找所有问题。

        selelctOne:根据问题ID查找问题。主要用户回答页面的使用。

以上的方法都是类似的。只展示DButil和BlogDao的代码,其他代码可以在这个基础上修改得到。

public class DBUtil {
    private static final String URL = "jdbc:mysql://127.0.0.1:3306/BlogSystem?characterEncoding=utf8&useSSL=false"; // BlogSystem是数据库的名称
    private static final String username = "root";
    private static final String password = "1111";  // 输入数据库的密码
    private static DataSource dataSource = new MysqlDataSource();
    static {
        ((MysqlDataSource)dataSource).setURL(URL);
        ((MysqlDataSource)dataSource).setUser(username);
        ((MysqlDataSource)dataSource).setPassword(password);
    }
    public Connection getConnectin() throws SQLException {
        return dataSource.getConnection();
    }
    public void close(Connection connection, PreparedStatement statement, ResultSet resultSet){
        if(resultSet != null){
            try {
                resultSet.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(statement != null){
            try {
                statement.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(connection == null){
            try {
                connection.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
}
package Model;

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

public class BlogDao {
    public static void insert(Blog blog){
        DBUtil dbUtil = new DBUtil();
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            connection = dbUtil.getConnectin();
            String sql = "insert into blog (blogId,blogTitle,blogContent,blogTime,blogAuthor) values(null,?,?,?,?)";
            statement = connection.prepareStatement(sql);
            statement.setString(1,blog.getBlogTitle());
            statement.setString(2,blog.getBlogContent());
            statement.setTimestamp(3,blog.getBlogTime());
            statement.setInt(4,blog.getBlogAuthor());
            int ret = statement.executeUpdate();
            if(ret == 1){
                UserDao userDao = new UserDao();
                int blogcount = userDao.getBlogCount(blog.getBlogAuthor());
                System.out.println(blogcount);
                blogcount +=1;
                userDao.changeBlogCount(blogcount,blog.getBlogAuthor());
                System.out.println("插入成功");
            }else{
                System.out.println("插入失败");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            dbUtil.close(connection,statement,null);
        }
    }
    public static void delete(int blogId){
        DBUtil dbUtil = new DBUtil();
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            connection = dbUtil.getConnectin();
            String sql = "delete from blog where blogId=?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            int ret = statement.executeUpdate();
            if(ret == 1){
                System.out.println("删除成功");
            }else{
                System.out.println("删除失败");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            dbUtil.close(connection,statement,null);
        }
    }
    public static Blog selectOne(int blogId){
        DBUtil dbUtil = new DBUtil();
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        Blog blog = new Blog();
        try {
            connection = dbUtil.getConnectin();
            String sql = "select * from blog where blogId=?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            resultSet = statement.executeQuery();
            if(resultSet.next()){
                blog.setBlogTitle(resultSet.getString("blogTitle"));
                blog.setBlogTime(resultSet.getTimestamp("blogTime"));
                blog.setBlogContent(resultSet.getString("blogContent"));
                blog.setBlogAuthor(resultSet.getInt("blogAuthor"));
                blog.setBlogId(resultSet.getInt("blogId"));
                blog.setCommentCount(resultSet.getInt("commentCount"));
                blog.setVisitCount(resultSet.getInt("visitCount"));
                return blog;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            dbUtil.close(connection,statement,resultSet);
        }
        return null;
    }
    public static List selectAll(){
        DBUtil dbUtil = new DBUtil();
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        List blogs = new ArrayList<>();
        try {
            connection = dbUtil.getConnectin();
            String sql = "select * from blog order by blogTime desc";
            statement = connection.prepareStatement(sql);
            resultSet = statement.executeQuery();
            while (resultSet.next()){
                Blog blog = new Blog();
                blog.setBlogTitle(resultSet.getString("blogTitle"));
                blog.setBlogTime(resultSet.getTimestamp("blogTime"));
                String content = resultSet.getString("blogContent");
                if(content.length() > 100){
                    content = content.substring(0,100) + "...";
                    System.out.println(100);
                }
                blog.setBlogContent(content);
                blog.setBlogAuthor(resultSet.getInt("blogAuthor"));
                blog.setBlogId(resultSet.getInt("blogId"));
                blog.setCommentCount(resultSet.getInt("commentCount"));
                blog.setVisitCount(resultSet.getInt("visitCount"));
                blogs.add(blog);
            }
            return blogs;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            dbUtil.close(connection,statement,resultSet);
        }
        return null;
    }
    public static void updateBlog(String blogTitle, String blogContent, int blogId){
        DBUtil dbUtil = new DBUtil();
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            connection = dbUtil.getConnectin();
            String sql = "update blog set blogTitle = ?,blogContent=? where blogId = ?";
            statement = connection.prepareStatement(sql);
            statement.setString(1,blogTitle);
            statement.setString(2,blogContent);
            statement.setInt(3,blogId);
            int ret = statement.executeUpdate();
            if(ret == 1){
                System.out.println("修改成功");
            }else{
                System.out.println("修改失败");
            }
            return;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            dbUtil.close(connection,statement,null);
        }
    }
    public static void updateVisitCount(int count,int blogId){
        DBUtil dbUtil = new DBUtil();
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            connection = dbUtil.getConnectin();
            String sql = "update blog set visitCount = ? where blogId = ?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,count);
            statement.setInt(2,blogId);
            int ret = statement.executeUpdate();
            if(ret == 1){
                System.out.println("博客访问次数修改成功");
            }else{
                System.out.println("博客访问次数修改失败");
            }
            return;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            dbUtil.close(connection,statement,null);
        }
    }
    public static void updateCommentCount(int count,int blogId){
        DBUtil dbUtil = new DBUtil();
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            connection = dbUtil.getConnectin();
            String sql = "update blog set commentCount = ? where blogId = ?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,count);
            statement.setInt(2,blogId);
            int ret = statement.executeUpdate();
            if(ret == 1){
                System.out.println("评论次数修改成功");
            }else{
                System.out.println("评论次数修改失败");
            }
            return;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            dbUtil.close(connection,statement,null);
        }
    }
    public static int selectVisitAllCount(int userId){
        DBUtil dbUtil = new DBUtil();
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        int count = 0;
        try {
            connection = dbUtil.getConnectin();
            String sql = "select sum(visitCount) from blog where blogAuthor = ?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,userId);
            resultSet = statement.executeQuery();
            if(resultSet.next()){
                count = resultSet.getInt("sum(visitCount)");
                return count;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            dbUtil.close(connection,statement,null);
        }
        return 0;
    }
    public static int selectVisitCount(int blogId){
        DBUtil dbUtil = new DBUtil();
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        int count = 0;
        try {
            connection = dbUtil.getConnectin();
            String sql = "select visitCount from blog where blogId = ?";
            statement = connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            resultSet = statement.executeQuery();
            if(resultSet.next()){
                count = resultSet.getInt("visitCount");
                return count;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            dbUtil.close(connection,statement,null);
        }
        return 0;
    }

三、Thymeleaf的相关操作

3.1 Thymeleaf初始化的优化

如果我们按照博客Lesson11:模板引擎_刘减减的博客-CSDN博客中的操作实现博客列表页,就会在博客列表页中创建一个TemplateEngine实例,并且进行初始化操作。现在如果我们要在其他的页面,如博客详情页中使用TemplateEngine,就没法使用之前创建好的TemplateEngine对象。解决方案有以下几种:

①如果其他页面需要用到TemplateEngine,就再创建TemplateEngine实例,并再初始化一遍。

评价:可行但是不建议采用。TemplateEngine和数据库中的DataSource类似,只需要一份实例即可。如果搞了多份,每份TemplateEngine实例都要加载模板,会多消耗一份内存。会导致同一份模板数据,在数据库中存在了多份。

②能否把TemplateEngine做成一个单例呢?

ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(getServletContext());
resolver.setPrefix("/WEB-INF/template/");
resolver.setSuffix(".html");
resolver.setCharacterEncoding("utf-8");

从TemplateEngine的初始化代码可以看到,初始化必须用到ServletContext对象。这个对象又只能在Servlet的环境下来获取到,即将上面的初始化代码,随便在servlet的某个方法里都好写。但是放在一个和Servlet无关的单独的类中,都不好写。因此这种方法并不推荐。

③借助Servlet中自身关于ServletContext的机制

ServletContext是上下文对象,每个webapp都有一个上下文对象 。可以让一个webapp内部的servlet之间共享同一个ServletContext。这样就可以依据ServletContext来进行多个Servlet之间的数据共享操作。基于这个机制,我们可以创建好一个TemplateEngine,保存到ServletContext中,这样,所有的servlet都可以使用这个TemplateEngine。

具体的解决方案:

在ServletContext被Tomcat创建好了之后,就立刻进行初始化TemplateEngine,并且把engine保存到ServletContext里面。servlet可以拿到ServletContext,进一步就可以拿到engine。

我们怎样才能捕获到Tomcat创建ServletContext呢?

使用Servlet的监听器可以允许程序员监听某些动作,当动作被Tomcat触发的时候,可以执行程序员自己写的代码。此时我们要监听的就是Tomcat创建ServletContext这个动作。

// 通过这个注解,Tomcat才能认识这是一个监听器对象
@WebListener
public class ThymeLeafListener implements ServletContextListener {
    // servletContext被创建时触发
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        // 1.创建一个模板引擎对象
        TemplateEngine engine = new TemplateEngine();
        // 2.创建一个ServletContextTemplateResolver对象,功能就是从磁盘上加载模板引擎文件
        // 这里需要改一下获取方式
        ServletContextTemplateResolver resolver = new ServletContextTemplateResolver(servletContextEvent.getServletContext());
        //3对resolver对象设置一些属性 加载 /WEB-INF/template/ 目录中, 以 .html 结尾的文件, 作为模板引擎
        resolver.setPrefix("/WEB-INF/template/");
        resolver.setSuffix(".html");
        resolver.setCharacterEncoding("utf-8");
        // 4 把resolver和engine关联起来
        engine.setTemplateResolver(resolver);
        // 5.将创建好的engine放到servletContext里面
        servletContextEvent.getServletContext().setAttribute("engine",engine);
        System.out.println("Themeleaf初始化完毕");
    }
    // ServletContext被销毁前触发 ,暂时不需要写
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        
    }
}

注意:@WebListener这个注解一定要写。

3.2 编写模板文件

step1:把之前写的静态页面,全都拷贝到webapp目录中

step2:修改html文件,制作成Thymeleaf的模板文件

        将需要动态替换的部分,使用占位符占个位置。

step3:新建目录结构,将刚刚制作好的模板文件移到该目录下。具体操作见博客

Lesson11:模板引擎_刘减减的博客-CSDN博客的3.3小节。

四、实现登录页面、强制登录功能和注册页面

4.1 实现登录页面

登录页面是一个纯静态的页面,不需要通过servlet来渲染。登录页面的实现流程见博客Lesson10:ServletAPI详解(HttpServlet、HttpServletRequest、HttpServletResponse)_刘减减的博客-CSDN博客的第4.5小节。

@WebServlet("/login")
public class loginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if(username == null || "".equals(username) || password == null || "".equals(password)){
            resp.getWriter().write("输入不合法");
            return;
        }
        User user = UserDao.selectByName(username);
        if(user == null){
            resp.getWriter().write("用户名或者密码错误");
            return;
        }
        boolean result = user.getPassword().equals(password);
        if(!result){
            resp.getWriter().write("用户名或者密码错误");
            return;
        }
        HttpSession session = req.getSession(true);
        session.setAttribute("user",user); // 将用户保存在session中
        resp.sendRedirect("bloglist.html"); // 登录成功后,跳转到博客列表页
    }
}

4.2 实现强制登录功能

我们约定,只有用户登录后,才能进入到博客系统中,访问到博客系统的各个页面。如果不登陆,直接尝试访问博客系统中的某一个页面,就会自动的跳转到登录页面。

如何实现呢?我们可以在进入代码入口的时候,先判定一下当前是否在已经登录的状态。这个功能可以通过session机制实现,在登录的时候 将user信息保存在session中,然后从session中读取user,如果可以读取到,就证明已经登录过了,执行正常的页面渲染。如果未读取到,则是未登录状态,就跳转到登录页面。由于每个页面都会用到强制登录功能,因此将其封装在一个类中。

public class Util {
    public static User checkLogin(HttpServletRequest req){
        HttpSession session = req.getSession(false);
        if(session == null){
            return null;
        }
        User user = (User) session.getAttribute("user");
        if(user == null){
            return null;
        }
        return user;
    }
}

4.3 实现注册页面

注册页面的前端实现部分只需要在登录页面上进行微调就可以。因此再次不做赘述。注册页面的实现逻辑:

点击登录页面上的注册——》跳转到注册页面——》输入用户名和两次密码——》点击注册,触发一个POST请求——》后端进行处理

后端拿到用户名和密码后:先从请求中读出用户名和密码——》判断输入是否合法——》在数据库中查询该用户是否已经存在——》不存在,判断两次密码输入是否一致——》一致就往数据库中的user表中插入该数据。

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        if(username == null || "".equals(username) || password == null || "".equals(password)){
            resp.getWriter().write("输入不合法");
            return;
        }
        User user = UserDao.selectByName(username);
        if(user == null){
            resp.getWriter().write("用户名或者密码错误");
            return;
        }
        boolean result = user.getPassword().equals(password);
        if(!result){
            resp.getWriter().write("用户名或者密码错误");
            return;
        }
        HttpSession session = req.getSession(true);
        session.setAttribute("user",user); // 将用户保存在session中
        resp.sendRedirect("bloglist.html"); // 登录成功后,跳转到博客列表页
    }
}

五、实现博客详情页

5.1 博客详情展示

实现流程:先判断是否登录——》从请求中读到blogId——》判断blogId的合法性——》根据blogId去数据库查询博客——》查询出来之后就更新博客的访问次数。

注意,此时信息卡片页显示的是博客作者的信息,根据博客的作者姓名在用户表里查到博客作者的信息。

@WebServlet("/blogdetail.html")
public class DetailServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType ("text/html;charset=utf-8");
        // loginuser 表示当前登录的用户
        User Loginuser = Util.checkLogin(req);
        if(Loginuser == null){
            resp.sendRedirect("login.html");
            return;
        }
        String blogId = req.getParameter("blogId");
        HttpSession session = req.getSession(false);
        session.setAttribute("blogId",blogId);
        if(blogId == null || "".equals(blogId)){
            resp.getWriter().write("blogId不存在");
            return;
        }
        Blog blog = BlogDao.selectOne(Integer.parseInt(blogId));
        if(blog == null){
            resp.getWriter().write("查询的博客不存在");
            return;
        }else{
            // 此页的信息卡片需要显示作者的信息,根据博客的作者姓名在用户表里查到博客作者的信息
            User BlogUser = UserDao.selectOne(blog.getBlogAuthor());
            if(BlogUser == null){
                resp.getWriter().write("查询的博客作者不存在");
                return;
            }
            // 从评论表中查询出所有的博客
            List comments = CommentDao.selectAll(Integer.parseInt(blogId));
            ServletContext servletContext = getServletContext();
            TemplateEngine engine = (TemplateEngine) servletContext.getAttribute("engine");
            WebContext webContext = new WebContext(req,resp,servletContext);
            // 如果读出的评论不为空,就显示评论
            if(comments != null){
                System.out.println(comments);
                webContext.setVariable("comments",comments);
            }
            // 进入到博客的详情页,该博客的访问量需要+1,先读出访问量,+1后,再写回到数据库
            int visitCount = blog.getVisitCount();
//            System.out.println("访问前的次数"+visitCount);
            visitCount +=1;
            BlogDao.updateVisitCount(visitCount,Integer.parseInt(blogId));
//            Blog blog2 = BlogDao.selectOne(Integer.parseInt(blogId));
//            int visitCount2 = blog2.getVisitCount();
//            System.out.println("访问后的次数"+visitCount2);
            webContext.setVariable("blog",blog);
            webContext.setVariable("bloguser",BlogUser);
//            System.out.println("登录用户"+Loginuser);
            // 在评论时,显示的是登录用户的信息
            webContext.setVariable("loginuser",Loginuser);

            int count = BlogDao.selectVisitCount(Integer.parseInt(blogId));
            webContext.setVariable("visitCount",count);
            // 只有登录的用户和博客作者是同一个人,才能删除博客、修改博客,为了避免发生错误,只有是同一个人才显示这两个按钮
            webContext.setVariable("showDeleteButton",Loginuser.getUserID()==blog.getBlogAuthor());
            webContext.setVariable("showAmendButton",Loginuser.getUserID()==blog.getBlogAuthor());
            engine.process("blogdetail",webContext, resp.getWriter());
        }
    }
}

5.2 评论的显示

实现流程和博客列表页的实现流程类似,在此不做赘述。

5.3 评论功能

先判断是否登录——》从请求中读到评论内容——》判断评论内容的合法性——》从session中读到blogId和user——》构造comment对象——》插入comment数据库——》根据blogID去blog中查询出被评论的博客,更新博客的评论次数。

@WebServlet("/comment")
public class CommentServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        User user = Util.checkLogin(req);
        if(user == null){
            resp.sendRedirect("login.html");
            return;
        }
        Comment comment = new Comment();
        String commentContent = req.getParameter("comment");
        System.out.println("从req中读到的评论内容"+commentContent);
        if(commentContent == null || "".equals(commentContent)){
            resp.getWriter().write("输入的评论不能为空");
            return;
        }
        HttpSession session = req.getSession(false);
        String blogId = (String) session.getAttribute("blogId");
//        System.out.println("从session中读到的blogId" + blogId);
        comment.setCommentContent(commentContent);
        comment.setCommentTime(new Timestamp(System.currentTimeMillis()));
        comment.setCommentUser(user.getUserName());
        comment.setBlogId(Integer.parseInt(blogId));
//        System.out.println(user.getUserPicture());
        comment.setCommentUserImage(user.getUserPicture());
//        System.out.println("登录用户的图片地址"+ user.getUserPicture());
//        System.out.println(comment);
        // comment表中新增一个数据后,评论数量+1
        CommentDao.insert(comment);
        Blog blog = BlogDao.selectOne(Integer.parseInt(blogId));
//        System.out.println("找出来的blog"+blog);
        int commentCount = blog.getCommentCount();
//        System.out.println("commentCount更新前" + commentCount);
        commentCount = commentCount + 1;
        BlogDao.updateCommentCount(commentCount,Integer.parseInt(blogId));
//        Blog blog2 = BlogDao.selectOne(Integer.parseInt(blogId));
//        int commentCount2 = blog2.getCommentCount();
//        System.out.println(blog2);
//        commentCount += 1;
//        System.out.println("commentCount更新后" + commentCount2);
        resp.sendRedirect("blogdetail.html?blogId=" + blogId);
    }
}

5.4 提问功能

提问功能的实现流程和评论功能类似,再此不做赘述。

问题提交后,会触发一个post请求。在servlet中处理post请求主要是将请求中的问题内容读出来并插入到数据库中。同时,问题提交后会跳转到问题展示页。此时会触发一个get请求,servlet在处理get请求时主要是显示所有的问题。

@WebServlet("/question.html")
public class QuestionServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        // loginuser 表示当前登录的用户
        User Loginuser = Util.checkLogin(req);
        if(Loginuser == null){
            resp.sendRedirect("login.html");
            return;
        }
//        String blogId = req.getParameter("blogId");
        List questions = QuestionDao.selectAll();
        if(questions != null){
            ServletContext servletContext = getServletContext();
            TemplateEngine engine = (TemplateEngine) servletContext.getAttribute("engine");
            WebContext webContext = new WebContext(req,resp,servletContext);
            webContext.setVariable("questions",questions);
            engine.process("question",webContext, resp.getWriter());
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
//        System.out.println("进入到questionServlet的post请求");
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        User user = Util.checkLogin(req);
        if(user == null){
            resp.sendRedirect("KnowledgeList_list.html");
            return;
        }
        Question question = new Question();
        String commentContent = req.getParameter("comment");
//        System.out.println("从req中读到的问题内容"+commentContent);
        if(commentContent == null || "".equals(commentContent)){
            resp.getWriter().write("输入的问题不能为空");
            return;
        }
        HttpSession session = req.getSession(false);
        String blogId = (String) session.getAttribute("blogId");
//        System.out.println("从session中读到的blogId" + blogId);
        question.setQuestionContent(commentContent);
        question.setUserId(user.getUserID());
        question.setBlogId(Integer.parseInt(blogId));
        QuestionDao.insert(question);
        resp.sendRedirect("question.html");
    }
}

5.5 问题删除功能

实现流程和删除博客类似,再此不做赘述。

5.6 注意

①commentservlet是博客评论功能构建的form表单触发的get请求,在列表页的servlet代码的session中加入blogID,这样在commentservlet中就能知道被评论的博客是谁了,为更新博客的评论次数做铺垫。

②此时登录的用户就是评价的用户。所以评论中博客的相关用户信息就是登录用户的相关信息。

③注意,博客详情页涉及到两个用户,一个是登录用户,一个是博客作者。只有登录的用户和博客作者是同一个人,才能删除博客、修改博客。为了保险起见,只有是同一个人才显示删除博客和修改博客这两个按钮。

④一个input输入框会对应两个按钮,此时不能使用form标签了。可以用函数来实现。

⑤如何将页面按照markdown的形式显示。

借助editor.md的内置功能,

    

5.7 前端代码



    
    
    
    Document
    
    
    
    
    
    
    



    
    
        
        我的博客系统
        
        主页
        写博客
        删除博客
        修改博客
        问答区
        注销
    
    
        
            
                

                

GitHub地址 文章 访问量

六、博客删除页

先判断是否登录——》从请求中读取博客Id——》判断blogId是否为空——》去数据库中查询是否存在——》存在就删除——》跳转到博客列表页。

@WebServlet("/deleteBlog")
public class DeleteBlogServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        User user = Util.checkLogin(req);
        if(user == null){
            resp.sendRedirect("login.html");
            return;
        }
        String blogId = req.getParameter("blogId");
        if(blogId == null){
            resp.getWriter().write("blogId不存在");
            return;
        }
        Blog blog = BlogDao.selectOne(Integer.parseInt(blogId));
        if(blog == null){
            resp.getWriter().write("您要删除的博客不存在");
            return;
        }
        BlogDao.delete(Integer.parseInt(blogId));
        resp.sendRedirect("bloglist.html");
    }
}

七、实现博客编辑页

7.1 前端页面的设计

①加入form表单,点击提交按钮可以触发一个HTTP请求。

②需要提交一个标题和正文,标题已经是一个input标签了,正文可以在editor.md这个第三方库中进行编辑,editor.md也支持form表单,具体设置为:

先在博客编辑区的div中放一个隐藏的text area。再在初始化editor对象的时候,指定一个特殊的选项saveHTMLToTextArea:true,这个选项的功能就是editor.md把用户编辑的正文放到这个text area里面。

        
            
            

7.2 后端实现逻辑

先判断是否登录——》从请求中读去博客标题和博客内容——》判断博客标题和博客内容是否合法——》构造博客对象并插入到数据库中——》跳转到博客列表页。

@WebServlet("/edit")
public class EditServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //1. 判断是否登录
        User user = Util.checkLogin(req);
        if(user == null){
            resp.sendRedirect("login.html");
            return;
        }
        // 2.从rep中拿到title和content,并校验
        String title = req.getParameter("title");
//        System.out.println(title);
        String content = req.getParameter("content");
//        System.out.println(content);
        if(title == null || "".equals(title) || content == null || "".equals(content)){
            resp.getWriter().write("标题或者正文缺失");
            return;
        }
        //3.构建一个blog,插入到数据库中
        Blog blog = new Blog();
        blog.setBlogContent(content);
        blog.setBlogTitle(title);
        blog.setBlogTime(new Timestamp(System.currentTimeMillis()));
        blog.setBlogAuthor(user.getUserID());
        BlogDao blogDao = new BlogDao();
        blogDao.insert(blog);
        //4.跳转到博客列表页
        resp.sendRedirect("bloglist.html");
    }
}

八、实现博客修改页

和博客列表页的前端页面类似,只不过博客的标题和内容是从数据库中读出来的。可以先用thymeleaf进行占位,将从数据库中读到的数据再给渲染进去。

        
            
            

当跳转到博客修改页,会触发一个get请求,在处理这个get请求时需要将要修改的博客的标题的内容返回。

当修改完成点击提交按钮,会触发一个post请求,对该请求的处理流程为:先判断是否登录——》从请求中读取博客标题和博客内容——》判断博客标题和博客内容是否合法——》更新博客——》跳转到博客详情页,跳转时需要带上博客的id。

@WebServlet("/amendBlog")
public class AmendServlet extends HttpServlet {
    public static int blogId = 0;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        User user = Util.checkLogin(req);
        if(user == null){
            resp.sendRedirect("login.html");
            return;
        }
        String blogID = req.getParameter("blogId");
        if(blogID == null){
            resp.getWriter().write("blogId不存在");
            return;
        }
        blogId = Integer.parseInt(blogID);
        Blog blog = BlogDao.selectOne(blogId);
        if(blog == null){
            resp.getWriter().write("您要修改的博客不存在");
            return;
        }
        System.out.println("要修改的博客:"+ blog);
        ServletContext servletContext = getServletContext();
        TemplateEngine engine = (TemplateEngine) servletContext.getAttribute("engine");
        WebContext webContext = new WebContext(req,resp,servletContext);
        webContext.setVariable("blog",blog);
        engine.process("blog_amend.html",webContext, resp.getWriter());
//        resp.sendRedirect("blog_amend.html");

    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //1. 判断是否登录
        User user = Util.checkLogin(req);
        if(user == null){
            resp.sendRedirect("KnowledgeList_login.html");
            return;
        }
        // 2.从rep中拿到title和content,并校验
        String title = req.getParameter("title");
//        System.out.println(title);
        String content = req.getParameter("content");
//        System.out.println(content);
        if(title == null || "".equals(title) || content == null || "".equals(content)){
            resp.getWriter().write("标题或者正文缺失");
            return;
        }
        BlogDao.updateBlog(title,content,blogId);
        resp.sendRedirect("blogdetail.html?blogId="+blogId);
    }
}

九、实现上传头像功能

先创建一个images文件夹,将用户的头像保存到这个文件夹里。

判断是否登录——》获取到images所在的磁盘路径——》获取到图片的part对象——》将头像存放在images目录中,并以用户名命名——》跳转到登录页面。

此时用户session中的user信息是没有头像属性的,会导致上传的头像无法正常显示出来。用户重新登录后,才能更新session中的user信息,此时才能将头像正常显示出来。

@MultipartConfig
@WebServlet("/imageUpload")
public class UploadImageServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        User user = Util.checkLogin(req);
        if(user == null){
            resp.sendRedirect("login.html");
            return;
        }
        String username = user.getUserName();
        System.out.println("用户的名字"+ username);
        // 获取到image所在的磁盘路径
        String path = getServletContext().getRealPath("/images");
        path = path + "/" + username + ".jpg";
       // System.out.println(path);
        // 获取到图片的Part对象
        Part part = req.getPart("image");
        // 获取到图片名字
        //String name = part.getSubmittedFileName();
        //System.out.println(name);
        // 把图片放在指定目录中
        String path2 = "./images/"+ username + ".jpg";
        part.write(path);
        UserDao userDao = new UserDao();
        userDao.uploadImages(username,path2);
        resp.sendRedirect("login.html");
    }
}

十、实现问题回答页

10.1 前端页面设计

前端页面的设计参考Lesson6:JS的WEBAPI实例练习_刘减减的博客-CSDN博客

中4.2TodoList的设计。此时约定:点击查看答案,博客的内容才会显示出来。使用display这个参数来控制,读出display的属性,如果display=none,点击后就将display=block。如果此时display=block,点击后就将display=none。可以用一个函数来实现这个功能。

        
            答题区
            
        
        
            
            
        
    
    

10.2 后端设计

点击回答按钮,会触发一个get请求,对该请求的处理流程为:先判断是否登录——》从请求中读取问题ID——》判断问题id是否合法——》根据问题ID在问题数据库中查找问题——》如果查找到问题,根据问题中的博客ID属性在博客数据库中找出博客信息——》将博客信息渲染到页面中。

@WebServlet("/answer.html")
public class AnswerServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        req.setCharacterEncoding("utf-8");
        User user = Util.checkLogin(req);
        if(user == null){
            resp.sendRedirect("login.html");
            return;
        }
        String questionId = req.getParameter("questionId");
//        String blogId = req.getParameter("blogId");
        if(questionId == null){
            resp.getWriter().write("您要回答的问题不存在");
        }
//        if(blogId == null){
//            resp.getWriter().write("您要回答的问题相关的博客不存在");
//        }
        Question question = new Question();
        question = QuestionDao.selectOne(Integer.parseInt(questionId));
        if(question == null){
            resp.getWriter().write("您要回答的问题相关的博客没有查询到");
        }
        Blog blog = BlogDao.selectOne(question.getBlogId());
        if(blog == null){
            resp.getWriter().write("您要回答的问题相关的博客没有查询到");
        }
        WebContext webContext = new WebContext(req,resp,getServletContext());
        TemplateEngine engine = (TemplateEngine) getServletContext().getAttribute("engine");
        webContext.setVariable("blog",blog);
        engine.process("answer",webContext, resp.getWriter());
    }
}

十一、实现注销功能

实现流程:判断是否登录——》获取会话session——》从session中删除user字段——》跳转到登录页面。

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        User user = Util.checkLogin(req);
        if(user == null){
            resp.getWriter().write("未登录");
            resp.sendRedirect("login.html");
        }
        HttpSession session = req.getSession();
        session.removeAttribute("user");
        resp.sendRedirect("login.html");
    }
}

 十二、实现博客列表页

12.1 实现流程

通过服务器代码,查询数据库,再将用户的信息和博客列表展示在页面上。此处需要用到Thymeleaf。

12.2 生成模板

将需要动态替换的信息使用th进行占位。博客列表的显示需要用到循环,具体步骤为:

①去掉原来页面多余的div,只保留一个页面的div。

②通过th:each的方式,根据服务器查询到包含所有博客信息的博客数组,来循环构建出这里的博客div。

③根据数据库中查询出的每个博客,将博客的标题、时间、博客内容信息,显示到页面上。

④没必要将博客正文的所有内容都显示出来,可以只显示一部分,增加一个查看全文按钮。此时,需要将blogId给拼接到a标签的url中,这时才能够知道需要从服务器中获取哪个博客。

12.3 博客的内容太多,超过设置的背景

给背景加上个css属性:overflow:auto 如果当前元素的内容溢出,就会自动加个滚动条。此时指的是给标签加上滚动条,而不是给页面加上滚动条。

    
        
            
                

                

GitHub地址 文章 总访问量 查看全文>>

12.4 完成Servlet的代码,实现整个页面的渲染
@WebServlet("/bloglist.html")
public class ListServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset = utf-8");
        User user = Util.checkLogin(req);
        if(user == null){
            resp.sendRedirect("login.html");
            return;
        }
        // 从数据库中读出所有的博客
        List blogs = BlogDao.selectAll();
        // 在登录页面时已经将用户的信息保存到session中,在强制登录方法中从session中读到登录信息,返回一个User
        int visitCount = BlogDao.selectVisitAllCount(user.getUserID());
        WebContext webContext = new WebContext(req,resp,getServletContext());
        TemplateEngine engine = (TemplateEngine) getServletContext().getAttribute("engine");
        webContext.setVariable("blogs",blogs);
        webContext.setVariable("user",user);
        webContext.setVariable("visitCount",visitCount);
        engine.process("bloglist",webContext, resp.getWriter());
    }
}

如果需要源代码,可以在评论区留言呀!!!

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

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

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