Jersey有没有类似Spring的HandlerInterceptor的Interceptor
Is there an Interceptor in Jersey similar to that of Spring's HandlerInterceptor
我需要 Jersey 中的拦截器 2.x,它提供对请求、响应和与 Web 服务路径匹配的方法的引用。
类似于 Spring 的 HandlerInterceptor。
要求:
- 需要在 Class 上使用注释 - 执行以下检查,仅当球衣需要调用的相应方法未使用自定义注释进行注释时。
- 请求 - get/set 属性并获取会话对象以验证用户。
- Response - 重定向调用,以防任何验证失败,甚至在调用相应的方法之前。
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 - 这仅提供 Class 的注释。无法访问 request/response.
- ContainerRequestFilter - 提供请求对象但没有 Annotations/Response.
- ContainerResponseFilter - 提供请求和响应。但是在调用 web-service/Method 之后。
有没有其他方法可以在不使用过滤器的情况下实现这一点。因为只有在存在相应的 Web 服务时我才需要进行此处理。
另一方面,带有 /* 的过滤器将始终执行这些验证,即使未找到资源也是如此。
编辑:
感谢@peeskillet 这就是我实现它的方式。
@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);
...
// Sending JSON/Object back as response
...
String json = gson.toJson(resposeJson);
Response response = new ResponseBuilderImpl().encoding(StandardCharsets.UTF_8.name())
.type(MediaType.APPLICATION_JSON).entity(json).build();
requestContext.abortWith(response);
...
// or Sending URL back
...
URI uri = new URI(baseUrl + redirectUrl + "?refback=" + url);
requestContext.abortWith(Response.temporaryRedirect(uri).build());
...
这两种方法都非常有效,类似于 Spring 的 HandlerInterceptor。
Is there anyother way this can be achieved without using Filters. because I need this processing to happen ONLY if the corresponding web-service is present. Filter's with /* on the other hand would always perform these validations even when the resource was not found.
注册过滤器有多种方法。
只要正常注册,结果就是过滤器总是被调用。 (你不想要的)。
已注册注释,但 name binding。这样,只有带注释的资源才会通过过滤器。 (这是您想要的 种 ,唯一的问题是您需要对每个 class 进行注释)
@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
,因此您只需为 every 调用注册过滤器即可。这与使用名称绑定(这可能是您想要的)注释每个资源 class(如上所述)具有相同的效果。
@Provider
public class MyFeature implements DynamicFeature {
@Override
public void configure(ResourceInfo ri, FeatureContext ctx) {
ctx.register(YourFilter.class);
}
}
另请参阅:
我需要 Jersey 中的拦截器 2.x,它提供对请求、响应和与 Web 服务路径匹配的方法的引用。
类似于 Spring 的 HandlerInterceptor。
要求:
- 需要在 Class 上使用注释 - 执行以下检查,仅当球衣需要调用的相应方法未使用自定义注释进行注释时。
- 请求 - get/set 属性并获取会话对象以验证用户。
- Response - 重定向调用,以防任何验证失败,甚至在调用相应的方法之前。
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 - 这仅提供 Class 的注释。无法访问 request/response.
- ContainerRequestFilter - 提供请求对象但没有 Annotations/Response.
- ContainerResponseFilter - 提供请求和响应。但是在调用 web-service/Method 之后。
有没有其他方法可以在不使用过滤器的情况下实现这一点。因为只有在存在相应的 Web 服务时我才需要进行此处理。 另一方面,带有 /* 的过滤器将始终执行这些验证,即使未找到资源也是如此。
编辑:
感谢@peeskillet
@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);
...
// Sending JSON/Object back as response
...
String json = gson.toJson(resposeJson);
Response response = new ResponseBuilderImpl().encoding(StandardCharsets.UTF_8.name())
.type(MediaType.APPLICATION_JSON).entity(json).build();
requestContext.abortWith(response);
...
// or Sending URL back
...
URI uri = new URI(baseUrl + redirectUrl + "?refback=" + url);
requestContext.abortWith(Response.temporaryRedirect(uri).build());
...
这两种方法都非常有效,类似于 Spring 的 HandlerInterceptor。
Is there anyother way this can be achieved without using Filters. because I need this processing to happen ONLY if the corresponding web-service is present. Filter's with /* on the other hand would always perform these validations even when the resource was not found.
注册过滤器有多种方法。
只要正常注册,结果就是过滤器总是被调用。 (你不想要的)。
已注册注释,但 name binding。这样,只有带注释的资源才会通过过滤器。 (这是您想要的 种 ,唯一的问题是您需要对每个 class 进行注释)
@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
,因此您只需为 every 调用注册过滤器即可。这与使用名称绑定(这可能是您想要的)注释每个资源 class(如上所述)具有相同的效果。@Provider public class MyFeature implements DynamicFeature { @Override public void configure(ResourceInfo ri, FeatureContext ctx) { ctx.register(YourFilter.class); } }
另请参阅: