Java 11句柄不可修改的地图

Java 11 handle unmodifiable map

我有一个 class 来处理一些上传的压缩文件。 以及一种解压缩并填充 HashMap 并转换为 Collection.unmodifiableMap.

的方法
public class MyClass extends HttpServlet {

...
    private Map<String, String> rnaseqfiles = new HashMap<>();
...

    private void processZipFile(String zipfile) throws Exception {
        String fileName = zipfile;
        byte[] buffer = new byte[1024];
        try (ZipInputStream zis = new ZipInputStream(new FileInputStream(fileName))) {
            ZipEntry zipEntry = zis.getNextEntry();
            
            while (zipEntry != null) {
                File newFile = new File(diretorio, zipEntry.toString());
                if (zipEntry.isDirectory()) {
                    if (!newFile.isDirectory() && !newFile.mkdirs()) {
                        throw new IOException("Failed to create directory " + newFile);
                    }
                } else {
                    FileOutputStream fos = new FileOutputStream(newFile);
                    int len;
                    while ((len = zis.read(buffer)) > 0) {
                        fos.write(buffer, 0, len);
                    }
                    fos.close();
                    rnaseqfiles.put(zipEntry.toString(), newFile.getAbsolutePath());
                }
                zipEntry = zis.getNextEntry();
            }
            
            rnaseqfiles = Collections.unmodifiableMap(rnaseqfiles);
            
            zis.closeEntry();
            zis.close();
        }
    }
...
}

当我用一个小例子测试时,它工作得很好,但是当我用真实的例子测试时,我遇到了这种错误。

java.lang.UnsupportedOperationException
        at java.base/java.util.Collections$UnmodifiableMap.put(Collections.java:1457)

我找到了一些处理它的提示,但我不知道该怎么做。

感谢任何帮助

servlet 很烦人。想一想任何给定的 servlet 可能会 运行 多次,并且可能同时多次,因为各种用户访问您的站点。

它们是两个世界中最糟糕的:servlet 规范保证系统为每个请求初始化一个新对象(意思是,许多不同的请求,有些甚至是同时的,都使用相同的字段),但它也保证相反的情况:系统可以自由地这样做。

结论:servlet 中的字段几乎没有用。但是你有一个,它造成了麻烦:一个 'run' 用一个不可变的 hashmap 覆盖了你的可变 hashmap,然后下一个 servlet 试图向这个现在不可变的 map 添加东西。

解决方法通常是删除 servlet。现在有更好的方法来编写 Web 应用程序,例如 spark, DropWizard, Spring 和许多其他方法。

如果您坚持,那么您的 servlet 不应该有任何字段。如果你需要它们,你的 servlet 代码应该简单地创建一个新对象,然后在那里调用你想要的任何东西——你的 doGet 和朋友大多只是 new ActualHandler(req, res).go() 或类似形式的单行者。现在每个请求实际上有一个实例。

或者,只是.. 编写代码以便不需要任何字段。例如,我不明白你为什么需要一个字段。您当前的代码可以;

  • 接收请求并解析内容(你没有粘贴这部分)
  • 该代码显然调用了 processZipFile,但 return 什么都没有,而是使用字段传回数据。 (这在 servlet 中不起作用)。
  • 您的请求处理代码然后使用该字段作为内容。

似乎很容易替换它 - 没有字段,使用 processZipFile 方法 return 映射。