KamiG

门户

Showing 1000 changed files with 4777 additions and 0 deletions

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.runsa</groupId>
<artifactId>crmapp</artifactId>
<version>1.0.1-SNAPSHOT</version>
<relativePath>../crmapp/pom.xml</relativePath>
</parent>
<artifactId>crm-base</artifactId>
<packaging>jar</packaging>
<name>crm-base</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring_version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis_version}</version>
</dependency>
<!-- aspect java -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj_version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj_version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring_version}</version>
</dependency>
<!-- java code generation -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>5.0.2</version>
</dependency>
<!-- json -->
<dependency><!-- databind 编译依赖annotations,core -->
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson_xml_version}</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency><!-- databind 编译依赖annotations,core -->
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson_xml_version}</version>
</dependency>
<dependency><!-- mapper-asl 编译依赖 core-asl 不需要再次引用 -->
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>${jackson_version}</version>
</dependency>
<!-- redis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.6.2.RELEASE</version>
</dependency>
<!-- java excel -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi_version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi_version}</version>
</dependency>
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>1.4.01</version>
</dependency>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.11.0</version>
</dependency>
<!-- httpClient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpClient_version}</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>${httpClient_version}</version>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>${commons_configuration_version}</version>
</dependency>
<!-- http async -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpasyncclient</artifactId>
<version>4.1</version>
</dependency>
<!-- java mail -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>mailapi</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>smtp</artifactId>
<version>1.5.2</version>
</dependency>
<!-- java date time -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.5</version>
</dependency>
<!-- commons -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.9</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.3</version>
</dependency>
<!-- google guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
<!-- quartz -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>${quartz_version}</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>${quartz_version}</version>
</dependency>
<dependency>
<groupId>de.alpharogroup</groupId>
<artifactId>jgeohash</artifactId>
<version>1.4.7</version>
</dependency>
<!-- qiniu picture -->
<dependency>
<groupId>com.qiniu</groupId>
<artifactId>qiniu-java-sdk</artifactId>
<version>7.0.7</version>
</dependency>
<dependency>
<groupId>com.aliyun.mns</groupId>
<artifactId>aliyun-sdk-mns</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-amqp</artifactId>
<version>1.5.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>2.4.6</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.4.Final</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.9</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson_version}</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>${ehcache_core_version}</version>
</dependency>
</dependencies>
</project>
package cn.runsa.crmapp.base;
import java.util.Date;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
/**
* 系统常量
*
* @author Stephen
*
*/
public class Constants {
/**
* rest webservice 提供的页面地址
*/
public static final String CONSTANTS_SERVER_WEB_URL = "SERVER_URL";
/**
* rest webservice 提供页面的超时时间
*/
public static final int CONSTANTS_API_PAGE_REGISTER_TIMEOUT = 30*60;
/**
* rest webservice 提供页面的业务:会员入会
*/
public static final String CONSTANTS_API_PAGE_SCOPE_REGISTER = "REGISTER";
public static final String CONSTANTS_CLASS_IMPL_PROFILE = "class.impl.profile";
public static final String CONSTANTS_CLASS_IMPL_SYSTEM = "system";
public static final String CONSTANTS_SERVER_CONFIG_PATH = "server_config";
/**
* 系统默认字符集
*/
public static final String CONSTANTS_DEFAULT_CHARSET = "UTF-8";
public static final String CONSTANTS_DEFAULT_SQL_DELIMITER = "#@#!#";
/**
* 内容服务的类型:url
*/
public static final Byte CONSTANTS_CONTENT_URL = 0;
/**
* 东八区:中国
*/
public static final int CONSTANTS_CHINA_OFFSET_UTC = 8;
/**
* 一天的秒
*/
public static final int CONSTANTS_MILLS_OF_DAYS = 24 * 60 * 60 * 1000;
/**
* 操作失败(响应到前端)
*/
public static final String RES_EXEC_FAILURE = "cn.runsa.failure";
/**
* 阳历
*/
public static final int CALENDAR_GREGORIAN = 0;
/**
* 阴历
*/
public static final int CALENDAR_LUNAR = 1;
/**
* 未婚
*/
public static final int MARRIAGE_NO = 0;
/**
* 已婚
*/
public static final int MARRIAGE_YES = 1;
/**
* 婚姻保密
*/
public static final int MARRIAGE_UNKNOWN = 2;
/**
* 女
*/
public static final int SEX_FEMALE = 0;
/**
* 男
*/
public static final int SEX_MALE = 1;
/**
* 性别保密
*/
public static final int SEX_UNKNOWN = 2;
/**
* 永久
*/
public static Date DATE_FOR_EVER = new DateTime(2099, 12, 31, 23, 59, 59,DateTimeZone.forOffsetHours(CONSTANTS_CHINA_OFFSET_UTC)).toDate();
/**
* 业务处理需要分页的默认值
*/
public static final int CONSTANTS_BUSINESS_DEFAULT_PAGE_SIZE = 100;
/**
* 顾客未验证
*/
public static final byte CONSTANTS_CUSTOMER_VERIFY_NOT = 0;
/**
* 非会员
*/
public static final Byte CONSTANTS_CUSTOMER_NOT_MEMBER = (byte)0;
/**
* 会员
*/
public static final Byte CONSTANTS_CUSTOMER_MEMBER = (byte)1;
/**
* 顾客来源渠道:线下
*/
public static final String CONSTANTS_CUSTOMER_CHANNEL_OFFLINE = "OFFLINE";
/**
* 顾客来源渠道:微信
*/
public static final String CONSTANTS_CUSTOMER_CHANNEL_WEIXIN = "WEIXIN";
/**
* 顾客来源:门店
*/
public static final String CONSTANTS_CUSTOMER_SOURCE_SITE = "SIT";
/**
* 顾客来源:推荐顾客
*/
public static final String CONSTANTS_CUSTOMER_SOURCE_CUSTOMER = "CST";
/**
* 顾客来源:推荐雇员
*/
public static final String CONSTANTS_CUSTOMER_SOURCE_EMPLOYEE = "EMP";
/**
* 顾客来源:优惠券
*/
public static final String CONSTANTS_CUSTOMER_SOURCE_COUPON = "CPN";
/**
* 顾客来源:搜索公众号
*/
public static final String CONSTANTS_CUSTOMER_SOURCE_WEIXINGZH = "GZH";
/**
* 顾客来源:物流单
*/
public static final String CONSTANTS_CUSTOMER_SOURCE_EXPRESS = "EXP";
/**
* 顾客来源:商品
*/
public static final String CONSTANTS_CUSTOMER_SOURCE_GOODS = "GDS";
/**
* 顾客来源:活动
*/
public static final String CONSTANTS_CUSTOMER_SOURCE_ACTIVITY = "ACT";
/**
* 顾客来源:订单
*/
public static final String CONSTANTS_CUSTOMER_SOURCE_ORDER= "ODR";
/**
* 顾客来源:APP
*/
public static final String CONSTANTS_CUSTOMER_SOURCE_APP = "APP";
/**
* 优惠券来源:内部券
*/
public static final int CONSTANTS_COUPONS_COME_FROM_INNER = 0;
/**
* 优惠券来源:外部券
*/
public static final int CONSTANTS_COUPONS_COME_FROM_OUTER = 1;
/**
* 优惠券类型:折扣券
*/
public static final int CONSTANTS_COUPONS_TYPE_DISCOUNT = 0;
/**
* 优惠券类型:金额券
*/
public static final int CONSTANTS_COUPONS_TYPE_MONEY = 1;
/**
* 优惠券类型:礼品券
*/
public static final int CONSTANTS_COUPONS_TYPE_GIFT = 2;
/**
* 优惠券类型:定价券
*/
public static final int CONSTANTS_COUPONS_TYPE_PRICE = 3;
/**
* 优惠券类型:包邮券
*/
public static final int CONSTANTS_COUPONS_TYPE_FREESHIPPING = 4;
/**
* 优惠券的生成方式:自动
*/
public static final int CONSTANTS_COUPONS_GENERATE_AUTO = 0;
/**
* 优惠券的生成方式:导入
*/
public static final int CONSTANTS_COUPONS_GENERATE_IMPORT = 1;
/**
* 优惠券的生成方式:接口接入
*/
public static final int CONSTANTS_COUPONS_GENERATE_INTERFACE = 2;
/**
* 手机
*/
public static final String CONSTANTS_CHANNEL_PHONE = "phone";
/**
* 邮箱
*/
public static final String CONSTANTS_CHANNEL_EMAIL = "email";
/**
* 联盟级
*/
public static final String CONSTANTS_CUSTOMER_RANK_DEFAULT = "LMJ";
/**
* 等级改变:升级
*/
public static final boolean CONSTANTS_RANK_CHANGE_UPGRADE = true;
/**
* 等级改变:降级
*/
public static final boolean CONSTANTS_RANK_CHANGE_DEGRADE = false;
/**
* 订单回执业务:积分
*/
public static final String CONSTANTS_ORDER_SERVICE_POINTS = "POINTS";
/**
* 订单回执业务:优惠券
*/
public static final String CONSTANTS_ORDER_SERVICE_COUPONS = "COUPON";
public static final Byte CONSTANTS_ORDER_POINTS_INCREASE = 1;
public static final Byte CONSTANTS_ORDER_POINTS_DECREASE = 2;
/**
* API账户:公众号
*/
public static final String CONSTANTS_API_TYPE_WXGZH = "GZH";
/**
* API账户:POS
*/
public static final String CONSTANTS_API_TYPE_POS = "POS";
/**
* API账户:电商
*/
public static final String CONSTANTS_API_TYPE_E_COMMERCE = "EC";
/**
* API账户:导购
*/
public static final String CONSTANTS_API_TYPE_SALES_ASSISTANT = "SALES";
/**
* 缓存前缀:token
*/
public static final String CONSTANTS_PREFIX_TOKEN = "TOKEN";
/**
* 缓存前缀:顾客信息
*/
public static final String CONSTANTS_PREFIX_CUSTOMER_INFO = "CST_INF";
/**
* 缓存前缀:顾客手机号
*/
public static final String CONSTANTS_PREFIX_CUSTOMER_ID_PHONE = "CST_TEL";
/**
* 缓存前缀:顾客微信
*/
public static final String CONSTANTS_PREFIX_CUSTOMER_ID_WXGZH = "CST_GZH";
/**
* 缓存前缀:顾客账套信息
*/
public static final String CONSTANTS_PREFIX_CUSTOMER_CRM_ACCOUNTS_ALL = "CST_ACTA";
/**
* 缓存前缀:顾客部分账套信息
*/
public static final String CONSTANTS_PREFIX_CUSTOMER_CRM_ACCOUNTS_PART = "CST_ACTP";
public static final String CONSTANTS_TEMPLATE_SCOPE_POINTS_EXPIRY = "POINTS_EXPIRY";
public static final String CONSTANTS_POINTS_CHANGE_TYPE_ADJUST_MANUAL ="ADJ_MAN";
public static final String CONSTANTS_POINTS_CHANGE_TYPE_EXPIRY ="EXPIRY";
/**
* 新建时字段
*/
public static final String CONSTANTS_FIELD_MODE_NEW = "NEW";
/**
* 更新时字段
*/
public static final String CONSTANTS_FIELD_MODE_MODIFY = "MOD";
/**
* 审批通过
*/
public static final Byte CONSTANTS_APPROVAL_STAT_PASS = 2;
public static final String CONSTANTS_EVENT_ENV_KEY_NAME_POINTS_CALCULATE = "CRM_CALCULATE";
/**
* QiNiu
*/
public static final String QN_ACCESS_KEY = "QN_ACCESS_KEY";
public static final String QN_SECRET_KEY = "QN_SECRET_KEY";
public static final String QN_BUCKET = "QN_BUCKET";
}
package cn.runsa.crmapp.base.cache;
import java.util.Collection;
import javax.annotation.Resource;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.support.CompositeCacheManager;
import org.springframework.stereotype.Component;
import cn.runsa.crmapp.base.utils.SpringUtils;
/**
* @author Stephen
*/
@Component
public final class CacheAdmin {
@Resource(type=CompositeCacheManager.class)
private CacheManager cacheManager;
public void clearCache(CacheManager manager,String name){
if(manager==null)
manager = cacheManager;
Cache cache = manager.getCache(name);
if(cache!=null){
cache.clear();
}
}
public void clearlocalCache(){
CacheManager local = SpringUtils.getBean("local", CacheManager.class);
for(String cache:local.getCacheNames()){
clearCache(local,cache);
}
}
public void clearCenterCache(){
CacheManager center = SpringUtils.getBean("center", CacheManager.class);
for(String cache:center.getCacheNames()){
clearCache(center,cache);
}
}
public void clearAllCache(){
Collection<String> caches = cacheManager.getCacheNames();
for(String cache:caches){
clearCache(null,cache);
}
}
}
package cn.runsa.crmapp.base.conf;
import java.io.IOException;
import java.util.Properties;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import cn.runsa.crmapp.base.Constants;
public class ServerConfigration {
private final static Properties prop;
static{
try {
prop = PropertiesLoaderUtils.loadProperties(new FileSystemResource(System.getProperty(Constants.CONSTANTS_SERVER_CONFIG_PATH)));
} catch (IOException e) {
LoggerFactory.getLogger(ServerConfigration.class).error("load resource-product configration file error",e);
throw new RuntimeException(e);
}
}
public static Properties getServerConfig(){
return prop;
}
}
package cn.runsa.crmapp.base.email;
import java.util.Calendar;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.Message.RecipientType;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SendMail {
private final static Logger logger = LoggerFactory.getLogger(SendMail.class);
public static final String EN_CODE = "text/html;charset=gb2312";
private Transport transport;
private Session mailSession;
private InternetAddress fromAddress;
public SendMail(String smtpHost, String from, String fromUserPassword) throws MessagingException{
this.connect(smtpHost, from, fromUserPassword);
}
public void connect(String smtpHost, String from, String fromUserPassword) throws MessagingException {
// 第一步:配置javax.mail.Session对象
System.out.println("为" + smtpHost + "配置mail session对象");
fromAddress = new InternetAddress(from);
Properties props = new Properties();
props.put("mail.smtp.host", smtpHost);
props.put("mail.smtp.starttls.enable", "true");// 使用 STARTTLS安全连接
// props.put("mail.smtp.port", "25"); //google使用465或587端口
props.put("mail.smtp.auth", "true"); // 使用验证
// props.put("mail.debug", "true");
mailSession = Session.getInstance(props, new MyAuthenticator(from, fromUserPassword));
transport = mailSession.getTransport("smtp");
transport.connect(smtpHost, from, fromUserPassword);
}
@SuppressWarnings("static-access")
public void sendMessage(String to, String subject,
String messageText, String messageType) throws MessagingException {
logger.info("开始发送mail.收件人:"+ to);
InternetAddress toAddress = new InternetAddress(to);
MimeMessage message = new MimeMessage(mailSession);
message.setFrom(fromAddress);
message.addRecipient(RecipientType.TO, toAddress);
message.setSentDate(Calendar.getInstance().getTime());
message.setSubject(subject);
if(messageType == null){
message.setContent(messageText, EN_CODE);
}else{
message.setContent(messageText, messageType);
}
// 第三步:发送消息
transport.send(message, message.getRecipients(RecipientType.TO));
System.out.println("message yes");
}
public void sendMessage(String to, String subject,
String messageText) throws MessagingException {
sendMessage(to, subject, messageText,null);
}
@SuppressWarnings("static-access")
public static void sendMessage(String smtpHost, String from, String fromUserPassword, String to, String subject,
String messageText, String messageType) throws MessagingException {
Properties props = new Properties();
props.put("mail.smtp.host", smtpHost);
props.put("mail.smtp.starttls.enable", "true");// 使用 STARTTLS安全连接
// props.put("mail.smtp.port", "25"); //google使用465或587端口
props.put("mail.smtp.auth", "true"); // 使用验证
// props.put("mail.debug", "true");
Session mailSession = Session.getInstance(props, new MyAuthenticator(from, fromUserPassword));
// 第二步:编写消息
logger.info("开始发送mail.发送人:" + from + "收件人:" + to);
InternetAddress fromAddress = new InternetAddress(from);
InternetAddress toAddress = new InternetAddress(to);
MimeMessage message = new MimeMessage(mailSession);
message.setFrom(fromAddress);
message.addRecipient(RecipientType.TO, toAddress);
message.setSentDate(Calendar.getInstance().getTime());
message.setSubject(subject);
if(messageType == null){
message.setContent(messageText, EN_CODE);
}else{
message.setContent(messageText, messageType);
}
// 第三步:发送消息
Transport transport = mailSession.getTransport("smtp");
transport.connect(smtpHost, from, fromUserPassword);
transport.send(message, message.getRecipients(RecipientType.TO));
transport.close();
System.out.println("message yes");
}
public void close(){
try {
transport.close();
} catch (MessagingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
System.out.println("单发一人用法,自带关闭");
SendMail.sendMessage("smtp.runsa.cn", "support@runsa.cn", "Runsatest@123", "472109366@qq.com", "nihao","English123中文", EN_CODE);
System.out.println("连续发多人用法,需要手动关闭连接");
SendMail send = new SendMail("smtp.runsa.cn", "support@runsa.cn", "Runsatest@123");
send.sendMessage("472109366@qq.com", "nihao","English123中文", EN_CODE);
send.sendMessage("472109366@qq.com", "nihao","English123中文", EN_CODE);
send.close();
} catch (MessagingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class MyAuthenticator extends Authenticator {
String userName = "";
String password = "";
public MyAuthenticator() {
}
public MyAuthenticator(String userName, String password) {
this.userName = userName;
this.password = password;
}
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(userName, password);
}
}
package cn.runsa.crmapp.base.email;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.Message.RecipientType;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SendMail2 {
private final static Logger logger = LoggerFactory.getLogger(SendMail2.class);
public static final String EN_CODE = "text/html;charset=gb2312";
private Transport transport;
private Session mailSession;
private InternetAddress fromAddress;
public SendMail2(String smtpHost, String from, String fromUserPassword) throws MessagingException{
this.connect(smtpHost, from, fromUserPassword);
}
@SuppressWarnings("static-access")
public void connect(String smtpHost, String from, String fromUserPassword) throws MessagingException {
// 第一步:配置javax.mail.Session对象
System.out.println("为" + smtpHost + "配置mail session对象");
fromAddress = new InternetAddress(from);
Properties props = new Properties();
props.put("mail.smtp.host", smtpHost);
props.put("mail.smtp.starttls.enable", "true");// 使用 STARTTLS安全连接
// props.put("mail.smtp.port", "25"); //google使用465或587端口
props.put("mail.smtp.auth", "true"); // 使用验证
// props.put("mail.debug", "true");
mailSession = Session.getInstance(props, new MyAuthenticator(from, fromUserPassword));
transport = mailSession.getTransport("smtp");
transport.connect(smtpHost, from, fromUserPassword);
}
public void sendMsg(String subject, String messageText){
}
@SuppressWarnings("static-access")
public void sendMessage(String to, String subject,
String messageText, String messageType) throws MessagingException {
System.out.println("编写消息from——to:" + "——" + to);
InternetAddress toAddress = new InternetAddress(to);
MimeMessage message = new MimeMessage(mailSession);
message.setFrom(fromAddress);
message.addRecipient(RecipientType.TO, toAddress);
message.setSentDate(Calendar.getInstance().getTime());
message.setSubject(subject);
if(messageType == null){
message.setContent(messageText, EN_CODE);
}else{
message.setContent(messageText, messageType);
}
// 第三步:发送消息
transport.send(message, message.getRecipients(RecipientType.TO));
System.out.println("message yes");
}
public void close(){
try {
transport.close();
} catch (MessagingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
System.out.println(sdf.format(new Date()));
SendMail2 send = new SendMail2("smtp.runsa.cn", "support@runsa.cn", "Runsatest@123");
send.sendMessage("472109366@qq.com", "nihao",
"---------------wrwe-----------中文", EN_CODE);
System.out.println(sdf.format(new Date()));
send.sendMessage("472109366@qq.com", "nihao",
"---------------wrwe-----------中文", EN_CODE);
System.out.println(sdf.format(new Date()));
} catch (MessagingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package cn.runsa.crmapp.base.event;
import cn.runsa.crmapp.base.event.exception.BusinessEventException;
/**
* 抽象evnetHandler,定义流程
* @author Stephen
*/
public abstract class AbstractBusinessEventHandler implements BusinessEventHandler {
public abstract boolean preHandle(BusinessEvent event);
public abstract void handle(BusinessEvent event) throws BusinessEventException;
public abstract void postHandle(BusinessEvent event, BusinessEventException e);
@Override
public final void listen(BusinessEvent event) {
if (preHandle(event)) {
try {
handle(event);
} catch (BusinessEventException e) {
postHandle(event, e);
}
}
}
}
package cn.runsa.crmapp.base.event;
import java.io.Serializable;
import java.util.Map;
/**
* 业务事件
* @author Stephen
*
*/
public class BusinessEvent implements Serializable{
private static final long serialVersionUID = 7738977611490794967L;
/**
* 事件代号
*/
private String eventCode;
/**
* 账套
*/
private Long [] acts;
private Object target;
private Map<String,Object> env;
private long timestamp;
public BusinessEvent() {
super();
}
public BusinessEvent(Object target, long timestamp) {
super();
this.target = target;
this.timestamp = timestamp;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
public Map<String, Object> getEnv() {
return env;
}
public Object getEnval(String key){
if(this.env!=null){
return this.env.get(key);
}
return null;
}
public void setEnv(Map<String, Object> env) {
this.env = env;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public String getEventCode() {
return eventCode;
}
public void setEventCode(String eventCode) {
this.eventCode = eventCode;
}
public Long[] getActs() {
return acts;
}
public void setActs(Long[] acts) {
this.acts = acts;
}
}
package cn.runsa.crmapp.base.event;
import com.google.common.eventbus.Subscribe;
/**
* 业务事件监听接口
* @author Stephen
*
*/
public interface BusinessEventHandler {
@Subscribe
void listen(BusinessEvent event);
}
package cn.runsa.crmapp.base.event;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import com.google.common.eventbus.EventBus;
/**
* @author Stephen
*/
@Aspect
public class BusinessEventHelper {
@Before("execution(public * com.google.common.eventbus.EventBus.post(*)")
public void eventBefore(JoinPoint point){
Object[] args = point.getArgs();
if(args !=null&&args.length==1){
Object obj = args[0];
if(BusinessEvent.class.equals(obj.getClass())){
BusinessEvent event = (BusinessEvent) args[0];
EventBus bus = (EventBus) point.getTarget();
event.setEventCode(bus.identifier());
}
}
}
}
package cn.runsa.crmapp.base.event;
import java.util.HashMap;
import java.util.Map;
/**
* 业务事件builder
* @author Stephen
*/
public class EventBuilder {
private BusinessEvent event;
private EventBuilder(){
}
public static EventBuilder newEvent(Object target){
EventBuilder builder = new EventBuilder();
builder.event = new BusinessEvent(target,System.currentTimeMillis());
return builder;
}
public static EventBuilder newEvent(Object target,String code){
EventBuilder builder = new EventBuilder();
builder.event = new BusinessEvent(target,System.currentTimeMillis());
builder.event.setEventCode(code);
return builder;
}
public EventBuilder putEnv(String name,Object value){
this.getEnvMap().put(name, value);
return this;
}
public EventBuilder putEnvs(Map<String,Object> envs){
this.getEnvMap().putAll(envs);
return this;
}
public EventBuilder putActs(Long [] acts){
this.event.setActs(acts);
return this;
}
public BusinessEvent build(){
return this.event;
}
private Map<String,Object> getEnvMap(){
if(event.getEnv()==null){
synchronized (event) {
if(event.getEnv()==null){
event.setEnv(new HashMap<String,Object>());
}
}
}
return event.getEnv();
}
}
package cn.runsa.crmapp.base.event;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ClassPathResource;
import cn.runsa.crmapp.base.utils.SpringUtils;
import com.google.common.eventbus.EventBus;
/**
* Build EventBus<br>
* 一个id,对应唯 一 一 个EventBus
*
* @author Stephen
*
*/
public class EventBusBuilder {
private final static Logger log = LoggerFactory.getLogger(EventBusBuilder.class);
private static final Map<String, EventBus> list = new HashMap<String, EventBus>();
static {
init();
}
/**
* 获取命名EventBus
*
* @param identifier
* @return
*/
public static EventBus named(String identifier) {
EventBus eventBus = null;
if (list.containsKey(identifier)) {
eventBus = list.get(identifier);
if (eventBus != null)
return eventBus;
}
eventBus = new EventBus(identifier);
list.put(identifier, eventBus);
return eventBus;
}
/**
* 读取配置,初始化
*/
@SuppressWarnings("unchecked")
public static void init() {
SAXReader reader = new SAXReader();
InputStream in = null;
try {
in = new ClassPathResource("event/business_event.xml").getInputStream();
Document doc = reader.read(in);
Element root = doc.getRootElement();
//event element
List<Element> events = root.elements("event");
for (Element ele : events) {
//event id
String name = ele.attributeValue("id").trim();
EventBus bus = new EventBus(name);
Element ls = ele.element("listeners");
if (ls != null) {
List<Element> list = ls.elements("listener");
if (list != null && list.size() > 0) {
List<Listener> listeners = new ArrayList<Listener>();
for (Element lis : list) {
String clz = lis.attributeValue("class");
String priority = lis.attributeValue("priority");
String async = lis.attributeValue("async");
if (StringUtils.isNotBlank(clz)) {
Listener listner = new Listener();
listner.setClz(clz.trim());
if (StringUtils.isBlank(async)) {
listner.setAsync(false);
} else {
listner.setAsync("true".equalsIgnoreCase(async.trim()));
}
if (StringUtils.isNotBlank(priority)) {
listner.setPriority(Integer.parseInt(priority.trim()));
}
listeners.add(listner);
}
}
if (listeners.size() > 0) {
Collections.sort(listeners);
for (Listener l : listeners) {
try{
bus.register(SpringUtils.getBean(Class.forName(l.getClz())));
}catch(Exception e){
log.error("load class error", e);
}
}
}
}
}
list.put(name, bus);
}
} catch (Exception e) {
log.error("init event bus builder throw an exception", e);
}finally{
IOUtils.closeQuietly(in);
}
}
}
package cn.runsa.crmapp.base.event;
/**
* @author Stephen
*/
public class Listener implements Comparable<Listener>{
private String clz;
private int priority;
private boolean async;
public String getClz() {
return clz;
}
public void setClz(String clz) {
this.clz = clz;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public boolean isAsync() {
return async;
}
public void setAsync(boolean async) {
this.async = async;
}
@Override
public int compareTo(Listener o) {
if(o==null){
return -1;
}
if(this==o){
return 0;
}
if(this.priority>o.priority){
return -1;
}else if(this.priority<o.priority){
return 1;
}else{
return 0;
}
}
}
package cn.runsa.crmapp.base.event;
import cn.runsa.crmapp.base.event.exception.BusinessEventException;
/**
* 简单实现的eventHandler,用户可以直接继承
* @author Stephen
*
*/
public abstract class SimpleBusinessEventHandler extends AbstractBusinessEventHandler{
@Override
public boolean preHandle(BusinessEvent event) {
return true;
}
/**
* 只是把exception记录下来
*/
@Override
public void postHandle(BusinessEvent event, BusinessEventException e) {
if(e!=null){
e.printStackTrace();
}
}
}
package cn.runsa.crmapp.base.event.exception;
public class BusinessEventException extends Exception {
private static final long serialVersionUID = -97726556007905578L;
public BusinessEventException() {
super();
}
public BusinessEventException(String message, Throwable cause) {
super(message, cause);
}
public BusinessEventException(String message) {
super(message);
}
public BusinessEventException(Throwable cause) {
super(cause);
}
}
package cn.runsa.crmapp.base.excel.converter;
import java.util.HashSet;
import java.util.Set;
import cn.runsa.crmapp.base.excel.core.Converter;
/**
* @author Stephen
*/
public class BooleanConverter implements Converter<Boolean>{
private static final Set<String> trueValues = new HashSet<String>(4);
private static final Set<String> falseValues = new HashSet<String>(4);
static {
trueValues.add("true");
trueValues.add("on");
trueValues.add("yes");
trueValues.add("1");
trueValues.add("是");
falseValues.add("false");
falseValues.add("off");
falseValues.add("no");
falseValues.add("0");
trueValues.add("否");
}
@Override
public Boolean convert(String source){
String value = source.trim();
if ("".equals(value)) {
return null;
}
value = value.toLowerCase();
if (trueValues.contains(value)) {
return Boolean.TRUE;
}
else if (falseValues.contains(value)) {
return Boolean.FALSE;
}
else {
throw new IllegalArgumentException(source+"无法判断是或否");
}
}
}
package cn.runsa.crmapp.base.excel.converter;
import java.text.ParseException;
import java.util.Date;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.poi.ss.usermodel.DateUtil;
import cn.runsa.crmapp.base.excel.core.Converter;
/**
* @author Stephen
*/
public class DateConverter implements Converter<Date> {
private String defaultPattern = "yyyy-MM-dd";
private String[] acceptPatterns = new String[] {"yyyy-MM-dd HH:mm:ss"};
public DateConverter(){
super();
}
public DateConverter(String pattern){
this(pattern,null);
}
public DateConverter(String pattern,String [] accepts){
super();
if(pattern==null){
this.defaultPattern=pattern;
}
if(accepts!=null&&accepts.length>0){
this.acceptPatterns = accepts;
}
}
@Override
public Date convert(String source){
Date date=null;
String value = source.trim();
if ("".equals(value)) {
return null;
}
if(source.matches("^\\d+\\.\\d+$")){
double dt = Double.parseDouble(source);
date = DateUtil.getJavaDate(dt);
return date;
}
try{
date=DateUtils.parseDate(source,defaultPattern);
if(date==null){
date=DateUtils.parseDate(source,acceptPatterns);
}
}catch(ParseException e){
throw new IllegalArgumentException(source+"无法转换为日期");
}
return date;
}
}
package cn.runsa.crmapp.base.excel.converter;
import org.springframework.util.NumberUtils;
import cn.runsa.crmapp.base.excel.core.Converter;
/**
* @author Stephen
* 数字转换器
*/
public class NumberConverter<T extends Number> implements Converter<T>{
private final Class<T> targetType;
public NumberConverter(Class<T> targetType){
this.targetType = targetType;
}
@Override
public T convert(String source) {
if (source.length() == 0) {
return null;
}
try{
return NumberUtils.parseNumber(source, this.targetType);
}catch(Exception e){
e.printStackTrace();
throw new IllegalArgumentException(source+"无法转换为数字");
}
}
}
package cn.runsa.crmapp.base.excel.core;
/**
* @author Stephen
*/
public interface ConvertService {
boolean canConvert(Class<?> targetType);
<T> T convert(String source, Class<T> targetType);
}
package cn.runsa.crmapp.base.excel.core;
/**
* 类型转换器
* @author Stephen
*/
public interface Converter<T> {
T convert(String source);
}
package cn.runsa.crmapp.base.excel.core;
/**
* 注册类型转换
* @author Stephen
*/
public interface ConverterRegistry {
<T> void addConverter(Class<T> type,Converter<T> converter);
void removeConvertible(Class<?> type);
}
package cn.runsa.crmapp.base.excel.core;
/**
* @author Stephen
*/
public class DBExcelSchema {
}
package cn.runsa.crmapp.base.excel.core;
import java.util.Map;
import java.util.regex.Pattern;
import org.apache.commons.lang3.builder.ToStringBuilder;
/**
* excel的列
* @author Stephen
* @version 1.0
*/
public class ExcelCol implements Comparable<ExcelCol>{
private Class<?> type;
private String code;//name;
private String name;//title;
/**
* 排序
*/
private Integer sortCode = 0;
private boolean nullable = true;
private Integer maxLength = -1;
private Integer minLength = 0;
/**
* 考虑到有可能做维护界面,预留字符串pattern
*/
private String pattern;
/**
* 编译后的pattern
*/
private Pattern compiledPattern;
private Map<String, Object> items; //下拉后的选项值.数据来源于code_list 的值
public Class<?> getType() {
return type;
}
public void setType(Class<?> type) {
this.type = type;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getSortCode() {
return sortCode;
}
public void setSortCode(Integer sortCode) {
this.sortCode = sortCode;
}
public boolean isNullable() {
return nullable;
}
public void setNullable(boolean nullable) {
this.nullable = nullable;
}
public Integer getMaxLength() {
return maxLength;
}
public void setMaxLength(Integer maxLength) {
this.maxLength = maxLength;
}
public Integer getMinLength() {
return minLength;
}
public void setMinLength(Integer minLength) {
this.minLength = minLength;
}
public String getPattern() {
return pattern;
}
public void setPattern(String pattern) {
this.pattern = pattern;
}
public Pattern getCompiledPattern() {
return compiledPattern;
}
public void setCompiledPattern(Pattern compiledPattern) {
this.compiledPattern = compiledPattern;
}
public Map<String, Object> getItems() {
return items;
}
public void setItems(Map<String, Object> items) {
this.items = items;
}
@Override
public int compareTo(ExcelCol o) {
if(o ==null){
return 1;
}else{
return this.sortCode-o.sortCode;
}
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}
package cn.runsa.crmapp.base.excel.core;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* excel数据获取后续的处理,如
* 每次读几行,读完之后存入临时表
* 调用存储过程等
* @author Stephen
*/
public abstract class ExcelDataHandler {
/**
* 每次获取行数的默认数目
*/
private static final int DEFAULT_SIZE = 100;
private static final int MAX_ERROR_SIZE = 100; //最大错误行数,超过此行数,不需要处理,返回错误结果
private static final int MAX_SIZE = 10000; //最大处理行数
/**
* 每次获取的行数
*/
private int sizeOneTime;
private int maxErrRow;
/**
* excel数据处理的上下文环境变量
*/
private Map<String,Object> excelDataContext = new HashMap<String,Object>();
protected ExcelDataHandler(){
this(null);
}
protected ExcelDataHandler(Map<String,Object> context){
super();
this.sizeOneTime = DEFAULT_SIZE;
this.maxErrRow = MAX_ERROR_SIZE;
if(context!=null){
this.excelDataContext = context;
}else{
this.excelDataContext = new HashMap<String,Object>();
}
}
protected ExcelDataHandler(Map<String,Object> context, int maxRow, int maxErrRow){
super();
if(maxRow>0&&maxRow<=MAX_SIZE){
this.sizeOneTime = maxRow;
}else{
this.sizeOneTime = DEFAULT_SIZE;
}
if(maxErrRow>0&&maxErrRow<=MAX_ERROR_SIZE){
this.maxErrRow = maxErrRow;
}else{
this.maxErrRow = MAX_ERROR_SIZE;
}
if(context!=null){
this.excelDataContext = context;
}else{
this.excelDataContext = new HashMap<String,Object>();
}
}
protected void putData(String key,Object val){
excelDataContext.put(key, val);
}
protected void putDatas(Map<String,Object> vals){
excelDataContext.putAll(vals);
}
public int getSizeOneTime() {
return sizeOneTime;
}
public Map<String, Object> getExcelDataContext() {
return excelDataContext;
}
/**
* 处理获取的数据
* @param schema 从db中获取的excel结构
* @param groupId 组id,用于标记是这个用户操作的(用于多用户操作的区分)
* @param datas 获取的数据集
*/
public abstract void dataFetched(ExcelSchema schema, String groupId, List<Map<String, Object>> datas);
/**
* excel数据读取完成
* @param schema 从db中获取的excel结构
* @param headSchema 从excel中获取的结构,和schema的区别在于: schema是预定义格式,headSchema是真实格式
* @param groupId 组id,用于标记是这个用户操作的(用于多用户操作的区分)
* @param 废弃 errorProcessor excel错误处理器 已放在DefaultSheetContentsHandler中处理
* @return 返回失败的数据条数
*/
public abstract ExcelResult dataFinish(ExcelSchema schema, Map<String, ExcelCol> headSchema, String groupId);
}
package cn.runsa.crmapp.base.excel.core;
import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFComment;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
public class ExcelErrorProcessor{
private final Map<String,Integer> headIndex;
private final SXSSFWorkbook workbook;
private final Sheet errorSheet;
// 创建绘图对象
XSSFDrawing p ;
private volatile int next = 0;
public ExcelErrorProcessor(Map<String, ExcelCol> headSchema){
headIndex = new HashMap<String,Integer>(headSchema.size());
for(String str:headSchema.keySet()){
headIndex.put(headSchema.get(str).getCode(),HSSFSheetHandler.toNumber(str)); //存入的是code,待定 zwj,数据存的是位置
}
headIndex.put("RAWREF", headSchema.size());
headIndex.put("ERRMSG", headSchema.size()+1);
workbook = new SXSSFWorkbook(100);
workbook.setCompressTempFiles(true);
errorSheet = workbook.createSheet("错误信息");
p = (XSSFDrawing) errorSheet.createDrawingPatriarch();
Row row = errorSheet.createRow(next++);
Cell cell =null;
//因为现在不读取原数据,所以去掉
// for(ExcelCol col:headSchema.values()){
// Integer theIndex = headIndex.get(col.getCode());
// if(theIndex!=null){
// cell = row.createCell(theIndex);
// cell.setCellValue(col.getName());
//
// }
// }
// int start = headSchema.size();
int start = 0;
cell = row.createCell(start);
cell.setCellValue("原excel位置");
cell = row.createCell(start+1);
cell.setCellValue("报错信息");
}
//ExcelResult result
public void flushErrors(List<Map<String,Object>> errorRows){
if(errorRows!=null&&errorRows.size()>0){
for(Map<String,Object> rowVal:errorRows){
Row row = errorSheet.createRow(next++);
Cell cell =null;
for(String name:rowVal.keySet()){
Integer theIndex = headIndex.get(name);
if(theIndex!=null){
cell = row.createCell(theIndex);
Object val = rowVal.get(name);
if(val==null){
cell.setCellValue("");
}else{
cell.setCellValue(val.toString());
}
}
}
}
}
}
public void flushErrors(ExcelResult result){
Map<String,String> errMsgMap = result.getErrMsgMap();
List<Map<String, Object>> errRows = result.getErrRows();
Cell cell =null;
for(Map<String, Object> map: errRows){
Row row = errorSheet.createRow(next++);
for(Map.Entry<String, Object> entry : map.entrySet()){
Integer theIndex = headIndex.get(entry.getKey());
if(theIndex!=null){
cell = row.createCell(theIndex);
Object val = entry.getValue();
if(val==null){
cell.setCellValue("");
}else{
cell.setCellValue(val.toString());
}
}
}
}
for(Map.Entry<String, String> entry:errMsgMap.entrySet()){
Row row = errorSheet.createRow(next++);
cell = row.createCell(0);
cell.setCellValue(entry.getKey());
cell = row.createCell(1);
cell.setCellValue(entry.getValue());
}
// cell.setCellComment(comment);
// SXSSFComment
//
// // 前四个参数是坐标点,后四个参数是编辑和显示批注时的大小.
// XSSFComment comment = p.createCellComment(new XSSFClientAnchor(0, 0, 0,
// 0, (short) 3, 3, (short) 5, 6));
// // 输入批注信息
// comment.setString(new XSSFRichTextString("这是批注内容!"));
// comment.setString(new XSSFRichTextString("这是批注内容!"));
// // 添加作者,选中B5单元格,看状态栏
// comment.setAuthor("toad");
// // 将批注添加到单元格对象中
// if(cell != null){
// cell.setCellComment(comment);
// }
}
public void flushErrors2Excel(ExcelResult result, String groupId){
flushErrors(result);
String filePath =result.getFilePath();
String fileName =result.getFileName();
File file = new File(filePath,fileName);
write(file);
}
/**
* 请用OutputStream接收SXSSFWorkbook
* eg:
* OutputStream ouputStream = response.getOutputStream();
* workbook.write(stream);
* @param result
* @param groupId
* @return excel格式对象
*/
public SXSSFWorkbook flushErrors(ExcelResult result, String groupId){
flushErrors(result);
return workbook;
}
void write(File file){
FileOutputStream stream =null;
try {
stream = new FileOutputStream(file);
stream.flush();
workbook.write(stream);
stream.close();
} catch (Exception e) {
e.printStackTrace();
}finally{
IOUtils.closeQuietly(stream);
}
}
}
package cn.runsa.crmapp.base.excel.core;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.builder.ToStringBuilder;
/**
* excel导入结果
* @author Stephen
*/
public class ExcelResult {
private Integer total; //总行数
private Integer error; //错误行数
private String fileName; //错误的文件名称
private String filePath; //错误的文件名称
private String uuid; //不知道
private Map<String,String> errMsgMap; //错误消息,应该是需要写到文件中的
//是不是需要存错误行数
private List<Map<String, Object>> errRows = new ArrayList<Map<String, Object>>();
public Integer getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
public Integer getError() {
return error;
}
public void setError(Integer error) {
this.error = error;
}
public String getUuid() {
return uuid;
}
public void setUuid(String uuid) {
this.uuid = uuid;
}
public Map<String, String> getErrMsgMap() {
return errMsgMap;
}
public void setErrMsgMap(Map<String, String> errMsgMap) {
this.errMsgMap = errMsgMap;
}
public List<Map<String, Object>> getErrRows() {
return errRows;
}
public void setErrRows(List<Map<String, Object>> errRows) {
this.errRows = errRows;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}
package cn.runsa.crmapp.base.excel.core;
import java.util.List;
public class ExcelSchema {
private String code;
private String title;
private String targetTableName;
private List<ExcelCol> columns;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List<ExcelCol> getColumns() {
return columns;
}
public void setColumns(List<ExcelCol> columns) {
this.columns = columns;
}
public String getTargetTableName() {
return targetTableName;
}
public void setTargetTableName(String targetTableName) {
this.targetTableName = targetTableName;
}
}
package cn.runsa.crmapp.base.excel.core;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageAccess;
import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.StylesTable;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import cn.runsa.crmapp.base.excel.exception.ExcelException;
import cn.runsa.crmapp.base.excel.support.DefaultSheetContentsHandler;
/**
* excel处理工具类
* @author Stephen
*/
public class ExcelUtils {
private static final Logger log = LoggerFactory.getLogger(ExcelUtils.class);
private static final SAXReader saxReader;
static {
saxReader = new SAXReader();
saxReader.setIncludeExternalDTDDeclarations(false);
saxReader.setIncludeInternalDTDDeclarations(false);
saxReader.setValidation(false);
saxReader.setIgnoreComments(true);
saxReader.setStripWhitespaceText(true);
}
//03 excel处理器
private static final HSSFSheetHandler handler = new HSSFSheetHandler();
public static ExcelResult readExcel(File file, ExcelSchema schema,ExcelDataHandler dataHandler)throws ExcelException{
//检查文件
if (!file.exists()) {
throw new ExcelException("文件不存在");
}
if (!file.canRead()) {
throw new ExcelException("文件不可读");
}
//检查文件类型
String fileName = file.getName();
boolean isE2003 = false;
if (StringUtils.isBlank(fileName)) {
throw new ExcelException("无效的文件名,文件名不能为空");
} else if (fileName.endsWith("xlsx")) {
isE2003 = false;
} else if (fileName.endsWith("xls")) {
isE2003 = true;
} else {
throw new ExcelException("无效的文件类型");
}
//检查excel模型
if (schema == null) {
throw new ExcelException("缺少excel表头信息,请配置数据库");
}
if (dataHandler == null) {
throw new ExcelException("缺少excel处理方法");
}
SheetContentsHandler processor = new DefaultSheetContentsHandler(dataHandler, schema);
if (isE2003) {
FileInputStream stream = null;
try {
stream = new FileInputStream(file);
//poi 2003 HSSFWorkbook
HSSFWorkbook workbook = new HSSFWorkbook(stream);
//目前仅处理第一个sheet
HSSFSheet sheet = workbook.getSheetAt(0);
handler.parse(processor,sheet);
return processor.finish();
}catch(ExcelException ee) {
throw ee;
}catch (Exception e) {
log.error("excel处理失败", e);
throw new ExcelException("excel处理失败");
} finally {
IOUtils.closeQuietly(stream);
}
} else {
OPCPackage pkg = null;
InputStream sheet = null;
try {
pkg = OPCPackage.open(file, PackageAccess.READ);
XSSFReader reader = new XSSFReader(pkg);
StylesTable style = reader.getStylesTable();
XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
//字符串常量池
ReadOnlySharedStringsTable stringValueHandler = new ReadOnlySharedStringsTable(pkg);
XSSFSheetXMLHandler xmlHandler = new XSSFSheetXMLHandler(style,stringValueHandler, processor);
parser.setContentHandler(xmlHandler);
Document doc = saxReader.read(reader.getWorkbookData());
Element root = doc.getRootElement();
Element sheets = root.element("sheets");
Element thisSheet = sheets.element("sheet");
String id = thisSheet.attributeValue("id");
sheet = reader.getSheet(id);
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
return processor.finish();
}catch(ExcelException ee) {
throw ee;
} catch (Exception e) {
log.error("excel处理失败", e);
throw new ExcelException("excel处理失败");
} finally {
IOUtils.closeQuietly(sheet);
//todo
try {
pkg.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
package cn.runsa.crmapp.base.excel.core;
import java.math.BigDecimal;
import java.util.Iterator;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DateUtil;
import cn.runsa.crmapp.base.excel.exception.ExcelException;
/**
* 处理excel97-03版本
* @author stephen
*/
public class HSSFSheetHandler {
private static final char[] digits = { 'A', 'B', 'C', 'D', 'E', 'F', 'G','H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T','U', 'V', 'W', 'X', 'Y', 'Z' };
/**
* 解析excel文件
* @throws ExcelException
*/
public void parse(SheetContentsHandler contentHandler, HSSFSheet sheet) throws ExcelException {
int first = sheet.getFirstRowNum();
int last = sheet.getLastRowNum();
if (last - first < 1)
throw new ExcelException("excel内容为空");
for (int i = first; i <= last; i++) {
HSSFRow row = sheet.getRow(i);
//开始行
contentHandler.startRow(i);
Iterator<Cell> cells = row.cellIterator();
while (cells.hasNext()) {
HSSFCell cell = (HSSFCell) cells.next();
String cellRef = getABCNumber(cell.getColumnIndex());
String cellVal = null;
int type = cell.getCellType();
//不处理公式,error类型
switch (type) {
case Cell.CELL_TYPE_BOOLEAN:
cellVal = String.valueOf(cell.getBooleanCellValue());
break;
case Cell.CELL_TYPE_NUMERIC:
//如果是时间
if (isDateFormat(cell)) {
cellVal = SheetContentsHandler.DATE_PREFIX+cell.getDateCellValue().getTime();
} else {
BigDecimal bd = new BigDecimal(cell.getNumericCellValue());
cellVal = bd.toPlainString();
}
break;
case Cell.CELL_TYPE_STRING:
cellVal = cell.getStringCellValue();
break;
default:
break;
}
contentHandler.cell(cellRef, cellVal);
}
contentHandler.endRow();
}
}
/**
* 将列号转换为excel统一格式,如A,B,AB等
* @param number
* @return
*/
public static String getABCNumber(int number) {
if (number < 26) {
return String.valueOf(digits[number]);
} else {
StringBuilder sb = new StringBuilder();
do {
int a = number % 26;
sb.append(digits[a]);
number /= 26;
number--;
} while (number > 25);
sb.append(digits[number]);
return sb.reverse().toString();
}
}
/**
* 将excel统一列号转换为十进制数
* @param excelNum
* @return
*/
public static int toNumber(String excelNum) {
byte[] abcs = excelNum.getBytes();
int number = 0;
if(abcs.length == 1){
number = index(abcs[0]);
}else{
int total = abcs.length-1;
for(int i = 0;i<total;i++){
number=(int) (number+(index(abcs[i])+1)*Math.pow(26, total-i));
}
number+=index(abcs[total]);
}
return number;
}
/**
* 给定字符的序号
* @param abc
* @return
*/
private static int index(byte abc) {
return abc-65;
}
/**
* 判断是否是时间
* @param cell
* @return
*/
private boolean isDateFormat(Cell cell) {
if (cell == null)
return false;
boolean bDate = false;
double d = cell.getNumericCellValue();
if (DateUtil.isValidExcelDate(d)) {
CellStyle style = cell.getCellStyle();
if (style == null)
return false;
int i = style.getDataFormat();
bDate = i >= 0x0e && i <= 0x24;
}
return bDate;
}
}
package cn.runsa.crmapp.base.excel.core;
/**
* 内部枚举,标识类
* @author Stephen
*/
public class InnerEnum {
}
package cn.runsa.crmapp.base.excel.core;
import cn.runsa.crmapp.base.excel.exception.ExcelException;
/**
* @author stephen
* excel内容处理器,事件驱动
*/
public interface SheetContentsHandler {
public static final String DATE_PREFIX = "@Date";
/**
* 开始一行
* @param rowNum 行号,0开始
*/
void startRow(int rowNum);
/**
* 行结束
*/
void endRow() throws ExcelException;
/**
* 获取单元格
* @param cellReference 单元格位置
* @param formattedValue 格式化的字符串值
*/
String cell(String cellReference, String formattedValue);
/**
* excel读取完成
* @return
*/
ExcelResult finish();
}
package cn.runsa.crmapp.base.excel.core;
import java.math.BigDecimal;
import java.util.Date;
import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import cn.runsa.crmapp.base.excel.exception.ExcelException;
public class XSSFSheetXMLHandler extends DefaultHandler {
enum xssfDataType {
BOOLEAN, ERROR, FORMULA, INLINE_STRING, SST_STRING, NUMBER;
}
//sheet样式表
private StylesTable stylesTable;
//字符串常量池
private ReadOnlySharedStringsTable sharedStringsTable;
//excel内容处理器
private final SheetContentsHandler output;
// V开始
private boolean vIsOpen;
// F开始
private boolean fIsOpen;
// Inline String 开始
private boolean isIsOpen;
private xssfDataType nextDataType;
private short formatIndex;
private String formatString;
private String cellRef;
private StringBuffer value = new StringBuffer();
private StringBuffer formula = new StringBuffer();
/**
* Accepts objects needed while parsing.
*
* @param styles
* Table of styles
* @param strings
* Table of shared strings
*/
public XSSFSheetXMLHandler(StylesTable styles,ReadOnlySharedStringsTable strings,SheetContentsHandler sheetContentsHandler) {
this.stylesTable = styles;
this.sharedStringsTable = strings;
this.output = sheetContentsHandler;
this.nextDataType = xssfDataType.NUMBER;
}
private boolean isTextTag(String name) {
if ("v".equals(name)) {
return true;
}
if ("inlineStr".equals(name)) {
return true;
}
if ("t".equals(name) && isIsOpen) {
return true;
}
return false;
}
public void startElement(String uri, String localName, String name,Attributes attributes) throws SAXException {
if (isTextTag(name)) {
vIsOpen = true;
// Clear
value.setLength(0);
} else if ("is".equals(name)) {
isIsOpen = true;
} else if ("f".equals(name)) {
// Clear
formula.setLength(0);
//标记将要处理公式
if (nextDataType == xssfDataType.NUMBER) {
nextDataType = xssfDataType.FORMULA;
}
// 公式类型
String type = attributes.getValue("t");
if (type != null && type.equals("shared")) {
String ref = attributes.getValue("ref");
//如果有引用
if (ref != null) {
fIsOpen = true;
}
} else {
fIsOpen = true;
}
} else if ("row".equals(name)) {
//开始行
int rowNum = Integer.parseInt(attributes.getValue("r")) - 1;
output.startRow(rowNum);
}
//开始单元格
else if ("c".equals(name)) {
//默认number.
this.nextDataType = xssfDataType.NUMBER;
this.formatIndex = -1;
this.formatString = null;
cellRef = attributes.getValue("r");//.replaceAll("\\d", "");
String cellType = attributes.getValue("t");
String cellStyleStr = attributes.getValue("s");
if ("b".equals(cellType))
nextDataType = xssfDataType.BOOLEAN;
else if ("e".equals(cellType))
nextDataType = xssfDataType.ERROR;
else if ("inlineStr".equals(cellType))
nextDataType = xssfDataType.INLINE_STRING;
else if ("s".equals(cellType))
nextDataType = xssfDataType.SST_STRING;
else if ("str".equals(cellType))
nextDataType = xssfDataType.FORMULA;
else if (cellStyleStr != null) {
//带有样式的内容
int styleIndex = Integer.parseInt(cellStyleStr);
XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);
this.formatIndex = style.getDataFormat();
this.formatString = style.getDataFormatString();
if (this.formatString == null)
this.formatString = BuiltinFormats.getBuiltinFormat(this.formatIndex);
}
}
}
public void endElement(String uri, String localName, String name)throws ExcelException,SAXException {
String thisStr = null;
//读取excel文本内容(excel以xml格式存储,会有字段标记此单元格的)
if (isTextTag(name)) {
vIsOpen = false;
switch (nextDataType) {
case BOOLEAN:
char first = value.charAt(0);
thisStr = first == '0' ? "false" : "true";
break;
case INLINE_STRING:
XSSFRichTextString rtsi = new XSSFRichTextString(value.toString());
thisStr = rtsi.toString();
break;
case SST_STRING:
String sstIndex = value.toString();
try {
int idx = Integer.parseInt(sstIndex);
XSSFRichTextString rtss = new XSSFRichTextString(sharedStringsTable.getEntryAt(idx));
thisStr = rtss.toString();
} catch (NumberFormatException ex) {
//undo
}
break;
case NUMBER:
String n = value.toString();
if (this.formatString != null) {
//若为日期
if (this.formatIndex >= 0x0e && this.formatIndex <= 0x24) {
Date date = DateUtil.getJavaDate(Double.parseDouble(n));
thisStr = SheetContentsHandler.DATE_PREFIX+date.getTime();
} else {
BigDecimal bd = new BigDecimal(n);
thisStr = bd.toPlainString();
}
} else
thisStr = n;
break;
default:
break;
}
output.cell(cellRef, thisStr);
} else if ("f".equals(name)) {
fIsOpen = false;
} else if ("is".equals(name)) {
isIsOpen = false;
} else if ("row".equals(name)) {
output.endRow();
}
}
public void characters(char[] ch, int start, int length) throws SAXException {
if (vIsOpen) {
value.append(ch, start, length);
}
if (fIsOpen) {
formula.append(ch, start, length);
}
}
}
package cn.runsa.crmapp.base.excel.exception;
import org.xml.sax.SAXException;
@SuppressWarnings("serial")
/**
* excel处理异常
* @author stephen
*/
public class ExcelException extends SAXException {
public ExcelException() {
super();
}
public ExcelException(Exception e) {
super(e);
}
public ExcelException(String message, Exception e) {
super(message, e);
}
public ExcelException(String message) {
super(message);
}
}
package cn.runsa.crmapp.base.excel.support;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
import cn.runsa.crmapp.base.excel.core.Converter;
import cn.runsa.crmapp.base.excel.core.ConverterRegistry;
import cn.runsa.crmapp.base.excel.core.ExcelCol;
import cn.runsa.crmapp.base.excel.core.ExcelDataHandler;
import cn.runsa.crmapp.base.excel.core.ExcelErrorProcessor;
import cn.runsa.crmapp.base.excel.core.ExcelResult;
import cn.runsa.crmapp.base.excel.core.ExcelSchema;
import cn.runsa.crmapp.base.excel.core.SheetContentsHandler;
import cn.runsa.crmapp.base.excel.exception.ExcelException;
/**
* @author Stephen
*/
public class DefaultSheetContentsHandler implements SheetContentsHandler,ConverterRegistry{
//类型转换
private static GeneralConvertService convertService = new GeneralConvertService();
//处理获取的数据
private ExcelDataHandler dataHandler;
private volatile boolean isHead = true;
private volatile boolean isError = false;
private volatile boolean isRowError = false; //废弃,直接用current.keySet().containsAll(requiredCols)
private volatile String errMsg;
private Map<String,String> errMsgMap = new HashMap<String,String>();
private volatile int totalRow = 0; //总行数
// private volatile int errorRow = 0; //错误行数
//全部列 废弃,用schema.getColumns()获取 ,同时为了和headSchema做区别 2016-05-16
// private volatile List<ExcelCol> thead; //excel的表头,从db中获取
//sheet页的code,以此code,就可以推算出需要插入的表和存储过程
//eg: code 为user,则插入的表为user_excel,存储过程为: pro_user_excel(写法待定,但是肯定可以推导出) 废弃
//private String sheetCode; //废弃 ,用schema.getCode() 代替 -- 2016-05-16
//从db中获取的excel表结构.可能会和真实的excel不一致,因为有的列不是必填的
private ExcelSchema schema;
private Map<String, ExcelCol> headSchema; //从excel中获取的表头,和db中获取的表头不一定对应
private final Set<String> requiredCols = new HashSet<String>();
//当前行数据
private Map<String, Object> current;
//页中行数据
private final List<Map<String, Object>> rows ;
//页中行数据
private final List<Map<String, Object>> errRows= new ArrayList<Map<String, Object>>();
ExcelErrorProcessor errorProcessor;
//不知道原来id有什么用,准备作为group用,算了,自己定义一个吧
// private final String id = UUID.randomUUID().toString().replaceAll("-", "");
private final String groupId = (new SimpleDateFormat("yyyyMMddHHmmssSSS")).format(new Date())+ (new Random()).nextInt(9);
//zwj 引入了ExcelSchema
// public DefaultSheetContentsHandler(ExcelDataHandler dataHandler,List<ExcelCol> header,String sheetCode) {
// this.dataHandler = dataHandler;
// this.thead = header;
// this.sheetCode = sheetCode;
// rows = new ArrayList<Map<String, Object>>(dataHandler.getSizeOneTime());
// }
public DefaultSheetContentsHandler(ExcelDataHandler dataHandler,ExcelSchema schema) {
this.dataHandler = dataHandler;
// this.thead = schema.getColumns(); 已废弃
// sheetCode = schema.getCode(); 已废弃
this.schema = schema;
rows = new ArrayList<Map<String, Object>>(dataHandler.getSizeOneTime());
}
@Override
public void startRow(int rowNum) {
current = new HashMap<String, Object>();
isError = false;
isRowError = false;
errMsg = null;
if(!isHead){
totalRow++;
current.put("ROWNUM", ++rowNum);
}
}
/**
* 表头处理
* @throws ExcelException
*/
public void headRowHandle() throws ExcelException{
//列名
List<String> cols = new ArrayList<String>();
//必填列名
List<String> required = new ArrayList<String>();
for (ExcelCol col : schema.getColumns()){
cols.add(col.getName());
if (!col.isNullable()){
required.add(col.getName());
requiredCols.add(col.getCode());
}
}
Collection<Object> row = current.values();
//出现超出范围的列
if(!cols.containsAll(row)){
throw new ExcelException("表头超出范围");
}
//必填的列未出现
if(!row.containsAll(required)){
throw new ExcelException("缺少必填表头");
}
headSchema = new HashMap<String,ExcelCol>(current.size());
for(String ref:current.keySet()){
String title = current.get(ref).toString();
for(ExcelCol col :schema.getColumns()){
if(title.equals(col.getName())){
headSchema.put(ref, col);
break;
}
}
}
errorProcessor = new ExcelErrorProcessor(headSchema);
for (ExcelCol col : headSchema.values()){
Class<?> type = col.getType();
if(!List.class.equals(type)&&!String.class.equals(type)){
if(!convertService.canConvert(type)){
throw new ExcelException("缺少类型转换器");
}
}
}
}
@Override
public void endRow() throws ExcelException {
if(isHead){
headRowHandle();
isHead = false;
}else{
if(isRowError){
System.out.println("行格式错误");
errRows.add(current);
}else if(!current.keySet().containsAll(requiredCols)){
System.out.println("行缺少必填项");
errRows.add(current);
}else{
rows.add(current);
if(rows.size()==dataHandler.getSizeOneTime()){
dataHandler.dataFetched(schema, groupId, rows);
rows.clear();
}
}
}
}
@Override
public String cell(String cellReference, String formattedValue) {
String cellAbsoluteLocation = cellReference;
errMsg = "内容["+formattedValue+"]";
cellReference = cellReference.replaceAll("\\d", "");
if(isError){
return errMsg;
}
if(isHead){
//非空
if(StringUtils.isNotBlank(formattedValue)){
current.put(cellReference, formattedValue.trim());
}
}else{
ExcelCol col = headSchema.get(cellReference);
if(StringUtils.isNotBlank(formattedValue)){
//没有表头,直接跳过
if(col == null){
return errMsg;
}
Class<?> type = col.getType();
String source = null;
//第一阶段 格式化验证 开始
//最大长度
if(col.getMaxLength() !=null && formattedValue.length()>col.getMaxLength()){
errMsg += "不符合最大长度"+col.getMinLength()+"的要求;";
isError = true;
} else
//最小长度
if(col.getMinLength() !=null && formattedValue.length()<col.getMinLength()){
errMsg += "不符合最小长度"+col.getMinLength()+"的要求;";
isError = true;
}
//正则
if(col.getCompiledPattern()!=null){
if(!col.getCompiledPattern().matcher(formattedValue).matches()){
errMsg += "不符合格式规定;";
isError = true;
}
}
//第一阶段检测报告
if(isError){
// errMsgList.add(errMsg);
errMsgMap.put(cellAbsoluteLocation, errMsg);
isError = false;
isRowError = true;
return errMsg;
}
//第一阶段 格式化验证结束
//第二阶段,数据类型转换开始
if(String.class.equals(type)){
current.put(col.getCode(), formattedValue);
}else if(List.class.equals(type)){
//如果是内部枚举
Object val = col.getItems().get(formattedValue.trim());
//参数错误
if(val == null){
errMsg += "不在可选择范围内;";
isError = true;
}else{
current.put(col.getCode(), val);
}
}else if(Date.class.equals(type)&&(source=formattedValue.trim()).startsWith(DATE_PREFIX)){
Date val = new Date(Long.parseLong(source.substring(DATE_PREFIX.length())));
current.put(col.getCode(), val);
}else{
try{
Object val = convertService.convert(formattedValue, type);
if(val == null){
isError = true;
}else{
current.put(col.getCode(),val);
}
}catch(Exception e){
e.printStackTrace();
isError = true;
errMsg += e.getMessage();
}
}
}
// else{
// if(!col.isNullable()){
// errMsg += "不能为空;";
// }
// }
//第二阶段检测报告
if(isError){
errMsgMap.put(cellAbsoluteLocation, errMsg);
isError = false;
isRowError = true;
return errMsg;
}
//第二阶段,数据类型转换结束
}
return null;
}
@Override
/**
* zhangweijiang
* 1. 处理最后几行数据(最后几行数据需要手动调用dataFetched,因为没有达到DEFAULT_SIZE大小)
* 2. 把错误日志写入文件中
* 3. 调用存储过程
*/
public ExcelResult finish() {
if(rows.size()>0){
dataHandler.dataFetched(schema, groupId, rows);
rows.clear();
}
ExcelResult result = dataHandler.dataFinish(schema, headSchema, groupId);
result.setTotal(totalRow);
//需要包含ErrorProcessor处理的错误信息,如果没有报错就算了
if(result.getErrMsgMap()!=null && !result.getErrMsgMap().isEmpty() ){
errMsgMap.putAll(result.getErrMsgMap());
}
result.setErrMsgMap(errMsgMap);
result.setFileName(groupId+".xlsx"); //组号即为文件名称
Set<String> errRefSet = new HashSet<String>();
if(!errMsgMap.isEmpty()){
for(String celRef:errMsgMap.keySet()){
String rowRef = celRef.replaceAll("[a-zA-Z]","");
errRefSet.add(rowRef);
}
}
result.setError(errRefSet.size());
result.setErrRows(errRows);
errorProcessor.flushErrors2Excel(result,groupId);
return result;
}
@Override
public <T> void addConverter(Class<T> type, Converter<T> converter) {
convertService.converts.put(type, converter);
}
@Override
public void removeConvertible(Class<?> type) {
convertService.converts.remove(type);
}
public String getErrMsg() {
return errMsg;
}
}
package cn.runsa.crmapp.base.excel.support;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import cn.runsa.crmapp.base.excel.converter.BooleanConverter;
import cn.runsa.crmapp.base.excel.converter.DateConverter;
import cn.runsa.crmapp.base.excel.converter.NumberConverter;
import cn.runsa.crmapp.base.excel.core.ConvertService;
import cn.runsa.crmapp.base.excel.core.Converter;
/**
* @author Stephen
*/
public class GeneralConvertService implements ConvertService{
protected final Map<Class<?>,Converter<?>> converts;
{
converts = new ConcurrentHashMap<Class<?>,Converter<?>>();
converts.put(Boolean.class, new BooleanConverter());
converts.put(Date.class, new DateConverter());
converts.put(Byte.class, new NumberConverter<Byte>(Byte.class));
converts.put(Short.class, new NumberConverter<Short>(Short.class));
converts.put(Integer.class, new NumberConverter<Integer>(Integer.class));
converts.put(Long.class, new NumberConverter<Long>(Long.class));
converts.put(Float.class, new NumberConverter<Float>(Float.class));
converts.put(Double.class, new NumberConverter<Double>(Double.class));
converts.put(BigDecimal.class, new NumberConverter<BigDecimal>(BigDecimal.class));
converts.put(BigInteger.class, new NumberConverter<BigInteger>(BigInteger.class));
}
@Override
public boolean canConvert(Class<?> targetType) {
return converts.containsKey(targetType);
}
@Override
public <T> T convert(String source, Class<T> targetType) {
@SuppressWarnings("unchecked")
Converter<T> converter = (Converter<T>) converts.get(targetType);
return converter.convert(source);
}
}
package cn.runsa.crmapp.base.extendsion.spring;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.web.context.support.XmlWebApplicationContext;
/**
* @author Stephen
* 修改beanfactory的默认实现
*/
public class CustomXmlWebApplicationContext extends XmlWebApplicationContext{
@Override
protected DefaultListableBeanFactory createBeanFactory() {
return new MultipleImplementsBeanFactory(getInternalParentBeanFactory());
}
}
package cn.runsa.crmapp.base.extendsion.spring;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import cn.runsa.crmapp.base.Constants;
/**
* @author Stephen
* 多种实现选择注入的beanFactory
*/
public class MultipleImplementsBeanFactory extends DefaultListableBeanFactory{
public MultipleImplementsBeanFactory() {
super();
}
public MultipleImplementsBeanFactory(BeanFactory parentBeanFactory) {
super(parentBeanFactory);
}
/**
* 约定:系统外实现,包名包含open.***
*/
@Override
protected String determinePrimaryCandidate(Map<String, Object> candidateBeans, Class<?> requiredType) {
String prop = System.getProperty(Constants.CONSTANTS_CLASS_IMPL_PROFILE);
//允许多个profile
String [] profiles = null;
if(StringUtils.isBlank(prop)){
profiles = new String []{Constants.CONSTANTS_CLASS_IMPL_SYSTEM};
}else{
prop = prop.trim();
profiles = prop.split(",");
}
String beanName = null;
Map<String, Object> beans = new HashMap<String,Object>();
for (Map.Entry<String, Object> entry : candidateBeans.entrySet()) {
//取到包名
String pkgName = entry.getValue().getClass().getPackage().getName();
for(String profile : profiles){
//系统
if(Constants.CONSTANTS_CLASS_IMPL_SYSTEM.equals(profile)){
if(pkgName.indexOf(".open.") == -1){
beanName = entry.getKey();
beans.put(beanName, entry.getValue());
}
}else{
if(pkgName.indexOf(".open."+profile) != -1){
beanName = entry.getKey();
beans.put(beanName, entry.getValue());
}
}
}
}
if(beans.size() == 0){
throw new NoSuchBeanDefinitionException(requiredType);
}else if(beans.size() == 1){
return beanName;
}else{
return super.determinePrimaryCandidate(beans, requiredType);
}
}
}
package cn.runsa.crmapp.base.fs;
/**
* 文件系统
* @author Stephen
*
*/
public interface FileSystem {
}
package cn.runsa.crmapp.base.http;
/**
* Http post 数据格式
* @author Stephen
*
*/
public enum HttpDataType {
FORM,
XML,
JSON
}
package cn.runsa.crmapp.base.http;
/**
* Http post 数据格式
*
* @author Stephen
*
*/
public enum HttpMethodType {
GET, POST, PUT
}
package cn.runsa.crmapp.base.http;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.fileupload.util.Streams;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import cn.runsa.crmapp.base.http.exception.HttpDataFormatException;
import cn.runsa.crmapp.base.http.exception.HttpDataTypeNotSupportException;
import cn.runsa.crmapp.base.http.exception.HttpResponseException;
import cn.runsa.crmapp.base.utils.JsonUtils;
import cn.runsa.crmapp.base.utils.XmlUtils;
public class ResponseHandler {
@SuppressWarnings("unchecked")
public static <T> T handle(final CloseableHttpResponse response, Class<T> clz)
throws HttpResponseException, HttpDataFormatException {
final StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() != HttpStatus.SC_OK) {
IOUtils.closeQuietly(response);
throw new HttpResponseException("http code :"
+ statusLine.getStatusCode());
} else {
HttpEntity entity = response.getEntity();
String type =null;
try{
type = entity.getContentType().getValue().toLowerCase();
}catch(Exception e){
}
InputStream in = null;
try {
in = entity.getContent();
String result = IOUtils.toString(in, "UTF-8");
if(clz.equals(String.class)){
return (T) result;
}
if (type.startsWith("application/json")) {
return JsonUtils.jsonToBean(result, clz);
} else if (type.startsWith("text/xml")||type.startsWith("application/xml")) {
return XmlUtils.xmlToBean(result, clz);
}else{
throw new HttpDataTypeNotSupportException(type+" not support");
}
} catch (Exception e) {
throw new HttpDataFormatException("", e);
}finally{
IOUtils.closeQuietly(in);
// IOUtils.closeQuietly(response);
}
}
}
public static void downLoadFile(final CloseableHttpResponse response, File file) throws HttpResponseException{
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() != HttpStatus.SC_OK) {
IOUtils.closeQuietly(response);
throw new HttpResponseException("http code :"
+ statusLine.getStatusCode());
} else {
HttpEntity entity = response.getEntity();
InputStream in =null;
OutputStream out = null;
try {
in = entity.getContent();
out = new FileOutputStream(file);
Streams.copy(in, out, true);
} catch (IOException e) {
throw new HttpResponseException("File copy error.",e);
}finally{
IOUtils.closeQuietly(out);
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(response);
}
}
}
}
package cn.runsa.crmapp.base.http;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import org.apache.http.conn.ssl.TrustStrategy;
/**
* Https 安全策略:信任所有
* @author Stephen
*
*/
public class TrustAllStrategy implements TrustStrategy{
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
}
package cn.runsa.crmapp.base.http.exception;
/**
* http 请求数据格式化异常
* @author Stephen
*
*/
public class HttpDataFormatException extends HttpException {
private static final long serialVersionUID = -446888465201916329L;
public HttpDataFormatException() {
super();
}
public HttpDataFormatException(String message, Throwable cause) {
super(message, cause);
}
public HttpDataFormatException(String message) {
super(message);
}
}
package cn.runsa.crmapp.base.http.exception;
/**
* http 处理响应数据异常
* @author Stephen
*
*/
public class HttpDataProcessException extends Exception {
private static final long serialVersionUID = -446888465233339L;
public HttpDataProcessException() {
super();
}
public HttpDataProcessException(final String message) {
super(message);
}
public HttpDataProcessException(final String message, final Throwable cause) {
super(message,cause);
}
}
package cn.runsa.crmapp.base.http.exception;
/**
* http 请求数据格式不支持
* @author Stephen
*
*/
public class HttpDataTypeNotSupportException extends HttpException {
private static final long serialVersionUID = -4677744724999454091L;
public HttpDataTypeNotSupportException() {
super();
}
public HttpDataTypeNotSupportException(final String message) {
super(message);
}
public HttpDataTypeNotSupportException(final String message, final Throwable cause) {
super(message,cause);
}
}
package cn.runsa.crmapp.base.http.exception;
/**
* Http 请求异常
*
* @author Stephen
*
*/
public class HttpException extends Exception {
private static final long serialVersionUID = 2781235741466577292L;
public HttpException() {
super();
}
public HttpException(final String message) {
super(message);
}
public HttpException(final String message, final Throwable cause) {
super(message);
initCause(cause);
}
}
package cn.runsa.crmapp.base.http.exception;
/**
* http 响应时异常
*
* @author Stephen
*
*/
public class HttpResponseException extends HttpException {
private static final long serialVersionUID = -2960376536362148494L;
public HttpResponseException() {
super();
}
public HttpResponseException(String message, Throwable cause) {
super(message, cause);
}
public HttpResponseException(String message) {
super(message);
}
}
package cn.runsa.crmapp.base.mq;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import com.alibaba.fastjson.JSON;
import com.google.common.io.ByteStreams;
public class BaseService {
public final static <T> T getOject(String jsonString, Class<T> cls) {
T t = null;
try {
t = JSON.parseObject(jsonString, cls);
} catch (Exception e) {
// TODO: handle exception
}
return t;
}
public final static String unGZIP(byte[] body) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayInputStream in = new ByteArrayInputStream(body);
try {
GZIPInputStream gunzip = new GZIPInputStream(in);
ByteStreams.copy(gunzip, out);
return out.toString();
} catch (IOException e1) {
e1.printStackTrace();
} finally {
try {
in.close();
out.close();
} catch (IOException e) {
}
}
return null;
}
public final static byte[] GZIP(byte[] body) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
GZIPOutputStream gunzip = new GZIPOutputStream(out);
gunzip.write(body);
gunzip.close();
return out.toByteArray();
} catch (IOException e1) {
e1.printStackTrace();
} finally {
try {
out.close();
} catch (IOException e) {
}
}
return null;
}
}
package cn.runsa.crmapp.base.mq;
/**
* @author Stephen
* 延迟消息
*/
public class DelayMessage extends MqMessage{
private static final long serialVersionUID = -6406648480333023838L;
private int delay ;
public int getDelay() {
return delay;
}
public void setDelay(int delay) {
this.delay = delay;
}
}
package cn.runsa.crmapp.base.mq;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import cn.runsa.crmapp.base.Constants;
import com.google.common.base.Throwables;
/**
* 阿里云凭证
* @author Stephen
*/
public final class MNSCredential {
private static Properties credential = null;
private static final Logger log = LoggerFactory.getLogger(MNSCredential.class);
static{
try {
credential = PropertiesLoaderUtils.loadProperties(new FileSystemResource(System.getProperty(Constants.CONSTANTS_SERVER_CONFIG_PATH)));
} catch (Exception e) {
log.error("mns auth config error,with config file classpath:/mq/aliyun-mns.properties",e);
Throwables.propagate(e);
}
}
public static String getMNSAccountEndpoint() {
return credential.getProperty("mns.accountendpoint");
}
public static String getMNSAccessKeyId() {
return credential.getProperty("mns.accesskeyid");
}
public static String getMNSAccessKeySecret() {
return credential.getProperty("mns.accesskeysecret");
}
public static String getMNSSecurityToken() {
return credential.getProperty("mns.securitytoken");
}
}
package cn.runsa.crmapp.base.mq;
/**
* @author Stephen
*
* 消息监听
*/
public interface MessageListener <T> {
void onMessage(T t) throws Exception;
}
package cn.runsa.crmapp.base.mq;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.ClassPathResource;
import cn.runsa.crmapp.base.mq.entity.MqClient;
import cn.runsa.crmapp.base.mq.entity.MqQueue;
import cn.runsa.crmapp.base.utils.XmlUtils;
import com.aliyun.mns.client.CloudAccount;
import com.aliyun.mns.client.CloudQueue;
import com.aliyun.mns.client.MNSClient;
public class MessageReceiver implements InitializingBean, DisposableBean{
private static MNSClient client = null;
private static Map<String,CloudQueue> queues = new ConcurrentHashMap<String,CloudQueue>();
private static final Logger log = LoggerFactory.getLogger(MessageReceiver.class);
private static ExecutorService es ;
private static CloudQueue getQueue(String name){
CloudQueue queue = queues.get(name);
if(queue==null){
queue = client.getQueueRef(name);
queues.put(name, queue);
}
return queue;
}
@Override
public void destroy() throws Exception {
es.shutdown();
es.awaitTermination(60, TimeUnit.SECONDS);
if(client!=null)
client.close();
queues.clear();
}
@Override
public void afterPropertiesSet() throws Exception {
CloudAccount account = new CloudAccount(
MNSCredential.getMNSAccessKeyId(),
MNSCredential.getMNSAccessKeySecret(),
MNSCredential.getMNSAccountEndpoint());
client = account.getMNSClient();
es = Executors.newCachedThreadPool();
init();
}
private void init(){
MqClient clt = null;
try {
clt = XmlUtils.xmlToBean(new ClassPathResource("mq/aliyun-mns.xml").getInputStream(), MqClient.class);
} catch (IOException e) {
log.error("mns init error", e);
}
List<MqQueue> list = clt.getQueues();
if(list != null && list.size() >0){
for(final MqQueue queue:list){
for(int i=1;i<=queue.getThread();i++){
final int index = i;
QueueReceiver reveiver = new QueueReceiver(index, getQueue(queue.getName()), queue.getListener());
es.execute(reveiver);
}
}
}
}
}
package cn.runsa.crmapp.base.mq;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import cn.runsa.crmapp.base.mq.QueueNameAlias.InnerQueue;
import cn.runsa.crmapp.base.mq.entity.MqClient;
import cn.runsa.crmapp.base.utils.XmlUtils;
import com.aliyun.mns.client.CloudAccount;
import com.aliyun.mns.client.CloudQueue;
import com.aliyun.mns.client.CloudTopic;
import com.aliyun.mns.client.MNSClient;
import com.aliyun.mns.model.Message;
/**
* 发送mq消息
* @author Stephen
*/
public final class MessageSender implements InitializingBean, DisposableBean{
private static final Logger log = LoggerFactory.getLogger(MessageSender.class);
private static MNSClient client = null;
private static Map<String,CloudQueue> queues = new ConcurrentHashMap<String,CloudQueue>();
private static Map<String,CloudTopic> topics = new ConcurrentHashMap<String,CloudTopic>();
private static Map<InnerQueue,String> queueAlias = new HashMap<InnerQueue,String>();
@Override
public void destroy() throws Exception {
if(client!=null)
client.close();
queues.clear();
topics.clear();
}
@Override
public void afterPropertiesSet() throws Exception {
MqClient clt = null;
try {
clt = XmlUtils.xmlToBean(new ClassPathResource("mq/aliyun-mns.xml").getInputStream(), MqClient.class);
} catch (IOException e) {
log.error("mns init error", e);
throw new RuntimeException(e);
}
if(clt.getQueueAlias()!=null&&clt.getQueueAlias().size()>0){
for(QueueNameAlias a : clt.getQueueAlias()){
queueAlias.put(a.getInner(), a.getQueueName());
}
}
CloudAccount account = new CloudAccount(
MNSCredential.getMNSAccessKeyId(),
MNSCredential.getMNSAccessKeySecret(),
MNSCredential.getMNSAccountEndpoint());
client = account.getMNSClient();
}
private static CloudQueue getQueue(String name){
CloudQueue queue = queues.get(name);
if(queue==null){
queue = client.getQueueRef(name);
queues.put(name, queue);
}
return queue;
}
/*private static CloudTopic getTopic(String name){
CloudTopic topic = topics.get(name);
if(topic==null){
synchronized (topic) {
if (topic == null){
topic = client.getTopicRef(name);
topics.put(name, topic);
}
}
}
return topic;
}*/
public static void putMessage(String queueName,MqMessage message){
CloudQueue queue = getQueue(queueName);
Message msg = new Message();
msg.setMessageBody(BaseService.GZIP(message.getMessageBody()));
msg.setPriority(message.getPriority());
queue.putMessage(msg);
}
public static void putMessage(InnerQueue alias,MqMessage message){
if(checkQueueAlias(alias)){
putMessage(queueAlias.get(alias), message);
}
}
public static void putMessage(String queueName,List<MqMessage> messages){
CloudQueue queue = getQueue(queueName);
List<Message> list = new ArrayList<Message>(messages.size());
for(MqMessage message:messages){
Message msg = new Message();
msg.setMessageBody(BaseService.GZIP(message.getMessageBody()));
msg.setPriority(message.getPriority());
list.add(msg);
}
queue.batchPutMessage(list);
}
public static void putMessage(InnerQueue alias,List<MqMessage> messages){
if(checkQueueAlias(alias)){
putMessage(queueAlias.get(alias), messages);
}
}
public static void putDelayMessage(InnerQueue alias,DelayMessage message){
if(checkQueueAlias(alias)){
putDelayMessage(queueAlias.get(alias), message);
}
}
public static void putDelayMessage(String queueName,DelayMessage message){
CloudQueue queue = getQueue(queueName);
Message msg = new Message();
msg.setMessageBody(BaseService.GZIP(message.getMessageBody()));
msg.setPriority(message.getPriority());
msg.setDelaySeconds(message.getDelay());
queue.putMessage(msg);
}
public static void putDelayMessage(String queueName,List<DelayMessage> messages){
CloudQueue queue = getQueue(queueName);
List<Message> list = new ArrayList<Message>(messages.size());
for(DelayMessage message:messages){
Message msg = new Message();
msg.setMessageBody(BaseService.GZIP(message.getMessageBody()));
msg.setPriority(message.getPriority());
msg.setDelaySeconds(message.getDelay());
list.add(msg);
}
queue.batchPutMessage(list);
}
public static void putDelayMessage(InnerQueue alias,List<DelayMessage> messages){
if(checkQueueAlias(alias)){
putDelayMessage(queueAlias.get(alias), messages);
}
}
private static boolean checkQueueAlias(InnerQueue alias){
if(!queueAlias.containsKey(alias)){
if(log.isDebugEnabled()){
log.debug("alias with no queue name defined,queue alias :"+alias);
}
return false;
}
return true;
}
}
package cn.runsa.crmapp.base.mq;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
/**
* @author Stephen
* mq消息
*/
public class MqMessage implements Serializable{
private static final long serialVersionUID = -2913291790464662305L;
private static final String ENCODING = "UTF-8";
private static final int DEFAULT_PRIORITY = 8;
private int priority ;
private byte[] messageBody ;
public MqMessage(){
super();
}
public MqMessage(byte[] messageBody) {
this(DEFAULT_PRIORITY,messageBody);
}
public MqMessage(int priority, byte[] messageBody) {
super();
this.priority = priority;
this.messageBody = messageBody;
}
public MqMessage(String messageBody) {
this(DEFAULT_PRIORITY,messageBody);
}
public MqMessage(int priority, String messageBody) {
super();
this.priority = priority;
setStringMessageBody(messageBody);
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public byte[] getMessageBody() {
return messageBody;
}
public void setMessageBody(byte[] messageBody) {
this.messageBody = messageBody;
}
public void setStringMessageBody(String messageBody){
byte[] body = null;
try {
body = messageBody.getBytes(ENCODING);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("Not support encoding");
}
setMessageBody(body);
}
}
package cn.runsa.crmapp.base.mq;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
/**
* @author Stephen
* queue 别名
*/
@XStreamAlias("alias")
public class QueueNameAlias {
public static enum InnerQueue {
events
}
@XStreamAsAttribute
private InnerQueue inner;
@XStreamAlias("ref")
@XStreamAsAttribute
private String queueName;
public InnerQueue getInner() {
return inner;
}
public void setInner(InnerQueue inner) {
this.inner = inner;
}
public String getQueueName() {
return queueName;
}
public void setQueueName(String queueName) {
this.queueName = queueName;
}
}
package cn.runsa.crmapp.base.mq;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.runsa.crmapp.base.mq.entity.MqListener;
import cn.runsa.crmapp.base.utils.SpringUtils;
import com.alibaba.fastjson.JSON;
import com.aliyun.mns.client.CloudQueue;
import com.aliyun.mns.model.Message;
/**
* @author Stephen
*/
public class QueueReceiver implements Runnable{
public static final int WAIT_SECONDS = 30;
public static final int BEAT_TEST_SECONDS = 10;
public static final int MAX_MSG_RETRY_TIMES = 5;
private static final Map<String, Object> sLockObjMap = new HashMap<String, Object>();
private static Map<String, Integer> sPollingMap = new ConcurrentHashMap<String, Integer>();
private static final Logger log = LoggerFactory.getLogger(MessageReceiver.class);
private Object lockObj;
private String queueName;
private CloudQueue queue;
private int workerId;
@SuppressWarnings("rawtypes")
private MessageListener msgListener;
@SuppressWarnings("rawtypes")
private Class msgType;
public QueueReceiver(int worker, CloudQueue queue,MqListener listener) {
workerId = worker;
this.queue = queue;
queueName = queue.getAttributes().getQueueName();
try {
msgListener = (MessageListener<?>) SpringUtils.getBean(Class.forName(listener.getLisClass()));
msgType = Class.forName(listener.getMsgType());
} catch (ClassNotFoundException e) {
log.error("queue receiver init error",e);
throw new IllegalArgumentException(e);
}
// 初始化lock对象
synchronized (sLockObjMap) {
lockObj = sLockObjMap.get(queueName);
if (lockObj == null) {
lockObj = new Object();
sLockObjMap.put(queueName, lockObj);
}
}
}
public boolean setPolling() {
// 进入轮询状态
synchronized (lockObj) {
Integer ret = sPollingMap.get(queueName);
if (ret == null || ret == -1) {
sPollingMap.put(queueName, workerId);
System.out.println(workerId+"轮询");
return true;
} else if (ret == workerId) {
return true;
} else {
return false;
}
}
}
public void clearPolling() {
// 退出轮询状态
synchronized (lockObj) {
sPollingMap.put(queueName, -1);
lockObj.notifyAll();
System.out.println("唤醒");
}
}
public Message receiveMessage() {
// 轮询标志
boolean polling = false;
while (true) {
synchronized (lockObj) {
Integer p = sPollingMap.get(queueName);
// 轮询中,则等待
if (p != null && p >= 0) {
if (p != workerId) {
try {
polling = false;
System.out.println(workerId+"歇会儿");
lockObj.wait();
} catch (InterruptedException e) {
log.error("MessageReceiver Interrupted! QueueName is " + queueName, e);
return null;
}
} else {
//只有异常或者断网情况下进入这里
try {
Thread.sleep(WAIT_SECONDS * 1000);
} catch (InterruptedException e) {
// undo
}
}
}
}
Message message;
// 未处于轮询状态
if (!polling) {
try {
message = queue.popMessage();
if (message == null) {
polling = true;
continue;
}
} catch (Exception e) {
log.error("Exception Happened when popMessage: " + e);
polling = true;
continue;
}
} else {
// 尝试进入轮询状态
if (!setPolling()) {
continue;
}
try {
do {
message = queue.popMessage(WAIT_SECONDS);
} while (message == null);
clearPolling();
} catch (Exception e) {
log.error("Exception Happened when popMessage: " + e);
polling = false;
continue;
}
}
return message;
}
}
@SuppressWarnings("unchecked")
@Override
public void run() {
while (true) {
Message msg = receiveMessage();
if(msg != null){
String data = BaseService.unGZIP(msg.getMessageBodyAsBytes());
try{
if(String.class.equals(msgType)){
msgListener.onMessage(data);
}else{
msgListener.onMessage(JSON.parseObject(data, msgType));
}
queue.deleteMessage(msg.getReceiptHandle());
}catch(Exception e){
log.error("Exception Happened when process msg: " + e);
if(msg.getDequeueCount()>=MAX_MSG_RETRY_TIMES){
queue.deleteMessage(msg.getReceiptHandle());
}
}
}
}
}
}
package cn.runsa.crmapp.base.mq;
import com.aliyun.mns.model.Message;
import cn.runsa.crmapp.base.mq.exception.MqExcepiton;
public interface ReceiverService {
public void execute(Message message) throws MqExcepiton;
}
package cn.runsa.crmapp.base.mq;
/**
* @author Stephen
*/
public class TopicReceiver {
}
package cn.runsa.crmapp.base.mq.entity;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
import cn.runsa.crmapp.base.mq.QueueNameAlias;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* @author Stephen
*/
@XmlRootElement
@XStreamAlias("client")
public class MqClient {
private List<MqQueue> queues;
private List<MqTopic> topics;
private List<QueueNameAlias> queueAlias;
public List<MqQueue> getQueues() {
return queues;
}
public void setQueues(List<MqQueue> queues) {
this.queues = queues;
}
public List<MqTopic> getTopics() {
return topics;
}
public void setTopics(List<MqTopic> topics) {
this.topics = topics;
}
public List<QueueNameAlias> getQueueAlias() {
return queueAlias;
}
public void setQueueAlias(List<QueueNameAlias> queueAlias) {
this.queueAlias = queueAlias;
}
}
package cn.runsa.crmapp.base.mq.entity;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
/**
* @author Stephen
*/
@XStreamAlias("listener")
public class MqListener {
@XStreamAlias("class")
@XStreamAsAttribute
private String lisClass;
@XStreamAsAttribute
private String msgType;
public String getLisClass() {
return lisClass;
}
public void setLisClass(String lisClass) {
this.lisClass = lisClass;
}
public String getMsgType() {
return msgType;
}
public void setMsgType(String msgType) {
this.msgType = msgType;
}
}
package cn.runsa.crmapp.base.mq.entity;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
/**
* @author Stephen
*/
@XStreamAlias("queue")
public class MqQueue {
@XStreamAsAttribute
private String name;
@XStreamAsAttribute
private int thread = 1;
@XStreamAsAttribute
private String compress = "gzip";
private MqListener listener;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getThread() {
return thread;
}
public void setThread(int thread) {
this.thread = thread;
}
public String getCompress() {
return compress;
}
public void setCompress(String compress) {
this.compress = compress;
}
public MqListener getListener() {
return listener;
}
public void setListener(MqListener listener) {
this.listener = listener;
}
}
package cn.runsa.crmapp.base.mq.entity;
import java.util.List;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
/**
* @author Stephen
*/
@XStreamAlias("topic")
public class MqTopic {
@XStreamImplicit
private List<MqListener> listeners;
public List<MqListener> getListeners() {
return listeners;
}
public void setListeners(List<MqListener> listeners) {
this.listeners = listeners;
}
}
package cn.runsa.crmapp.base.mq.exception;
public class MqExcepiton extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 220632093115334702L;
public MqExcepiton() {
super();
}
public MqExcepiton(String message, Throwable cause) {
super(message, cause);
}
public MqExcepiton(String message) {
super(message);
}
public MqExcepiton(Throwable cause) {
super(cause);
}
}
package cn.runsa.crmapp.base.redis;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.data.redis.core.RedisTemplate;
import cn.runsa.crmapp.base.utils.JsonUtils;
public class Redis {
private static final Logger log = LogManager.getLogger(Redis.class);
@SuppressWarnings("rawtypes")
private static RedisTemplate redis;
@SuppressWarnings("rawtypes")
public RedisTemplate getRedis() {
return redis;
}
@SuppressWarnings("rawtypes")
public void setRedis(RedisTemplate redis) {
Redis.redis = redis;
}
public static String getString(String key) {
String str = null;
Object val = redis.opsForValue().get(key);
if(val!=null){
str = val.toString();
}
return str;
}
public static <T> T getObject(String key, Class<T> cls) {
T t = null;
try {
String str = getString(key);
if(str!=null)
t = JsonUtils.jsonToBean(str, cls);
} catch (Exception e) {
log.error("redis get object value error", e);
}
return t;
}
@SuppressWarnings("unchecked")
public static boolean setString(String key, String value) {
redis.opsForValue().set(key, value);
return true;
}
public static boolean setObject(String key, Object value) {
setString(key, JsonUtils.beanToJson(value));
return true;
}
@SuppressWarnings("unchecked")
public static boolean setString(String key, String value, int timeout) {
redis.opsForValue().set(key, value,timeout,TimeUnit.SECONDS);
return true;
}
public static boolean setObject(String key, Object value, int timeout) {
setString(key, JsonUtils.beanToJson(value), timeout);
return true;
}
}
package cn.runsa.crmapp.base.redis;
public class RedisMQ {
}
package cn.runsa.crmapp.base.redis.exception;
public class RedisException extends Exception{
private static final long serialVersionUID = 6585013822092454600L;
public RedisException() {
super();
// TODO Auto-generated constructor stub
}
public RedisException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public RedisException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
}
package cn.runsa.crmapp.base.sms;
import com.alibaba.fastjson.JSON;
public abstract class AbstractHttpSmsSender implements SmsSender {
private Protocol protocol;
public AbstractHttpSmsSender() {
super();
}
@Override
public void setProtocol(Protocol protocol) {
this.protocol = protocol;
}
public Protocol getProtocol() {
return protocol;
}
public <T> T getOject(String jsonString, Class<T> cls) {
T t = null;
try {
t = JSON.parseObject(jsonString, cls);
} catch (Exception e) {
// TODO: handle exception
}
return t;
}
public String toJsonString(Object T) {
return JSON.toJSONString(T);
}
}
\ No newline at end of file
package cn.runsa.crmapp.base.sms;
public interface Protocol {
String sendMsg(String url, String data);
}
package cn.runsa.crmapp.base.sms;
import java.io.Serializable;
/**
* 短信消息
* @author Stephen
*
*/
public class SmsMessage implements Serializable{
private static final long serialVersionUID = 8620596786869937729L;
/**
* 手机号,可以为多个,中间以英文逗号分隔
*/
private String mobile;
/**
* 内容编码为UTF8
*/
private String content;
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
package cn.runsa.crmapp.base.sms;
public class SmsProvider {
}
package cn.runsa.crmapp.base.sms;
import cn.runsa.crmapp.base.sms.exception.SmsException;
/**
* 发短信
*
* @author Stephen
*
*/
public interface SmsSender {
void sendSMS(SmsMessage msg) throws SmsException;
/**
* 发送验证码,返回有效时间,单位为秒
*
* @param mobile
* 手机号
* @param sequence
* 序列号(可以为场景字符串或者任意字符)
* @param code
* 验证码
* @return
* @throws SmsException
*/
int sendCaptcha(String mobile, String sequence, String code) throws SmsException;
/**
* 查询余额,返回剩余条数
*
* @return
* @throws SmsException
*/
long remainCheck() throws SmsException;
/**
* 设置处理协议
*
* @param protocol
*/
void setProtocol(Protocol protocol);
}
package cn.runsa.crmapp.base.sms.exception;
/**
* 短信发送异常,不包括发送短信但没有接收到,意思就是 并不是端到端
* @author Stephen
*
*/
public class SmsException extends Exception{
private static final long serialVersionUID = 7587790473289942572L;
public SmsException() {
super();
}
public SmsException(String message, Throwable cause) {
super(message, cause);
}
public SmsException(String message) {
super(message);
}
public SmsException(Throwable cause) {
super(cause);
}
}
package cn.runsa.crmapp.base.utils;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;
import cn.runsa.crmapp.base.event.BusinessEvent;
/**
* @author Stephen
*/
public class BeanUtils extends org.springframework.beans.BeanUtils{
private static final Logger log = LoggerFactory.getLogger(BeanUtils.class);
/**
* 归并相同类型的两个对象
* @param target
* @param source
* @param strategy
* @param ignores
*/
public static void merge(Object target, Object source, MergeStrategy strategy,String [] ignores) {
Assert.notNull(source, "Source must not be null");
Assert.notNull(target, "Target must not be null");
if(!target.getClass().equals(source.getClass())){
throw new IllegalArgumentException("source and target must be same class type");
}
PropertyDescriptor[] targetPds = getPropertyDescriptors(target.getClass());
byte code = strategy.code;
Set<String> allIgnore = new HashSet<String>();
if(ignores!=null){
for(String ignore:ignores){
allIgnore.add(ignore);
}
}
for (PropertyDescriptor targetPd : targetPds) {
String name = targetPd.getName();
if("class".equals(name)){
continue;
}
Method read = targetPd.getReadMethod();
if(read==null){
allIgnore.add(name);
}else{
//target not null
if((code&0x01)!=0){
try{
if(read.invoke(target)!=null){
allIgnore.add(name);
}
}catch(Exception e){
log.error("get properties error with name "+name, e);
allIgnore.add(name);
}
}
//source not null
if((code&0x10)!=0){
try{
if(read.invoke(source)==null){
allIgnore.add(name);
}
}catch(Exception e){
log.error("get properties error with name "+name, e);
allIgnore.add(name);
}
}
}
}
ignores = new String [allIgnore.size()];
allIgnore.toArray(ignores);
copyProperties(source, target, ignores);
}
public static enum MergeStrategy{
targetEmpty((byte)1),sourceNotEmpty((byte)2),targetEmptyAndSourceNotEmpty((byte)3);
private byte code;
private MergeStrategy(byte code){
this.code = code;
}
public byte getCode(){
return code;
}
}
public static void main(String[] args) {
merge(new BusinessEvent(), new BusinessEvent(),MergeStrategy.targetEmpty, null);
}
}
package cn.runsa.crmapp.base.utils;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
public class ExportExcel {
public static int exportDoc(String destFile, String fileContent) {
try {
StringBuffer sb = new StringBuffer();
sb.append("<html><head></head><body><div>sssssssssssss" + fileContent + "</div></body></html>");
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(sb.toString().getBytes("UTF-8"));
POIFSFileSystem fileSystem = new POIFSFileSystem();
DirectoryEntry directory = fileSystem.getRoot();
directory.createDocument("WordDocument", byteArrayInputStream);
FileOutputStream fileOutputStream = new FileOutputStream(destFile);
fileSystem.writeFilesystem(fileOutputStream);
byteArrayInputStream.close();
fileOutputStream.close();
return 1;
} catch (IOException e) {
return 0;
}
}
}
package cn.runsa.crmapp.base.utils;
import com.google.common.base.Strings;
public class FourBytesCharEscapeUtils {
public static String escape(String str){
if(Strings.isNullOrEmpty(str)){
return str;
}else{
byte[] conbyte = str.getBytes();
for (int i = 0; i < conbyte.length; i++) {
//四字节,替换为? ?
if ((conbyte[i] & 0xF8) == 0xF0) {
for (int j = 0; j < 4; j+=2) {
conbyte[i+j]=0x3f;
}
for (int j = 1; j < 4; j+=2) {
conbyte[i+j]=0x20;
}
i += 3;
}
}
str = new String(conbyte);
return str;
}
}
}
package cn.runsa.crmapp.base.utils;
import com.alibaba.fastjson.JSON;
public class JsonUtils {
/**
* 将java对象转换成json字符串
*
* @param obj
* 准备转换的对象
* @return json字符串
* @throws Exception
*/
public static String beanToJson(Object obj) {
return JSON.toJSONString(obj);
//.replaceAll("\\\\", "").replaceAll("\"", "\\\"")
}
/**
* 将json字符串转换成java对象
*
* @param json
* 准备转换的json字符串
* @param cls
* 准备转换的类
* @return
* @throws Exception
*/
public static <T> T jsonToBean(String json, Class<T> cls) {
return JSON.parseObject(json, cls);
}
}
package cn.runsa.crmapp.base.utils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
/**
* @author Stephen
*/
@Component
public final class SpringUtils implements BeanFactoryPostProcessor {
private static ConfigurableListableBeanFactory beanFactory;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
SpringUtils.beanFactory = beanFactory;
}
/**
* 获取对象
*/
public static Object getBean(String name) {
return beanFactory.getBean(name);
}
/**
* 获取对象
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name, Class<T> clz) {
T result = (T) beanFactory.getBean(name);
return result;
}
/**
* 获取对象
*/
public static <T> T getBean(Class<T> clz) {
T result = (T) beanFactory.getBean(clz);
return result;
}
/**
* 判断是否包含对象
*/
public static boolean containsBean(String name) {
return beanFactory.containsBean(name);
}
/**
* 创建对象到spring context
*/
@SuppressWarnings("unchecked")
public static <T> T createBean(Class<T> clz) {
T result = (T) beanFactory.createBean(clz, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
return result;
}
/**
* 删除对象
*/
public static void destroyBean(String beanName) {
beanFactory.destroyScopedBean(beanName);
}
}
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.