5、spring boot + Maven + Restful filter+interceptor+Aspect
阿新 • • 發佈:2018-12-10
- 過濾器有兩種建立方式,第一種需要直接實現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"); } }
- 第二種實現過濾器實現一個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; } }
- 重寫註冊器,載入攔截器
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;
}
}
- 正常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()方法