实现博客系统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>
六、效果展示