Spring Bootを使ったJavaプロジェクトで、 bootRun
をしてから起動するまで数分かかっていた。
調べてみると、 processResources
タスクで src/main/webapp/WEB-INF
を build/build/resources/main/WEB-INF
にコピーしていたが、 src/main/webapp/WEB-INF
配下がNodeパッケージとなっており、node_modules配下のファイルコピーで時間がかかっていた。
取り急ぎ、シンボリックリンクを作って対応したのでメモ。mklinkについて調べたのはこのため。
環境
Java v8.262.10, Gradle v6.3。
シンボリックリンクの作成
build.gradle
に以下を追加。
Windowsの場合、開発者モードを有効化するか管理者権限で mklink
を実行しないとシンボリックリンクが作れないため、PowerShell経由で管理者権限で起動したコマンドプロンプトで、 mklink
を実行している。
import java.nio.file.Files final def isWindows = System.getProperty('os.name') .toLowerCase() .contains('windows') final def srcDir = 'src/main/resources/WEB-INF' task createWebInfSymbolicLink(type: Exec) { // Windowsの場合、スラッシュをバックスラッシュに置換 // FilenameUtils#separatorsToSystem(String) などでもいい def normalizePath = { isWindows ? it.replaceAll('/', '\\\\') : it } def destDir = "${projectDir}/build/resources/main/WEB-INF" def destDirFile = destDir as File def normalizedSrcDir = normalizePath("../../../${srcDir}") if (destDirFile.directory) { def destDirPath = destDirFile.toPath() // シンボリックリンクかを判定 if (Files.isSymbolicLink(destDirPath)) { // srcへのシンボリックリンクがあれば作業不要。 // ExecタスクではExecSpecを返す必要があるため、適当にechoする。 def destLink = Files.readSymbolicLink(destDirPath) if (normalizedSrcDir == destLink.toString()) { def executer = isWindows ? ['cmd', '/c'] : [] return commandLine(executer + ['echo', 'exists link']) } // シンボリックリンクでも、パスが違っていれば削除 destDirFile.delete() } else { // 実ファイルであればディレクトリを削除 destDirFile.deleteDir() } } // Windows以外であれば、lnでシンボリックリンクを作成 if (!isWindows) { return commandLine('ln', '-s', "${normalizedSrcDir}", "${destDir}") } // Windowsの場合、コマンドプロンプトからPowerShellを起動し、 // さらにPowerShellから管理者権限のコマンドプロンプトでmklinkを実行。 // 直接PowerShellを起動しても大丈夫な気がするが、 // やったことないのでとりあえずコマンドプロンプト経由で。 def arguments = [ '/c', 'mklink', '/d', normalizePath(destDir), normalizedSrcDir ] commandLine 'cmd', '/c', 'powershell', '-Command', '"Start-Process -Verb Runas"', '-FilePath', '"cmd"', '-ArgumentList', arguments.collect { /"${it}"/ }.join(',') } // processResources の後に実行するよう設定 processResources.finalizedBy createWebInfSymbolicLink
振り返り
mklink
でシンボリックリンクを作ろうとすると、やはり権限が必要になるのがネック。
今回の方法では管理者権限が必要になるので、 gradle clean
などを実行した後だとUACのポップアップが出てしまう。
ディレクトリジャンクションを使って、管理者権限なしで実行できそうなので、そのうち改良したい。