[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)

目录

一、登录功能

1.1 思路

1.2 LoginController

1.3 EmpService

1.4 EmpServiceImpl

1.5 EmpMapper

1.6 启动服务-测试

1.7 前后端联调

二、登录校验(重点)

2.1 问题

 2.2 问题分析

 2.3 登录校验​编辑

2.4 会话技术

2.4.1 会话技术

 2.4.2 会话跟踪方案对比

2.5 JWT令牌

2.5.1 简介

2.5.2 应用场景 

2.5.3 jwt-生成 

5.5.3.1 引入包

5.5.3.2 生成JWT

 5.5.3.3 解析JWT

2.6 案例实现JWT

 2.6.1 新建JwtUtils工具类

2.6.2 LoginController

2.6.3 启动服务-测试 

2.6.4 前后端联调

2.7 过滤器Filter

2.7.1 概述

2.7.2 快速入门

 2.7.2.1 新增DemoFilter

 2.7.2.2 SpringBootProjectTestApplication

2.7.2.3 启动服务-测试

2.7.2.4 总结

2.7.3 详解(执行流程、拦截路径、过滤器链)

2.7.3.1 执行流程

 2.7.3.2 Filter-拦截路径 ​编辑

2.7.3.3 过滤器链(优先级按过滤器名自然排序)

 2.7.3.4 总结

2.7.4 案例-登录校验-Filter

2.7.4.1 思路

 2.7.4.2 pom.xml引入依赖fastjson

2.7.4.3 新建工具类拦截器LoginCheckFilter 

 2.7.4.4 启动服务-测试

2.8 拦截器Interceptor

2.8.1 简介

2.8.2 快速入门

2.8.2.1 新建LoginCheckInterceptor

 2.8.2.2 WebConfig

2.8.2.3 启动服务测试

2.8.3 详解

2.8.3.1 拦截路径

2.8.3.2  拦截器- 执行流程

2.8.4 案例-登录校验-Interceptor

2.8.4.1 LoginCheckInterceptor

2.8.4.2 WebConfig

2.8.4.3 启动服务-测试

三、异常处理

3.1 异常现象--新增重复名称部门

3.2 思考如何处理

 3.3 全家异常处理

 3.3.1 异常类GlobalExceptionHandler 

3.3.2 启动服务-测试

 3.3.3 总结


前言:实现案例的登录功能、登录校验和异常处理

一、登录功能

1.1 思路

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第1张图片

 [JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第2张图片

 

1.2 LoginController

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第3张图片

 

package com.runa.controller;

import com.runa.pojo.Emp;
import com.runa.pojo.Result;
import com.runa.service.EmpService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
public class LoginController {

    @Autowired
    private EmpService empService;
    @PostMapping("/login")
    public Result login(@RequestBody Emp emp){
        log.info("登录的用户:{}",emp);
        Emp e = empService.login(emp);
        return e != null ? Result.success():Result.error("用户名或密码错误");

    }
}

1.3 EmpService

package com.runa.service;

import com.runa.pojo.Emp;
import com.runa.pojo.PageBean;
import org.springframework.format.annotation.DateTimeFormat;

import java.time.LocalDate;
import java.util.List;

public interface EmpService {



    /**
     * 分页查询  不带条件
     * @param page
     * @param pageSize
     * @return
     */
//    PageBean page(Integer page, Integer pageSize);

    /**
     * 分页查询 带条件
     * @param page
     * @param pageSize
     * @return
     */
    PageBean page(Integer page, Integer pageSize,String name, Short gender, LocalDate begin, LocalDate end);

    /**
     * 批量删除员工
     * @param ids
     */
    void delete(List ids);

    /**
     * 新增员工
     * @param emp
     */
    void save(Emp emp);

    /**
     * 根据id查询员工
     * @param id
     * @return
     */
    Emp getById(Integer id);

    /**
     * 修改员工
     * @param emp
     */
    void update(Emp emp);

    /**
     * 登录
     * @param emp
     * @return
     */
    Emp login(Emp emp);
}

1.4 EmpServiceImpl

package com.runa.service.impl;



import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.runa.mapper.EmpMapper;
import com.runa.pojo.Emp;
import com.runa.pojo.PageBean;
import com.runa.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

@Service
public class EmpServiceImpl implements EmpService {

    @Autowired
    private EmpMapper empMapper;

    /**
     * 分页查询 pagehelper+组合查询
     * @param page
     * @param pageSize
     * @param name
     * @param gender
     * @param begin
     * @param end
     * @return
     */
    @Override
    public PageBean page(Integer page, Integer pageSize, String name, Short gender, LocalDate begin, LocalDate end) {
        // 1 设置分页参数
        PageHelper.startPage(page, pageSize);

        // 2 执行查询
        List empList = empMapper.list(name, gender, begin, end);
        Page p = (Page) empList;

        // 3 封装PangeBean对象
        PageBean pageBean = new PageBean(p.getTotal(),((Page) empList).getResult());
        return pageBean;
    }

    /**
     * 批量删除员工
     * @param ids
     */
    @Override
    public void delete(List ids) {
        empMapper.delete(ids);

    }

    /**
     * 新增员工
     * @param emp
     */
    @Override
    public void save(Emp emp) {
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());
        empMapper.insert(emp);

    }

    /**
     * 根据ID查询员工
     * @param id
     * @return
     */
    @Override
    public Emp getById(Integer id) {

        return empMapper.getByID(id);
    }

    /**
     * 修改员工
     * @param emp
     */
    @Override
    public void update(Emp emp) {
        emp.setUpdateTime(LocalDateTime.now());
        empMapper.update(emp);

    }

    /**
     * 登录
     * @param emp
     * @return
     */
    @Override
    public Emp login(Emp emp) {

        return empMapper.getByUsernameAndPassword(emp);
    }


    /**
     * 分页查询  加pagehelper
     * @param page
     * @param pageSize
     * @return
     */
//    @Override
//    public PageBean page(Integer page, Integer pageSize) {
//        // 1 设置分页参数
//        PageHelper.startPage(page, pageSize);
//
//        // 2 执行查询
//        List empList = empMapper.list();
//        Page p = (Page) empList;
//
//        // 3 封装PangeBean对象
//        PageBean pageBean = new PageBean(p.getTotal(),((Page) empList).getResult());
//        return pageBean;
//    }

    /**
     * 分页查询
     * @param page
     * @param pageSize
     * @return
     */
//    @Override
//    public PageBean page(Integer page, Integer pageSize) {
//        // 1 获取总记录数
//        Long count = empMapper.count();
//
//        // 2 获取分页查询结果列表
//        Integer start = (page - 1) * pageSize;
//        List empList = empMapper.page(start, pageSize);
//
//        // 3 封装PangeBean对象
//        PageBean pageBean = new PageBean(count,empList);
//    }


}

1.5 EmpMapper

package com.runa.mapper;

import com.runa.pojo.Emp;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.time.LocalDate;
import java.util.List;

/**
 * 员工管理
 */
@Mapper
public interface EmpMapper {


    /**
     * 查询总记录数
     * @return
     */
//    @Select("select count(*) from emp")
//    public Long count();

    /**
     * 分页查询 获取列表数据
     * @param start
     * @param pageSize
     * @return
     */
//    @Select("select * from emp limit #{start}, #{pageSize}")
//    public List page(Integer start, Integer pageSize);
    /**
     * 使用pagehelper的员工信息查询
     * @return
     */
//    @Select("select * from emp")
//    public List list();

    /**
     * 使用pagehelper的员工信息查询(带条件)--动态sql
     * 使用xml注解sql
     * @return
     */

    public List list(String name, Short gender, LocalDate begin, LocalDate end);

    /**
     * 批量删除员工
     * @param ids
     */
    void delete(List ids);

    /**
     * 新增员工
     * @param emp
     */
    @Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)" +
            " values(#{username}, #{name}, #{gender}, #{image}, #{job}, #{entrydate}, #{deptId}, #{createTime}, #{updateTime})")
    void insert(Emp emp);

    /**
     * 根据id查询员工
     * @param id
     * @return
     */
    @Select("select * from emp where id = #{id}")
    Emp getByID(Integer id);

    /**
     * 修改员工
     * @param emp
     */
    void update(Emp emp);



    /**
     * 登录
     * @param emp
     * @return
     */
    @Select("select * from emp where username = #{username} and password = #{password}")
    Emp getByUsernameAndPassword(Emp emp);
}

1.6 启动服务-测试

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第4张图片

 

1.7 前后端联调

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第5张图片

 

二、登录校验(重点)

2.1 问题

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第6张图片

 2.2 问题分析

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第7张图片

 2.3 登录校验[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第8张图片

2.4 会话技术

2.4.1 会话技术

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第9张图片

 2.4.2 会话跟踪方案对比

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第10张图片

 Cookies与Session例子,启动服务http://localhost:8080/c1 

  [JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第11张图片

 

package com.runa.controller;

import com.runa.pojo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;

/**
 * HttpSession演示
 */
@Slf4j
@RestController
public class SessionController {

    //设置Cookie
    @GetMapping("/c1")
    public Result cookie1(HttpServletResponse response){
        response.addCookie(new Cookie("login_username","itheima")); //设置Cookie/响应Cookie
        return Result.success();
    }

    //获取Cookie
    @GetMapping("/c2")
    public Result cookie2(HttpServletRequest request){
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            if(cookie.getName().equals("login_username")){
                System.out.println("login_username: "+cookie.getValue()); //输出name为login_username的cookie
            }
        }
        return Result.success();
    }



    @GetMapping("/s1")
    public Result session1(HttpSession session){
        log.info("HttpSession-s1: {}", session.hashCode());

        session.setAttribute("loginUser", "tom"); //往session中存储数据
        return Result.success();
    }

    @GetMapping("/s2")
    public Result session2(HttpServletRequest request){
        HttpSession session = request.getSession();
        log.info("HttpSession-s2: {}", session.hashCode());

        Object loginUser = session.getAttribute("loginUser"); //从session中获取数据
        log.info("loginUser: {}", loginUser);
        return Result.success(loginUser);
    }
}

2.5 JWT令牌

2.5.1 简介

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第12张图片

2.5.2 应用场景 

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第13张图片

2.5.3 jwt-生成 

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第14张图片

 [JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第15张图片

 

5.5.3.1 引入包

        
        
            io.jsonwebtoken
            jjwt
            0.9.1
        

5.5.3.2 生成JWT

 [JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第16张图片

 记得注释他//@SpringBootTest

package com.runa;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

//@SpringBootTest
class SpringBootProjectTestApplicationTests {

//    @Test
//    void contextLoads() {
//    }

    /**
     * 测试JWT令牌的生成
     */
    @Test
    public void testGenJwt(){
        Map claims = new HashMap<>();
        claims.put("id",1);
        claims.put("name","bocai");
        String jwt = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, "runa") // 签名算法 算法有哪些上官网
                .setClaims(claims) //自定义的内容(载荷)
                .setExpiration(new Date(System.currentTimeMillis() + 3600* 1000)) // 设置有效期为1h
                .compact();
        System.out.println(jwt);

    }

}

 

 生成的jwt令牌上官网

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第17张图片

 5.5.3.3 解析JWT

package com.runa;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

//@SpringBootTest
class SpringBootProjectTestApplicationTests {

//    @Test
//    void contextLoads() {
//    }

    /**
     * 生成Jwt令牌
     */
    @Test
    public void testGenJwt(){
        Map claims = new HashMap<>();
        claims.put("id",1);
        claims.put("name","bocai");
        String jwt = Jwts.builder()
                .signWith(SignatureAlgorithm.HS256, "runa") // 签名算法 算法有哪些上官网
                .setClaims(claims) //自定义的内容(载荷)
                .setExpiration(new Date(System.currentTimeMillis() + 3600* 1000)) // 设置有效期为1h
                .compact();
        System.out.println(jwt);

    }

    /**
     * 解析Jwt
     */
    @Test
    public void testPareJwt(){
        Claims claims = Jwts.parser()
                .setSigningKey("runa") //runa要与前面生成一致
                .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiYm9jYWkiLCJpZCI6MSwiZXhwIjoxNjkyNzc3MzAwfQ.KPqgKc5JS8j7GN7aPQ0GwQnUaGm78WWbzf2N7LGq34g")
                .getBody();
        System.out.println(claims);

    }

}

2.6 案例实现JWT

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第18张图片

 [JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第19张图片

 [JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第20张图片

 

 2.6.1 新建JwtUtils工具类

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第21张图片

 

 

package com.runa.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;

public class JwtUtils {

    private static String signKey = "runa";
    private static Long expire = 43200000L;  // 12h

    /**
     * 生成JWT令牌
     * @param claims JWT第二部分负载 payload 中存储的内容
     * @return
     */
    public static String generateJwt(Map claims){
        String jwt = Jwts.builder()
                .addClaims(claims)
                .signWith(SignatureAlgorithm.HS256, signKey)
                .setExpiration(new Date(System.currentTimeMillis() + expire))
                .compact();
        return jwt;
    }

    /**
     * 解析JWT令牌
     * @param jwt JWT令牌
     * @return JWT第二部分负载 payload 中存储的内容
     */
    public static Claims parseJWT(String jwt){
        Claims claims = Jwts.parser()
                .setSigningKey(signKey)
                .parseClaimsJws(jwt)
                .getBody();
        return claims;
    }
}

 

2.6.2 LoginController

package com.runa.controller;

import com.runa.pojo.Emp;
import com.runa.pojo.Result;
import com.runa.service.EmpService;
import com.runa.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@Slf4j
@RestController
public class LoginController {

    @Autowired
    private EmpService empService;
    @PostMapping("/login")
    public Result login(@RequestBody Emp emp){
        log.info("登录的用户:{}",emp);
        Emp e = empService.login(emp);

        // 登录成功,生成令牌,下发令牌
        if(e != null){
            Map claims = new HashMap<>();
            claims.put("id",e.getId());
            claims.put("name", e.getName());
            claims.put("username", e.getUsername());

            String jwt = JwtUtils.generateJwt(claims);
            return Result.success(jwt);
        }
        // 登录失败,返回错误信息

        return Result.error("用户名或密码错误");

    }
}

2.6.3 启动服务-测试 

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第22张图片

2.6.4 前后端联调

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第23张图片 

 [JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第24张图片

 

2.7 过滤器Filter

2.7.1 概述

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第25张图片

2.7.2 快速入门

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第26张图片

 2.7.2.1 新增DemoFilter

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第27张图片

 

package com.runa.filter;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;

import java.io.IOException;

@WebFilter(urlPatterns = "/*")
public class DemoFilter implements Filter {
    @Override  // 初始化方法,只调用一次
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init初始化方法执行了");
    }

    @Override // 拦截到请求之后调用,调用多次
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("拦截到请求了~~~");
        // 放行
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override // 销毁方法,只调用一次
    public void destroy() {
        System.out.println("destroy方法执行了");
    }
}

 2.7.2.2 SpringBootProjectTestApplication

package com.runa;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@ServletComponentScan  //开启了对servlet组件支持
@SpringBootApplication
public class SpringBootProjectTestApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootProjectTestApplication.class, args);
    }

}

2.7.2.3 启动服务-测试

2.7.2.4 总结

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第28张图片

 

   

2.7.3 详解(执行流程、拦截路径、过滤器链)

2.7.3.1 执行流程

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第29张图片

 

 2.7.3.2 Filter-拦截路径 [JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第30张图片

2.7.3.3 过滤器链(优先级按过滤器名自然排序)

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第31张图片

 

 

 [JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第32张图片

package com.runa.filter;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;

import java.io.IOException;

@WebFilter(urlPatterns = "/*")
public class SecondFilter implements Filter {

    @Override // 拦截到请求之后调用,调用多次
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("SecondFilter 拦截---2到请求了~~~放行之前逻辑");
        // 放行
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("SecondFilter拦截---2到请求了~~~放行之后逻辑");
    }
}

 2.7.3.4 总结

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第33张图片

 

2.7.4 案例-登录校验-Filter

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第34张图片

 

2.7.4.1 思路

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第35张图片

 2.7.4.2 pom.xml引入依赖fastjson

        
        
            com.alibaba
            fastjson
            1.2.76
        

2.7.4.3 新建工具类拦截器LoginCheckFilter 

package com.runa.filter;

import com.alibaba.fastjson.JSONObject;
import com.runa.pojo.Result;
import com.runa.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;

@Slf4j
//@WebFilter(urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;

        //1.获取请求url。
        String url = req.getRequestURL().toString();
        log.info("请求的url: {}",url);

        //2.判断请求url中是否包含login,如果包含,说明是登录操作,放行。
        if(url.contains("login")){
            log.info("登录操作, 放行...");
            chain.doFilter(request,response);
            return;
        }

        //3.获取请求头中的令牌(token)。
        String jwt = req.getHeader("token");

        //4.判断令牌是否存在,如果不存在,返回错误结果(未登录)。
        if(!StringUtils.hasLength(jwt)){
            log.info("请求头token为空,返回未登录的信息");
            Result error = Result.error("NOT_LOGIN");
            //手动转换 对象--json --------> 阿里巴巴fastJSON
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);
            return;
        }

        //5.解析token,如果解析失败,返回错误结果(未登录)。
        try {
            JwtUtils.parseJWT(jwt);
        } catch (Exception e) {//jwt解析失败
            e.printStackTrace();
            log.info("解析令牌失败, 返回未登录错误信息");
            Result error = Result.error("NOT_LOGIN");
            //手动转换 对象--json --------> 阿里巴巴fastJSON
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);
            return;
        }

        //6.放行。
        log.info("令牌合法, 放行");
        chain.doFilter(request, response);

    }
}

 2.7.4.4 启动服务-测试

记得将 DemoFilter 与SecondFilter 的@WebFilter(urlPatterns = "/*") 注释掉

 [JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第36张图片

 [JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第37张图片

 

2.8 拦截器Interceptor

2.8.1 简介

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第38张图片

 

2.8.2 快速入门

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第39张图片

2.8.2.1 新建LoginCheckInterceptor

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第40张图片

 

package com.runa.interceptor;


import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;


@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
    @Override //目标资源方法运行前运行, 返回true: 放行, 放回false, 不放行
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
        System.out.println("preHandle ...");
        return true;
    }

    @Override //目标资源方法运行后运行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle ...");
    }

    @Override //视图渲染完毕后运行, 最后运行
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion...");
    }
}

 2.8.2.2 WebConfig

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第41张图片

 

package com.runa.config;

import com.runa.interceptor.LoginCheckInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration //配置类
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoginCheckInterceptor loginCheckInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");
    }
}

2.8.2.3 启动服务测试

 将过滤器 LoginCheckFilter @WebFilter(urlPatterns = "/*") 注释掉

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第42张图片

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第43张图片 

 

2.8.3 详解

2.8.3.1 拦截路径

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第44张图片

 

2.8.3.2  拦截器- 执行流程

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第45张图片

 

2.8.4 案例-登录校验-Interceptor

2.8.4.1 LoginCheckInterceptor

package com.runa.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.runa.pojo.Result;
import com.runa.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@Slf4j
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
    @Override //目标资源方法运行前运行, 返回true: 放行, 放回false, 不放行
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
        //1.获取请求url。
        String url = req.getRequestURL().toString();
        log.info("请求的url: {}",url);

        //2.判断请求url中是否包含login,如果包含,说明是登录操作,放行。
        if(url.contains("login")){
            log.info("登录操作, 放行...");
            return true;
        }

        //3.获取请求头中的令牌(token)。
        String jwt = req.getHeader("token");

        //4.判断令牌是否存在,如果不存在,返回错误结果(未登录)。
        if(!StringUtils.hasLength(jwt)){
            log.info("请求头token为空,返回未登录的信息");
            Result error = Result.error("NOT_LOGIN");
            //手动转换 对象--json --------> 阿里巴巴fastJSON
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);
            return false;
        }

        //5.解析token,如果解析失败,返回错误结果(未登录)。
        try {
            JwtUtils.parseJWT(jwt);
        } catch (Exception e) {//jwt解析失败
            e.printStackTrace();
            log.info("解析令牌失败, 返回未登录错误信息");
            Result error = Result.error("NOT_LOGIN");
            //手动转换 对象--json --------> 阿里巴巴fastJSON
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);
            return false;
        }

        //6.放行。
        log.info("令牌合法, 放行");
        return true;
    }

    @Override //目标资源方法运行后运行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle ...");
    }

    @Override //视图渲染完毕后运行, 最后运行
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion...");
    }
}

2.8.4.2 WebConfig

package com.runa.config;

import com.runa.interceptor.LoginCheckInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration //配置类
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoginCheckInterceptor loginCheckInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
    }
}

2.8.4.3 启动服务-测试

注释Filter

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第46张图片 

 

三、异常处理

3.1 异常现象--新增重复名称部门

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第47张图片

 

 [JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第48张图片

 [JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第49张图片

3.2 思考如何处理

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第50张图片

 3.3 全家异常处理

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第51张图片

 3.3.1 异常类GlobalExceptionHandler 

 [JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第52张图片

 

package com.runa.exception;

import com.runa.pojo.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全局异常处理器
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)//捕获所有异常
    public Result ex(Exception ex){
        ex.printStackTrace();
        return Result.error("对不起,操作失败,请联系管理员");
    }

}

3.3.2 启动服务-测试

新建重复部门

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第53张图片

 3.3.3 总结

[JavaWeb]【十一】web后端开发-SpringBootWeb案例(登录)_第54张图片

 

你可能感兴趣的:(java,前端,java,servlet)