如何使用Java Stream改造XSS防护的HttpServletRequestWrapper重写代码并优化性能?
用Java Stream重构XSS防御的RequestWrapper代码并优化性能
嘿,这个需求很典型——用Java Stream确实能让这段嵌套循环+判断的代码变得更简洁清爽,同时我们也可以聊聊几个性能优化的小细节。
首先是Stream重构后的代码
@Override public Map<String, String[]> getParameterMap() { return Optional.ofNullable(super.getParameterMap()) .map(params -> params.entrySet().stream() .collect(Collectors.toMap( Map.Entry::getKey, entry -> Arrays.stream(entry.getValue()) .map(value -> StrUtil.hasEmpty(value) ? value : HtmlUtil.filter(value)) .toArray(String[]::new), (oldVal, newVal) -> newVal, LinkedHashMap::new ))) .orElseGet(LinkedHashMap::new); }
代码逻辑说明
- 用
Optional.ofNullable替代了原有的null判断,避免了生硬的if分支,代码流更流畅; - 直接遍历
entrySet()而非先取keySet再查值,减少了一次map的查找操作,效率更高; - 对每个参数值数组,用
Arrays.stream转成流后,通过map统一处理空值判断和XSS过滤,替代了原有的嵌套for循环; - 最后用
Collectors.toMap指定生成LinkedHashMap,保证和原代码一致的参数顺序。
性能优化建议
- 禁止修改原数组:原代码直接修改了
super.getParameterMap()返回的数组,而Servlet规范中getParameterMap返回的可能是不可变集合或共享数组,直接修改可能引发线程安全问题。重构后的代码生成新数组,更安全也符合规范; - 复用空集合实例:如果参数map为空,可以提前定义一个静态常量
EMPTY_PARAM_MAP(比如private static final Map<String, String[]> EMPTY_PARAM_MAP = new LinkedHashMap<>();),替代每次创建新的空LinkedHashMap,减少对象创建开销; - 优化过滤操作的开销:如果
HtmlUtil.filter是耗时操作,可以考虑对常见的安全输入做缓存(比如用Guava的LoadingCache),但要注意缓存key的设计,避免内存溢出; - 按需选择实现方式:Stream操作的可读性优势远大于其微小的性能损耗,除非经过压测证明Stream是性能瓶颈,否则推荐保留Stream版本;如果是极端高并发场景,可以回归普通循环+提前初始化数组的方式,但要做好线程安全处理。
内容的提问来源于stack exchange,提问作者Criwran
相关产品推荐
相关产品推荐

