Jersey中是不是有类似于Spring的HandlerInterceptor的Interceptor
Posted
技术标签:
【中文标题】Jersey中是不是有类似于Spring的HandlerInterceptor的Interceptor【英文标题】:Is there an Interceptor in Jersey similar to that of Spring's HandlerInterceptorJersey中是否有类似于Spring的HandlerInterceptor的Interceptor 【发布时间】:2016-06-14 03:24:03 【问题描述】:我需要 Jersey 2.x 中的拦截器,它提供对请求、响应和与 Web 服务路径匹配的方法的引用。
类似于 Spring 的 HandlerInterceptor 的东西。
要求:
-
需要在类上使用注释 - 仅当需要由 jersey 调用的相应方法未使用自定义注释进行注释时,才执行以下检查。
请求 - 获取/设置属性并获取会话对象以验证用户。
响应 - 重定向调用,以防任何验证失败,甚至在调用相应的方法之前。
Spring等效代码:
public class WebServiceInterceptor implements HandlerInterceptor
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
try
SkipWebServiceIntercept skipWebService = handler.getClass().getAnnotation(SkipWebServiceIntercept.class);
if (skipWebService != null)
return Boolean.TRUE;
...
if(securityFails)
if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With")))
response.setCharacterEncoding("utf-8");
response.setContentType("application/json");
PrintWriter out = response.getWriter();
String json;
...
out.println(json);
return Boolean.FALSE;
else
response.sendRedirect(redirectUrl);
else
return Boolean.TRUE;
catch (Exception e)
log.error("Exception in preHandle, redirecting to Login page", e);
return LoginUtil.redirectToLogin(request, response);
我找到了
的参考资料-
ReaderInterceptor - 这仅提供类的注释。无权访问请求/响应。
ContainerRequestFilter - 提供请求对象但不提供注释/响应。
ContainerResponseFilter - 提供请求和响应。但是在调用 web-service/Method 之后。
有没有其他方法可以在不使用过滤器的情况下实现这一点。因为只有存在相应的 Web 服务时,我才需要进行此处理。 另一方面,带有 /* 的过滤器将始终执行这些验证,即使未找到资源也是如此。
编辑: 感谢@peeskillet answer 这就是我实现它的方式。
@Provider
public class ResourceInterceptor implements DynamicFeature
@Override
public void configure(ResourceInfo resourceInfo, FeatureContext context)
System.out.println("Resource Interceptor called");
if (resourceInfo.getResourceClass() != null
&& resourceInfo.getResourceClass().getAnnotation(SkipWebServiceIntercept.class) != null)
return;
context.register(LoginFilter.class);
@Slf4j
public class LoginFilter implements ContainerRequestFilter
@Context
private HttpServletRequest request;
@Context
private ServletContext servletContext;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException
try
WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
CookieAuthenticator cookieAuthenticator = springContext.getBean(CookieAuthenticator.class);
HttpSession session = request.getSession(true);
...
// 将 JSON/Object 作为响应发送回来
...
String json = gson.toJson(resposeJson);
Response response = new ResponseBuilderImpl().encoding(StandardCharsets.UTF_8.name())
.type(MediaType.APPLICATION_JSON).entity(json).build();
requestContext.abortWith(response);
...
// 或发回网址
...
URI uri = new URI(baseUrl + redirectUrl + "?refback=" + url);
requestContext.abortWith(Response.temporaryRedirect(uri).build());
...
这两种方法都运行良好,类似于 Spring 的 HandlerInterceptor。
【问题讨论】:
感谢您返回并使用有效的解决方案进行更新。我一切正常,但我不明白 SkipWebServiceIntercept 是什么。这是如何创建的? 没关系,我刚刚创建了一个自定义注解 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface SkipWebServiceIntercept String value() default ""; 【参考方案1】:有没有其他方法可以在不使用过滤器的情况下实现这一点。因为仅当存在相应的 Web 服务时,我才需要进行此处理。另一方面,带有 /* 的过滤器将始终执行这些验证,即使在未找到资源时也是如此。
有多种注册过滤器的方法。
只要正常注册,结果就是过滤器总是被调用。 (你不想要的)。
注册了一个注释,虽然name binding。这样,只有带注释的资源才会通过过滤器。 (这是你想要的种,唯一的问题是你需要注释每个类)
@Target(TYPE, METHOD)
@Retention(RetentionPolicy.RUNTIME);
class @interface Filtered
@Path("..")
@Filtered
public class YourResource
@Filtered
@Provider
public class YourFilter implements ContainerRequestFilter
Use a DynamicFeature 以编程方式而非声明方式绑定资源。 DynamicFeture
将为您的每个资源方法 调用,因此您只需为每个 调用注册过滤器。这与使用名称绑定注释每个资源类(如上所述)具有相同的效果(这可能是您想要的)。
@Provider
public class MyFeature implements DynamicFeature
@Override
public void configure(ResourceInfo ri, FeatureContext ctx)
ctx.register(YourFilter.class);
另请参阅:
Chapter 10. Filters and Interceptors【讨论】:
使用ContainerRequestFilter
的问题是我没有响应对象。我可以访问 ResourceInfo 来检查注释,但如果验证失败,那么我将不得不从过滤器本身重定向而不调用资源。使用 Servlet Filter 我可以使用 response.sendRedirect() 来实现这一点。如何使用 ContainerRequestFilter 来执行此操作?我探索了 ContainerRequestContext 的所有 API,但找不到响应。那么有没有办法从 ContainerRequestFilter 重定向到另一个 URL 呢?
您可以使用requestContext.abortWith(Response)
...(Response.seeOther(...)
用于重定向)
或者您可以抛出异常并在ExceptionMapper中处理重定向
谢谢。我会尝试这些方法并更新。另外如何在球衣 web.xml 中注册 DynamicFeature?我写了一个 DynamicFeature 但配置方法没有被调用。
如果您按包扫描资源,即您有 init-param jersey.config.server.provider.packages
,您可以使用多个包,只需用逗号分隔即可。包扫描获取@Provider
注释。或者您可以使用 init-param jersey.config.server.provider.classnames
显式注册该类以上是关于Jersey中是不是有类似于Spring的HandlerInterceptor的Interceptor的主要内容,如果未能解决你的问题,请参考以下文章
JPA/Spring/Hibernate/etc 中是不是有类似于 JPA 的 @PrePersist 允许更改相关实体的功能?
列出所有已部署的 REST 端点(spring-boot、jersey)
有没有人在嵌入模式下使用Jersey(不是servlet env而是独立的Grizzly实例)成功使用模板引擎?
Jersey和Springboot应用程序抛出java.lang.StackOverflowError