HttpServlet请求.getParameterMap()是否不可变


@GetMapping(value = "/getSalaries")
public List getSalaries(@RequestParam(value = "id")String id, HttpServletRequest request) {
ParameterMap parameterMap = (ParameterMap) request.getParameterMap();
parameterMap.setLocked(false);
parameterMap.put("id", "b");
System.out.println(request.getParameterMap().get("id"));

return  null;
}

一切都很好,id已经更改。为什么id可以更改?

@GetMapping(value = "/getSalaries")
public List getSalaries(@RequestParam(value = "id")String id, HttpServletRequest request) {
ParameterMap parameterMap = (ParameterMap) request.getParameterMap();
parameterMap.setLocked(false);
System.out.println(request.getParameterMap().get("id"));
parameterMap.put("id", "b");
System.out.println(request.getParameterMap().get("id"));

return  null;
}

抛出异常:[]抛出异常[请求处理失败;嵌套异常为java.lang.IllegalStateException:不允许对具有根本原因的锁定ParameterMap]进行修改

java.lang.IollegalStateException:不允许对锁定的ParameterMap 进行任何修改

因为我添加了代码"request.getParameterMap((.get("id"("?

好的,所以问题是您使用ParameterMap的方式不对。

ParameterMap实际上并不是不可变的,但您应该将其视为不可变的。如果你想变异它,正确的方法是复制它,然后更改副本;例如,根据@chasingfish的回答。

正如您所观察到的,您可以调用setLocked(false)以便更新地图。但问题是,您正在更改的映射仍然与HttpServletRequest共享。当您再次调用getParameterMap()时,请求对象会很有帮助地注意到映射当前已解锁,从源请求信息中刷新它,然后再次锁定它。

您可以通过阅读源代码来了解发生了什么;例如。https://github.com/quickhack/tomcat/blob/master/src/main/java/org/apache/catalina/connector/Request.java线路1164

您可能可以处理这种Tomcat特定的行为,但我的建议是不要这样做。只需将getParameterMap()返回的对象视为不可变的。。。就像Servlet规范所说的那样。


因为我添加了代码request.getParameterMap().get("id")

不完全是。这是因为你给getParameterMap()打了两次电话。这些调用对参数映射的状态有未记录的副作用。

看起来您正试图修改接收到的表单参数Map,根据Tomcat对HTTP请求处理的解释,这是一个no。(Servlet规范3.0并没有明确说明这一点(第3章(,但强烈暗示了这一方向(只有"get"方法,没有"set"方法(。

也许你可以试试:

ParameterMap parameterMap = new HashMap(request.getParameterMap())

最新更新