Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to apply the PathPatternParser introduced in Spring 5?

I want to create a GET request that takes a filepath as a path variable.

As described in the Spring documentation found here, this should be possible by using the following: /resources/{*path}.

I am using Spring Boot 2.1.2 which uses Spring 5.

However when I set up my controller method like this, the request doesn't match the route. An expected matching path would be for example /resources/some/filepath which should lead the PathVariable "path" to be /some/filepath

  @GetMapping("/resources/{*path}")
  public String content(@PathVariable String path) {
    return null;
  }

I didn't find any information about any configuration that is needed in order to make use of the new PathPattern. The only other piece of information I found about this new feature is a post at Baeldung (https://www.baeldung.com/spring-5-mvc-url-matching) which doesn't mention anything about configuration. So I expect that it should work out of the box, but it doesn't.

I cloned the project mentioned in the Baeldung post. The corresponding unit tests run. When I copy the Controller method and the unit test to my project, it fails. So I expect that it has to do with configuration.

Thank you for any help.

like image 619
Lyannic Avatar asked Apr 01 '19 14:04

Lyannic


People also ask

What is the use of AntPathMatcher?

Tests whether a string matches against a pattern via a Pattern . The default Comparator implementation returned by getPatternComparator(String) .

What is Spring mvc Pathmatch matching strategy?

mvc. pathmatch. matching-strategy, that's used as "Choice of strategy for matching request paths against registered mappings".

What is ANT path matcher?

public class AntPathMatcher extends java.lang.Object implements PathMatcher. PathMatcher implementation for Ant-style path patterns. Part of this mapping code has been kindly borrowed from Apache Ant.

What is RequestMappingHandlerMapping?

RequestMappingHandlerMapping automatically searches for @RequestMapping annotations in all controller classes annotated with @Controller. In java configuration class, we need to implement WebMvcConfigurationSupport.


2 Answers

In the Common Application properties in the Spring documentation there's a property called spring.mvc.pathmatch.matching-strategy, that's used as "Choice of strategy for matching request paths against registered mappings".

The default value (up to this date) is ant-path-matcher, and since you want to use PathPattern, you'll need to write this in the application.properties file:

spring.mvc.pathmatch.matching-strategy=path-pattern-parser

like image 76
Enmanuel Rodríguez Paz Avatar answered Oct 17 '22 06:10

Enmanuel Rodríguez Paz


I was finally able to find out the reason for my problem.

Thanks to Fabien's link.

The AntPathMatcher is the default implementation for the PathMatcher. 1.10.12. Path Matching shows how to configure the PathMatcher. However the PathMatchConfigurer::setPathMatcher takes a PathMatcher as the argument and AntPathMatcher is the only implementation of PathMatcher so you can not set the PathPattern there...

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer
            .setUseSuffixPatternMatch(true)
            .setUseTrailingSlashMatch(false)
            .setUseRegisteredSuffixPatternMatch(true)
            .setPathMatcher(antPathMatcher())
            .setUrlPathHelper(urlPathHelper())
            .addPathPrefix("/api",
                    HandlerTypePredicate.forAnnotation(RestController.class));
    }

    @Bean
    public UrlPathHelper urlPathHelper() {
        //...
    }

    @Bean
    public PathMatcher antPathMatcher() {
        //...
    }

}

The only class where I found the PathPattern in the Baeldung project is the following:

@Configuration
public class CorsWebFilterConfig {

    @Bean
    CorsWebFilter corsWebFilter() {
        CorsConfiguration corsConfig = new CorsConfiguration();
        corsConfig.setAllowedOrigins(Arrays.asList("http://allowed-origin.com"));
        corsConfig.setMaxAge(8000L);
        corsConfig.addAllowedMethod("PUT");
        corsConfig.addAllowedHeader("Baeldung-Allowed");

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", corsConfig);

        return new CorsWebFilter(source);
    }

}
like image 2
Lyannic Avatar answered Oct 17 '22 05:10

Lyannic