ファイルのアップロード

ほぼサンプル通り。
Commons FileUploadをパスに通し、設定ファイルに以下を追加するだけ。

<bean id="multipartResolver"
	class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<property name="maxUploadSize" value="1024" />
</bean>

あとは、マルチパートでリクエストを飛ばせば、勝手にやってくれる。


その他メモ。

  • ファイルサイズが超過した場合、MaxUploadSizeExceededExceptionがスローされるので、これでハンドリングする。
  • CommonsMultipartResolverは、他にもいくつかプロパティがあるっぽい。
    • maxInMemorySize
    • defaultEncoding
  • サーバ側では、MultipartFileというクラスでファイルを受け取れる。MultipartFileにはファイル名とかInputStreamが取得できるインタフェースが定義されている・・・って当たり前か。


参考
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-multipart

例外のハンドリング

例外のハンドリングは、運用(ログ)にも関わるので、デフォで用意されて
いるものよりは独自に実装したいなーというわけでメモ。


手順はこれだけ。

  • HandlerExceptionResolverを実装したクラスを作成する。
    • resolveExceptionの戻り値であるModelAndViewで遷移先が決まる。
    • AbstractHandlerExceptionResolverとかその他のクラスを継承した方が色々とラクかも。
  • 設定ファイルに記述する。
<bean id="exceptionHandler" class="jp.gr.java_conf.ykhr.sptest.TekitouExceptionHandler" />


Controllerクラスのメソッドに@ExceptionHandlerを付けるような実装もできる
みたいだけど、こうするならtry-catchの方がいい気がする・・・。


詳細
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-exceptionhandlers

Controller前後に実行される共通の処理を作る

というメモ。


HandlerInterceptorかWebRequestInterceptorの実装クラスを作り、
設定ファイルに書けば、Contorollerの前後に共通の処理を挟める
ようになる。

  • 実装クラス
public class HogeInterceptor implements HandlerInterceptor {
    private static final Log log = LogFactory.getLog(HogeInterceptor.class);
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
            Object handler) throws Exception {
        log.info("preHandle");
        return true;
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, 
            Object handler, ModelAndView modelAndView) throws Exception {
        log.info("postHandle");
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
            Object handler, Exception ex) throws Exception {
        log.info("afterCompletion");
    }
}
    • HandlerInterceptorを実装しているが、全メソッドを実装する必要がない場合、HandlerInterceptorAdapterを継承した方がラク
    • afterCompletionは、Viewのレンダリングが終了したときに呼ばれる。その他のメソッドはControllerの前後。
    • WebRequestInterceptorの場合、引数がWebRequestクラスとなる。HttpServletRequest#getParameterを使ってもリクエストパラメータが取得できないが、WebRequestからだと取得できる・・・みたいだけどどうしてこんなんなってるかはまだ追い切れてない。
  • 設定ファイル
<mvc:interceptors>
    <bean class="jp.gr.java_conf.ykhr.sptest.HogeInterceptor" />
</mvc:interceptors>

特定のパスのみ実行したい場合の設定。
# マニュアルに書いてあっただけで試してない

<mvc:interceptors>
    <mvc:interceptor>
        <mapping path="/hoge/*"/>
        <bean class="jp.gr.java_conf.ykhr.sptest.HogeInterceptor" />
    </mvc:interceptor>
</mvc:interceptors>


その昔、DispatcherServletを拡張するとか思ってたが
愚かな行為だったようだ・・・。

DriverManagerDataSource

Springのデータソースの定義で指定する
org.springframework.jdbc.datasource.DriverManagerDataSource
というクラス、プールの機能とかはないちょっとしたテスト用のものだった。
http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/jdbc/datasource/DriverManagerDataSource.html


そこらへんのサンプルでちらほら使われてるけど、気付かずに本番で
この設定でいくと偉いことになりそう。


ふつーのプロジェクトならプールのパラメータとか決められてるだろうから
そんなことないだろうけど、自由なプロジェクトだけになぁ。

Spring MVC 始めました

で、前に触ったときと同じく、どうもしっくりこないなーなんて。
Struts病なんでしょうかね。

自由度高いのはうれしいけど、そうすると破綻する
プロジェクトばっかだからなぁ。


追記
ついでにMyBatis(iBATIS)も使う。

OutOfMemoryError

  • いつものOutOfMemory

java.lang.OutOfMemoryError: Java heap space

  • ちょっと違うOutOfMemory

java.lang.OutOfMemoryError: GC overhead limit exceeded

  • このときのGCログ

[Full GC [〜] GC time would exceed GCTimeLimit of 98%
・・・
[Full GC [〜] GC time is exceeding GCTimeLimit of 98%


Javaどっかからこんな感じになった?

http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html#par_gc.oom
The parallel collector will throw an OutOfMemoryError if too much time is being spent in garbage collection: if more than 98% of the total time is spent in garbage collection and less than 2% of the heap is recovered, an OutOfMemoryError will be thrown. This feature is designed to prevent applications from running for an extended period of time while making little or no progress because the heap is too small. If necessary, this feature can be disabled by adding the option -XX:-UseGCOverheadLimit to the command line.

というわけで。
この状態だと恐らくその後に死ぬっぽいしOFFにする理由もあんまないのかな。

いやんな感じだけど正しく動いちゃうコード

Calendar calendar = Calendar.getInstance();
calendar.clear();

// 2011/02/01
calendar.set(2011, Calendar.FEBRUARY, 1);
// 1ヵ月後
calendar.add(Calendar.MONDAY, 1);

System.out.printf("%1$tF", calendar);

まぁいんだけどさ・・・。
そういえば、printfってまともに使ったの初めてだなぁ(今更