過濾器(Filter)和攔截器(Interceptor)

servlet+過濾器:github:https://github.com/xaioheilj/ServeletCRUDandJSON.git

所有的Servlet過濾器類都必須實現javax.servlet.Filter接口。該接口定義了以下3個方法:

  •  init(FilterConfig) :這是Servlet過濾器的初始化方法,Servlet容器創建Servlet過濾器實例後就會調用這個方法。在這個方法中可以通過 FilterConfig來讀取web.xml文件中Servlet過濾器的初始化參數。
  • doFilter(ServletRequest, ServletResponse, FilterChain) : 這是完成實際的過濾操作的方法,當客戶請求訪問與過濾器關聯的URL時,Servlet容器先調用該方法。FilterChain參數用來訪問後續的過濾 器的doFilter()方法。
  • destroy() :Servlet容器在銷燬過濾器實例前調用該方法,在這個方法中,可以釋放過濾器佔用的資源。

Filter的生命週期

    Filter的創建和銷燬由web服務器控制。

  • 服務器啓動的時候,web服務器創建Filter的實例對象,並調用其init方法,完成對象的初始化功能。filter對象只會創建一次,init方法也只會執行一次。
  • 攔截到請求時,執行doFilter方法。可以執行多次。
  • 服務器關閉時,web服務器銷燬Filter的實例對象。
  • 缺點是一個過濾器實例只能在容器初始化時調用一次。

1.集中解決中文亂碼 

public class EncodingFilter implements Filter {
    @Override
    public void destroy() {
    }
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
 
        request.setCharacterEncoding("UTF-8");
 
        chain.doFilter(request, response);
    }
 
    @Override
    public void init(FilterConfig arg0) throws ServletException {
 
    }
 
}

 在web.xml中添加映射即可

    <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>filter.EncodingFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

 

2.登錄驗證

 

public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        HttpSession session = request.getSession(true); //啓用Session,過濾器從中獲取信息
        String name = request.getParameter("userName");
        String password = request.getParameter("password");

        session.setAttribute("userName",name);
        session.setAttribute("password",password);

        if ("admin".equals(name) && "123".equals(password)) {
            request.getRequestDispatcher("addHero.html").forward(request, response);
        }else{
            response.sendRedirect("login.html");
        }

    }
}
public class AuthFilter implements Filter {

    @Override
    public void destroy() {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        String uri = request.getRequestURI();
        if (uri.endsWith("login.html") || uri.endsWith("login")) {
            chain.doFilter(request, response);
            return;
        }

        String userName = (String) request.getSession().getAttribute("userName");
        if (null == userName) {
            response.sendRedirect("login.html");
            return;
        }

        chain.doFilter(request, response);
    }

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

    }

}

  在web.xml中添加映射即可

    <filter>
        <filter-name>AuthFilter</filter-name>
        <filter-class>filter.AuthFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>AuthFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

 

SpringBoot+Interceptor :github:https://github.com/xaioheilj/SpringBoottest1.git

它依賴於web框架,在SpringMVC中就是依賴於SpringMVC框架。在實現上,基於Java的反射機制,屬於面向切面編程(AOP)的一種運用,就是在service或者一個方法前,調用一個方法,或者在方法後,調用一個方法,比如動態代理就是攔截器的簡單實現,在調用方法前打印出字符串(或者做其它業務邏輯的操作),也可以在調用方法後打印出字符串,甚至在拋出異常的時候做業務邏輯的操作。由於攔截器是基於web框架的調用,因此可以使用Spring的依賴注入(DI)進行一些業務操作,同時一個攔截器實例在一個controller生命週期之內可以多次調用。但是缺點是隻能對controller請求進行攔截,對其他的一些比如直接訪問靜態資源的請求則沒辦法進行攔截處理。
 

/*過濾器,登錄檢查*/
/*實現攔截器可以通過繼承HandlerInterceptorAdapter類。如果preHandle方法return true,則繼續後續處理。*/
public class LoginHandleInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Object user= request.getSession().getAttribute("loginUser");
        if (user == null){
            //沒有登陸過,不予許直接訪問dashboard,並返回到登錄頁面
            request.setAttribute("msg","沒有權限,先登錄");
            request.getRequestDispatcher("/login").forward(request,response);
            return false;
        }else {
            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 {

    }

在配置信息註冊攔截器

/*
*實現攔截器後還需要將攔截器註冊到spring容器中,可以通過implements WebMvcConfigurer,覆蓋其*addInterceptors(InterceptorRegistry registry)方法。記得把Bean註冊到Spring容器中,可以選擇*@Component 或者 @Configuration。
*/
//@EnableWebMvc //全面接管SpringMVC
@Configuration
//使用WebMvcConfigurer擴展SpringMVC的功能,所有的WebMvcConfigurer都會一起起作用
public class MyMVCconfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //瀏覽器發送/felix請求,到達firstPage頁面
        registry.addViewController("/felix").setViewName("firstPage");
    }
        @Bean // 將組建註冊在容器中
    public WebMvcConfigurer wbc(){
                //引入靜態資源文件,使訪問路徑直接訪問到login頁面
                WebMvcConfigurer webMvcConfigurer = new WebMvcConfigurer() {
                    @Override
                    public void addViewControllers(ViewControllerRegistry registry) {
                        registry.addViewController("/").setViewName("login");
                        registry.addViewController("/login").setViewName("login");
                        registry.addViewController("/main").setViewName("dashboard");
                    }

                    //註冊攔截器
                    @Override
                    public void addInterceptors(InterceptorRegistry registry) {
                        registry.addInterceptor(new LoginHandleInterceptor()).addPathPatterns("/**").excludePathPatterns("/login","/","/user/login","/asserts/**","/webjars/**");

                    }


                };
                return webMvcConfigurer;
    }

}

 

 過濾器filter和攔截器Interceptor的區別
spring的攔截器和servlet的過濾器有相似之處,都是AOP思想的體現,都可以實現權限檢查,日誌記錄,不同的是

適用範圍不同:Filter是Servlet容器規定的,只能使用在servlet容器中,而攔截器的使用範圍就大得多
使用的資源不同:攔截器是屬於spring的一個組件,因此可以使用spring的所有資源,對象,如service對象,數據源,事務控制等,而過濾器就不行
深度不同:Filter還在servlet前後起作用。而攔截器能夠深入到方法前後,異常拋出前後,因此攔截器具有更大的彈性,所有在spring框架中應該優先使用攔截器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章