Apache CXF 在項目中的真實運用--WS服務編寫
我的項目是一個醫療用品公司的網站,其中的診所數據、工單數據、工單圖片數據來自客戶的另個自己CS系統。客戶需要每天定時上傳這些數據到我的服務器。考慮使用WebService作為解決方案.
1、處于了團隊分工合作考慮,我的整個解決方案由多個項目構成:

2、SY WS就是CXF WebService項目,這個WS比較簡單:
項目結構:

各個包說明如下:
com.defshare.sy.ws:WS接口包
com.defshare.sy.ws.config:WS配置包
com.defshare.sy.ws.impl:WS實現類包
com.defshare.sy.ws.po:WS的VO類包
com.defshare.sy.ws.test:WS測試包
ws.properties:存放WS所有接口訪問的安全賬戶和密碼以及文件上傳后的存放路徑
只有一個接口,代碼如下:
package com.defshare.sy.ws;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import com.defshare.sy.ws.po.Clinique;
import com.defshare.sy.ws.po.ToothSpec;
import com.defshare.sy.ws.po.WorkList;
import com.defshare.sy.ws.po.WorkListPicFile;
@WebService(targetNamespace="http://www.springframework.org/schema/beans")
public interface ISYWebService {
/**
* <pre>
* 上傳工單[工單中包含牙齒規格],同時記錄工單上傳歷史
* </pre>
* @param workLists 要上傳工單所組成的數組
* @return 上傳結果
*/
@WebMethod
public int upLoadWorkList(@WebParam String userName,@WebParam String password,@WebParam WorkList[] workLists);
/**
* 上傳診所信息,同時記錄上傳歷史
* @param cliniques 要上傳診所所組成的數組
* @return 上傳結果
*/
public int upLoadClinique(@WebParam String userName,@WebParam String password,@WebParam Clinique[] cliniques);
/**
* 上傳工單圖片文件,如果該圖片文件對應的工單編號在系統中不存在則當前文件上傳失敗
* @param file 要上傳的工單圖片文件
* @return 上傳結果
*/
@WebMethod
public int upLoadWorkListPic(@WebParam String userName,@WebParam String password,@WebParam WorkListPicFile file);
/**
* 更新工單,工單編號不能存在則更新失敗
* @param workList 包含更新后工單信息的工單對象
* @return 更新結果
*/
@WebMethod
public int updateWorkList(@WebParam String userName,@WebParam String password,@WebParam WorkList workList);
/**
* 更新牙齒規格的工序
* @param toothSpecId 牙齒規格編號
* @param gx 新的工序
* @return
*/
@WebMethod
public int updateToothSpecGX(@WebParam String toothSpecId,@WebParam String gx);
/**
* 更新診所信息,診所編號不存在則更新失敗
* @param cliniques 包含更新后診所信息的工單對象
* @return 更新結果
*/
@WebMethod
public int updateClinique(@WebParam String userName,@WebParam String password,@WebParam Clinique cliniques);
/**
* 刪除工單,刪除工單要一并刪除工單對應的圖片
* @param workListId 要刪除工單的編號
* @return 刪除結果
*/
@WebMethod
public int removeWorkList(@WebParam String userName,@WebParam String password,@WebParam String workListId);
/**
* <h3>成功</h3>
* <p>SUCCESS = 0</p>
*/
public static final int SUCCESS = 0;
/**
* <h3>工單編號為空</h3>
* <p>WORKLIST_ID_IS_EMPTY = 1</p>
*/
public static final int WORKLIST_ID_IS_EMPTY = 1;
/**
* <h3>診所編號為空</h3>
* <p>CLINIQUE_ID_IS_EMPTY = 2</p>
*/
public static final int CLINIQUE_ID_IS_EMPTY = 2;
/**
* <h3>沒有文件信息上傳</h3>
* <p>NO_FILEINFO_UPLOAD = 3</p>
*/
public static final int NO_FILEINFO_UPLOAD = 3;
/**
* <h3>沒有工單信息可以上傳</h3>
* <p> NO_WORKLIST_UPLOAD = 4</p>
*/
public static final int NO_WORKLIST_UPLOAD = 4;
/**
* <h3>沒有工單圖片文件可以上傳</h3>
* <p> NO_WORKLIST_PIC_UPLOAD = 5</p>
*/
public static final int NO_WORKLIST_PIC_UPLOAD = 5;
/**
* <h3>沒有診所信息可以上傳</h3>
* <p>NO_CLINIQUE_UPLOAD = 6</p>
*/
public static final int NO_CLINIQUE_UPLOAD = 6;
/**
* <h3>沒有工單可以更新</h3>
* <p>NO_WORKLIST_UPDATE = 7</p>
*/
public static final int NO_WORKLIST_UPDATE = 7;
/**
* <h3>沒有診所信息可以更新</h3>
* <p>NO_CLINIQUE_UPDATE = 8</p>
*/
public static final int NO_CLINIQUE_UPDATE = 8;
/**
* <h3>不安全的調用</h3>
* <p>INSECURE_CALL = 9</p>
*/
public static final int INSECURE_CALL = 9;
/**
* <h3>不存在的工單[上傳工單圖片時檢查]</h3>
* <p>NO_EXSITS_WORKLIST = 10</p>
*/
public static final int NO_EXSITS_WORKLIST = 10;
/**
* <h3>輸入輸出異常</h3>
* <p>IO_EXCEPTION = 11</p>
*/
public static final int IO_EXCEPTION = 11;
/**
* <h3>錄入數據失敗[存在重復數據]</h3>
* <p>IO_EXCEPTION = 12</p>
*/
public static final int IO_REPEAT = 12;
/**
* 應用程序異常
*/
public static final int APPLICATION_EXCEPTION = 13;
/**
* 數據庫異常
*/
public static final int SQLEXCEPTION = 14;
/**
* <h3>規格編號為空</h3>
* <p>TOOTHSPEC_ID_IS_EMPTY = 15</p>
*/
public static final int TOOTHSPEC_ID_IS_EMPTY = 15;
}
3、實現類如下:
package com.defshare.sy.ws.impl;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.Timestamp;
import java.util.List;
import java.util.UUID;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.servlet.ServletContext;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.aspectj.lang.annotation.AfterThrowing;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.web.context.ServletContextAware;
import com.defshare.foundation.dao.IHibernateCallback;
import com.defshare.foundation.global.DateUtil;
import com.defshare.foundation.global.ExceptionUtil;
import com.defshare.foundation.pubs.Md5Encrypt;
import com.defshare.sy.biz.impl.ServiceTemplate;
import com.defshare.sy.po.SystemLog;
import com.defshare.sy.po.ToothSpec;
import com.defshare.sy.po.WorkListHistory;
import com.defshare.sy.ws.ISYWebService;
import com.defshare.sy.ws.po.Clinique;
import com.defshare.sy.ws.po.WorkList;
import com.defshare.sy.ws.po.WorkListPicFile;
//@Service("syWebService")
@WebService(targetNamespace = "http://www.springframework.org/schema/beans")
public class SYWebService implements ISYWebService, ServletContextAware {
Logger LOG = Logger.getLogger(SYWebService.class);
/**
* 刪除工單
*
* <pre>
* 1.查詢出工單關聯的圖片名稱:xxx.jpg,xxx2.jpg,xxx3.jpg
* 2.刪除工單關聯的牙齒規格數據 session.delete(arg0)
* 3.刪除工單數據 session.delete(arg0)
* 4.循環刪除管理的圖片
* 5.以上步驟2、3、4必須運行在一個事務里面
* </pre>
*/
@Override
public int removeWorkList(@WebParam String userName,
@WebParam String password, final String workListId) {
// 判斷登陸信息是否有效
if (!isSecure(userName, password))
return INSECURE_CALL;
// 判斷工單id是否有效
if (StringUtils.isBlank(workListId))
return WORKLIST_ID_IS_EMPTY;
return (Integer)serviceTemplate.getCommonDao().execute(new IHibernateCallback() {
@SuppressWarnings("unchecked")
@Override
public Object doInHibernate(Session session) {
// 刪除工單
LOG.info(session.isOpen() ? "Hibernate Session 是有效的"
: "Hibernate session是無效的");
try {
ProjectionList plist = Projections.projectionList();
plist.add(Projections.property("pics"));
plist.add(Projections.property("gdbh"));
// 查詢工單圖片
Object[] wl = (Object[]) session.createCriteria(
com.defshare.sy.po.WorkList.class).setProjection(
plist).add(Restrictions.eq("gdbh", workListId))
.uniqueResult();
if (wl == null && wl.length <= 0)
return NO_EXSITS_WORKLIST;
LOG
.info("-------------------------------------------------------------------------------");
String pics = null;
String[] picses = null;
if (wl[0] != null) {
pics = wl[0].toString();
picses = pics.split(",");
}
LOG.info("-----------圖片名稱-------------" + pics);
// 查詢牙齒規格
List<ToothSpec> toothlist = (List<ToothSpec>) session
.createCriteria(ToothSpec.class).add(
Restrictions.eq("gdbh", workListId)).list();
// 循環刪除牙齒規格
if (toothlist != null && toothlist.size() > 0) {
for (ToothSpec toothSpec : toothlist) {
session.delete(toothSpec);
LOG.info("刪除牙齒規格成功");
}
}
// 刪除工單
com.defshare.sy.po.WorkList worklist = new com.defshare.sy.po.WorkList();
worklist.setGdbh(workListId);
session.delete(worklist);
LOG.info("刪除工單成功");
// LOG.info("===========================" + getSavepath());
// File file = new File(getSavepath());
// String path = file.getAbsolutePath();
// System.out.println("---------" + path);
// // 循環刪除本地圖片 --------------------(本地測試)worklist
// if (picses != null && picses.length > 0) {
// for (String ps : picses) {
// File f = new File(path + "/" + ps);
// f.delete();
// LOG.info("每次本地刪除文件成功");
// }
// }
// 循環刪除本地圖片 --------------------(服務器)
if (picses != null && picses.length > 0) {
for (String ps : picses) {
File f = new File(servletContext.getRealPath("/")
+ "/" + getSavepath() + "/" + ps);
f.delete();
}
}
} catch (HibernateException e) {
return NO_EXSITS_WORKLIST;
}
return SUCCESS;
}
});
}
/**
* 上傳診所信息
*/
@Override
public int upLoadClinique(@WebParam String userName,
@WebParam String password, final Clinique[] cliniques) {
if (!isSecure(userName, password))
return INSECURE_CALL;
if (null == cliniques || 0 == cliniques.length)
return NO_CLINIQUE_UPLOAD;
return (Integer)serviceTemplate.getCommonDao().execute(new IHibernateCallback() {
private static final long serialVersionUID = -1708351120071544240L;
@Override
public Object doInHibernate(Session session) {
for (Clinique clinique : cliniques) {
if (StringUtils.isBlank(clinique.getZsid()))
return CLINIQUE_ID_IS_EMPTY;
com.defshare.sy.po.Clinique cli = new com.defshare.sy.po.Clinique();
cli.setDq(clinique.getDq());
cli.setZsid(clinique.getZsid());
cli.setDqbh(clinique.getDqbh());
cli.setDxts(clinique.getDxts());
cli.setLxdh(clinique.getLxdh());
cli.setYsxm(clinique.getYsxm());
cli.setYwjl(clinique.getYwjl());
cli.setYwy(clinique.getYwy());
cli.setZsdz(clinique.getZsdz());
cli.setZsjx(clinique.getZsjx());
cli.setZsmc(clinique.getZsmc());
if(clinique.getZsmm()==null || "".equals(clinique.getZsmm())){
clinique.setZsmm("0000");
}
cli.setZsmm(new Md5Encrypt().getMD5ofStr(clinique.getZsmm()));//MD5后再存入數據庫
try {
session.save(cli);
} catch (Exception e) {
return IO_REPEAT;
}
WorkListHistory workList = new WorkListHistory();
workList.setKind("2");
workList.setReceiveTime(new Timestamp(System
.currentTimeMillis()));
workList.setBh(cli.getZsid());
workList.setWorkListHistoryId(UUID.randomUUID().toString());
session.save(workList);
}
return SUCCESS;
}
});
}
/**
* 上傳工單
*/
@Override
public int upLoadWorkList(@WebParam String userName,
@WebParam String password, final WorkList[] workLists) {
if (null == workLists || 0 == workLists.length)
return NO_WORKLIST_UPLOAD;
if (!isSecure(userName, password))
return INSECURE_CALL;
return (Integer) serviceTemplate.getCommonDao().execute(new IHibernateCallback() {
private static final long serialVersionUID = -3808681177275551002L;
@Override
public Object doInHibernate(Session session) {
for (WorkList workList : workLists) {
LOG.info(workList.getGdbh());
if (StringUtils.isBlank(workList.getGdbh()))
return WORKLIST_ID_IS_EMPTY;
com.defshare.sy.po.WorkList wo = new com.defshare.sy.po.WorkList();
wo.setBrxm(workList.getBrxm());
wo.setCjr(workList.getCjr());
wo.setCjrq(Timestamp.valueOf(workList.getCjrq()));
wo.setFggdbh(workList.getFggdbh());
wo.setFgyy(workList.getFgyy());
wo.setGdbh(workList.getGdbh());
wo.setJjrq(Timestamp.valueOf(workList.getJjrq()));
wo.setJzrq(Timestamp.valueOf(workList.getJzrq()));
wo.setLuz(workList.getLuz());
wo.setPics(workList.getPics());
wo.setSsdq(workList.getSsdq());
wo.setYsxm(workList.getYsxm());
wo.setYwy(workList.getYwy());
wo.setZsid(workList.getZsid());
session.save(wo);
if (workList.getToothSpecs()!= null) {
LOG.info("------------jin---------");
for (com.defshare.sy.ws.po.ToothSpec tt : workList
.getToothSpecs()) {
if(tt!=null){
ToothSpec ts = new ToothSpec();
ts.setToothSpecId(tt.getToothSpecId());
ts.setAddsl(tt.getAddsl());
ts.setDx(tt.getDx());
ts.setGdbh(wo.getGdbh());
ts.setGx(tt.getGx());
ts.setHbhid(tt.getHbhid());
ts.setJg(tt.getJg());
ts.setSl(tt.getSl());
ts.setYclx(tt.getYclx());
ts.setYs(tt.getYs());
ts.setYw(tt.getYw());
ts.setZl(tt.getZl());
session.save(ts);
}}
}
LOG.info("------------沒進---------");
WorkListHistory work = new WorkListHistory();
work.setKind("0");
work.setReceiveTime(new Timestamp(System
.currentTimeMillis()));
work.setBh(workList.getGdbh());
work.setWorkListHistoryId(UUID.randomUUID().toString());
session.save(work);
}
return SUCCESS;
}
});
}
/**
* 上傳工單圖片文件
*/
@Override
public int upLoadWorkListPic(@WebParam String userName,
@WebParam String password, final WorkListPicFile file) {
LOG.info("-----------------------------------------------------");
LOG.info("開始執行上傳工單圖片");
if (!isSecure(userName, password))
return INSECURE_CALL;
if (StringUtils.isBlank(file.getWorkListId()))
return WORKLIST_ID_IS_EMPTY;
if (file.getPosition() == 0) {
LOG.info("首次上傳文件塊,檢查是否存在該圖片關聯的工單[" + file.getWorkListId() + "]");
// 如果是首次上傳則檢查工單編號對應的工單在系統中是否存在
Object result = serviceTemplate.getCommonDao().execute(
new IHibernateCallback() {
@Override
public Object doInHibernate(Session session) {
LOG
.info(session.isOpen() ? "Hibernate Session 是有效的"
: "Hibernate session是無效的");
return session.createCriteria(
com.defshare.sy.po.WorkList.class)
.setProjection(Projections.rowCount()).add(
Restrictions.eq("gdbh", file
.getWorkListId()))
.uniqueResult();
}
});
LOG.info("檢查結果,存在[" + result + "]條");
if (result == null || Integer.valueOf(result.toString()) != 1) {
return NO_EXSITS_WORKLIST;
}
}
// 執行上傳
LOG.info("執行上傳文件塊[" + file.getBytes().length + "\t"
+ file.getPosition() + "/" + file.getFileSize() + "]");
OutputStream os = null;
try {
File f = new File(servletContext.getRealPath("/") + "/"
+ getSavepath() + "/" + file.getServerFile());
LOG.info("服務器保存文件路徑:" + f.getAbsolutePath());
if (file.getPosition() != 0) {
os = FileUtils.openOutputStream(f, true);
} else {
os = FileUtils.openOutputStream(f, false);
}
os.write(file.getBytes());
} catch (IOException e) {
return IO_EXCEPTION;
} finally {
if (os != null)
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
IOUtils.closeQuietly(os);
}
LOG.info("上傳文件塊完成");
// 如果是最后一次上傳則修改工單
if (file.getPosition() + file.getBytes().length == file.getFileSize()) {
LOG.info("最后一次上傳文件數據塊,上傳后修改工單的圖片字段");
com.defshare.sy.po.WorkList workList = serviceTemplate.findById(
com.defshare.sy.po.WorkList.class, file.getWorkListId());
String pics = workList.getPics();
pics = pics == null ? "" : pics;
pics = pics.equals("") ? file.getServerFile() : pics + ","
+ file.getServerFile();
workList.setPics(pics);
}
LOG.info("執行本次上傳工單圖片完成\n");
return SUCCESS;
}
/**
* 更新診所信息
*/
@Override
public int updateClinique(@WebParam String userName,
@WebParam String password, final Clinique clinique) {
LOG.info("-----------------------------------------------------");
LOG.info("----------------開始執行更新---------------------");
if (null == clinique)
return NO_CLINIQUE_UPDATE;
if (StringUtils.isBlank(clinique.getZsid()))
return CLINIQUE_ID_IS_EMPTY;
if (!isSecure(userName, password))
return INSECURE_CALL;
LOG
.info(serviceTemplate.getCommonDao() == null ? "serviceTemplate.getCommonDao()無效"
: "serviceTemplate.getCommonDao()有效");
LOG.info("-----------------------------------------------------");
LOG.info("----------------正在執行更新---------------------");
return (Integer)serviceTemplate.getCommonDao().execute(new IHibernateCallback() {
@Override
public Object doInHibernate(Session session) {
LOG.info(session.isOpen() ? "Hibernate Session 是有效的"
: "Hibernate session是無效的");
com.defshare.sy.po.Clinique cqe = (com.defshare.sy.po.Clinique) session
.get(com.defshare.sy.po.Clinique.class, clinique
.getZsid());
if(null==cqe)
return NO_CLINIQUE_UPDATE;
LOG.info("***********" + cqe.getDq());
if (!StringUtils.isBlank(clinique.getDq()))
cqe.setDq(clinique.getDq());
if (!StringUtils.isBlank(clinique.getDqbh()))
cqe.setDqbh(clinique.getDqbh());
if (!StringUtils.isBlank(clinique.getLxdh()))
cqe.setLxdh(clinique.getLxdh());
if (!StringUtils.isBlank(clinique.getLxdh()))
cqe.setLxdh(clinique.getLxdh());
if (!StringUtils.isBlank(clinique.getYwjl()))
cqe.setYwjl(clinique.getYwjl());
if (!StringUtils.isBlank(clinique.getYwy()))
cqe.setYwy(clinique.getYwy());
if (!StringUtils.isBlank(clinique.getZsdz()))
cqe.setZsdz(clinique.getZsdz());
if (!StringUtils.isBlank(clinique.getZsjx()))
cqe.setZsjx(clinique.getZsjx());
if (!StringUtils.isBlank(clinique.getZsmc()))
cqe.setZsmc(clinique.getZsmc());
if (!StringUtils.isBlank(clinique.getZsmm()))
cqe.setZsmm(new Md5Encrypt().getMD5ofStr(clinique.getZsmm()));
if (clinique.getDxts() != null
&& !clinique.getDxts().equals(""))
cqe.setDxts(clinique.getDxts());
LOG
.info("-----------------------------------------------------");
LOG.info("----------------更新成功---------------------");
return SUCCESS;
}
});
}
/**
* 更新工單
*/
@Override
public int updateWorkList(@WebParam final String userName,
@WebParam final String password, final WorkList workList) {
if (!isSecure(userName, password))
return INSECURE_CALL;
if (null == workList)
return NO_WORKLIST_UPDATE;
if (StringUtils.isBlank(workList.getGdbh()))
return WORKLIST_ID_IS_EMPTY;
return (Integer) serviceTemplate.getCommonDao().execute(new IHibernateCallback() {
private static final long serialVersionUID = -5913043706463089942L;
@Override
public Object doInHibernate(Session session) {
LOG.info(session.isOpen() ? "Hibernate Session 是有效的"
: "Hibernate session是無效的");
com.defshare.sy.po.WorkList _workList = (com.defshare.sy.po.WorkList) session
.get(com.defshare.sy.po.WorkList.class, workList
.getGdbh());
if (_workList == null)
return NO_WORKLIST_UPDATE;
if (!StringUtils.isBlank(workList.getFggdbh()))
_workList.setFggdbh(workList.getFggdbh());
if (!StringUtils.isBlank(workList.getZsid()))
_workList.setZsid(workList.getZsid());
if (!StringUtils.isBlank(workList.getYsxm()))
_workList.setYsxm(workList.getYsxm());
if (!StringUtils.isBlank(workList.getBrxm()))
_workList.setBrxm(workList.getBrxm());
if (!StringUtils.isBlank(workList.getYwy()))
_workList.setYwy(workList.getYwy());
if (!StringUtils.isBlank(workList.getSsdq()))
_workList.setSsdq(workList.getSsdq());
if (!StringUtils.isBlank(workList.getFgyy()))
_workList.setFgyy(workList.getFgyy());
if (!StringUtils.isBlank(workList.getJjrq()))
_workList.setJjrq(Timestamp.valueOf(workList.getJjrq()));
if (!StringUtils.isBlank(workList.getCjrq()))
_workList.setCjrq(Timestamp.valueOf(workList.getCjrq()));
if (!StringUtils.isBlank(workList.getJzrq()))
_workList.setJzrq(Timestamp.valueOf(workList.getJzrq()));
if (!StringUtils.isBlank(workList.getXgrq()))
_workList.setXgrq(Timestamp.valueOf(workList.getXgrq()));
if (!StringUtils.isBlank(workList.getXgcs()))
_workList.setXgcs(Short.valueOf(workList.getXgcs()));
if (!StringUtils.isBlank(workList.getLuz()))
_workList.setLuz(workList.getLuz());
if (!StringUtils.isBlank(workList.getCjr()))
_workList.setCjr(workList.getCjr());
if (workList.getToothSpecs() != null) {
for (com.defshare.sy.ws.po.ToothSpec tt : workList
.getToothSpecs()) {
if(tt!=null){
List<ToothSpec> spec = session.createCriteria(
ToothSpec.class).add(
Restrictions.eq("gdbh", tt.getGdbh())).list();
ToothSpec ts = null;
LOG.info("ToothSpec查詢出的規格:" + spec.size());
if (spec != null) {
for (ToothSpec toothSpec : spec) {
LOG.info("ToothSpec查詢出的工單編號:"
+ toothSpec.getGdbh());
session.delete(toothSpec);
}
}
ts = new ToothSpec();
ts.setToothSpecId(tt.getToothSpecId());
ts.setAddsl(tt.getAddsl());
ts.setDx(tt.getDx());
ts.setGdbh(tt.getGdbh());
ts.setGx(tt.getGx());
ts.setHbhid(tt.getHbhid());
ts.setJg(tt.getJg());
ts.setSl(tt.getSl());
ts.setYclx(tt.getYclx());
ts.setYs(tt.getYs());
ts.setYw(tt.getYw());
ts.setZl(tt.getZl());
session.save(ts);
}
}
}
return SUCCESS;
}
});
}
/**
* 更新牙齒規格的工序
* @param toothSpecId 牙齒規格編號
* @param gx 新的工序
* @return
*/
@Override
public int updateToothSpecGX(final String toothSpecId, final String gx) {
// TODO Auto-generated method stub
LOG.info("ToothSpec規格編號:" + toothSpecId);
LOG.info("ToothSpec工序:" + gx);
if(StringUtils.isBlank(toothSpecId))
return TOOTHSPEC_ID_IS_EMPTY;
return (Integer)serviceTemplate.getCommonDao().execute(new IHibernateCallback() {
@Override
public Object doInHibernate(Session session) {
LOG.info("ToothSpec規格編號:" + toothSpecId);
LOG.info("ToothSpec工序:" + gx);
ToothSpec spec=(ToothSpec) session.createCriteria(ToothSpec.class).add(Restrictions.eq("toothSpecId", toothSpecId)).uniqueResult();
LOG.info("ToothSpec查詢出的規格:" +spec.getGx());
if(!StringUtils.isBlank(gx))
spec.setGx(gx);
return SUCCESS;
}
});
}
// @Resource(name = "serviceTemplate")
private ServiceTemplate serviceTemplate;
public ServiceTemplate getServiceTemplate() {
return serviceTemplate;
}
public void setServiceTemplate(ServiceTemplate serviceTemplate) {
this.serviceTemplate = serviceTemplate;
}
/**
* 調用是否安全,每個WebService方法應該調用此方法
*
* @param userName
* @param password
* @return
*/
private Boolean isSecure(String userName, String password) {
if (StringUtils.isBlank(userName) || StringUtils.isBlank(password)) {
return false;
}
return userName.equals(wsUserName) && password.equals(wsPassword);
}
private String wsUserName;
private String wsPassword;
public String getWsUserName() {
return wsUserName;
}
public void setWsUserName(String wsUserName) {
this.wsUserName = wsUserName;
}
public String getWsPassword() {
return wsPassword;
}
public void setWsPassword(String wsPassword) {
this.wsPassword = wsPassword;
}
private String savepath = "worklistupfiles";
public String getSavepath() {
return savepath;
}
public void setSavepath(String savepath) {
this.savepath = savepath;
}
private ServletContext servletContext;
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
} 4、CXF配置文件如下:
<?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:jaxws="http://cxf.apache.org/jaxws"
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-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://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd" default-lazy-init="true" default-dependency-check="none">
<!--會向cxf jar包去找 -->
<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" />
<!-- 以下Bean的狀態可以修改為通過注解實現裝配-->
<bean id="syWebService" class="com.defshare.sy.ws.impl.SYWebService">
<property name="savepath" value="${ws.upfiles}"></property>
<property name="serviceTemplate" ref="serviceTemplate"/>
<property name="wsUserName" value="${ws.username}"></property>
<property name="wsPassword" value="${ws.password}"></property>
</bean>
<jaxws:endpoint id="syWS" implementor="#syWebService" address="/SYWebService" endpointName="SYWebService" serviceName="SYWebService">
<jaxws:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
</jaxws:outInterceptors>
</jaxws:endpoint>
</beans>
5、關于WS的VO類的說明:
VO類的屬性成員完全根據WS的客戶端需要決定,不一定和項目的PO類屬性相同。
此項目中CXF和Spring、Hibernate集成,開發中曾經反了一個荒唐錯誤就是“在WS項目中使用VO作Hibernate查詢類,導致查詢不來系統有沒有錯誤警告,折騰許久”。想在想來可笑。(總結一下:當你遇到一個極近明顯而又找不到原因的錯誤,小心可能只是你的粗心大意造成)
6、這個項目由于和Spring集成,因此方法中凡是涉及數據庫部分自然也用到了容器事務。這個事務的配置我是在另一個項目中(SY Core)完成的,這個SY Core項目是我這個項目的Spring配置文件,內容如下:
<?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:jaxws="http://cxf.apache.org/jaxws"
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-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://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd" default-lazy-init="true" default-dependency-check="none">
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:jdbc.properties</value>
<value>classpath:ws.properties</value>
</list>
</property>
</bean>
<!-- 掃描類路徑下被注解的組件,這些組件將被自動注冊為Spring Bean-->
<context:component-scan
base-package="com.defshare.foundation.dao,com.defshare.sy.biz.impl,com.defshare.sy.ws.impl,com.defshare.sy.web.action" />
<!-- 配置數據源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass">
<value>${jdbc.driverClassName}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
<!--初始化時獲取0個連接,取值應在minPoolSize與maxPoolSize之間。Default: 3 -->
<property name="initialPoolSize">
<value>0</value>
</property>
<property name="minPoolSize">
<value>1</value>
</property>
<!--連接池中保留的最大連接數。Default: 15 -->
<property name="maxPoolSize">
<value>15</value>
</property>
<!--當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數。Default: 3 -->
<property name="acquireIncrement">
<value>1</value>
</property>
<!--定義在從數據庫獲取新連接失敗后重復嘗試的次數。Default: 30 -->
<property name="acquireRetryAttempts">
<value>3</value>
</property>
<!--兩次連接中間隔時間,單位毫秒。Default: 1000 -->
<property name="acquireRetryDelay">
<value>1000</value>
</property>
<!--連接關閉時默認將所有未提交的操作回滾。Default: false -->
<property name="autoCommitOnClose">
<value>false</value>
</property>
<!--最大空閑時間,1800秒內未使用則連接被丟棄。若為0則永不丟棄。Default: 0 -->
<property name="maxIdleTime">
<value>1800</value>
</property>
<!--當連接池用完時客戶端調用getConnection()后等待獲取新連接的時間,超時后將拋出
SQLException,如設為0則無限期等待。單位毫秒。Default: 0
-->
<property name="checkoutTimeout">
<value>30000</value>
</property>
<!--每600秒檢查所有連接池中的空閑連接。Default: 0 -->
<property name="idleConnectionTestPeriod">
<value>600</value>
</property>
<!--c3p0將建一張名為C3P0TEST的空表,并使用其自帶的查詢語句進行測試。如果定義了這個參數那么
屬性preferredTestQuery將被忽略。你不能在這張Test表上進行任何操作,它將只供c3p0測試
使用。Default: null
-->
<property name="automaticTestTable">
<value>C3P0TEST</value>
</property>
<!--獲取連接失敗將會引起所有等待連接池來獲取連接的線程拋出異常。但是數據源仍有效
保留,并在下次調用getConnection()的時候繼續嘗試獲取連接。如果設為true,那么在嘗試
獲取連接失敗后該數據源將申明已斷開并永久關閉。Default: false
-->
<property name="breakAfterAcquireFailure">
<value>false</value>
</property>
</bean>
<!--
<bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler"
lazy-init="true">
</bean>
-->
<!--
Spring針對Hibernate提供的標準本地會話工廠Bean子類,支持JDK1.5以上元數據映射,這個類需要Hibernate3.2以上版本
-->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<!--
<property name="lobHandler">
<ref bean="lobHandler" />
</property>
-->
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
<property name="configLocation">
<value>classpath:com/defshare/sy/config/hibernate.cfg.xml</value>
</property>
<property name="packagesToScan" value="com.defshare.sy.po"></property>
<!-- 存放特殊的查詢語句
<property name="mappingResources">
<list>
<value>com/defshare/sy/config/hibernate/ReportQuery.hbm.xml</value>
</list>
</property>
-->
</bean>
<!--
Spring整合Hibernate提供的Hibernate模板,可以簡化Hibernate操作,同時整合Hibenate操作到事務
-->
<bean name="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 事務管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- 事務通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 配置事務傳遞屬性 -->
<tx:attributes>
<tx:method name="get*" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" propagation="REQUIRED" read-only="true" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="log*" propagation="REQUIRES_NEW"
rollback-for="Exception"/>
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!-- 事務切面 -->
<aop:config>
<!--切入點 -->
<aop:pointcut id="myPointCutA"
expression="execution(* com.defshare.sy.biz.impl.*.*(..))" />
<aop:pointcut expression="execution(* com.defshare.sy.ws.impl.*.*(..))" id="myPointCutB"/>
<!-- 將切入點和通知組合在一起 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="myPointCutA" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="myPointCutB"/>
</aop:config>
<!-- 日志工具
<bean id="logUtil" class="com.defshare.sy.log.LogUtil"></bean>-->
<!-- 日志切面
<aop:config>
<aop:aspect ref="logUtil">
<aop:pointcut expression="execution(* com.defshare.sy.biz.impl.*.*(..))"
id="doLog1" />
<aop:around pointcut-ref="doLog1" method="doLog" />
</aop:aspect>
</aop:config>-->
</beans>
注意其中的:
<context:component-scan
base-package="com.defshare.foundation.dao,com.defshare.sy.biz.impl,com.defshare.sy.ws.impl,com.defshare.sy.web.action" />
和
<!--切入點 -->
<aop:pointcut id="myPointCutA"
expression="execution(* com.defshare.sy.biz.impl.*.*(..))" />
<aop:pointcut expression="execution(* com.defshare.sy.ws.impl.*.*(..))" id="myPointCutB"/>
就是對WS中的方法的事務配置。
當初這個地方忘記配置出現的問題是WS的方法不能完成數據庫的寫操作(又是折騰許久:))。