開発環境
- java 17
- springboot
- thymeleaf
やりたいこと
- ファイル添付を実装(しながら仕組みを学ぶ)
- ファイル保管場所:ローカル
手順
- バックグラウンド側の各ファイル操作処理を実装
- フロント側に添付ファイルのインターフェースになるフォームを実装
こちら参考に実装:ファイルのアップロード
※私は適当なjavaアプリがあったため、「アプリケーションクラスを作成する」 から部分的に移植する形で実装。Exceptionなど大体の追加ファイルはとりあえずcommonディレクトリにぶちこみ。
そのまま実装するとエラーになったので補足
ビルドは通るが実行すると失敗
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.example.プロジェクト名.common.FileSystemStorageService required a bean of type 'com.example.プロジェクト名.common.StorageProperties' that could not be found.
Action:
Consider defining a bean of type 'com.example.プロジェクト名.common.StorageProperties' in your configuration.
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
直訳
FileSystemStorageService のコンストラクターのパラメーター 0 には、「com.example.プロジェクト名.common.StorageProperties」タイプの Bean が必要でしたが、見つかりませんでした。
つまり、StorageProperties
がBeanに登録されていない。
■エラー発生箇所
FileSystemStorageService.java
@Service
public class FileSystemStorageService implements StorageService {
private final Path rootLocation;
@Autowired
public FileSystemStorageService(StorageProperties properties) { // ← 多分ここ
■エラー原因
@Autowired
を付けるとインスタンス処理を spring boot が自動で行ってくれるが、
引数で引用しようとしているStorageProperties
がBeanに登録されておらず、呼び出せない状態。
@Autowired
にインスタンス化を任せることができるのはSpringフレームワークが提供しているDIコンテナに登録されているクラスのみ。
利用したいクラスに@Component
,@Controller
,@Service
,@Repository
をつけることでDIコンテナへ登録が可能です。...引用1
■解決策
StorageProperties
クラスに@Component
を付与(ほかにも方法はあるらしい)。
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component; // 追加
@Component // 追加:ConfigurationPropertiesを付けたクラスに付けることでBeanに登録する
@ConfigurationProperties("storage") //DIコンテナに登録されたBeanに対してプロパティを設定するためのアノテーション
public class StorageProperties {
private String location = "upload-dir";
}
...
■その他
場合によってはStorageProperties.location
をget/setすためにgetter/setterが必要になる。
Lambok を使用している場合は下記で、使用しない場合は直で実装する必要がある。
import lombok.Getter; // 追加
import lombok.Setter; // 追加
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Getter // 追加
@Setter // 追加
@Component
@ConfigurationProperties("storage")
public class StorageProperties { ...
アプリ起動しファイル添付実行
■添付ファイルが保存された場所
今回は↑に記載した通りStorageProperties
クラスでファイルデータを保管するロケーションを"upload-dir"
と指定している。
public class StorageProperties {
private String location = "upload-dir";
}
確認するとプロジェクト直下に"upload-dir"
が作成され、ファイルアップロードが成功すると添付ファイル名でファイルが生成(※正しくはデータのコピー保存)されている。
【読み解き】実装を調べてみた
...は次回の投稿に