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