今天开始使用JAVA WEB工程集成Spring+IBatis+CXF(restful web service),我尽量把一些细节讲清楚,让自己和你们一起成长~
1.首先准备一个动态WEB工程,我把他取名为tnserver,我准备首先完成Spring与IBatis的集成,最后集成CXF,并完成一个资源的CURD操作。
2.准备Spring所需要的jar包,jar为:
- org.springframework.aop-3.1.2.RELEASE.jar
- org.springframework.asm-3.1.2.RELEASE.jar
- org.springframework.aspects-3.1.2.RELEASE.jar
- org.springframework.beans-3.1.2.RELEASE.jar
- org.springframework.context-3.1.2.RELEASE.jar
- org.springframework.context.support-3.1.2.RELEASE.jar
- org.springframework.core-3.1.2.RELEASE.jar
- org.springframework.expression-3.1.2.RELEASE.jar
- org.springframework.instrument-3.1.2.RELEASE.jar
- org.springframework.instrument.tomcat-3.1.2.RELEASE.jar
- org.springframework.jdbc-3.1.2.RELEASE.jar
- org.springframework.orm-3.1.2.RELEASE.jar
- org.springframework.test-3.1.2.RELEASE.jar
- org.springframework.transaction-3.1.2.RELEASE.jar
- org.springframework.web-3.1.2.RELEASE.jar
3.准备CXF RS所需要的jar包,jar为:
- cxf-2.6.13.jar
- jettison-1.3.3.jar
- jsr311-api-1.1.2.r612.jar
- neethi-3.0.3.jar
- wsdl4j-1.6.3.jar
- xmlschema-core-2.0.3.jar
- ezmorph-1.0.4.jar
- slf4j-log4j12-1.7.6.jar
- slf4j-api-1.7.6.jar
4.准备Ibatis所需要的jar包,jar为:
5.其它jar:
- antlr-2.7.7.jar
- aopalliance-1.0.jar
- asm-3.3.jar
- mysql-connector-java-5.1.7-bin.jar mysql数据库驱动jar
- c3p0-0.9.1.2.jar 数据库数据源
- commons-beanutils-1.8.0.jar apache公用jar
- commons-codec-1.4.jar apache公用jar
- commons-collections-3.2.jar apache公用jar
- commons-io-2.0.1.jar apache公用jar
- commons-lang-2.4.jar apache公用jar
- commons-lang3-3.1.jar apache公用jar
- commons-logging-1.1.1.jar apache公用jar
6.完成上述jar包的收集一般会占用大量时间,我希望以后资源都能共享,而且是方便免费的,如果这样相信中国软件行业发展会更好(好的分享往往会让我们成长),附件中我会提供除Spring之外的jar下载。如果你需要spring的jar,可以去spring官网。
7.首先配置
web.xml,其中CXFServlet为CXF初始化配置(这里我将所有的请求都交给CXF处理“/*”):
<?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_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>tnserver</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
8.接下来创建spring的配置文件,这里我把spring的配置文件分成了两份,前缀都一样(为web.xml中applicationContext*.xml),分别是applicationContext-core.xml(存放数据源、注解及扫描、Ibatis配置、BaseDao配置)、applicationContext-server.xml用来发布restful服务的。
9.applicationContext-core.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<!-- 开启注解处理器 -->
<context:annotation-config/>
<!-- 数据源配置 -->
<context:property-placeholder location="classpath:conf/jdbc.properties" />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverName}" />
<property name="jdbcUrl" value="${jdbc.url}" />
<property name="user" value="${jdbc.userName}" />
<property name="password" value="${jdbc.password}" />
<property name="autoCommitOnClose" value="${c3p0.autoCommitOnClose}" />
<property name="checkoutTimeout" value="${jdbc.checkoutTimeout}" />
<property name="initialPoolSize" value="${jdbc.initialPoolSize}" />
<property name="minPoolSize" value="${jdbc.minPoolSize}" />
<property name="maxPoolSize" value="${jdbc.maxPoolSize}" />
<property name="testConnectionOnCheckin" value="${c3p0.testConnectionOnCheckin}" />
<property name="testConnectionOnCheckout" value="${c3p0.testConnectionOnCheckout}" />
<property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}" />
<property name="automaticTestTable" value="${c3p0.automaticTestTable}" />
</bean>
<!-- ibatis2.x 配置 SqlMapClient-->
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:SqlMapConfig.xml"/>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
<bean id="defaultBaseDao" class="cn.thinknet.database.ibatis.DefaultBaseDaoImpl">
<property name="sqlMapClient" ref="sqlMapClient" />
</bean>
<!-- 扫描并自动装配 -->
<context:component-scan base-package="cn.thinknet.common.service" />
<tx:annotation-driven/>
</beans>
10.applicationContext-server.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:p="http://www.springframework.org/schema/p"
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:cxf="http://cxf.apache.org/core"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxrs:server id="healthRestful" address="/health">
<jaxrs:serviceBeans>
<ref bean="healthRestfulBean" />
</jaxrs:serviceBeans>
</jaxrs:server>
<bean id="healthRestfulBean" class="cn.tn.restful.third.health.HealthRestful"></bean>
11.spring配置到此为止,后续我都是采用的注解进行注入的,现在来弄Ibatis的配置SqlMapConfig.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<!-- <settings cacheModelsEnabled="true" enhancementEnabled="true"
lazyLoadingEnabled="true" maxRequests="32" maxSessions="10"
maxTransactions="5" useStatementNamespaces="false" /> -->
<!-- this put xxxx_sqlMap.xml files -->
sqlMap resource="conf/mappings/health_sqlMap.xml" />
</sqlMapConfig>
12.如果你感兴趣,可以继续配置log4j的配置文件log4j.properties:
#--------------------------------
#log4j.rootLogger=DEBUG, stdout, fileout
log4j.rootLogger=INFO, stdout, fileout
#log4j.logger.test=info
#log4j.logger.org.apache.jasper = DEBUG
#log4j.logger.org.apache.catalina.startup.TldConfig = DEBUG
#log4j.logger.org.apache.catalina.session.ManagerBase = DEBUG
log4j.logger.com.fiscal = INFO
log4j.logger.com.system = INFO
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.fileout=org.apache.log4j.RollingFileAppender
log4j.appender.fileout.File=${catalina.home}/logs/tnserver.log
log4j.appender.fileout.MaxFileSize=10000KB
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH\:mm\:ss} \:%m%n
log4j.appender.fileout.layout=org.apache.log4j.PatternLayout
log4j.appender.fileout.layout.ConversionPattern=[%-5p]_%d{yyyy-MM-dd HH\:mm\:ss} \:%m%n
13.以上基本就已经完成一个spring+ibatis+CXF RS集成,下面我开始输出一个实例。
14.创建一个java类:HealthRestful.java:
package cn.tn.restful.third.health;
import java.util.Map;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.QueryParam;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import cn.thinknet.common.service.common.CommonService;
import cn.thinknet.common.service.third.health.HealthService;
import cn.thinknet.utils.exception.AKBaseException;
import cn.thinknet.utils.others.AKJsonValues;
/**
* 第三方健康接口 ,用于存储数据和提取数据
* @author ***
* @date 2014/05/21
*/
public class HealthRestful
{
@Autowired
private HealthService healthService;
@Autowired
private CommonService commonService;
/**
* 保存健康记录
* @param data 第三方数据
* @return String
*/
@POST
public String saveHealthData(String data)
{
boolean flag = true;
try
{
JSONObject jo = JSONObject.fromObject(data);
String deviceId = jo.get("deviceId").toString();
// 校验设备ID是否正确
flag = commonService.validateDeviceId(deviceId);
if (flag)
{
Object obj = jo.get("data");
Map<String,String> map = commonService.getUserAndCardRelation();
// 保存数据
healthService.addHealth(deviceId, obj,map);
}
}
catch (AKBaseException akbe)
{
akbe.writeToLogger();
flag = false;
}
if (flag)
{
// 返回成功
return AKJsonValues.getStatusSuccess().toString();
}
else
{
return AKJsonValues.getStatusFailed().toString();
}
}
/**
* 查询门禁信息
* @param userName 用户名
* @param examProject 体检项目
* @param page 当前页码
* @return 门禁信息 json数组
*/
@GET
public String queryDoor(@QueryParam("userName")
String userName, @QueryParam("examProject")
String examProject, @QueryParam("page")
String page)
{
Boolean flag = true;
JSONArray ja = new JSONArray();
JSONObject jo = new JSONObject();
try
{
int pageIndex = NumberUtils.toInt(page);
// 执行方法
ja = healthService.queryHealth(userName, examProject, pageIndex);
}
catch (AKBaseException akbe)
{
akbe.writeToLogger();
flag = false;
}
if (flag)
{
// 成功
jo.put(AKJsonValues.STATUS_KEY, AKJsonValues.STATUS_SUCCESS);
jo.put("list", ja);
}
else
{
// 失败
jo.put(AKJsonValues.STATUS_KEY, AKJsonValues.STATUS_FAILED);
jo.put("list", "");
}
return jo.toString();
}
}
15.service层代码HealthService.java:
package cn.thinknet.common.service.third.health;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.thinknet.database.ibatis.BatisBaseDao;
import cn.thinknet.utils.date.AKDateUtil;
import cn.thinknet.utils.exception.AKBaseException;
import cn.thinknet.utils.others.AKPagination;
import cn.thinknet.utils.vo.third.health.HealthVo;
/**
* 健康业务类
*
* @date 2014/05/21
*
* @author ****
*/
@Service("healthService")
public class HealthService
{
@Autowired
private BatisBaseDao baseDao;
/**
* 保存第三方健康数据
*
* @param deviceId 设备号
* @param data 第三方数据
* @throws AKBaseException
*/
public void addHealth(String deviceId, Object data, Map<String, String> map)
throws AKBaseException
{
if (MapUtils.isNotEmpty(map))
{
return;
}
try
{
// 将第三方数据转换成Json数组
JSONArray ja = JSONArray.fromObject(data);
JSONObject jo = null;
HealthVo hv = null;
for (Object obj : ja)
{
// 获得JSON对象
jo = JSONObject.fromObject(obj);
hv = new HealthVo();
hv.setCardNo(jo.getString("cardNo"));
// 根据卡号找到用户名
hv.setUserName(map.get(jo.getString("cardNo")));
hv.setDeviceId(deviceId);
hv.setExamProject(jo.getString("examProject"));
hv.setExamValue(jo.getString("examValue"));
hv.setExamUnit(jo.getString("examUnit"));
hv.setExamStatus(jo.getInt("examStatus"));
hv.setExamTime(AKDateUtil.stringConvertDate(
jo.getString("examTime"), AKDateUtil.DATEFORMAT002));
// 存储到数据库中
baseDao.add("third_health_insert", hv);
}
}
catch (AKBaseException ake)
{
throw new AKBaseException(ake);
}
}
/**
* 查询第三方健康信息
*
* @param userName 用户名
* @param examProject 体检项目
* @param 页码
* @return JSONArray
* @throws AKBaseException
*/
@SuppressWarnings("unchecked")
public JSONArray queryHealth(String userName, String examProject,
int pageIndex) throws AKBaseException
{
List<HealthVo> hList = null;
JSONObject jo = null;
JSONArray ja = new JSONArray();
try
{
Map<String, Object> params = new HashMap<String, Object>();
pageIndex = pageIndex == 0 ? 1 : pageIndex;
params.put(AKPagination.MYSQL_PAGE_ROW_NUMBER_KEY, (pageIndex - 1)
* AKPagination.MYSQL_PAGE_SIZE_KEY);
params.put(AKPagination.MYSQL_PAGE_ROW_SIZE_KEY,
AKPagination.MYSQL_PAGE_SIZE_KEY);
params.put("userName", userName);
params.put("examProject", examProject);
hList = (List<HealthVo>) baseDao.queryPagination(
"third_health_select", params);
// 将查询出来的数据转换成JSON数组
if (CollectionUtils.isNotEmpty(hList))
{
for (HealthVo hv : hList)
{
jo = new JSONObject();
jo.put("cardNo", hv.getCardNo());
jo.put("examProject", hv.getExamProject());
jo.put("examValue", hv.getExamValue());
jo.put("examUnit", hv.getExamUnit());
jo.put("examStatus", hv.getExamStatus());
jo.put("examTime",
AKDateUtil.dateConvetStringByFormat(
hv.getExamTime(), AKDateUtil.DATEFORMAT002));
ja.add(jo);
}
}
}
catch (AKBaseException ake)
{
throw new AKBaseException(ake);
}
return ja;
}
}
16.这里列出我一直用来访问数据的接口与默认实现类,接口类BatisBaseDao.java:
package cn.thinknet.database.ibatis;
import java.io.Serializable;
import java.util.List;
import cn.thinknet.utils.exception.AKSQLException;
/**
* 数据库操作父接口
*
* @author 李时增
*
* CreateTime 2013-03-10
*/
public interface BatisBaseDao extends Serializable
{
/**
* 添加对象
*
* @param sqlId IBatis SQL Id
* @param obj 需要添加的对象
*
* @throws AKSQLException SQL异常
*/
void add(String sqlId, Object obj) throws AKSQLException;
/**
* 删除对象
*
* @param sqlId IBatis SQL Id
* @param params 删除参数
*
* @throws AKSQLException SQL异常
*/
void delete(String sqlId, Object params) throws AKSQLException;
/**
* 根据条件查询数据,此方法不分页
*
* @param sqlId IBatis SQL Id
* @param params 查询参数
*
* @throws AKSQLException SQL异常
*
* @return List<Object> 查询结果集合
*/
List<?> query(String sqlId, Object params) throws AKSQLException;
/**
* 根据条件查询数据,用于分页
*
* @param sqlId IBatis SQL Id
* @param params 查询参数
*
* @throws AKSQLException SQL异常
*
* @return List<Object> 查询结果集合
*/
List<?> queryPagination(String sqlId, Object params)
throws AKSQLException;
/**
* 根据条件查询数据记录数,用于分页
*
* @param sqlId IBatis SQL Id
* @param params 查询参数
*
* @throws AKSQLException SQL异常
*
* @return List<Object> 查询结果集合
*/
int queryCount(String sqlId, Object params) throws AKSQLException;
/**
* 查询一条记录
*
* @param sqlId IBatis SQL Id
* @param params 查询参数
*
* @throws AKSQLException SQL异常
*
* @return List<Object> 查询结果集合
*/
Object queryOneModel(String sqlId, Object params) throws AKSQLException;
/**
* 查询所有数据
*
* @param sqlId IBatis SQL Id
* @param params 查询参数
*
* @throws AKSQLException SQL异常
*
* @return List<Object> 查询结果集合
*/
List<?> queryAll(String sqlId) throws AKSQLException;
/**
* 更新对象
*
* @param sqlId IBatis SQL Id
* @param updateObj 需要更新的对象
*
* @throws AKSQLException SQL异常
*/
void update(String sqlId, Object updateObj) throws AKSQLException;
}
实现类DefaultBaseDaoImpl.java:
package cn.thinknet.database.ibatis;
import java.util.List;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
import cn.thinknet.utils.exception.AKSQLException;
/**
* 数据库操作父类
*
* @author lishizeng
*
* CreateTime 2013-03-10
*/
public class DefaultBaseDaoImpl extends SqlMapClientDaoSupport implements BatisBaseDao
{
private static final long serialVersionUID = -2493529163246756507L;
/**
* 添加对象
*
* @param sqlId IBatis SQL Id
* @param obj 需要添加的对象
*
* @throws AKSQLException SQL异常
*/
@Override
public void add(String sqlId, Object obj) throws AKSQLException
{
try
{
this.getSqlMapClientTemplate().insert(sqlId, obj);
}
catch (Exception sqle)
{
throw new AKSQLException(sqle.getMessage(), sqle.getCause());
}
}
/**
* 删除对象
*
* @param sqlId IBatis SQL Id
* @param params 删除参数
*
* @throws AKSQLException SQL异常
*/
@Override
public void delete(String sqlId, Object params) throws AKSQLException
{
try
{
this.getSqlMapClientTemplate().delete(sqlId, params);
}
catch (Exception sqle)
{
throw new AKSQLException(sqle.getMessage(), sqle.getCause());
}
}
/**
* 根据条件查询数据,此方法不分页
*
* @param sqlId IBatis SQL Id
* @param params 查询参数
*
* @throws AKSQLException SQL异常
*
* @return List<Object> 查询结果集合
*/
@Override
public List<?> query(String sqlId, Object params) throws AKSQLException
{
List<?> list = null;
try
{
list = this.getSqlMapClientTemplate().queryForList(sqlId,
params);
}
catch (Exception sqle)
{
throw new AKSQLException(sqle.getMessage(), sqle.getCause());
}
return list;
}
/**
* 查询所有数据
*
* @param sqlId IBatis SQL Id
* @param params 查询参数
*
* @throws AKSQLException SQL异常
*
* @return List<Object> 查询结果集合
*/
@Override
public List<?> queryAll(String sqlId) throws AKSQLException
{
List<?> list = null;
try
{
list = this.getSqlMapClientTemplate().queryForList(sqlId);
}
catch (Exception sqle)
{
throw new AKSQLException(sqle.getMessage(), sqle.getCause());
}
return list;
}
/**
* 更新对象
*
* @param sqlId IBatis SQL Id
* @param updateObj 需要更新的对象
*
* @throws AKSQLException SQL异常
*/
@Override
public void update(String sqlId, Object updateObj) throws AKSQLException
{
try
{
this.getSqlMapClientTemplate().update(sqlId, updateObj);
}
catch (Exception sqle)
{
throw new AKSQLException(sqle.getMessage(), sqle.getCause());
}
}
/**
* 根据条件查询数据,用于分页
*
* @param sqlId IBatis SQL Id
* @param params 查询参数
*
* @throws AKSQLException SQL异常
*
* @return List<Object> 查询结果集合
*/
@Override
public List<?> queryPagination(String sqlId, Object params)
throws AKSQLException
{
List<?> list = null;
try
{
list = this.getSqlMapClientTemplate().queryForList(sqlId,
params);
}
catch (Exception sqle)
{
throw new AKSQLException(sqle.getMessage(), sqle.getCause());
}
return list;
}
/**
* 根据条件查询数据记录数,用于分页
*
* @param sqlId IBatis SQL Id
* @param params 查询参数
*
* @throws AKSQLException SQL异常
*
* @return List<Object> 查询结果集合
*/
@Override
public int queryCount(String sqlId, Object params) throws AKSQLException
{
int count = 0;
try
{
count = Integer.valueOf(this.getSqlMapClientTemplate()
.queryForObject(sqlId, params).toString());
}
catch (NumberFormatException e)
{
count = 0;
}
catch (Exception e)
{
throw new AKSQLException(e.getMessage(), e.getCause());
}
return count;
}
/**
* 查询一条记录
*
* @param sqlId IBatis SQL Id
* @param params 查询参数
*
* @throws AKSQLException SQL异常
*
* @return List<Object> 查询结果集合
*/
@Override
public Object queryOneModel(String sqlId, Object params)
throws AKSQLException
{
try
{
return this.getSqlMapClientTemplate().queryForObject(sqlId,
params);
}
catch (Exception e)
{
throw new AKSQLException(e.getMessage(), e.getCause());
}
}
}
20.如果你想要什么jar包或是哪里有什么不明白的请发我邮箱
[email protected],我尽量帮助你:)