问题分析
代码实现
处理逻辑
创建过滤器,添加注解 @WebFilter
?
添加
过滤器名称:filterName = "loginCheckFilter",
拦截路径:urlPatterns = "/*"
实现filter里的doFilter方法
LoginCheckFilter.java
package com.itheima.reggie.filter;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 检查用户是否已完成登录
*/
@Slf4j
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request= (HttpServletRequest) servletRequest;//强转
HttpServletResponse response = (HttpServletResponse) servletResponse;
log.info("拦截到请求:{}",request.getRequestURI());
filterChain.doFilter(request,response);
}
}
在application.java添加@ServletComponentScan注解,这样才能去扫描我们的@WebFilter注解,从而把我们 的过滤器创建出来。
运行测试效果
首先将5个步骤复制到代码中,然后在根据每一步进行代码编写,这样的代码清晰易懂,每一行做好备注。
编写过滤器处理逻辑
前端JS中使用了响应拦截器,用来拦截服务的给页面上的响应的
后端也有一个
package com.itheima.reggie.filter;
import com.alibaba.fastjson.JSON;
import com.itheima.reggie.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 检查用户是否已完成登录
*/
@Slf4j
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
//路径匹配器,支持通配符。专门用来路径比较的
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request= (HttpServletRequest) servletRequest;//强转
HttpServletResponse response = (HttpServletResponse) servletResponse;
//1、获取本次请求的URI
String requestURI= request.getRequestURI();//backend/index.html
//定义不需要处理的请求路径
String[] urls= new String[]{
"/employee/login", //表示点击的登录按钮 直接放行
"/employee/logout", //表示点击的退出按钮 直接放行
"/backend/**",//静态资源直接放行,页面没事 但是对应的数据 会发生ajax请求,无法访问。只拦截controller的请求。
"/front/**"
} ;
//2、判断本次请求是否需要处理
boolean check = check(urls, requestURI);//调用check方法 把urls和reqiestURI传进去
// 3、如果不需要处理,则直接放行
if (check){
filterChain.doFilter(request,response);
return;
}
// 4、判断登录状态,如果已登录,则直接放行
//session中可以取出用户,不为空,则说明已经登录了
if(request.getSession().getAttribute("employee") != null){
filterChain.doFilter(request,response);
return;
}
// 5、如果未登录则返回未登录结果,过输出流的方式向客户端响应数据
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));//NOTLOGIN取自backend中request.js响应拦截器里的
return;
// log.info("拦截到请求:{}",request.getRequestURI());
// filterChain.doFilter(request,response);
}
/**路径匹配,检查本次请求是否需要放行
* 把URLS传进来 遍历
* @param urls
* @param requestURI
* @return
*/
public boolean check(String[] urls,String requestURI){
for (String url : urls) {
boolean match = PATH_MATCHER.match(url, requestURI);
if(match){
return true;
}
}return false ;//匹配不上返回false
}
}
可以加一些日志,方便调试
测试1,不登陆 ,直接访问:localhost:8080/backend/index.html,可以看到效果,一闪而过的index页面就返回了登录首页。如果点击登录的话,就可以正常进入index页面了。
控制台会有拦截请求
也可以页面测试 F12-sources-request.js 加断点
汉语版
英文版,汉语版好理解,博主这里给大家展示英文版的
访问backend/index.html
显示如下
这个是单步调试
走一步 会显示
放行按钮
package com.itheima.reggie.filter;
import com.alibaba.fastjson.JSON;
import com.itheima.reggie.common.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 检查用户是否已完成登录
*/
@Slf4j
@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
//路径匹配器,支持通配符。专门用来路径比较的
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request= (HttpServletRequest) servletRequest;//强转
HttpServletResponse response = (HttpServletResponse) servletResponse;
//1、获取本次请求的URI
String requestURI= request.getRequestURI();//backend/index.html
log.info("拦截到请求:{}",requestURI);
//定义不需要处理的请求路径
String[] urls= new String[]{
"/employee/login", //表示点击的登录按钮 直接放行
"/employee/logout", //表示点击的退出按钮 直接放行
"/backend/**",//静态资源直接放行,页面没事 但是对应的数据 会发生ajax请求,无法访问。只拦截controller的请求。
"/front/**"
} ;
//2、判断本次请求是否需要处理
boolean check = check(urls, requestURI);//调用check方法 把urls和reqiestURI传进去
// 3、如果不需要处理,则直接放行
if (check){
log.info("本次请求{}不需要处理",requestURI);
filterChain.doFilter(request,response);
return;
}
// 4、判断登录状态,如果已登录,则直接放行
//session中可以取出用户,不为空,则说明已经登录了
if(request.getSession().getAttribute("employee") != null){
log.info("用户已登录,用户id微:{}",request.getSession().getAttribute("empliyee"));
filterChain.doFilter(request,response);
return;
}
// 5、如果未登录则返回未登录结果,过输出流的方式向客户端响应数据
log.info("用户未登录");
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));//NOTLOGIN取自backend中request.js响应拦截器里的
return;
// log.info("拦截到请求:{}",request.getRequestURI());
// filterChain.doFilter(request,response);
}
/**路径匹配,检查本次请求是否需要放行
* 把URLS传进来 遍历
* @param urls
* @param requestURI
* @return
*/
public boolean check(String[] urls,String requestURI){
for (String url : urls) {
boolean match = PATH_MATCHER.match(url, requestURI);
if(match){
return true;
}
}return false ;//匹配不上返回false
}
}
添加一些数据,点击保存,这一步,我们主要看请求发到哪里去了,消息是json形式的
先写一个框架,打上断点,然后测试
填上一些数据,点击保存
数据过来了
至此,证明心中数据是可以正常封装的,进行下一步
//设置初始密码,但是要进行MD5加密
employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));
/**
* 新增员工
* 要返回json 所以添加@requestbody
* @param employee
* @return
*/
@PostMapping
public R<String> save(HttpServletRequest request,@RequestBody Employee employee){
log.info("新增员工,员工信息:{}",employee);
//设置初始密码,但是要进行MD5加密
employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));
//设置创建时间
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
// 获得当前用户的ID 强转为LONG类型
Long empId = (Long) request.getSession().getAttribute("employee");
employee.setCreateUser(empId);
employee.setUpdateUser(empId);
// 最后调用save方法进行存入
employeeService.save(employee);
return R.success("新增员工成功");
}
}
代码测试
查看控制台insert语句
插入成功,时间就是当前时间,密码也是进行了MD5加密的123456
当我们在添加同一条姓名的数据时,报错
而这是最底层的数据库反馈的,稍后我们解决这个问题。
package com.itheima.reggie.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.itheima.reggie.common.R;
import com.itheima.reggie.entity.Employee;
import com.itheima.reggie.service.EmployeeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
@Slf4j
@RestController
@RequestMapping("/employee")
public class EmployeeController {
@Autowired
private EmployeeService employeeService;
/**
*员工登录
*/
@PostMapping("/login")
public R<Employee> login(HttpServletRequest request, @RequestBody Employee employee){
/**
* 1、将页面提交的密码password进行md5加密处理
* 2、根据页面提交的用户名username查询数据库
* 3、如果没有查询到则返回登录失败结果
* 4、密码比对,如果不一致则返回登录失败结果
* 5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果
* 6、登录成功,将员工id存入Session并返回登录成功结果
*/
// * 1、将页面提交的密码password进行md5加密处理
String password = employee.getPassword();
password = DigestUtils.md5DigestAsHex(password.getBytes());
// * 2、根据页面提交的用户名username查询数据库
LambdaQueryWrapper<Employee> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Employee::getUsername,employee.getUsername());
Employee emp = employeeService.getOne(queryWrapper);
// * 3、如果没有查询到则返回登录失败结果
if (emp==null){
return R.error("登陆失败");
}
// * 4、密码比对,如果不一致则返回登录失败结果
if(!emp.getPassword().equals(password)){
return R.error("登陆失败");
}
// * 5、查看员工状态,如果为已禁用状态,则返回员工已禁用结果
if(emp.getStatus() == 0){
return R.error("账号已禁用");
}
// * 6、登录成功,将员工id存入Session并返回登录成功结果
request.getSession().setAttribute("employee",emp.getId());
return R.success(emp);
}
/**
* 员工退出
* @param request
* @return
*/
@PostMapping("logout")
public R<String> logout(HttpServletRequest request){
//清理Session中保存的当前登陆员工的id
request.getSession().removeAttribute("employee");
return R.success("退出成功");
}
/**
* 新增员工
* 要返回json 所以添加@requestbody
* @param employee
* @return
*/
@PostMapping
public R<String> save(HttpServletRequest request,@RequestBody Employee employee){
log.info("新增员工,员工信息:{}",employee);
//设置初始密码,但是要进行MD5加密
employee.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));
//设置创建时间
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
// 获得当前用户的ID 强转为LONG类型
Long empId = (Long) request.getSession().getAttribute("employee");
employee.setCreateUser(empId);
employee.setUpdateUser(empId);
// 最后调用save方法进行存入
employeeService.save(employee);
return R.success("新增员工成功");
}
}
day01链接:Java项目实战--瑞吉外卖DAY01-CSDN博客
持续更新中---------------------------------------------------------------------------