Insert StringMessageConverter for SSE

Closes gh-24465
This commit is contained in:
Rossen Stoyanchev 2020-02-05 18:13:27 +00:00
parent 65c8a10fb0
commit 9aea10179b
2 changed files with 24 additions and 7 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,6 +18,8 @@ package org.springframework.web.servlet.mvc.method.annotation;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
@ -33,6 +35,7 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpResponse; import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
@ -60,6 +63,8 @@ public class ResponseBodyEmitterReturnValueHandler implements HandlerMethodRetur
private final List<HttpMessageConverter<?>> messageConverters; private final List<HttpMessageConverter<?>> messageConverters;
private final List<HttpMessageConverter<?>> sseMessageConverters;
private final ReactiveTypeHandler reactiveHandler; private final ReactiveTypeHandler reactiveHandler;
@ -72,6 +77,7 @@ public class ResponseBodyEmitterReturnValueHandler implements HandlerMethodRetur
public ResponseBodyEmitterReturnValueHandler(List<HttpMessageConverter<?>> messageConverters) { public ResponseBodyEmitterReturnValueHandler(List<HttpMessageConverter<?>> messageConverters) {
Assert.notEmpty(messageConverters, "HttpMessageConverter List must not be empty"); Assert.notEmpty(messageConverters, "HttpMessageConverter List must not be empty");
this.messageConverters = messageConverters; this.messageConverters = messageConverters;
this.sseMessageConverters = initSseConverters(messageConverters);
this.reactiveHandler = new ReactiveTypeHandler(); this.reactiveHandler = new ReactiveTypeHandler();
} }
@ -88,9 +94,22 @@ public class ResponseBodyEmitterReturnValueHandler implements HandlerMethodRetur
Assert.notEmpty(messageConverters, "HttpMessageConverter List must not be empty"); Assert.notEmpty(messageConverters, "HttpMessageConverter List must not be empty");
this.messageConverters = messageConverters; this.messageConverters = messageConverters;
this.sseMessageConverters = initSseConverters(messageConverters);
this.reactiveHandler = new ReactiveTypeHandler(registry, executor, manager); this.reactiveHandler = new ReactiveTypeHandler(registry, executor, manager);
} }
private static List<HttpMessageConverter<?>> initSseConverters(List<HttpMessageConverter<?>> converters) {
for (HttpMessageConverter<?> converter : converters) {
if (converter.canWrite(String.class, MediaType.TEXT_PLAIN)) {
return converters;
}
}
List<HttpMessageConverter<?>> result = new ArrayList<>(converters.size() + 1);
result.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
result.addAll(converters);
return result;
}
@Override @Override
public boolean supportsReturnType(MethodParameter returnType) { public boolean supportsReturnType(MethodParameter returnType) {
@ -186,7 +205,7 @@ public class ResponseBodyEmitterReturnValueHandler implements HandlerMethodRetur
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T> void sendInternal(T data, @Nullable MediaType mediaType) throws IOException { private <T> void sendInternal(T data, @Nullable MediaType mediaType) throws IOException {
for (HttpMessageConverter<?> converter : ResponseBodyEmitterReturnValueHandler.this.messageConverters) { for (HttpMessageConverter<?> converter : ResponseBodyEmitterReturnValueHandler.this.sseMessageConverters) {
if (converter.canWrite(data.getClass(), mediaType)) { if (converter.canWrite(data.getClass(), mediaType)) {
((HttpMessageConverter<T>) converter).write(data, mediaType, this.outputMessage); ((HttpMessageConverter<T>) converter).write(data, mediaType, this.outputMessage);
this.outputMessage.flush(); this.outputMessage.flush();

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,7 +16,6 @@
package org.springframework.web.servlet.mvc.method.annotation; package org.springframework.web.servlet.mvc.method.annotation;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -31,7 +30,6 @@ import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.context.request.ServletWebRequest;
@ -72,8 +70,8 @@ public class ResponseBodyEmitterReturnValueHandlerTests {
@BeforeEach @BeforeEach
public void setup() throws Exception { public void setup() throws Exception {
List<HttpMessageConverter<?>> converters = Arrays.asList( List<HttpMessageConverter<?>> converters =
new StringHttpMessageConverter(), new MappingJackson2HttpMessageConverter()); Collections.singletonList(new MappingJackson2HttpMessageConverter());
this.handler = new ResponseBodyEmitterReturnValueHandler(converters); this.handler = new ResponseBodyEmitterReturnValueHandler(converters);
this.request = new MockHttpServletRequest(); this.request = new MockHttpServletRequest();