Java 在Spring引导中处理嵌入的Tomcat异常
我们遇到了一个问题,嵌入式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
LegacyCookieProcessor
抛出IllegalArgumentException
。它抛出一个500 HTTP响应代码
我们需要处理异常并对其进行处理(具体来说,将其作为400发送)
典型的@ExceptionHandler(IllegalArgumentException.class)
似乎没有被触发,Google似乎只给出处理Spring引导特定异常的结果
例子: 下面是一个重现该行为的示例。您可以通过下载初始项目(包括版本2.1.5.RELEASE中的SpringWeb())来执行该示例。然后将以下两个类添加到项目中 DemoControllerAdvice.java
然后,启动服务器并在浏览器中请求以下URL:
在控制器中手动抛出http://localhost:8080/working
。然后它被ControllerAdvice捕获,因此将生成一个JSON字符串,其中包含IllegalArgumentException
DemoControllerAdvice
Tomcat抛出了一个http://localhost:8080/not-正在工作?demo=test^123
,因为无法解析请求参数(因为无效字符IllegalArgumentException
)。但是,ControllerAdvice不会捕获异常。它显示Tomcat提供的默认HTML页面。它还提供了与^
中定义的不同的错误代码DemoControllerAdvice
正如在回答中提到的,这是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.";
}
}