当前位置: 首页 > 知识库问答 >
问题:

如何在Java应用程序中选择性地灭活RESTendpoint?

堵茂勋
2023-03-14

日志记录对此应用程序非常重要。需要在开始正常操作之前始终初始化日志系统(以确保完全的可跟踪性)。应用程序使用一个安全的日志系统,该系统需要一个密钥来初始化日志(使用该密钥对日志进行签名,以防止篡改日志)。还有一个要求,即日志记录密钥应该上传到每个服务。每个后端服务都有一个用于接收日志记录密钥的endpoint。

有一个“鸡还是蛋”类型的问题。应用程序需要运行才能接收密钥,但在接收密钥之前,应用程序不应该完全运行。

为满足要求,我们正在考虑以下启动程序:

    null

我已经检查过,并且知道变量FilterChain不是null,但是在方法doFilter(ServletRequest,ServletResponse,FilterChain)中出现了错误,我无法调试它。

可能,我没有初始化一些需要初始化的东西。

我已经添加了下面得到的输出。

<filter>
    <filter-name>myFilter</filter-name>
    <filter-class>com.company.filter.LoggingFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>myFilter</filter-name>
    <url-pattern>*</url-pattern>
</filter-mapping>
public class LoggingFilter implements Filter {

    @Override
    public void init(final FilterConfig filterConfig) throws ServletException {

    }

    public void doFilter(final ServletRequest request, 
                         final ServletResponse response, 
                         final FilterChain filterChain) throws IOException, 
                                                               ServletException {

        String url = "";
        if (request instanceof HttpServletRequest) {
            url = ((HttpServletRequest) request).getRequestURL().toString();
        }

        if (url.endsWith("/installkey/")) {
            filterChain.doFilter(request, response);
            return;
        } else if (loggerConfig.isInitialized()) {
            filterChain.doFilter(request, response);
            return;
        }
    }

    public void destroy() {
        System.out.println("XXXXXXXXXXX Running destroy");
    }
}

但我得到以下错误:

Jan 19, 2016 10:42:25 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [default] in context with path [/vw-ws-rest] threw exception [Error processing webservice request] with root cause
java.lang.NullPointerException
    at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:240)
    at org.apache.openejb.server.cxf.rs.CxfRsHttpListener.doInvoke(CxfRsHttpListener.java:227)
    at org.apache.tomee.webservices.CXFJAXRSFilter.doFilter(CXFJAXRSFilter.java:94)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at com.company.filter.LoggingFilter.doFilter(LoggingFilter.java:63)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:44)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

作为替代方案,我尝试了Cássio Mazzochi Molin建议的使用JAX-RS名称绑定的方法。

我创建了接口:

import javax.ws.rs.NameBinding;

@NameBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD })
public @interface TemporarilyDisabled {
}
@Provider
@TemporarilyDisabled
public class LoggingFilter implements ContainerRequestFilter {

    @Override
    public void filter(final ContainerRequestContext requestContext) throws IOException {

        System.out.println("in filter method!");
    }
}
@Path("installkey")
@Stateless(name = "vw-installKeyResource")
public class VwInstallKeyResource {

    @Inject
    private Logger LOG;

    @EJB
    //... some required classes

    @POST
    @TemporarilyDisabled
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response savePlatformData(final InstallKeyData installKeyData)
        throws CryptographicOperationException, DuplicateEntryException {

        ....
    }
}
<!-- JAX-RS -->
<dependency>
    <groupId>javax.ws.rs</groupId>
    <artifactId>javax.ws.rs-api</artifactId>
    <version>2.0</version>
</dependency>

出于某种原因,筛选器没有捕获请求。

我不知道问题是否与endpoint是一个帖子有关。或者,JAX-RS可能找不到过滤器类,它用@provider修饰,但我不知道是否需要用其他方式注册过滤器。

共有1个答案

楚宪
2023-03-14

我不认为你会找到任何开箱即用的解决办法。

在使用JAX-RS2.0及其实现时,您会发现一些很好的资源:您可以使用名称绑定筛选器根据您的条件中止对某个endpoint的请求。

这种方法很酷的一点是,您可以保持endpoint的精干并专注于它们的业务逻辑。负责中止请求的逻辑将在筛选器中。要暂时禁用一个或多个endpoint,只需在它们上放置一个注释即可。它将激活阻止请求到达终结点的筛选器。默认情况下,所有endpoint都是启用的,您将有选择地禁用不希望接收请求的endpoint。

@NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface TemporarilyDisabled { }
@Provider
@TemporarilyDisabled
public class TemporarilyDisableEndpointRequestFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        
        if (isEndpointTemporarilyDisabled) {
            requestContext.abortWith(Response.status(Response.Status.SERVICE_UNAVAILABLE)
                                        .entity("Service temporarily unavailable.")
                                        .build());
        }
    }
}

@provider注释标记了JAX-RS运行时在提供者扫描阶段可以发现的扩展接口的实现。

您可以编写任何条件来测试终结点是否应该暂时禁用。

在上面的示例中:

注意:503状态代码的存在并不意味着服务器在超载时必须使用它。有些服务器可能希望简单地拒绝连接。

要将筛选器绑定到endpoint方法或类,请使用上面定义的@temporarilydisabled注释对它们进行注释。对于带注释的方法和/或类,将执行过滤器:

@Path("/")
public class MyEndpoint {

    @GET
    @Path("{id}")
    @Produces("application/json")
    public Response myMethod(@PathParam("id") Long id) {
        // This method is not annotated with @TemporarilyDisabled
        // The request filter won't be executed when invoking this method
        ...
    }

    @DELETE
    @Path("{id}")
    @TemporarilyDisabled
    @Produces("application/json")
    public Response myTemporarilyDisabledMethod(@PathParam("id") Long id) {
        // This method is annotated with @TemporarilyDisabled
        // The request filter will be executed when invoking this method
        ...
    }
}

在上面的示例中,请求筛选器将只针对MyTemporarilyDisabledMethod(Long)方法执行,因为它是用@TemporarilyDisabled注释的。

 类似资料:
  • 实际上,我想要以下二进制图像上的“白色”像素的五个外部边界框。所需的区域用红色突出显示。 要获得第5个边界框,我会放大或模糊它。但是,膨胀会将区域3与区域1和2合并,因此我将获得一个几乎覆盖整个图像的边界框。(如果我不放大或模糊它,那么将产生大量的小矩形。) 换句话说,我只想要“足够大”的边界框。 这只是一个样本模式。分区的位置可能会有所不同。有没有一种方法可以从总体上解决这个问题?

  • 我有两个关于Intellij IDEA中Gradle的问题 我知道退出按钮将优雅地关闭java应用程序 (文件)- 但我想知道如何通过gradle run优雅地关闭我的java应用程序? 因为gradle运行时没有退出按钮 (文件)- 另一个问题是如何通过编辑配置将java选项(如-Xmx选项)设置为java应用程序 虚拟机选项似乎设置了gradle虚拟机选项,而不是我的java应用程序选项。 非

  • 我有一个Winforms应用程序,它目前正在使用application Insights SDK捕获错误日志、事件、异常、表单视图和另一个遥测。App Center现在支持WinForms应用程序,它还支持将遥测数据导出到应用程序洞察中。我现在的问题是,我是否应该从WinForms应用程序中删除Application Insights SDK,而使用AppCenter SDK?这样做有什么好处吗?

  • 问题内容: 我的应用程序必须支持阿拉伯语(从右到左方向)和英语(从左到右方向)语言,我需要设置UI并基于用户 从我的应用程序中选择的语言。 我将使用NSLayoutConstraint实现UI,以便它可以根据前导和尾随约束自动更新UI 。 现在我的问题是我该如何实现?由于我的设备语言是英语,并且从我的应用程序用户中选择阿拉伯语(仅限于我的应用程序),因此我的Flow,UI,动画等应从右到左。 问题

  • 以下是GAE灵活Java8/Jetty应用程序的app.yaml文件。 由于某种原因,部署应用程序时没有使用JAVA_HEAP_OPTS值。至少我不认为它被使用了,因为当我SSHdocker容器并运行以下命令时,内存值要少得多。 有人能告诉我发生了什么,或者我需要做些什么改变吗? 谢谢

  • 问题内容: 我是android的新手,我的论文就像android的“ Battery Doctor Saver”一样。我的第一个问题是选择多个应用程序并立即将其杀死。老实说,我已经遇到了第一大问题,但是我的问题是我一次只能杀死一个应用程序。因此,这是我的代码,谢谢您对我的问题的立即答复:)。 问题答案: 创建onButton,然后单击您的kill按钮。从ListView中收集所有选择的按钮及其位置