Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在Spring引导中处理嵌入的Tomcat异常_Java_Spring_Tomcat_Spring Boot - Fatal编程技术网

Java 在Spring引导中处理嵌入的Tomcat异常

Java 在Spring引导中处理嵌入的Tomcat异常,java,spring,tomcat,spring-boot,Java,Spring,Tomcat,Spring Boot,我们遇到了一个问题,嵌入式Tomcat从LegacyCookieProcessor抛出IllegalArgumentException。它抛出一个500 HTTP响应代码 我们需要处理异常并对其进行处理(具体来说,将其作为400发送) 典型的@ExceptionHandler(IllegalArgumentException.class)似乎没有被触发,Google似乎只给出处理Spring引导特定异常的结果 例子: 下面是一个重现该行为的示例。您可以通过下载初始项目(包括版本2.1.5.RE

我们遇到了一个问题,嵌入式Tomcat从
LegacyCookieProcessor
抛出
IllegalArgumentException
。它抛出一个500 HTTP响应代码

我们需要处理异常并对其进行处理(具体来说,将其作为400发送)

典型的
@ExceptionHandler(IllegalArgumentException.class)
似乎没有被触发,Google似乎只给出处理Spring引导特定异常的结果


例子: 下面是一个重现该行为的示例。您可以通过下载初始项目(包括版本2.1.5.RELEASE中的SpringWeb())来执行该示例。然后将以下两个类添加到项目中

DemoControllerAdvice.java


然后,启动服务器并在浏览器中请求以下URL:

  • http://localhost:8080/working
    在控制器中手动抛出
    IllegalArgumentException
    。然后它被ControllerAdvice捕获,因此将生成一个JSON字符串,其中包含
    DemoControllerAdvice
  • http://localhost:8080/not-正在工作?demo=test^123
    Tomcat抛出了一个
    IllegalArgumentException
    ,因为无法解析请求参数(因为无效字符
    ^
    )。但是,ControllerAdvice不会捕获异常。它显示Tomcat提供的默认HTML页面。它还提供了与
    DemoControllerAdvice
    中定义的不同的错误代码
日志中显示以下消息:

o、 apache.coyote.http11.Http11Processor:分析HTTP请求头时出错 注意:HTTP请求解析错误的进一步出现将在调试级别记录

java.lang.IllegalArgumentException:在请求目标中找到无效字符。有效字符在RFC 7230和RFC 3986中定义 在org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:467)~[tomcat-embed-core-9.0.19.jar:9.0.19]


正如在回答中提到的,这是Tomcat本身的一个特性

但是,您可以这样做,允许您期望的特殊字符作为请求的一部分,并自己处理它们

首先,您需要通过如下设置relaxedQueryChars来允许需要处理的特殊字符

import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;

@Component
public class TomcatCustomizer implements 
WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

@Override
public void customize(TomcatServletWebServerFactory factory) {
    factory.addConnectorCustomizers((connector) -> {
        connector.setAttribute("relaxedQueryChars", "^");
    });
 }
}
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoRestController {

@GetMapping(value = "/working")
public void working() {
    throw new java.lang.IllegalArgumentException();
}

@GetMapping(value = "/not-working")
public String notWorking(@RequestParam String demo) {

    if (demo.contains("^")) {
        throw new java.lang.IllegalArgumentException("^");
    }
    return "You need to pass e.g. the character ^ as a request param to test this.";
}

}

您可能还需要参考答案,以确定是否确实需要此修复

@Imran字符串不是这样比较的!也许你找不到答案,因为你没有为其他人提供一个简单的复制问题的方法。你不能截取这个。这个异常是在Servlet API处理之前抛出的,因此这里甚至没有涉及Servlet过滤器、侦听器或
DispatcherServlet
。这只是tomcat内部很早就崩溃了。@ssc-hrep3奇怪的是,我无法在
http://localhost:8080/not-正在工作?demo=test^123
,它给了我200。您能告诉我您使用的是哪个版本的Java,以及启用了哪些特殊属性吗?。一个完整的github回购示例有助于尝试一些选项。@ssc-hrep3,看看MCVE有多有用?新的人——不一定是我,因为我是AOP专家,但对容器了解不多,所以一开始就要求MCVE——加入讨论并提供有价值的信息,重新提出了一个2.5年的问题<代码>:-)谢谢您的回复,这很有趣。但是,我不想允许这些字符。我只想以相同的方式响应所有异常:返回一个包含JSON的HTTP包(和自定义头)。允许这些字符,然后在每个控制器中再次处理它们似乎不是一个好的解决方案。实际上,它并不能阻止Tomcat抛出其他异常(我假设还有其他场景,Tomcat会抛出一个除特殊字符之外的异常)。允许每个控制器中包含这些字符只是这个场景的一个示例。你可以做的是构建一个HTTP拦截器,并检查带有特殊字符的参数,然后从拦截器中抛出IllegalArgumentException以获得一个通用的实现。虽然问题已经演变为谈论查询参数,但最初的问题实际上是关于cookie中的一个奇怪值,而不是查询参数。这对两种情况都有效吗?
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;

@Component
public class TomcatCustomizer implements 
WebServerFactoryCustomizer<TomcatServletWebServerFactory> {

@Override
public void customize(TomcatServletWebServerFactory factory) {
    factory.addConnectorCustomizers((connector) -> {
        connector.setAttribute("relaxedQueryChars", "^");
    });
 }
}
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoRestController {

@GetMapping(value = "/working")
public void working() {
    throw new java.lang.IllegalArgumentException();
}

@GetMapping(value = "/not-working")
public String notWorking(@RequestParam String demo) {

    if (demo.contains("^")) {
        throw new java.lang.IllegalArgumentException("^");
    }
    return "You need to pass e.g. the character ^ as a request param to test this.";
}

}