diff --git a/spring-core/src/main/java/org/springframework/util/MimeType.java b/spring-core/src/main/java/org/springframework/util/MimeType.java
index 4fbc08eb4ae0..9a5a8e233416 100644
--- a/spring-core/src/main/java/org/springframework/util/MimeType.java
+++ b/spring-core/src/main/java/org/springframework/util/MimeType.java
@@ -316,7 +316,7 @@ public boolean includes(@Nullable MimeType other) {
}
else if (getType().equals(other.getType())) {
if (getSubtype().equals(other.getSubtype())) {
- return true;
+ return parametersInclude(other);
}
if (isWildcardSubtype()) {
// Wildcard with suffix, e.g. application/*+xml
@@ -340,6 +340,37 @@ else if (getType().equals(other.getType())) {
}
return false;
}
+
+ /**
+ * Determine if the parameters in this {@code MimeType} include those
+ * of the supplied {@code MimeType}, performing case-insensitive comparisons
+ * for {@link Charset}s.
+ *
Parameters are not included when this contains more parameters than
+ * the supplied, when this contains a parameter that the supplied does not,
+ * or when they both contain the same parameter with different values.
+ * @since 5.10.0
+ */
+ private boolean parametersInclude(MimeType other) {
+ if (this.parameters.size() > other.parameters.size()) {
+ return false;
+ }
+
+ for (Map.Entry entry : this.parameters.entrySet()) {
+ String key = entry.getKey();
+ if (!other.parameters.containsKey(key)) {
+ return false;
+ }
+ if (PARAM_CHARSET.equals(key)) {
+ if (getCharset() != null && !getCharset().equals(other.getCharset()))
+ return false;
+ }
+ else if (!ObjectUtils.nullSafeEquals(entry.getValue(), other.parameters.get(key))) {
+ return false;
+ }
+ }
+
+ return true;
+ }
/**
* Indicate whether this MIME Type is compatible with the given MIME Type.
@@ -359,7 +390,7 @@ public boolean isCompatibleWith(@Nullable MimeType other) {
}
else if (getType().equals(other.getType())) {
if (getSubtype().equals(other.getSubtype())) {
- return true;
+ return parametersAreCompatibleWith(other);
}
// Wildcard with suffix? e.g. application/*+xml
if (isWildcardSubtype() || other.isWildcardSubtype()) {
@@ -382,6 +413,28 @@ else if (thisPlusIdx != -1 && otherPlusIdx != -1) {
}
return false;
}
+
+ /**
+ * Determine if the parameters in this {@code MimeType} and the supplied
+ * {@code MimeType} are compatible, performing case-insensitive comparisons
+ * for {@link Charset}s.
+ * Parameters are incompatible when they contain the same parameter
+ * with different values.
+ * @since 5.10.0
+ */
+ private boolean parametersAreCompatibleWith(MimeType other) {
+ for (Map.Entry entry : this.parameters.entrySet()) {
+ String key = entry.getKey();
+ if (PARAM_CHARSET.equals(key)) {
+ if (other.getCharset() != null && !other.getCharset().equals(getCharset()))
+ return false;
+ }
+ else if (other.parameters.containsKey(key) && !entry.getValue().equals(other.parameters.get(key)))
+ return false;
+ }
+
+ return true;
+ }
@Override
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/ProducesRequestCondition.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/ProducesRequestCondition.java
index a3c816adb54b..fae4b345eaa7 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/ProducesRequestCondition.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/condition/ProducesRequestCondition.java
@@ -178,7 +178,7 @@ public ProducesRequestCondition combine(ProducesRequestCondition other) {
* Checks if any of the contained media type expressions match the given
* request 'Content-Type' header and returns an instance that is guaranteed
* to contain matching expressions only. The match is performed via
- * {@link MediaType#isCompatibleWith(MediaType)}.
+ * {@link MediaType#includes(MediaType)}.
* @param request the current request
* @return the same instance if there are no expressions;
* or a new condition with matching expressions;
@@ -327,7 +327,7 @@ public final boolean match(List acceptedMediaTypes) {
private boolean matchMediaType(List acceptedMediaTypes) {
for (MediaType acceptedMediaType : acceptedMediaTypes) {
- if (getMediaType().isCompatibleWith(acceptedMediaType)) {
++ if (acceptedMediaType.includes(getMediaType())) {
return true;
}
}