日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

工作总结4:拦截器的使用

發布時間:2023/12/9 64 豆豆
生活随笔 收集整理的這篇文章主要介紹了 工作总结4:拦截器的使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.攔截器綜述

攔截器的功能是定義在Java攔截器規范。

攔截器規范定義了三種攔截點:

業務方法攔截,
生命周期回調偵聽,
超時攔截(EJB)方法。
在容器的生命周期中進行攔截

public class DependencyInjectionInterceptor {@PostConstructpublic void injectDependencies(InvocationContext ctx) { ... } }

EJB超時時使用的攔截器

public class TimeoutInterceptor {@AroundTimeoutpublic Object manageTransaction(InvocationContext ctx) throws Exception { ... } }

在業務上,對某一個Bean的方法進行攔截

public class TransactionInterceptor {@AroundInvokepublic Object manageTransaction(InvocationContext ctx) throws Exception { ... } }

@AroundInvoke注釋指定了要用作攔截器的方法,攔截器方法與被攔截的業務方法執行同一個java調用堆棧、同一個事務和安全上下文中。用@AroundInvoke注釋指定的方法必須遵守以下格式:public Object XXX(javax.interceptor.InvocationContext ctx) throws Exception

下面是javax.interceptor.InvocationContext封裝了客戶端所調用業務方法的一些信息。

package javax.interceptor; public interface InvocationContext{public Object getTarget();public Method getMethod();public Ojbect[] getParameters();public void setParameters(Object[] newArgs);public java.util.Map<String, Ojbect> getContextData();public Object proceed() throws Exception; }

getTarget() 指向被調用的bean實例
getMethod() 指向被攔截的業務方法
getParameters() 獲取被攔截業務方法的參數
setParameters() 設置被攔截業務方法的參數
getContextData() 返回一個Map對象,它在整個方法調用期間都可以被訪問到。位于同一個方法調用內的不同攔截器之間可以利用它來傳遞上下文相關的數據。
示例:

//被攔截的方法 @Interceptors(HelloInterceptor.class) public class HelloChinaBean {public String SayHello(String name) {return name +"Hello World.";} } //攔截器定義 public class HelloInterceptor {@AroundInvokepublic Object log(InvocationContext ctx) throws Exception {try{if (ctx.getMethod().getName().equals("SayHello")){System.out.println("Holle World!!!" );} return ctx.proceed();}catch (Exception e) {throw e;}} }

2.攔截器綁定(Interceptor bindings)

假設我們想要申明一些bean的事務。我們先要的是一個攔截器綁定類型來指定哪些bean我們要申明.
首先定義一個注解

@InterceptorBinding @Target({METHOD, TYPE}) @Retention(RUNTIME) public @interface Transactional {} 現在我們可以很容易地指定類ShoppingCart是事務性對象:

@Transactional public class ShoppingCart { ... } 或者我們可以指定一個方法的事務

public class ShoppingCart {@Transactional public void checkout() { ... } }
  • 1
  • 2
  • 3

2.攔截器實現(Implementing interceptors)

我們實際上要實現提供了這種事務管理方面的攔截器,所以我們需要做的是創建一個標準的攔截,并配上@Interceptor和@transactional注解.

@Transactional @Interceptor public class TransactionInterceptor {@AroundInvokepublic Object manageTransaction(InvocationContext ctx) throws Exception { ... } }

攔截器可以利用依賴注入:

@Transactional @Interceptor public class TransactionInterceptor {@Resource UserTransaction transaction;@AroundInvokepublic Object manageTransaction(InvocationContext ctx) throws Exception { ... } }

多個攔截器可以使用相同的攔截器綁定類型。

@Resource和@Inject的區別:

3.啟用攔截器(Enabling interceptors)

默認情況下,所有攔截器被禁用.要使用攔截器.需要在bean.xml中進行配置,以啟用.從CDI 1.1起攔截器可以使用@Priority注釋為整個應用程序啟用。

<beansxmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"><interceptors><class>org.mycompany.myapp.TransactionInterceptor</class></interceptors> </beans>

這樣有2個好處:

攔截器比較重要,在XML中確保其確定性行為
它讓我們在部署時啟用或禁用攔截器類。
當然也可以配置啟用多個攔截器

<beansxmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"><interceptors><class>org.mycompany.myapp.SecurityInterceptor</class><class>org.mycompany.myapp.TransactionInterceptor</class></interceptors> </beans>

攔截器畢竟比較重要,不推薦使用@Priority啟用.
在CDI中,XML配置的優先級高于@Priority.
關于@Priority可以參考下列:

public static class Interceptor.Priority
extends Object
Priorities that define the order in which interceptors are invoked. These values should be used with the Priority annotation.

Interceptors defined by platform specifications should have priority values in the range PLATFORM_BEFORE up until LIBRARY_BEFORE, or starting at PLATFORM_AFTER.
Interceptors defined by extension libraries should have priority values in the range LIBRARY_BEFORE up until APPLICATION, or LIBRARY_AFTER up until PLATFORM_AFTER.
Interceptors defined by applications should have priority values in the range APPLICATION up until LIBRARY_AFTER.
An interceptor that must be invoked before or after another defined interceptor can choose any appropriate value.

Interceptors with smaller priority values are called first. If more than one interceptor has the same priority, the relative order of these interceptor is undefined.

For example, an extension library might define an interceptor like this:

@Priority(Interceptor.Priority.LIBRARY_BEFORE+10)@Interceptorpublic class ValidationInterceptor { ... }

4.Interceptor bindings with members(攔截器注解屬性)
假設我們想要添加一些額外的信息給我們的@transactional注解:

@InterceptorBinding @Target({METHOD, TYPE}) @Retention(RUNTIME) public @interface Transactional {boolean requiresNew() default false; }

CDI將使用requiresNew的值選擇兩個不同的攔截器,TransactionInterceptor和RequiresNewTransactionInterceptor

下面是requiresNew為true的攔截器

@Transactional(requiresNew = true) @Interceptor public class RequiresNewTransactionInterceptor {@AroundInvokepublic Object manageTransaction(InvocationContext ctx) throws Exception { ... } }

如下使用:

@Transactional(requiresNew = true) public class ShoppingCart { ... }

但是如果我們只有一個攔截器,我們希望容器攔截器綁定時忽略requiresNew的值,也許這些信息只用于攔截器實現。我們可以使用@Nonbinding注釋:

@InterceptorBinding @Target({METHOD, TYPE}) @Retention(RUNTIME) public @interface Secure {@Nonbinding String[] rolesAllowed() default {}; }

5.Multiple interceptor binding annotations(多重攔截器綁定注解)

通常我們使用攔截器綁定的組合類型綁定多個攔截器bean。例如,下面的聲明將用于綁定TransactionInterceptor和SecurityInterceptor這2個攔截器到ShoppingCart.

@Secure(rolesAllowed="admin") @Transactional public class ShoppingCart { ... }

然而,在非常復雜的情況下,一個攔截器本身可能指定攔截器綁定類型:

@Transactional @Secure @Interceptor public class TransactionalSecureInterceptor { ... }
  • 1
  • 2

那么這個攔截器可以綁定到checkout() 方法,以下任何組合都可使用:

public class ShoppingCart {@Transactional @Secure public void checkout() { ... } } @Secure public class ShoppingCart {@Transactional public void checkout() { ... } } @Transactional public class ShoppingCart {@Secure public void checkout() { ... } } @Transactional @Secure public class ShoppingCart {public void checkout() { ... } }

6. Interceptor binding type inheritance(攔截器綁定類型繼承)

Java語言支持注解的一個限制就是缺乏注解繼承.注解應該重用內置已有的.就如同下面這段代碼表達的意思

//實際沒這寫法 public @interface Action extends Transactional, Secure { ... }
  • 1
  • 2

幸運的是,CDI圍繞Java沒有的這個特性開展了一些工作.
我們會標注一個攔截器綁定類型,其有其他攔截器的綁定類型,(稱為元注解)
表述起來有點費勁,就如同下面代碼這樣.

@Transactional @Secure @InterceptorBinding @Target(TYPE) @Retention(RUNTIME) public @interface Action { ... }

現在任何Bean綁定 Action這個注解 ,其實就是綁定到了@Transactional @Secure.(就是攔截器TransactionInterceptor和攔截器SecurityInterceptor). (甚至TransactionalSecureInterceptor,如果它存在.)

7.Use of @Interceptors(同時用多個攔截器)
這個注解@Interceptors是攔截器規范定義的,cdi是支持的<使用托管bean和EJB規范>.如下:

@Interceptors({TransactionInterceptor.class, SecurityInterceptor.class}) public class ShoppingCart {public void checkout() { ... } }

但缺點也很明顯,不推薦使用.缺點如下:

攔截器在代碼中是硬編碼.
攔截器在部署時不好更改.
攔截器命令是非全局的——它是在類級別由攔截器的順序列出.
因此還是使用上面CDI的使用方式比較好.

總結

以上是生活随笔為你收集整理的工作总结4:拦截器的使用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。