• 1. Struts2+spring注解配置简介
  • 2. Struts2中使用注解配置Action与Action配置相关的注解 注解(Annotation)是J2SE5.0中提供的新特性,主要作用用于代替XML配置文件,使用注解来提供配置信息。Struts2也提供了使用注解的方式来配置Action,这样就不再需要struts.xml文件,以实现零配置。(需要导入struts2-convention-plugin-2.1.6.jar, 从 struts2.1 版本开始, Convention Plugin 作为替换替换 Codebehind Plugin 来实现 Struts2 的零配置.同时导入Convention 与Codebehind 会出现启动异常) 在此插件中包含如下annotations : 注解名称备注作用域@Action指定一个action名称 类,方法,actions注解中@Actions给一个action指定多个名称方法@ParentPackage指定继承的包(struts2)名 包,类 @Namespace指定action所属的名称空间包,类 @Result定义一个result映射 类,Results注解中 @Results定义一组result映射类,action注解中@Namespaces指定一组action所属的名称空间包,类 @InterceptorRef一个拦截器类,InterceptorRefs注解中 @InterceptorRefs一组拦截器集合类,action注解中
  • 3. Struts2中使用注解配置Action@ParentPackage ParentPackage注解的参数,如下: NameSpace注解的参数如下表: 如: @Namespace(value=“/”) 或@NameSpace(“/list”)参数类型是否必需默认值描述valueString是无指要继承的父包注意:如果注解中只有一个名为value的参数,或者有其他参数,但其他参数都有默认值,那么在为value参数设值时可以忽略value和等号(=),例如: @ParentPackage(value=“struts-default”) @ParentPackage(“struts-default”) 这二种配置是一样的参数类型是否必需默认值描述valueString是无指定action所属的名称空间
  • 4. Struts2中使用注解配置Action@Nampspace及@Namespaces NameSpace注解的参数如下表: 如: @Namespace(value=“/”) 或@NameSpace(“/list”) 注意:如果没有给定Namespace选项,会默认为从定义的.package.locators标示开始到包结束的部分,就是命名空间,比如: com.ustb.web.user.userAction的命名空间是:”/user”。com.ustb.web.user.detail.UserAction的命名空间是:”/user/detail” Namepspaces用于声明一组名称空间。参数如下表所示: 参数类型是否必需默认值描述valueString是无指定action所属的名称空间参数类型是否必需默认值描述valueNamespace否无在里面定义一Namespace的数组@Namespaces({ @Namespace("/crud"), @Namespace("/user") }) public class BookAction extends ActionSupport{ ... } 也就是可以通过发起:/crud/book!add.action /user/book!add.action 二个uri 请求都能访问到Action中的方法
  • 5. Struts2中使用注解配置Action与注解有关的参数 Result注解的参数如表所示: 对应@Results和@Result可分为全局的与本地的 全局的(global) 本地的(local) 参数类型是否必需默认值 描述nameString否Actoin.SUCCESS指定result的逻辑名,即代码结果locationString是无指定result对应的URLtypeString否dispatcher指定result的类型paramsString[]否{}为result传递参数,格式为{key1,value1,key2, value2}@Results({ @Result(name="failure", location="/WEB-INF/fail.jsp") }) public class HelloWorld extends ActionSupport { public String execute(){return "failure";} }public class HelloWorld extends ActionSupport { @Action(value="/other/bar",results={@Result(name = "error", location = "www.baidu.com",type="redirect")}) public String method1() {return "error";} }
  • 6. Struts2中使用注解配置Action与注解有关的参数 Results注解的参数如表所示:参数类型是否必需默认值描述valueResult[]是无为action定义一组result映射示例: @Results({ @Result(name=“input”,value=“/input.jsp”), @Result(name=“success” value=“/success.jsp”) }) //上例中定义了两个result映射。一个逻辑名是input,资源位置是/input.jsp。另一个逻辑名是success,资源位置是/success.jsp
  • 7. Struts2中使用注解配置Action@Action 在默认的情况下,当Action的类名以Action字符结尾(如:HelloAction),不进行任何配置,将默认采用去掉”Action”的字符且把首字母变成小写(如:HelloAction->hello)作为action的名字。如: 通过使用@Action可以ExceptionsMappings[]定action的名称。public class HelloAction extends ActionSupport { public String method1() {...} public String method2() {...} } //如果要调用上述的method1()及method2() 方法,可以用下面URI method1 /hello!method1.action method2 /hello!method2.action参数类型描述valueString指定action的名称resultsResults[]指定此action中的result集合interceptorRefsInterceptorRefs[]指定此action下对应的拦截器paramsString[]提供的参数exceptoinMappingsExceptionMappings指定的异常处理public class HelloAction extends ActionSupport { @Action("action1") public String method1() {...} @Action("/user/action2") public String method2() {...} @Action(value="/user/action3“,results={ @Result(name="viewsuccess",location="/view/showbooks.jsp"), @Result(name="viewinput",location="/view/showbooks.jsp", type="redirectAction“)},interceptorRefs={ @InterceptorRef("mydefaultStack") }) public String method3() {...} } //如果采用此种方式,可以使用如下方式访问 method1 /action1!method1.action. method2 /user/action2!method2.action method3 /user/action3!method3.action
  • 8. Struts2中使用注解配置Action@Actions 可以为action类定义一组访问的action名称,主要有如下参数: 比如: 一个方法被@Action或@Actions注释后,只是多了一种调用方式,而不是说覆盖了原来的调用方式。参数名类型描述valueAction[]用于包含一组@Action注解public class HelloAction extends ActionSupport { @Actions({ @Action("/different/url"), @Action("/another/url") }) public String method1() {...} } /different/url!method1.action 或 /another/url!method1.action 来调用method1 方法。public class HelloAction extends ActionSupport { @Action("/another/url") public String method1() {...} } 我们调用method1方法可以通过两种方式: 1  /hello!method1.action  2 /another/url!method1.action 可见,两种方式均可对method1方法进行调用,唯一的区别就是,两种调用的映射是不一样的,所以,想跳转到不同的界面,这是一个非常好的选择。
  • 9. Struts2中使用注解配置Action当@Namespace与@Action配合使用注意事项 如果在@Action注解中包括”/”字符地,则意味着该注释覆盖了默认的namespace(这里是’/’),此时访问action就有一些小的改动。如下例:@Namespace("/other") public class HelloWorld extends ActionSupport { public String method1() {...} @Action("url") public String method2() { ...} @Action("/different/url") public String method3() {... } } 通过 /other/hello-world!method1.action 访问method1 方法。 通过 /other/url!method2.action 访问method2 方法 通过 /different /url!method3.action 访问method3 方法  与@Action 注释不同的是,该注释覆盖了默认的namespace(这里是’/’),此时再用hello!method1.action 已经不能访问method1 了.
  • 10. Struts2中使用注解配置Action@InterceptorRef及@InterceptorRefs 可以使用@InterceptorRef来为一个action定义一个拦截器,注意此注解只是在此action上引用拦截器,此拦截器需要在struts.xml中进行定义。此注解可以加在类,InterceptorRefs等上面 。 @DefaultInterceptorRef可以合定义一个默认的拦截器. 参数类型描述valueString用于指定拦截器的名字paramsString[]用于指定传递的参数public class HelloWorld extends ActionSupport { @Action(“url”,interceptorRefs={ @InterceptorRef{“mystack”}, @InterceptorRef(“logincheck”) }) public String method2() { ...} } @InterceptorRefs({ @InterceptorRef("mydefaultStack") }) public class HelloWorld extends ActionSupport { public String method2() { ...} }
  • 11. Struts2中使用注解配置Action使用注解配置Action注意事项 在Struts2中使用注解配置action,有一些需要注意的地方。 与action配置相关的4个注解只能用于类级别 需要在web.xml文件中为FilterDispatcher过滤器设置actionPackages参数 指定使用注解配置的Action所在包的列表,多个包之间以逗号(,)分隔。这些包和它们的子包都将被扫描,定包中的所有实现了Action接口的类或是以”Action”结尾的类都将被检测。所以后者允许我们编写POJO Action类,而不需要实现Action接口。如果有多个包,则以逗 号(,)分隔。 包名,名称空间和action名的产生方式如下: Action类所在的包作为action包名 除了使用Namespacke注解指定名称空间外,也可以通过子包名来产生名称空间。如:action所在的包为cn.com.test.action,如果 参数指定的包是cn.com.test,那么“/action”将作为名称空间的名字。 通过action的类名来产生action的名字。如类名以“Action”结尾,那么“Action”将被 去掉,其余部分将首字母变小写作为action的名字。如: RegisterAction 将将会产生的action的名字是register。 如果想让包继承struts-default包,无须使用ParentPackage注解。在框架内部,动让你的包继承struts-default包。 struts                              org.apache.struts2.dispatcher.FilterDispatcher                                 actionPackages                 com.struts2.action1,com.struts.action2-->              com.struts2.action                此配置的作用是帮你导入处理annoation的类,也就相当于不需要再配置 注意在使用需要在头部导入命名空间。
  • 14. Spring2.5中的注解@Autowired 注释 Spring 2.5 引入了 @Autowired 注释,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。来看一下使用 @Autowired 进行成员变量自动注入的代码:public class Boss { @Autowired private Car car; @Autowired private Office office; setter/getter.. } 当 Spring 容器启动时,AutowiredAnnotationBeanPostProcessor 将扫描 Spring 容器中所有 Bean,当发现 Bean 中拥有 @Autowired 注释时就找到和其匹配(默认按类型匹配)的 Bean,并注入到对应的地方中去。 Spring 将直接采用 Java 反射机制对 Boss 中的 car 和 office 这两个私有成员变量进行自动注入。所以对成员变量使用 @Autowired 后,您大可将它们的 setter 方法(setCar() 和 setOffice())从 Boss 中删除。
  • 15. Spring2.5中的注解 @Autowired 对方法或构造函数进行标注 将 @Autowired 注释标注在构造函数上将 @Autowired 注释标注在set方法上将 @Autowired 注释标注在多个参数函数上
  • 16. Spring2.5中的注解当候选 Bean 数目为 0 时的应对方法 在默认情况下使用 @Autowired 注释进行自动注入时,Spring 容器中匹配的候选 Bean 数目必须有且仅有一个。当找不到一个匹配的 Bean 时,Spring 容器将抛出 BeanCreationException 异常,并指出必须至少拥有一个匹配的 Bean。我们可以来做一个实验:由于 office Bean 被注释掉了,所以 Spring 容器中将没有类型为 Office 的 Bean 了,而 Boss 的 office 属性标注了 @Autowired,当启动 Spring 容器时,异常就产生了。当不能确定 Spring 容器中一定拥有某个类的 Bean 时,可以在需要自动注入该类 Bean 的地方可以使用 @Autowired(required = false),这等于告诉 Spring:在找不到匹配 Bean 时也不报错。对于此种情况,一般只会在测试与开发周期中会出现,所以象此种注解很少用到。
  • 17. Spring2.5中的注解当候选 Bean 数目不为 1 时的应对方法 如果 Spring 容器中拥有多个候选 Bean,Spring 容器在启动时也会抛出 BeanCreationException 异常。来看下面的例子: 我们在 Spring 容器中配置了两个类型为 Office 类型的 Bean,当对 Boss 的 office 成员变量进行自动注入时,Spring 容器将无法确定到底要用哪一个 Bean,因此异常发生了。Spring 允许我们通过 @Qualifier 注释指定注入 Bean 的名称,这样歧义就消除了,可以通过下面的方法解决异常:@Qualifier(“office”) 中的 office 是 Bean 的名称,所以 @Autowired 和 @Qualifier 结合使用时,自动注入的策略就从 byType 转变成 byName 了。@Autowired 可以对成员变量、方法以及构造函数进行注释,而 @Qualifier 的标注对象是成员变量、方法入参、构造函数入参。对成员变量使用 @Qualifier 注释对构造函数变量使用 @Qualifier 注释
  • 18. Spring2.5使用使用 JSR-250 的注释@Resource注解 @Resource 的作用相当于 @Autowired,只不过 @Autowired 按 byType 自动注入,面 @Resource 默认按 byName 自动注入罢了。@Resource 有两个属性是比较重要的,分别是 name 和 type,Spring 将 @Resource 注释的 name 属性解析为 Bean 的名字,而 type 属性则解析为 Bean 的类型。所以如果使用 name 属性,则使用 byName 的自动注入策略,而使用 type 属性时则使用 byType 自动注入策略。如果既不指定 name 也不指定 type 属性,这时将通过反射机制使用 byName 自动注入策略。Resource 注释类位于 Spring 发布包的 lib/j2ee/common-annotations.jar 类包中,因此在使用之前必须将其加入到项目的类库中。同时要在 bean.xml文件中加入 //(需要加入声明)
  • 19. Spring2.5使用使用 JSR-250 的注释@PostConstruct 和 @PreDestroy Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,您既可以通过实现 InitializingBean/DisposableBean 接口来定制初始化之后 / 销毁之前的操作方法,也可以通过 元素的 init-method/destroy-method 属性指定初始化之后 / 销毁之前调用的操作方法。 JSR-250 为初始化之后/销毁之前方法的指定定义了两个注释类,分别是 @PostConstruct 和 @PreDestroy,这两个注释只能应用于方法上。标注了 @PostConstruct 注释的方法将在类实例化后调用,而标注了 @PreDestroy 的方法将在类销毁之前调用。 通过 元素的 init-method/destroy-method 属性进行配置,都只能为 Bean 指定一个初始化 / 销毁的方法。但是使用 @PostConstruct 和 @PreDestroy 注释却可以指定多个初始化 / 销毁方法,那些被标注 @PostConstruct 或@PreDestroy 注释的方法都会在初始化 / 销毁时被执行。
  • 20. Spring2.5使用使用 JSR-250 的注释使用 @Component 虽然我们可以通过 @Autowired 或 @Resource 在 Bean 类中使用自动注入功能,但是 Bean 还是在 XML 文件中通过 进行定义 —— 也就是说,在 XML 配置文件中定义 Bean,通过 @Autowired 或 @Resource 为 Bean 的成员变量、方法入参或构造函数入参提供自动注入的功能。能否也通过注释定义 Bean,从 XML 配置文件中完全移除 Bean 定义的配置呢?答案是肯定的,我们通过 Spring 2.5 提供的 @Component 注释就可以达到这个目标了。 下面,我们完全使用注释定义 Bean 并完成 Bean 之间装配:@Component 有一个可选的入参,用于指定 Bean 的名称,在 Boss 中,我们就将 Bean 名称定义为“boss”。一般情况下,Bean 都是 singleton 的,需要注入 Bean 的地方仅需要通过 byType 策略就可以自动注入了,所以大可不必指定 Bean 的名称。简化版本的bean.xml文件用此种方式,不需要在配置文件中再配置bean,也不需要再导入上面对应的处理bean。也就是说可以不需要在配置文件中使用 了,因为此种方式会自动导入
  • 21. Spring2.5使用使用 JSR-250 的注释 @Scope及具有特殊语义的注释 默认情况下通过 @Component 定义的 Bean 都是 singleton 的,如果需要使用其它作用范围的 Bean,可以通过 @Scope 注释来达到目标,如以下代码所示: 采用具有特殊语义的注释 Spring 2.5 中除了提供 @Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository、@Service 和 @Controller。在目前的 Spring 版本中,这 3 个注释和 @Component 是等效的,但是从注释类的命名上,很容易看出这 3 个注释分别和持久层、业务层和控制层(Web 层)相对应。虽然目前这 3 个注释和 @Component 相比没有什么新意,但 Spring 将在以后的版本中为它们添加特殊的功能。所以,如果 Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用 @Repository、@Service 和 @Controller 对分层中的类进行注释,而用 @Component 对那些比较中立的类进行注释。@Scope("prototype") @Component("boss") public class Boss { … }
  • 22. Spring2.5使用使用 JSR-250 的注释说明 还允许定义过滤器将基包下的某些类纳入或排除。Spring 支持以下 4 种类型的过滤方式,通过下表说明: 过滤器类型说明注释假如 com.baobaotao.SomeAnnotation 是一个注释类,我们可以将使用该注释的类过滤出来。类名指定通过全限定类名进行过滤,如您可以指定将 com.baobaotao.Boss 纳入扫描,而将 com.baobaotao.Car 排除在外。正则表达式通过正则表达式定义过滤的类,如下所示: com\.baobaotao\.Default.*AspectJ 表达式通过 AspectJ 表达式定义过滤的类,如下所示: com. baobaotao..*Service+
  • 23. 注释配置和 XML 配置的适用场合使用说明 是否有了这些 IOC 注释,我们就可以完全摒除原来 XML 配置的方式呢?答案是否定的。有以下几点原因: 注释配置不一定在先天上优于 XML 配置。如果 Bean 的依赖关系是固定的,(如 Service 使用了哪几个 DAO 类),这种配置信息不会在部署时发生调整,那么注释配置优于 XML 配置;反之如果这种依赖关系会在部署时发生调整,XML 配置显然又优于注释配置,因为注释是对 Java 源代码的调整,您需要重新改写源代码并重新编译才可以实施调整。 如果 Bean 不是自己编写的类(如 JdbcTemplate、SessionFactoryBean 等),注释配置将无法实施,此时 XML 配置是唯一可用的方式。 注释配置往往是类级别的,而 XML 配置则可以表现得更加灵活。比如相比于 @Transaction 事务注释,使用 aop/tx 命名空间的事务配置更加灵活和简单。 所以在实现应用中,我们往往需要同时使用注释配置和 XML 配置,对于类级别且不会发生变动的配置可以优先考虑注释配置;而对于那些第三方类以及容易发生调整的配置则应优先考虑使用 XML 配置。Spring 会在具体实施 Bean 创建和 Bean 注入之前将这两种配置方式的元信息融合在一起。
  • 24. 在spring2.5中通过注解实现声明式事务@Transactional 除了基于XML文件的声明式事务配置外,在Spring中还支持基于注解方式的事务配置。主要通过使用@Transactional注解来达到目的。 下面我们通过一个例子来演示基于注解方式的声明式事务配置: 当上述POJO定义在spring ioc容器中时,此bean实例只需要简单配置就可以具有事务性。 注意:@Transactional注解只能加在public的方法上,如果加在非public方法,系统不会报错,但是没有对应的事务特性。此POJO可以采用前面的@Commpent配置定义事务处理类,这和以前的配置是一样的,如果将此bean的id设置为transactionManager,那么就可以忽略中的transaction-manager配置
  • 25. Thank you