博客系统1.4.3(个人版本) (win64)

博客系统1.4.3(个人版本) (win64)

需求分析

场景1:用户管理页面(注册/登录页面)
显示注册框、登录输入框及注册/登录功能按钮;
场景2:首页/博客列表页
博客系统入口页;
展示历史已有博客的题目及内容节选(非正式用户也可查看);
场景2:查看博客
展示博客标题,当前博客正文所有内容,博客作者及发表时间;
场景3:发布博客
博客标题输入框、正文输入框;
发布博客功能按钮;
场景4:删除博客
删除博客功能按钮(登录后可用);
判断登录用户与计划删除博客作者是否为同一用户;
场景5:注销账户
注销账户功能按钮(已注册登录用户可用);

用户管理界面

1.设计数据库
①首先设计了两个表user表和blog表
user表, userId、username、password
user表

blog表
blog表,blogId、title、content、userId、postTime
在这里插入图片描述

两张表通过userId进行关联,可得到对应博客的作者信息,也可对后续的删除博客进一步的逻辑设计。
注意:
可以将设计数据库的sql语句放在一个文件里面,有利于后续在服务器上进行建表操作,不用进行重复编写sql语句

②将操作数据库的代码进行封装,简化代码
JDBC操作数据库与数据库建立连接,封装和数据库建立连接的过程,使用单例类封装数据库建立连接的过程

package utils;

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 JDBCUtil {
    private static final String URL="jdbc:mysql:///rb?characterEncoding=utf8&useSSL=false";
    private static final String USERNAME="root";
    private static final String PASSWORD="数据库密码";
    private static DataSource dataSource;
    public static DataSource getDataSource(){
        //首先要看DataSource是否已有实例,没有就创建新的,有就返回之前的
        //为了确保DataSource指的是当前引用,要判断其是否为null
        if(dataSource==null){
            MysqlDataSource mysqlDataSource = new MysqlDataSource();
            mysqlDataSource.setUrl(URL);
            mysqlDataSource.setUser(USERNAME);
            mysqlDataSource.setPassword(PASSWORD);
            dataSource=mysqlDataSource;
        }
        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){
        if(resultSet!=null){
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(statement!=null){
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(connection!=null){
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

2.创建实体类(blog user)

package dao;

import java.sql.Timestamp;

public class Blog {
    private int blogId;
    private String title;
    private String content;
    private int userId;
    //java.sql.data只能表示日期,没有时分秒,而Timestamp有
    private Timestamp postTime;

    public int getBlogId() {
        return blogId;
    }

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

    public String getTitle() {
        return title;
    }

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

    public String getContent() {
        return content;
    }

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

    public int getUserId() {
        return userId;
    }

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

    public Timestamp getPostTime() {
        return postTime;
    }

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

    @Override
    public String toString() {
        return "dao.Blog{" +
                "blogId=" + blogId +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", userId=" + userId +
                ", postTime=" + postTime +
                '}';
    }
}
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 "dao.User{" +
                "userId=" + userId +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

3.针对博客和用户进行具体的增删改查操作(实现了UserDao,BlogDao)
①UserDao实现了新建用户、根据用户名获取密码、根据用户ID获取用户信息

package dao;

import entity.User;
import utils.JDBCUtil;

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

public class UserDao {
    public void insert(User user){
        //1.和数据库建立连接;
        Connection connection= JDBCUtil.getConnection();
        //2.拼装sql
        String sql="insert into user values(null,?,?)";
        PreparedStatement statement=null;
        try {
            statement = connection.prepareStatement(sql);
            statement.setString(1,user.getUsername());
            statement.setString(2,user.getPassword());
            //3.执行sql
            statement.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            //4.关闭连接
            JDBCUtil.close(connection,statement,null);
        }
    }
    //登陆的时候,需要根据用户名获取到密码
    public User selectByName(String username){
        //1.和数据库建立连接
        Connection connection=JDBCUtil.getConnection();
        //2.拼装sql
        String sql="select * from user where username = ?";
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            statement=connection.prepareStatement(sql);
            statement.setString(1,username);
            //3.执行sql
            resultSet =statement.executeQuery();
            //4.遍历结果集,按照名字查找的结果是唯一的
            if (resultSet.next()){
                User user=new User();
                user.setUserId(resultSet.getInt("userId"));
                user.setUsername(resultSet.getString("username"));
                user.setPassword(resultSet.getString("password"));
                System.out.println("userDao"+user);
                return user;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JDBCUtil.close(connection,statement,resultSet);
        }
        return null;
    }
    //根据用户id获取用户信息
    //显示博客的时候需要用到
    public User selectById(int userId){
        //1.和数据库建立连接
        Connection connection=JDBCUtil.getConnection();
        //2.拼装sql
        String sql="select * from user where userId = ?";
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            statement=connection.prepareStatement(sql);
            statement.setInt(1,userId);
            //3.执行sql
            resultSet=statement.executeQuery();
            //4.遍历结果,预期结果是中有一个或者0个
            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 throwables) {
            throwables.printStackTrace();
        }finally {
            JDBCUtil.close(connection,statement,resultSet);
        }
        return null;
    }

②BlogDao实现了添加博客、删除博客、查找博客、查询所有博客等内容

package dao;

import entity.Blog;
import utils.JDBCUtil;

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 void insert(Blog blog){
        //1.和数据库服务器建立连接
        Connection connection= JDBCUtil.getConnection();
        //2.拼装SQL语句
        String sql="insert into blog values(null,?,?,?,now())";
        PreparedStatement statement=null;
        try {
            statement=connection.prepareStatement(sql);
            statement.setString(1,blog.getTitle());
            statement.setString(2,blog.getContent());
            statement.setInt(3,blog.getUserId());
            //执行SQL
            statement.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JDBCUtil.close(connection,statement,null);
        }
    }
    //从数据库中删除博客
    public void delete(int blogId){
        //1.数据库服务器建立连接
        Connection connection= JDBCUtil.getConnection();
        //拼装SQL
        String sql="delete from blog where blogId=?";
        PreparedStatement statement=null;
        try {
            statement =connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            //执行SQL
            statement.executeUpdate();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JDBCUtil.close(connection,statement,null);
        }
    }
    //limit offset 数据库中内容很多可进行分页
    public List<Blog> selectAll(){
        List<Blog> blogs=new ArrayList<Blog>();
        //1.和数据库服务器建立连接
        Connection connection= JDBCUtil.getConnection();
        //2.拼装SQL
        String sql="select * from blog order by blogId desc ";
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            statement=connection.prepareStatement(sql);
            //3.执行sql
            resultSet=statement.executeQuery();
            //4.遍历结果集
            while (resultSet.next()){
                Blog blog=new Blog();
                blog.setBlogId(resultSet.getInt("blogId"));
                blog.setTitle(resultSet.getString("title"));
                String content=resultSet.getString("content");
                if(content.length()>10){
                    content=content.substring(0,10)+".......";//左闭右开的区间
                }
                blog.setContent(content);
                blog.setUserId(resultSet.getInt("userId"));
                blog.setPostTime(resultSet.getTimestamp("postTime"));
                blogs.add(blog);
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            JDBCUtil.close(connection,statement,resultSet);
        }
        return blogs;
    }
    public Blog selectOne(int blogId){
        //1.和数据库建立连接
        Connection connection= JDBCUtil.getConnection();
        //2.拼装sql
        String sql="select * from blog where blogId = ?";
        PreparedStatement statement=null;
        ResultSet resultSet=null;
        try {
            statement=connection.prepareStatement(sql);
            statement.setInt(1,blogId);
            //执行sql
            resultSet=statement.executeQuery();
            //4.遍历结果集,要么使0个,要么只有一条记录;
            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 throwables) {
            throwables.printStackTrace();
        }finally {
            JDBCUtil.close(connection,statement,resultSet);
        }
        return null;
    }

写完后可根据每个功能进行Junit测试,或者冒烟测试,保证代码的逻辑正确。

servlet

1.注册登录功能
获取请求中的username和password,然后进行判断。写代码的过程中一定要注意编码问题,要记得设定统一的编码,防止中文乱码。
其中的一些错误页面,也可以写出对应的静态页面,然后通过重定向。eg:resp.sendRedirect(“blogList”);

package servlet;

import entity.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.先从请求中读取username和password
        req.setCharacterEncoding("utf-8");
        String username=req.getParameter("username");
        String password=req.getParameter("password");
        if(username==null||"".equals(username)||password==null||"".equals(password)){
            resp.sendError(404,"用户名或密码为空");
            return;
        }
        //2.从数据中查找指定用户名的信息
        UserDao userDao=new UserDao();
        User user= userDao.selectByName(username);
        System.out.println(user);
        if(user==null){
            resp.sendError(404,"您的用户名或密码有误或未注册");
            return;
        }
        if(!password.equals(user.getPassword())){
            resp.sendError(404,"您的用户名或密码有误");
            return;
        }
        //3.登陆成功,创建会话
        HttpSession session= req.getSession(true);
        session.setAttribute("user",user);
        //4.直接把用户页面重定向到主页(博客列表页)
        resp.sendRedirect("blogList");
    }
}
package servlet;

import entity.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 java.io.IOException;

@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //如果不做任何限定,此时服务器这边读取Parameter时侯默认不是UTF-8
        req.setCharacterEncoding("utf-8");
        //1.先读取用户名提交的用户和密码
        String username=req.getParameter("username");
        String password=req.getParameter("password");
        if(username==null||"".equals(username)||password==null||"".equals(password)){
            resp.sendError(404,"提交的用户名或密码为空");
            return;
        }
        //2.查询数据库看username是否存在
        UserDao userDao=new UserDao();
        User existUser=userDao.selectByName(username);
        if(existUser!=null){
            //用户已经存在提醒注册失败
            resp.sendError(404,"用户名已存在");
            return;
        }
        //3.构造User对象,插入到数据库中
        User newuser=new User();
        newuser.setUsername(username);
        newuser.setPassword(password);
        userDao.insert(newuser);
        //4.返回一个结果
        resp.setContentType("text/html;charset=utf-8");
        resp.getWriter().write("<h3>恭喜注册成功!</h3>");
    }

2.博客列表页
博客列表页中涉及了一个有关Thmeleaf渲染的功能。
Thmeleaf最大的特点是能够直接在浏览器中打开并正确显示模板页面,而不需要启动整个web页面。
Thmeleaf通过第三方库导入依赖,engine需要在多个servlet之间共享,所以将初始化engine的工作交给ServletContext,任意一个servlet都可以拿到一个ServletContext对象,这样也就能拿到同一个engine。

package servlet;

import entity.Blog;
import dao.BlogDao;
import entity.User;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

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.util.List;

@WebServlet("/blogList")
public class BlogListServlet extends HttpServlet {
    private  TemplateEngine engine=null;
    @Override
    public void init() throws ServletException {
        //init生命周期,初始化一次,我们可以利用这个方法,将Thmeleaf初始化
        //1)创建一个engie(引擎),负责把java中的数据替换到模板中
        engine=new TemplateEngine();
        //2)创建一个resover对象(解析器)负责找到html模板在哪啦,供engie对象使用
        ServletContextTemplateResolver resolver=new ServletContextTemplateResolver(getServletContext());
        //3)给resover设置一些属性,让它能够找到html模板
        resolver.setCharacterEncoding("utf-8");
        //prefix表示前缀,设定了满足啥样条件的文件被加载到内存中作为HTML模板
        resolver.setPrefix("/WEB-INF/template/");
        //Suffix表示后缀
        resolver.setSuffix(".html");
        //4)把resolver和engine关联起来
        engine.setTemplateResolver(resolver);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //0.从req中读取一下当前用户信息,判定用户是否登录
        HttpSession session=req.getSession(false);
        boolean isLogin=true;
        User user=null;
        if(session==null){
            isLogin=false;
        }else{
            user=(User)session.getAttribute("user");
            if(user==null){
                isLogin=false;
            }
        }
        //1.先从数据库查询出有那些博客
        BlogDao blogDao=new BlogDao();
        List<Blog> blogsList= blogDao.selectAll();
        //2.构造博客页面
        //1)通过Thymeleaf进行渲染,渲染的时候要定义”数据集合“这样的概念
        //WebContext功能就是把要替换的数据收集起来,统一的交给模板引擎
        WebContext webContext=new WebContext(req,resp,getServletContext());
        //2)setVariable可以设置多个键值对,完全取决于模板代码怎么写。
        //模板里的每一个${}里面的内容都需要在webContext设定进去
        webContext.setVariable("blogs",blogsList);
        webContext.setVariable("isLogin",isLogin);
        webContext.setVariable("user",user);
        //3)进行渲染
        TemplateEngine engine=(TemplateEngine)getServletContext().getAttribute("engine");
        String html= engine.process("blog_list",webContext);//渲染的文件名
        System.out.println("模板渲染的内容:"+html);
        resp.setContentType("text/html;charset=utf-8");
        resp.getWriter().write(html);
    }
}

3.博客发布页
如果用户尚未登录,则无法添加博客。

package servlet;

import entity.Blog;
import dao.BlogDao;
import entity.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;

@WebServlet("/blogInsert")

public class BlogInsertServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //0.判定用户是否已经登陆

        req.setCharacterEncoding("utf-8");
        HttpSession session=req.getSession(false);
        if(session==null){
            resp.sendError(404,"请登录后发布博客");
            return;
        }
        User user=(User) session.getAttribute("user");
        if(user==null){
            resp.sendError(404,"请登录后发布博客");
            return;
        }
        //1.读取请求中的参数.
        String title=req.getParameter("title");
        String content=req.getParameter("content");
        if(title==null||"".equals(title)||content==null||"".equals(content)){
            resp.sendError(500,"标题或者正文为空");
            return;
        }
        //2.根据读到的数据构造blog对象,并填入数据库
        Blog blog=new Blog();
        blog.setTitle(title);
        blog.setContent(content);
        blog.setUserId(user.getUserId());
        BlogDao blogDao=new BlogDao();
        blogDao.insert(blog);
        //3.重定向到博客列表页
        resp.sendRedirect("blogList");
    }
}

4.博客正文页
根据对应的博客ID找到对应的博客再根据博客中的userId找到对应作者的信息。

package servlet;

import entity.Blog;
import dao.BlogDao;
import entity.User;
import dao.UserDao;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;

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;


@WebServlet("/blogContent")
public class BlogContentServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        String blogId = req.getParameter("blogId");
        if(blogId==null||"".equals(blogId)){
            resp.sendError(404,"blogId不存在");
            return;
        }
        BlogDao blogDao=new BlogDao();
        Blog blog=blogDao.selectOne(Integer.parseInt(blogId));
        if(blog==null){
            resp.sendError(404,"blogId指定的文章不存在");
            return;
        }
        UserDao userDao=new UserDao();
        User user=userDao.selectById(blog.getUserId());
        //根据详细内容,渲染到模板中
        TemplateEngine engine= (TemplateEngine) getServletContext().getAttribute("engine");
        WebContext webContext=new WebContext(req,resp,getServletContext());
        webContext.setVariable("blog",blog);
        webContext.setVariable("username",user.getUsername());
        String html=engine.process("blog_content",webContext);
        //把渲染好的结果返回给·客户端
        resp.getWriter().write(html);
    }
}

5.博客删除页面
获取要删除的博客ID,判断用户是否登录,以及此博客对应的userId是否一致来判断是否可以删除此博客。

package servlet;

import entity.Blog;
import dao.BlogDao;
import entity.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;
@WebServlet("/blogDelete")
public class BlogDeleteServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String blohId=req.getParameter("blogId");
        if(blohId==null||"".equals(blohId)){
            resp.sendError(404,"您的blogId为空");
            return;
        }
        HttpSession session=req.getSession(false);
        if(session==null){
            resp.sendError(404,"当前未登录不能删除");
            return;
        }
        User user=(User)session.getAttribute("user");
        if(user==null){
            resp.sendError(404,"当前未登录不能删除");
            return;
        }
        BlogDao blogDao=new BlogDao();
        Blog blog=blogDao.selectOne(Integer.parseInt(blohId));
        if(blog==null){
            resp.sendError(404,"当前博客不存在!");
            return;
        }
        if(blog.getUserId()!=user.getUserId()){
            resp.sendError(403,"您无法删除此博客");
            return;
        }
        blogDao.delete(Integer.parseInt(blohId));
        //5.重定向到博客列表页
        resp.sendRedirect("blogList");
    }
}

前端实现

1.登录注册页面
在这里插入图片描述
2.博客列表页及正文页
在这里插入图片描述

3.博客发布页
在这里插入图片描述
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值