在使用Java EE开发和发展REST API的过程中,有些情况下您希望以更细粒度的方式(视情况而定)对传入的HTTP请求(特别是标头参数)进行“观察” Servlet过滤器或更具体的ContainerRequestFilters 。
我发现在某些情况下非常方便的一种可能方式是,在我的JAXRS Resource实现中添加CDI拦截器 ,该拦截器最终可以访问传入的HTTP请求并执行一些“自定义”逻辑。 作为开发人员,我可以完全控制–只需添加或删除自定义批注即可在哪个路径(哪个路径)中拦截请求。随着Java EE 7的引入,混合“关注点”变得更加容易,因此您可以轻松注入对纯CDI拦截器的HTTP请求 。
在下面,我仅记录一个非常简单的示例,在该示例中,我使用自定义拦截器来“拦截”业务REST API上的HTTP请求,以便执行一些非常特定的自定义身份验证逻辑。 我正在检查在我的REST API中发起请求的“用户”是否具有系统定义的某些特定自定义角色。 当然,整个示例只是一个示例,但是您明白了。
为了引入这样一个组件,您需要两件事:
- 引入自定义注释,该注释将在定义后用于激活拦截器
- 实现CDI拦截器。
- 在其余api的路径/资源上应用注释
注释界面
这里没什么特别的,只是一个自定义的运行时批注,因此我们可以使用它来“标记” JAXRS API的特定方法。
package gr.javapapo.sample.cdi;/*** Created by <a href="mailto:javapapo@mac.com">javapapo</a> on 24/09/15.*/
import javax.enterprise.util.Nonbinding;
import javax.interceptor.InterceptorBinding;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface CheckRequest {@Nonbinding String role() default "ADMIN";
}
拦截器的实现
值得注意的几点:
- 拦截器已使用我们的自定义注释“标记”了-简单
- 我们@Inject HttpServletReqest
- 我们基于注释详细信息应用一些自定义逻辑(我阅读了定义中的所有参数)
- 从请求中,我读取了标头并基于注释参数-我做了一些基本的逻辑
package gr.javapapo.sample.cdi;import javax.inject.Inject;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.NotAllowedException;/*** CDI interceptor for the {@linkplain CheckRequest} annotation* Created by <a href="mailto:javapapo@mac.com">javapapo</a> on 24/09/15.*/
@Interceptor
@CheckRequest
public class CheckRequestInterceptor {@InjectHttpServletRequest request;@AroundInvokepublic Object checkAccess(InvocationContext ctx) throws Exception {CheckRequest annotation = ctx.getMethod().getAnnotation(CheckRequest.class);String role = annotation.role();String roleToken = request.getHeader("roleToken");if(roleToken==null && !role.equals(roleToken)){throw new NotAllowedException("Not allowed if your request does not have the roleToken header " +"or your role is not correct ");}return ctx.proceed();}
}
应用拦截器/注释
最终,您可以注释@Path JAXRS资源和方法,以便“踢”自定义逻辑:
@Path("/status")
public class StatusResource {/*** Returns a simple JSON object, regarding the app status, n** @return Response <JsonObject>*/@GET@Produces(MediaType.APPLICATION_JSON)@CheckRequest(role="ADMIN")public Response getStatus() {JsonObject object = Json.createObjectBuilder().add("status", "Status with CDI internceptor check,It Works at " + LocalDateTime.now().toString()).build();Response.ResponseBuilder repBuilder = Response.ok().entity(object);return repBuilder.build();}
- 您可以在github上这个非常简单的示例项目中找到所有文件。
翻译自: https://www.javacodegeeks.com/2015/10/cdi-interceptor-of-http-request-and-header-params-simple-example.html