1. 程式人生 > >5、spring boot + Maven + Restful filter+interceptor+Aspect

5、spring boot + Maven + Restful filter+interceptor+Aspect

  1. 過濾器有兩種建立方式,第一種需要直接實現Filter
package com.imooc.filter;

import java.io.IOException;
import java.util.Date;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.springframework.stereotype.Component;

/**
 * 只需要宣告Component註解就能起作用
 * @author caijiajun
 * @date   2018年9月11日
 */
@Component 
public class TimeFilter implements Filter {
	
	/**
	 *容器緊跟在垃圾收集之前呼叫 destroy()方法,以便能夠執行任何必需的清理程式碼。
	 */
	@Override
	public void destroy() {
		System.out.println("time filter destroy");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("time filter start");
		long start  = new Date().getTime();
		chain.doFilter(request, response);
		System.out.println("time filter:" +(new Date().getTime() - start));
		System.out.println("time filter finish");
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		System.out.println("time filter init");
	}

}

  1. 第二種實現過濾器實現一個WebMvcConfigurationAdapter載入介面卡
package com.imooc.web.config;

import java.util.ArrayList;
import java.util.List;

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.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.imooc.filter.TimeFilter;
import com.imooc.web.interceptor.TimeInterceptor;

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter{
	
	@Autowired
	private TimeInterceptor timeInterceptor;
	/**
	 * 自定義載入過濾器 
	 *spring中 filter是以 
	 *FilterRegistrationBean形式存在的,然後我們 
	 *setFilter為這個filter放入spring 容器管理。
	 *可以用setOrder方法為filter設定排序值
	 * @return
	 */
	@Bean
	public FilterRegistrationBean timeFilter() {
		FilterRegistrationBean  registrationBean = new FilterRegistrationBean();
		//載入過濾器
		TimeFilter timeFilter = new TimeFilter();
		registrationBean.setFilter(timeFilter);
		
		List<String> urls = new ArrayList<>(); 
		urls.add("/*");
		registrationBean.setUrlPatterns(urls);
		
		return registrationBean;
	}
	}

3.攔截器,攔截器的配置必須在重寫註冊,自定義攔截器TimeInterceptor類

package com.imooc.web.interceptor;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

@Component
public class TimeInterceptor implements HandlerInterceptor {
	/**
	 * 無論如何都會被呼叫在postHandle後面,只有在preHandle返回true才會執行
	 * 在DispatcherServlet 渲染了對應的檢視之後執行。用於進行資源清理。
	 */
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object arg2, Exception ex)
			throws Exception {
		System.out.println("afterCompletion");
		long start = (long)request.getAttribute("startTime");
		System.out.println("time interceptor 耗時: " + (new Date().getTime() - start));
		System.out.println("ex :" + ex);
	}
	/**
	 * 控制器處理後被呼叫,如果controller方法丟擲異常,就不會被呼叫
	 * 該方法將在請求處理之後,DispatcherServlet進行檢視返回渲染之前進行呼叫
	 */
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndeVidw)
			throws Exception {
		System.out.println("postHandle");
		long start = (long)request.getAttribute("startTime");
		System.out.println("time interceptor 耗時: " + (new Date().getTime() - start));
	}
	/**
	 * controller方法呼叫前被呼叫
	 * 只有該方法返回true,後面的Interceptor和cotroller才會被執行
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		System.out.println("preHandle");
		//對應的類名
		System.out.println(((HandlerMethod)handler).getBean().getClass().getName());
		//對應的方法名
		System.out.println(((HandlerMethod)handler).getMethod().getName());
		request.setAttribute("startTime", new Date().getTime());
		return true;
	}

}

  1. 重寫註冊器,載入攔截器
package com.imooc.web.config;

import java.util.ArrayList;
import java.util.List;

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.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.imooc.filter.TimeFilter;
import com.imooc.web.interceptor.TimeInterceptor;

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter{
		
	@Autowired
	private TimeInterceptor timeInterceptor;
	
	/**
	 * 自定義載入過濾器 
	 *spring中 filter是以 
	 *FilterRegistrationBean形式存在的,然後我們 
	 *setFilter為這個filter放入spring 容器管理。 
	 *可以用setOrder方法為filter設定排序值
	 * @return
	 */
	@Bean
	public FilterRegistrationBean timeFilter() {
		FilterRegistrationBean  registrationBean = new FilterRegistrationBean();
		//載入攔截器
		TimeFilter timeFilter = new TimeFilter();
		registrationBean.setFilter(timeFilter);
		
		List<String> urls = new ArrayList<>(); 
		urls.add("/*");
		registrationBean.setUrlPatterns(urls);
		
		return registrationBean;
	}
	/**
	 * 重寫註冊器  載入攔截器
	 */
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(timeInterceptor);
	}
	}

5 . Aspect增強

package com.imooc.web.aspect;

import java.util.Date;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class TimeAspect {
	

	/**
	 * 設定切入點
	 * proceedingJoinPoint 裡面包含攔截的方法的資訊
	 * @param proceedingJoinPoint
	 * @return
	 */
	@Around("execution(* com.imooc.web.controller.UserController.*(..))")
	public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("time aspect start");
		//傳入引數
		Object[] args = pjp.getArgs();
		for(Object arg : args) {
			System.out.println("args is "+arg);
		}
		long start = new Date().getTime();
		//呼叫被加強的方法、
		Object object = pjp.proceed();
		
		System.out.println("time aspect 耗時:" + (new Date().getTime() -start));
		System.out.println("time aspect end");
		return object;
	}
}

  1. 正常Controller執行Filter,interceptor,Aspect的順序 在這裡插入圖片描述 總結:Filter(init) -> Filter(doFilter) -> interceptor(preHandle) -> Aspect(around) -> Controller -> Aspect(Around) ->interceptor(postHandle) -> interceptor(AfterCompletion) ->Filter(doFilter) -> Filter(destroy) 註釋:如果interceptor中prehandle()方法返回false 則不會進入後面兩個方法,如果interceptor中prehandle()方法返回true,但是controller報異常,則不會進入postHandle()方法