過濾器和攔截器比較及實現未登錄跳轉登錄頁的方式

看了一下午的文檔,對Filter(過濾器)和Interceptor(攔截器)有了更深入的理解,下面主要記錄對這兩個在未登錄時自動跳轉登錄頁面的實現的一些自己的理解。

首先要求攔截未登錄自動跳轉登錄頁面這種場景,用Filter(過濾器)和Interceptor(攔截器)都能夠實現。

但Filter(過濾器)和Interceptor(攔截器)有以下差異。

1、攔截器是基於java的反射機制的;而過濾器是基於函數回調 。 
2、過濾器的實現與struts2、spring等框架無關,在用戶請求被相應前執行,它依賴與servlet容器;而攔截器由Spring管理,不依賴與servlet容器,攔截器只對action起作用,不能攔截jsp頁面、圖片等其他資源。 
3、攔截器只能對action請求起作用,而過濾器則可以對幾乎所有的請求起作用(比如jsp、html、js、css、圖片等) 。 
4、攔截器可以訪問action上下文、值棧裏的對象,而過濾器不能 。 
5、在action的生命週期中,攔截器可以多次被調用,而過濾器只能在容器初始化時被調用一次 。
6、過濾器的配置在web.xml中,而攔截器的配置在基於使用的mvc框架不同在不同的xml配置中(如Strust2在strust.xml,而springmvc在spring-mvc.xml中)。
7、Filter是Servlet規範規定的,只能用於Web程序中。而攔截器既可以用於Web程序,也可以用於Application、Swing程序中。 
8、攔截器是一個Spring的組件,歸Spring管理,配置在Spring文件中,因此能使用Spring裏的任何資源、對象,例如Service對象、數據源、
事務管理等,通過IOC注入到攔截器即可;而Filter則不能。
9、Filter在只在Servlet前後起作用。而攔截器能夠深入到方法前後、
異常拋出前後等,因此攔截器的使用具有更大的彈性。
10、Filter根據mapping配置的先後順序;Interceptor也是按照配置的順序,但是可以通過order控制順序。

  

其實用Filter和Interceptor都能實現攔截未登錄自動跳轉登錄頁,但是在實際我接觸過的項目(主要是一些企業級開發的項目,用戶量並不太大)中基本上使用的都是Filter。

注意:Interceptor是針對action的攔截,如果知道jsp地址的話在URL欄直接輸入JSP的地址,那麼攔截器是沒有效果的,可以通過把所有的jsp放到WEB-INF下面避免。


下面是從網上摘的Filter(過濾器)和Interceptor(攔截器)實現攔截的案例

Filter過濾器實現

配置:web.xml

<filter>
  	<filter-name>RightFilter</filter-name>
	<filter-class>com.***.rights.RightFilter</filter-class>
</filter>
<filter-mapping>
  	<filter-name>RightFilter</filter-name>
  	<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
  	<filter-name>RightFilter</filter-name>
  	<url-pattern>*.action</url-pattern>
</filter-mapping>

java代碼:

mport java.io.IOException;
 
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 javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
 
public class RightFilter extends HttpServlet implements Filter {
 
	public void doFilter(ServletRequest arg0, ServletResponse arg1,
			FilterChain arg2) throws IOException, ServletException {
		HttpServletResponse response = (HttpServletResponse) arg1;  
		HttpServletRequest request=(HttpServletRequest)arg0;
		HttpSession session = request.getSession(true);  
		String usercode = (String) session.getAttribute("usercode");//
		String url=request.getRequestURI();
		if(usercode==null || usercode.equals(""))
		{
			//判斷獲取的路徑不爲空且不是訪問登錄頁面或執行登錄操作時跳轉
			if(url!=null && !url.equals("") && ( url.indexOf("Login")<0 && url.indexOf("login")<0 ))
			{
				response.sendRedirect("登錄路徑");
				return ;
			}			
		}
			//已通過驗證,用戶訪問繼續
			arg2.doFilter(arg0, arg1);
			return;
	}
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
	}

Interceptor攔截器實現(struts框架):

ps:struts2通過繼承AbstractInterceptor抽象類實現攔截器

配置:struts.xml

   <interceptors>  
	<!--定義一個名爲authority的攔截器-->  
	<interceptor  class="com.***.rights.RightInterceptor" name="rightInterceptor"/>  
	<!--定義一個包含權限檢查的攔截器棧-->  
	<interceptor-stack name="mydefault">  
	<!--配置內建默認攔截器-->  
	<interceptor-ref name="defaultStack"/>  
	<!--配置自定義的攔截器-->  
	<interceptor-ref name="rightInterceptor"/>  
	</interceptor-stack>  
   </interceptors>  
   <default-interceptor-ref name="mydefault" />  
   <!--定義全局Result-->  
   <global-results> 
  	  <result name="login">Login.jsp</result>  
	  <result name="error">/error.jsp </result> 
   </global-results>   		

java代碼:

import java.util.HashMap;
import java.util.Map;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.ActionContext;
public class RightInterceptor extends AbstractInterceptor {
 
	@Override
	public String intercept(ActionInvocation invocation) throws Exception {
		//System.out.println("攔截器開始驗證");
		try
		{
			ActionContext actionContext = ActionContext.getContext();
			Map<String,Object> session = actionContext.getSession();
	        String user=session.get("usercode").toString();   
	        //當前用戶session無效且訪問的action不是登錄action時,執行攔截,跳轉
	        if((user==null || user.equals("")) && !invocation.getAction().getClass().getName().equals("登錄action")) 
	        {
	            return Action.LOGIN;
	        }
		}
		catch(Exception e)
		{
			e.printStackTrace();
			return Action.LOGIN;
		}
        //System.out.println("攔截器通過驗證");
        return invocation.invoke();//執行訪問的action
		
 
	}
 
}

Interceptor攔截器實現(springmvc框架):

ps:springmvc通過實現HandlerInterceptor接口實現攔截器

配置:spring-mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd 
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 掃描controller(controller層注入) -->
    <context:component-scan base-package="com.bybo.aca.web.controller"/>

<mvc:interceptors>
        <mvc:interceptor>
            <!-- 攔截所有URL中包含/user/的請求 -->
            <mvc:mapping path="/user/**"/>
        <!-- 不進行攔截 -->
        <mvc:exclude-mapping path="/index.html"/>
            <bean class="com.jikexueyuan.demo.springmvc.lesson4.interceptor.LoginInterceptor"></bean>
        </mvc:interceptor>
</mvc:interceptors>   
    
<!-- 定義跳轉的文件的前後綴 ,視圖模式配置-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 自動給後面action的方法return的字符串加上前綴和後綴,變成一個 可用的url地址 -->
        <property name="prefix" value="/WEB-INF/page/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

java代碼:

package com.jikexueyuan.demo.springmvc.lesson4.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.jikexueyuan.demo.springmvc.lesson4.constant.Global;

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        Object user = request.getSession().getAttribute(Global.USER_SESSION_KEY);
        if (user == null) {
            System.out.println("尚未登錄,調到登錄頁面");
            response.sendRedirect("/loginpage.html");
            return false;
        }
        
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
    }

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

}

 

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