在这里插入图片描述

//自定义拦截器
@Component
public class LoginCheckInterceptor implements HandlerInterceptor {
//目标资源方法执行前执行。 返回true:放行 返回false:不放行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle … ");

    return true; //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 .... ");
}

}

注意:

​ preHandle方法:目标资源方法执行前执行。 返回true:放行 返回false:不放行

​ postHandle方法:目标资源方法执行后执行

​ afterCompletion方法:视图渲染完毕后执行,最后执行

注册配置拦截器:实现WebMvcConfigurer接口,并重写addInterceptors方法

@Configuration
public class WebConfig implements WebMvcConfigurer {

//自定义的拦截器对象
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;


@Override
public void addInterceptors(InterceptorRegistry registry) {
   //注册自定义拦截器对象
    registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**");//设置拦截器拦截的请求路径( /** 表示拦截所有请求)
}

}

2.5.2 Interceptor详解
2.5.2.1 拦截路径

在注册配置拦截器的时候,我们要指定拦截器的拦截路径,通过addPathPatterns("要拦截路径")方法,就可以指定要拦截哪些资源。

在入门程序中配置的是/**,表示拦截所有资源,而在配置拦截器时,不仅可以指定要拦截哪些资源,还可以指定不拦截哪些资源,只需要调用excludePathPatterns("不拦截路径")方法,指定哪些资源不需要拦截。

@Configuration
public class WebConfig implements WebMvcConfigurer {
//拦截器对象
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//注册自定义拦截器对象
registry.addInterceptor(loginCheckInterceptor)
.addPathPatterns(“/")//设置拦截器拦截的请求路径( / 表示拦截所有请求)
.excludePathPatterns(”/login");//设置不拦截的请求路径
}
}

在这里插入图片描述
/**/*的区别:

  • 修改拦截器配置,把拦截路径设置为/*
    @Configuration
    public class WebConfig implements WebMvcConfigurer {

    //拦截器对象
    @Autowired
    private LoginCheckInterceptor loginCheckInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    //注册自定义拦截器对象
    registry.addInterceptor(loginCheckInterceptor)
    .addPathPatterns(“/*”)
    .excludePathPatterns(“/login”);//设置不拦截的请求路径
    }
    }
    在这里插入图片描述

@Configuration
public class WebConfig implements WebMvcConfigurer {

//拦截器对象
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {
   //注册自定义拦截器对象
    registry.addInterceptor(loginCheckInterceptor)
            .addPathPatterns("/*")
            .excludePathPatterns("/login");//设置不拦截的请求路径
}

}

在这里插入图片描述

  • 当我们打开浏览器来访问部署在web服务器当中的web应用时,此时我们所定义的过滤器会拦截到这次请求。拦截到这次请求之后,它会先执行放行前的逻辑,然后再执行放行操作。而由于我们当前是基于springboot开发的,所以放行之后是进入到了spring的环境当中,也就是要来访问我们所定义的controller当中的接口方法。

  • Tomcat并不识别所编写的Controller程序,但是它识别Servlet程序,所以在Spring的Web环境中提供了一个非常核心的Servlet:DispatcherServlet(前端控制器),所有请求都会先进行到DispatcherServlet,再将请求转给Controller。

  • 当我们定义了拦截器后,会在执行Controller的方法之前,请求被拦截器拦截住。执行preHandle()方法,这个方法执行完成后需要返回一个布尔类型的值,如果返回true,就表示放行本次操作,才会继续访问controller中的方法;如果返回false,则不会放行(controller中的方法也不会执行)。

  • 在controller当中的方法执行完毕之后,再回过来执行postHandle()这个方法以及afterCompletion() 方法,然后再返回给DispatcherServlet,最终再来执行过滤器当中放行后的这一部分逻辑的逻辑。执行完毕之后,最终给浏览器响应数据。

过滤器和拦截器同时存在的执行流程:

  • 开启LoginCheckInterceptor拦截器
    @Component
    public class LoginCheckInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    System.out.println("preHandle … ");

      return true; //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 … ");
    }
    }

@Configuration
public class WebConfig implements WebMvcConfigurer {

//拦截器对象
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {
    //注册自定义拦截器对象
    registry.addInterceptor(loginCheckInterceptor)
            .addPathPatterns("/**")//拦截所有请求
            .excludePathPatterns("/login");//不拦截登录请求
}

}
开启DemoFilter过滤器
@WebFilter(urlPatterns = “/*”)
public class DemoFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println(“DemoFilter 放行前逻辑…”);

    //放行请求
    filterChain.doFilter(servletRequest,servletResponse);

    System.out.println("DemoFilter   放行后逻辑.....");
}

}
登录校验- Interceptor
//自定义拦截器
@Component //当前拦截器对象由Spring创建和管理
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {
//前置方式
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle … ");
//1.获取请求url
//2.判断请求url中是否包含login,如果包含,说明是登录操作,放行

    //3.获取请求头中的令牌(token)
    String token = request.getHeader("token");
    log.info("从请求头中获取的令牌:{}",token);

    //4.判断令牌是否存在,如果不存在,返回错误结果(未登录)
    if(!StringUtils.hasLength(token)){
        log.info("Token不存在");

        //创建响应结果对象
        Result responseResult = Result.error("NOT_LOGIN");
        //把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)
        String json = JSONObject.toJSONString(responseResult);
        //设置响应头(告知浏览器:响应的数据类型为json、响应的数据编码表为utf-8)
        response.setContentType("application/json;charset=utf-8");
        //响应
        response.getWriter().write(json);

        return false;//不放行
    }

    //5.解析token,如果解析失败,返回错误结果(未登录)
    try {
        JwtUtils.parseJWT(token);
    }catch (Exception e){
        log.info("令牌解析失败!");

        //创建响应结果对象
        Result responseResult = Result.error("NOT_LOGIN");
        //把Result对象转换为JSON格式字符串 (fastjson是阿里巴巴提供的用于实现对象和json的转换工具类)
        String json = JSONObject.toJSONString(responseResult);
        //设置响应头
        response.setContentType("application/json;charset=utf-8");
        //响应
        response.getWriter().write(json);

        return false;
    }

    //6.放行
    return true;
}
**注册配置拦截器**
@Configuration  

public class WebConfig implements WebMvcConfigurer {
//拦截器对象
@Autowired
private LoginCheckInterceptor loginCheckInterceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {
   //注册自定义拦截器对象
    registry.addInterceptor(loginCheckInterceptor)
            .addPathPatterns("/**")
            .excludePathPatterns("/login");
}

}

全局异常处理器

  • 定义全局异常处理器非常简单,就是定义一个类,在类上加上一个注解@RestControllerAdvice,加上这个注解就代表我们定义了一个全局异常处理器。
  • 在全局异常处理器当中,需要定义一个方法来捕获异常,在这个方法上需要加上注解@ExceptionHandler。通过@ExceptionHandler注解当中的value属性来指定我们要捕获的是哪一类型的异常。
@RestControllerAdvice
public class GlobalExceptionHandler {

    //处理异常
    @ExceptionHandler(Exception.class) //指定能够处理的异常类型
    public Result ex(Exception e){
        e.printStackTrace();//打印堆栈中的异常信息

        //捕获到异常之后,响应一个标准的Result
        return Result.error("对不起,操作失败,请联系管理员");
    }
}

此时,我们可以看到,出现异常之后,异常已经被全局异常处理器捕获了。然后返回的错误信息,被前端程序正常解析,然后提示出了对应的错误提示信息。

以上就是全局异常处理器的使用,主要涉及到两个注解:

  • @RestControllerAdvice //表示当前类为全局异常处理器
  • @ExceptionHandler //指定可以捕获哪种类型的异常进行处理
Logo

苏州本地的技术开发者社区,在这里可以交流本地的好吃好玩的,可以交流技术,可以交流招聘等等,没啥限制。

更多推荐