@huynh
2016-06-06T09:20:09.000000Z
字数 12702
阅读 1994
package hust.webservice.service;import hust.webservice.domain.SqlRequest;import hust.webservice.domain.SqlResponse;import javax.jws.WebService;/*** Sql操作服务接口,参数必须有数据库名。<br>* <p>* 1.如果是单表操作,则还需传入表名和参数<br>* 2.如果是多表复杂操作,则提供sql语句,该sql语句可以是完全的sql,也可以是mybatis带参数形式的sql<br>* 3.详细参数见SqlRequest说明<br>* </p>* 所有操作参数都封装在SqlRequest中,本接口所有方法只有该参数。<br>* 所有操作的返回值均封装在了SqlResponse中。* @date 2016年4月8日* @author huynh*/@WebServicepublic interface SqlService {/*** Select* @param sqlRequest* @return*/SqlResponse select(SqlRequest sqlRequest);/*** 查询总数* @param sqlRequest* @return*/SqlResponse selectCount(SqlRequest sqlRequest);/*** Insert<br>* 注意插入日期,需要将日期序列化为"yyyy-MM-dd HH:mm:ss"字符串,下面是使用fastjson注解实体类属性<br>* <pre class="code">* {@code\@JSONField (format="yyyy-MM-dd HH:mm:ss",name="register_time")private Date registerTime;<br>}</pre>实体类必须先使用JSON.toJSONString(javaBean)序列化<br>* @param sqlRequest* @return*/SqlResponse insert(SqlRequest sqlRequest);/*** Update <br>* 只能根据主键或者唯一字段更新* @param sqlRequest* @return*/SqlResponse update(SqlRequest sqlRequest);/*** Delete <br>* paramter和condition只能用其一* @param sqlRequest* @return*/SqlResponse delete(SqlRequest sqlRequest);/*** 多组更新操作需要在一个事务中完成* @param sqls 多组操作的sql语句,使用英文分号;隔开。注意sql的执行顺序* @return 只有返回1表示执行成功,其他情况均为失败*/int updateTransaction(String databaseName,String sqls);}
package hust.webservice.service;import hust.webservice.domain.SqlCondition;import hust.webservice.domain.SqlConditionRule;import hust.webservice.domain.SqlRequest;import hust.webservice.domain.SqlResponse;import java.util.ArrayList;import java.util.List;import java.util.concurrent.CountDownLatch;import org.apache.commons.lang.StringUtils;import org.apache.cxf.endpoint.Client;import org.apache.cxf.frontend.ClientProxy;import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;import org.apache.cxf.transport.http.HTTPConduit;import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/*** 本类为SqlService的代理实现类,供客户端使用,所有业务类都应该使用本类进行WebService的服务调用<br>* 在spring中将本类配置为非单例,配置如下:<br>** <pre class="code">* {@code* <bean id="sqlService" class="hust.dbservice.webservice.SqlServiceProxy" scope="prototype">* <constructor-arg index="0">* <value type="java.lang.String"> WebService服务地址 </value>* </constructor-arg>* </bean>* }* </pre>** @date 2016年4月12日* @author huynh*/public class SqlServiceProxy implements SqlService {private static final Logger logger = LoggerFactory.getLogger(SqlServiceProxy.class);private final SqlService sqlService;private final JaxWsProxyFactoryBean jaxWsProxyFactoryBean;public SqlServiceProxy(String wsdlAddress) {if (StringUtils.isBlank(wsdlAddress)) {throw new RuntimeException("服务地址不能为空!");}jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();try {sqlService = generateProxyClient(SqlService.class, wsdlAddress);} catch (Exception e) {logger.error("Fail to create webservice of SqlService! wsdlAddress={}",new Object[]{wsdlAddress,e});throw new RuntimeException("Fail to create SqlServiceProxy! Could not connect to CXF WebService,WSDL address is " + wsdlAddress);}if (sqlService != null) {logger.info("The webservice of sqlService is created successfully!");}}/*** 生成CXF服务接口代理类** @param classType* 服务接口* @return 服务接口代理类* @throws Exception 可能抛出网络连接异常**/private <T> T generateProxyClient(Class<T> classType, String wsdlAddress) throws Exception {jaxWsProxyFactoryBean.setServiceClass(classType);jaxWsProxyFactoryBean.setAddress(wsdlAddress);T service = (T) jaxWsProxyFactoryBean.create();Client proxy = ClientProxy.getClient(service);HTTPConduit conduit = (HTTPConduit) proxy.getConduit();HTTPClientPolicy policy = new HTTPClientPolicy();policy.setConnectionTimeout(40000); // 连接超时时间,默认30000policy.setReceiveTimeout(40000);// 请求超时时间,默认60000policy.setAllowChunking(false);// 取消块编码conduit.setClient(policy);return service;}@Overridepublic SqlResponse select(SqlRequest sqlRequest) {return sqlService.select(sqlRequest);}@Overridepublic SqlResponse selectCount(SqlRequest sqlRequest) {return sqlService.selectCount(sqlRequest);}@Overridepublic SqlResponse insert(SqlRequest sqlRequest) {return sqlService.insert(sqlRequest);}@Overridepublic SqlResponse update(SqlRequest sqlRequest) {return sqlService.update(sqlRequest);}@Overridepublic SqlResponse delete(SqlRequest sqlRequest) {return sqlService.delete(sqlRequest);}@Overridepublic int updateTransaction(String databaseName, String sqls) {return sqlService.updateTransaction(databaseName, sqls);}}
注:SqlServuceProxy使用方式: 本类为SqlService的代理实现类,供客户端使用,所有业务类都应该使用本类进行WebService的服务调用
在spring中将本类配置为非单例,配置如下:
<bean id="sqlService" class="hust.webservice.service.SqlServiceProxy" scope="prototype"><constructor-arg><value type="java.lang.String">wsdl地址</value></constructor-arg></bean>
数据库服务请求参数的实体类是hust.webservice.domain.ServiceRequest,这个类是固定的。建议所有服务请求参数的包名均为hust.webservice.domain
| 参数名称 | 参数类型 | 是否为空 | 参数说明 |
| databaseName | string | 不能为空 | 数据库名,选择数据源使用 |
| tableName | string | 仅当sqlId不为空时,该参数可以为空 | 数据库表名 |
| sql | string | 单表操作可以为空,其他多表必须指定 | 自定义数据库操作的sql语句,可以是MyBatis的带参数的sql |
| paramter | String | 可以为空 | 数据库操作条件部分字段对应参数,使用equal和and连接,JSONObject类型。 |
| isPage | bool | 默认为false | 是否进行分页查询 |
| pageNo | int | 可以为空 | 分页查询页码 |
| pageSize | int | 可以为空 | 分页查询页大小 |
| orderBy | String | 可以为空 | 排序字段,单表使用,如 根据id排序: orderBy = "id asc" |
| sqlCondition | SqlCondition | 可以为空,如果不为空,优先使用此参数,而忽略tableField参数 | 单表操作条件 |
请求Sql服务的示例(详细可参见服务中单例测试)
//创建数据库服务请求参数实例SqlRequest sqlRequest = new SqlRequest();//指定数据库sqlRequest.setDatabaseName("smartshop");//设置数据库表名sqlRequest.setTableName("user");//设置分页查询sqlRequest.setPage(true);sqlRequest.setPageNo(1);sqlRequest.setPageSize(2);sqlRequest.setOrderBy("buildingnumber desc");//分页查询支持排序//设置查询参数User user = new User();user.setUsername("huynh")//将SqlRequest序列化到ServiceRequest中sqlRequest.setParamter(JSON.toJSONString(user));//调用Web服务SqlResponse sqlResponse = sqlService.select(sqlRequest);//执行的sql = select * from user where username='huynh'
//创建数据库服务请求参数实例SqlRequest sqlRequest = new SqlRequest();//指定数据库sqlRequest.setDatabaseName("smartshop");//设置数据库表名sqlRequest.setTableName("user");//指定要查询的字段sqlRequest.setQueryField("distinct username,password");//设置查询参数User user = new User();user.setUsername("huynh")//将SqlRequest序列化到ServiceRequest中sqlRequest.setParamter(JSON.toJSONString(user));//调用Web服务SqlResponse sqlResponse = sqlService.select(sqlRequest);//执行的sql = select distinct username,password from user where username='huynh'
SqlRequest sqlRequest = new SqlRequest();sqlRequest.setDatabaseName("smartshop");sqlRequest.setTableName("cart");//设置复杂条件List<SqlConditionRule> conditions = new ArrayList<SqlConditionRule>();SqlConditionRule condition = new SqlConditionRule();condition.setField("total_price");condition.setOperation("<");condition.setValue(5);conditions.add(condition);condition = new SqlConditionRule();condition.setField("id");condition.setOperation("<");condition.setValue(37);conditions.add(condition);SqlCondition sqlCondition = new SqlCondition("and", conditions, null);sqlRequest.setSqlCondition(sqlCondition);SqlResponse sqlResponse = sqlService.select(sqlRequest);//执行的sql = select * from cart where total_price<5 and id < 37
SqlRequest sqlRequest = new SqlRequest();sqlRequest.setDatabaseName("smartshop");sqlRequest.setTableName("user");//创建sql语句,这里的语句包含了#{}参数形式sqlRequest.setSql("select a.username,b.name from user as a,shop as b where a.id = b.user_id and a.id = #{id}");//设置参数值sqlRequest.setParamter("{\"id\":1}");SqlResponse sqlResponse = sqlService.select(sqlRequest);
数据库服务响应参数的实体类是hust.webservice.domain.SqlResponse,这个类是固定的。
| 参数名称 | 参数类型 | 参数说明 |
| success | boolean | 服务是否调用成功 |
| errorMsg | String | 服务调用失败错误信息 |
| queryResult | JSON | 数据库查询结果 |
| updateResult | int | 对数据库做更新操作后被影响的行数,如果是插入单条记录,且数据库字段是自增的,则返回插入成功后的id |
| insertId | int | 仅仅针对MySql表主键为id且自增,当插入成功会返回被插入的id |
| totalCount | long | 查询满足条件的总数,对应selectCout方法返回值 |
| totalPage | int | 分页查询后总页数 |
1.先增加数据源配置
位置在dbservice-dal/resource/datasource
<?xml version="1.0" encoding="GBK"?><!-- 商城数据源 --><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:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-3.0.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"><!-- 配置数据源,使用alibaba的DruidDataSource --><bean id="smartshopDataSource" class="com.alibaba.druid.pool.DruidDataSource"init-method="init" destroy-method="close"><!-- 基本连接配置 --><property name="driverClassName" value="${jdbc.driver}" /><property name="url"value="jdbc:mysql://222.20.95.248:3306/smartshop?characterEncoding=utf8" /><property name="username" value="root" /><property name="password" value="Idc+123456" /><!-- 配置初始化大小、最小、最大 --><property name="initialSize" value="${initialSize}" /><property name="minIdle" value="${minIdle}" /><property name="maxActive" value="${maxActive}" /><!-- 配置获取连接等待超时的时间 --><property name="maxWait" value="${maxWait}" /><!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --><property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" /><!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --><property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" /></bean><!-- 线程安全类,可以是单例。用于对数据库的基本操作 --><bean id="smartshopSqlSession" class="org.mybatis.spring.SqlSessionTemplate"><!-- 构造函数中需要传入会话工厂 --><constructor-arg index="0" ref="smartshopSqlSessionFactory" /></bean><!-- MyBatis的会话工厂 --><bean id="smartshopSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="smartshopDataSource" /><!-- 指定 MyBatis XML 映射器文件的位置 <property name="mapperLocations" value="classpath:mapper_smartshop/*.xml"/> --><!-- 配置别名包 使用的时候可以省略包名 <property name="typeAliasesPackage" value="cscec3.dbservice.smartshop.model"/> --><!-- 配置插件 --><property name="plugins"><array><!-- 配置分页插件 --><bean class="com.github.pagehelper.PageHelper"><!-- 这里的几个配置主要演示如何使用,如果不理解,一定要去掉下面的配置 --><property name="properties"><value>dialect=mysqlreasonable=truesupportMethodsArguments=trueparams=count=countSqlautoRuntimeDialect=true</value></property></bean></array></property></bean><!-- 配置 spring 事务管理 --><bean id="smartshopTransactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="smartshopDataSource" /></bean><!-- 由于声明式事务不支持多数据源切换,因此使用的是编程式事务,所以不需要此注解 --><!--<tx:annotation-driven transaction-manager="transactionManager"/> --></beans>
2.将1增加的配置写入总配置
位置在dbservice-dal/resource/hust-dbservice-dal.xml
<?xml version="1.0" encoding="GBK"?><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:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-3.0.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"><!-- 测试用的 <import resource="classpath:datasource/spring-mybatis_test.xml"/> --><!-- 指定jdbc属性配制文件位置 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 正式用的 --><!-- 配置物业数据源 --><import resource="classpath:datasource/datasource_smartproperty.xml" /><!-- 配置权限管理数据源 --><import resource="classpath:datasource/datasource_authorization.xml" /><!-- 配置商城数据源 --><import resource="classpath:datasource/datasource_smartshop.xml" /></beans>
3.将数据源和事务管理器配置当作SqlServiceImpl的属性注入
位置在dbservice-biz/resource/bean/hust-dbservice-bean.xml
<?xml version="1.0" encoding="GBK"?><!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"><beans default-autowire="byName"><!-- 配置数据库服务实例 --><bean id="sqlService" class="hust.dbservice.webservice.impl.SqlServiceImpl" ><!-- 这里配置不同数据源的SqlSessionTemplate实例 --><constructor-arg index="0"><map><entry key="smartshop" value-ref="smartshopSqlSession" /><entry key="smartproperty" value-ref="smartpropertySqlSession" /><entry key="authorization" value-ref="authorizationSqlSession" /></map></constructor-arg><!-- 这里配置不同数据源的TransactionManager实例 --><constructor-arg index="1"><map><entry key="smartshop" value-ref="smartshopTransactionManager" /><entry key="smartproperty" value-ref="smartpropertyTransactionManager" /><entry key="authorization" value-ref="authorizationTransactionManager" /></map></constructor-arg></bean></beans>