2010-09-10 12 views
104

C'è un modo per ottenere il valore completo del percorso dopo che sono stati analizzati i valori requestMapping@PathVariable?Spring 3 RequestMapping: Ottieni il valore del percorso

Cioè: /{id}/{restOfTheUrl} dovrebbe essere in grado di analizzare in /1/dir1/dir2/file.htmlid=1 e restOfTheUrl=/dir1/dir2/file.html

Tutte le idee sarebbe apprezzato.

risposta

169

parte non corrispondenti dell'URL è esposto come un attributo di richiesta di nome 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, ha imparato qualcosa di nuovo – Bozho

+52

No, attributo HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE contiene il percorso completo WHOLE. – uthark

+8

uthark ha ragione. Il valore in 'restOfTheUrl' sarà l'intero percorso, non solo la parte rimanente catturata da' ** ' – dcstraw

4

Ho usato il Tuckey URLRewriteFilter per gestire elementi di percorso che contengono '/' caratteri, come non credo Spring 3 MVC li supporta ancora.

http://www.tuckey.org/

Hai messo questo filtro per la vostra applicazione, e di fornire un file di configurazione XML. In tale file vengono fornite regole di riscrittura, che è possibile utilizzare per tradurre gli elementi del percorso contenenti i caratteri '/' nei parametri di richiesta che Spring MVC può gestire correttamente utilizzando @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> 

controller metodo:

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

appena scoperto che problema corrispondente a il mio problema. Usando le costanti HandlerMapping mi è stato in grado di scritto una piccola utility per questo scopo:

/** 
* 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

Ho un problema simile e ho risolto in questo modo:

@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 
} 

Nota che req.getPathInfo() restituirà il percorso completo (con {siteCode} e {fileName}.{fileExtension}), quindi sarà necessario elaborare in modo conveniente.

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

Sì, la restOfTheUrl non restituisce valore solo necessaria, ma possiamo ottenere il valore utilizzando UriTemplate corrispondenza.

ho risolto il problema, ecco la soluzione di lavoro per il problema:

@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

Lo apprezzo molto! funziona per me .. grazie :) – shiva

1

Ecco come ho fatto. Puoi vedere come converto il file richiestoURI in un percorso del file system (di cosa tratta questa domanda SO). Bonus: e anche come rispondere con il file.

@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

Questo è stato qui un po 'ma postando questo. Potrebbe essere utile per qualcuno.

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

Il problema con questo codice è che non gestisce il prefisso servlet e il prefisso di mapping. – gavenkoa

Problemi correlati