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

在Spring Boot中处理嵌入式Tomcat异常

全兴运
2023-03-14

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

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

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

下面是一个重现这种行为的例子。您可以通过下载包含SpringWeb的初始项目来执行该示例(https://start.spring.io/)在版本2.1.5中。释放然后将以下两个类添加到项目中。

DemoControllerAdvice。JAVA

package com.example.demo;

import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class DemoControllerAdvice {

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public Map<String, String> forbiddenHandler() {
        Map<String, String> map = new HashMap<>();
        map.put("error", "An error occurred.");
        map.put("status", HttpStatus.FORBIDDEN.value() + " " + HttpStatus.FORBIDDEN.name());
        return map;
    }

}

DemoRestController。JAVA

package com.example.demo;

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) {
        return "You need to pass e.g. the character ^ as a request param to test this.";
    }

}

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

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

日志中显示以下消息:

o、 阿帕奇。郊狼。http11。Http11Processor:解析HTTP请求头时出错注意:HTTP请求解析错误的进一步出现将在调试级别记录。

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

共有1个答案

茅华灿
2023-03-14

这是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.";
}

}

您可能还想参考这个答案来决定您是否真的需要这个修复程序。

 类似资料:
  • 我有时会在pom中看到以下声明。xml。。。 如您所见,sping-boo-starter-web被声明为tomcat-embed-jasper。 是不是sping-boo-starter-web已经有一个嵌入式tomcat了?为什么一些开发人员仍然声明tomcat-embed-jasper以及boot-starter-web?还是有什么原因?

  • 我需要将我的Spring Boot ZuL网关中的MaxKeepAliverRequests值修改为高于默认值100的值。注意到该值未在Spring Boo的公共属性列表中公开,我尝试通过@Configuration class设置属性: 但似乎并没有起到预期的效果。有没有一种合适的方法可以让我更改没有通过Spring common properties公开的Tomcat属性?

  • 在将非spring应用程序转换为Spring Boot时,您希望使用现有上下文。嵌入tomcat中的xml文件。 使用Spring Boot 1.5.1和Tomcat 8.5.11 TomcatEmbeddedServletContainerFactory配置 检查数据库连接的方法, 那么如何在Spring Boot中加载现有的context.xml。

  • 问题内容: 我需要在Tomcat中启动Hazelcast,而无需单独的war文件。因此,将hazelcast.jar放入lib文件夹中的hazelczast.xml某处…接下来呢?还是不可能? 问题答案: 第一步是好的,只需将Hazelcast lib和配置放在Tomcat的libs文件夹中。接下来,如果您不需要单独的WAR文件,则是构建一个小的Valve类来启动/关闭Hazelcast节点。问题

  • 使用Spring Boot和启用LoadTimeWeaving的嵌入式tomcat,缓存方面在运行时没有任何影响,但我们看到在日志中编织的情况很好。 下面是配置,LoadTimeWeave与模式一起启用,作为用于缓存的AsheJ Spring代理-javaagent:..//Spring-仪表-4.3.3。释放。罐子 原木 围绕这个有很多讨论。编织发生在RestartClassLoader上,不确

  • 我正在使用NetBeans IDE和带有Spring Boot的Maven。每当我运行我的应用程序不止一次,我就会得到这个错误: O.A.Coyote.http11.http11nioprotocol:无法启动与ProtocolHandler关联的终结点[“http-nio-8080”] spring boot java.lang.IllegalStateException:Tomcat连接器处于