- 登录页
- 实现强制登录
URL解决后;现在到查看全文按钮。我们点击这个查看全文我们就跳转到博客详情页。
我们希望就是在这个页面;把这些写死的数据换成从后端获取的。
1:约定前后端交互接口
请求:GET /blog?blogId=1 (这样子写和博客列表页是同一个绑定的路径;还是同一个方法;但是我们会判断如果URL里有query string就返回博客详情页内容;否则返回博客列表页内容。这里新绑定一个路径也无所谓;只是这两个要响应结果比较相似;也能方便不少)但是我还是试试在不同路径下的写法;分离开降低点耦合。
响应:
HTTP/1.1 200OK
{
blogId:1,
title:“这是第一篇博客”
content :“第一次变成这样子的我;让我怎么否认”,
postTime:“2023-5-7 21:23”,
userId :1
}
2:实现后端代码;这会就不需要截断文章内容。query string可以用这个方法根据key获取val。我们就轻松拿到这个blogId。(我们在博客列表页前端并不需要传数据;如果前端是以json格式传数据;还是比较麻烦处理的。query string的接收就比较方便)
这里还得处理一下:query string是null;返回并没有问题;但是null字符串转成int就报错了。
但是这样子在后台打印的处理并不满意;因为用户看不到是什么情况;希望返回错误页面提示说没有这篇博客id的博客。但是这样子不好弄
ajax发的数据想要重定向还是比较麻烦;不像form表单、a标签是支持的。
两种方案:
一:我构造一个json数据;当blogId=null或者查不到博客时就返回这个对象。这个对象里面的内容提示说blogId=null或者查不到博客;本来正常跳转是不会出现查不到的情况;但是有时候博客太多;需要手动在地址栏搜索。避免出现这种情况
二:或者在前端代码逻辑改变一下;当查不到东西就返回null给前端。前端解析到null;使用location.assign(‘错误页面.html’)跳转到错误页面。错误页面还得我们自己实现;所以才有各种网站的错误页面的各不相同的。
3:实现前端代码
参照这个我们之前写死格式进行构造
url:‘blogdetail’+location.search,这里的location.search是js一个全局对象;获取浏览器地址栏的query string。直接拼接?blogId=3;问号都不用我们自己写
登录页
这里就使用form表单的方式:登录页是要跳转的;因为ajax没法直接返回302跳转这么方便;还得其它写法.form本身就是会触发页面跳转。
三步走:
1:前后端交互接口
请求 POST /login
username=zhangsan&password=123
响应
HTTP/1.1 302
Location:blog_list.html
2:修改前端代码
这里的id是选择器;前面引入的css文件里有;选择这些框的样式;name属性是获取这个框的内容;把它赋值于这个name名字;username=zhangsan ,password=123。
3:后端代码
先读取传过来的用户名和密码;然后看看能否在数据库中查询到
String username=req.getParameter(“username”);
String password=req.getParameter(“password”);
form读取还是比较方便的;不像json需要转来转去;但是这里读取的是英文还好;如果是中文就乱码了。所以需要设置读取的。
一个请求在设置;一个是响应在设置;理解请求和构造响应(告诉浏览器要怎么理解这个编码)。响应类型是一个页面也设置上;方便我们在登录错误的时候返回一个服务器构造页面提示登录失败
req.setCharacterEncoding(“utf8”);
resp.setContentType(“text/html;charset=utf8”);
注意这两段逻辑:不要写明确是用户错误还是密码错误;比如有个人随便输入一个用户名和密码;结果提示密码错误;那么它就搞个程序;循环遍历输入密码;那不就能找到你的密码吗。
后端代码完成:
package api;
import model.User;
import model.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 Blog_loginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.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)){
// 登录失败;这时候就可以返回一个登录失败的页面
String html = "<h3>登录失败! 缺少 username 或者 password 字段</h3>";
resp.getWriter().write(html);
return;
}
//看看用户名和密码是否匹配;如果不匹配;还是登录失败
UserDao userDao=new UserDao();
User user=userDao.selectByUsername(username);
//数据库查不到这个用户
if(user==null){
String html = "<h3>登录失败! 缺少 username 或者 password 字段</h3>";
resp.getWriter().write(html);
return;
}
if (!password.equals(user.getPassword())) {
// 密码不对
String html = "<h3>登录失败! 用户名或密码错误</h3>";
resp.getWriter().write(html);
return;
}
// 登录成功;创建会话;然后使用该会话保存用户信息
HttpSession session=req.getSession(true);
session.setAttribute("user",user);
// 重定向到博客列表页
resp.sendRedirect("blog_list.html1.html");
}
}
数据库创建几个用户登录测试一下:
强制刷新:ctrl+F5;有时候我们修改代码后重新输入URL发现内容还是原来的。浏览器的缓冲导致的。因为这个操作费时等;操作一次后浏览器就给你缓存下来;然后你再操作就直接取缓存的结果。类似多线程内存可见性问题。频繁的读到的结果一样;它就保存下来;不再去反复去读;而是直接用这个值。强制刷新无视本地缓存。
实现强制登录
当用户访问博客列表页/详情页/编辑页都要求是已登录状态;登录才能用;你自己修改自己的。你总不能改人家的吧。
还是在登录页上实现:
GET /login
HTTP/1.1 200 OK (响应把当前的登录用户信息返回;如果未登录就返回一个userId=0)
{
userId :1
username:‘zhangsan’
}
前端代码:
就是说访问每一个页面代码都会执行到这样的一个函数;然后发送这个ajax构建的get请求;然后就查看一下是否登录;登录就啥都不干;如果发现是未登录就强制跳转登录页。这段逻辑给博客列表、详情页、编辑页都加上
正常下重启服务器就得重新登录;如果服务器重启登录后;浏览器还是登录状态;这种是插件搞怪。有的tomcat插件版本会方便调试在关闭服务器的时候;把session持久化保存;在重启的时候自动恢复。war包形式是不会出现这种问题;也可以修改配置实现这种效果。这个会话我们也能用数据库持久化保存。