2010-09-10 90 views
104

有沒有辦法在requestMapping@PathVariable值被分析後得到完整的路徑值?Spring 3 RequestMapping:獲取路徑值

即: /{id}/{restOfTheUrl}應該能夠解析/1/dir1/dir2/file.htmlid=1restOfTheUrl=/dir1/dir2/file.html

任何想法,將不勝感激。

回答

169

不匹配的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); 
    ... 
} 
+11

+1,學到了新東西 – Bozho 2010-09-10 19:29:21

+52

不,屬性HandlerMapping。PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE包含整個匹配路徑。 – uthark 2012-12-06 23:14:24

+8

uthark是對的。 'restOfTheUrl'中的值將是整個路徑,而不僅僅是'**'所捕獲的剩餘部分。 – dcstraw 2013-04-29 18:42:33

4

我已經使用了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 /* --> 

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> 

控制器的方法:

@RequestMapping("/{id}") 
public void handler(@PathVariable("id") int id, @RequestParam("restOfTheUrl") String pathToFile) { 
    ... 
} 
35

剛剛找到相對應的問題我的問題。使用的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; 

} 
-2

我有一個類似的問題,我用這種方式解決:

@RequestMapping(value = "{siteCode}/**/{fileName}.{fileExtension}") 
public HttpEntity<byte[]> getResource(@PathVariable String siteCode, 
     @PathVariable String fileName, @PathVariable String fileExtension, 
     HttpServletRequest req, HttpServletResponse response) throws IOException { 
    String fullPath = req.getPathInfo(); 
    // Calling http://localhost:8080/SiteXX/images/argentine/flag.jpg 
    // fullPath conentent: /SiteXX/images/argentine/flag.jpg 
} 

注意req.getPathInfo()將返回完整路徑(與{siteCode}{fileName}.{fileExtension}),所以你將不得不處理方便。

0
private final static String MAPPING = "/foo/*"; 

@RequestMapping(value = MAPPING, method = RequestMethod.GET) 
public @ResponseBody void foo(HttpServletRequest request, HttpServletResponse response) { 
    final String mapping = getMapping("foo").replace("*", ""); 
    final String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE); 
    final String restOfPath = url.replace(mapping, ""); 
    System.out.println(restOfPath); 
} 

private String getMapping(String methodName) { 
    Method methods[] = this.getClass().getMethods(); 
    for (int i = 0; i < methods.length; i++) { 
     if (methods[i].getName() == methodName) { 
      String mapping[] = methods[i].getAnnotation(RequestMapping.class).value(); 
      if (mapping.length > 0) { 
       return mapping[mapping.length - 1]; 
      } 
     } 
    } 
    return null; 
} 
2

是在restOfTheUrl沒有返回時才需要的價值,但我們可以通過UriTemplate匹配獲得的價值。

我已經解決了這個問題,所以這裏的問題可行的解決方案:

@RequestMapping("/{id}/**") 
public void foo(@PathVariable("id") int id, HttpServletRequest request) { 
String restOfTheUrl = (String) request.getAttribute(
    HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE); 
    /*We can use UriTemplate to map the restOfTheUrl*/ 
    UriTemplate template = new UriTemplate("/{id}/{value}");   
    boolean isTemplateMatched = template.matches(restOfTheUrl); 
    if(isTemplateMatched) { 
     Map<String, String> matchTemplate = new HashMap<String, String>(); 
     matchTemplate = template.match(restOfTheUrl); 
     String value = matchTemplate.get("value"); 
     /*variable `value` will contain the required detail.*/ 
    } 
} 
+0

我真的很感激!爲我工作..謝謝:) – shiva 2016-09-01 06:41:46

1

這裏是我做到了。你可以看到我如何將requestedURI轉換爲文件系統路徑(這是什麼問題)。獎金:以及如何迴應該檔案。

@RequestMapping(value = "/file/{userId}/**", method = RequestMethod.GET) 
public void serveFile(@PathVariable("userId") long userId, HttpServletRequest request, HttpServletResponse response) { 
    assert request != null; 
    assert response != null; 

    // requestURL: http://192.168.1.3:8080/file/54/documents/tutorial.pdf 
    // requestURI: /file/54/documents/tutorial.pdf 
    // servletPath: /file/54/documents/tutorial.pdf 
    // logger.debug("requestURL: " + request.getRequestURL()); 
    // logger.debug("requestURI: " + request.getRequestURI()); 
    // logger.debug("servletPath: " + request.getServletPath()); 

    String requestURI = request.getRequestURI(); 
    String relativePath = requestURI.replaceFirst("^/file/", ""); 

    Path path = Paths.get("/user_files").resolve(relativePath); 
    try { 
     InputStream is = new FileInputStream(path.toFile()); 
     org.apache.commons.io.IOUtils.copy(is, response.getOutputStream()); 
     response.flushBuffer(); 
    } catch (IOException ex) { 
     logger.error("Error writing file to output stream. Path: '" + path + "', requestURI: '" + requestURI + "'"); 
     throw new RuntimeException("IOError writing file to output stream"); 
    } 
} 
16

這已經在這裏相當長一段時間,但張貼這個。可能對某人有用。

@RequestMapping("/{id}/**") 
public void foo(@PathVariable String id, HttpServletRequest request) { 
    String urlTail = new AntPathMatcher() 
      .extractPathWithinPattern("/{id}/**", request.getRequestURI()); 
} 
+0

此代碼的問題是,它不處理servlet前綴和映射前綴。 – gavenkoa 2017-05-18 11:28:12