Как сериализовать многокомпонентный файловый класс в java

#java #spring #serialization #file-upload #sonarqube

#java #spring #сериализация #загрузка файла #sonarqube

Вопрос:

Кто-нибудь знает, как сериализовать org.springframework.web.multipart.MultipartFile класс

В sonarqube это проявляется как критическая проблема.

введите описание изображения здесь

Комментарии:

1. Почему ваш класс Serializable на первом месте? Либо создайте поле transient так, чтобы оно не сериализовалось, либо удалите Serializable его из своего собственного класса. Если вам действительно не нужно, чтобы он был сериализуемым, потому что вы записываете его на диск. Но нет, вы не можете сериализовать MultipartFile , если не перестроите Spring и не сделаете его сериализуемым (что, вероятно, откроет другую банку с червями).

2. Реализации Spring этого интерфейса, StandardMultipartFile и CommonsMultipartFile, являются сериализуемыми. На практике поле, вероятно, будет одним из этих и поэтому сериализуемым. Однако это не удовлетворит Sonar.

Ответ №1:

Эти правила sonarqube пытаются рассказать вам о потенциальной проблеме программирования.

Если вы не собираетесь пытаться выяснить, в чем проблема, вам следует просто полностью отключить sonarqube. Из вашего вопроса неясно, действительно ли вы хотите сериализовать класс, содержащий это поле, или вы просто хотите устранить проблему, которую показывает эта ошибка, или вы просто хотите избавиться от сообщения, не заботясь о основной проблеме, о которой оно пытается вас проинформировать.

Я хочу просто избавиться от сообщения

Просто! Просто удалите sonarqube. Гораздо приятнее, чем вводить случайные ключевые слова, которые вы не понимаете.

Я хочу знать о основной проблеме

Java имеет так называемый встроенный механизм сериализации. сериализация — это идея взять объект и превратить его в поток байтов, чтобы вы могли сохранить его в файле, отправить по сети и так далее.

Проблема в том, что MultipartFile не предназначен для сериализации. Однако класс, в котором находится это private MultipartFile file; поле, говорит, что его можно сериализовать, и в этом проблема: он говорит, что. Но это неправда.

Скорее всего, допущенная вами ошибка (если это можно так назвать, это не такая уж большая ошибка) заключается в том, что вы ошибочно пометили класс, содержащий это поле, как сериализуемый. Вы действительно сериализуете эту вещь? Я предполагаю, что это не так.

Итак, у вас действительно есть намерение сериализовать этот объект? Я предполагаю, что вы этого не делаете. Если вы явно не вызываете, например .writeObject(someInstanceOfThisclass) , для ObjectOutputStream или аналогичного, вы не сериализуете это.

У вас нет намерения сериализовать это

Одним из недостатков механизма сериализации является то, что как только супертип решает, что вы сериализуемы (выполняется с помощью реализации java.io.Serializable интерфейса), тогда вы просто сериализуемы, и вы не можете затем отметить: на самом деле, нет, я не. Итак, чтобы правильно избавиться от этого предупреждения, необходимо убедиться, что ни один ваш супертип не «расширяет Serializable». Если вы можете это сделать, сделайте это. Например, если вы решили extends HashMap , не делайте этого — вместо implements Map этого создайте поле типа HashMap и создайте однострочные реализации всех методов в Map, которые просто вызывают ваше поле hashmap.

Однако, если тип, который вы реализуете / расширяете, который сам реализует Serializable, не может быть удален из ваших супертипов, тогда есть альтернатива. Для этого добавьте следующие методы:

 private void writeObject(ObjectOutputStream out) throws IOException {
    throw new IOException("Not serializable");
}

private void readObject(ObjectInputStream in) throws IOException {
    throw new IOException("Not serializable");
}
 

делая это, из кода становится ясно, что вы явно намеревались, чтобы этот класс не был сериализуемым, и sonarqube тоже это поймет: проблема с sonarqube исчезнет, когда вы это сделаете.

На самом деле я хочу сериализовать это

Ах. Это гораздо большая проблема, так как MultipartFile не позволяет вам. Ваше единственное решение — полностью избавиться от поля multipartfile и заменить его чем-то сериализуемым (например, списком строк, массивом байтов и т. Д.) Или Написать свой собственный код для создания последовательности байтов, чтобы вы могли восстановить этот MultipartFile из этой последовательности байтов позже. Вероятно, это означает, что вам нужно сохранить все эти байты, что может быть болезненным — их может быть много.

Для этого переопределите те же методы, но фактически реализуйте что-то вместо того, чтобы генерировать это исключение. Написать свой собственный метод writeObject немного сложно, но вы можете найти множество примеров, выполнив поиск в Интернете.

Если вы на самом деле не заботитесь об этом поле, то, по-видимому, просто.. удалите поле. Зачем это нужно?

Вы могли бы пометить поле как transient . Однако это означает, что если этот объект сериализуется, а затем десериализуется, он будет null . какой смысл в том, чтобы позволить себе сериализоваться? transient в первую очередь полезен для полей, представляющих кэшированные данные, к которым обращаются только методы, которые просто (повторно) вычисляют, если поле не инициализировано. Тривиальный пример — если ваш hashCode() метод является потенциально дорогостоящей операцией.

Ответ №2:

Используйте свою собственную реализацию / абстракцию MultipartFile. Это позволит решить критическую проблему SonarQube:

 public abstract class MyMultipartFile implements MultipartFile, Serializable{

private static final long serialVersionUID = 5XXXXXXXXXXXXXXXXXXL;
 

}