Struts2的Annotation使用 实现 struts2 “零配置”项目

从struts2.1开始,struts2不再推荐使用Codebehind作为零配置插件,而是改为使用Convention插件来支持零配置,和Codebehind相比,Convention插件更彻底,该插件完全抛弃配置信息,不仅不需要是使用struts.xml文件进行配置,甚至不需要使用Annotation进行配置,而是由struts2根据约定自动配置。

如何使用Convention

1.       将struts-Convention-plugin-2.1.6.jar文件复制到WEB-INF/lib路径下

2.       对于Convention插件而言,它会自动搜索位于action,actions,struts,struts2包下的所有java类,Convention插件会把如下两种java类当成Action处理:

1)  所有实现了com.opensymphony.xwork2.Action的java类

2)  所有类名以Action结尾的java类

3.       Convention插件还允许设置如下三个常量:

1)  struts.Convention.exclude.packges:指定不扫描哪些包下的java类,位于这些包结构下的java类将不会自动映射成Action;

2)  struts.convention.package.locators:Convention插件使用该常量指定的包作为搜寻Action的根包。对于actions.fore.LoginAction类,按约定原本应映射到/fore/login;如果将该常量设为fore,则该Action将会映射到/login

3)  struts.convention.action.packages:Convention插件以该常量指定包作为根包来搜索Action类。Convention插件除了扫描action,actions,struts,struts2四个包的类以外,还会扫描该常量指定的一个或多个包,Convention会试图从中发现Action类。

注意:struts.convention.package.locators和struts.convention.action.packages两个常量的作用比较微妙,开发者在利用这两个常量时务必小心。

如:下面Action所在包被映射的命名空间如下:

com.fun.actions.LoginAction 映射到   /

com.fun.actions.myoffice.CarInfoAction 映射到 /myoffice

com.fun.struts.myoffice.EntINfoAction 映射到 /myofiice

4.       映射Action的name时,遵循如下两步规则:

1)  如果该Action类名包含Action后缀,将该Action类名的Action后缀去掉。否则不做任何处理。

2)  将Action类名的驼峰写法(每个单词首字母大写、其他字母小写的写法)转成中画线写法(所有字母小写,单词与单词之间以中画线隔开)

如:LoginAction映射的Acion的name属性为login,GetBooks映射的Action的name的属性为get-books,AddEmployeeAction映射的Action的name属性为add-employee

5.       默认情况下。Convention总会到WEB应用的WEB-INF/content路径下定位物理资源,定位资源的约定是:actionRUL+resultCODE+suffix。当某个逻辑视图找不到对应的试图资源时,Convention会自动视图使用ActionURL+suffix作为物理视图资源。

       如:actions.fore.LoginAction 返回success字符串时,Convention优先考虑使用WEB-INF/content/fore目录下的login-success.jsp作为视图资源。如果找不到该文件,login.jsp也可作为对应的试图资源。如果返回input字符串,Convention会将WEB-INF/content/fore里面查找login-input.jsp

6.       为了看到struts2应用里的Action等各种资源的影射情况,struts2提供了Config Browser插件。使用方法,将struts2-config-browser-plugin-2.1.6.jar文件复制到struts2应用的WEB-INF/lib目录中。

打开首页地址:http://localhost:8080/应用名字/config-browser/actionNames.action这里可以看到Config Browser插件的首页。

注意:这里不管开发者是否使用struts.xml文件进行配置,一样可以看到struts的配置信息。

7.Action链的约定

如果希望一个Action处理结束后不是进入一个试图页面,而是进行另一个Action形成的Action链。通过Convention插件则只需遵守如下三个约定即可。

1)  第一个Action返回的逻辑视图字符串没有对应的视图资源

2)  第二个Action与第一个Action处在同一个包下

3)  第二个Action影射的URL为:firstActionURL+resultCODE

如,第一个Action为OneAction,里面有个方法返回为“two”,那么就得保证,WEB-INF/content/下没有one.jsp或one-two.jsp 对于第二个action 它的名字应该是OneTwoAction,而对应的url应该是:“one-two.action”

注意:由于Convention插件根据Action和jsp页面来动态生成映射的,因此不管是Acion的改变,还是JSP页面的改变都需要Convention插件重新加载映射。那么只要我们为struts2应用配置如下两个常量就可以了。

< !--配置struts2应用于开发模式--!>

<constant name=”struts.devMode” value=”true”/>

< !—配置Convention插件自动重加载映射--!>

<constant name=”struts.convention.classes.reload” value=”true”/>

几个重要的常量

struts.convention.action.disableJarScanning---是否从包中搜索Action

struts.convention.action.package--------Convention插件以该常量指定包作为根包

struts.convention.result.path ---设置Convention插件定位视图资源的根路径。默认值为/WEB-INF/content

struts.convention.result.flatLayout—如果是为false则可以将试图放置Action对应的目录下,无需放入WEB-INF/content

8.       Convention的Annotation

1)  与Action相关的两个Annotation是@Action 和@Actions

2)  @Action中可指定一个value属性。类似于指定<action name=””/>属性值

3)  @Action中还可以指定一个params属性,该属性是一个字符串数组,用于该Acion指定的参数名和参数值。params属性应遵守如下格式:{“name1”,”value1”,”name2”,”value2”}

4)  @Actions 也用于修饰Action类里的方法,用于将该方法映射到多个URL.@Actions用于组织多个@Action.因此它可将一个方法映射成多个逻辑Action。


如:

  1. package com.fun.actions;    
  2.    
  3. import org.apache.struts2.convention.annotation.Action;    
  4.    
  5. import org.apache.struts2.convention.annotation.Actions;    
  6.    
  7. import com.fun.service.LoginService;    
  8.    
  9. import com.opensymphony.xwork2.ActionSupport;    
  10.    
  11. publicclass LoginActionextends ActionSupport {   
  12.    
  13.     private String str;   
  14.    
  15.     @Actions({   
  16.    
  17.      @Action(value="login1",params={"str","这是已经注入的了!"}),   
  18.    
  19.      @Action(value="login2")   
  20.    
  21.     })   
  22.    
  23.     public String login(){   
  24.    
  25.      return"str";   
  26.    
  27.     }   
  28.    
  29.     @Action(value="ggg")   
  30.    
  31.     public String abc(){   
  32.    
  33.      return"abc";   
  34.    
  35.     }   
  36.    
  37.     public String getStr() {   
  38.    
  39.      return str;   
  40.    
  41.     }   
  42.    
  43.     publicvoid setStr(String str) {   
  44.    
  45.      this.str = str;   
  46.    
  47.     }   
  48. }  

我们可以通过/login1.action访问,而在访问时,str这个属性已经有值,为str=”这是已经注入的!” 返回的视图是login1-str.jsp

当我们用/login2.action访问时,str的值为null。返回的视图为 login2-str.jsp

而我们通过/ggg.action调用的是abc()方法,返回的视图为/ggg-abc.jsp

9.       与Result配置相关的Annotation

1)@ResultPath @Result 和Results

2)@Results用于组织多个@Result因此它只需指定一个value属性值,该value属性值为多个@Result

3)@Result相当于struts.xml文件中的<result/>元素的做哟欧诺个。使用@Result必须指定一个name属性,相当于<result name=””/>另外,它还有几个可选的属性。

     ☆ type 相当于<result type=””/>指定返回视图资源的类型

     ☆ location 相当于<result>…..</result>中间部分,用于指定实际视图位置

     ☆ params:该属性相当于<result/>元素里多个<param../>子元素的作用,用于为该Result指定参数值。该属性应满足{“name1”,”value1”,”name2”,”value2”}格式

4)@Result有以下两种用法

1 Action级的Result映射:以@Actions组合多个@Action后修饰的Action类。这种Result映射对该Action里的所有方法都有效。

2方法级Result映射:将多个@Result组成数组后作为@Action的results属性值。这种Result映射仅对被修饰的方法有效。

5)@ResultPath则用于修饰包和Action类,用于改变被修饰Action所对应的物理视图资源的根路径。举例说:默认情况下,Convention都会到WEB-INF/content路径下找物理视图资源,一旦我们使用@ResultPath(“/abc”)修饰该Action,系统将回到abc目录下寻找物理视图资源。举例:在默认情况下,Convention都会到WEB-INF/content路径下需找物理视图资源,一旦我们使用@ResultPath(“/abc”)修饰该Action,系统会到abc目录下寻找物理视图资源。

10.  与包和命名空间相关的Annotation:

   @Namespace:修饰Action类或其所在的包。该Annotation中指定一个value属性值,用于指定被修饰的Action所在的命名空间

  @Namespaces:修饰Action类或其所在的包,用于组合多个@Namespace

  @ParentPackage: 用于指定被修饰的Action所在包的夫包。

11.  异常处理相关的Annotation

  @ExceptionMappings 用于组织多个@ExceptionMapping,因此它只需指定一个value属性值,该value属性值为多个@ExceptionMapping。

@ExceptionMapping 用于定义异常类和物理视图之间的对应关系,也相当于struts.xml文件里<exception-mapping../>元素的作用 使用时,必须注意以下两个属性:

  exception: 用于指定异常类

  result : 用于指定逻辑视图

@ExceptionMpping有如下两种用法

   Action级的异常定义:以@ExceptionMappings组合多个@ExceptionMapping后修饰的Action类。这种异常定义对Action中的所有方法有效

  方法级的异常定义: 将多个@ExceptionMapping组成数组后作为@Action的exceptionMappings属性值,这种异常定义仅对被修饰的方法有效。

12.拦截器配置相关的Annotation

与拦截器配置的Annotation有@InterceptorRef、@InterceptorRefs和@DefaultInterceptorRef

@InterceptorRefs用于组织多个@InterceptorRef,因此它只需要指定一个value属性值,该value属性值为多个@InterceptorRef

@InterceptorRef用于为指定Action引用lanjieq或者是拦截器栈。也就相当于strut.xml中位于<action../>元素内部的<interceptor-ref../>子元素的作用。使用@InterceptorRefAnnotation时,必须制定一个value属性,用于指定所引用的拦截器或拦截器栈的名字。相当于<interceptor-ref../>子元素里name属性的作用。

 

 

Struts2零配置之Configuration by Convention(一)

 

随着struts2的不断升级,Struts开始使用convention-plugin代替codebehind-plugin来实现struts的零配置。所谓的零配置并不是任何配置都不需要,而是采用约定大于配置的方式。

在web开发过程中,根据convention-plugin的默认约定,我们不再需要在Struts.xml中配置任何信息。

首先,让我们先来看一下基于convention-plugin实现的Struts"零配置"的HelloWorld。


struts.xml

  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <!DOCTYPE struts PUBLIC 
  3.     "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
  4.     "http://struts.apache.org/dtds/struts-2.3.dtd">
  5. <struts>
  6.     <packagename="default"namespace="/"extends="struts-default"/>
  7. </struts>
<?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="default" namespace="/" extends="struts-default" />
</struts>


我的HelloWorld


  1. package com.example.actions;
  2.  
  3. import com.opensymphony.xwork2.ActionSupport;
  4.  
  5. public class HelloWorldextends ActionSupport {
  6.  
  7.     private staticfinallong serialVersionUID = -6662538623355755690L;
  8.  
  9.     private String message;
  10.  
  11.     public String getMessage() {
  12.         return message; 
  13.     } 
  14.  
  15.     public String execute() {
  16.         if (System.currentTimeMillis() %2 ==0) {
  17.             message = "It's 0";
  18.             return "zero";
  19.         } 
  20.  
  21.         message = "It's 1";
  22.         return SUCCESS; 
  23.     } 
package com.example.actions;

import com.opensymphony.xwork2.ActionSupport;

public class HelloWorld extends ActionSupport {

    private static final long serialVersionUID = -6662538623355755690L;

    private String message;

    public String getMessage() {
        return message;
    }

    public String execute() {
        if (System.currentTimeMillis() % 2 == 0) {
            message = "It's 0";
            return "zero";
        }

        message = "It's 1";
        return SUCCESS;
    }
}


对于一个简单的HelloWorld来讲,struts.xml里面的配置简直精简到了极致。不需要再写一堆一堆的<action>配置了。而我们需要做的只是加入一个struts2-convention-plugin-x.x.x.x.jar

之所以在HelloWorld中不需要任何配置,是因为struts2-convention-plugin进行了以下一系列的约定。

  • Action location by package naming conventions
    com.example. action.Main Action
    com.example. actions.products.Display (implements com.opensymphony.xwork2.Action)
    com.example. struts.company.details.ShowCompanyDetails Action
    com.example. struts2.company.details.ShowCompanyDetailsAction


          Convention plugin默认将包路径包含action,actions,struts,struts2的所有包都作为Action类的路径来搜索。你可以通过设置struts.convention.package.locators属性来修改这个配置。 Convention plugin默认的配置如下:

  1. <constantname="struts.convention.package.locators"value="action,actions,struts,struts2"/>
<constant name="struts.convention.package.locators" value="action,actions,struts,struts2"/>

Convention plugin在上述的包及其子包中查找后缀为Action、或者实现了com.opensymphony.xwork2.Action的类。你可以通过设置

struts.convention.action.suffix属性来修改这个配置。Convention plugin默认的配置如下:

  1. <constantname="struts.convention.action.suffix"value="Action"/>
<constant name="struts.convention.action.suffix" value="Action"/>

  • Result (JSP, FreeMarker, etc) location by naming conventions

          当在浏览器中输入http://localhost:8080/hello-world访问时,页面会跳转到WEB-INF/content/hello-world.jsp。
          默认情况下, Convention plugin假设所有的results存放在WEB-INF/content/下。可以通过设置struts.convention.result.path进行修改。Convention plugin默认的配置如下:

  1. <constantname="struts.convention.result.path"value="/WEB-INF/content/"/>
<constant name="struts.convention.result.path" value="/WEB-INF/content/"/>

          Convention plugin即使在找不到对应的action的情况下,也可以通过Action的URL(这里是/hello-world)找到对应的结果(/hello-world.jsp)。

  • Class name to URL naming convention

          com.example.actions.MainAction -> /main
          com.example.actions.products.Display -> /products/display

          com.example.struts.company.details.ShowCompanyDetailsAction -> /company/details/show-company-details

          com.example.struts.company.details.ShowCompanyDetailsAction对应的Action URL为例,Convention plugin会将com.example.struts.company.details.ShowCompanyDetailsAction的struts后的子包转换成命名空间“/company/details/”,然后ShowCompanyDetailsAction中的“Action”后缀去掉,并将驼峰式的命名大写变小写,并在之间加上“-”(当然“-”也是Convention plugin默认的)最终形成/company/details/show-company-details。这就是类名和Action URL之间的“约定”。


  • Package name to namespace convention

          com.example.actions.MainAction -> /
          com.example.actions.products.Display -> /products

          com.example.struts.company.details.ShowCompanyDetailsAction -> /company/details

          Convention plugin默认将actions、actionstruts、struts2作为root Package,那么com.example.actions.MainAction的命名空间即为“/”,而com.example.actions.products.Display的命名空间为“/products”。

 

Struts2注解配置之@Action(二)

当注解配置能够简化繁杂的xml,你是否想过也要使用注解?

最近对原有项目的框架使用的Struts2进行升级。很早以前就想尝试注解的方式进行配置。但是由于项目稳定性和改配置方式可能带来的问题一直没有进行。但是这不妨碍我们程序员求知的心。哈哈~~~~。

言归正传,开始Struts2最常用的几个注解的学习吧。

@Action


  • 使用@Action注解改变Convention plug约定的action与url之间的映射关系。

废话少说代码说事儿。

  1. package com.example.actions;
  2.  
  3. import org.apache.struts2.convention.annotation.Action;
  4.  
  5. import com.opensymphony.xwork2.ActionSupport;
  6.  
  7. public class HelloWorld2extends ActionSupport {
  8.  
  9.  
  10.     @Action("/different/url")
  11.     public String execute() {
  12.  
  13.         return SUCCESS;
  14.     } 
package com.example.actions;

import org.apache.struts2.convention.annotation.Action;

import com.opensymphony.xwork2.ActionSupport;

public class HelloWorld2 extends ActionSupport {


	@Action("/different/url")
	public String execute() {

		return SUCCESS;
	}
}


本例中在String execute()方法上使用了@Action("/different/url"),它改变了Action 与Action URL之间的映射关系,而这种改变并不是“OverWrite”而是在原来约定的基础上增加了另外一种调用方式。

原本在没有@Action("/different/url")注解的情况下,我们可以在浏览器中输入:http://应用服务器ip:端口/应用/hello-world2,即可访问到com.example.actions.HelloWorld2,并最终显示http://应用服务器ip:端口/应用/hello-world2.jsp页面。(当然这里也可能是html等页面)。

@Action("/different/url")注解的情况下,除了上述的访问方式外,我们还可以在浏览器中输入:http://应用服务器ip:端口/应用

/different/url,也可访问到com.example.actions.HelloWorld2,但最终显示http://应用服务器ip:端口/应用/different/url.jsp页面。

  • 使用@Action注解解决一个ACTION中的一个方法,响应多个不同的URL.

实际项目开发过程中有很大的几率碰到Action的处理相同,但是最终跳转的页面不同的情况。将@Actions和@Action组合起来用即可解决这样的需求。

还是先上代码

  1. package com.example.actions;
  2.  
  3. import org.apache.struts2.convention.annotation.Action;
  4. import org.apache.struts2.convention.annotation.Actions;
  5.  
  6. import com.opensymphony.xwork2.ActionSupport;
  7.  
  8. public class HelloWorld3extends ActionSupport {
  9.  
  10.     private String message; 
  11.  
  12.     public String getMessage() { 
  13.         return message;
  14.     } 
  15.  
  16.     @Actions( { @Action("/one/url"),@Action("/another/url") })
  17.     public String execute() {
  18.         message = "经过HelloWorld3的处理";
  19.         return SUCCESS;
  20.     } 
package com.example.actions;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Actions;

import com.opensymphony.xwork2.ActionSupport;

public class HelloWorld3 extends ActionSupport {

	private String message;

	public String getMessage() {
		return message;
	}

	@Actions( { @Action("/one/url"), @Action("/another/url") })
	public String execute() {
		message = "经过HelloWorld3的处理";
		return SUCCESS;
	}
}


本例中在String execute()方法上使用了@Actions和@Action注解。其中@Actions注解包含@Action("/one/url")和@Action("/another/url")注解。这样的注解除了可以通过http://应用服务器ip:端口/应用/hello-world3访问com.example.actions.HelloWorld3,并最终显示http://应用服务器ip:端口/应用/hello-world3.jsp之外,还有两种访问方式:

即:

通过http://应用服务器ip:端口/应用/one/url,访问com.example.actions.HelloWorld3,并最终显示http://应用服务器ip:端口/应用/one/url.jsp

通过http://应用服务器ip:端口/应用/another/url,访问com.example.actions.HelloWorld3,并最终显示http://应用服务器ip:端口/应用/another/url.jsp
这样就达到了一个ACTION中的一个方法,响应多个不同的URL的效果。


  • 使用@Action注解解决一个ACTION中的多个方法,其中每个方法响应不同的URL.
这是实际项目开发过程中最常用的。
再上一个代码示例:
  1. package com.example.actions;
  2.  
  3. import org.apache.struts2.convention.annotation.Action;
  4.  
  5. import com.opensymphony.xwork2.ActionSupport;
  6.  
  7. public class HelloWorld4extends ActionSupport {
  8.  
  9.     private String message;
  10.  
  11.     public String getMessage() {
  12.         return message; 
  13.     } 
  14.  
  15.     @Action("/H4/url")
  16.     public String execute() { 
  17.         message = "HelloWorld4 execute()!";
  18.         return SUCCESS; 
  19.  
  20.     } 
  21.  
  22.     @Action("url")
  23.     public String doSomething() {
  24.         message = "HelloWorld4 doSomething()!";
  25.         return SUCCESS;
  26.     } 
package com.example.actions;

import org.apache.struts2.convention.annotation.Action;

import com.opensymphony.xwork2.ActionSupport;

public class HelloWorld4 extends ActionSupport {

	private String message;

	public String getMessage() {
		return message;
	}

	@Action("/H4/url")
	public String execute() {
		message = "HelloWorld4 execute()!";
		return SUCCESS;

	}

	@Action("url")
	public String doSomething() {
		message = "HelloWorld4 doSomething()!";
		return SUCCESS;
	}
}

本例中在String execute()方法上使用了@Action("H4/url")注解。在StringdoSomething()方法中使用了@Action("url")。前者可以通过 http://应用服务器ip:端口/应用/H4/url访问com.example.actions.HelloWorld4中的execute()方法,并最终显示http://应用服务器ip:端口/应用/H4/url.jsp。后者是通过http://应用服务器ip:端口/应用/url来访问com.example.actions.HelloWorld4中的doSomething()方法,并最终显示 http://应用服务器ip:端口/应用/url .jsp

这个例子里面需要注意的是@Action("/H4/url")和@Action("url")的不同,在“url”前并没有“/”这意味着"url"是基于HelloWorld4的命名空间的。假设HelloWorld4所在的包是com.example.actions.aaa,那么,只有通过http://应用服务器ip:端口/应用/aaa/url才可以访问到com.example.actions.aaa.HelloWorld4,并最终显示http://应用服务器ip:端口/应用/aaa/url.jsp而“/H4/url”是基于“/”命名空间的。

 

Struts2注解配置之@Results和@Result(三)

在Struts2注解配置之@Action(二)中对于结果页面我还是采用Convention Plugin的约定,但是这一节我需要利用@Results和@Result改变一下这种约定。以及@Results和@Result对类和方法进行注解后所产生的效果。
还是先看一段代码:

  1. package com.example.actions;
  2.  
  3. import org.apache.struts2.convention.annotation.Action;
  4. import org.apache.struts2.convention.annotation.Result;
  5. import org.apache.struts2.convention.annotation.Results;
  6.  
  7. import com.opensymphony.xwork2.ActionSupport;
  8.  
  9. @Results( { @Result(name ="global", location ="/global.jsp") })
  10. public class HelloWorld5extends ActionSupport {
  11.  
  12.     @Action(value = "/H5/url", results = {@Result(name = SUCCESS, location ="/H5/success.jsp"), 
  13.             @Result(name ="failure", location ="/H5/fail.jsp") })
  14.     public String execute() { 
  15.         if (System.currentTimeMillis() %3 ==0) {
  16.             return "failure";
  17.         } else if (System.currentTimeMillis() %3 ==1) {
  18.             return SUCCESS; 
  19.         } else
  20.             return "global";
  21.         } 
  22.     } 
  23.  
  24.     @Action("globalTest")
  25.     public String global() {
  26.         return "global";
  27.     } 
  28.  
  29.     @Action(value = "globalOverWrite", results = { @Result(name ="global", location ="/H5/globalOverWrite.jsp") })
  30.     public String globalOverWrite() {
  31.         return "global";
  32.     } 
  33.  
package com.example.actions;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;

import com.opensymphony.xwork2.ActionSupport;

@Results( { @Result(name = "global", location = "/global.jsp") })
public class HelloWorld5 extends ActionSupport {

	@Action(value = "/H5/url", results = { @Result(name = SUCCESS, location = "/H5/success.jsp"),
			@Result(name = "failure", location = "/H5/fail.jsp") })
	public String execute() {
		if (System.currentTimeMillis() % 3 == 0) {
			return "failure";
		} else if (System.currentTimeMillis() % 3 == 1) {
			return SUCCESS;
		} else {
			return "global";
		}
	}

	@Action("globalTest")
	public String global() {
		return "global";
	}

	@Action(value = "globalOverWrite", results = { @Result(name = "global", location = "/H5/globalOverWrite.jsp") })
	public String globalOverWrite() {
		return "global";
	}

}




  • 使用@Result注解改变Convention Plugin的约定跳转页面。

在代码的String execute()方法上进行了    @Action(value = "/H5/url", results = { @Result(name = SUCCESS, location = "/H5/success.jsp"),
            @Result(name = "failure", location = "/H5/fail.jsp") })注解。如果@Action(...)没有results = { @Result(name = SUCCESS, location = "/H5/success.jsp"),
            @Result(name = "failure", location = "/H5/fail.jsp") }
,那么依据Convention Plugin的约定,结果页面会是/H5/url.jsp。加上红色字体的部分后,execute()方法执行后,会根据红色字体的配置,将结果跳转到对应的页面。

  • 对Action类添加@Result注解,@Result将被Action类中的所有方法所共享。
仔细观察上述代码,在HelloWorld5上进行了@Results( { @Result(name = "global", location = "/global.jsp") })注解。这意味着该类及其子类的所有方法都可以返回一个名字为“global”的结果页面。而这个页面是"/global.jsp"。这就使得不用在每个需要跳转到"/global.jsp"的方法都进行@Result(name = "global", location = "/global.jsp")注解。这在实际工作中也是非常常见的一种情况。可以仔细观察的execute()方法和global()方法。他们都可能跳转到名字为“global”的结果页面(即location属性定义的“/global.jsp”页面)。
  • 对Action类中的方法添加@Result注解,@Result将只作用于被添加的方法。Action类方法上添加的@Result优先级高于Action类上添加的@Result。(前者覆盖后者)

再仔细观察上述代码的globalOverWrite()方法,该方法也跳转到名字为“global”的页面。但是在该方法上使用了@Action(value = "globalOverWrite", results = { @Result(name = "global", location = "/H5/globalOverWrite.jsp") })注解。并且其中@Result(...)注解中也有一个名字为“global”的结果页面定义。此时,该方法的结果页面就会跳转到/H5/globalOverWrite.jsp页面而不是在类上进行注解时候的“/global.jsp”页面。

Struts2注解配置之@Namespace(四)

还是先看一段代码:

  1. package com.example.actions;
  2.  
  3. import org.apache.struts2.convention.annotation.Action;
  4. import org.apache.struts2.convention.annotation.Namespace;
  5.  
  6. import com.opensymphony.xwork2.ActionSupport;
  7.  
  8. @Namespace("/custom")
  9. public class HelloWorld6extends ActionSupport {
  10.     @Action("/H6/url")
  11.     public String execute() {
  12.         return SUCCESS; 
  13.     } 
  14.  
  15.     @Action("url")
  16.     public String doSomething() { 
  17.         return SUCCESS;
  18.     } 
package com.example.actions;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;

import com.opensymphony.xwork2.ActionSupport;

@Namespace("/custom")
public class HelloWorld6 extends ActionSupport {
	@Action("/H6/url")
	public String execute() {
		return SUCCESS;
	}

	@Action("url")
	public String doSomething() {
		return SUCCESS;
	}
}

  • 名称空间注释允许操作类名称空间改变而不是使用Convention Plugin约定的Java包的名称。
仔细分析上述代码。HelloWorld6的包名为package com.example.actions;。如果没有@Namespace("/custom")注解,按照Convention Plugin的约定,会将此包作为根包。对应Action URL的命名空间为“/”。而有@Namespace("/custom")注解的情况下,HelloWorld6的命名空间被改成了“/custom”。但是我们在浏览器中输入http://应用服务器ip:端口/应用/H6/url访问时,没有任何问题,还可以跳转到“/H6/url.jsp”页面。
这是什么原因呢?
关键在于@Action("/H6/url")。此处“/H6/url”是对Action的名称空间进行了完全限定。实验证明@Namespace("/custom")注解对名称空间进行完全限定的不起作用。
  • 针对某个Action类进行@Namespace注释后,该注释的效果将应用于该类中所有未完全限定的action URLs
试着在浏览器中输入http://应用服务器ip:端口/应用/url访问时,报出了错误提示信息。将@Namespace("/custom")注解去掉,重新启动服务,再次访问,成功!再次将@Namespace("/custom")注解加上,重新启动服务,访问,失败。
此回合操作验证了一个问题,@Namespace注解已经作用到doSomething()方法上。
仔细观察每一个细节。该方法上有@Action("url")注解。它“url”的前面没有“/”。这是未完全限定的action URL啊。这样正好说明了针对某个Action类进行@Namespace注释后,该注释的效果将应用于该类中所有未完全限定的action URLs。
这样我们在浏览器中输入http://应用服务器ip:端口/应用/cutsom/url访问时,成功。跳转页面为“/custom/url.jsp”。

近日在CSND头条中爆出Struts2高危漏洞造成大规模的信息泄露的消息,让我们这些从事javaweb软件开发,并且应用struts2的人惊出一身冷汗。Struts漏洞影响巨大,受影响站点以电商、银行、门户、政府居多。而且一些自动化、傻瓜化的利用工具开始出现,填入地址可直接执行服务器命令,读取数据甚至直接关机等操作...

我们的很多项目都是基于Struts2的,这也让我们必须对此做出及时正确的响应。及时升级Struts2是最快最能解决根本问题的方式。困难在于各个项目的Struts2原有版本都不尽相同。

本文记录Struts2-2.3.4升级到2.3.15.1并且最少化改动已有工程代码的情况下的步骤


1.删除的jar包
jsonplugin-0.30.jar(此jar由struts2-json-plugin-2.3.15.1.jar代替,如果以前采用过其他jsonplugin插件的话)

2.添加的jar包
commons-lang3-3.1.jar
struts2-json-plugin-2.3.15.1.jar

3.替换的jar包
将原有低版本的ognl-x.x.x.jar替换为ognl-3.0.6.jar
将原有低版本的struts2-core-x.x.x.x.jar替换为struts2-core-2.3.15.1.jar
将原有低版本的xwork-core-x.x.x.x.jar替换为xwork-core-2.3.15.1.jar
将原有低版本的javassist-x.x.x.jar替换为javassist-3.11.0.GA.jar

4.xwork-conversion.properties
注释掉java.lang.Enum=com.opensymphony.xwork2.util.EnumTypeConverter

5.替换工程中所有*.xml Struts配置文件中type="redirect-action"为type="redirectAction",并将xml的头部信息修改为:

  1. <!DOCTYPE struts PUBLIC 
  2.     "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" 
  3.     "http://struts.apache.org/dtds/struts-2.3.dtd">
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">


6.修改struts.xml中返回类型为json的处理类相关的配置。(如果你的工程原来采用的是其他的json类型处理插件的话)
将其中片段修改成如下状态:
  1. <result-types>
  2.             <!-- 添加的自定义类型JSON对象 -->
  3.             <!--
  4.                 <result-type name="json" class="com.googlecode.jsonplugin.JSONResult" />
  5.             --> 
  6.             <result-typename="json"class="org.apache.struts2.json.JSONResult"/>
  7. </result-types>
<result-types>
            <!-- 添加的自定义类型JSON对象 -->
            <!--
                <result-type name="json" class="com.googlecode.jsonplugin.JSONResult" />
            -->
            <result-type name="json" class="org.apache.struts2.json.JSONResult" />
</result-types>

7.所有涉及到jsonplugin-0.30.jar的类由struts2-json-plugin-2.3.15.1.jar中的对应类替换。(如果你的工程原来采用的是其他的json类型处理插件的话)

8.struts2标签库的升级
将原有的struts-tag.tld升级为最新。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值