2023-11-11 JJUG CCC セッション資料 String Templateによる文字列補間
String Templateによる文字列補間櫻庭 祐一Java in the Box
View Slide
AgendaBackgroundJEP 459 String Templates文字列補間の危険性とCustom Template ProcessorAdvanced Usage
Background
変数を含んだ文字列連結どうしてる?1. 変数が少なければ + 演算子多くなったら StringBuilder2. String.format or java.util.Formatter3. java.text.MessageFormat
を変数で切り替えたい“Hello, World!” World+ 演算子“Hello, ” + name + “!”;StringBuildernew StringBuilder(“Hello, ”).append(name).append(“!”).toString();変数が多いとコードを読み書きしにくい ...
を変数で切り替えたい“Hello, World!” WorldString.format() or java.util.FormatterString.format(“Hello, %s”, name);new Formatter().format(“Hello, %s”, name).toString();=java.text.MessageFormatMessageFormat.format(“Hello, {0}”, name);変数が多いとフォーマット記述子と変数の対応が ...
もっと簡単にまちがいも起こしにくい方法がほしいテンプレートを使った文字列補間だからといってテンプレートエンジンを使うほどでは ...
もっと簡単にまちがいも起こしにくい方法がほしいテンプレートを使った文字列補間だからといってテンプレートエンジンを使うほどでは ...もっと手軽に汎用の文字列補間がほしいJEP 459 String Templates
JEP 459 String Templates
String Templates文字列に 変数 / 式 を埋め込み文字列補間を行う言語仕様“Hello, ” + name + “!”;STR.”Hello \{name}!”
String Templates の書き方STR.”Hello \{name}!”テンプレートプロセッサ テンプレート引数}}変数 / 式 埋め込みテンプレートプロセッサ java.lang.StringTemplate.Processor関数型インタフェース processメソッド標準で提供 STR, FMT, RAWテンプレート引数 文字列リテラルテキストブロック
java.lang.StringTemplate.STR文字列を生成する最も基本的なテンプレートプロセッサせずとも使用可能static importWBSYWBSZ453za\Y^a\Z^a\YZ^zzzWBSUPEBZ-PDBM%BUFOPX 453zzz5PEBZJTa\UPEBZ^ a\TXJUDI UPEBZHFU%BZ0G8FFL \DBTF4"563%": 46/%":l8FFLFOEzEFGBVMUl8FFLEBZz^^lzzz5PEBZJT 8FFLFOEz
java.util.FormatProcessor.FMT形式のフォーマットを使用し、Formatter文字列を生成するテンプレートプロセッサWBSYWBSZ'.5zGa\Y^Ga\Z^Ga\YZ^zzz'.5z5PEBZJTU%a\-PDBM%BUFOPX ^zz5PEBZJTzロケールを指定する場合WBSGNU'PSNBU1SPDFTTPSDSFBUF -PDBMFPG KB +1ʀGNUz5PEBZJTU"a\-PDBM%BUFOPX ^zz5PEBZJT༵z
java.lang.StringTemplate.RAW未処理の オブジェクトを生成するプロセッサStringTemplateWBSYWBSZ453za\Y^a\Z^a\YZ^z4USJOH5FNQMBUFTU3"8za\Y^a\Z^a\YZ^z453QSPDFTT TU
String Templates の動作により実行invokeDynamic453z)FMMP a\OBNF^z要素ごとに分解z)FMMP l OBNF lzz)FMMP l OBNFlz-JTU4USJOHGSBHNFOUT -JTU0CKFDUWBMVFT文字列と値を別々にまとめるWBSTU4USJOH5FNQMBUFPG GSBHNFOUT WBMVFT オブジェクト生成StringTemplate453QSPDFTT TU メソッドコールProcessor.process
Custom Template Processor文字列補間の危険性と
Custom Template Processor特定用途向け Template Processor文字列以外を返すことも可能QVCMJDJOUFSGBDF4USJOH5FNQMBUF\QVCMJDJOUFSGBDF1SPDFTTPS3 &FYUFOET5ISPXBCMF\3QSPDFTT 4USJOH5FNQMBUFTUSJOH5FNQMBUFUISPXT&TUBUJD51SPDFTTPS5 3VOUJNF&YDFQUJPOPG'VODUJPO TVQFS4USJOH5FNQMBUF FYUFOET5QSPDFTT\^^^例外を扱うのであれば をオーバーライドprocess例外を使用しない場合 をコールof
of メソッドによるカスタマイズ4USJOH5FNQMBUF1SPDFTTPS4USJOH 3VOUJNF&YDFQUJPOQSPD4USJOH5FNQMBUF1SPDFTTPSPG TU\GSBHNFOUT ͱWBMVFT Λ༻ͯ͠هड़SFUVSO^
of メソッドによるカスタマイズと同等のSTR Template Processor4USJOH5FNQMBUF1SPDFTTPS4USJOH 3VOUJNF&YDFQUJPOQSPD4USJOH5FNQMBUF1SPDFTTPSPG TU\*UFSBUPS4USJOHJUTUGSBHNFOUT JUFSBUPS WBSTCOFX4USJOH#VJMEFS JUOFYU GPS 0CKFDUPCKTUWBMVFT \TCBQQFOE PCKTCBQQFOE JUOFYU ^SFUVSOTCUP4USJOH ^
of メソッドによるカスタマイズと同等のSTR Template Processor4USJOH5FNQMBUF1SPDFTTPS4USJOH 3VOUJNF&YDFQUJPOQSPD4USJOH5FNQMBUF1SPDFTTPSPG 4USJOH5FNQMBUFJOUFSQPMBUF
of メソッドによるカスタマイズ値をすべて大文字に変換4USJOH5FNQMBUF1SPDFTTPS4USJOH 3VOUJNF&YDFQUJPOQSPD4USJOH5FNQMBUF1SPDFTTPSPG TU\WBSWBMVFTTUWBMVFT TUSFBN NBQ WWUP4USJOH UP6QQFS$BTF UP-JTU SFUVSO4USJOH5FNQMBUFJOUFSQPMBUF TUGSBHNFOUT WBMVFT^
Processor インタフェースをラムダ式で記述4USJOH5FNQMBUF1SPDFTTPS4USJOH 3VOUJNF&YDFQUJPOQSPDTU\GSBHNFOUT ͱWBMVFT Λ༻ͯ͠هड़ྫ֎Λεϩʔ͢Δ͜ͱՄSFUVSO^
Processor インタフェースをラムダ式で記述を許容しないnull Template Processor4USJOH5FNQMBUF1SPDFTTPS4USJOH /VMM1PJOUFS&YDFQUJPOQSPDTU\JG TUWBMVFT DPOUBJOT OVMM\UISPXOFX/VMM1PJOUFS&YDFQUJPO ^SFUVSOTUJOUFSQPMBUF ^
Processor インタフェースをラムダ式で記述を扱うJSON4USJOH5FNQMBUF1SPDFTTPS+40/0CKFDU 3VOUJNF&YDFQUJPOKTPO1SPDTUOFX+40/0CKFDU TUJOUFSQPMBUF Template ProcessorWBSOBNFl4BLVSBCBzWBSDJUZl5PLZPzWBSKTPOKTPO1SPDzzz\lOBNFzla\OBNF^z lDJUZzla\DJUZ^z^lzz
Custom Template Processor のユースケースJSONSQLHTML/CSS/XMLログメッセージ/エラーメッセージ...
文字列補間の危険性変数 / 式を埋め込んだ結果が不適切な表現になることがあるSQL インジェクションクロスサイトスクリプティング4USJOHRVFSZ4534&-&$5'30.1FSTPOQ8)&3&QOBNFa\OBNF^OBNFl4BLVSBCB03QOBNF4BLVSBCBzCustom Template Processor で対応可
Custom Template Processor による対応使用できない文字をエスケープ4USJOH5FNQMBUF1SPDFTTPS4USJOH 3VOUJNF&YDFQUJPO130$TU\-JTU4USJOHWBMVFTTUWBMVFT TUSFBN NBQ WWUP4USJOH SFQMBDF aaUP-JTU SFUVSO4USJOH5FNQMBUFJOUFSQPMBUF TUGSBHNFOUT WBMVFT^4USJOHOBNF4BLVSBCB03QOBNF4BLVSBCB4USJOHTRM130$4&-&$5'30.1FSTPOQ8)&3&QOBNFa\OBNF^z4&-&$5'30.1FSTPOQ8)&3&QOBNF4BLVSBCBa03QOBNFa4BLVSBCBz
Custom Template Processor による対応使用できない文字があれば例外4USJOH5FNQMBUF1SPDFTTPS4USJOH *MMFHBM"SHVNFOU&YDFQUJPO130$TU\TUWBMVFT TUSFBN NBQ WWUP4USJOH pMUFS WWDPOUBJOT pOE'JSTU JG1SFTFOU T\UISPXOFX*MMFHBM"SHVNFOU&YDFQUJPO 453*MMFHBM5FYUa\T^^SFUVSOTUJOUFSQPMBUF ^
Custom Template Processor による対応型による制限 (インスタンス生成時にチェック)SFDPSE1FSTPO 4USJOHOBNF\ίϯετϥΫλͰνΣοΫ^4USJOH5FNQMBUF1SPDFTTPS4USJOH *MMFHBM"SHVNFOU&YDFQUJPO130$TU\WBSWBMVFTTUWBMVFT TUSFBN NBQ W\JG WJOTUBODFPG1FSTPO WBSOBNF\SFUVSOOBNF^FMTF\UISPXOFX*MMFHBM"SHVNFOU&YDFQUJPO 453a\WHFU$MBTT ^a\W^^^UP-JTU SFUVSO4USJOH5FNQMBUFJOUFSQPMBUF TUGSBHNFOUT WBMVFT^
Custom Template Processor による対応型による制限 (インスタンス生成時にチェック)0,WBSQFSTPOOFX1FSTPO 4BLVSBCB4USJOHTRM130$4&-&$5'30.1FSTPOQ8)&3&QOBNFa\QFSTPO^/(WBSOBNF4BLVSBCB4USJOHTRM130$4&-&$5'30.1FSTPOQ8)&3&QOBNFa\OBNF^
Advanced Usage
の制限String Templateテンプレート引数 : 文字列リテラル テキストブロックor453)FMMP a\OBNF^z文字列リテラルテキストブロック}テンプレート引数をファイルから読み込みたい文字列リテラルを持つクラスを動的生成
動的テンプレート引数作成道具 Compiler APIClass LoaderRe ection or MethodHandle手順 1. 文字列でクラスのひな型を用意2. テンプレート引数にする文字列をひな型に埋め込み3. ひな型をコンパイル4. コンパイルしたクラスファイルをクラスロード5. リフレクションもしくは で実行MethodHandle
動的テンプレート引数作成QSJWBUFTUBUJD-JTU FYUFOET+BWB'JMF0CKFDUDSFBUF+BWB'JMF0CKFDUT 4USJOHUFNQMBUF\+BWBͷιʔεͱͳΔจࣈྻ4USJOHUFNQ4SD453QVCMJDDMBTT5FNQMBUF\QVCMJDTUBUJD4USJOH5FNQMBUFQSPDFTT 4USJOHWBSJBCMF\ SFUVSOKBWBMBOH4USJOH5FNQMBUF3"8aaaa\UFNQMBUF^aaa^^ クラスのひな型とテンプレートの埋め込みจࣈྻΛιʔεͱ͢Δ+BWB'JMF0CKFDUΛੜ͢Δ+BWB'JMF0CKFDUpMFPCKOFX4USJOH+BWB'JMF0CKFDU 5FNQMBUF UFNQ4SDSFUVSO-JTUPG pMFPCK^
動的テンプレート引数作成ίϯύΠϧ͢ΔϑΝΠϧͷ४උWBSpMFPCKTDSFBUF+BWB'JMF0CKFDUT UFNQMBUFίϯύΠϥͷऔಘ+BWB$PNQJMFSDPNQJMFS5PPM1SPWJEFSHFU4ZTUFN+BWB$PNQJMFS ԾϑΝΠϧϚωʔδϟͷऔಘWBSpMF.BOBHFSDPNQJMFSHFU4UBOEBSE'JMF.BOBHFS OVMM OVMM OVMMίϯύΠϧλεΫͷੜ+BWB$PNQJMFS$PNQJMBUJPO5BTLUBTLDPNQJMFSHFU5BTL OVMM pMF.BOBHFS OVMM -JTUPG SFMFBTF FOBCMFQSFWJFX OVMM pMFPCKTίϯύΠϧUBTLDBMM クラスのコンパイル
動的テンプレート引数作成ΫϥεͷϩʔυWBSMPBEFS$MBTT-PBEFSHFU4ZTUFN$MBTT-PBEFS WBSDMTTMPBEFSMPBE$MBTT 5FNQMBUF.FUIPEΦϒδΣΫτΛऔಘ͠ɺϦϑϨΫγϣϯͰ࣮ߦ͢ΔWBSNFUIPEDMTTHFU.FUIPE QSPDFTT 4USJOHDMBTT4USJOH5FNQMBUFEZOBNJD5FNQMBUF 4USJOH5FNQMBUFNFUIPEJOWPLF OVMM OFX0CKFDU<>\WBSJBCMF^クラスのロードと実行
動的テンプレート引数作成ϑΝΠϧ͔ΒςϯϓϨʔτΛಡΈࠐΈ4USJOHUFNQMBUFOFX4USJOH 'JMFTSFBE"MM#ZUFT 1BUIPG IFMMPUFNQಈతςϯϓϨʔτੜୈҾςϯϓϨʔτୈҾςϯϓϨʔτʹຒΊࠐΉจࣈྻWBSEZOBNJD5FNQMBUF%ZOBNJD5FNQMBUFQSPDFTT UFNQMBUF #PC%ZMBOҙͷςϯϓϨʔτϓϩηοαͰॲཧWBSSFTVMU453QSPDFTT EZOBNJD5FNQMBUF動的テンプレートの使用例
Conclusionで簡単、簡潔に文字列補間String Templateで拡張可能Custom Template Processor文字列補間の危険性もCustom Template Processor 対応可能