Browse Source

Merge branch '5.3.x'

pull/28821/head
rstoyanchev 2 years ago
parent
commit
f814fb420b
  1. 6
      spring-core/src/main/java/org/springframework/util/AntPathMatcher.java
  2. 3
      spring-core/src/test/java/org/springframework/util/AntPathMatcherTests.java
  3. 45
      spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java
  4. 14
      spring-web/src/main/java/org/springframework/web/util/pattern/CaptureVariablePathElement.java
  5. 10
      spring-web/src/main/java/org/springframework/web/util/pattern/RegexPathElement.java
  6. 19
      spring-web/src/test/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilderTests.java
  7. 3
      spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternTests.java
  8. 19
      src/docs/asciidoc/web/webmvc.adoc

6
spring-core/src/main/java/org/springframework/util/AntPathMatcher.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 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.
@ -705,8 +705,8 @@ public class AntPathMatcher implements PathMatcher { @@ -705,8 +705,8 @@ public class AntPathMatcher implements PathMatcher {
else {
this.exactMatch = false;
patternBuilder.append(quote(pattern, end, pattern.length()));
this.pattern = (this.caseSensitive ? Pattern.compile(patternBuilder.toString()) :
Pattern.compile(patternBuilder.toString(), Pattern.CASE_INSENSITIVE));
this.pattern = Pattern.compile(patternBuilder.toString(),
Pattern.DOTALL | (this.caseSensitive ? 0 : Pattern.CASE_INSENSITIVE));
}
}

3
spring-core/src/test/java/org/springframework/util/AntPathMatcherTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 the original author or authors.
* Copyright 2002-2022 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.
@ -131,6 +131,7 @@ class AntPathMatcherTests { @@ -131,6 +131,7 @@ class AntPathMatcherTests {
assertThat(pathMatcher.match("/{bla}.*", "/testing.html")).isTrue();
assertThat(pathMatcher.match("/{bla}", "//x\ny")).isTrue();
assertThat(pathMatcher.match("/{var:.*}", "/x\ny")).isTrue();
}
@Test

45
spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilder.java

@ -520,7 +520,7 @@ public class Jackson2ObjectMapperBuilder { @@ -520,7 +520,7 @@ public class Jackson2ObjectMapperBuilder {
}
/**
* Specify one or more modules to be registered with the {@link ObjectMapper}.
* Specify the modules to be registered with the {@link ObjectMapper}.
* <p>Multiple invocations are not additive, the last one defines the modules to
* register.
* <p>Note: If this is set, no finding of modules is going to happen - not by
@ -537,15 +537,9 @@ public class Jackson2ObjectMapperBuilder { @@ -537,15 +537,9 @@ public class Jackson2ObjectMapperBuilder {
}
/**
* Set a complete list of modules to be registered with the {@link ObjectMapper}.
* <p>Multiple invocations are not additive, the last one defines the modules to
* register.
* <p>Note: If this is set, no finding of modules is going to happen - not by
* Jackson, and not by Spring either (see {@link #findModulesViaServiceLoader}).
* As a consequence, specifying an empty list here will suppress any kind of
* module detection.
* <p>Specify either this or {@link #modulesToInstall}, not both.
* Variant of {@link #modules(Module...)} with a {@link List}.
* @see #modules(Module...)
* @see #modules(Consumer)
* @see com.fasterxml.jackson.databind.Module
*/
public Jackson2ObjectMapperBuilder modules(List<Module> modules) {
@ -555,6 +549,22 @@ public class Jackson2ObjectMapperBuilder { @@ -555,6 +549,22 @@ public class Jackson2ObjectMapperBuilder {
return this;
}
/**
* Variant of {@link #modules(Module...)} with a {@link Consumer} for full
* control over the underlying list of modules.
* @since 6.0
* @see #modules(Module...)
* @see #modules(List)
* @see com.fasterxml.jackson.databind.Module
*/
public Jackson2ObjectMapperBuilder modules(Consumer<List<Module>> consumer) {
this.modules = (this.modules != null ? this.modules : new ArrayList<>());
this.findModulesViaServiceLoader = false;
this.findWellKnownModules = false;
consumer.accept(this.modules);
return this;
}
/**
* Specify one or more modules to be registered with the {@link ObjectMapper}.
* <p>Multiple invocations are not additive, the last one defines the modules
@ -565,6 +575,7 @@ public class Jackson2ObjectMapperBuilder { @@ -565,6 +575,7 @@ public class Jackson2ObjectMapperBuilder {
* allowing to eventually override their configuration.
* <p>Specify either this or {@link #modules(Module...)}, not both.
* @since 4.1.5
* @see #modulesToInstall(Consumer)
* @see #modulesToInstall(Class...)
* @see com.fasterxml.jackson.databind.Module
*/
@ -574,6 +585,21 @@ public class Jackson2ObjectMapperBuilder { @@ -574,6 +585,21 @@ public class Jackson2ObjectMapperBuilder {
return this;
}
/**
* Variant of {@link #modulesToInstall(Module...)} with a {@link Consumer}
* for full control over the underlying list of modules.
* @since 6.0
* @see #modulesToInstall(Module...)
* @see #modulesToInstall(Class...)
* @see com.fasterxml.jackson.databind.Module
*/
public Jackson2ObjectMapperBuilder modulesToInstall(Consumer<List<Module>> consumer) {
this.modules = (this.modules != null ? this.modules : new ArrayList<>());
this.findWellKnownModules = true;
consumer.accept(this.modules);
return this;
}
/**
* Specify one or more modules by class to be registered with
* the {@link ObjectMapper}.
@ -585,6 +611,7 @@ public class Jackson2ObjectMapperBuilder { @@ -585,6 +611,7 @@ public class Jackson2ObjectMapperBuilder {
* allowing to eventually override their configuration.
* <p>Specify either this or {@link #modules(Module...)}, not both.
* @see #modulesToInstall(Module...)
* @see #modulesToInstall(Consumer)
* @see com.fasterxml.jackson.databind.Module
*/
@SafeVarargs

14
spring-web/src/main/java/org/springframework/web/util/pattern/CaptureVariablePathElement.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 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.
@ -59,15 +59,9 @@ class CaptureVariablePathElement extends PathElement { @@ -59,15 +59,9 @@ class CaptureVariablePathElement extends PathElement {
}
else {
this.variableName = new String(captureDescriptor, 1, colon - 1);
if (caseSensitive) {
this.constraintPattern = Pattern.compile(
new String(captureDescriptor, colon + 1, captureDescriptor.length - colon - 2));
}
else {
this.constraintPattern = Pattern.compile(
new String(captureDescriptor, colon + 1, captureDescriptor.length - colon - 2),
Pattern.CASE_INSENSITIVE);
}
this.constraintPattern = Pattern.compile(
new String(captureDescriptor, colon + 1, captureDescriptor.length - colon - 2),
Pattern.DOTALL | (caseSensitive ? 0 : Pattern.CASE_INSENSITIVE));
}
}

10
spring-web/src/main/java/org/springframework/web/util/pattern/RegexPathElement.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2022 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.
@ -108,12 +108,8 @@ class RegexPathElement extends PathElement { @@ -108,12 +108,8 @@ class RegexPathElement extends PathElement {
}
patternBuilder.append(quote(text, end, text.length()));
if (this.caseSensitive) {
return Pattern.compile(patternBuilder.toString());
}
else {
return Pattern.compile(patternBuilder.toString(), Pattern.CASE_INSENSITIVE);
}
return Pattern.compile(patternBuilder.toString(),
Pattern.DOTALL | (this.caseSensitive ? 0 : Pattern.CASE_INSENSITIVE));
}
public List<String> getVariableNames() {

19
spring-web/src/test/java/org/springframework/http/converter/json/Jackson2ObjectMapperBuilderTests.java

@ -240,6 +240,16 @@ class Jackson2ObjectMapperBuilderTests { @@ -240,6 +240,16 @@ class Jackson2ObjectMapperBuilderTests {
assertThat(serializers.findSerializer(null, SimpleType.construct(Integer.class), null)).isSameAs(serializer1);
}
@Test
void modulesWithConsumer() {
NumberSerializer serializer1 = new NumberSerializer(Integer.class);
SimpleModule module = new SimpleModule();
module.addSerializer(Integer.class, serializer1);
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().modules(list -> list.add(module) ).build();
Serializers serializers = getSerializerFactoryConfig(objectMapper).serializers().iterator().next();
assertThat(serializers.findSerializer(null, SimpleType.construct(Integer.class), null)).isSameAs(serializer1);
}
@Test
void modulesToInstallByClass() {
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json()
@ -258,6 +268,15 @@ class Jackson2ObjectMapperBuilderTests { @@ -258,6 +268,15 @@ class Jackson2ObjectMapperBuilderTests {
assertThat(serializers.findSerializer(null, SimpleType.construct(Integer.class), null).getClass()).isSameAs(CustomIntegerSerializer.class);
}
@Test
void modulesToInstallWithConsumer() {
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json()
.modulesToInstall(list -> list.add(new CustomIntegerModule()))
.build();
Serializers serializers = getSerializerFactoryConfig(objectMapper).serializers().iterator().next();
assertThat(serializers.findSerializer(null, SimpleType.construct(Integer.class), null).getClass()).isSameAs(CustomIntegerSerializer.class);
}
@Test
void wellKnownModules() throws JsonProcessingException, UnsupportedEncodingException {
ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().build();

3
spring-web/src/test/java/org/springframework/web/util/pattern/PathPatternTests.java

@ -301,6 +301,7 @@ public class PathPatternTests { @@ -301,6 +301,7 @@ public class PathPatternTests {
checkCapture("{var:f o}","f%20o","var","f o"); // constraint is expressed in non encoded form
checkCapture("{var:f.o}","f%20o","var","f o");
checkCapture("{var:f\\|o}","f%7co","var","f|o");
checkCapture("{var:.*}","x\ny","var","x\ny");
}
@Test
@ -320,6 +321,8 @@ public class PathPatternTests { @@ -320,6 +321,8 @@ public class PathPatternTests {
checkCapture("/{var1}_ _{var2}","/f%20o_%20_f%7co","var1","f o","var2","f|o");
checkCapture("/{var1}_ _{var2:f\\|o}","/f%20o_%20_f%7co","var1","f o","var2","f|o");
checkCapture("/{var1:f o}_ _{var2:f\\|o}","/f%20o_%20_f%7co","var1","f o","var2","f|o");
checkCapture("/{var1:f o}_ _{var2:f\\|o}","/f%20o_%20_f%7co","var1","f o","var2","f|o");
checkCapture("/{var1}_{var2}","/f\noo_foo","var1","f\noo","var2","foo");
}
@Test

19
src/docs/asciidoc/web/webmvc.adoc

@ -650,7 +650,7 @@ See <<mvc-config-interceptors>> in the section on MVC configuration for examples @@ -650,7 +650,7 @@ See <<mvc-config-interceptors>> in the section on MVC configuration for examples
configure interceptors. You can also register them directly by using setters on individual
`HandlerMapping` implementations.
Note that `postHandle` is less useful with `@ResponseBody` and `ResponseEntity` methods for
`postHandle` method is less useful with `@ResponseBody` and `ResponseEntity` methods for
which the response is written and committed within the `HandlerAdapter` and before
`postHandle`. That means it is too late to make any changes to the response, such as adding
an extra header. For such scenarios, you can implement `ResponseBodyAdvice` and either
@ -659,6 +659,7 @@ declare it as an <<mvc-ann-controller-advice>> bean or configure it directly on @@ -659,6 +659,7 @@ declare it as an <<mvc-ann-controller-advice>> bean or configure it directly on
[[mvc-exceptionhandlers]]
=== Exceptions
[.small]#<<web-reactive.adoc#webflux-dispatcher-exceptions, WebFlux>>#
@ -5397,7 +5398,6 @@ the following example shows: @@ -5397,7 +5398,6 @@ the following example shows:
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LocaleChangeInterceptor());
registry.addInterceptor(new ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*");
}
}
----
@ -5411,7 +5411,6 @@ the following example shows: @@ -5411,7 +5411,6 @@ the following example shows:
override fun addInterceptors(registry: InterceptorRegistry) {
registry.addInterceptor(LocaleChangeInterceptor())
registry.addInterceptor(ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**")
registry.addInterceptor(SecurityInterceptor()).addPathPatterns("/secure/*")
}
}
----
@ -5427,13 +5426,19 @@ The following example shows how to achieve the same configuration in XML: @@ -5427,13 +5426,19 @@ The following example shows how to achieve the same configuration in XML:
<mvc:exclude-mapping path="/admin/**"/>
<bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/secure/*"/>
<bean class="org.example.SecurityInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
----
NOTE: Mapped interceptors are not ideally suited as a security layer due to the potential
for a mismatch with annotated controller path matching, which can also match trailing
slashes and path extensions transparently, along with other path matching options. Many
of these options have been deprecated but the potential for a mismatch remains.
Generally, we recommend using Spring Security which includes a dedicated
https://docs.spring.io/spring-security/reference/servlet/integrations/mvc.html#mvc-requestmatcher[MvcRequestMatcher]
to align with Spring MVC path matching and also has a security firewall that blocks many
unwanted characters in URL paths.
[[mvc-config-content-negotiation]]

Loading…
Cancel
Save