为了账号安全,请及时绑定邮箱和手机立即绑定

如何使用 ResponseBodyAdvice 响应不带双引号的字符串正文数据?

如何使用 ResponseBodyAdvice 响应不带双引号的字符串正文数据?

浮云间 2023-10-13 09:49:06
我使用springboot框架。我需要加密正文数据(从 json 到加密字符串)。所以我将 ResponseBodyAdvice.java 与 @ControllerAdvice 一起使用,但有一个问题,它总是用双引号响应加密数据(例如“hello”),我需要只响应 hello 而不是“hello”。@Overridepublic Object beforeBodyWrite(...) {response.getHeaders().set("content-type", "text/plain;charset=UTF-8");//some codes..String result = "hello";return result;}它响应“你好”(我需要不带双引号的数据)在控制器类中,它仅响应 hello(不带双引号)。请参阅下面的代码。  @ApiOperation(value = "absdfasdf", produces = "text/plain")  @GetMapping("/absd")  public String asdfasdf() {    return "hello";  }
查看完整描述

1 回答

?
互换的青春

TA贡献1797条经验 获得超6个赞

您需要检查您的 MessageConverters 以确保 StringMessageConverter 在 MappingJackson2HttpMessageConverter 之前。否则,将选择 JSON MessageConverter 来序列化字符串并添加额外的双引号。


@Component

public class MyWebMvcConfigurer implements WebMvcConfigurer {

    @Override

    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {

        // check converter order here

    }

}

如以下spring源码,流程为:

  1. 选择消息转换器

  2. 在 ResponseBodyAdvice 中调用 beforeBodyWrite 方法

  3. 转换消息

AbstractMessageConverterMethodProcessor.java

// choose a message converter

if (genericConverter != null ?

                        ((GenericHttpMessageConverter) converter).canWrite(targetType, valueType, selectedMediaType) :

                        converter.canWrite(valueType, selectedMediaType)) {

                    // invoke beforeBodyWrite

                    body = getAdvice().beforeBodyWrite(body, returnType, selectedMediaType,

                            (Class<? extends HttpMessageConverter<?>>) converter.getClass(),

                            inputMessage, outputMessage);

                    if (body != null) {

                        Object theBody = body;

                        LogFormatUtils.traceDebug(logger, traceOn ->

                                "Writing [" + LogFormatUtils.formatValue(theBody, !traceOn) + "]");

                        addContentDispositionHeader(inputMessage, outputMessage);

                        if (genericConverter != null) {

                            genericConverter.write(body, targetType, selectedMediaType, outputMessage);

                        }

                        else {

                            // convert message

                            ((HttpMessageConverter) converter).write(body, selectedMediaType, outputMessage);

                        }

                    }

事实是我们无法更改 ResponseBodyAdvice 中的 MessageConverter。但我们可以自定义一个Dynamic MessageConverter。例如:


public class DynamicMessageConverter implements HttpMessageConverter<Object> {


    private final HttpMessageConverter<Object> jsonConverter;

    private final HttpMessageConverter<String> stringConverter;


    public DynamicMessageConverter(HttpMessageConverter<Object> jsonConverter, HttpMessageConverter<String> stringConverter) {

        this.jsonConverter = jsonConverter;

        this.stringConverter = stringConverter;

    }


    @Override

    public boolean canWrite(Class clazz, MediaType mediaType) {

        return jsonConverter.canWrite(clazz, mediaType) || stringConverter.canWrite(clazz, mediaType);

    }


    @Override

    public List<MediaType> getSupportedMediaTypes() {

        List<MediaType> jsonMediaTypes = jsonConverter.getSupportedMediaTypes();

        List<MediaType> stringMediaTypes = stringConverter.getSupportedMediaTypes();

        List<MediaType> all = new ArrayList<>();

        all.addAll(jsonMediaTypes);

        all.addAll(stringMediaTypes);

        return all;

    }


    @Override

    public void write(Object o, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {

        if (o instanceof String) {

            stringConverter.write((String) o, contentType, outputMessage);

        } else {

            jsonConverter.write(o, contentType, outputMessage);

        }

    }


    @Override

    public boolean canRead(Class clazz, MediaType mediaType) {

        return false;

    }


    @Override

    public Object read(Class clazz, HttpInputMessage inputMessage) throws HttpMessageNotReadableException {

        throw new UnsupportedOperationException();

    }

}

然后启用它


    @Override

    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {

        MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();

        StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();

        DynamicMessageConverter dynamicMessageConverter = new DynamicMessageConverter(jsonConverter, stringConverter);

        converters.add(0, dynamicMessageConverter);

    }

直接通过response来写似乎更简洁。


    @Override

    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {

        response.getHeaders().set("content-type", "text/plain;charset=UTF-8");


        //some codes..


        String result = "hello";


        try (OutputStream stream = response.getBody()) {

            stream.write(result.getBytes("utf-8"));

            stream.flush();

        } catch (IOException e) {

            // log ex

        }

        return null;

    }


查看完整回答
反对 回复 2023-10-13
  • 1 回答
  • 0 关注
  • 244 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信