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.xml中struts2的过滤器用自定义的类替换掉自带的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中包含了spring、strust2、dwr的配置,唯独没有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、包结构:
示例项目中包层次分别为:
Action:action层,包含所有action类,这些类继承BaseAction
Service: 业务层,包含所有处理业务逻辑的类,这些类继承BaseService
Dao :数据连接层,包含所有用于访问数据的类,这些类继承BaseHibernateDao
Framework:框架,包含所有以Base开头的父类,以及DaoFactory
Domain:实体层,由hibernate使用,建立OR映射
Dwr:包含dwr需要调用的所有类
Uitl:工具类,目前仅包含自定义的Strust2过滤器DwrStrutsFilter
4、Action:
a) 所有的Action都通过继承BaseAction来继承Strust2的ActionSupport
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定义出来就是作为一个公共类来使用。
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会报错。
8、DWR
以下是测试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" οnclick="btn_onClick()" />
<div id="info"></div>
</form>
</body>
</html>
到此为止,全文结束,童鞋们可以试着配置一把,有什么问题可以相互探讨探讨,:)