需求:
1、服务器端程序是J2EE架构,运行在J2EE服务器上。数据库是Oracle.
2、客户端是Java应用程序,数据库使用的是SQLite;
3、客户端从服务器同步数据。
4、客户端与服务器上数据库中表结构基本相同。
5、客户端发出同步请求时,同步。
总体设计
流程:
1、客户发出同步请求,包含同步哪些数据的条件;
2、服务器响应请求:根据客户端发出的条件准备SQL语句;
3、 创建SimpleOracleJDBCReader实例,该实例可以根据一条SQL查询语句从数据库中获得对应的数据,以中间类型的数据结构存在;创建 SimpleXMLWriter实例,该实例可将中间类型数据写出到XML文档中。创建一个搬运器,将数据从Oracle数据库搬运到XML文件中。
4、服务器返回给客户端一个数据流.该数据流从第3步中生成的xml文件中取数据,发送到客户端
5、客户端接收从服务器发来的xml数据流,生成xml文件,保存在本地
6、在客户端创建SimpleXMLReader从下载的xml读出数据,以中间类型的形式存在;创建SimpleSQLiteJDBCWriter,将中间类型的数据写入到SQLite中;创建一个搬运器,将数据从XML搬运到SQLite数据库文件中。
服务器端程序
private IBaseDAO copyDAO;
private String cachePath = "d:/test/";
/**
* 组装更新数据
*
* @date 2010-11-2
* @param os
* @return
*/
public String getUpdateData(String xmlName, OutputStream os){
if(xmlName != null){
try {
getXML(xmlName , os);
} catch (Exception e) {
e.printStackTrace();
}
return null;
} else {
List<String> sqlList = getSql();
if(sqlList.size()==0){
return null;
}
String result = null;
try {
result = createXMLS(sqlList);
os.write(result.getBytes());
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally{
if(os != null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
}
/**
* 生成多个xml
*
* @date 2010-11-2
* @param sqlList
* @return
* @throws Exception
*/
private String createXMLS(List<String> sqlList) throws Exception{
StringBuffer sb = new StringBuffer();
String temp = null;
for(String sql : sqlList){
temp = createXML(sql);
if(temp != null){
sb.append(temp).append(",");
}
}
return sb.toString();
}
/**
* 生成xml
*
* @date 2010-11-2
* @param sql
* @return
* @throws Exception
*/
private String createXML(String sql) throws Exception{
Reader reader = new SimpleJdbcReader(sql, copyDAO.getConnection());
String objectName = reader.getHeader().getObjectName();
String name = "data_"+objectName+"_"+System.currentTimeMillis()+".xml";
File xmlfile = new File(cachePath + name);
if(!xmlfile.exists()){
xmlfile.createNewFile();
}
Writer xmlWriter = new SimpleXmlWriter(reader.getHeader(), xmlfile);
new SimpleTractor(reader, xmlWriter).start();
return objectName+":"+name;
}
/**
* 下载一个xml文档
*
* @date 2010-11-2
* @param xmlName
* @param os
* @return
* @throws Exception
*/
public InputStream getXML(String xmlName, OutputStream os) throws Exception{
File file = new File(cachePath + xmlName);
FileInputStream is = null;
try {
if(file.exists()){
is = new FileInputStream(file);
byte[] buffer = new byte[8096];
int length = -1;
while((length = is.read(buffer)) != -1){
os.write(buffer, 0, length);
}
} else {
return null;
}
} catch (RuntimeException e) {
e.printStackTrace();
} finally{
if(is != null){
try {
is.close();
} catch (RuntimeException e) {
e.printStackTrace();
}
}
if(os != null){
try {
os.close();
} catch (RuntimeException e) {
e.printStackTrace();
}
}
file.delete();
}
return null;
}
/**
* 组装sql
*
* @date 2010-11-2
* @return
*/
private List<String> getSql(){
List<String> sqlList = new ArrayList<String>();
sqlList.add("select * from users");
return sqlList;
}
客户端程序
/**
* 更新数据
*
* @date 2010-11-2
* @param types
* @param verison
*/
private void updateData(String[] types, String verison){
try {
// 请求服务器准备xml格式的更新数据,每个表一个xml文档,返回xmlName格式是
// tableName1:xml文件名1,tableName2:xml文件名2,....
String[] xmlNames = getXMLNames(types, verison);
if (xmlNames != null && xmlNames.length > 0) {
String urlString = serverUrl + "?copyBean.xmlName=";
File xmlFile = null;
for (String xml : xmlNames) {
if (xml == null) {
continue;
}
// xml格式是 tableName1:xml文件名1
String[] temp = xml.split(":");
if (temp == null || temp.length < 2) {
continue;
}
// 下载xml文件
xmlFile = getFileResponse(urlString + temp[1]);
// 插入新数据
Reader reader = new SimpleXmlReader(xmlFile);
Writer writer = new SimpleSQLiteJdbcWriter(copyDAO.getConnection(), reader.getHeader());
new SimpleTractor(reader, writer).start();
// 删除临时文件
xmlFile.delete();
}
//更新版本号
updateVersion(verison);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 请求服务器准备xml格式的更新数据,每个表一个xml文档,返回xmlName格式是
*
* @date 2010-11-2
* @throws IOException
*/
private String[] getXMLNames(String[] types, String version) throws IOException {
String typeStr = "";
for (String t : types) {
typeStr += "©Bean.allInfoTypes=" + t;
}
String orgId = SysContext.getCurrentUserFromSession().getGroup()
.getId();
String urlString = serverUrl + "?copyBean.fromGroupId=" + orgId
+ typeStr;
if (version != null) {
urlString += "©Bean.verison=" + version;
}
String result = getStringResponse(urlString);
if (result != null) {
String[] fileNames = result.split(",");
return fileNames;
} else {
return null;
}
}
/**
* 获得字符串请求
*
* @date 2010-11-2
* @param urlString
* @return
* @throws IOException
*/
private String getStringResponse(String urlString) throws IOException {
InputStream is = sendHttpRequest(urlString);
StringBuffer sb = new StringBuffer();
try {
byte[] buffer = new byte[8096];
int length = -1;
while ((length = is.read(buffer)) != -1) {
sb.append(new String(buffer, 0, length));
}
} catch (RuntimeException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (RuntimeException e) {
}
}
return sb.toString();
}
/**
* 获取文件
*
* @date 2010-11-2
* @param urlString
* @return
* @throws IOException
*/
private File getFileResponse(String urlString) throws IOException {
InputStream is = sendHttpRequest(urlString);
File xmlfile = new File("data_client_" + System.currentTimeMillis()
+ ".xml");
OutputStream os = null;
if (!xmlfile.exists()) {
xmlfile.createNewFile();
}
os = new FileOutputStream(xmlfile);
try {
byte[] buffer = new byte[8096];
int length = -1;
while ((length = is.read(buffer)) != -1) {
os.write(buffer, 0, length);
}
} catch (RuntimeException e) {
e.printStackTrace();
} finally {
try {
os.close();
} catch (RuntimeException e) {
}
try {
is.close();
} catch (RuntimeException e) {
}
}
return xmlfile;
}
/**
* 发送请求
*
* @date 2010-11-2
* @param urlString
* @return
* @throws IOException
*/
private InputStream sendHttpRequest(String urlString) throws IOException {
HttpURLConnection httpConnection = null;
URL url;
int code = -1;
for (int i = RETRY; i > 0; i--) {
try {
url = new URL(urlString.toString());
httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestMethod("GET");
httpConnection.setDoOutput(true);
httpConnection.setDoInput(true);
httpConnection.setConnectTimeout(TIMEOUT);
httpConnection.setReadTimeout(TIMEOUT);
code = httpConnection.getResponseCode();
if (code != HttpURLConnection.HTTP_OK) {
continue;
}
break;
} catch (SocketTimeoutException e) {
if (i == 1) {
throw new RuntimeException(e);
} else {
continue;
}
} catch (UnknownHostException e) {
if (i == 1) {
throw new RuntimeException(e.getMessage());
} else {
continue;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
if (code == HttpURLConnection.HTTP_OK) {
return httpConnection.getInputStream();
} else {
return null;
}
}