Java の interface method に public や abstract を宣言してもよいか

interface MyInterface {
  public abstract void myMethod(); // public と abstract の宣言
}

Oracle の Docs より

「してもよいが、冗長なので奨められない」

意訳(一部)

interface のメソッドは暗黙のうちに public である

interface のメソッドは暗黙のうちに abstract である,
なのでブロックは持たずセミコロンで表現されている必要がある

public と abstract どちらか/両方 を interface のメソッドで宣言してもよいが、
冗長なので奨められるされるやり方ではない

意訳(一部)元

Every method declaration in the body of an interface is implicitly public.

Every method declaration in the body of an interface is implicitly abstract,
so its body is always represented by a semicolon, not a block.

It is permitted, but discouraged as a matter of style,
to redundantly specify the public and/or abstract modifier for a method declared in an interface.

struts.xml の global-exception-mappings とは何か

struts2-core v2.3.28

global-exception-mappings とは

はじめに、Struts2 には Exception mappings という機能がある

これは Action 内で throw された例外を自動的に catch

あらかじめ用意された resultマッピングする機能である

この Exception mappings

どの resultマッピングするかを定義する xml 属性が

global-exception-mappings である

2 点注意が必要

1(X)

ローカルのマッピング(action.exception-mapping)を定義できるが

これを有効化した時、グローバルのマッピング(global-exception-mappings)は無効化される

2(Y)

あくまで action#classexecute 内で発生した例外をマッピングするもので

action#classコンストラクタ内で throw された例外はマッピングされない

具体的に

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">

<struts>
  <constant name="struts.devMode" value="true" />
  <constant name="struts.ui.theme" value="simple" />
  <package name="top" extends="struts-default">
    <global-results>
      <result name="myException">/Exception.jsp</result>
    </global-results>
    <global-exception-mappings>
      <exception-mapping exception="java.lang.Exception" result="myException" />
    </global-exception-mappings>
    <action name="index" class="jp.ymatsukawa.top.Index">
      <result name="success">/index.jsp</result>
    </action>
  </package>
</struts>

/top/index.action へ GET リクエストされたとする

action#class=jp.ymatsukawa.top.IndexExceptionthrow された場合

global-exception-mappingsException を捕捉する

この時 exception-mapping#result に対応する result を実行する

上の場合だと resultmyException なので

global-results.result#name="myException" が実行される

(/Exception.jspdispatch される)

(X)

(動作確認より)

global-exception-mappings.exception-mapping を定義後

action.exceptoin-mapping を用いて

個々の actionexception-mapping を定義することができる

ただし、その場合は global-exception-mapping の設定は無効になる

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">

<struts>
  <constant name="struts.devMode" value="true" />
  <constant name="struts.ui.theme" value="simple" />
  <package name="top" extends="struts-default">
    <global-results>
      <result name="myException">/Exception.jsp</result>
    </global-results>
    <global-exception-mappings>
      <exception-mapping exception="java.sql.SQLException" result="myException" />
    </global-exception-mappings>
    <action name="index" class="jp.ymatsukawa.top.Index">
      <exception-mapping exception="java.lang.RuntimeException" result="error" />
      <result name="success">/index.jsp</result>
      <result name="error">/myError.jsp></result>
    </action>
  </package>
</struts>

もし jp.ymatsukawa.top.Index

java.sql.SQLExceptionthrow されても

/Exception.jspdispatch されず

/myError.jspdispatch される

(global-exception-mappings.exception-mapping#exception=java.lang.Exception

でハンドリングをまとめておき、個々の action

Exception 以外の例外捕捉を必要に応じて追加するのが良いか...)

(Y)

jp.ymatsukawa.top.Indexコンストラクタが 例外を throw し得る場合

global-exception-mappings はこの例外をマッピングしない

極端な例

package jp.ymatsukawa.top.Index;
import com.opensymphony.xwork2.ActionSupport;

public class Index extends ActionSupport {
  public Index() throws Exception {
    throw new Exception;
  }

  @Override
  public String execute() {
    return SUCCESS;
  }
}

この場合、Struts2 は例外マッピング、例外ハンドリングすることなく、エラー処理を実行する

[参考元]

https://struts.apache.org/docs/exception-configuration.html

struts.xml global-results 要素とは何か

struts2-core v2.3.24.1

struts.xml global-results 要素とは何か

action 間で共有したい result がある時、これを定義する為の要素

  • package ごとに global-results を定義できる
  • Struts2 は先ず ローカルの result(package.action.result)を走査する
    • ローカルで result が見つからない場合、global-results を走査する

(要素の設置順序が決まっているようなので設定ミスしないように)(X)

具体的に

或る package の result#name="error" を共通化する

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">

<struts>
  <constant name="struts.devMode" value="true" />
  <constant name="struts.ui.theme" value="simple" />
  <package name="top" extends="struts-default">
    <global-results>
      <result name="error">/error.jsp</result>
    </global-results>
    <action name="index" class="jp.ymatsukawa.top.Index">
      <result name="success">/index.jsp</result>
    </action>
  </package>
</struts>

action 要素の前に global-results を設定する

global-results の下に共通化したい result を設定する

global-results.result を action.result で上書きできるか

できる

上の例より result#name="error" の時

/error.jsp ではなく, /myError.jsp を render させたい場合は

下のように設定する

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">

<struts>
  <constant name="struts.devMode" value="true" />
  <constant name="struts.ui.theme" value="simple" />
  <package name="top" extends="struts-default">
    <global-results>
      <result name="error">/error.jsp</result>
    </global-results>
    <action name="index" class="jp.ymatsukawa.top.Index">
      <result name="error">/myError.jsp</result>
      <result name="success">/index.jsp</result>
    </action>
  </package>
</struts>

(X)要素の設定順序に注意

action の前に global-results を設定する

要素は上から順に以下の通りである

result-types?,
interceptors?,
default-interceptor-ref?,
default-action-ref?,
default-class-ref?,
global-results?,
global-allowed-methods?,
global-exception-mappings?,
action*

[参考元]

https://struts.apache.org/docs/result-configuration.html#ResultConfiguration-GlobalResults

http://stackoverflow.com/questions/3742379/struts2-global-results-configuration-error

struts.xml default-interceptor-ref 要素とは何か

default-interceptor-stack 要素とは何か

package 内で定義した interceptor-stack の内

package の各アクションにてデフォルトで参照させたい

interceptor を定義する

具体的に

下記 struts.xml より interceptor-stack に ロギングが定義されている

(action はまだ interceptor を参照していない)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">

<struts>
  <constant name="struts.devMode" value="true" />
  <constant name="struts.ui.theme" value="simple" />
  <package name="top" extends="struts-default">
    <interceptors>
      <interceptor name="myLogging" class="jp.ymatsukawa.interceptors.Logger" />
      <interceptor-stack name="myStackLogging">
        <interceptor-ref name="myLogging" />
      </interceptor-stack>
    </interceptors>
    <action name="index" class="jp.ymatsukawa.top.Index">
      <result name="success">/index.jsp</result>
    </action>
  </package>
</struts>

actionpackage.interceptors.interceptor-stack#name="mystackLogging"

が参照されることになったので default-interceptor-ref を使い、目的を達成する

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">

<struts>
  <constant name="struts.devMode" value="true" />
  <constant name="struts.ui.theme" value="simple" />
  <package name="top" extends="struts-default">
    <interceptors>
      <interceptor name="myLogging" class="jp.ymatsukawa.interceptors.Logger" />
      <interceptor-stack name="myStackLogging">
        <interceptor-ref name="myLogging" />
      </interceptor-stack>
    </interceptors>
    <default-interceptor-ref name="myStackLogging" />
    <action name="index" class="jp.ymatsukawa.top.Index">
      <result name="success">/index.jsp</result>
    </action>
  </package>
</struts>

interceptors を定義した後に

default-interceptor-ref#name="共通参照したい interceptor-stack" を定義する

action 要素の下には interceptor-ref の記載は入れない

default-interceptor-ref 定義後に
各 action で interceptor-ref を定義した時の挙動

default-interceptor-ref を定義した後、各 action

interceptor-ref を定義するとどうなるか

先に要約すると default-interceptor-ref は実行されず

action で定義された interceptor-ref が実行される

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">

<struts>
  <constant name="struts.devMode" value="true" />
  <constant name="struts.ui.theme" value="simple" />
  <package name="top" extends="struts-default">
    <interceptors>
      <interceptor name="myLogging" class="jp.ymatsukawa.interceptors.Logger" />
      <interceptor name="myOtherLogging" class="jp.ymatsukawa.interceptors.OtherLogger" />
      <interceptor-stack name="myStackLogging">
        <interceptor-ref name="myLogging" />
      </interceptor-stack>
    </interceptors>
    <default-interceptor-ref name="myStackLogging" />
    <action name="index" class="jp.ymatsukawa.top.Index">
      <interceptor-ref name="myOtherLogging" />
      <result name="success">/index.jsp</result>
    </action>
  </package>
</struts>

default-interceptor-ref(myLogging) > action.interceptor-ref(myOtherLogging) が実行されると思いきや

action.interceptor-ref(myOtherLogging) のみ実行される

[参考元]

https://struts.apache.org/docs/how-do-we-configure-an-interceptor-to-be-used-with-every-action.html

struts.xml interceptor-stack 要素とは何か

interceptor-stack 要素とは何か

interceptors.interceptor をひとまとまり に定義したもの

利用により、汎用的に interceptorinterceptor-ref で参照できる

具体的に

下記 struts.xml より

  • interceptor が
    • ロギング
    • DB コネクション処理

の 2 つで定義されているとする

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">

<struts>
  <constant name="struts.devMode" value="true" />
  <constant name="struts.ui.theme" value="simple" />
  <package name="top" extends="struts-default">
    <interceptors>
      <interceptor name="myLogging" class="jp.ymatsukawa.interceptors.Logger" />
      <interceptor name="myDBConnection" class="jp.ymatsukawa.interceptors.DBConnection" />
    </interceptors>
    <action name="index" class="jp.ymatsukawa.top.Index">
      <interceptor-ref name="myLogging" />
      <interceptor-ref name="myDBConnection" />
      <result name="success">/index.jsp</result>
    </action>
  </package>
</struts>

action が新規追加されるごとに action#name="index"

interceptor-ref がコピペされそうである

汎用的に これらまとまり(interceptors.interceptor) を参照できる形式にしよう

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
        "http://struts.apache.org/dtds/struts-2.5.dtd">

<struts>
  <constant name="struts.devMode" value="true" />
  <constant name="struts.ui.theme" value="simple" />
  <package name="top" extends="struts-default">
    <interceptors>
      <interceptor name="myLogging" class="jp.ymatsukawa.interceptors.Logger" />
      <interceptor name="myDBConnection" class="jp.ymatsukawa.interceptors.DBConnection" />
      <interceptor-stack name="myStackDBCon">
        <interceptor-ref name="myLogging" />
        <interceptor-ref name="myDBConnection" />
      </interceptor-stack>
    </interceptors>
    <action name="index" class="jp.ymatsukawa.top.Index">
      <interceptor-ref name="myStackDBCon" />
      <result name="success">/index.jsp</result>
    </action>
  </package>
</struts>

struts.package.interceptors.interceptor の下に

  • interceptor-stack を追加
  • interceptor-stack#name に 各 actioninterceptor-ref が参照する名前を命名

[参考元]

https://struts.apache.org/docs/interceptors.html#Interceptors-StackingInterceptors