Skip to content

Commit

Permalink
Direct exposure of StringBuilder instead of intermediate String
Browse files Browse the repository at this point in the history
  • Loading branch information
jhoeller authored and xcl(徐程林) committed Aug 16, 2020
1 parent 5a77cda commit 749ae7b
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 19 deletions.
Expand Up @@ -47,19 +47,17 @@
*/
public class ServerSentEventHttpMessageReader implements HttpMessageReader<Object> {

private static final DataBufferFactory bufferFactory = new DefaultDataBufferFactory();

private static final ResolvableType STRING_TYPE = ResolvableType.forClass(String.class);

private static final DataBufferFactory bufferFactory = new DefaultDataBufferFactory();


@Nullable
private final Decoder<?> decoder;

private final StringDecoder lineDecoder = StringDecoder.textPlainOnly();




/**
* Constructor without a {@code Decoder}. In this mode only {@code String}
* is supported as the data of an event.
Expand Down Expand Up @@ -171,31 +169,31 @@ else if (line.startsWith(":")) {
}
}

Object decodedData = (data != null ? decodeData(data.toString(), valueType, hints) : null);
Object decodedData = (data != null ? decodeData(data, valueType, hints) : null);

if (shouldWrap) {
if (comment != null) {
sseBuilder.comment(comment.toString().substring(0, comment.length() - 1));
sseBuilder.comment(comment.substring(0, comment.length() - 1));
}
if (decodedData != null) {
sseBuilder.data(decodedData);
}
return sseBuilder.build();
}
else {
return (decodedData);
return decodedData;
}
}

@Nullable
private Object decodeData(String data, ResolvableType dataType, Map<String, Object> hints) {
private Object decodeData(StringBuilder data, ResolvableType dataType, Map<String, Object> hints) {
if (String.class == dataType.resolve()) {
return data.substring(0, data.length() - 1);
}
if (this.decoder == null) {
throw new CodecException("No SSE decoder configured and the data is not String.");
}
byte[] bytes = data.getBytes(StandardCharsets.UTF_8);
byte[] bytes = data.toString().getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = bufferFactory.wrap(bytes); // wrapping only, no allocation
return this.decoder.decode(buffer, dataType, MediaType.TEXT_EVENT_STREAM, hints);
}
Expand All @@ -221,7 +219,6 @@ private class LimitTracker {

private int accumulated = 0;


public void afterLineParsed(String line) {
if (getMaxInMemorySize() < 0) {
return;
Expand All @@ -242,8 +239,7 @@ public void afterLineParsed(String line) {

private void raiseLimitException() {
// Do not release here, it's likely down via doOnDiscard..
throw new DataBufferLimitException(
"Exceeded limit on max bytes to buffer : " + getMaxInMemorySize());
throw new DataBufferLimitException("Exceeded limit on max bytes to buffer : " + getMaxInMemorySize());
}
}

Expand Down
Expand Up @@ -153,15 +153,15 @@ else if (data instanceof String) {
result = Flux.just(encodeText(sb + (String) data + "\n\n", mediaType, factory));
}
else {
result = encodeEvent(sb.toString(), data, dataType, mediaType, factory, hints);
result = encodeEvent(sb, data, dataType, mediaType, factory, hints);
}

return result.doOnDiscard(PooledDataBuffer.class, DataBufferUtils::release);
});
}

@SuppressWarnings("unchecked")
private <T> Flux<DataBuffer> encodeEvent(String eventContent, T data, ResolvableType dataType,
private <T> Flux<DataBuffer> encodeEvent(StringBuilder eventContent, T data, ResolvableType dataType,
MediaType mediaType, DataBufferFactory factory, Map<String, Object> hints) {

if (this.encoder == null) {
Expand All @@ -174,16 +174,13 @@ private <T> Flux<DataBuffer> encodeEvent(String eventContent, T data, Resolvable
}

private void writeField(String fieldName, Object fieldValue, StringBuilder sb) {
sb.append(fieldName);
sb.append(':');
sb.append(fieldValue.toString());
sb.append("\n");
sb.append(fieldName).append(':').append(fieldValue).append("\n");
}

private DataBuffer encodeText(CharSequence text, MediaType mediaType, DataBufferFactory bufferFactory) {
Assert.notNull(mediaType.getCharset(), "Expected MediaType with charset");
byte[] bytes = text.toString().getBytes(mediaType.getCharset());
return bufferFactory.wrap(bytes); // wrapping, not allocating
return bufferFactory.wrap(bytes); // wrapping, not allocating
}

@Override
Expand Down

0 comments on commit 749ae7b

Please sign in to comment.