HttpServletRequest.getParameterMap()是否不可变?为何修改结果不一致?
HttpServletRequest.getParameterMap() 是否不可变?
案例1:修改成功的情况
@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可以被修改?
案例2:抛出异常的情况
@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; }
执行后抛出异常:
[] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: No modifications are allowed to a locked ParameterMap] with root cause
java.lang.IllegalStateException: No modifications are allowed to a locked ParameterMap
是否因为添加了代码request.getParameterMap().get("id")导致的?
问题解析
Tomcat实现的HttpServletRequest中,ParameterMap是一个支持锁定/解锁的Map实现,默认处于锁定状态,不允许修改。
案例1成功原因:
- 获取
ParameterMap实例后,调用setLocked(false)解锁,此时该实例处于可修改状态; - 执行
put("id", "b")完成修改后,调用request.getParameterMap()返回的仍是同一个实例(Tomcat的request内部会复用这个Map实例),因此能输出修改后的值。
- 获取
案例2抛出异常的原因:
- 关键就在于中间添加的
request.getParameterMap().get("id")调用。Tomcat的getParameterMap()方法实现逻辑中,每次调用都会自动将返回的ParameterMap重新锁定; - 流程是:解锁实例→调用
request.getParameterMap()→该方法返回前重新锁定Map→此时再执行put操作,Map已经回到锁定状态,因此抛出IllegalStateException。
- 关键就在于中间添加的
结论:两次案例的差异确实是因为添加了request.getParameterMap().get("id")调用,该操作触发了Tomcat对ParameterMap的重新锁定,导致后续修改失败。
内容的提问来源于stack exchange,提问作者宝开何
相关产品推荐
相关产品推荐

