现在的位置: 首页 > 综合 > 正文

Spring2.5.6+Struts2+Hibernate3.6.7+DWR3.0 注解(Annotation)式配置

2013年10月06日 ⁄ 综合 ⁄ 共 11688字 ⁄ 字号 评论关闭

Annotation(注解)JDK5.0及以后版本引入的。它可以用于创建文档,跟踪代码中的依赖性,甚至执行基本编译时检查。注解的使用非常简单,在代码中只需要以‘@注解名这种形式使用即可。除了符号'@'以外,注解的用法和java的基本语法基本相似。

    注解式配置又称为“零配置”。这是由于采用这种配置方式几乎不用写XML配置文件(仍旧有少量配置文件,后文将具体介绍)。在以往的项目中我们总是会使用大量的XML配置来搭建项目,项目越大其对应的配置文件就越多。项目维护时不仅要修改java文件还要修改XMl配置文件。而使用注解式配置则免去了配置文件膨胀以及维护点分散的麻烦,你只需要关注于java文件的修改。

本文的介绍基于Myeclipse9.0

一、JAR

首先向大家介绍引入的jar包。偶是懒人一个,jar包就不一一写出了,特截图如下,图中是示例项目的所有外部jar包:

以上jar包已经表明了版本号,同学们切勿用错。


WEB.XML内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
version="2.5">
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/SpringConfig/beans.xml</param-value>  <!-- Spring配置文件地址 -->
  </context-param>
  <!-- Dwr配置 -->
  <servlet>
    <servlet-name>dwr</servlet-name>
    <servlet-class>org.directwebremoting.spring.DwrSpringServlet</servlet-class>
    <init-param>
      <param-name>debug</param-name>
      <param-value>true</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>dwr</servlet-name>
    <url-pattern>/dwr/*</url-pattern>
  </servlet-mapping>
  <!-- Spring上下文监听器 -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <!-- 编码过滤器 -->
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>utf-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <!-- Strust2配置 -->
  	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>util.DwrStrutsFilter</filter-class>		
		<init-param>
            <param-name>actionPackages</param-name>
            <param-value>com.licong.action</param-value>
        </init-param>
	</filter>

	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

</web-app>

需要注意的是,struts2的过滤器需要使用 <url-pattern>/*</url-pattern> 配置,也就是拦截所有格式的请求。为了能够访问dwr的测试页面能正常工作(dwr测试页面地址为:"localhost:端口号/项目名称/dwr"),不被strust2拦截。本文采用自定义过滤器的方法放行dwr测试页面

public class DwrStrutsFilter extends StrutsPrepareAndExecuteFilter {//继承strust2的过滤器,并加以修改

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest httpRequest = (HttpServletRequest)request;
		if(httpRequest.getRequestURL().indexOf("/dwr") != -1) {//如果请求url中包含“/dwr”则放行
			chain.doFilter(request, response);
		} else {
			super.doFilter(request, response, chain);
		}
	}
	
}

web.xmlstruts2的过滤器用自定义的类替换掉自带的StrutsPrepareAndExecuteFilter 

<!-- Strust2配置 -->  
 <filter>  
   <filter-name>struts2</filter-name> 
    <filter-class>util.DwrStrutsFilter</filter-class>         
        <init-param>  

当然测试页面在项目发布时是需要关闭的,此时只要将

 <servlet-class>org.directwebremoting.spring.DwrSpringServlet</servlet-class>  
     <init-param>  
       <param-name>debug</param-name>  
       <param-value>true</param-value>  
     </init-param> 

 中得true设为false即可。表明dwr不开启调试模式。

Web.xml中包含了springstrust2dwr的配置,唯独没有hibernate。这是因为本文通过Spring来管理hibernate,只需要在spiring的配置文件中配号hibernate的相关配置就可以了。

Spring配置文件,BEAN.XML内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
	xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd


http://www.springframework.org/schema/context


http://www.springframework.org/schema/context/spring-context-2.5.xsd


http://www.springframework.org/schema/aop


http://www.springframework.org/schema/aop/spring-aop-2.5.xsd


http://www.springframework.org/schema/tx


http://www.springframework.org/schema/tx/spring-tx-2.5.xsd


http://www.directwebremoting.org/schema/spring-dwr

           http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd"
	default-autowire="byName">

	<context:annotation-config />


	<!-- 配置Spring 注解扫描范围 -->
	<context:component-scan base-package="com.licong" />

	<!-- 扫描spring注解的类,使其成为客户端调用接口 -->
	<dwr:annotation-config id="dwr_config"/>

	<!-- 扫描需要转换的java对象 -->
	<dwr:annotation-scan scanRemoteProxy="true" base-package="com.licong.dwr" />

	<!-- dwr初始化配置 -->
	<dwr:configuration></dwr:configuration>




	<!-- 配置数据库连接dataSource  -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">


		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
		<property name="url" value="jdbc:oracle:thin:@localhost:1521:TEST" />
		<property name="username" value="lctm2005" />
		<property name="password" value="tiger" />
	</bean>

	<!-- 配置sessionFactory -->
	<bean id="sf"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="packagesToScan">
			<list>
				<value>com.licong.domain</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.OracleDialect
					</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.format_sql">true</prop>
			</props>
		</property>
	</bean>

	<!-- 配置hibernateTemplate -->
	<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
		<property name="sessionFactory" ref="sf"></property>

	</bean>

	<!-- 注解式事务管理 -->
	<tx:annotation-driven transaction-manager="txManager" />
	<bean id="txManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sf" />
	</bean>

</beans>

3、包结构:

示例项目中包层次分别为:

Actionaction层,包含所有action类,这些类继承BaseAction

Service: 业务层,包含所有处理业务逻辑的类,这些类继承BaseService

Dao :数据连接层,包含所有用于访问数据的类,这些类继承BaseHibernateDao

Framework:框架,包含所有以Base开头的父类,以及DaoFactory

Domain:实体层,由hibernate使用,建立OR映射

Dwr:包含dwr需要调用的所有类

Uitl:工具类,目前仅包含自定义的Strust2过滤器DwrStrutsFilter

4、Action

a) 所有的Action都通过继承BaseAction来继承Strust2ActionSupport

b)BaseAction中可以完成一些公共的方法,比如异常日志的记录,操作日志的记录等等

c)以下是子类的代码

//@Namespace(value="/")   //指定名称空间
//@ParentPackage(value="struts-default")  //指定继承的包,struts-default无需指定
@Results({  
	   @Result(name="success",location="/example/exampleResult.jsp"),
       @Result(name="error",location="/framework/error.jsp"),  
       @Result(name="exception",location="/framework/exception.jsp")
})  
@ExceptionMappings({
    @ExceptionMapping(exception = "java.lang.Exception", result = "exception")
})
@Component("exampleAction")
public class ExampleAction extends BaseAction {

	private List<CityPairDomain> cityPairList;

	private CityPairService cityPairService;

	@Override
	@Action ("exampleAction")
	public String execute() throws Exception {
		try{
			cityPairList = cityPairService.getCityPairs();
		}catch(Exception e) {
			e.printStackTrace();
			throw e;
		}
		
		if (null != cityPairList) {	
			return SUCCESS;
		} else {
			return ERROR;
		}
	}

	public List<CityPairDomain> getCityPairList() {
		return cityPairList;
	}

	public void setCityPairList(List<CityPairDomain> cityPairList) {
		this.cityPairList = cityPairList;
	}

	public CityPairService getCityPairService() {
		return cityPairService;
	}

	@Resource
	public void setCityPairService(CityPairService cityPairService) {
		this.cityPairService = cityPairService;
	}
}

我们主要关注注释部分,其实注释大概有哪些大家可以通过XML配置推测出来,该有的总是要有的。

     1)与Action相关的两个Annotation@Action @Actions 
     2@Action中可指定一个value属性。类似于指定<action name=””/>属性值,用于前台请求的映射,这个是必须的 
     3@Action中还可以指定一个params属性,该属性是一个字符串数组,用于该Acion指定的参数名和参数值。params属性应遵守如下格式:{name1,value1,name2,value2,不过各人觉得完全没有这个必要,毕竟strust2已经能够“自动”把前台的form表单的内容映射到action的字段了。
     4@Actions 也用于修饰Action类里的方法,用于将该方法映射到多个URL.@Actions用于组织多个@Action.因此它可将一个方法映射成多个逻辑Action。当某个方法需要被多个不同URL公用时才派上用场,不过各人觉得容易导致混乱的代码,毕竟一般开发是按模块来的,各个类都有其特有作用,除非这个action定义出来就是作为一个公共类来使用。

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

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

7) @Namespace:修饰Action类或其所在的包。该Annotation中指定一个value属性值,用于指定被修饰的Action所在的命名空间
        8) @Namespaces:修饰Action类或其所在的包,用于组合多个@Namespace
        9) @ParentPackage: 用于指定被修饰的Action所在包的父包。 

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

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

12)除此之外,我们还可以定义拦截器,与拦截器配置的Annotation有@InterceptorRef、@InterceptorRefs和@DefaultInterceptorRef 同法与其他注解雷同,就不再介绍了。

如果你需要查看strust2注解配置的结果,struts2提供了Config Browser插件。使用方法:将struts2-config-browser-plugin-2.1.6.jar文件复制到struts2应用的WEB-INF\lib目录中。打开首页地址:http://localhost:8080/应用名字/config-browser/actionNames.action
这里可以看到Config Browser插件的首页。

5、Service

一般来说业务层会抽象为接口供上次使用,例如:

public interface CityPairService {
	public List<CityPairDomain> getCityPairs() throws Exception;
}

而实现类:

@Component("cityPairService")
public class CityPairServiceImpl extends BaseService implements CityPairService {	
	public List<CityPairDomain> getCityPairs() throws Exception{
		return daoFactory.getCityPairDao().getCityPairs();
	}
}

由于在配置文件中配置了按名字进行注入(default-autowire="byName"),在action层调用该接口时需要保证对象名字与注解声明的名字一致。

QueryCityPairAction中部分代码:

private CityPairService cityPairService;
	public CityPairService getCityPairService() {
		return cityPairService;
	}


	@Resource
	public void setCityPairService(CityPairService cityPairService) {
		this.cityPairService = cityPairService;
	}

在set方法上加注解@Resource告知Spring使用set方法注入,当然也可以直接在变量上用@AutoWire注解告诉Spring进行注入操作。

那么BaseService又是怎么实现的呢?

public class BaseService {

	protected DaoFactory daoFactory;

	public DaoFactory getDaoFactory() {
		return daoFactory;
	}

	@Resource
	public void setDaoFactory(DaoFactory daoFactory) {
		this.daoFactory = daoFactory;
	}

}

BaseService中注入了一个叫座DaoFactory的类的对象,该类中包含了所有Dao层类的对象(当然也是通过Spring注入的),任何一个业务层的类只需要调用

DaoFactory的getXXXDao()方法就可以获得相应DAO的对象,免去了再每个service类中注入DAO对象的麻烦。一个service类可能会用到多个DAO对象,会使得该类的代码变的冗长,通过该方法,在业务类中只需要专注于编写业务实现。

@Component("daoFactory")
public class DaoFactory {
	private CityPairDao cityPairDao;

	public CityPairDao getCityPairDao() {
		return cityPairDao;
	}
	@Resource
	private void setCityPairDao(CityPairDao cityPairDao) {
		this.cityPairDao = cityPairDao;
	}
}

6、DAO

考虑到DAO层可能有多种实现方式,hibernate、jdbc等等,DAO层仍旧采用提供接口的方式供上层使用。此处以hibernate访问数据库为例

public abstract class BaseHibernateDao {

	protected HibernateTemplate hibernateTemplate;

	public HibernateTemplate getHibernateTemplate() {
		return hibernateTemplate;
	}

	@Resource
	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}

}

BaseHIbernateDao中注入hibernateTemplate供所有继承该类的dao类使用。这么做同样是为了简化代码,避免在每个Dao类中注入

hibernateTemplate。

7、Domain:

以CityPairDomain为例:

@Entity
@Table(name = "CITYPAIR") //对应的数据库表名
@SequenceGenerator(sequenceName = "SEQ_CITYPAIR", name = "s") //定义Sequence
public class CityPairDomain {
	
	@Id //标注ID,也就是数据库表的主键
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "s")//规定ID的自生成策略为Sequence生成
	private int id;
	@Column(name = "ARRCITYNAME")	//对应的列名,可以不写
	private String arriveCity;
	@Column(name = "ARRCITYCODE")
	private String arriveCityCode;
	@Column(name = "DEPCITYNAME")
	private String depatureCity;
	@Column(name = "DEPCITYCODE")
	private String depatureCityCode;
	
	public int getId() {
		return id;
	}

...set\get方法

}

hibernate可以把上面这个类和数据库中对应的表建立起对应关系。

值得注意的是主键是必须得,没有主键hibernate会报错。

 8DWR

以下是测试DWR页面的截图,部分说明见图



我们需要在页面中调用dwr映射好的方法,我把调用的JS函数卸载名为dwr.js的JS文件中:

function btn_onClick() {
	//调用dwr.xml中配置的类方法,回调函数callback带有返回的结果集    
	TestDwrInvoke.getCityPairs(callback);
}

如果函数有返回值,可以在JS文件中再谢一个callback函数
然后再页面上就需要多调用一个js文件

<!--dwr必备的两个js文件 -->
		<script type='text/javascript' src='/TestDWRSpring/dwr/util.js'>
</script>
		<script type='text/javascript' src='/TestDWRSpring/dwr/engine.js'>
</script>
		<!--配置自己的类 -->
		<script type='text/javascript' src='/TestDWRSpring/dwr/interface/TestDwrInvoke.js'>
</script>

		<!--外部引用JS文件 -->
		<script type="text/javascript" src="./js/dwr.js">
</script>

	</head>
	<body>
		<form name="myform" method="post">
			<input type="button" value="print" onclick="btn_onClick()" />
			<div id="info"></div>
		</form>
	</body>
</html>

到此为止,全文结束,童鞋们可以试着配置一把,有什么问题可以相互探讨探讨,:)

抱歉!评论已关闭.