Spring 3 RequestMapping:获取path值
在parsing了requestMapping
@PathVariable
值后,有没有办法获得完整的path值?
那就是: /{id}/{restOfTheUrl}
应该能够将/1/dir1/dir2/file.html
parsing为id=1
, restOfTheUrl=/dir1/dir2/file.html
任何想法,将不胜感激。
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); ... }
刚刚发现这个问题对应我的问题。 使用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; }
这已经有一段时间了,但发布了这个。 可能对某人有用。
@RequestMapping( "/{id}/**" ) public void foo( @PathVariable String id, HttpServletRequest request ) { String urlTail = new AntPathMatcher() .extractPathWithinPattern( "/{id}/**", request.getRequestURI() ); }
我使用了Tuckey的URLRewriteFilter来处理包含'/'字符的path元素,因为我不认为Spring 3 MVC支持它们。
你把这个filter放到你的应用程序中,并提供一个XMLconfiguration文件。 在该文件中,您提供了重写规则,您可以使用它来将包含“/”字符的path元素转换为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) { ... }
是的restOfTheUrl
不是只返回所需的值,但我们可以通过使用UriTemplate
匹配得到的值。
我已经解决了这个问题,所以这里的问题的工作解决scheme:
@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.*/ } }
这是我如何做到的。 你可以看到我如何将requestedURI转换为文件系统path(这是什么问题)。 奖金:以及如何回应文件。
@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"); } }
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; }
我有一个类似的问题,我以这种方式解决:
@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/SiteXXhttp://img.dovov.comargentine/flag.jpg // fullPath conentent: /SiteXXhttp://img.dovov.comargentine/flag.jpg }
请注意, req.getPathInfo()
将返回完整的path( {siteCode}
和{fileName}.{fileExtension}
),所以您将不得不进行方便的处理。