关于在Spring Reactive中自定义ErrorAttributeOptions的问题

huangapple go评论104阅读模式
英文:

Problem with cutomizing ErrorAttributeOptions in Spring Reactive

问题

在我的处理程序函数中,我有这个方法:

  1. public Mono<ServerResponse> itemsEx(ServerRequest serverRequest) {
  2. throw new RuntimeException("RuntimeException Occured");
  3. }

现在,我想处理这个异常,所以我覆盖了 AbstractErrorWebExceptionHandler 并创建了这个类:

  1. package com.learnreactivespring.learnreactivespring.exception;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.boot.autoconfigure.web.ResourceProperties;
  4. import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
  5. import org.springframework.boot.web.error.ErrorAttributeOptions;
  6. import org.springframework.boot.web.reactive.error.ErrorAttributes;
  7. import org.springframework.context.ApplicationContext;
  8. import org.springframework.http.HttpStatus;
  9. import org.springframework.http.MediaType;
  10. import org.springframework.http.codec.ServerCodecConfigurer;
  11. import org.springframework.stereotype.Component;
  12. import org.springframework.web.reactive.function.BodyInserters;
  13. import org.springframework.web.reactive.function.server.*;
  14. import reactor.core.publisher.Mono;
  15. import java.util.Map;
  16. @Component
  17. @Slf4j
  18. public class FunctionalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
  19. public FunctionalErrorWebExceptionHandler(ErrorAttributes errorAttributes,
  20. ApplicationContext applicationContext,
  21. ServerCodecConfigurer serverCodecConfigurer) {
  22. super(errorAttributes, new ResourceProperties(), applicationContext);
  23. super.setMessageWriters(serverCodecConfigurer.getWriters());
  24. super.setMessageReaders(serverCodecConfigurer.getReaders());
  25. }
  26. @Override
  27. protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
  28. return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
  29. }
  30. private Mono<ServerResponse> renderErrorResponse(ServerRequest serverRequest) {
  31. ErrorAttributeOptions errorAttributes = ErrorAttributeOptions.of(ErrorAttributeOptions.Include.MESSAGE);
  32. Map<String, Object> errorAttributesMap = getErrorAttributes(serverRequest, errorAttributes);
  33. log.info("errorAttributesMap : " + errorAttributesMap);
  34. return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR)
  35. .contentType(MediaType.APPLICATION_JSON)
  36. .body(BodyInserters.fromValue(errorAttributesMap.get("message")));
  37. }
  38. }

问题是,尽管我明确只定义了 ErrorAttributeOptions 的消息部分,但我的终端仍然有堆栈跟踪。我的当前版本是 Spring Boot 2.3.1.RELEASE。在之前的版本(2.1.1)中,我没有这个问题,因为我使用了以下代码:

  1. package com.learnreactivespring.exception;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
  4. import org.springframework.boot.autoconfigure.web.ResourceProperties;
  5. import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
  6. import org.springframework.boot.web.reactive.error.ErrorAttributes;
  7. import org.springframework.context.ApplicationContext;
  8. import org.springframework.http.HttpStatus;
  9. import org.springframework.http.MediaType;
  10. import org.springframework.http.codec.ServerCodecConfigurer;
  11. import org.springframework.stereotype.Component;
  12. import org.springframework.web.reactive.function.BodyInserters;
  13. import org.springframework.web.reactive.function.server.*;
  14. import reactor.core.publisher.Mono;
  15. import java.util.Map;
  16. @Component
  17. @Slf4j
  18. public class FunctionalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
  19. public FunctionalErrorWebExceptionHandler(ErrorAttributes errorAttributes,
  20. ApplicationContext applicationContext,
  21. ServerCodecConfigurer serverCodecConfigurer) {
  22. super(errorAttributes, new ResourceProperties(), applicationContext);
  23. super.setMessageWriters(serverCodecConfigurer.getWriters());
  24. super.setMessageReaders(serverCodecConfigurer.getReaders());
  25. }
  26. @Override
  27. protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
  28. return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
  29. }
  30. private Mono<ServerResponse> renderErrorResponse(ServerRequest serverRequest) {
  31. Map<String, Object> errorAttributesMap = getErrorAttributes(serverRequest, false);
  32. log.info("errorAttributesMap : " + errorAttributesMap);
  33. return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR)
  34. .contentType(MediaType.APPLICATION_JSON)
  35. .body(BodyInserters.fromObject(errorAttributesMap.get("message")));
  36. }
  37. }

现在,在升级 Spring Boot 版本后,出现了这个问题。

英文:

In my handler function I have this method

  1. public Mono&lt;ServerResponse&gt; itemsEx(ServerRequest serverRequest) {
  2. throw new RuntimeException(&quot;RuntimeException Occured&quot;);
  3. }

Now, I want to handle this exception, so I override AbstractErrorWebExceptionHandler and create this class.

  1. package com.learnreactivespring.learnreactivespring.exception;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.boot.autoconfigure.web.ResourceProperties;
  4. import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
  5. import org.springframework.boot.web.error.ErrorAttributeOptions;
  6. import org.springframework.boot.web.reactive.error.ErrorAttributes;
  7. import org.springframework.context.ApplicationContext;
  8. import org.springframework.http.HttpStatus;
  9. import org.springframework.http.MediaType;
  10. import org.springframework.http.codec.ServerCodecConfigurer;
  11. import org.springframework.stereotype.Component;
  12. import org.springframework.web.reactive.function.BodyInserters;
  13. import org.springframework.web.reactive.function.server.*;
  14. import reactor.core.publisher.Mono;
  15. import java.util.Map;
  16. @Component
  17. @Slf4j
  18. public class FunctionalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
  19. public FunctionalErrorWebExceptionHandler(ErrorAttributes errorAttributes,
  20. ApplicationContext applicationContext,
  21. ServerCodecConfigurer serverCodecConfigurer) {
  22. super(errorAttributes, new ResourceProperties(), applicationContext);
  23. super.setMessageWriters(serverCodecConfigurer.getWriters());
  24. super.setMessageReaders(serverCodecConfigurer.getReaders());
  25. }
  26. @Override
  27. protected RouterFunction&lt;ServerResponse&gt; getRoutingFunction(ErrorAttributes errorAttributes) {
  28. return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
  29. }
  30. private Mono&lt;ServerResponse&gt; renderErrorResponse(ServerRequest serverRequest) {
  31. ErrorAttributeOptions errorAttributes = ErrorAttributeOptions.of(ErrorAttributeOptions.Include.MESSAGE);
  32. Map&lt;String, Object&gt; errorAttributesMap = getErrorAttributes(serverRequest, errorAttributes);
  33. log.info(&quot;errorAttributesMap : &quot; + errorAttributesMap);
  34. return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR)
  35. .contentType(MediaType.APPLICATION_JSON)
  36. .body(BodyInserters.fromValue(errorAttributesMap.get(&quot;message&quot;)));
  37. }

The problem is, that I have still a Stacktrace in my terminal... but I explicitly defined ErrorAttributeOptions only with message.
My current version of Spring Boot is 2.3.1.RELEASE. In previous version (2.1.1) I didn't have this problem because I used to this

  1. package com.learnreactivespring.exception;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
  4. import org.springframework.boot.autoconfigure.web.ResourceProperties;
  5. import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
  6. import org.springframework.boot.web.reactive.error.ErrorAttributes;
  7. import org.springframework.context.ApplicationContext;
  8. import org.springframework.http.HttpStatus;
  9. import org.springframework.http.MediaType;
  10. import org.springframework.http.codec.ServerCodecConfigurer;
  11. import org.springframework.stereotype.Component;
  12. import org.springframework.web.reactive.function.BodyInserters;
  13. import org.springframework.web.reactive.function.server.*;
  14. import reactor.core.publisher.Mono;
  15. import java.util.Map;
  16. @Component
  17. @Slf4j
  18. public class FunctionalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
  19. public FunctionalErrorWebExceptionHandler(ErrorAttributes errorAttributes,
  20. ApplicationContext applicationContext,
  21. ServerCodecConfigurer serverCodecConfigurer) {
  22. super(errorAttributes, new ResourceProperties(), applicationContext);
  23. super.setMessageWriters(serverCodecConfigurer.getWriters());
  24. super.setMessageReaders(serverCodecConfigurer.getReaders());
  25. }
  26. @Override
  27. protected RouterFunction&lt;ServerResponse&gt; getRoutingFunction(ErrorAttributes errorAttributes) {
  28. return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
  29. }
  30. private Mono&lt;ServerResponse&gt; renderErrorResponse(ServerRequest serverRequest) {
  31. Map&lt;String, Object&gt; errorAttributesMap = getErrorAttributes(serverRequest, false);
  32. log.info(&quot;errorAttributesMap : &quot; + errorAttributesMap);
  33. return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR)
  34. .contentType(MediaType.APPLICATION_JSON)
  35. .body(BodyInserters.fromObject(errorAttributesMap.get(&quot;message&quot;)));
  36. }
  37. }

Now, after bumped version of Spring Boot this issue occured.

答案1

得分: 5

你应该使用 ErrorAttributeOptions.defaults()。但请注意,默认情况下消息始终为空(并且堆栈跟踪不存在)。

因此,您可能想要使用类似以下的内容:

  1. ErrorAttributeOptions options = ErrorAttributeOptions
  2. .defaults()
  3. .including(ErrorAttributeOptions.Include.MESSAGE)
  4. ;

如果您想要排除某些内容,可以使用 .excluding(.)

英文:

You should use ErrorAttributeOptions.defaults(). But note that by default message is always empty (and stacktrace is not present).

So you probably want to use something like this:

  1. ErrorAttributeOptions options = ErrorAttributeOptions
  2. .defaults()
  3. .including(ErrorAttributeOptions.Include.MESSAGE)
  4. ;

And use .excluding(.) if you want to exclude something.

huangapple
  • 本文由 发表于 2020年8月7日 01:48:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/63289130.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定