请求的handleEnd()中出现异常时中止(HTTP 500)请求

时间:2018-09-02 19:05:05

标签: vert.x

我正在使用vert.x-web实施小型服务。我的请求结束处理程序之一(通过CHAR进行了设置)抛出了这个context.request().endHandler()

NullPointerException

为什么此异常不调用我的请求的异常处理程序?为什么不处理?我已将请求的异常处理程序设置为2018-09-02 20:54:35,125 - ERROR [vert.x-eventloop-thread-1] (ContextImpl.java:345) - lambda$wrapTask$2() Unhandled exception java.lang.NullPointerException at (My handler class) at io.vertx.core.http.impl.HttpServerRequestImpl.handleEnd(HttpServerRequestImpl.java:417) at io.vertx.core.http.impl.Http1xServerConnection.handleEnd(Http1xServerConnection.java:482) at io.vertx.core.http.impl.Http1xServerConnection.handleContent(Http1xServerConnection.java:477) at io.vertx.core.http.impl.Http1xServerConnection.processMessage(Http1xServerConnection.java:458) at io.vertx.core.http.impl.Http1xServerConnection.handleMessage(Http1xServerConnection.java:144) at io.vertx.core.http.impl.HttpServerImpl$ServerHandlerWithWebSockets.handleMessage(HttpServerImpl.java:712) at io.vertx.core.http.impl.HttpServerImpl$ServerHandlerWithWebSockets.handleMessage(HttpServerImpl.java:619) at io.vertx.core.net.impl.VertxHandler.lambda$channelRead$1(VertxHandler.java:146) at io.vertx.core.impl.ContextImpl.lambda$wrapTask$2(ContextImpl.java:337) at io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:195) at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:144) (通过context.fail())。但这似乎没有任何作用。

还有我不知道的另一个异常处理程序吗?

编辑:这是最小的复制代码:

context.request().exceptionHandler()

预期的行为:Vertx vertx = Vertx.vertx(); Router router = Router.router(vertx); router.route().handler(context -> { context.request() .exceptionHandler(context::fail) .endHandler(nothing -> { throw new NullPointerException("null"); }) .handler(buffer -> {}); }); vertx.createHttpServer() .requestHandler(router::accept) .listen(8080); 被调用,并且连接因HTTP ERROR 500而关闭。

行为正确:上下文没有失败,连接“挂起”。

2 个答案:

答案 0 :(得分:0)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> ... <packaging>jar</packaging> <description></description> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-boot-admin.version>2.0.2</spring-boot-admin.version> <spring-boot-dependencies.version>2.0.4.RELEASE</spring-boot-dependencies.version> ... <rat.skip>true</rat.skip> <log4j-version>2.6.1</log4j-version> </properties> <repositories> ... </repositories> <dependencyManagement> <dependencies> <!-- Necessary dependency for running Spring Boot without starter parent --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-releasetrain</artifactId> <version>Fowler-SR2</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot-dependencies.version}</version> <type>pom</type> <scope>import</scope> </dependency> ... </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-server</artifactId> <version>${spring-boot-admin.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> ... <!-- TODO The version of this dependency lets Spring Boot fail, but is necessary tu run the old backend --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>${log4j-version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>${log4j-version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-iostreams</artifactId> <version>${log4j-version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-1.2-api</artifactId> <version>${log4j-version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-jcl</artifactId> <version>${log4j-version}</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-jul</artifactId> <version>${log4j-version}</version> </dependency> <dependency> <groupId>org.fusesource.jansi</groupId> <artifactId>jansi</artifactId> <version>1.13</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> </dependency> ... </dependencies> <build> <defaultGoal>verify</defaultGoal> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> ... </plugin> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>2.6</version> <executions> <execution> <id>prepare-config-zip</id> <phase>prepare-package</phase> <goals> <goal>single</goal> </goals> <configuration> <descriptors> <descriptor>${basedir}/src/main/assembly/config.xml</descriptor> </descriptors> <finalName>configs</finalName> <appendAssemblyId>false</appendAssemblyId> </configuration> </execution> <execution> <id>prepare-dist-zip</id> <phase>package</phase> <goals> <goal>single</goal> </goals> <configuration> <descriptor>src/main/assembly/dist.xml</descriptor> <finalName>...</finalName> <appendAssemblyId>false</appendAssemblyId> </configuration> </execution> </executions> </plugin> <plugin> <artifactId>maven-enforcer-plugin</artifactId> <configuration> <rules> <requireJavaVersion> <version>1.8</version> </requireJavaVersion> </rules> </configuration> </plugin> </plugins> </build> <profiles> <profile> <id>attach-standalone</id> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <configuration> <shadedArtifactAttached>true</shadedArtifactAttached> <shadedClassifierName>standalone</shadedClassifierName> </configuration> </plugin> </plugins> </build> </profile> <profile> <id>dont-attach-standalone</id> <activation> <activeByDefault>true</activeByDefault> </activation> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <configuration> <!-- Prevent huge shaded artifacts from being deployed to Artifactory --> <outputFile>...</outputFile> </configuration> </plugin> </plugins> </build> </profile> </profiles> 适用于exceptionHandler对象。该方法是从HttpServerRequest接口继承的。每当处理HTTP请求而不是用户代码的Vert.x / Netty代码出现问题时,都会调用此回调。

如果您想在实际请求处理之前执行一些代码,我建议您注册一条路由并在处理程序中调用ReadStream

RoutingContext#next

然后,预处理逻辑中的任何故障都将被路由器捕获并正常管理。

答案 1 :(得分:0)

这里需要指出两点:

  • 由响应未明确结束引起的挂起(请参见HttpServerResponse#end()

  • 要处理在请求处理期间发生的异常,请在路由级别添加故障处理程序(请参见Route#failureHandler())。根据请求处理异常只会在读取流时捕获异常。

例如:

Router router = Router.router(vertx);
router.route().failureHandler(handler -> handler.response().end());
router.route().handler(routingContext -> routingContext.request().endHandler(handler -> {
  throw new NullPointerException("exception here!");
}));
vertx.createHttpServer().requestHandler(router::accept).listen(8085);