Global results with Struts 2 and convention plugin

*爱你&永不变心* 提交于 2019-12-11 01:14:40

问题


i would like to have some global results in my application. In good old XML configuration it would look like:

<global-results>
  <result name="error" type="redirectAction">
    <param name="actionName">index</param>
    <param name="namespace">/</param>
  </result>
</global-results>

But as I'm using the convention plugin the global results in the XML seem to be ignored so how could I implement this using the convention plugin? I don't want to have all my action classes extend a custom class that has those global results defined. I think the package-info.java should be my friend but all i can define there having something to do with results is @org.apache.struts2.convention.annotation.ResultPath.

Just to make clear: I don't want to avoid struts.xml configuration - I just want to have some working global forwards so in case of an error in any action i want to forward the user to a central error page. This is currently not working with my configuration. If you see the problem in my struts.xml or my action and can help me to fix it it would be perfectly fine.

Maybe the order in the struts.xml matters? Here's the structure of my struts.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
  <constant name="struts.devMode" value="false" />
  <constant name="struts.convention.result.path" value="/content/"/>
  <constant name="struts.convention.default.parent.package" value="my-package"/>
  <constant name="struts.convention.package.locators.disable" value="true"/>
  <constant name="struts.convention.action.packages" value="..."/>
  <constant name="struts.custom.i18n.resources" value="global" />
  <constant name="struts.multipart.maxSize" value="10485760" />
  <package name="my-package" extends="struts-default,json-default" namespace="/">
    <result-types>
      <result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult"/>
    </result-types>

    <interceptors>
      <interceptor name="login" class="loginInterceptor" />
      <interceptor name="pagetitle" class="pagetitleInterceptor"></interceptor>

      <interceptor-stack name="secureStack">
        ...
      </interceptor-stack>

      <interceptor-stack name="insecureStack">
        ...
      </interceptor-stack>
    </interceptors>

    <default-interceptor-ref name="secureStack" />

    <global-results>
      <result name="error" type="redirectAction">
        <param name="actionName">index</param>
        <param name="namespace">/</param>
      </result>
    </global-results>
  </package>
</struts>

in my action I have:

public class MyActionClass extends ActionSupport {
  @Actions({ @Action(value = "my-action", results = { @Result(name = "success", type = "tiles", location = "my.location") }) })
  public final String myAction() throws Exception {
    return ERROR;
  }
}

of course myAction has more functionality - this is just for illustration. When the action is executed it forwards to the my-action.jsp without using tiles but I expected it to forward to /index.action.


回答1:


Unfortunately you can't define the Result or Results annotation on the package using convention plugin. You have to define global results in xml configuration and they aren't ignored because the runtime configuration is defined regardless which configuration provider you use. The workaround is to define Result or Results on the base class.




回答2:


You are defining a global-result in a package. These kind of results(global) are global only to the package they are defined in. So only those actions which are also declared in the same package can access these global-results. You have two options in front of you:


XML Configuration:

It's very obvious how to do it in XML configuration(you just define them in the same package):

<package name="my-package" extends="struts-default,json-default" namespace="/">

    <!-- This result is local to this action -->
    <action name="someAction"class="com.example.SomeAction" method="execute">
        <result name="someLocalResult">/localResult.jsp</result>
    </action>
    .
    .
    .
    <global-results>
        <!--This result is global **to the actions in my-package** -->
        <result name="error" type="redirectAction">
            <param name="actionName">index</param>
            <param name="namespace">/</param>
        </result>
    </global-results>

</package>

Convention Plugin:

So if you're using convention plugin to only mark your java classes as actions, you are not defining a package for them to rest in(They will belong to the default package). To do so, you can use the annotation @ParentPackage to tell the framework that this action belongs to this package and can use it's global-results. In order to achieve this, your java class should look like this:

@ParentPackage(value="my-pacakge")
public class MyActionClass extends ActionSupport {
    @Actions({ @Action(value = "my-action", results = { @Result(name = "success", type = "tiles", location = "my.location") }) })
    public final String myAction() throws Exception {
        return ERROR;
    }
}

Your struts.xml will remain the same:

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
    <package name="my-package" extends="struts-default,json-default" namespace="/"> 
        .
        .
        . 
        <global-results> 
             <result name="error" type="redirectAction"> 
                 <param name="actionName">index</param> 
                 <param name="namespace">/</param> 
             </result> 
         </global-results> 
     </package> 
 </struts>

A similar alternative solution to get rid of setting every action's @ParentPackage is to set the actions default pacakge to your favorite package(Here, the package containing the global-result). Just add this constant element to your struts.xml (inside of <struts>) and you'll be fine:

<constant name="struts.convention.default.parent.package" value="my-package"/>

Here is a useful link about @ParentPackage:

  1. @ParentPackage annotation from apache



回答3:


Well regarding to: Convention Plugin Documentation:

From 2.1.7 on, global results (defined on the class level) defined using annotations will be inherited.

So it sounds to me as i can for example have a base action which all of my actions extend and then i have a global result. The other idea was the package-info.java.

The same documentation says:

The Convention plugin allows action classes to define different results for an action. Results fall into two categories, global and local. Global results are shared across all actions defined within the action class. These results are defined as annotations on the action class. Local results apply only to the action method they are defined on. Here is an example of the different types of result annotations`

So I think they are a different concept from the standard Local Result and Global Result.

Standard Struts:

  1. Global Result is visible to each Action / Interceptor defined in the package;
  2. Local Result is visible to that Action only (but to all methods if invoked with Dynamic Method Invocation);
  3. Local Result is visible to that Action and Method only, if the method is included in the Action tag in struts.xml (then you would have multiple action tags for the same Action class and different methods).

I think that With Convention, Global is (2.) and Local is (3.) They're both local to the Action, but global is returnable from each method, while local only from the specific method who defined it.



来源:https://stackoverflow.com/questions/19034052/global-results-with-struts-2-and-convention-plugin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!