实现博客系统2

简介: 实现博客系统

实现博客系统1:https://developer.aliyun.com/article/1521719

3、实现登录页

约定前后端交互接口

使用form表单来进行提交

//请求
POST/login
Content-Type:application/x-www-form-urlencoded
username=?&password=?
//响应
HTTP/1.1 302
Location:blog_list.html

服务器端

先将请求和响应都按照utf8进行解析避免出现乱码,然后获取到请求中的userName和password判断是否与数据库匹配,若匹配就创建会话跳转到博客列表页。

@WebServlet("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf8");
        resp.setCharacterEncoding("utf8");
        resp.setContentType("text/html;charset=utf8");
        String userName = req.getParameter("userName");
        String password = req.getParameter("password");
        if(userName == null || "".equals(userName) || password == null || "".equals(password)){
            resp.getWriter().write("用户名或密码不能为空");
            return;
        }
        UserDAO userDAO = new UserDAO();
        User user = userDAO.getUserByName(userName);
        if(user != null && user.getPassword().equals(password)){
            //创建会话
            HttpSession session = req.getSession(true);
            //将信息存储到绘画中
            session.setAttribute("user",user);
            //返回重定向报文,跳转到详情页
            resp.sendRedirect("blog-list.html");
        }else{
            resp.getWriter().write("用户名或密码错误");
        }
    }
}

客户端

利用form表单进行提交。

<form action="login" method="post">
    <div class="row">
        <span>用户名</span>
        <span><input  class="input" type="text" name="userName"></span>
    </div>
    <div class="row">
        <span>密码</span>
        <span><input  class="input" type="password" name="password"></span>
    </div>
    <div class="submit">
        <input type="submit" id="submit" value="提交">
    </div>
</form>

4、实现强制要求登陆

对于博客列表页和博客详情页等都需要在登录成功的基础上来进行后序的操作。

约定前后端交互接口

登录状态就返回当前用户的信息,未登录就返回userId为0的对象。

//请求
GET/login
//响应
HTTP/1.1 200 OK
Content-Type:application/json
{
    userId:xx,
    userName
}


服务器端

先判断是否创建会话,再判断会话中是否存在user对象,两种情况等都满足表示已经登录,否则就是未登录状态。

//获取当前的登录状态
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        resp.setContentType("application/json;charset=utf8");
        HttpSession session = req.getSession(false);
        User user = new User();
        if(session == null){
            //未创建会话,表示未登录
            resp.getWriter().write(objectMapper.writeValueAsString(user));
            return;
        }
        user = (User)session.getAttribute("user");
        if(user == null){
            //会话中没有user对象
            user = new User();
            resp.getWriter().write(objectMapper.writeValueAsString(user));
            return;
        }
        //将密码信息不返回给前端
        user.setPassword("");
        resp.getWriter().write(objectMapper.writeValueAsString(user));
    }


客户端

在博客列表页和详情页等加入该方法来判断是否登录,若未登录就跳转到登录页面进行登录。

//获取当前登录状态
        function getUserInfo(pageName){
            $.ajax({
                type:'get',
                url:'login',
                success:function(body){
                    //判定body中的user对象是否有效
                    if(body.userId && body.userId > 0){
                        //表示登录成功,暂时不做处理
                    }else{
                        alert("您当前尚未登录");
                        //跳转到登录页
                        location.assign('blog-login.html');
                    }
                },
                error:function(){
                    alert("您当前尚未登录");
                    //跳转到登录页
                    location.assign('blog-login.html');
                }
            });
        }

5、实现显示用户信息

在登录之后,博客详情页能显示当前作者的个人信息。

进入博客详情页之后能显示作者的个人信息。  

约定前后端交互接口

//请求
GET/user
//响应
{
    userId:xx,
    userName:xxx
    
}
//请求
GET/user?userId=xx
//响应
{
    userId:xx,
    userName:xxx
    
}

服务器端

在数据库中先得到当前博客的id,再获取到其作者信息。

@WebServlet("/authorInfo")
public class AuthorServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf8");
        //获取到指定博客的作者信息
        String param = req.getParameter("blogId");
        if (param == null || "".equals(param)) {
            resp.getWriter().write("{\"ok\":false,\"reason:\":\"参数缺失!\"}");
            return;
        }
        BlogDAO blogDAO = new BlogDAO();
        Blog blog = blogDAO.getBlog(Integer.parseInt(param));
        if(blog == null){
            resp.getWriter().write("{\"ok\":false,\"reason:\":\"要查询的博客不存在!\"}");
            return;
        }
        UserDAO userDAO = new UserDAO();
        User author = userDAO.getUserById(blog.getUserId());
        if(author == null){
            resp.getWriter().write("{\"ok\":false,\"reason:\":\"要查询的用户不存在!\"}");
            return;
        }
        ObjectMapper objectMapper = new ObjectMapper();
        author.setPassword("");
        resp.getWriter().write(objectMapper.writeValueAsString(author));
    }
}


客户端

只需要在登录成功时将用户名改成当前登录的用户名。

function changeUserName(userName){
        let h3 = document.querySelector('.card>h3');
        h3.innerHTML = userName;
    }

在进入博客列表详情页时显示作者名。

 function getAuthorInfo(user){
        $.ajax({
            type:'get',
            url:'authorInfo'+location.search,
            success:function(body){
                if(body.userName){
                    changeUserName(body.userName);
                }else{
                    alert("获取作者信息失败")
                }
            },
            error:function(){
                alert("获取作者信息失败")
            }
        });
    }

6、实现发布博客

实现前后端交互接口

//请求
POST/blog
Content-Type:application/x-www-form-urlencoded
//响应
HTTP/1.1 302
Location:blog_list.html


服务器端

先确保用户是登录状态,然后再确认发表的博客标题和内容都不能为空,然后将发表的博客插入到数据库中,页面跳转到博客列表页。

//发表博客
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf8");
        resp.setCharacterEncoding("utf8");
        resp.setContentType("text/html;charset=utf8");
        ObjectMapper objectMapper = new ObjectMapper();
        HttpSession session = req.getSession(false);
        if(session == null){
            resp.getWriter().write("用户未登录");
            return;
        }
        User user = (User)session.getAttribute("user");
        if(user == null){
            resp.getWriter().write("用户未登录");
            return;
        }
        String title = req.getParameter("title");
        String content = req.getParameter("content");
        if(title == null || "".equals(title) || content == null || "".equals(title)){
            resp.getWriter().write("提交博客失败,缺少博客标题或内容");
            return;
        }
        Blog blog = new Blog();
        blog.setUserId(user.getUserId());
        blog.setTitle(title);
        blog.setContent(content);
        BlogDAO blogDAO = new BlogDAO();
        try {
            blogDAO.addBlog(blog);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        resp.sendRedirect("blog-list.html");
    }

客户端

利用form表单将内容进行提交。

<form action="blog" method="post" style="height:100%">
            <div class="title">
                <input type="text" placeholder="在此处输入标题" name="title" id="title">
                <!-- <button>发布文章</button> -->
                <input type="submit" value="发布文章" id="submit">
            </div>
            <!-- 放置 md 编辑器 -->
            <div id="editor">
                <!-- 为了进行 form 的提交, 此处搞一个 textarea 多行编辑框, 借助这个编辑框来实现表单的提交 -->
                <!-- 可以设置 editor.md, 让编辑器把 markdown 内容也同步的保存到这个隐藏的 textarea 中, 从而可以进行 form 提交 -->
                <textarea name="content" style="display:none"></textarea>
            </div>
</form>

7、删除博客

约定前后端交互接口

//请求
GET/user?blogId=x
//响应
{
userId:xx;
userName:xxx;
isYourBlog: 1,  // 1 表示当前博客就是登陆者的博客. 0 表示当前博客不是登陆者的博客. 
}

服务器端

先判断当是否为登录状态,然后判断当前作者与登录用户是否一致,若相同则在数据库中删除该博客,然后将页面跳转到博客列表页。

@WebServlet("/blogDelete")
public class DeleteBlogServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf8");
        HttpSession session = req.getSession(false);
        if(session == null){
            resp.getWriter().write("用户未登录");
            return;
        }
        User user = (User)session.getAttribute("user");
        if (user == null) {
            resp.getWriter().write("用户未登录");
            return;
        }
        String blogId = req.getParameter("blogId");
        if(blogId == null || "".equals(blogId)){
            resp.getWriter().write("博客编号有误");
            return;
        }
        BlogDAO blogDAO = new BlogDAO();
        Blog blog = blogDAO.getBlog(Integer.parseInt(blogId));
        if(blog == null || "".equals(blog)){
            resp.getWriter().write("待删除的博客不存在");
            return;
        }
        if(user.getUserId() != blog.getUserId()){
            resp.getWriter().write("不是本博客的作者,无法删除");
            return;
        }
        try {
            blogDAO.deleteBlog(Integer.parseInt(blogId));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        resp.sendRedirect("blog-list.html");
    }
}

客户端

在列表详情页如果判断当前的作者是正在登录的用户,就新增一个删除超链接,可以进行删除。

function getAuthorInfo(user){
        $.ajax({
            type:'get',
            url:'authorInfo'+location.search,
            success:function(body){
                if(body.userName){
                    changeUserName(body.userName);
                    if(body.userName == user.userName){
                        let navDiv = document.querySelector('.nav');
                        let a = document.createElement('a');
                        a.innerHTML='删除';
                        a.href = 'blogDelete' +location.search;
                        navDiv.appendChild(a);
                    }
                }else{
                    alert("获取作者信息失败")
                }
            },
            error:function(){
                alert("获取作者信息失败")
            }
        });
    }

8、实现注销功能

约定前后端交互接口

//请求
GET/logout
//响应
HTTP/1.1 302
Location:login.html

服务器端

先确认是否创建会话以确保登录状态,然后删除会话信息,并将登录的用户从数据库中删除,注销后跳转到登录页面。

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("application/json;charset=utf8");
        HttpSession session = req.getSession(false);
        if(session == null){
            resp.getWriter().write("用户未登录");
            return;
        }
        User user = (User)session.getAttribute("user");
        //删除会话信息
        session.removeAttribute("user");
        UserDAO userDAO = new UserDAO();
        try {
            userDAO.deleteUser(user.getUserId());
            System.out.println(user.getUserId());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        resp.sendRedirect("blog-login.html");
    }
}


客户端

将注销超链接的href修改为logout。

<a href="logout">注销</a>

六、效果展示


目录
相关文章
|
API Android开发 开发者
Android UI设计: 什么是RecyclerView?为什么它比ListView更好?
Android UI设计: 什么是RecyclerView?为什么它比ListView更好?
241 2
|
机器学习/深度学习 存储 NoSQL
Graph RAG: 知识图谱结合 LLM 的检索增强
RAG(Retrieval Argumented Generation)这种基于特定任务/问题的文档检索范式中,我们通常先收集必要的上下文,然后利用具有认知能力的机器学习模型进行上下文学习(in-context learning),来合成任务的答案。这次,我们借助 LLM 的力量,强化下 RAG。
2623 0
Graph RAG: 知识图谱结合 LLM 的检索增强
|
缓存 算法 网络协议
面向5G的阿里自研标准化协议库XQUIC
XQUIC是阿里巴巴淘系架构团队自研的IETF QUIC标准化协议库实现,在手机淘宝上进行了广泛的应用,并在多个不同类型的业务场景下取得明显的效果提升,为手机淘宝APP的用户带来丝般顺滑的网络体验: 在RPC请求场景,网络耗时降低15% 在直播高峰期场景,卡顿率降低30%、秒开率提升2% 在短视频场景,卡顿率降低20%
4582 1
面向5G的阿里自研标准化协议库XQUIC
|
12月前
|
SQL 机器学习/深度学习 分布式计算
dataworks节点任务
在DataWorks中,你可以通过拖拽节点以及连线来构建复杂的工作流,这样可以方便地管理多个任务之间的依赖关系。此外,DataWorks还提供了调度功能,使得这些任务可以在设定的时间自动执行。这对于构建自动化、定时的数据处理管道非常有用。
232 5
|
存储 算法
USB3.2 摘录(10)
USB3.2 摘录(10)
174 1
|
Web App开发 JSON 前端开发
网络调试利器:Chrome Network工具的详细指南
Chrome开发者工具的Network面板是测试工程师的利器,用于监视HTTP请求、响应及资源加载。打开它可通过右键点击页面选择“检查”或使用快捷键。界面包含请求列表和详细信息,如Headers、Preview、Response、Timing。过滤器帮助定位特定请求,而瀑布流图展示加载顺序。模拟网络环境和保存HAR文件功能便于性能分析和问题排查。
|
存储 SQL 关系型数据库
MySQL数据库——存储过程-介绍以及基本语法(特点、创建、调用、查看、删除、示例)
MySQL数据库——存储过程-介绍以及基本语法(特点、创建、调用、查看、删除、示例)
1345 0
|
JavaScript
Vue状态管理:什么是getters?Vuex中的getters有什么作用?
Vue状态管理:什么是getters?Vuex中的getters有什么作用?
474 3
|
弹性计算 关系型数据库 Apache
手把手教你使用阿里云服务器搭建个人博客
这是我第一次搭建个人博客网站,总体上来说还是非常顺利的,主要四个步骤,首先创建阿里云服务器,其次创建云数据库实例,再次阿里云服务器链接云数据库,最后安装WordPress。四步轻松就可以搭建个人博客网站啦,之前搭建博客起码需要一两周的时间,这次建站只花费了我1个小时就完成啦。
3933 12