java 拦截器&过滤器


 


@Pointcut("execution(* com.jbs.oms.aggreg.web.controller.*.*.*(..))")
private void excudeController() {
}

@Before("excudeController()")
public void before(JoinPoint joinPoint) {
  //通过joinPoint可以获取request相关参数:
  Object[] args = joinPoint.getArgs();
  
  //获取当前方法对象:
Signature signature = (MethodSignature)point.getSignature();
  Method method = signature.getMethod();
 
  //获取当前类:
  joinPoint.getTarget().getClass();
  
}



拦截机制中Aspect、ControllerAdvice、Interceptor、Fliter之间的区别详解

 在项目的开发中,在某些情况下,我们需要对客户端发出的请求进行拦截,常用的API拦截方式有Fliter,Interceptor,ControllerAdvice以及Aspect。

 

 

上图是spring中的拦截机制,如果出现异常的话,异常的顺序是从里面到外面一步一步的进行处理,如果到了最外层都没有进行处理的话,就会由tomcat容器抛出异常。下面我将详细的解释这四个拦截方式的不同。因为只是演示就不是所有的使用了日志记录。这里相关的依赖自己可以去https://mvnrepository.com/下载,我就不一一添加了

先做一个总的总结吧

1.过滤器:Filter   

Filter有如下几个种类。

  • 用户授权的Filter:Filter负责检查用户请求,根据请求过滤用户非法请求。
  • 日志Filter:详细记录某些特殊的用户请求。
  • 负责解码的Filter:包括对非标准编码的请求解码。
  • 能改变XML内容的XSLT Filter等。
  • Filter可以负责拦截多个请求或响应;一个请求或响应也可以被多个Filter拦截。

  可以获得Http原始的请求和响应信息,但是拿不到响应方法的信息

@WebFilter(filterName = "FilterDemo01", urlPatterns = { "/*" })
public class FilterDemo01 implements Filter {
  @Override
  public void init(FilterConfig filterConfig) throws ServletException {
    System.out.println("----FilterDemo01过滤器初始化----");
  }
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    // 对request和response进行一些预处理
    request.setCharacterEncoding("UTF-8");
    response.setCharacterEncoding("UTF-8");
    response.setContentType("text/html;charset=UTF-8");
    System.out.println("FilterDemo01执行前!!!");
    chain.doFilter(request, response);
    // 让目标资源执行,放行
    System.out.println("FilterDemo01执行后!!!");
  }

  @Override
  public void destroy() {
    System.out.println("----过滤器销毁----");
  } 
}

=========================================================

2.拦截器:Interceptor

  :可以获得Http原始的请求和响应信息,也拿得到响应方法的信息,但是拿不到方法响应中参数的值

1)Class X extends HandlerInterceptor 
2)Class Y implements WebMvcConfigurer
3)y.addInteceptor(x)
=========================================================

3.ControllerAdvice(Controller增强,自spring3.2的时候推出):

@ControllerAdvice 作用于类

@HandlerException作用于方法  

该拦截器的实现逻辑:RequestMappingHandlerAdaptor.initControllerAdviceCache()    

如果有多个ControllerAdvice拦截器,可使用@Order进行排序(责任链模式)

HandlerExceptionResolverComposite.resovleException()--->AbstractHandlerExceptionResolver.resolveException()---->doResolveException()

主要是用于全局的异常拦截和处理,这里的异常可以使自定义异常也可以是JDK里面的异常

用于处理当数据库事务业务和预期不同的时候抛出封装后的异常,进行数据库事务回滚,并将异常的显示给用户

@Slf4j
@ResponseBody
@ControllerAdvice
public class ControllerExceptionHandler {

@ExceptionHandler(Throwable.class)
public Result handlerException(Throwable e) {
return ExceptionDeal.exceptionDeal(e);
}
}
=========================================================

4.切片:Aspect

   登录拦截

  可以拿得到方法响应中参数的值,但是拿不到原始的Http请求和相对应响应的方法

Aspect:  @Pointcut  @Around   @Before   @After

Filter(过滤器)

可以获得Http原始的请求和响应信息,但是拿不到响应方法的信息

filter是属于Servlet规范的,不属于Spring

springboot中的配置方法:

自定义一个Filter

import javax.servlet.*;

import java.io.IOException;

public class TimeFilter implements Filter {

/**Filter接口中的部分方法添加了default关键字,这样的方法就不是一定要重写*/

@Override

    public void init(FilterConfig filterConfig)throws ServletException {

System.out.println("Time Filter init");

    }

@Override

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {

System.out.println("time filter start");

        /**这里说明一下,在JDK8以及之后的JDK版本中都不再建议使用new Date().getTime()这种方式来获得时间*/

        long start = System.currentTimeMillis();

        chain.doFilter(request,response);

        System.out.println("time filter:"+(System.currentTimeMillis()-start));

        System.out.println("time filter finish");

    }

@Override

    public void destroy() {

System.out.println("time filter destroy");

    }

}

方式一:通过Bean注入的方式

注册Filter,springboot当中提供了FilterRegistrationBean类来注册Filter

import com.imooc.Filter.TimeFilter;

import com.imooc.Interceptor.TimeInterceptor;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.boot.web.servlet.FilterRegistrationBean;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.ArrayList;

import java.util.List;

@Configuration

public class WebConfig implements WebMvcConfigurer {

/**WebMvcConfigurerAdapter在JDK8中这个类已经过时,我们直接继承这个类所继承的接口*/

@Bean

    public FilterRegistrationBean timeFilter(){

FilterRegistrationBean registrationBean =new FilterRegistrationBean();

        TimeFilter timeFilter =new TimeFilter();

        registrationBean.setFilter(timeFilter);

        /**添加拦截的地址*/

        List urls =new ArrayList<>();

        urls.add("/*");

        return registrationBean;

    }

}

方式二:通过@WebFilter注解实现

import org.springframework.stereotype.Component;

import javax.servlet.*;

import javax.servlet.annotation.WebFilter;

import java.io.IOException;

@Component

@WebFilter(filterName ="TimeFilter",urlPatterns ="/*")

public class TimeFilter implements Filter {

@Override

    public void init(FilterConfig filterConfig)throws ServletException {

System.out.println("Time Filter init");

    }

@Override

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {

System.out.println("time filter start");

        /**这里说明一下,在JDK8以及之后的JDK版本中都不再建议使用new Date().getTime()这种方式来获得时间*/

        long start = System.currentTimeMillis();

        chain.doFilter(request,response);

        System.out.println("time filter:"+(System.currentTimeMillis()-start));

        System.out.println("time filter finish");

    }

@Override

    public void destroy() {

System.out.println("time filter destroy");

    }

}

@WebFilter 的常用属性


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM