在spring实例化bean的前后执行一些附加操作。
有时,你会发现需要立刻在Spring实例化一个bean的前后执行一些附件操作。这些操作可以简单到修改一个bean,也可以复杂到返回一个完全不同的对象。
BeanPostProcessor接口包含两个method:
postProcessBeforeInitialization方法:在Spring调用任何bean的初始化钩子(例如InitializingBean.afterPropertiesSet或者init方法)之前被调用。
postProcessAfterInitialization方法:Spring在成功完成嵌入初始化以后调用他。
/**
* Copyright (C) 2014 Winbons Technology Software Co.,Ltd
* All Rights Reserved.
* Development of this softwareWinbons Technology Software Co.,Ltd.
* Without the formal written consent of the Company,
* any other individuals, groups may not use,
* copy, modify, or distribute this software
* @Title: IErrorListener.java
* @Package saas.crm.importer
* @Description: TODO(用一句话描述该文件做什么)
* @author star.ye
* @date 2014年11月6日 下午2:50:12
* @version 1.0
*/
package saas.crm.importer;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* @ClassName: IErrorListener
* @Description: TODO(这里用一句话描述这个类的作用)
* @author star.ye
* @date 2014年11月6日 下午2:50:12
*/
public interface ImportListener {
void onStart(String fileId, ImportType importType);
Object convertEntity(String propertyName, Object value, Object data) throws Exception;
/**
* 是否保存成功
* @return 1 - 保存成功
* 0 - 保存/覆盖失败
* -1 - 覆盖/忽略成功
*/
int onSaveData(Object obj, ImportType importType, int dataIndex,Long importLogId);
ImportData init(int type);
/**
* 导入结束后的操作
* @param totalCounttotalCount[0] - 成功导入记录数totalCount[1] - 成功覆盖/忽略记录数
* @param importDataEn
* @param importLog
* @param datas
*/
void onComplete(ImportDataEn importDataEn, Map<String, String> datas,Integer dataRowNum,ConcurrentLinkedQueue<Integer> queue);
String getModuleName();
void exportTemplete(OutputStream outputStream, int type) throws IOException;
Map<String, Object> getNewListItem();
}
/**
* Copyright (C) 2014 Winbons Technology Software Co.,Ltd
* All Rights Reserved.
* Development of this softwareWinbons Technology Software Co.,Ltd.
* Without the formal written consent of the Company,
* any other individuals, groups may not use,
* copy, modify, or distribute this software
* @Title: DefaultCellListener.java
* @Package saas.crm.importer
* @Description: TODO(用一句话描述该文件做什么)
* @author star.ye
* @date 2014年11月6日 下午2:57:03
* @version 1.0
*/
package saas.crm.importer;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import saas.crm.Constant;
import saas.crm.base.manager.ITempFileManager;
import saas.crm.base.uisetting.IListService;
import saas.crm.base.uisetting.IUISetting;
import saas.crm.data.model.definition.DefinedFeild;
import saas.crm.data.model.log.ImportLog;
import saas.crm.importer.excel.WorkBookUtils;
import saas.data.manager.ISystemProfileManager;
import saas.framework.dao.BaseDao;
import saas.framework.data.model.ListItem;
import saas.framework.utils.Env;
import saas.framework.utils.SecurityUtils;
/**
* @ClassName: DefaultCellListener
* @Description: TODO(这里用一句话描述这个类的作用)
* @author star.ye
* @date 2014年11月6日 下午2:57:03
*/
public abstract class AbstractImportListener implements ImportListener {
protected static final Logger logger = org.slf4j.LoggerFactory.getLogger("IMPORT.ERROR");
@Autowired
private ISystemProfileManager systemProfileManager;
public String hightSeaActivated ="N"; //默认设置公海池开关为 关
private static ConcurrentHashMap<Long, ImportLog> importLogMap=new ConcurrentHashMap<Long, ImportLog>();
private static ConcurrentHashMap<Long, List<ErrorRow>> errorListMap=new ConcurrentHashMap<Long, List<ErrorRow>>();
@Autowired
private ITempFileManager tempFileManager;
public abstract String getEntityClassName();
protected static ThreadLocal<Map<String, Object>> cacheValue = new ThreadLocal<Map<String, Object>>() {
protected Map<String, Object> initialValue() {
return new HashMap<String, Object>();
}
};
protected static ThreadLocal<Map<String, Object>> newItemCache = new ThreadLocal<Map<String, Object>>() {
@Override
protected Map<String, Object> initialValue() {
return new HashMap<String, Object>();
}
};
public Map<String, Object> getInitData() {
return null;
}
@Autowired
protected BaseDao baseDao;
@Autowired
private IUISetting uiSetting;
@Autowired
private IListService listService;
public static final String ERROR_FOLDER = "importErrors";
public Object convertEntity(String propertyName, Object value, Object data) throws Exception {
BeanUtils.setProperty(data, propertyName, value);
return data;
}
public Map<String, Object> getNewListItem(){
return newItemCache.get();
}
public void onStart(String fileId, ImportType importType) {
logger.info("fileId:{} start to import...", fileId);
cacheValue.get().clear();
newItemCache.get().clear();
}
@Override
public ImportData init(int type) {
return getConfig(type);
}
public ImportData getConfig(int type) {
Modules modules = Modules.getByType(type);
List<DefinedFeild> definedFeilds = uiSetting.getModelDefineField(modules.tableName);
if(modules.equals(Modules.LEADS)){
clearSpeFields(definedFeilds, "ownerId");
}
if(modules.equals(Modules.CONTACT)){
clearSpeFields(definedFeilds, "ownerId");
}
hightSeaActivated = systemProfileManager.getSystemProfileNoCache(SecurityUtils.getTenantId(), "customerPool", "activated");
//如果是 联系人导入 ,增加 客户池 这个数据栏
if(modules.equals(Modules.CONTACT) && "Y".equals(hightSeaActivated)){
DefinedFeild definedFeild=new DefinedFeild();
definedFeild.setField_label("客户池");
definedFeild.setMapping_field_name("cust_pool");
definedFeild.setIs_mandatory(true);
definedFeild.setIs_updateable(true);
definedFeild.setField_type("autocomplete");
definedFeild.setMax_length(20);
definedFeild.setTable_name("t_crm_cust_contact");
definedFeilds.add(definedFeild);
}
ImportData importData = new ImportData();
Map<String, Column> cMap = new HashMap<String, Column>();
importData.setColumnMap(cMap);
Set<String> cSet = new HashSet<String>();
importData.setRequiredFields(cSet);
for (DefinedFeild definedFeild : definedFeilds) {
String lable = definedFeild.getField_label();
if (StringUtils.isNotBlank(lable)) {
String mappingName = definedFeild.getMapping_field_name();
if (definedFeild.isIs_updateable()) {
Column column = new Column(lable, mappingName, definedFeild.getField_type(), definedFeild.getMax_length());
cMap.put(definedFeild.getField_label(), column);
}
//设置必填项
if (definedFeild.getIs_mandatory() && !"owner_id".equals(mappingName) && !"deptId".equals(mappingName)
&& !"deptName".equals(mappingName) && !"district".equals(mappingName) && !"area".equals(mappingName) ) {
cSet.add(definedFeild.getMapping_field_name());
}
if(!"Y".equals(hightSeaActivated)){
cSet.remove("cust_pool");// 如果公海未开启,那么cust_pool不能设为必填项
}
}
}
importData.setEntityClassName(getEntityClassName());
return importData;
}
/**
* @param totalCount
* 成功导入数据条数
* @param errorCells
* 失败记录集合
* @param importLog
* 导入日志
* @param totalNum
* 当前Sheet中的总列数
*/
@Override
@Transactional
public void onComplete(ImportDataEn importDataEn, Map<String, String> datas,Integer dataRowNum,ConcurrentLinkedQueue<Integer> queue) {
ImportLog importLog = importDataEn.getImportLog();
Long imLogId=importLog.getId();
logger.info("-----------onComplete()");
if (dataRowNum!=null && dataRowNum>Constant.importMutiOn){
ImportLog commImportLog = importLogMap.get(importLog.getId());
if (commImportLog==null || commImportLog.getId().longValue()!=importLog.getId().longValue()){
ImportLog finalLog;
try {
finalLog = (ImportLog)BeanUtils.cloneBean(importLog);
finalLog.setStatus(ImportStatus.COMPLETE.value);
importLogMap.put(importLog.getId(), finalLog);
} catch (Exception e) {
e.printStackTrace();
}
}
if (importLog.getStatus()==ImportStatus.FAIL.value){
importLogMap.get(importLog.getId()).setStatus(ImportStatus.FAIL.value);
}
}
List<ErrorRow> errorCells = importDataEn.getErrorCells();
if (dataRowNum!=null && dataRowNum>Constant.importMutiOn){
List<ErrorRow> comList = errorListMap.get(importLog.getId());
if (comList==null){
List<ErrorRow> re=new ArrayList<ErrorRow>();
errorListMap.put(importLog.getId(), re);
}
if (errorCells!=null && !errorCells.isEmpty()){
errorListMap.get(importLog.getId()).addAll(errorCells);
}
}
if (dataRowNum!=null && dataRowNum>Constant.importMutiOn){
ExcelBizImporter.numLock.lock();
int succ = ExcelBizImporter.importResultNums.get(imLogId)[0]+ExcelBizImporter.importResultNums.get(imLogId)[1];
int failRe=ExcelBizImporter.importResultNums.get(imLogId)[2];
String successMsg = "成功导入" + ExcelBizImporter.importResultNums.get(imLogId)[0] + "条数据," + importDataEn.getImportType().name
+ ExcelBizImporter.importResultNums.get(imLogId)[1] + "条数据";
ExcelBizImporter.numLock.unlock();
if (!errorListMap.get(importLog.getId()).isEmpty()) {
importLog.setMsg(successMsg + ",失败 " + failRe + " 条,失败请查看日志");
} else {
importLog.setMsg(successMsg);
}
//int totalImport=finalRe[0]+finalRe[1];
int imortNum=ExcelBizImporter.importIngNum.get(importLog.getId());
if (queue.isEmpty() && imortNum>= (dataRowNum-2)){
if (importLogMap.get(importLog.getId()).getStatus()==ImportStatus.FAIL.value){
importLog.setStatus(ImportStatus.FAIL.value);
}
List<ErrorRow> errList=errorListMap.get(importLog.getId());
int actuRowNum=dataRowNum-ExcelBizImporter.emptyRowNum.get(importLog.getId());
if (succ<actuRowNum){
if ((succ+failRe)<1 && dataRowNum>0){
errList.add(new ErrorRow(new String[]{""},new Integer[]{1},"模板数据有问题,请重新下载模板来填写数据!"));
}
writeErrorLog(errList, importLog, datas); // add errorLog
}
tempFileManager.removeTempFile(importLog.getImportfile());
errorListMap.remove(importLog.getId());
importLogMap.remove(importLog.getId());
ImportManagerImpl.conMap.remove(importLog.getId());
ImportManagerImpl.leadsMap.remove(importLog.getId());
ImportManagerImpl.custNamesMap.remove(importLog.getId());
ImportManagerImpl.custMap.remove(importLog.getId());
}
}else{
ExcelBizImporter.numLock.lock();
int succ = ExcelBizImporter.importResultNums.get(imLogId)[0]+ExcelBizImporter.importResultNums.get(imLogId)[1];
int failRe=ExcelBizImporter.importResultNums.get(imLogId)[2];
String successMsg = "成功导入" + ExcelBizImporter.importResultNums.get(imLogId)[0] + "条数据," + importDataEn.getImportType().name
+ ExcelBizImporter.importResultNums.get(imLogId)[1] + "条数据";
ExcelBizImporter.numLock.unlock();
int actuRowNum=dataRowNum-ExcelBizImporter.emptyRowNum.get(importLog.getId());
if (succ<actuRowNum) {
if ((succ+failRe)<1 && dataRowNum>0){
errorCells.add(new ErrorRow(new String[]{""},new Integer[]{1},"模板数据有问题,请重新下载模板来填写数据!"));
}
writeErrorLog(errorCells, importLog, datas); // add errorLog
importLog.setMsg(successMsg + ",失败 " + failRe + " 条,失败请查看日志");
} else {
importLog.setMsg(successMsg);
}
tempFileManager.removeTempFile(importLog.getImportfile());
ImportManagerImpl.conMap.remove(importLog.getId());
ImportManagerImpl.leadsMap.remove(importLog.getId());
ImportManagerImpl.custNamesMap.remove(importLog.getId());
ImportManagerImpl.custMap.remove(importLog.getId());
}
importLog.setCompletiondate(new Date());
baseDao.update(importLog);
baseDao.flush();
cacheValue.get().clear();
newItemCache.get().clear();
}
private void writeErrorLog(List<ErrorRow> errorCells, ImportLog importLog, Map<String, String> datas) {
int totalNum = datas.size();
HSSFWorkbook wb = new HSSFWorkbook();
Modules modules = Modules.getByType(importLog.getImporttype());
// createHeaderByTableName(wb, modules.tableName, true);
createHeaderByCurrentData(wb, modules.tableName, datas);
Sheet sheet = wb.getSheetAt(0);
int rowNum = 1;
for (ErrorRow errorCell : errorCells) {
Row row = sheet.createRow(rowNum);
String[] errorDatas = errorCell.getData();
Integer[] indexs = errorCell.getDataIndex();
if (datas != null) {
for (int i = 0; i < errorDatas.length; i++) {
if (indexs[i] != null) {
Cell cell = row.createCell(indexs[i]);
cell.setCellType(Cell.CELL_TYPE_STRING);
cell.setCellValue(errorDatas[i]);
}
}
}
Cell lastCell = row.createCell(totalNum + 1);
WorkBookUtils.setRedCellValue(wb, lastCell, errorCell.getErrorMsg());
rowNum++;
}
try {
logger.info("------------开始去写错误日志了");
saveWb(wb, importLog);
logger.info("------------完成写错误日志了");
} catch (Exception e) {
logger.error("写入错误日志失败", e);
}
}
private static String getFileOutDir() {
DateTime dateTime = new DateTime();
StringBuffer sb = new StringBuffer();
char s = File.separatorChar;
sb.append(SecurityUtils.getTenantId()).append(s);
sb.append(ERROR_FOLDER).append(s).append(dateTime.toString("yyyy" + s + "M" + s + "d" + s));
logger.info("-----------上传的路径是:"+sb.toString());
return sb.toString();
}
private String saveWb(Workbook sb, ImportLog importLog) throws Exception {
String logFile = getFileOutDir();
String outPutDir = Env.getInstatnce().getConfigProperty("fileserver.path") + getFileOutDir();
logger.info("------------outPutDir 是:"+outPutDir);
File outPutFile = new File(outPutDir);
logger.info("------------outPutFile 是:"+outPutFile);
if (!outPutFile.exists()) {
outPutFile.mkdirs();
logger.info("------------outPutFile不存在,所以 創建一個文件"+outPutFile);
}
String fileName = importLog.getImportfile() + "_error.xls";
String fileUrl = outPutDir + fileName;
importLog.setLogfile(logFile + fileName);
FileOutputStream fileOutputStream = new FileOutputStream(fileUrl);
sb.write(fileOutputStream);
fileOutputStream.close();
return fileUrl;
}
private List<String> createHeaderByTableName(Workbook wb, String tableName) {
return createHeaderByTableName(wb, tableName, false);
}
protected List<DefinedFeild> addOtherHeads(List<DefinedFeild> listDefinedFeild) {
return listDefinedFeild;
}
private List<String> createHeaderByTableName(Workbook wb, String tableName, boolean errorLog) {
List<DefinedFeild> definedFeilds = uiSetting.getModelDefineField(tableName);
clearFields(definedFeilds);
if(tableName.equals(Modules.LEADS.tableName)){//线索导入时 负责人 列删除
clearSpeFields(definedFeilds,"ownerId");
clearSpeFields(definedFeilds,"country");
clearSpeFields(definedFeilds,"deptName");
clearSpeFields(definedFeilds,"tag"); //删除 是否转为客户
clearSpeFields(definedFeilds,"followPeriod"); //总跟进时长
clearSpeFields(definedFeilds,"closeReason"); //关闭原因
clearSpeFields(definedFeilds,"distributeStatus"); //分配状态
clearSpeFields(definedFeilds,"distributeDate"); //最近跟进时长
clearSplit(definedFeilds,"splitline");
}
if(tableName.equals(Modules.CUSTOMER.tableName)){//客户导入时 负责人 列删除
//
clearSpeFields(definedFeilds,"deptName");
clearSpeFields(definedFeilds,"district");
clearSplit(definedFeilds,"splitline");
}
//如果下载的模板是联系人,则在表格里最后加一 栏 "客户池",是必填栏
if(tableName.equals(Modules.CONTACT.tableName)){
clearSpeFields(definedFeilds,"ownerId");
clearSplit(definedFeilds,"splitline");
/*String s = systemProfileManager.getSystemProfileNoCache(SecurityUtils.getTenantId(), "customerPool", "activated");
//如果开启公海,则excel 增加 客户池
if ("Y".equals(s)){
DefinedFeild definedFeild=new DefinedFeild();
definedFeild.setField_label("客户池");
definedFeild.setIs_mandatory(true);
definedFeild.setMapping_field_name("cust_pool");
definedFeilds.add(definedFeild);
}*/
}
if(tableName.equals(Modules.USER.tableName)){
definedFeilds = addOtherHeads(definedFeilds);
}
Sheet sh = wb.createSheet();
sh.setAutobreaks(true);
sh.setDefaultColumnWidth(16);
List<String> headerName = null;
//单元格式
CellStyle style = wb.createCellStyle();
DataFormat fmt = wb.createDataFormat();
style.setDataFormat(fmt.getFormat("@"));
if (!errorLog) {
headerName = new ArrayList<String>();
}
for (int rownum = 0; rownum < 1; rownum++) {
Row row = sh.createRow(rownum);
int i = 0;
for (DefinedFeild definedFeild : definedFeilds) {
Cell cell = row.createCell(i);
String cellValue = definedFeild.getField_label();
//设置 销售线索 公司电话,公司传真,电话 的格式是文本格式
if (!errorLog && tableName.equals(Modules.LEADS.tableName)){
String fieldName = definedFeild.getMapping_field_name();
if (fieldName!=null && (fieldName.equals("compTel") || fieldName.equals("compFax") || fieldName.equals("tel"))){
sh.setDefaultColumnStyle(i,style);
}
}
//设置 联系人 公司电话,传真 的格式是文本格式
if (!errorLog && tableName.equals(Modules.CONTACT.tableName)){
String fieldName = definedFeild.getMapping_field_name();
if (fieldName!=null && (fieldName.equals("tel") || fieldName.equals("fax"))){
sh.setDefaultColumnStyle(i,style);
}
}
if (!errorLog){
String fieldName = definedFeild.getMapping_field_name();
if (fieldName!=null && (fieldName.equals("name") || fieldName.equals("compName")
|| fieldName.equals("customerName") || fieldName.equals("cust_id"))){
sh.setDefaultColumnStyle(i,style);
}
}
if (definedFeild.getIs_mandatory()) {// 必填
WorkBookUtils.setRedCellValue(wb, cell, cellValue);
WorkBookUtils.addCommentCell(cell, "此列数据必填", wb, sh);
} else {
cell.setCellValue(cellValue);
}
i++;
if (!errorLog) {
headerName.add(definedFeild.getMapping_field_name());
}
}
if (errorLog) {
Cell cell = row.createCell(i + 1);
WorkBookUtils.setRedCellValue(wb, cell, "错误原因");
}
}
return headerName;
}
private void clearSpeFields(List<DefinedFeild> definedFeilds,String ... mapNames){
for(int i=0;i<definedFeilds.size();i++){
DefinedFeild df = definedFeilds.get(i);
for(String name : mapNames){
if(name.equals(df.getMapping_field_name())){
definedFeilds.remove(i);
}
}
}
}
private void clearSplit(List<DefinedFeild> definedFeilds,String ... fieldType){
List<DefinedFeild> needRemoveList = new ArrayList<DefinedFeild>();
for (int i = 0; i < definedFeilds.size(); i++) {
DefinedFeild df = definedFeilds.get(i);
for (String name : fieldType) {
if (name.equals(df.getField_type())) {
// definedFeilds.remove(i);
// update by 6031 修复过滤分割线问题
needRemoveList.add(definedFeilds.get(i));
}
}
}
definedFeilds.removeAll(needRemoveList);
}
/**
* 过滤不需要输出的字段
*
* @param definedFields
*/
private void clearFields(List<DefinedFeild> definedFields) {
Set<String> displayField = this.getDisplayNames(); // 不需要输出的字段集合
if (!displayField.isEmpty()) {
List<DefinedFeild> displayFields = new ArrayList<DefinedFeild>();
for (DefinedFeild field : definedFields) {
if (!(field.isIs_updateable() && StringUtils.isNotBlank(field.getField_label()) && !displayField
.contains(field.getMapping_field_name()))) {
displayFields.add(field);
}
}
definedFields.removeAll(displayFields);
}
}
public void exportTemplete(OutputStream outputStream, int type) throws IOException {
Modules modules = Modules.getByType(type);
Workbook wb = new HSSFWorkbook();
List<String> headerNames = createHeaderByTableName(wb, modules.tableName);
afterCreateHeaderSheet(wb, headerNames);
wb.write(outputStream);
outputStream.close();
}
protected void afterCreateHeaderSheet(Workbook wb, List<String> headerNames) {
Map<String, Object> initData = getInitData();
if (initData != null) {
Sheet sheet = wb.getSheetAt(0);
int lastRow = sheet.getLastRowNum();
Row row = sheet.createRow(lastRow + 1);
for (int i = 0, len = headerNames.size(); i < len; i++) {
String headerName = headerNames.get(i);
Cell cell = row.createCell(i);
Object data = initData.get(headerName);
if (data != null)
cell.setCellValue(String.valueOf(data));
}
}
}
/**
* 通过实际数据生成行首
*
* @param wb
* @param datas
*/
@SuppressWarnings("rawtypes")
private void createHeaderByCurrentData(Workbook wb, String tableName, Map<String, String> datas) {
Sheet sheet = wb.createSheet();
Row row = sheet.createRow(0);
List<DefinedFeild> definedFeilds = uiSetting.getModelDefineField(tableName);
List<String> required = new ArrayList<String>();
for (DefinedFeild field : definedFeilds) {
if (field.getIs_mandatory()) {
required.add(field.getField_label());
}
}
Set<String> keys = datas.keySet();
int i = 0;
for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
String idx = (String) iterator.next();
String cellValue = datas.get(idx);
Cell cell = row.createCell(Integer.parseInt(idx));
if (required.contains(cellValue)) {
WorkBookUtils.setRedCellValue(wb, cell, cellValue);
WorkBookUtils.addCommentCell(cell, "此列数据必填", wb, sheet);
} else {
cell.setCellValue(cellValue);
}
i++;
}
Cell cell = row.createCell(i + 1);
WorkBookUtils.setRedCellValue(wb, cell, "错误原因");
}
protected Set<String> getDisplayNames() {
Set<String> displayField = new HashSet<String>();
displayField.add("owner_id");
return displayField;
}
protected Long getDbValue(String name, long listId) {
String key = listId + "_" + name;
Map<String, Object> caMap = cacheValue.get();
Long dbValue = (Long) caMap.get(key);
if (dbValue == null) {
dbValue = listService.findByName(name, listId);
//if (dbValue == null) {
//// 新增一个类型
//ListItem listItem = new ListItem();
//listItem.setItemLabel(name);
//listItem.setListId(listId);
//listItem.setValid(true);
//listItem.setEditable(true);
//listItem.setDeletable(true);
//listItem.setDescn(name);
//listService.addListItem(listItem);
//dbValue = listItem.getId();
//newItemCache.get().put(key, dbValue);
//}
caMap.put(key, dbValue);
}
return dbValue;
}
}
/**
* Copyright (C) 2014 Winbons Technology Software Co.,Ltd
* All Rights Reserved.
* Development of this softwareWinbons Technology Software Co.,Ltd.
* Without the formal written consent of the Company,
* any other individuals, groups may not use,
* copy, modify, or distribute this software
* @Title: CustomerExcelImporter.java
* @Package saas.crm.customer.service
* @Description: TODO(用一句话描述该文件做什么)
* @author star.ye
* @date 2014年11月4日 上午11:24:23
* @version 1.0
*/
package saas.crm.market.data.event;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.reflect.FieldUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DataFormat;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import saas.crm.base.uisetting.ICheckRepeatCache;
import saas.crm.base.uisetting.IComboxCache;
import saas.crm.base.uisetting.IDateTimeCache;
import saas.crm.base.uisetting.IListService;
import saas.crm.base.uisetting.IUISetting;
import saas.crm.base.utils.BeanUtils;
import saas.crm.base.utils.IPropertyFilter;
import saas.crm.customer.data.manager.ICustomerManager;
import saas.crm.customer.data.manager.ICustomerPoolManager;
import saas.crm.customer.manager.IPoolActivatedService;
import saas.crm.data.constant.Gender;
import saas.crm.data.constant.Tag;
import saas.crm.data.model.customer.CustomerContact;
import saas.crm.data.model.definition.DefinedFeild;
import saas.crm.data.model.leads.Leads;
import saas.crm.data.vo.ListItemVO;
import saas.crm.global.IExistChecker;
import saas.crm.importer.AbstractImportListener;
import saas.crm.importer.IBizImporter;
import saas.crm.importer.ImportManagerImpl;
import saas.crm.importer.ImportType;
import saas.crm.importer.Modules;
import saas.crm.market.enumtype.LeadsConstant;
import saas.crm.market.manager.ILeadsManager;
import saas.crm.security.service.IPermission;
import saas.framework.event.EventAPI;
import saas.framework.event.entity.PreSaveEvent;
import saas.framework.freemarker.ITempleteService;
import saas.framework.utils.SecurityUtils;
import com.alibaba.fastjson.JSON;
/**
* @ClassName: CustomerExcelImporter
* @Description: TODO(这里用一句话描述这个类的作用)
* @author star.ye
* @date 2014年11月4日 上午11:24:23
*/
@Component
public class LeadsImportListener extends AbstractImportListener implements InitializingBean {
private BeanUtils beanUtils = null;
private static Map<String, Object> testData = new HashMap<String, Object>();
private static final String INIT_TPL = "leads/initData.ftl";
@Autowired
private ITempleteService templeteService;
@Autowired
private IComboxCache comboxCache;
@Autowired
private IDateTimeCache dateTimeCache;
@Autowired
private ICustomerManager customerManager;
@Autowired
private IListService listService;
@Autowired
protected EventAPI publisher;
@Autowired
private ILeadsManager leadsManager;
@Autowired
private IPoolActivatedService poolActivatedService;
@Autowired
private ICustomerPoolManager customerPoolManager;
@Autowired
private IPermission permissionManager;
@Autowired
private IUISetting uISetting;
@Autowired
private ICheckRepeatCache checkRepeatCache;
@Autowired
private IExistChecker existChecker;
private static final Integer DEFAULT_POOL_DAY = 30;// 默认的公海过期天数与人数
private ReentrantLock lockLeads=new ReentrantLock();
public Map<String, Object> getInitData() {
return testData;
}
protected void afterSaveData(Long cusId) {
// CustomerShareAcl customerShareAcl = new CustomerShareAcl();
// customerShareAcl.setDbId(SecurityUtils.getTenantId());
// customerShareAcl.setSecureId(CrmContext.getCurrentOwnerId());
// customerShareAcl.setCustId(cusId);
// customerShareAcl.setReadable(true);
// customerShareAcl.setOwner(true);
// baseDao.getSession().merge(customerShareAcl);
}
/**
* 校验日期、时间格式
* @param type
* @param value
* @return
*/
private boolean vaildDTFormat(String type, String value){
if(StringUtils.isNotBlank(type)){
String rep = "";
if("time".equals(type)){
rep = "^(([0-1][0-9])|2[0-3]):[0-5][0-9]$";
} else if("date".equals(type)){
rep = "^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$";
} else if("dt".equals(type)){
rep = "^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)\\s+(([0-1][0-9])|2[0-3]):[0-5][0-9]$";
}
if(StringUtils.isNotBlank(type)){
Pattern pattern = Pattern.compile(rep);
Matcher matcher = pattern.matcher(value);
return matcher.matches();
}
}
return false;
}
public Object convertEntity(String propertyName, Object value, Object data) throws Exception {
Object tempValue = null;
Field field_ = FieldUtils.getField(Leads.class, propertyName, true);
if (field_ != null) {
Class type = field_.getType();
tempValue = beanUtils.convert(value, type);
}
String fieldStr = checkRepeatCache.getRepeatFieldName("t_crm_leads");
if(fieldStr.indexOf(propertyName)>=0){
if(existChecker.checkNameIsExistByClazzName(tempValue, "Leads", propertyName)){
String label = checkRepeatCache.getRepeatFieldLabel("t_crm_leads", propertyName);
String errorMsg = label!=null?"【" + label + "】字段值重复,请修改!!":null;
throw new IllegalArgumentException(errorMsg);
}
}
if ("name".equals(propertyName)) {
if (value == null || StringUtils.isEmpty(value.toString())) {
throw new IllegalArgumentException("联系人名称不能为空");
}
}
if ("compTel".equals(propertyName) || "mobile".equals(propertyName) || "tel".equals(propertyName)) {
if (value != null) {
String rep = "^[0-9]*$";
Pattern pattern = Pattern.compile(rep);
Matcher matcher = pattern.matcher(String.valueOf(value));
if (!matcher.matches()){
String ss="";
if ("compTel".equals(propertyName)){
ss="公司电话";
}
if ("mobile".equals(propertyName)){
ss="手机";
}
if ("tel".equals(propertyName)){
ss="电话";
}
throw new IllegalArgumentException(ss+"填写错误,只能填数字!");
}
}
}
if (value != null) {
Long dbValue = null;
LeadsConstant leadsConstant = LeadsConstant.getConstant(propertyName);
if (leadsConstant != null) {
if("source".equals(propertyName)){
dbValue = getDbValue(value.toString(), leadsConstant.dbValue);// 校验一下重要属性的值
if (dbValue != null){
return super.convertEntity(propertyName, dbValue, data);
}else{
DefinedFeild field = uISetting.getDefineField("t_crm_leads", propertyName);
String fieldName = propertyName;
if(field!=null){
fieldName = field.getField_label();
}
throw new IllegalArgumentException("没有对应的【" + fieldName + "】的值【"+value.toString()+"】,请先在系统中新建这个下拉项值");
}
}
} else {
// 校验单选框的值
Long listId = comboxCache.getListId(propertyName, "t_crm_leads");
if (listId != null) {
dbValue = getDbValue(value.toString(), listId);
if (dbValue != null){
return super.convertEntity(propertyName, dbValue, data);
}else{
DefinedFeild field = uISetting.getDefineField("t_crm_leads", propertyName);
String fieldName = propertyName;
if(field!=null){
fieldName = field.getField_label();
}
throw new IllegalArgumentException("没有对应的【" + fieldName + "】的值【"+value.toString()+"】,请先在系统中新建这个下拉项值");
}
} else {
// 校验日期、时间类型的值
String format = dateTimeCache.getTypeByFiled(propertyName, "t_crm_leads");
if(format != null){
if(!vaildDTFormat(format, value.toString())){
value = "";
}
}
}
}
super.convertEntity(propertyName, dbValue, data);
}
if("gender".equals(propertyName)){
if("0".equals(value) || "男".equals(value) || "male".equals(value)){
value = Gender.male;
}else if("1".equals(value) || "女".equals(value) || "female".equals(value)){
value = Gender.female;
}
}
if("tag".equals(propertyName)){
if("0".equals(value) || "未转".equals(value)){
value = Tag.notturn;
}else if("1".equals(value) || "已转".equals(value)){
value = Tag.turn;
}
}
if("status".equals(propertyName)){
if("未处理".equals(value)){
value = 0;
}else if("已联系".equals(value)){
value = 1;
}else if("关闭".equals(value)){
value = 2;
}
}
return super.convertEntity(propertyName, value, data);
}
public void afterPropertiesSet() throws Exception {
beanUtils = new BeanUtils(null);
beanUtils.addPropertyFilter(new IPropertyFilter() {
public boolean filter(String name, Object value) {
if (value == null) {
return true;
}
return false;
}
});
initTestData();
}
private synchronized void initTestData() {
String jsonString = templeteService.processTemplateIntoString(INIT_TPL, null);
testData.putAll(JSON.parseObject(jsonString));
}
public String getModuleName() {
return Modules.LEADS.name();
}
public String getEntityClassName() {
return Leads.class.getName();
}
public int onSaveData(Object data, ImportType importType, int index,Long importLogId) {
Leads leads = (Leads) data;
Leads dbLeads = null;
//List<Leads> leadsList = leadsManager.getRepeatLeadsByCompName(leads.getCompName());
//如果 是导入线索,则导入前,先把同一用户的公司名称缓存起来,以备有重复的公司名称时,可以直接代替更新(如果在导入过程中一条一条的更新,发现影响导入速度比较大)
HashMap<Long,ConcurrentHashMap<String,Leads>> leadsMap=ImportManagerImpl.leadsMap;
Long userId=SecurityUtils.getUserId();
if (leadsMap.get(importLogId)==null){
lockLeads.lock();
try{
if (leadsMap.get(importLogId)==null){
List<Leads> dbLeadsList=leadsManager.getLeadsByCompNameOwnerId(ImportManagerImpl.custNamesMap.get(importLogId),userId);
ConcurrentHashMap<String,Leads> hashMapCon=new ConcurrentHashMap<String,Leads>();
if (dbLeadsList!=null && !dbLeadsList.isEmpty()){
for (Leads con: dbLeadsList){
hashMapCon.put(con.getCompName(), con);
}
}
leadsMap.put(importLogId, hashMapCon);
}
} finally {
lockLeads.unlock();
}
}
ConcurrentHashMap<String,Leads> dbList=leadsMap.get(importLogId);
if (dbList!=null && dbList.get(leads.getCompName())!=null){
dbLeads=dbList.get(leads.getCompName());
}
int result = 1;
/** 设置地理位置信息 */
boolean isSave = true;// 是否为新增操作
if(dbLeads != null){
isSave = false;
}
//默认 负责人 为本用户
leads.setOwnerId(SecurityUtils.getUserId());
// 如果导入的数据与原数据poolId一致,再判断是否覆盖;否则直接保存
if (dbLeads != null) {
if (ImportType.COVER.equals(importType)) {
try {
beanUtils.copyProperties(dbLeads, leads);
} catch (Exception e) {
result = -1;
logger.error("copy customer error", e);
}
if(result != -1){
PreSaveEvent preSaveEvent = new PreSaveEvent(dbLeads, false);
publisher.publishEvent(preSaveEvent);
baseDao.update(dbLeads);
result=0;
}
}else if(ImportType.JUMP.equals(importType)){
result = 0;
return result;
}
} else {
leadsManager.save(leads);
dbList.put(leads.getCompName(), leads);
}
return result;
}
protected void afterCreateHeaderSheet(Workbook wb, List<String> headerNames) {
super.afterCreateHeaderSheet(wb, headerNames);
// 销售线索来源
for (LeadsConstant leadsConstant : LeadsConstant.values()) {
createDescSheet(wb, leadsConstant.title, leadsConstant.dbValue);
}
}
private void createDescSheet(Workbook wb, String title, long id) {
Sheet sheet = wb.createSheet(title + IBizImporter.DESC_SHEET);
sheet.setVerticallyCenter(true);
Row row = null;
Cell cell = null;
ListItemVO[] listItemVOs = null;
if(id==9999L && title.equals("性别")){
listItemVOs = new ListItemVO[2];
listItemVOs[0] = new ListItemVO(0,"男");
listItemVOs[1] = new ListItemVO(1,"女");
}else if(id==9998L && title.equals("转换状态")){
listItemVOs = new ListItemVO[2];
listItemVOs[0] = new ListItemVO(0,"未转");
listItemVOs[1] = new ListItemVO(1,"已转");
}else if(id==9997L && title.equals("跟进状态")){
listItemVOs = new ListItemVO[3];
listItemVOs[0] = new ListItemVO(0,"未处理");
listItemVOs[1] = new ListItemVO(1,"已联系");
listItemVOs[2] = new ListItemVO(2,"关闭");
}else {
listItemVOs = listService.findByListId(id);
}
// 设置单元格格式为文本格式
CellStyle style = wb.createCellStyle();
DataFormat fmt = wb.createDataFormat();
style.setDataFormat(fmt.getFormat("@"));
for (int i = 0; i < listItemVOs.length; i++) {
row = sheet.createRow(i);
cell = row.createCell(0);
cell.setCellStyle(style);
cell.setCellValue(listItemVOs[i].getLable());
}
}
@Override
protected Set<String> getDisplayNames() {
Set<String> displayField = new HashSet<String>();
displayField.add("owner_id");
displayField.add("firstContact");
displayField.add("pictureLocation");
displayField.add("valid");
displayField.add("deptId");
if(!poolActivatedService.isOpen()){
displayField.add("cust_pool");
}
return displayField;
}
}
/**
* Copyright (C) 2014 Winbons Technology Software Co.,Ltd
* All Rights Reserved.
* Development of this softwareWinbons Technology Software Co.,Ltd.
* Without the formal written consent of the Company,
* any other individuals, groups may not use,
* copy, modify, or distribute this software
* @Title: ImportListenerManagerImpl.java
* @Package saas.crm.importer
* @Description: TODO(用一句话描述该文件做什么)
* @author star.ye
* @date 2014年11月7日 上午9:16:06
* @version 1.0
*/
package saas.crm.importer;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
/**
* @ClassName: ImportListenerManagerImpl
* @Description: TODO(这里用一句话描述这个类的作用)
* @author star.ye
* @date 2014年11月7日 上午9:16:06
*/
@Component
public class ImportListenerManagerImpl implements ImporterListenerManager, BeanPostProcessor {
private Map<String, ImportListener> importMap = new ConcurrentHashMap<String, ImportListener>();
public ImportListener getImporterListener(String moduleName) {
return importMap.get(moduleName);
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof ImportListener) {
ImportListener importListener = (ImportListener) bean;
importMap.put(importListener.getModuleName(), importListener);
}
return bean;
}
}
相关推荐
在本文中,我们将深入探讨 Spring IOC 的概念、工作原理以及如何在实际项目中应用。 首先,理解 IOC 的概念至关重要。IOC 是一种设计模式,它将对象的创建和管理权反转,由框架负责管理对象的生命周期,而不是由...
Spring的BeanPostProcessor接口提供了一个适配器机制,允许开发者在bean初始化前后插入自定义逻辑,使得不同的组件能够相互协作。 以上只是Spring 5中设计模式的部分应用,实际上Spring框架充分利用了各种设计模式...
12.2.2. 在Spring的application context中创建 SessionFactory 12.2.3. HibernateTemplate 12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. ...
例如,可以通过实现BeanPostProcessor接口来对Bean进行额外的处理,或者通过实现ApplicationContextInitializer接口来在ApplicationContext启动前执行自定义操作。 针对Bean的配置,Spring支持多种方式。基于注解的...
在Spring中可以通过在XML配置文件中添加context命名空间并声明注解驱动元素,或者使用Java配置类上的注解(如@ComponentScan)来启动注解装配。 27、@Component,@Controller,@Repository,@Service有何区别? 这些...
本知识点将围绕Spring AOP的核心组件进行分析,尤其是AnnotationAwareAspectJAutoProxyCreator类的作用,以及BeanPostProcessor接口在创建AOP代理中的角色。 首先,AnnotationAwareAspectJAutoProxyCreator是Spring...
- **BeanPostProcessor**:可以在 Bean 初始化前后执行自定义逻辑。 ##### 3.6 使用 BeanFactoryPostprocessors 定制 Bean 工厂 - **BeanFactoryPostProcessor**:可以在 BeanFactory 初始化之后修改 Bean 的定义...
Spring框架允许开发者扩展容器行为,这包括自定义BeanPostProcessor、BeanFactoryPostProcessor等。 在Spring框架的学习和应用中,开发者需要深刻理解这些核心知识点,只有这样,才能充分利用Spring提供的强大功能...
Bean在Spring中扮演着中心角色,如同OOP中的对象。Spring通过IoC容器管理Bean之间的依赖关系,实现了代码解耦和模块化。IoC容器(也称为依赖注入容器)通过配置文件或注解来定义Bean及其依赖,使得在运行时动态地...
Spring 的核心特性之一是依赖注入,它允许开发者在运行时通过容器来管理对象及其依赖关系,而不是在代码中硬编码。这提高了代码的可测试性和可维护性,因为对象的创建和组装过程被解耦。 2. **Bean 容器(Bean ...
- BeanPostProcessor接口允许开发者在bean初始化前后执行自定义操作。 - **3.8.2 使用BeanFactoryPostProcessor定制配置元数据** - 可以修改Spring容器中的bean定义。 - **3.8.3 使用FactoryBean定制实例化逻辑*...
DI是Spring的核心特性,允许在运行时动态地将依赖关系注入到对象中,而不是由对象自行查找或创建。这使得代码更易于测试和维护,降低了组件之间的耦合度。 4. **Bean的范围** - Singleton:默认的Bean范围,...
6.8.1. 在Spring中使用AspectJ来为domain object进行依赖注入 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用中使用AspectJ Load-time weaving(LTW) 6.9. ...
5. **BeanPostProcessor**:提供了在bean初始化前后进行自定义处理的机会,可以用来进行依赖注入的补充工作。 五、实战应用 在实际开发中,我们可以结合注解驱动和XML配置来实现依赖注入。例如,使用`@Autowired`...
6.8.1. 在Spring中使用AspectJ进行domain object的依赖注入 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用中使用AspectJ加载时织入(LTW) 6.9. 更多资源 7...
6.8.4. 在Spring应用中使用AspectJ Load-time weaving(LTW) 6.9. 其它资源 7. Spring AOP APIs 7.1. 简介 7.2. Spring中的切入点API 7.2.1. 概念 7.2.2. 切入点实施 7.2.3. AspectJ切入点表达式 7.2.4. ...
- **示例**:实现 BeanPostProcessor 接口,并重写 postProcessBeforeInitialization 和 postProcessAfterInitialization 方法来修改 bean 的行为。 #### Spring Bean 定义继承 Bean 定义也可以支持继承,子 bean ...
6.8.1. 在Spring中使用AspectJ进行domain object的依赖注入 6.8.2. Spring中其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用中使用AspectJ加载时织入(LTW) 6.9. 更多资源 7...