Spring MVC - 如何在Spring控制器中将所有请求参数放入一个map中?

228

示例URL:

../search/?attr1=value1&attr2=value2&attr4=value4

我不知道attr1、att2和attr4的名称。

我想要能够做类似这样的事情(或者类似的,不用在意,只要我能访问请求参数名与值的映射即可:

@RequestMapping(value = "/search/{parameters}", method = RequestMethod.GET)
public void search(HttpServletRequest request, 
@PathVariable Map<String,String> allRequestParams, ModelMap model)
throws Exception {//TODO: implement}

我该如何在Spring MVC中实现这个?

10个回答

360
虽然其他答案是正确的,但直接使用HttpServletRequest对象并不符合“Spring方式”。如果您熟悉Spring MVC,答案实际上非常简单且符合您的预期。具体请查看RequestParam文档
@RequestMapping(value = {"/search/", "/search"}, method = RequestMethod.GET)
public String search(
@RequestParam Map<String,String> allRequestParams, ModelMap model) {
   return "viewName";
}

61
如果您想处理列表值,例如来自具有相同名称的一组复选框,请使用:@RequestParam MultiValueMap<String, String> - IcedDante
1
谢谢。您也可以使用标题完成相同的操作:https://dev59.com/PWIk5IYBdhLWcg3wI7AF#19556291 - Rob Worsnop
4
仅当请求方法为GET或POST时才有效,无法处理PUT、DELETE等请求方法。 - Georgios Syngouroglou
1
@typelogic ModelMap 不是必需品,可以将所有请求参数作为映射获取;这仅是针对 OP 代码的特定细节。 - xlm
参数缩进会更好 - IndustryUser1942
显示剩余2条评论

37

编辑

有人指出,存在(至少在3.0版本中)一种纯Spring MVC机制可以获取这些数据。我不会在这里详细说明,因为这是另一个用户的答案。请参阅@AdamGent的答案了解详情,并不要忘记点赞。

在Spring 3.2文档中,这种机制在RequestMapping JavaDoc页面和RequestParam JavaDoc页面上都有提到,但在之前的版本中,只有在RequestMapping页面中提到。在2.5文档中没有提到这种机制。

这可能是大多数开发人员首选的方法,因为它消除了对由servlet-api jar定义的HttpServletRequest对象的(至少这种)绑定。

/编辑

您应该可以通过request.getQueryString()访问请求查询字符串。

除了使用getQueryString,还可以从request.getParameterMap()中作为Map检索查询参数。


14
我怀疑有人因为getQueryString返回的是一个字符串而不是一个映射表(downvoted)这个回答。OP正在寻找参数映射表。我在你的答案中添加了getParameterMap以帮助使其更正确 :) +1 - jamesmortensen
我点了踩是因为这不是 Spring MVC 的做法。@RequestParam 可以很愉快地将 Map 作为参数使用(请参见我的答案)。 - Adam Gent
@AdamGent 这个问题是在Spring 3.2发布之前提出的。回去看看3.1的JavaDoc,你会注意到没有提到利用@RequestParam来检索所有查询字符串参数的Map<String,String>。请不要对这里的答案感到太过厌恶...它们并没有那么糟糕:) http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/bind/annotation/RequestParam.html - nicholas.hauschild
我认为它在3.1版本中存在,但没有JavaDoc记录。我并没有说我感到憎恶,而是震惊于没有采用@RequestParam Map<>的方式。我有些烦恼,因为我看到许多现代项目都使用Spring MVC(spring 3.1及更高版本),他们会在每个方法上放置HttpServletRequest和HttpServletResponse。似乎这是因为初级开发人员使用StackOverflow和Google而不是查看文档。这使得Spring项目难以从servlet API切换到Netty API。JAX-RS也存在类似的滥用问题,但程度要轻得多。 - Adam Gent
1
而且它在3.1版本中已经进行了JavaDoc,只是没有在所有正确的位置:“此外,@RequestParam可以用于Map <String,String>或MultiValueMap <String,String>方法参数,以访问所有请求参数”。实际上,它一直延续到3.0版本(我知道我在3.1之前就用过它)。我的烦恼仍然存在,因为人们没有费心去做研究:) - Adam Gent
@AdamGent 好的,我更喜欢3.2中的文档方式,因为它似乎更加清晰。编辑后提交。 - nicholas.hauschild

19

这里是一个简单的例子,演示如何将requestParams获取到一个Map中:

@RequestMapping(value="submitForm.html", method=RequestMethod.POST)
public ModelAndView submitForm(@RequestParam Map<String, String> reqParam) {
    String name  = reqParam.get("studentName");
    String email = reqParam.get("studentEmail");     
    ModelAndView model = new ModelAndView("AdmissionSuccess");
    model.addObject("msg", "Details submitted by you::Name: " + name
                                                + ", Email: " + email );
}

在这种情况下,它将绑定以下值:

  • studentNamename
  • studentEmailemail

2
我真的很喜欢这个答案,但是Map<String, String>似乎有问题,因为某些参数可能具有多个值。我猜Map<String, ?>或者类似的更有意义。 - Natan Cox

15

1
获取参数映射还将包含来自POST请求的表单数据。如果用户不知道查询字符串中的键,那么他们如何区分来自查询字符串的内容和来自POST正文的数据? - nicholas.hauschild
2
问题陈述称他不知道参数名称是什么。此外,我也不知道它们是什么。 ;) - nicholas.hauschild
11
在一个数据驱动的应用程序中,这个说法是有意义的。在这种应用中,客户端可以自己创建请求路径和查询字符串,应用服务器会通过使用这些路径和查询字符串作为关键字来查找相应的值(从任何类型的数据源中)。需要注意的是,在翻译过程中不能改变原文的含义。 - nicholas.hauschild
你必须了解你获取的参数,或在数据驱动型应用程序的情况下,你必须知道你正在查找什么。如果两者都不知道,那么你只能将收到的参数集传递给其他知道要查找什么的方法。 - tapasvi
显示剩余4条评论

12

您可以简单地使用这个:

Map<String, String[]> parameters = request.getParameterMap();

那应该能很好地工作


8

这里有两个接口:

  1. org.springframework.web.context.request.WebRequest
  2. org.springframework.web.context.request.NativeWebRequest

它们可以允许您通用地访问请求参数以及request/session属性,不受本地Servlet/Portlet API的限制。

例如:

@RequestMapping(value = "/", method = GET)
public List<T> getAll(WebRequest webRequest){
    Map<String, String[]> params = webRequest.getParameterMap();
    //...
}

P.S. 这里有关于可以用作控制器参数的参数文档。


谢谢,它可以工作。我可以问一下,String[] 作为值的意义是什么?我必须将其索引为0才能获取该值。 - daparic
可能会存在值数组,例如 key=val1,val2key=val1&key=val2(如果我记得没错的话,Spring 支持这两种表示法),因此你将得到包含 2 个元素的数组。 - katoquro

8

在您的控制器方法中使用org.springframework.web.context.request.WebRequest作为参数,它提供了方法getParameterMap(),其优点是您不需要依赖Servlet API,WebRequest是JavaEE模式上下文对象的一个示例。


6
我可能有些晚了,但据我所知,您正在寻找类似于这样的东西:
for(String params : Collections.list(httpServletRequest.getParameterNames())) {
    // Whatever you want to do with your map
    // Key : params
    // Value : httpServletRequest.getParameter(params)                
}

2
@SuppressWarnings("unchecked")
Map<String,String[]> requestMapper=request.getParameterMap();
JsonObject jsonObject=new JsonObject();
for(String key:requestMapper.keySet()){
    jsonObject.addProperty(key, requestMapper.get(key)[0]);
}

所有参数将被存储在jsonObject中。


0

查询参数和路径参数之间存在根本性的区别。它是这样的: www.your_domain?queryparam1=1&queryparam2=2 - 查询参数。 www.your_domain/path_param1/entity/path_param2 - 路径参数。

令人惊讶的是,在Spring MVC世界中,很多人混淆了这两者。 虽然查询参数更像是搜索的标准,但路径参数很可能唯一地标识资源。话虽如此,并不意味着您不能在URI中有多个路径参数,因为资源结构可以嵌套。例如,假设您需要特定人员的特定汽车资源:

www.my_site/customer/15/car/2 - 寻找第15位客户的第二辆汽车。

将所有路径参数放入映射中的用例是什么?当您查看URI本身时,路径参数没有“键”,这些键在映射内部将从您的@Mapping注释中获取,例如:

@GetMapping("/booking/{param1}/{param2}")

从HTTP/REST的角度来看,路径参数无法真正映射到地图上。在我看来这一切都是关于Spring的灵活性以及他们希望迎合任何开发者的心愿。

我永远不会使用地图来处理路径参数,但对于查询参数来说,它可以非常有用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接