使用struts2的注解,注解的好处:类被移动一般不用修改代码或配置文件
学习的时候,一般先从xml下手,因为更贴近原理性的东西;但是工作的时候,往往使用注解,因为简单。应该在学习完xml后,深入理解struts2各种组件后,再学习注解就非常简单了
1.从struts2的2.3.7的版本lib中导入的包:
asm-3.3.jar
asm-commons-3.3.jar
commons-fileupload-1.2.2.jar
commons-io-2.0.1.jar
commons-lang3-3.1.jar
commons-logging-1.1.1.jar
freemarker-2.3.19.jar
javassist-3.11.0.GA.jar
ognl-3.0.5.jar
struts2-config-browser-plugin-2.3.7.jar
struts2-convention-plugin-2.3.7.jar
struts2-core-2.3.7.jar
struts2-dojo-plugin-2.3.7.jar
xwork-core-2.3.7.jar
其中主要是struts2-convention-plugin-2.3.7.jar起到解析注解的作用
这里的struts2-config-browser-plugin-2.3.7.jar是开发时用来看映射关系的,导入这个包后在地址栏输入http://localhost:8080/应用名字/config-browser/actionNames.action就可以查看工程中有哪些action每个action的详细映射信息,以及项目中的常量信息等
2.虽然使用注解不过还是要有配置文件struts.xml,里面置空即可,也可以设置一些常量(在xml中和struts.properties中均可)
struts2-convention-plugin-2.3.7.jar中提供了几个常量:
struts.convention.default.parent.package:这个常量表示缺省的包名是什么,相当于struts.xml中的extends属性。这个常量可以配也可以不配;不配默认是convention-default,在struts2-convention-plugin-2.3.7.jar中struts-plugin.xml定义了这个常量,还可以看到:<packagename="convention-default" extends="struts-default"></package>convention-default就是struts-default
struts.convention.package.locators:这个常量表示action类的所在包的包名的后缀是什么:比如action。这个常量也可以不配;不配置的默认值:action,actions,struts,struts2,那也就是说,如果我们的Action类的包名不是以这些结尾的,那么就会扫描不到
struts.convention.package.locators.basePackage: 这个常量表示你的action类的所在包的名字是什么,表示在这个包以及子包(符合struts.convention.package.locators定义的结尾)下面查找所有的Action。这个常量也可以不配;不配置默认为"",值只能是一个包,不能写多个包
struts.convention.action.suffix:<constantname="struts.convention.action.suffix" value="Action"/>定义了表示以Action为后缀的都会被解析为struts的Action,当然这个Action要在符合条件(struts.convention.package.locators.basePackag,struts.convention.package.locators)包下面,而且如果这个Action没有实现Action接口,里面必须有@Action注解才会被解析成Action,如果不是以这个指定的字符串结尾,那么必须实现Action接口才会被解析成Action
总之: Action要被解析为Action必须满足以下条件:
必须条件: Action类在struts.convention.package.locators.basePackage包或者子包中
必须条件: struts.convention.package.locators=action,actions,struts,struts2 Action所在包名的结尾
必须条件: (自己写的Action类实现了Action接口)或者(自己写的Action类以struts.convention.action.suffix指定的字符串结尾并在类中添加了@Action注解)
3.写HelloWorld应用程序,参考
http://www.2cto.com/kf/201110/106826.html
4.对注解的介绍:
@ParentPackage
作用在类上或包上,只有一个value字段
This annotation canbe used directly on Action classes or in thepackage-info.java class inorder to specify the default XWork parent package for all actions in the Javapackage. The search order for XWork parent packages is therefore:
1. Any ParentPackage annotations placed on individual action classes
2. Any ParentPackage annotations placed in the package-info.java file
3. The struts configuration property struts.convention.default.parent.package
@Namespace
@Target({ElementType.PACKAGE, ElementType.TYPE})
只有一个属性value
The value of a Namespace annotation shouldspecify the portion of the action URL between the context path and the actionname.
Thisannotation can also be placed inside the special Java file namedpackage-info.java,which allows package level annotations. If this is used in this manner itchanges the default namespace for all actions within that Java package. Thesearch order for the namespace of a particular class is therefore:
- If the Action annotation exists within the action and specifies a full URI (i.e. it starts with a / character)
- Any Namespace annotations placed on individual action classes
- Any Namespace annotations placed in the package-info.java file
- The namespace as determined using the Java package name and the standardconvention based naming
@Action
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public@interfaceAction {
String DEFAULT_VALUE ="DEFAULT_VALUE";
/**
* Allows actions to specify different URLsrather than the default that is based on the package
* and action name. This also allowsmethods other than execute() to be invoked or multiple URLs
* to map to a single class or a singlemethod to handle multiple URLs.
*
* @return The action URL.
*/
String value() defaultDEFAULT_VALUE;
/**
* Allows action methods to specificallycontrol the results for specific return values. These
* results are not used for othermethod/URL invocations on the action. These are only used for
* the URL that this action is associatedwith.
*
* @return The results for the action.
*/
Result[] results() default {};
/**
* Allows action methods to specify whatinterceptors must be applied to it.
* @return Interceptors to beapplied to the action
*/
InterceptorRef[] interceptorRefs()default {};
/**
* @return The parameters passed to the action. This isa list of strings that form a name/value
* pair chain since creating a Map for annotations is not possible. Anexample would be:
* <code>{"key", "value", "key2","value2"}</code>.
*/
String[] params() default {};
/**
* @return Maps return codes toexceptions. The "exceptions" interceptor must be applied to theaction.
*/
ExceptionMapping[] exceptionMappings()default {};
/**
* Allows actions to specify differentclass name.
*
* @return The class name forthe action.
*/
String className() defaultDEFAULT_VALUE;
}
Thisannotation can be used to control the URL that maps to a specific method in anAction class. By default, the method that is invoked is the execute method ofthe action and the URL is based on the package and class names. This annotationallows developers to change the URL or invoke a different method. This alsoallows developers to specify multiple URLs that will be handled by a singleclass or a single method.
Thiscan also be used via the Actions annotationto associate multiple URLs with a single method.
@Results
代码:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public@interfaceResults {
Result[] value();
}
This annotation allows a class to define morethan oneResultannotations
@result
代码:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public@interfaceResult {
/**
* @return The name of the result mapping. This is thevalue that is returned from the action
* method and is used to associate a location with a return value.
*/
String name() defaultcom.opensymphony.xwork2.Action.SUCCESS;
/**
* @return The location of the result within the webapplication or anywhere on disk. This location
* can be relative if the type of this result is one of the pre-defined relativeresult
* types (these default to dispatcher, velocity and freemarker). Or thislocation can be
* absolute relative to the root of the web application or the classpath(since velocity
* and freemarker templates can be loaded via the classpath).
*/
String location() default"";
/**
* @return The type of the result. This is usually setupin the struts.xml or struts-plugin.xml
* and is a simple name that is mapped to a result Class.
*/
String type() default"";
/**
* @return The parameters passed to the result. This isa list of strings that form a name/value
* pair chain since creating a Map for annotations is not possible. Anexample would be:
* <code>{"key", "value", "key2","value2"}</code>.
*/
String[] params() default {};
}
Thisannotation is used to specify non-convention based results for the Strutsconvention handling. This annotation is added to a class and can be used tospecify the result location for a specific result code from an action method.Furthermore, this can also be used to handle results only for specific actionmethods within an action class (if there are multiple).
Whenthis annotation is used on an action class, it generates results that areapplicable to all of the actions URLs defined in the class. These areconsidered global results for that class. Here is an example of a globalresult:
@Result(name="fail", location="failed.jsp")
public class MyAction {
}
Thisannotation can also be used inside an Action annotationon specific methods. This usage will define results for that specific actionURL. Here is an example of an action URL specific result:
@Action(results={@Result(name="success", location="/", type="redirect")})}
public String execute() {
}
@InterceptorRef
代码:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public@interface InterceptorRef {
/**
* @return name of theinterceptor or interceptor stack
*/
String value();
/**
* @return The parameters passed to the interceptor.This is a list of strings that form a name/value
* pair chain, since creating a Map for annotations is not possible. Anexample would be:
* <code>{"key", "value", "key2","value2"}</code>.
*/
String[] params() default {};
}
This annotationallows an interceptor to be applied to an action. If this annotation is used atthe class level, then the interceptor will be applied to all actions defined onthat class, and will be applied before the ones defined at the method level.
@InterceptorRefs
代码:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public@interfaceInterceptorRefs {
InterceptorRef[] value();
}
This annotation allows a class to define morethan oneInterceptorRefannotations.
@ExceptionMappings
代码:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public@interface ExceptionMappings {
/**
* @return Exception mappings
*/
ExceptionMapping[] value();
}
Thisannotation allows a class to define more than oneExceptionMappingannotations. These exception mappings will be on all actions defined in theannotated class, they are not global exception mappings.
@ ExceptionMapping
代码:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public@interfaceExceptionMapping {
/**
* @return Result name
*/
String result();
/**
* @return Class name of the exception to be thrown
*/
String exception();
/**
* @return The parameters passed to the exception. Thisis a list of strings that form a name/value
* pair chain since creating a Map for annotations is not possible. Anexample would be:
* <code>{"key", "value", "key2","value2"}</code>.
*/
String[] params() default {};
}
Adds an exceptionmapping to an action
验证,只需在方法上面写@ Validations,例如:
@Validations(
requiredFields={
@RequiredFieldValidator(fieldName="age",message="age isnull"),
@RequiredFieldValidator(fieldName="name",message="name isnull"),
}
,
requiredStrings={
@RequiredStringValidator(fieldName="name",message="${getText('age.required.invalide')}")
},
regexFields={
@RegexFieldValidator(fieldName="name",message="名字格式错误",expression="[a-z]{3,20}")
}
)
public String add(){
return"success";
}
@ SkipValidation
代码:
/**
* Marks an Action method to not be validated
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(METHOD)
public@interfaceSkipValidation {
}
表示某方法跳过验证
@Target( { ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public@interfaceValidations {
/**
* Custom Validation rules.
*/
publicCustomValidator[]customValidators()default {};
publicConversionErrorFieldValidator[] conversionErrorFields()default {};
publicDateRangeFieldValidator[] dateRangeFields()default {};
publicEmailValidator[] emails()default {};
publicFieldExpressionValidator[] fieldExpressions()default {};
publicIntRangeFieldValidator[] intRangeFields()default {};
publicRequiredFieldValidator[] requiredFields()default {};
publicRequiredStringValidator[] requiredStrings()default {};
publicStringLengthFieldValidator[] stringLengthFields()default {};
publicUrlValidator[] urls()default {};
publicConditionalVisitorFieldValidator[] conditionalVisitorFields()default {};
publicVisitorFieldValidator[] visitorFields()default {};
publicRegexFieldValidator[] regexFields()default {};
publicExpressionValidator[] expressions()default {};
}
If you want to useseveral annotations of the same type, these annotations must be nested withinthe @Validations() annotation.
Annotation usage:
Used at METHOD level.
Annotationparameters:
Parameter | Required | Notes |
requiredFields | no | Add list of RequiredFieldValidators |
customValidators | no | Add list of CustomValidators |
conversionErrorFields | no | Add list of ConversionErrorFieldValidators |
dateRangeFields | no | Add list of DateRangeFieldValidators |
emails | no | Add list of EmailValidators |
fieldExpressions | no | Add list of FieldExpressionValidators |
intRangeFields | no | Add list of IntRangeFieldValidators |
requiredStrings | no | Add list of RequiredStringValidators |
stringLengthFields | no | Add list of StringLengthFieldValidators |
urls | no | Add list of UrlValidators |
visitorFields | no | Add list of VisitorFieldValidators |
regexFields | no | Add list of RegexFieldValidator |
expressions | no | Add list of ExpressionValidator |
Example code:
@Validations(
requiredFields = {@RequiredFieldValidator(type = ValidatorType.SIMPLE, fieldName ="customfield", message ="You mustenter a value for field.") },
requiredStrings = {@RequiredStringValidator(type = ValidatorType.SIMPLE, fieldName ="stringisrequired", message ="You must enter avalue for string.") },
emails = {@EmailValidator(type =ValidatorType.SIMPLE, fieldName ="emailaddress", message ="You mustenter a value for email.") },
urls = { @UrlValidator(type =ValidatorType.SIMPLE, fieldName ="hreflocation", message ="You mustenter a value for email.") },
stringLengthFields = {@StringLengthFieldValidator(type = ValidatorType.SIMPLE, trim =true, minLength ="10", maxLength ="12", fieldName ="needstringlength", message ="You mustenter a stringlength.") },
intRangeFields = {@IntRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName ="intfield", min ="6", max = "10", message = "bar mustbe between ${min} and ${max}, current value is ${bar}.") },
dateRangeFields = {@DateRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName ="datefield", min ="-1", max = "99", message = "bar mustbe between ${min} and ${max}, current value is ${bar}.") },
expressions = {
@ExpressionValidator(expression ="foo >1", message ="Foo must be greater than Bar 1. Foo = ${foo}, Bar = ${bar}."),
@ExpressionValidator(expression ="foo >2", message ="Foo must be greater than Bar 2. Foo = ${foo}, Bar = ${bar}."),
@ExpressionValidator(expression ="foo >3", message ="Foo must be greater than Bar 3. Foo = ${foo}, Bar = ${bar}."),
@ExpressionValidator(expression ="foo >4", message ="Foo must be greater than Bar 4. Foo = ${foo}, Bar = ${bar}."),
@ExpressionValidator(expression ="foo >5", message ="Foo must be greater than Bar 5. Foo = ${foo}, Bar = ${bar}.") })
public String execute()throws Exception {
returnSUCCESS;
}