Spring 3 RequestMapping: Get path value

Spr*_*key 125 spring spring-mvc request-mapping

Is there a way to get the complete path value after the requestMapping @PathVariable values have been parsed?

这就是: /{id}/{restOfTheUrl}应该可以解析/1/dir1/dir2/file.htmlid=1restOfTheUrl=/dir1/dir2/file.html

任何想法,将不胜感激.

axt*_*avt 196

URL的不匹配部分公开为名为的请求属性HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE:

@RequestMapping("/{id}/**")
public void foo(@PathVariable("id") int id, HttpServletRequest request) {
    String restOfTheUrl = (String) request.getAttribute(
        HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
    ...
}
Run Code Online (Sandbox Code Playgroud)

  • 不,属性HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE包含WHOLE匹配的路径. (59认同)
  • uthark是对的.`restOfTheUrl`中的值将是整个路径,而不仅仅是`**`捕获的剩余部分 (10认同)
  • 是的,uthark是对的.这个答案并没有解决问题. (5认同)
  • HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE是可选的,对于某些实现可能为NULL或"".request.getRequestURI()返回相同的值,不是可选的. (4认同)
  • 此解决方案不再有效且不可靠。 (2认同)

小智 45

刚发现问题对应我的问题.使用HandlerMapping常量我能够为此目的编写一个小实用程序:

/**
 * Extract path from a controller mapping. /controllerUrl/** => return matched **
 * @param request incoming request.
 * @return extracted path
 */
public static String extractPathFromPattern(final HttpServletRequest request){


    String path = (String) request.getAttribute(
            HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
    String bestMatchPattern = (String ) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);

    AntPathMatcher apm = new AntPathMatcher();
    String finalPath = apm.extractPathWithinPattern(bestMatchPattern, path);

    return finalPath;

}
Run Code Online (Sandbox Code Playgroud)


Dan*_*ida 17

这已经有一段时间了但发布了这个.可能对某人有用.

@RequestMapping( "/{id}/**" )
public void foo( @PathVariable String id, HttpServletRequest request ) {
    String urlTail = new AntPathMatcher()
            .extractPathWithinPattern( "/{id}/**", request.getRequestURI() );
}
Run Code Online (Sandbox Code Playgroud)

  • 此代码的问题在于它不处理 servlet 前缀和映射前缀。 (2认同)

the*_*noh 16

基于Fabien Kruba 已经很好的答案,我认为如果**URL的部分可以通过注释作为控制器方法的参数以类似于@RequestParamand 的方式提供@PathVariable,而不是总是使用实用程序方法,那就太好了其中明确要求HttpServletRequest. 下面是一个如何实施的示例。希望有人觉得它有用。

创建注释以及参数解析器:

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WildcardParam {

    class Resolver implements HandlerMethodArgumentResolver {

        @Override
        public boolean supportsParameter(MethodParameter methodParameter) {
            return methodParameter.getParameterAnnotation(WildcardParam.class) != null;
        }

        @Override
        public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
            HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
            return request == null ? null : new AntPathMatcher().extractPathWithinPattern(
                    (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE),
                    (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE));
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

注册方法参数解析器:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new WildcardParam.Resolver());
    }

}
Run Code Online (Sandbox Code Playgroud)

使用控制器处理程序方法中的注释可以轻松访问**URL 部分:

@RestController
public class SomeController {

    @GetMapping("/**")
    public void someHandlerMethod(@WildcardParam String wildcardParam) {
        // use wildcardParam here...
    }

}
Run Code Online (Sandbox Code Playgroud)


Pet*_*der 6

您需要使用内置的pathMatcher

@RequestMapping("/{id}/**")
public void test(HttpServletRequest request, @PathVariable long id) throws Exception {
    ResourceUrlProvider urlProvider = (ResourceUrlProvider) request
            .getAttribute(ResourceUrlProvider.class.getCanonicalName());
    String restOfUrl = urlProvider.getPathMatcher().extractPathWithinPattern(
            String.valueOf(request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE)),
            String.valueOf(request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE)));
Run Code Online (Sandbox Code Playgroud)

  • 确认这适用于最新版本的Spring Boot (2认同)

sdo*_*ass 5

我使用Tuckey URLRewriteFilter来处理包含'/'字符的路径元素,因为我不认为Spring 3 MVC支持它们.

http://www.tuckey.org/

您将此过滤器放入您的应用程序,并提供XML配置文件.在该文件中,您提供了重写规则,您可以使用该规则将包含"/"字符的路径元素转换为Spring MVC可以使用@RequestParam正确处理的请求参数.

WEB-INF/web.xml文件:

<filter>
  <filter-name>UrlRewriteFilter</filter-name>
  <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<!-- map to /* -->
Run Code Online (Sandbox Code Playgroud)

WEB-INF/urlrewrite.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite
    PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN"
    "http://tuckey.org/res/dtds/urlrewrite3.0.dtd">
<urlrewrite>
  <rule>
    <from>^/(.*)/(.*)$</from>
    <to last="true">/$1?restOfTheUrl=$2</to>
</urlrewrite>
Run Code Online (Sandbox Code Playgroud)

控制器方法:

@RequestMapping("/{id}")
public void handler(@PathVariable("id") int id, @RequestParam("restOfTheUrl") String pathToFile) {
  ...
}
Run Code Online (Sandbox Code Playgroud)