Slim3 Source Code Reading No7 Validation
Slim3 Source Code Reading #7 - ChugokuGTUG
に参加してきました!
今回も@ttyokoyama 殿と2人だったので、まったりと進みました。
まぁ、他の方が参加していても、まったり進むのですがw
T.Yokoyamaのブログ: Slim3 Source Code Reading #7
今回はValidationです。
簡単な使い方や種類は公式にあります。
Validation - Slim3
大きく分類すると、以下のような感じ。
必須チェック
- Required
中身は単純で、nullチェックと空文字チェックだけです。
型チェック
- ByteType
- ShortType
- IntegerType
- LongType
- FloatType
- DoubleType
- NumberType
- DateType
こちらも中身は割と単純です。
例えばIntegerTypeだと、こんな感じ。
例外を投げるのは、StackTraceも生成したりするので、処理が重いと聞いたことがあるのですが、どうなのでしょう?
if (value == null || "".equals(value)) {
return null;
}
try {
String s = (String) value;
Integer.valueOf(s);
return null;
} catch (Throwable ignore) {
if (message != null) {
return message;
}
return ApplicationMessage.get(getMessageKey(), getLabel(name));
}
教えて、Javaに詳しい方!
ということで、型チェックのほとんどは上記のような処理です。
ただ、NumberTypeとDateTypeは少し違います。
例外が発生するのを確認しているのは同じですが、Integer.valueOf()の部分が異なります。
それぞれ、以下のクラスを利用しています。
ここで、ついでに話題に出たのがSimpleDateFormatのスレッドセーフ問題。
google先生に、SimpleDateFormatについて尋ねると、そのように書いてあるページが出てくるのだ。
ただ、それは随分と古い話のようで、今は違うようだ。
SimpleDateFormat にまつわるぐだぐだ話。 - kameidの備忘録 - Sharpen the Saw!
この記事の日付が2009/03/16。
恐らくSimpleDateFormatがスレッドセーフでは無かったのは、2000年ぐらいの話なのだろう。
それでも、未だにgoogle先生のトップページに来るのはSEO対策も真っ青であるw
また、SimpleDateFormatのparseについて、少し注意する必要があるようです。
@ttyokoyama 殿のBlogに詳しく書いてありますが、"2012-02-1a"は、2012-02-01として認識されます。
この挙動は少し注意してやる必要があるでしょう。
最悪、無視しても良いのかなぁとも思いますが、正規表現チェックを合わせてかけてやるなどすれば、対処できると思います。
範囲チェック
- DoubleRange
- LongRange
それぞれ、範囲に収まっているかをを確認しているだけです。
これらを利用する場合は、型チェックも合わせて利用した方が良いでしょう。
if (value == null || "".equals(value)) {
return null;
}
try {
String s = (String) value;
double doubleValue = Double.valueOf(s);
if (minimum <= doubleValue && doubleValue <= maximum) {
return null;
}
} catch (Throwable ignore) {
}
if (message != null) {
return message;
}
return ApplicationMessage.get(
getMessageKey(),
getLabel(name),
minimum,
maximum);
Double.valueOf()で例外が発生するので、エラーにはなりますが、ユーザに通知するメッセージを分けることができないためです。
まぁ、メッセージがいい加減な感じなものの場合は、型チェックせずに範囲チェックでも良いかもしれませんが・・・。
長さチェック
- Maxlength
- Minlength
これらも中身は単純で、StringにCastして、lengthを見ているだけです。
if (value == null || "".equals(value)) {
return null;
}
try {
String s = (String) value;
if (s.length() <= maxlength) {
return null;
}
} catch (Throwable ignore) {
}
if (message != null) {
return message;
}
return ApplicationMessage.get(
getMessageKey(),
getLabel(name),
maxlength);
正規表現によるチェック
こちらも中身は単純です。
java.util.regex.Matcherを利用して、正規表現にマッチするか確認しているだけです。
if (value == null || "".equals(value)) {
return null;
}
Matcher m = compiledPattern.matcher((String) value);
if (m.matches()) {
return null;
}
if (message != null) {
return message;
}
return ApplicationMessage.get(getMessageKey(), getLabel(name), pattern);
以上で、Validationは終わりです。
後、Controller周りで話題に上がったのが、IndexControllerを指定する時はPathの最後に"/"が必須であるということ。
"/"無しでもページは表示されるのですが、ログを見るかぎりでは、"/"付きでリダイレクトしているようです。
FrontControllerを読んでいる時に、"/"を探しているような処理があったけど、あれが関係しているのか・・・?