Browse Source

Improve performance of canRead() in HttpMessageReader's

Use MimeType.WILDCARD_TYPE for faster String.equals().
Move cheaper checks to the front of the canRead implementations.

See gh-30192
pull/30318/head
James Yuzawa 2 years ago committed by rstoyanchev
parent
commit
e77faf7484
  1. 5
      spring-core/src/main/java/org/springframework/util/MimeType.java
  2. 2
      spring-core/src/main/java/org/springframework/util/MimeTypeUtils.java
  3. 4
      spring-web/src/main/java/org/springframework/http/MediaType.java
  4. 14
      spring-web/src/main/java/org/springframework/http/codec/FormHttpMessageReader.java
  5. 10
      spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java
  6. 22
      spring-web/src/main/java/org/springframework/http/codec/multipart/MultipartHttpMessageReader.java

5
spring-core/src/main/java/org/springframework/util/MimeType.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -268,7 +268,8 @@ public class MimeType implements Comparable<MimeType>, Serializable { @@ -268,7 +268,8 @@ public class MimeType implements Comparable<MimeType>, Serializable {
* @return whether the subtype is a wildcard
*/
public boolean isWildcardSubtype() {
return WILDCARD_TYPE.equals(getSubtype()) || getSubtype().startsWith("*+");
String subtype = getSubtype();
return WILDCARD_TYPE.equals(subtype) || subtype.startsWith("*+");
}
/**

2
spring-core/src/main/java/org/springframework/util/MimeTypeUtils.java

@ -181,7 +181,7 @@ public abstract class MimeTypeUtils { @@ -181,7 +181,7 @@ public abstract class MimeTypeUtils {
static {
// Not using "parseMimeType" to avoid static init cost
ALL = new MimeType("*", "*");
ALL = new MimeType(MimeType.WILDCARD_TYPE, MimeType.WILDCARD_TYPE);
APPLICATION_GRAPHQL = new MimeType("application", "graphql+json");
APPLICATION_JSON = new MimeType("application", "json");
APPLICATION_OCTET_STREAM = new MimeType("application", "octet-stream");

4
spring-web/src/main/java/org/springframework/http/MediaType.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -435,7 +435,7 @@ public class MediaType extends MimeType implements Serializable { @@ -435,7 +435,7 @@ public class MediaType extends MimeType implements Serializable {
static {
// Not using "valueOf' to avoid static init cost
ALL = new MediaType("*", "*");
ALL = new MediaType(MimeType.WILDCARD_TYPE, MimeType.WILDCARD_TYPE);
APPLICATION_ATOM_XML = new MediaType("application", "atom+xml");
APPLICATION_CBOR = new MediaType("application", "cbor");
APPLICATION_FORM_URLENCODED = new MediaType("application", "x-www-form-urlencoded");

14
spring-web/src/main/java/org/springframework/http/codec/FormHttpMessageReader.java

@ -104,12 +104,14 @@ public class FormHttpMessageReader extends LoggingCodecSupport @@ -104,12 +104,14 @@ public class FormHttpMessageReader extends LoggingCodecSupport
@Override
public boolean canRead(ResolvableType elementType, @Nullable MediaType mediaType) {
boolean multiValueUnresolved =
elementType.hasUnresolvableGenerics() &&
MultiValueMap.class.isAssignableFrom(elementType.toClass());
return ((MULTIVALUE_STRINGS_TYPE.isAssignableFrom(elementType) || multiValueUnresolved) &&
(mediaType == null || MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(mediaType)));
if (mediaType == null || MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(mediaType)) {
if (MultiValueMap.class.isAssignableFrom(elementType.toClass()) &&
elementType.hasUnresolvableGenerics()) {
return true;
}
return MULTIVALUE_STRINGS_TYPE.isAssignableFrom(elementType);
}
return false;
}
@Override

10
spring-web/src/main/java/org/springframework/http/codec/json/AbstractJackson2Decoder.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -97,15 +97,15 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple @@ -97,15 +97,15 @@ public abstract class AbstractJackson2Decoder extends Jackson2CodecSupport imple
@Override
public boolean canDecode(ResolvableType elementType, @Nullable MimeType mimeType) {
// Skip String: CharSequenceDecoder + "*/*" comes after
if (CharSequence.class.isAssignableFrom(elementType.toClass()) || !supportsMimeType(mimeType)) {
return false;
}
ObjectMapper mapper = selectObjectMapper(elementType, mimeType);
if (mapper == null) {
return false;
}
JavaType javaType = mapper.constructType(elementType.getType());
// Skip String: CharSequenceDecoder + "*/*" comes after
if (CharSequence.class.isAssignableFrom(elementType.toClass()) || !supportsMimeType(mimeType)) {
return false;
}
if (!logger.isDebugEnabled()) {
return mapper.canDeserialize(javaType);
}

22
spring-web/src/main/java/org/springframework/http/codec/multipart/MultipartHttpMessageReader.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -81,21 +81,23 @@ public class MultipartHttpMessageReader extends LoggingCodecSupport @@ -81,21 +81,23 @@ public class MultipartHttpMessageReader extends LoggingCodecSupport
return MIME_TYPES;
}
@Override
public boolean canRead(ResolvableType elementType, @Nullable MediaType mediaType) {
if (MULTIPART_VALUE_TYPE.isAssignableFrom(elementType)) {
if (mediaType == null) {
private boolean supportsMediaType(@Nullable MediaType mediaType) {
if (mediaType == null) {
return true;
}
for (MediaType supportedMediaType : MIME_TYPES) {
if (supportedMediaType.isCompatibleWith(mediaType)) {
return true;
}
for (MediaType supportedMediaType : MIME_TYPES) {
if (supportedMediaType.isCompatibleWith(mediaType)) {
return true;
}
}
}
return false;
}
@Override
public boolean canRead(ResolvableType elementType, @Nullable MediaType mediaType) {
return supportsMediaType(mediaType) && MULTIPART_VALUE_TYPE.isAssignableFrom(elementType);
}
@Override
public Flux<MultiValueMap<String, Part>> read(ResolvableType elementType,

Loading…
Cancel
Save