フォームタグの各送信ボタンでリクエストパラメータを分けたい

とりあえず、思いつく限り。

  1. HTMLの仕様を無視して、各送信ボタンをフォームタグで括る。*1
  2. 送信ボタン自体のname属性とvalue属性を利用する。
  3. JavaScriptを使う。

2.のパターンは以下の通り。

  1. 送信ボタンのvalue属性(「送信」とか「戻る」とか)で判定。
  2. 送信ボタンのname属性で判定。(「送信」のname属性は「send」、「戻る」のname属性は「ret」とか)
  3. 送信ボタンのname属性を拡張。*2

3.の拡張は以下のような感じ。


<input type="submit" name="foo=bar"...

送信ボタンを使うパターンの場合、二重送信対策で送信時にボタンをdisableすると、ボタンのパラメータが送信されなくなってしまうので、注意のこと。

*1:フォームタグが入れ子になっていたり、交差してたりするとうまくいかない

*2:仕様に沿っているのかは不明

セレクトボックスの動的な変更

親セレクトボックスが変更されると、子セレクトボックスの値が親の値に紐付く値に変更される。
WEBアプリでわりと必要になる。


var childOptions = new Object();
childOptions[""] = new Array(new Option("select parent.",""));
childOptions["foo"] = new Array(new Option("AAAAA","01"), new Option("BBBBB","02"), new Option("CCCCC","03"));
childOptions["bar"] = new Array(new Option("aaaaa","01"), new Option("bbbbb","02"), new Option("ccccc","03"));
childOptions["hoge"] = new Array(new Option("11111","01"), new Option("22222","02"));

function change() {
var form = document.forms[0];
var parent = form.parent;
var child = form.child;

child.options.length = 0;

var options = childOptions[parent.value];

for(var i=0; i<options.length; i++) {
child.options[] = options[i];
}
}

実際の動作はこんな感じ

StrutsのURLリライティングを無効化

StrutsのURLリライティングを強制的に無効化する。バッドノウハウです。
一応、ファイルアップロードやファイルダウンロードでもアプリは動いてた。

ResponseWrapper

レスポンスクラスのURLエンコードを強制的に無効化するラッパー。


import javax.servlet.http.*;

public class ResWrap extends HttpServletResponseWrapper {

public ResWrap(HttpServletResponse res) {
super(res);
}

public String encodeUrl(String url) {
return url;
}

public String encodeURL(String url) {
return url;
}

}

ResponseWrappingFilter

レスポンスにラッパーを被せるフィルタ。


import java.io.IOException;

import javax.servlet.*;

public class ResWrapFilter implements Filter {

public void init(FilterConfig config) throws ServletException {
}

public void doFilter(
ServletRequest req,
ServletResponse res,
FilterChain chain)
throws IOException, ServletException {
chain.doFilter(req, new ResWrap( (HttpServletResponse) response ) );
}

public void destroy() {
}

}

メールアドレスの正規表現…etc

メールアドレスの正規表現

一応RFC2822の規格内。改行は不可。

^[-A-Za-z0-9!#$%&'*+/=?^_`{|}~]+(\.[-A-Za-z0-9!#$%&'*+/=?^_`{|}~]+)*@[-A-Za-z0-9!#$%&'*+/=?^_`{|}~]+(\.[-A-Za-z0-9!#$%&'*+/=?^_`{|}~]+)*$

「root@localhost」とかをはじきたいなら、末尾の「*$」を「+$」。
IPアドレスをはじきたいなら、次の正規表現にマッチしたアドレスをはじけばよいと思う。(1つの正規表現での表し方は不明)

^[-A-Za-z0-9!#$%&'*+/=?^_`{|}~]+(\.[-A-Za-z0-9!#$%&'*+/=?^_`{|}~]+)*@[0-9]+(\.[0-9]+)*$

文字数の制限はRFCに載っていたか思い出せない…256文字ぐらいかな。

CSVの仕様と解析用の正規表現

仕様はこんな感じ。

  1. 値は「,」(0x2C)で区切られる。例) 値1,値2,…
  2. 値に「,」(0x2C)が含まれる場合、「"」(0x22)で囲む。例)"A,B","1,2,3",…
  3. 値に「"」(0x22)が含まれる場合、「"」をエンクォート*1して「"」で囲む。例)"a=""123""","b=""345""",…

正規表現はこんな感じ(JDK1.4の正規表現ライブラリで動作確認)

("(?:[^"]|""|\P{ASCII})*"|(?:[^,]|\P{ASCII})*),

解析用のコードはこんな感じ。


private List parse(String line) {
List list = new ArrayList();
Pattern pattern = Pattern.compile("(\"(?:[^\"]|\"\"|\\P{ASCII})*\"|(?:[^,]|\\P{ASCII})*),");
Matcher matcher = pattern.matcher(line + ",");

while (matcher.find())
list.add(decode(matcher.group(1)));

return list;
}

private String decode(String value) {
Pattern pattern = Pattern.compile("^ *\"(.*)\" *");
Matcher matcher = pattern.matcher(value);

if (matcher.matches())
value = matcher.group(1);

return value.replaceAll("\"\"", "\"");
}

参考1
CSVTokenizer & CSVLine
参考2
Perlメモ

*1:「"」を2個にする