Как я могу ответить на данные тела строки без двойных кавычек, используя ResponseBodyAdvice? - PullRequest
0 голосов
/ 11 октября 2019

Я использую Springboot Framework. Мне нужно зашифровать данные тела (от JSON до зашифрованной строки). Поэтому я использовал ResponseBodyAdvice.java с @ControllerAdvice, но была проблема, что он всегда отвечает зашифрованные данные двойными кавычками (например, «привет»). Мне нужно просто ответить «привет» вместо «привет».

@Override
public Object beforeBodyWrite(...) {
response.getHeaders().set("content-type", "text/plain;charset=UTF-8");

//some codes..

String result = "hello";

return result;
}

Он отвечает "привет" (мне нужны данные без двойных кавычек)

В классе контроллера он отвечает просто привет (без двойных кавычек). См. Код ниже.


  @ApiOperation(value = "absdfasdf", produces = "text/plain")
  @GetMapping("/absd")
  public String asdfasdf() {
    return "hello";
  }

1 Ответ

0 голосов
/ 11 октября 2019

Вам необходимо проверить свои MessageConverters, чтобы убедиться, что StringMessageConverter находится перед MappingJackson2HttpMessageConverter. В противном случае JSON MessageConverter будет выбран для сериализации строки и добавления дополнительных двойных кавычек.

@Component
public class MyWebMvcConfigurer implements WebMvcConfigurer {
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // check converter order here
    }
}

В качестве следующего исходного кода пружины поток выглядит так:

  1. выберитеконвертер сообщений
  2. вызов метода beforeBodyWrite в ResponseBodyAdvice
  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);
                        }
                    }

Правда в том, что мы не можемизменить MessageConverter в ResponseBodyAdvice. Но мы можем настроить динамический 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);
    }

Запись непосредственно через ответ кажется более краткой.

    @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;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...