SSM項目遇到的問題(六)——攔截器和過濾器

過濾器

  1. 實現
    html

    implements javax.servlet.Filter、XML中配置filter信息。java

    重寫init、doFilter、destroy三個方法web

    • void init(FilterConfig var1) throws ServletException:初始化Filter,在servlet容器啓動時執行且只在此時啓動一次。(後續 不過濾指定請求 會用到)spring

    • void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException:實現過濾功能,能夠在請求前預處理,也能夠請求後處理,分界線是chain.doFilter()spring-mvc

    • void destroy():用於Filter銷燬前,可用於資源回收。bash

  2. 使用session

    public class TestFilter implements Filter {
        private String excluded;
        private String[] excludedPages;
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            excluded = filterConfig.getInitParameter("excluded");
            //System.out.println(excluded);
            if (excluded!=null && excluded.length()>0){
                excludedPages = excluded.split(",");
            }
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
            HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
            boolean flag = false;
            for (String page : excludedPages){
                if (httpServletRequest.getRequestURI().equals(page)){
                    flag = true;
                }
            }
    
            if (flag){
                filterChain.doFilter(servletRequest, servletResponse);
            }else {
                HttpSession session = httpServletRequest.getSession();
                Object curUser = session.getAttribute("curUser");
                if (curUser==null){
                    httpServletResponse.sendRedirect("/user/login");
                }else {
                    filterChain.doFilter(servletRequest, servletResponse);
                }
            }
        }
    
        @Override
        public void destroy() {
        }
    }
    複製代碼

攔截器

  1. 實現mvc

    implements org.springframework.web.servlet.HandlerInterceptor、spring-mvc.xml配置app

    重寫3個方法框架

    • boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception:若是返回true,則繼續後續Interceptor的preHandle方法和controller;若是返回false,則後面的都不會執行。
    • void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception:若是preHandle返回false,這個方法不會執行。該方法執行在preHandle以後,視圖渲染以前。多個Interceptor的postHandle的執行順序,是:先聲明的後執行。
    • void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception:該方法執行前提也是preHandle返回true。執行在請求結束以後,也就是渲染了視圖以後才執行,可用於資源清理。相似於Filter的destroy。
  2. 使用

    public class TestInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            Object user = request.getSession().getAttribute("member");
            if (user==null){
                response.sendRedirect("/user/login");
                return false;
            }
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request,     HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        }
    }
    複製代碼

攔截器和過濾器對比

對比 攔截器 過濾器
處理的目標 全部web請求 Action-部分web請求
實現原理 函數回調 Java反射(動態代理)
應用場景 字符編碼 攔截未登陸用戶
URL級別的權限訪問 審計日誌
過濾敏感詞
壓縮響應信息
執行順序 根據filter-mapping配置的前後 按配置的順序,可經過order控制
規範 在Servlet規範中定義,servlet容器支持 spring容器內,spring框架支持
使用範圍 只能用於Web程序 不只Web程序,Application、swing均可以。
深度 只能在servlet先後使用 能夠深刻到方法先後,拋出異常先後。

Filter使用更加方便,Interceptor功能能夠更細緻的處理需求。

舉例:計算請求響應時間。

Filter:

```
void doFilter() throw Exception{    
    long time = System.currentTimeMillis();    
    chain.doFilter();
    System.out.println("請求時間爲:"+ (System.currentTimeMillis()-time));
}
```
複製代碼

interceptor:

```
long time = System.currentTimeMillis();  
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
   time = System.currentTimeMillis();
   return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
    System.out.println("Interceptor cost="+(System.currentTimeMillis()-start));
}
```
複製代碼

Interceptor須要一個提早聲明全局變量來存值,這就有可能引發線程問題。能夠經過TreadLocal解決。


相關

相關文章
相關標籤/搜索