SAStruts/Action/urlPattern/正規表現

SAStruts/Action/urlPattern/正規表現

urlPattern はフレームワークの表向きとしては REST 的な URL を実現するために存在している。 なので、パラメータのセパレータはスラッシュで固定になっている。

しかし、内部実装は正規表現なので、このパラメータを若干トリッキーに設定すると正規表現をが使えるようになる。

内部実装

Pattern クラスによってなんのエスケープもなく正規表現として扱われている。

URL中の値を Form にマッピングする

{hogehoge}

この記法に中括弧を使うので、正規表現の繰り返し回数の指定記述ができない。この部分は

([^/]+)

に置換されてキャプチャ対象になる。この除外対象がスラッシュになっていることがURLを設計する上でおぼえていおかないといけない部分だ。

これがソースコードである。最終的にこれによって正規表現に変換される

        public void setUrlPattern(String urlPattern) {
            if (StringUtil.isEmpty(urlPattern)) {
                return;
            }
            this.urlPattern = urlPattern;
            StringBuilder sb = new StringBuilder(50);
            char[] chars = urlPattern.toCharArray();
            int length = chars.length;
            int index = -1;
            for (int i = 0; i < length; i++) {
                if (chars[i] == '{') {
                    index = i;
                } else if (chars[i] == '}') {
                    if (index >= 0) {
                        sb.append("([^/]+)");
                        urlParamNames.add(urlPattern.substring(index + 1, i));
                        index = -1;
                    } else {
                        throw new IllegalUrlPatternRuntimeException(urlPattern);
                    }
                } else if (index < 0) {
                    sb.append(chars[i]);
                }
            }
            if (index >= 0) {
                throw new IllegalUrlPatternRuntimeException(urlPattern);
            }
            String pattern = sb.toString();
            urlPatternAllSelected = pattern.equals("([^/]+)");
            urlPatternRegexp = Pattern.compile("^" + pattern + "$");
        }

この urlPattern に正規表現が使えるようになると Apache の mod_rewrite 的な使い方ができるようになるのだが、ハマるので止めたほうがヨイ。

正規表現を利用した非標準的URL設計への対応

SEO と称した非標準的なURLへの対応が必要な場合。今回例として、スラッシュ以外のセパレータ、たとえばアンダースコアなどを使うとURLのマッチング判定に問題が出る場合がある。

同一クラス内でURLに対するパターンが完全に一意に決定できるならばアンスコでも問題はおきない。 しかし解釈が被る場合に問題がでる。

このような2つのパターンが合った場合、URLによってはどちらか判断できない状態になる

{hoge}_{piyo}
{hoge}_{piyo}_{fuga}

このような URL に対して、どっちのメソッドも合致するということである。

1_2_3

これは 2 をキャプチャする記述が強欲マッチで 3 まで取りに行くためである。

大体このようなマッチングの設定には優先度があって、優先する設定を採用するというものだと思うのだが、SAStruts はそうなっていなくて、 優先度は不定のようだ。コンパイルする度に優先度が変わる可能性があるという感じ。このへんがよくわからない。

この部分の実装ソースコードを読むと Form にマッピングする部分の括弧から括弧が正規表現の ([^/]+) に変換されることがわかっている。 スラッシュで区切ると、強欲マッチがスラッシュ前で止まるので混同しないという仕組みだ。

なので、ここにアンスコもセパレータであるという記述を書き加えればよい。 それに Form へのマッピングの目印としての記述を追加して、先読みしてこの挙動に合致する正規表現を先に作ってやればよい。

結果、このようなURLパターンを書いてやればよい。完全に Hack である。

([^/_]+)_([^/_]+)_([^/_]+)(unkounko {hoge}{piyo}{fuga} unkounko)?

変換される予定の部分を予め先に変換済状態で記述し、その後ろに意味のない正規表現をくっつけて、Formへのマッピングの目印を記述している。 後ろの部分は意味が無い(絶対に合致しない)正規表現ならばなんでもよい。

これでアンスコ区切りのパラメータにも正常にマッピングできる URLPattern が記述できた。

java/sastruts/action/urlpattern/regexp.txt · 最終更新: 2020-09-21 18:25 by ore