springboot設置過濾器、監聽器、攔截器

其實這篇文章算不上是springboot的東西,咱們在spring普通項目中也是能夠直接使用的java

設置過濾器:web

之前在普通項目中咱們要在web.xml中進行filter的配置,可是隻從servlet 3.0後,咱們就能夠在直接在項目中進行filter的設置,由於她提供了一個註解@WebFilter(在javax.servlet.annotation包下),使用這個註解咱們就能夠進行filter的設置了,同時也解決了咱們使用springboot項目沒有web.xml的尷尬,使用方法以下所示spring

@WebFilter(urlPatterns="/*",filterName="corsFilter", asyncSupported = true)
public class CorsFilter implements Filter{

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
            FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse)servletResponse; 
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        chain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }

}

其實在WebFilter註解中有一些屬性咱們須要進行設置, 好比value、urlPatterns,這兩個屬性其實都是同樣的做用,都是爲了設置攔截路徑,asyncSupported這個屬性是設置配置的filter是否支持異步響應,默認是不支持的,若是咱們的項目須要進行請求的異步響應,請求通過了filter,那麼這個filter的asyncSupported屬性必須設置爲true否則請求的時候會報異常。springboot

設置攔截器:session

編寫一個配置類,繼承org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter或者org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport並重寫addInterceptors(InterceptorRegistry registry)方法,其實父類的addInterceptors(InterceptorRegistry registry)方法就是個空方法。使用方法以下:app

@Configuration
public class MvcConfig extends WebMvcConfigurationSupport {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration registration = registry.addInterceptor(new HandlerInterceptor() {
            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                return true;
            }

            @Override
            public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

            }

            @Override
            public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

            }
        });
        // 配置攔截路徑
        registration.addPathPatterns("/**");
        // 配置不進行攔截的路徑
        registration.excludePathPatterns("/static/**");
    }
}

配置監聽器:cors

通常咱們經常使用的就是request級別的javax.servlet.ServletRequestListener和session級別的javax.servlet.http.HttpSessionListener,下面以ServletRequestListener爲例,編寫一個類實現ServletRequestListener接口並實現requestInitialized(ServletRequestEvent event)方法和requestDestroyed(ServletRequestEvent event)方法,在實現類上加上@WebListener(javax.servlet.annotation包下),以下所示異步

@WebListener
public class RequestListener implements ServletRequestListener {

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("請求結束");
    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("請求開始");
    }
}

這樣每個請求都會被監聽到,在請求處理前equestInitialized(ServletRequestEvent event)方法,在請求結束後調用requestDestroyed(ServletRequestEvent event)方法,其實在spring中有一個很是好的例子,就是org.springframework.web.context.request.RequestContextListener類async

public class RequestContextListener implements ServletRequestListener {

    private static final String REQUEST_ATTRIBUTES_ATTRIBUTE =
            RequestContextListener.class.getName() + ".REQUEST_ATTRIBUTES";


    @Override
    public void requestInitialized(ServletRequestEvent requestEvent) {
        if (!(requestEvent.getServletRequest() instanceof HttpServletRequest)) {
            throw new IllegalArgumentException(
                    "Request is not an HttpServletRequest: " + requestEvent.getServletRequest());
        }
        HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest();
        ServletRequestAttributes attributes = new ServletRequestAttributes(request);
        request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes);
        LocaleContextHolder.setLocale(request.getLocale());
        RequestContextHolder.setRequestAttributes(attributes);
    }

    @Override
    public void requestDestroyed(ServletRequestEvent requestEvent) {
        ServletRequestAttributes attributes = null;
        Object reqAttr = requestEvent.getServletRequest().getAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE);
        if (reqAttr instanceof ServletRequestAttributes) {
            attributes = (ServletRequestAttributes) reqAttr;
        }
        RequestAttributes threadAttributes = RequestContextHolder.getRequestAttributes();
        if (threadAttributes != null) {
            // We're assumably within the original request thread...
            LocaleContextHolder.resetLocaleContext();
            RequestContextHolder.resetRequestAttributes();
            if (attributes == null && threadAttributes instanceof ServletRequestAttributes) {
                attributes = (ServletRequestAttributes) threadAttributes;
            }
        }
        if (attributes != null) {
            attributes.requestCompleted();
        }
    }

}

在這個類中,spring將每個請求開始前都將請求進行了一次封裝並設置了一個threadLocal,這樣咱們在請求處理的任何地方均可以經過這個threadLocal獲取到請求對象,好處固然是有的啦,好比咱們在service層須要用到request的時候,能夠不須要調用者傳request對象給咱們,咱們能夠經過一個工具類就能夠獲取,豈不美哉。ide

擴充:在springboot的啓動類中咱們能夠添加一些ApplicationListener監聽器,例如:

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(DemoApplication.class);
        application.addListeners(new ApplicationListener<ApplicationEvent>() {
            @Override
            public void onApplicationEvent(ApplicationEvent event) {
                System.err.println(event.toString());
            }
        });
        application.run(args);
    }
}
ApplicationEvent是一個抽象類,她的子類有不少好比ServletRequestHandledEvent(發生請求事件的時候觸發)、ApplicationStartedEvent(應用開始前觸發,作一些啓動準備工做)、ContextRefreshedEvent(容器初始化結束後觸發),其餘還有不少,這裏再也不多說,可是這些ApplicationListener只能在springboot項目以main方法啓動的時候纔會生效,也就是說項目要打jar包時才適用,若是打war包,放在Tomcat等web容器中是沒有效果的。
相關文章
相關標籤/搜索