欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java攔截器Interceptor實(shí)現(xiàn)原理及代碼示例

 更新時(shí)間:2021年12月15日 10:01:23   作者:春秋戰(zhàn)國(guó)程序猿  
本文詳細(xì)講解了Java攔截器Interceptor實(shí)現(xiàn)原理及代碼示例,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

?

1,攔截器的概念

java里的攔截器是動(dòng)態(tài)攔截Action調(diào)用的對(duì)象,它提供了一種機(jī)制可以使開發(fā)者在一個(gè)Action執(zhí)行的前后執(zhí)行一段代碼,也可以在一個(gè)Action執(zhí)行前阻止其執(zhí)行,同時(shí)也提供了一種可以提取Action中可重用部分代碼的方式。在AOP中,攔截器用于在某個(gè)方法或者字段被訪問之前,進(jìn)行攔截然后再之前或者之后加入某些操作。目前,我們需要掌握的主要是Spring的攔截器,Struts2的攔截器不用深究,知道即可。

2,攔截器的原理

大部分時(shí)候,攔截器方法都是通過代理的方式來調(diào)用的。Struts2的攔截器實(shí)現(xiàn)相對(duì)簡(jiǎn)單。當(dāng)請(qǐng)求到達(dá)Struts2的ServletDispatcher時(shí),Struts2會(huì)查找配置文件,并根據(jù)配置實(shí)例化相對(duì)的攔截器對(duì)象,然后串成一個(gè)列表(List),最后一個(gè)一個(gè)的調(diào)用列表中的攔截器。Struts2的攔截器是可插拔的,攔截器是AOP的一個(gè)實(shí)現(xiàn)。Struts2攔截器棧就是將攔截器按一定的順序連接成一條鏈。在訪問被攔截的方法或者字段時(shí),Struts2攔截器鏈中的攔截器就會(huì)按照之前定義的順序進(jìn)行調(diào)用。

3,自定義攔截器的步驟

  • 第一步:自定義一個(gè)實(shí)現(xiàn)了Interceptor接口的類,或者繼承抽象類AbstractInterceptor。
  • 第二步:在配置文件中注冊(cè)定義的攔截器。
  • 第三步:在需要使用Action中引用上述定義的攔截器,為了方便也可以將攔截器定義為默認(rèn)的攔截器,這樣在不加特殊說明的情況下,所有的Action都被這個(gè)攔截器攔截。

4,過濾器與攔截器的區(qū)別

過濾器可以簡(jiǎn)單的理解為“取你所想取”,過濾器關(guān)注的是web請(qǐng)求;攔截器可以簡(jiǎn)單的理解為“拒你所想拒”,攔截器關(guān)注的是方法調(diào)用,比如攔截敏感詞匯。

  • 4.1,攔截器是基于java反射機(jī)制來實(shí)現(xiàn)的,而過濾器是基于函數(shù)回調(diào)來實(shí)現(xiàn)的。(有人說,攔截器是基于動(dòng)態(tài)代理來實(shí)現(xiàn)的)
  • 4.2,攔截器不依賴servlet容器,過濾器依賴于servlet容器。
  • 4.3,攔截器只對(duì)Action起作用,過濾器可以對(duì)所有請(qǐng)求起作用。
  • 4.4,攔截器可以訪問Action上下文和值棧中的對(duì)象,過濾器不能。
  • 4.5,在Action的生命周期中,攔截器可以多次調(diào)用,而過濾器只能在容器初始化時(shí)調(diào)用一次。

5,Spring攔截器

抽象類HandlerInterceptorAdapter

我們?nèi)绻陧?xiàng)目中使用了Spring框架,那么,我們可以直接繼承HandlerInterceptorAdapter.java這個(gè)抽象類,來實(shí)現(xiàn)我們自己的攔截器。

Spring框架,對(duì)java的攔截器概念進(jìn)行了包裝,這一點(diǎn)和Struts2很類似。HandlerInterceptorAdapter繼承了抽象接口HandlerInterceptor。

package org.springframework.web.servlet.handler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public abstract class HandlerInterceptorAdapter implements HandlerInterceptor{
    // 在業(yè)務(wù)處理器處理請(qǐng)求之前被調(diào)用
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
        return true;
    }
    // 在業(yè)務(wù)處理器處理請(qǐng)求完成之后,生成視圖之前執(zhí)行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
      throws Exception{
    }
    // 在DispatcherServlet完全處理完請(qǐng)求之后被調(diào)用,可用于清理資源
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
      throws Exception{
    }
}

接下來我們看一下Spring框架實(shí)現(xiàn)的一個(gè)簡(jiǎn)單的攔截器UserRoleAuthorizationInterceptor,UserRoleAuthorizationInterceptor繼承了抽象類HandlerInterceptorAdapter,實(shí)現(xiàn)了用戶登錄認(rèn)證的攔截功能,如果當(dāng)前用戶沒有通過認(rèn)證,會(huì)報(bào)403錯(cuò)誤。

package org.springframework.web.servlet.handler;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class UserRoleAuthorizationInterceptor extends HandlerInterceptorAdapter{
    // 字符串?dāng)?shù)組,用來存放用戶角色信息
    private String[] authorizedRoles;
    public final void setAuthorizedRoles(String[] authorizedRoles){
        this.authorizedRoles = authorizedRoles;
    }
    public final boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws ServletException, IOException{
        if (this.authorizedRoles != null) {
            for (int i = 0; i < this.authorizedRoles.length; ++i) {
                if (request.isUserInRole(this.authorizedRoles[i])) {
                    return true;
                }
            }
        }
        handleNotAuthorized(request, response, handler);
        return false;
    }
    protected void handleNotAuthorized(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws ServletException, IOException{
          // 403表示資源不可用。服務(wù)器理解用戶的請(qǐng)求,但是拒絕處理它,通常是由于權(quán)限的問題
          response.sendError(403);
    }
}

下面,我們利用Spring框架提供的HandlerInterceptorAdapter抽過類,來實(shí)現(xiàn)一個(gè)自定義的攔截器。我們這個(gè)攔截器叫做UserLoginInterceptorBySpring,進(jìn)行登錄攔截控制。

工作流程是這樣的:如果當(dāng)前用戶沒有登錄,則跳轉(zhuǎn)到登錄頁面;登錄成功后,跳轉(zhuǎn)到之前訪問的URL頁面。

import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
/**
 * @description 利用spring框架提供的HandlerInterceptorAdapter,實(shí)現(xiàn)自定義攔截器
 */
public class UserLoginInterceptorBySpring extends HandlerInterceptorAdapter{
    // 在業(yè)務(wù)處理器處理請(qǐng)求之前被調(diào)用
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
        // equalsIgnoreCase 與 equals的區(qū)別?
        if("GET".equalsIgnoreCase(request.getMethod())){
            //RequestUtil.saveRequest();
        }
        System.out.println("preHandle...");
        String requestUri = request.getRequestURI();
        String contextPath = request.getContextPath();
        String url = requestUri.substring(contextPath.length());
        System.out.println("requestUri" + requestUri);
        System.out.println("contextPath" + contextPath);
        System.out.println("url" + url);
        String username = (String) request.getSession().getAttribute("username");
        if(null == username){
            // 跳轉(zhuǎn)到登錄頁面
            request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
            return false;
        }
        else{
            return true;
        }
    }
    // 在業(yè)務(wù)處理器處理請(qǐng)求完成之后,生成視圖之前執(zhí)行
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception{
        System.out.println("postHandle...");
        if(modelAndView != null){
            Map<String, String> map = new HashMap<String, String>();
            modelAndView.addAllObjects(map);
        }
    }
    // 在DispatcherServlet完全處理完請(qǐng)求之后被調(diào)用,可用于清理資源
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception{
        System.out.println("afterCompletion...");
    }
}

攔截器是依賴Java反射機(jī)制來實(shí)現(xiàn)的。攔截器的實(shí)現(xiàn),用到的是JDK實(shí)現(xiàn)的動(dòng)態(tài)代理,我們都知道,JDK實(shí)現(xiàn)的動(dòng)態(tài)代理,需要依賴接口。

攔截器是在面向切面編程中應(yīng)用的,就是在你的service或者一個(gè)方法前調(diào)用一個(gè)方法,或者在方法后調(diào)用一個(gè)方法。攔截器不是在web.xml,比如struts在struts.xml中配置。

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
    Object result = null;  
    System.out.println("方法調(diào)用前,可以執(zhí)行一段代碼" + method.getName());  
    result = method.invoke(this.targetObj, args);  
    System.out.println("方法調(diào)用后,可以執(zhí)行一段代碼 " + method.getName());  
    return result;  
}

總結(jié):

  • 1.過濾器(Filter):所謂過濾器顧名思義是用來過濾的,Java的過濾器能夠?yàn)槲覀兲峁┫到y(tǒng)級(jí)別的過濾,也就是說,能過濾所有的web請(qǐng)求,這一點(diǎn),是攔截器無法做到的。在Java Web中,你傳入的request,response提前過濾掉一些信息,或者提前設(shè)置一些參數(shù),然后再傳入servlet或者struts的action進(jìn)行業(yè)務(wù)邏輯,比如過濾掉非法url(不是login.do的地址請(qǐng)求,如果用戶沒有登陸都過濾掉),或者在傳入servlet或者struts的action前統(tǒng)一設(shè)置字符集,或者去除掉一些非法字符(聊天室經(jīng)常用到的,一些罵人的話)。filter 流程是線性的,url傳來之后,檢查之后,可保持原來的流程繼續(xù)向下執(zhí)行,被下一個(gè)filter, servlet接收。
  • 2.監(jiān)聽器(Listener):Java的監(jiān)聽器,也是系統(tǒng)級(jí)別的監(jiān)聽。監(jiān)聽器隨web應(yīng)用的啟動(dòng)而啟動(dòng)。Java的監(jiān)聽器在c/s模式里面經(jīng)常用到,它會(huì)對(duì)特定的事件產(chǎn)生產(chǎn)生一個(gè)處理。監(jiān)聽在很多模式下用到,比如說觀察者模式,就是一個(gè)使用監(jiān)聽器來實(shí)現(xiàn)的,在比如統(tǒng)計(jì)網(wǎng)站的在線人數(shù)。又比如struts2可以用監(jiān)聽來啟動(dòng)。Servlet監(jiān)聽器用于監(jiān)聽一些重要事件的發(fā)生,監(jiān)聽器對(duì)象可以在事情發(fā)生前、發(fā)生后可以做一些必要的處理。
  • 3.攔截器(Interceptor):java里的攔截器提供的是非系統(tǒng)級(jí)別的攔截,也就是說,就覆蓋面來說,攔截器不如過濾器強(qiáng)大,但是更有針對(duì)性。Java中的攔截器是基于Java反射機(jī)制實(shí)現(xiàn)的,更準(zhǔn)確的劃分,應(yīng)該是基于JDK實(shí)現(xiàn)的動(dòng)態(tài)代理。它依賴于具體的接口,在運(yùn)行期間動(dòng)態(tài)生成字節(jié)碼。攔截器是動(dòng)態(tài)攔截Action調(diào)用的對(duì)象,它提供了一種機(jī)制可以使開發(fā)者在一個(gè)Action執(zhí)行的前后執(zhí)行一段代碼,也可以在一個(gè)Action執(zhí)行前阻止其執(zhí)行,同時(shí)也提供了一種可以提取Action中可重用部分代碼的方式。在AOP中,攔截器用于在某個(gè)方法或者字段被訪問之前,進(jìn)行攔截然后再之前或者之后加入某些操作。java的攔截器主要是用在插件上,擴(kuò)展件上比如 Hibernate Spring Struts2等,有點(diǎn)類似面向切片的技術(shù),在用之前先要在配置文件即xml,文件里聲明一段的那個(gè)東西。

到此這篇關(guān)于Java攔截器Interceptor實(shí)現(xiàn)原理及代碼示例的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java的Lombok之@Builder使用總結(jié)

    Java的Lombok之@Builder使用總結(jié)

    這篇文章主要介紹了Java的Lombok之@Builder使用總結(jié),當(dāng)不使用@Builder注解到類上,創(chuàng)建T1的有參構(gòu)造函數(shù),入?yún)⒉粌H包括T1中所有的參數(shù),還包括T中所有的參數(shù),T2的屬性由T1在有參構(gòu)造函數(shù)中通過調(diào)用父類構(gòu)造器的方式賦初值,需要的朋友可以參考下
    2023-12-12
  • java IO流之轉(zhuǎn)換流的具體使用

    java IO流之轉(zhuǎn)換流的具體使用

    轉(zhuǎn)換流可以將一個(gè)字節(jié)流包裝成字符流,或者將一個(gè)字符流包裝成字節(jié)流,本文主要介紹了java IO流之轉(zhuǎn)換流的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • Java深入分析動(dòng)態(tài)代理

    Java深入分析動(dòng)態(tài)代理

    動(dòng)態(tài)代理指的是,代理類和目標(biāo)類的關(guān)系在程序運(yùn)行的時(shí)候確定的,客戶通過代理類來調(diào)用目標(biāo)對(duì)象的方法,是在程序運(yùn)行時(shí)根據(jù)需要?jiǎng)討B(tài)的創(chuàng)建目標(biāo)類的代理對(duì)象。本文將通過案例詳細(xì)講解一下Java動(dòng)態(tài)代理的原理及實(shí)現(xiàn),需要的可以參考一下
    2022-07-07
  • java實(shí)現(xiàn)簡(jiǎn)單發(fā)送郵件功能

    java實(shí)現(xiàn)簡(jiǎn)單發(fā)送郵件功能

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單發(fā)送郵件功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • java中BeanUtils.copyProperties的用法(超詳細(xì))

    java中BeanUtils.copyProperties的用法(超詳細(xì))

    本文介紹了BeanUtils.copyProperties()方法的使用,包括其功能、用法、注意事項(xiàng)和示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08
  • Mybatis-Plus和Mybatis的區(qū)別詳解

    Mybatis-Plus和Mybatis的區(qū)別詳解

    這篇文章主要介紹了Mybatis-Plus和Mybatis的區(qū)別,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • 詳解spring整合shiro權(quán)限管理與數(shù)據(jù)庫設(shè)計(jì)

    詳解spring整合shiro權(quán)限管理與數(shù)據(jù)庫設(shè)計(jì)

    這篇文章主要介紹了詳解spring整合shiro權(quán)限管理與數(shù)據(jù)庫設(shè)計(jì),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • SpringCloud之Ribbon使用示例解析

    SpringCloud之Ribbon使用示例解析

    這篇文章主要為大家介紹了SpringCloud之Ribbon使用示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • 分析jackjson的安全漏洞CVE-2019-14379

    分析jackjson的安全漏洞CVE-2019-14379

    這篇文章主要介紹了jackjson的使用及CVE-2019-14379漏洞分析,ackson知識(shí)點(diǎn)序列化和反序列化,setName和getName調(diào)用順序,通過實(shí)例代碼講解的很詳細(xì),需要的朋友可以參考下
    2021-06-06
  • 打卡每日10道面試題——JVM篇

    打卡每日10道面試題——JVM篇

    總結(jié)了JVM一些經(jīng)典面試題,分享出我自己的解題思路,希望對(duì)大家有幫助,有哪里你覺得不正確的話,歡迎指出,后續(xù)有空會(huì)更新,希望大家能夠喜歡
    2021-06-06

最新評(píng)論