Bootstrap

过滤器拦截器与异常捕获

通过上文开发,系统已经能够进行初步的使用,但是需要进一步完善功能,

本篇介绍拦截器与过滤器还有关于异常的捕获的知识笔记

        下面开始        


过滤器Filter

  • 入门程序

    • 定义Filter类,实现Filter接口,并重写其所有方法

    • package com.testpeople.filter;
      
      import javax.servlet.*;
      import javax.servlet.annotation.WebFilter;
      import java.io.IOException;
      
      @WebFilter(urlPatterns = "/*")//拦截所有请求
      public class demoFilter implements Filter {
      
          //初始化方法,调用一次
          @Override
          public void init(FilterConfig filterConfig) throws ServletException {
              System.out.printf("初始化方法被调用");
          }
          //销毁方法,调用一次
          @Override
          public void destroy() {
              Filter.super.destroy();
              System.out.println("销毁方法被调用");
          }
      
          //过滤方法,调用多次
          @Override
          public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
              System.out.printf("拦截了请求");
      
              filterChain.doFilter(servletRequest,servletResponse);//放行操作
      
          }
      }
    • 配置Filter类加上@WebFilter注解,配置拦截资源路径。引导类上加@ServeltComponentScan开启servlet组件支持。

    • 效果
    •   
    •  未拦截
    • 详解

      • 执行流程

        • 放行后访问对应资源,资源访问完会回到过滤器中。

        • 回到过滤器中,会执行放行后的逻辑。

      • 拦截路径

  •  过滤器链
  • 登录校验

    • 设计思路

  • 开发

  • package com.testpeople.filter;
    
    import com.alibaba.fastjson.JSONObject;
    import com.testpeople.pojo.Result;
    import com.testpeople.utils.JwtUtils;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.util.StringUtils;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    @Slf4j
    @WebFilter(urlPatterns = "/*")
    public class LoginFilter implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            Filter.super.init(filterConfig);
        }
    
        @Override
        public void destroy() {
            Filter.super.destroy();
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
            //强制类型转换请求和响应、
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
    
            //1.获取请求url
    
            String url = request.getRequestURI();
            log.info("请求的url:{}",url);
            //2.判断是否是登录操作
    
            if (url.contains("login")){
                log.info("此请求为登录,放行");
                filterChain.doFilter(request,response);
                return;
            }
    
            //3.获取请求头中的token
            String twj = request.getHeader("token");
    
            //4.判断令牌是否存在,若不存在,返回错误(未登录)
    
            if (!StringUtils.hasLength(twj)){
                log.info("请求头中token为空,返回错误(未登录)");
                Result error = Result.error("NOT_LOGIN");
                //手动转换将对象转换成json————————阿里巴巴工具包fastjson
                String notLogin = JSONObject.toJSONString(error);
                response.getWriter().write(notLogin);
                return;
            }
    
    
            //5.解析令牌,若解析失败,返回错误(未登录)
    
            try {
                JwtUtils.parseJwt(twj);
            } catch (Exception e) {//解析失败
                e.printStackTrace();
                log.info("令牌解析失败,返回错误(未登录)");
                Result error = Result.error("NOT_LOGIN");
                //手动转换将对象转换成json————————阿里巴巴工具包fastjson
                String notLogin = JSONObject.toJSONString(error);
                response.getWriter().write(notLogin);
                return;
            }
    
            //6.放行
            log.info("令牌合法,放行");
            filterChain.doFilter(request,response);
    
    
        }
    }
  • 测试

    • Postman

 拦截器interceptor

  • 简介

  • 入门程序

    • 定义拦截器,实现HandlerInterceptor接口,并重写其所有方法。(类)

    • 注册拦截器(类)

    • //用于定义拦截器,实现拦截功能
      
      package com.testpeople.interceptor;
      
      import org.springframework.stereotype.Component;
      import org.springframework.web.servlet.HandlerInterceptor;
      import org.springframework.web.servlet.ModelAndView;
      
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      
      @Component
      public class LoginCheckInterceptor implements HandlerInterceptor {
      
      
          @Override//目标方法资源运行前运行,返回值为true表示放行,false表示拦截
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 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");
          }
      
      
      }
      //用于注册拦截器,实现拦截的路径。
      package com.testpeople.config;
      
      import com.testpeople.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("/**");
          }
      }
    • 测试

      • 不放行

  • 放行

  • 详解

    • 拦截路径

@Override //注册拦截器
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
}
//addPathPatterns表示拦截什么,excludePatterns表示不拦截什么
//"/**"与"/*"的区别
  • 执行流程

  • 登录校验

    • 思路

  • 开发

  • package com.testpeople.interceptor;
    
    import com.alibaba.fastjson.JSONObject;
    import com.testpeople.pojo.Result;
    import com.testpeople.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 javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @Slf4j
    @Component
    public class LoginCheckInterceptor implements HandlerInterceptor {
    
    
        @Override//目标方法资源运行前运行,返回值为true表示放行,false表示拦截
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle");
    
            //1.获取请求url
    
            String url = request.getRequestURI();
            log.info("interceptor_请求的url:{}",url);
            //2.判断是否是登录操作
    //          前面已经排除/login了
    //        if (url.contains("login")){
    //            log.info("interceptor_此请求为登录,放行");
    //            return true;
    //        }
    
            //3.获取请求头中的token
            String twj = request.getHeader("token");
    
            //4.判断令牌是否存在,若不存在,返回错误(未登录)
    
            if (!StringUtils.hasLength(twj)){
                log.info("interceptor_请求头中token为空,返回错误(未登录)");
                Result error = Result.error("NOT_LOGIN");
                //手动转换将对象转换成json————————阿里巴巴工具包fastjson
                String notLogin = JSONObject.toJSONString(error);
                response.getWriter().write(notLogin);
                return false;
            }
    
    
            //5.解析令牌,若解析失败,返回错误(未登录)
    
            try {
                JwtUtils.parseJwt(twj);
            } catch (Exception e) {//解析失败
                e.printStackTrace();
                log.info("令牌解析失败,返回错误(未登录)");
                Result error = Result.error("NOT_LOGIN");
                //手动转换将对象转换成json————————阿里巴巴工具包fastjson
                String notLogin = JSONObject.toJSONString(error);
                response.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");
        }
    
    
    }
    
  • 测试

    • Postman

  • 后端显示正常

    • 登录功能没有被拦截,其他功能没有正确的token被拦截。

区别

异常处理

方案
  • 在所有的Controller中加入try..catch(不推荐)

  • 设置全局异常处理器(推荐)

  • package com.testpeople.exception;
    
    import com.testpeople.pojo.Result;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    
    /**
     * 全局异常处理类
     */
    @Slf4j
    @RestControllerAdvice
    public class GloablExceptionHandler {
    
        //捕获异常并返回
        @ExceptionHandler(Exception.class)//捕获所有异常(类型)
        public Result handleException(Exception e) {//捕获异常
            log.info("捕获异常:{}", e.getMessage());
            e.printStackTrace();//堆栈信息
            return Result.error("出现错误,请联系管理员");
        }
    
    
    }
  • 测试


拦截器和过滤器介绍完毕,也简单实现了异常的拦截

以上只是来自黑马程序员的课程,笔记为小编学习的笔记

项目地址

黑马程序员项目

;