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

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

Problem with cutomizing ErrorAttributeOptions in Spring Reactive

问题

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

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

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

package com.learnreactivespring.learnreactivespring.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.*;
import reactor.core.publisher.Mono;

import java.util.Map;

@Component
@Slf4j
public class FunctionalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {

    public FunctionalErrorWebExceptionHandler(ErrorAttributes errorAttributes,
                                              ApplicationContext applicationContext,
                                              ServerCodecConfigurer serverCodecConfigurer) {
        super(errorAttributes, new ResourceProperties(), applicationContext);
        super.setMessageWriters(serverCodecConfigurer.getWriters());
        super.setMessageReaders(serverCodecConfigurer.getReaders());
    }

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);

    }

    private  Mono<ServerResponse> renderErrorResponse(ServerRequest serverRequest) {

        ErrorAttributeOptions errorAttributes = ErrorAttributeOptions.of(ErrorAttributeOptions.Include.MESSAGE);

        Map<String, Object> errorAttributesMap = getErrorAttributes(serverRequest, errorAttributes);
        log.info("errorAttributesMap : " + errorAttributesMap);

        return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue(errorAttributesMap.get("message")));

    }
}

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

package com.learnreactivespring.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.*;
import reactor.core.publisher.Mono;

import java.util.Map;

@Component
@Slf4j
public class FunctionalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {

    public FunctionalErrorWebExceptionHandler(ErrorAttributes errorAttributes,
                                              ApplicationContext applicationContext,
                                              ServerCodecConfigurer serverCodecConfigurer) {
        super(errorAttributes, new ResourceProperties(), applicationContext);
        super.setMessageWriters(serverCodecConfigurer.getWriters());
        super.setMessageReaders(serverCodecConfigurer.getReaders());
    }

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);

    }

    private  Mono<ServerResponse> renderErrorResponse(ServerRequest serverRequest) {

        Map<String, Object> errorAttributesMap = getErrorAttributes(serverRequest, false);
        log.info("errorAttributesMap : " + errorAttributesMap);

        return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromObject(errorAttributesMap.get("message")));

    }
}

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

英文:

In my handler function I have this method

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

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

package com.learnreactivespring.learnreactivespring.exception;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.*;
import reactor.core.publisher.Mono;
import java.util.Map;
@Component
@Slf4j
public class FunctionalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
public FunctionalErrorWebExceptionHandler(ErrorAttributes errorAttributes,
ApplicationContext applicationContext,
ServerCodecConfigurer serverCodecConfigurer) {
super(errorAttributes, new ResourceProperties(), applicationContext);
super.setMessageWriters(serverCodecConfigurer.getWriters());
super.setMessageReaders(serverCodecConfigurer.getReaders());
}
@Override
protected RouterFunction&lt;ServerResponse&gt; getRoutingFunction(ErrorAttributes errorAttributes) {
return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
}
private  Mono&lt;ServerResponse&gt; renderErrorResponse(ServerRequest serverRequest) {
ErrorAttributeOptions errorAttributes = ErrorAttributeOptions.of(ErrorAttributeOptions.Include.MESSAGE);
Map&lt;String, Object&gt; errorAttributesMap = getErrorAttributes(serverRequest, errorAttributes);
log.info(&quot;errorAttributesMap : &quot; + errorAttributesMap);
return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(errorAttributesMap.get(&quot;message&quot;)));
}

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

package com.learnreactivespring.exception;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.template.TemplateAvailabilityProviders;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.*;
import reactor.core.publisher.Mono;
import java.util.Map;
@Component
@Slf4j
public class FunctionalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
public FunctionalErrorWebExceptionHandler(ErrorAttributes errorAttributes,
ApplicationContext applicationContext,
ServerCodecConfigurer serverCodecConfigurer) {
super(errorAttributes, new ResourceProperties(), applicationContext);
super.setMessageWriters(serverCodecConfigurer.getWriters());
super.setMessageReaders(serverCodecConfigurer.getReaders());
}
@Override
protected RouterFunction&lt;ServerResponse&gt; getRoutingFunction(ErrorAttributes errorAttributes) {
return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
}
private  Mono&lt;ServerResponse&gt; renderErrorResponse(ServerRequest serverRequest) {
Map&lt;String, Object&gt; errorAttributesMap = getErrorAttributes(serverRequest, false);
log.info(&quot;errorAttributesMap : &quot; + errorAttributesMap);
return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromObject(errorAttributesMap.get(&quot;message&quot;)));
}
}

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

答案1

得分: 5

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

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

ErrorAttributeOptions options = ErrorAttributeOptions
	.defaults()
	.including(ErrorAttributeOptions.Include.MESSAGE)
;

如果您想要排除某些内容,可以使用 .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:

ErrorAttributeOptions options = ErrorAttributeOptions
.defaults()
.including(ErrorAttributeOptions.Include.MESSAGE)
;

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:

确定