Spring三大器

Spring三大器

監聽器listener

Servlet的監聽器Listener,它主要做用是隨着web應用的啓動而啓動,只初始化一次,隨着web的中止而銷燬。java

主要工做是:進行一些初始化的工做,例如參數或者固定一些固定對象web

  • Spring boot框架自帶的Listener由框架提供,在Application的run方法中進行初始化並完成加載spring

  • 本身實現的監聽器可完成各類功能,在Spring boot下,能夠實現各類特殊的監聽器接口來實現各類動做的監聽。同時能夠經過使用註解@WebListener來完成Listener的初始化工做讓其注入到IoC容器,記得在Application啓動類上加上註解@ServletComponentScan。session

@WebListener
public class SocketCounter implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
     
    }
}
@ServletComponentScan
@SpringBootApplication(scanBasePackages = "com.example.socketdemo", exclude = {DataSourceAutoConfiguration.class})
public class SocketdemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SocketdemoApplication.class, args);
    }
}

攔截器Interceptor

Interceptor的urlPattern針對的是SpringMVC中的Controller控制器處理的請求框架

Interceptor是SpringMVC的一個機制,在Spring框架的程序中,優先使用攔截器socket

過濾器和攔截器的功能相似 :用於請求調用真正的業務邏輯以前和以後作一些通用性的處理,例如日誌打印,或者請求過濾等ide

Interceptor 的執行順序大體爲:post

  • 請求到達 DispatcherServletthis

  • DispatcherServlet 發送至 Interceptor ,執行 preHandleurl

  • 請求達到 Controller

  • 請求結束後,postHandle 執行

Spring boot框架下主要經過實現HandlerInterceptor接口來實現請求的攔截,該接口有3個主要方法

  • preHandler() 在handler執行以前,返回boolean,true表示繼續執行,false表示攔截

  • postHandler() 在handler執行以後,能夠在結果返回以前對結果進行修改

  • afterCompetition() 在請求徹底結束調用以後,用愛統計請求耗時等等

使用攔截器進行方法執行時間統計

@Slf4j
@Component
public class ExecuteTimeInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);
        System.out.println("in pre handle");
        // 攔截器放行
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 獲取到請求的開始時間
        System.out.println("in post handle");
        long startTime = (Long) request.getAttribute("startTime");
        long endTime = System.currentTimeMillis();
        long executeTime = endTime - startTime;
        //modified the exisitng modelAndView
        System.out.println(String.format("execute time is %s",executeTime));
    }

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

編寫config類,將對應的攔截器鏈注入到容器中。

@Configuration
public class MyWebConfig implements WebMvcConfigurer {

    // 配置攔截器
    // 將攔截器添加到 registry當中
    // 配置攔截須要攔截的請求路徑 /** 全匹配
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new ExecuteTimeInterceptor()).addPathPatterns("/**");
    }
}

過濾器Filter

Filter的urlPattern針對的是全部請求,在Servlet 先後起做用。

Filter由java實現,它依賴於Servlet容器。

通常狀況下 Filter是一個鏈

  • request -> filter1 -> filter2 ->filter3 -> …. -> request resource.

  • chain.doFilter將請求轉發給過濾器鏈下一個filter , 若是沒有filter那就是你請求的資源

@WebFilter(filterName = "AuthFilter",urlPatterns = "/*")
public class AuthFilter implements Filter {

    List<String> excludedUrlList;

    String excludedUrls = "/login";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("excludedUrls:" + excludedUrls);
        excludedUrlList = Arrays.asList(StringUtils.split(excludedUrls, ","));
        System.out.println("AuthFilter init success");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        // 校驗是否須要登陸
        System.out.println("url is " + ((HttpServletRequest) servletRequest).getRequestURL());
        Boolean result = excludedUrlList.contains(((HttpServletRequest) servletRequest).getRequestURI());
        System.out.println("是否須要重定向到login " + !result);
        if (!result) {
            System.out.println("this request need to go to 重定向頁面");
            response.sendRedirect("/login");
            return;
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }


    private Boolean needLogin(HttpServletRequest request) {
        System.out.println("in needLogin()");
        return true;
    }
}

Spring Boot中使用自定的Filter:

  1. 實現Filter接口,並重載其核心的三個方法。

  2. 使用註解 @WebFilter(filterName = "AuthFilter",urlPatterns = "/*") 將Filter完成注入,並配置好須要過濾的路徑

攔截器和過濾器的區別

  • 在Spring框架下,儘可能使用Interceptor,由於過濾器能作的事攔截器基本都能作
  • Interceptor可以操做上下文等Spring框架的容器中一些對象,而Filter不能夠
  • Filter基於針對Servlet的全部請求,而Interceptor只針對Controller的請求進行處理
相關文章
相關標籤/搜索