http://localhost:8080/backend/page/login/login.html
在这个路径下,当我们点击登陆时,会发现有这样一个请求
请求 URL: http://localhost:8080/employee/login
此时报错404,是因为我们后台还没有响应这个请求的处理器,所以我们需要创建相关类来处理登录请求
代码开发从前端代码中,可以得知请求为/employee/login,后端需要传给前端的数据有msg,data,code
code==1时表示登陆成功并会跳转到首页
-
创建实体类Employee,和数据库中employee表进行映射,这里可以用MyBatisPlus代码生成器自动生成
-
编写完实体类后马上编写mapper(MyBatisPlus的写法),注意标记@Mapper告诉Spring是Mapper层
@Mapper public interface EmployeeMapper extends BaseMapper
{} -
编写Service层托管Mapper层,提供给Controller调用
service接口
public interface EmployeeService extends IService
{} serviceImpl实现类==(注意标记@Service告诉Spring是Service层)==
@Service public class EmployeeServiceImpl extends ServiceImpl
implements EmployeeService {} -
编写EmployeeController层(对应前端请求)
注意加上@RestController注解,因为这是前后端分离项目,只需要传输json数据给前端即可
@RestController//@RestController注解,相当于@Controller+@ResponseBody两个注解的结合,返回json数据不需要在方法前面加@ResponseBody注解了,但使用@RestController这个注解,就不能返回jsp,html页面,视图解析器无法解析jsp,html页面 @Slf4j//开启日志 @RequestMapping("/employee") public class EmployeeController { //这里自动装配不推荐使用字段注入,因此手动写初始方法 private final EmployeeService employeeService; public EmployeeController(EmployeeService employeeService) { this.employeeService = employeeService; } } -
在EmployeeController层中登录请求实现 /employee/login
@PostMapping("/login") public Rlogin(HttpServletRequest request, @RequestBody Employee employee){ //1.将页面提交的密码password进行md5加密处理 String password = employee.getPassword(); password = DigestUtils.md5DigestAsHex(password.getBytes()); //2.根据页面提交的用户名username查询数据库 LambdaQueryWrapper 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); }
登录功能实现:
后台退出功能开发 需求分析当我们点击退出登录时,存在一个/logout请求
实现/logout请求
代码开发用户点击页面中退出按钮,发送请求,请求地址为/employee/logout,请求方式为Post
只需要在Controller中创建对应的处理方法即可,具体的处理逻辑:
- 清理Session中的用户id
- 返回结果
@PostMapping("/logout")
public R logout(HttpServletRequest request){
//1.清理Session中保存的当前登陆员工的id
request.getSession().removeAttribute("employee");
return R.success("退出成功");
}
功能测试
当我们登录时,存在Session
当退出登录时,自动清除Session数据
登录功能优化 问题分析 由于我们没有对于首页,资源访问等进行限制,因此即便是用户没有登录,也能通过对应的url访问到项目的所有静态资源,这是十分危险的事情,因此我们需要使用过滤器或者拦截器,在过滤器或者拦截器中判断用户是否已经完成登录,如果没有登录则跳转到登录页面。
代码实现实现步骤:
-
创建自定义过滤器LoginCheckFilter
@WebFilter(filterName = "loginCheckFilter",urlPatterns = " public boolean check(String[] urls,String requestURI){ for (String url : urls) { boolean match = PATH_MATCHER.match(url, requestURI); if(match){ return true; } } return false; } -
如果不需要处理,则直接放行
-
判断登录状态,如果已登录,则直接放行
-
如果未登录则返回未登录结果
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();
log.info("拦截到请求: {}",requestURI);
//定义不需要处理的请求路径
String[] urls = new String[]{
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**"
};
//2.判断本次请求是否需要处理
boolean check = check(urls, requestURI);
//3.如果不需要处理,则直接放行
if(check){
log.info("本次请求 {} 不需要处理",requestURI);
filterChain.doFilter(request,response);
return;
}
//4.判断登录状态,如果已登录,则直接放行
if (request.getSession().getAttribute("employee")!=null){
log.info("用户已登录,用户id为:{}",request.getSession().getAttribute("employee"));
filterChain.doFilter(request,response);
return;
}
log.info("用户未登录");
//5.如果未登录则返回未登录结果,通过输出流的方式向客户端响应数据
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
}



