在2005年之前,所有的开发框架集合都有一个特点,除了框架本身的代码需要编写之外,还需要编写大量的XML文件,并且利用这些文件决定项目的执行,想法很好,但是在实际的使用中会发现并不这么好,一旦项目开发很大,那么对于整个项目的控制文件就非常难以维护了。从2005年之后(正是在这一年Apache收购了WebWork),所以现在跨度比较大的框架都开始进行一些结构的修改,Struts 2.x就支持了Annotation(Struts 1.x依然不支持)。
如果要想在Struts 里面使用Annotation,那么需要进行一些配置才可以。
实际上这个时候依然无法使用Annotation开发,因为在Struts 2.x里面强调了,如果要使用Annotation配置,依然需要在web.xml文件的过滤器上进行修改。
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">
<display-name>SAProject</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>actionPages</param-name> <!-- 设置Annotation扫描包 -->
<param-value>org.lks.action</param-value> <!-- 所有action的保存路径 -->
</init-param>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
</web-app>
那么以后只要是保存在了org.lks.action
包中的所有程序类都支持Annotation配置使用。
1 Annotation的基本使用
在整个Struts 2.x项目里面最为核心的肯定是Action以及每一个Action对应的跳转路径,但是通过分析也应该知道,在整个的Struts 2.x项目里面是绝对离不开struts.xml文件的,因为在这个文件里面需要配置一些公共的操作。
范例:修改struts.xml文件,定义公共配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<package name="root" namespace="/" extends="struts-default">
<global-results>
<result name="forward">/pages/forward.jsp</result>
<result name="input">/pages/error.jsp</result>
</global-results>
<!-- 定义拦截器 -->
</package>
</struts>
随后所有的Action里面依然要延续使用以上的配置操作。
范例:定义Action使用Annotation配置
package org.lks.action;
import org.apache.struts2.convention.annotation.Action;
import com.opensymphony.xwork2.ActionSupport;
@SuppressWarnings("serial")
@Action(value="MemeberAction")
public class MemberAction extends ActionSupport {
public void insert(){
System.out.println("******* [Member data insert]******");
}
}
如果从一个实际的开发来讲,所有的Action应该都有其对应的父路径。
范例:进一步配置
package org.lks.action;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import com.opensymphony.xwork2.ActionSupport;
@SuppressWarnings("serial")
@ParentPackage(value="root") //继承了root包
@Namespace(value="/pages/back/admin/member") //定义了自己的命名空间
@Action(value="MemeberAction")
public class MemberAction extends ActionSupport {
public void insert(){
System.out.println("******* [Member data insert]******");
}
}
但是从实际来讲,每一个Action都有可能配置自己的跳转路径,那么这些result也可以通过Annotation配置。
范例:配置跳转路径
package org.lks.action;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import com.opensymphony.xwork2.ActionSupport;
@SuppressWarnings("serial")
@ParentPackage(value="root") //继承了root包
@Namespace(value="/pages/back/admin/member") //定义了自己的命名空间
@Action(value="MemeberAction")
@Results(value={
@Result(name="success",location="/pages/back/admin/member/insert.jsp",type="redirect"),
@Result(name="list",location="/pages/back/admin/member/list.jsp")
})
public class MemberAction extends ActionSupport {
public String insert(){
System.out.println("******* [Member data insert]******");
return ActionSupport.SUCCESS;
}
}
在整个Struts 2.x里面对于Annotation配置的时候还给了一些比较神奇的支持,例如,可以为每一个方法设置自己的路径。
范例:为update()方法设置一个UpdateAction的路径
@Actions(value={@Action("Update"), @Action("Hello")})
public void update(){
System.out.println("********* [Memeber] data update ********");
}
从此之后,一个Action中的方法就可以轻松的实现多个路径的映射,但是这样的操作并不好用,还是建议在一个Action里面只定义一个路径。
2 拦截器配置
如果要在某一个Action上去使用拦截器,最早都是通过配置得来的,那么现在也可以通过Annotation完成。
范例:在struts.xml文件里面定义拦截器
<!-- 定义拦截器 -->
<interceptors>
<interceptor-stack name="lksStack">
<interceptor name="timer"/>
<interceptor name="defaultStack"/>
</interceptor-stack>
</interceptors>
随后在Action里面去引用这些拦截器。
范例:引用单个拦截器
@InterceptorRef(value="lksStack")
但是很多时候有可能在一个项目里面会引用多个拦截器,那么就使用拦截器组配置。
范例:配置多个拦截器
@InterceptorRefs(value={
@InterceptorRef(value="timer"),
@InterceptorRef(value="defaultStack")
})
那么为什么需要多个拦截器,如果要想进行文件上传,一定需要多个拦截器的综合使用。
范例:文件上传
@InterceptorRefs(value={
@InterceptorRef(value="fileUpload",params={"param1","value1","param2","value2"}),
@InterceptorRef(value="defaultStack")
})
那么以后如果选择上传文件的支持,就使用此Annotation。
3 验证Annotation
虽然Struts 2.x中的养正框架没什么用,但是从实际的开发来讲,Annotation配置的验证还是稍微能够让人觉得简单一些的。
范例:定义一个VO类
package org.lks.vo;
import java.io.Serializable;
@SuppressWarnings("serial")
public class Member implements Serializable {
private Integer mid;
private String name;
private String email;
}
范例:编写验证规则
@Validations(
requiredStrings={
@RequiredStringValidator(fieldName="member.name",message="姓名不允许为空!"),
@RequiredStringValidator(fieldName="member.mid",message="ID不允许为空!"),
@RequiredStringValidator(fieldName="member.email",message="Email不允许为空!")
},
regexFields={
@RegexFieldValidator(fieldName="member.mid",expression="\\d+"),
@RegexFieldValidator(fieldName="member.email",expression="\\w+@\\w+\\.\\w+")
}
)
虽然现在看起来验证规则比较不错,但是从实际的开发来讲,则这种验证规则并不能够被我们所使用,原因只有一点,每一个Action都要进行多业务的处理,所有的规则一定不能够一样。