├── README.md └── sb-commons ├── .gitignore ├── common-basedb ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── chinasb │ └── common │ └── basedb │ ├── ExcelResourceReader.java │ ├── Getter.java │ ├── GetterBuilder.java │ ├── IndexBuilder.java │ ├── InitializeBean.java │ ├── JsonResourceReader.java │ ├── ResourceAdapter.java │ ├── ResourceListener.java │ ├── ResourceReader.java │ ├── ResourceReloadEvent.java │ ├── ResourceService.java │ ├── ResourceServiceImpl.java │ ├── Storage.java │ └── annotation │ ├── Id.java │ ├── Index.java │ └── Resource.java ├── common-db ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── chinasb │ └── common │ └── db │ ├── cache │ ├── CachedService.java │ ├── CachedServiceAdpter.java │ └── impl │ │ └── CacheServiceImpl.java │ ├── dao │ ├── CommonDao.java │ └── impl │ │ └── CommonDaoImpl.java │ ├── dialect │ └── MySQLDialect.java │ ├── executor │ ├── DbCallback.java │ ├── DbService.java │ └── impl │ │ └── DbServiceImpl.java │ └── model │ ├── BaseModel.java │ └── CacheObject.java ├── common-jreloader ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── chinasb │ └── common │ └── jreloader │ ├── JReloader.java │ ├── Reloadable.java │ ├── compiler │ ├── Compiler.java │ └── support │ │ ├── AbstractCompiler.java │ │ └── JdkCompiler.java │ └── watcher │ ├── FolderWatcher.java │ └── WatchEventListener.java ├── common-lock ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── chinasb │ └── common │ └── lock │ ├── ChainLock.java │ ├── IEntity.java │ ├── LockUtils.java │ ├── ObjectLock.java │ └── ObjectLockHolder.java ├── common-rhino ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── chinasb │ └── common │ └── rhino │ ├── MapWarperFactory.java │ ├── NativeJavaMap.java │ ├── Rhino.java │ └── RhinoHelper.java ├── common-socket ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── chinasb │ └── common │ └── socket │ ├── SessionManager.java │ ├── codec │ ├── CodecContext.java │ ├── DecoderState.java │ ├── MessageType.java │ ├── ObjectCodec.java │ ├── RequestDecoder.java │ └── ResponseEncoder.java │ ├── config │ └── ServerConfig.java │ ├── context │ └── ApplicationContext.java │ ├── controller │ ├── Dispatcher.java │ └── impl │ │ └── DispatcherImpl.java │ ├── firewall │ ├── ByteAttackFilter.java │ ├── ClientType.java │ ├── CmdAttackFilter.java │ ├── Firewall.java │ └── FloodRecord.java │ ├── handler │ ├── AbstractCommandHandler.java │ ├── CommandHandler.java │ ├── CommandResolver.java │ ├── CommandWorkerContainer.java │ ├── CommandWorkerMeta.java │ ├── DefaultCommandResolver.java │ ├── DefaultCommandWorkMeta.java │ ├── DefaultCommandWorkerContainer.java │ ├── Interceptor │ │ └── Interceptor.java │ ├── ServerInboundHandler.java │ ├── ServerOutboundHandler.java │ ├── annotation │ │ ├── CommandInterceptor.java │ │ ├── CommandMapping.java │ │ ├── CommandWorker.java │ │ └── interceptors │ │ │ ├── ClassInterceptors.java │ │ │ └── MethodInterceptors.java │ └── configuration │ │ ├── CommandInterceptorConfig.java │ │ └── CommandWorkerConfig.java │ ├── message │ ├── Message.java │ ├── Request.java │ └── Response.java │ ├── push │ ├── PushContext.java │ ├── PushType.java │ └── Pusher.java │ └── type │ ├── ResponseCode.java │ └── SessionType.java ├── common-threadpool ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── chinasb │ └── common │ └── threadpool │ ├── Task.java │ ├── ordered │ ├── AbstractDelayTask.java │ ├── AbstractTask.java │ ├── OrderedTaskQueue.java │ ├── OrderedTaskQueueExecutor.java │ └── TaskQueue.java │ └── ringbuffer │ ├── BasePublisher.java │ ├── DisruptorExecutor.java │ ├── Event.java │ ├── EventConsumer.java │ ├── EventPublisher.java │ └── RingBufferTaskQueue.java ├── common-utility ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── org │ └── chinasb │ └── common │ └── utility │ ├── BeanHelper.java │ ├── CollectionUtils.java │ ├── ConcurrentHashSet.java │ ├── Constants.java │ ├── EnumUtils.java │ ├── GenericsUtils.java │ ├── HashUtils.java │ ├── HexDumpUtils.java │ ├── JSONUtils.java │ ├── LRUCache.java │ ├── NamedDaemonThreadFactory.java │ ├── NamedThreadFactory.java │ ├── NetUtils.java │ ├── NumberUtils.java │ ├── PackageUtils.java │ ├── RandomUtils.java │ ├── ReflectionHelper.java │ ├── Splitable.java │ ├── StopWatch.java │ ├── StringUtils.java │ ├── ThreadPoolUtils.java │ ├── TimeUtils.java │ ├── Tools.java │ ├── URL.java │ ├── UUIDUtils.java │ └── holders │ ├── BigDecimalHolder.java │ ├── BigIntegerHolder.java │ ├── BooleanHolder.java │ ├── BooleanWrapperHolder.java │ ├── ByteArrayHolder.java │ ├── ByteHolder.java │ ├── ByteWrapperHolder.java │ ├── DoubleHolder.java │ ├── DoubleWrapperHolder.java │ ├── FloatHolder.java │ ├── FloatWrapperHolder.java │ ├── Holder.java │ ├── IntHolder.java │ ├── IntegerWrapperHolder.java │ ├── LongHolder.java │ ├── LongWrapperHolder.java │ ├── ObjectHolder.java │ ├── ShortHolder.java │ ├── ShortWrapperHolder.java │ └── StringHolder.java ├── pom.xml └── sb-commons ├── .gitignore └── pom.xml /README.md: -------------------------------------------------------------------------------- 1 | sb-framework 2 | ============ 3 | 4 | sb-framework for game server 5 | -------------------------------------------------------------------------------- /sb-commons/.gitignore: -------------------------------------------------------------------------------- 1 | /.project 2 | /.settings 3 | -------------------------------------------------------------------------------- /sb-commons/common-basedb/.gitignore: -------------------------------------------------------------------------------- 1 | /.settings 2 | /.project 3 | /target 4 | /.classpath 5 | -------------------------------------------------------------------------------- /sb-commons/common-basedb/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | sb-commons-parent 8 | org.chinasb 9 | 0.0.1-SNAPSHOT 10 | 11 | common-basedb 12 | jar 13 | ${project.artifactId} 14 | The base db module of sb-commons project 15 | 16 | true 17 | 18 | 19 | 20 | org.slf4j 21 | slf4j-api 22 | 23 | 24 | ${project.groupId} 25 | common-rhino 26 | ${project.version} 27 | 28 | 29 | ${project.groupId} 30 | common-utility 31 | ${project.version} 32 | 33 | 34 | org.springframework 35 | spring-context 36 | 37 | 38 | com.google.guava 39 | guava 40 | 41 | 42 | org.apache.poi 43 | poi-ooxml 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /sb-commons/common-basedb/src/main/java/org/chinasb/common/basedb/Getter.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.basedb; 2 | 3 | /** 4 | * 取值器接口 5 | * 6 | * @author zhujuan 7 | */ 8 | public interface Getter { 9 | /** 10 | * 获取对象值 11 | * 12 | * @param value 静态资源实例 13 | * @return {@link Object} 对象相关值 14 | */ 15 | Object getValue(Object value); 16 | } 17 | -------------------------------------------------------------------------------- /sb-commons/common-basedb/src/main/java/org/chinasb/common/basedb/GetterBuilder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.basedb; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Method; 5 | 6 | import org.chinasb.common.basedb.annotation.Id; 7 | import org.chinasb.common.utility.ReflectionHelper; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.slf4j.helpers.FormattingTuple; 11 | import org.slf4j.helpers.MessageFormatter; 12 | import org.springframework.util.ReflectionUtils; 13 | 14 | /** 15 | * 取值构建器 16 | * 17 | * @author zhujuan 18 | */ 19 | public class GetterBuilder { 20 | private static final Logger LOGGER = LoggerFactory.getLogger(GetterBuilder.class); 21 | 22 | /** 23 | * 创建指定资源类的ID取值器 24 | * 25 | * @param clz 资源类 26 | * @return 27 | */ 28 | public static Getter createIdGetter(Class clz) { 29 | Field[] fields = ReflectionHelper.getDeclaredFieldsWith(clz, Id.class); 30 | if (fields == null) { 31 | FormattingTuple message = MessageFormatter.format("类 [{}] 缺少唯一标识声明", clz); 32 | LOGGER.error(message.getMessage()); 33 | throw new RuntimeException(message.getMessage()); 34 | } 35 | if (fields.length > 1) { 36 | FormattingTuple message = MessageFormatter.format("类 [{}] 有多个唯一标识声明", clz); 37 | LOGGER.error(message.getMessage()); 38 | throw new RuntimeException(message.getMessage()); 39 | } 40 | return new FieldGetter(fields[0]); 41 | } 42 | 43 | /** 44 | * 属性取值器 45 | * 46 | * @author zhujuan 47 | */ 48 | private static class FieldGetter implements Getter { 49 | private final Field field; 50 | 51 | public FieldGetter(Field field) { 52 | ReflectionUtils.makeAccessible(field); 53 | this.field = field; 54 | } 55 | 56 | @Override 57 | public Object getValue(Object object) { 58 | Object value = null; 59 | try { 60 | value = field.get(object); 61 | } catch (Exception e) { 62 | FormattingTuple message = MessageFormatter.format("标识符属性访问异常", e); 63 | GetterBuilder.LOGGER.error(message.getMessage()); 64 | throw new RuntimeException(message.getMessage()); 65 | } 66 | return value; 67 | } 68 | } 69 | 70 | /** 71 | * 方法取值器 72 | * 73 | * @author zhujuan 74 | */ 75 | @SuppressWarnings("unused") 76 | private static class MethodGetter implements Getter { 77 | private final Method method; 78 | 79 | public MethodGetter(Method method) { 80 | ReflectionUtils.makeAccessible(method); 81 | this.method = method; 82 | } 83 | 84 | @Override 85 | public Object getValue(Object object) { 86 | Object value = null; 87 | try { 88 | value = method.invoke(object, new Object[0]); 89 | } catch (Exception e) { 90 | FormattingTuple message = MessageFormatter.format("标识方法访问异常", e); 91 | GetterBuilder.LOGGER.error(message.getMessage()); 92 | throw new RuntimeException(message.getMessage()); 93 | } 94 | return value; 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /sb-commons/common-basedb/src/main/java/org/chinasb/common/basedb/IndexBuilder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.basedb; 2 | 3 | import java.lang.reflect.Field; 4 | import java.util.ArrayList; 5 | import java.util.Collections; 6 | import java.util.Comparator; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import org.chinasb.common.basedb.ResourceServiceImpl.KeyBuilder; 12 | import org.chinasb.common.basedb.annotation.Index; 13 | import org.chinasb.common.rhino.RhinoHelper; 14 | import org.chinasb.common.utility.BeanHelper; 15 | import org.chinasb.common.utility.ReflectionHelper; 16 | 17 | import com.google.common.base.Objects; 18 | 19 | /** 20 | * 索引构建器 21 | * 22 | * @author zhujuan 23 | */ 24 | public class IndexBuilder { 25 | 26 | /** 27 | * 创建索引访问器 28 | * 29 | * @param clazz 类对象 30 | * @return 31 | */ 32 | public static Map createIndexVisitors(Class clazz) { 33 | Field[] fields = ReflectionHelper.getDeclaredFieldsWith(clazz, Index.class); 34 | Map indexMap = new HashMap(); 35 | for (Field field : fields) { 36 | Index index = (Index) field.getAnnotation(Index.class); 37 | if (index != null) { 38 | IndexVisitor indexVisitor = (IndexVisitor) indexMap.get(index.name()); 39 | if (indexVisitor == null) { 40 | indexVisitor = new IndexVisitor(index.name()); 41 | indexMap.put(index.name(), indexVisitor); 42 | } 43 | indexVisitor.attachField(new Field[] {field}); 44 | } 45 | } 46 | if (!indexMap.isEmpty()) { 47 | for (IndexVisitor indexVisitor : indexMap.values()) { 48 | List fieldList = indexVisitor.getFields(); 49 | if ((fieldList != null) && (fieldList.size() > 1)) { 50 | Collections.sort(fieldList, new Comparator() { 51 | @Override 52 | public int compare(Field f1, Field f2) { 53 | Index index1 = (Index) f1.getAnnotation(Index.class); 54 | Index index2 = (Index) f2.getAnnotation(Index.class); 55 | return index1.order() < index2.order() ? -1 : 1; 56 | } 57 | }); 58 | } 59 | } 60 | } 61 | return indexMap; 62 | } 63 | 64 | /** 65 | * 索引访问者 66 | * 67 | * @author zhujuan 68 | */ 69 | public static class IndexVisitor { 70 | private final String name; 71 | private final List fields = new ArrayList(); 72 | private final List expressions = new ArrayList(); 73 | 74 | public IndexVisitor(String indexName) { 75 | name = indexName; 76 | } 77 | 78 | /** 79 | * 附加索引字段 80 | * 81 | * @param fieldList 82 | */ 83 | public void attachField(Field... fieldList) { 84 | if (fieldList != null && fieldList.length > 0) { 85 | for (Field field : fieldList) { 86 | fields.add(field); 87 | Index index = field.getAnnotation(Index.class); 88 | if (index != null && index.expression() != null 89 | && index.expression().trim().length() > 0) { 90 | expressions.add(index.expression().trim()); 91 | } 92 | } 93 | } 94 | } 95 | 96 | /** 97 | * 获取索引访问者名称 98 | * 99 | * @return 100 | */ 101 | public String getName() { 102 | return name; 103 | } 104 | 105 | /** 106 | * 获取索引字段集合 107 | * 108 | * @return 109 | */ 110 | public List getFields() { 111 | return fields; 112 | } 113 | 114 | /** 115 | * 获取索引字段值域的组合键值(类名&索引名称#索引值1^索引值2) 116 | * 117 | * @param obj 118 | * @return 119 | */ 120 | public String getIndexKey(Object obj) { 121 | if (obj != null) { 122 | Object[] fieldValues = null; 123 | if (fields != null && !fields.isEmpty()) { 124 | fieldValues = new String[fields.size()]; 125 | for (int i = 0; i < fields.size(); i++) { 126 | Field field = (Field) fields.get(i); 127 | field.setAccessible(true); 128 | Object fieldValue = ReflectionHelper.getField(field, obj); 129 | if (fieldValue != null) { 130 | fieldValues[i] = String.valueOf(fieldValue); 131 | } else { 132 | fieldValues[i] = ""; 133 | } 134 | } 135 | } 136 | return KeyBuilder.buildIndexKey(obj.getClass(), name, fieldValues); 137 | } 138 | return null; 139 | } 140 | 141 | /** 142 | * 判断对象是否可以索引{非空对象和表达式正确} 143 | * 144 | * @param obj 145 | * @return true-可以索引 false-不可以索引 146 | */ 147 | @SuppressWarnings("unchecked") 148 | public boolean indexable(Object obj) { 149 | if (obj != null) { 150 | if (expressions != null && !expressions.isEmpty()) { 151 | Map ctx = BeanHelper.buildMap(obj); 152 | for (String expression : expressions) { 153 | if (!RhinoHelper.invoke(expression, ctx, Boolean.class)) { 154 | return false; 155 | } 156 | } 157 | } 158 | return true; 159 | } 160 | return false; 161 | } 162 | 163 | @Override 164 | public int hashCode() { 165 | return name != null ? name.hashCode() : 0; 166 | } 167 | 168 | @Override 169 | public boolean equals(Object o) { 170 | if (o == this) { 171 | return true; 172 | } 173 | if (!(o instanceof IndexVisitor)) { 174 | return false; 175 | } 176 | IndexVisitor rhs = (IndexVisitor) o; 177 | return Objects.equal(name, rhs.name); 178 | } 179 | } 180 | 181 | } 182 | -------------------------------------------------------------------------------- /sb-commons/common-basedb/src/main/java/org/chinasb/common/basedb/InitializeBean.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.basedb; 2 | 3 | /** 4 | * 初始化基础数据接口 5 | * 6 | * @author zhujuan 7 | */ 8 | public interface InitializeBean { 9 | /** 10 | * 在属性被设置完后(索引数据前)做一些处理 11 | */ 12 | public void afterPropertiesSet(); 13 | } 14 | -------------------------------------------------------------------------------- /sb-commons/common-basedb/src/main/java/org/chinasb/common/basedb/JsonResourceReader.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.basedb; 2 | 3 | import java.io.InputStream; 4 | import java.util.ArrayList; 5 | import java.util.Iterator; 6 | import java.util.List; 7 | 8 | import org.chinasb.common.utility.JSONUtils; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.stereotype.Component; 12 | 13 | import com.fasterxml.jackson.databind.JavaType; 14 | import com.fasterxml.jackson.databind.type.TypeFactory; 15 | 16 | /** 17 | * JSON 资源读取器 18 | * 19 | * @author zhujuan 20 | */ 21 | @Component("jsonResourceReader") 22 | public class JsonResourceReader implements ResourceReader { 23 | private static final Logger LOGGER = LoggerFactory.getLogger(JsonResourceReader.class); 24 | 25 | private static final TypeFactory typeFactory = TypeFactory.defaultInstance(); 26 | 27 | @Override 28 | public String getFormat() { 29 | return "json"; 30 | } 31 | 32 | @Override 33 | public Iterator read(InputStream input, Class clazz) { 34 | try { 35 | JavaType type = typeFactory.constructCollectionType(ArrayList.class, clazz); 36 | List list = JSONUtils.getObjectMapper().readValue(input, type); 37 | return list.iterator(); 38 | } catch (Exception e) { 39 | LOGGER.error("JsonReader读取基础数据:[{}] 文件异常!", clazz, e); 40 | throw new RuntimeException(e); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /sb-commons/common-basedb/src/main/java/org/chinasb/common/basedb/ResourceAdapter.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.basedb; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | 10 | /** 11 | * 资源适配器 12 | * 13 | * @author zhujuan 14 | */ 15 | public abstract class ResourceAdapter implements ResourceListener { 16 | 17 | @Autowired 18 | protected ResourceService resourceService; 19 | 20 | @Override 21 | public void onBasedbReload() { 22 | this.initialize(); 23 | } 24 | 25 | /** 26 | * 获取基础数据列表 27 | * 28 | * @param clazz 基础数据类对象 29 | * @param idList 基础数据ID列表 30 | * @return 31 | */ 32 | protected List getFromIdList(Class clazz, Collection idList) { 33 | if (idList != null && !idList.isEmpty()) { 34 | List entityList = new ArrayList(); 35 | for (Object id : idList) { 36 | T entity = resourceService.get(id, clazz); 37 | if (entity != null) { 38 | entityList.add(entity); 39 | } 40 | } 41 | return Collections.unmodifiableList(entityList); 42 | } 43 | return Collections.emptyList(); 44 | } 45 | 46 | /** 47 | * 初始化 48 | */ 49 | public abstract void initialize(); 50 | } 51 | -------------------------------------------------------------------------------- /sb-commons/common-basedb/src/main/java/org/chinasb/common/basedb/ResourceListener.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.basedb; 2 | 3 | /** 4 | * 资源监听器 5 | * 6 | * @author zhujuan 7 | */ 8 | public interface ResourceListener { 9 | /** 10 | * 当基础数据重载后调用 11 | */ 12 | public void onBasedbReload(); 13 | } 14 | -------------------------------------------------------------------------------- /sb-commons/common-basedb/src/main/java/org/chinasb/common/basedb/ResourceReader.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.basedb; 2 | 3 | import java.io.InputStream; 4 | import java.util.Iterator; 5 | 6 | /** 7 | * 资源读取器 8 | * 9 | * @author zhujuan 10 | */ 11 | public interface ResourceReader { 12 | /** 13 | * 获取资源格式 14 | * 15 | * @return 16 | */ 17 | public String getFormat(); 18 | 19 | /** 20 | * 从输入流读取资源实例 21 | * 22 | * @param 23 | * @param input 输入流 24 | * @param clz 资源实例类型 25 | * @return 26 | */ 27 | public Iterator read(InputStream paramInputStream, Class paramClass); 28 | } 29 | -------------------------------------------------------------------------------- /sb-commons/common-basedb/src/main/java/org/chinasb/common/basedb/ResourceReloadEvent.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.basedb; 2 | 3 | import org.springframework.context.ApplicationContext; 4 | import org.springframework.context.event.ApplicationContextEvent; 5 | 6 | /** 7 | * 资源重载事件 8 | * 9 | * @author zhujuan 10 | */ 11 | public class ResourceReloadEvent extends ApplicationContextEvent { 12 | 13 | private static final long serialVersionUID = 1L; 14 | 15 | public ResourceReloadEvent(ApplicationContext source) { 16 | super(source); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /sb-commons/common-basedb/src/main/java/org/chinasb/common/basedb/ResourceService.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.basedb; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 基础数据服务接口 7 | * 8 | * @author zhujuan 9 | */ 10 | public interface ResourceService { 11 | /** 12 | * 通过id获取基础数据 13 | * 14 | * @param id 主健 15 | * @param clazz 基础数据类对象 16 | * @return T 17 | */ 18 | T get(Object id, Class clazz); 19 | 20 | /** 21 | * 通过索引键、值获取基础数据列表 22 | * 23 | * @param indexName 索引名称 24 | * @param clazz 基础数据类对象 25 | * @param indexValues 索引值(顺序对应 {@link Index#order}) 26 | * @return List 27 | */ 28 | List listByIndex(String indexName, Class clazz, Object... indexValues); 29 | 30 | /** 31 | * 通过索引获取基础数据ID列表 32 | * 33 | * @param indexName 索引名称 34 | * @param clazz 基础数据类对象 35 | * @param pk 基础数据主键类对象 36 | * @param indexValues 索引值 37 | * @return {@link List} 返回对应的索引ID列表 38 | */ 39 | List listIdByIndex(String indexName, Class clazz, Class pk, 40 | Object... indexValues); 41 | 42 | /** 43 | * 通过索引键、值获取基础数据的唯一记录 44 | * 45 | * @param indexName 索引名称 46 | * @param clazz 基础数据类对象 47 | * @param indexValues 索引值(顺序对应 {@link Index#order}) 48 | * @return T 49 | */ 50 | T getByUnique(String indexName, Class clazz, Object... indexValues); 51 | 52 | /** 53 | * 获取全部基础数据列表 54 | * 55 | * @param clazz 基础数据类对象 56 | * @return List 57 | */ 58 | List listAll(Class clazz); 59 | 60 | /** 61 | * 添加基础数据ID索引 62 | * 63 | * @param indexName 索引名称 64 | * @param id 基础数据ID 65 | * @param clazz 基础数据类对象 66 | */ 67 | void addToIndex(String indexName, Object id, Class clazz); 68 | 69 | /** 70 | * 添加基础数据ID索引 71 | * 72 | * @param indexName 索引名称 73 | * @param id 基础数据ID 74 | * @param clazz 基础数据类对象 75 | * @param indexValues 索引值 76 | */ 77 | void addToIndex(String indexName, Object id, Class clazz, Object... indexValues); 78 | 79 | /** 80 | * 重新加载全部基础数据 81 | */ 82 | void reloadAll(); 83 | } 84 | -------------------------------------------------------------------------------- /sb-commons/common-basedb/src/main/java/org/chinasb/common/basedb/annotation/Id.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.basedb.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Id属性/方法注释 10 | * 11 | * @author zhujuan 12 | * 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target({ElementType.FIELD, ElementType.METHOD}) 16 | public @interface Id { 17 | } 18 | -------------------------------------------------------------------------------- /sb-commons/common-basedb/src/main/java/org/chinasb/common/basedb/annotation/Index.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.basedb.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * 静态资源数据索引声明 10 | * 11 | * @author zhujuan 12 | * 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target({ElementType.FIELD, ElementType.METHOD}) 16 | public @interface Index { 17 | /** 索引名,同一资源的索引名必须唯一 */ 18 | String name(); 19 | 20 | /** 排序 */ 21 | int order() default 0; 22 | 23 | /** 表达式 */ 24 | String expression() default ""; 25 | } 26 | -------------------------------------------------------------------------------- /sb-commons/common-basedb/src/main/java/org/chinasb/common/basedb/annotation/Resource.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.basedb.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * 资源数据对象声明 10 | * 11 | * @author zhujuan 12 | * 13 | */ 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Target({ElementType.TYPE}) 16 | public @interface Resource { 17 | /** 资源文件后缀 */ 18 | String suffix() default "json"; 19 | 20 | /** 资源文件类型 */ 21 | String type() default "json"; 22 | } 23 | -------------------------------------------------------------------------------- /sb-commons/common-db/.gitignore: -------------------------------------------------------------------------------- 1 | /.settings 2 | /.project 3 | /target 4 | /.classpath 5 | -------------------------------------------------------------------------------- /sb-commons/common-db/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | sb-commons-parent 8 | org.chinasb 9 | 0.0.1-SNAPSHOT 10 | 11 | common-db 12 | jar 13 | ${project.artifactId} 14 | The db module of sb-commons project 15 | 16 | true 17 | 18 | 19 | 20 | org.slf4j 21 | slf4j-api 22 | 23 | 24 | ${project.groupId} 25 | common-lock 26 | ${project.version} 27 | 28 | 29 | ${project.groupId} 30 | common-threadpool 31 | ${project.version} 32 | 33 | 34 | ${project.groupId} 35 | common-utility 36 | ${project.version} 37 | 38 | 39 | org.springframework 40 | spring-context 41 | 42 | 43 | org.springframework 44 | spring-orm 45 | 46 | 47 | com.google.guava 48 | guava 49 | 50 | 51 | org.hibernate 52 | hibernate-core 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /sb-commons/common-db/src/main/java/org/chinasb/common/db/cache/CachedService.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.db.cache; 2 | 3 | /** 4 | * 缓存服务接口 5 | * 6 | * @author zhujuan 7 | */ 8 | public interface CachedService { 9 | /** 10 | * 添加实体缓存 11 | * 12 | * @param key 13 | * @param value 14 | * @return 15 | */ 16 | Object put2EntityCache(String key, Object value); 17 | 18 | /** 19 | * 添加实体缓存 20 | * 21 | * @param key 22 | * @param value 23 | * @param timeToLive 存活时间 24 | * @return 25 | */ 26 | Object put2EntityCache(String key, Object value, long timeToLive); 27 | 28 | /** 29 | * 获取实体缓存 30 | * 31 | * @param key 32 | * @return 33 | */ 34 | Object getFromEntityCache(String key); 35 | 36 | /** 37 | * 移除实体缓存 38 | * 39 | * @param key 40 | */ 41 | void removeFromEntityCache(String key); 42 | 43 | /** 44 | * 添加通用缓存(覆盖模式) 45 | * 46 | * @param key 47 | * @param value 48 | */ 49 | void put2CommonCache(String key, Object value); 50 | 51 | /** 52 | * 添加通用缓存(覆盖模式) 53 | * 54 | * @param key 55 | * @param value 56 | * @param timeToLive 存活时间 57 | */ 58 | void put2CommonCache(String key, Object value, long timeToLive); 59 | 60 | /** 61 | * 添加通用缓存(put-if-absent模式) 62 | * 63 | * @param key 64 | * @param value 65 | * @return 66 | */ 67 | Object put2CommonCacheIfAbsent(String key, Object value); 68 | 69 | /** 70 | * 添加通用缓存(put-if-absent模式) 71 | * 72 | * @param key 73 | * @param value 74 | * @param timeToLive 存活时间 75 | * @return 76 | */ 77 | Object put2CommonCacheIfAbsent(String key, Object value, long timeToLive); 78 | 79 | /** 80 | * 添加通用缓存(覆盖模式) 81 | * 82 | * @param hashKey 83 | * @param subKey 84 | * @param value 85 | */ 86 | void put2CommonHashCache(String hashKey, String subKey, Object value); 87 | 88 | /** 89 | * 添加通用缓存(覆盖模式) 90 | * 91 | * @param hashKey 92 | * @param subKey 93 | * @param value 94 | * @param timeToLive 存活时间 95 | */ 96 | void put2CommonHashCache(String hashKey, String subKey, Object value, long timeToLive); 97 | 98 | /** 99 | * 添加通用缓存(put-if-absent模式) 100 | * 101 | * @param hashKey 102 | * @param subKey 103 | * @param value 104 | * @return 105 | */ 106 | Object put2CommonHashCacheIfAbsent(String hashKey, String subKey, Object value); 107 | 108 | /** 109 | * 添加通用缓存(put-if-absent模式) 110 | * 111 | * @param hashKey 112 | * @param subKey 113 | * @param value 114 | * @param timeToLive 存活时间 115 | * @return 116 | */ 117 | Object put2CommonHashCacheIfAbsent(String hashKey, String subKey, Object value, long timeToLive); 118 | 119 | /** 120 | * 获取通用缓存 121 | * 122 | * @param key 123 | * @return 124 | */ 125 | Object getFromCommonCache(String key); 126 | 127 | /** 128 | * 获取通用缓存 129 | * 130 | * @param hashKey 131 | * @param subKey 132 | * @return 133 | */ 134 | Object getFromCommonHashCache(String hashKey, String subKey); 135 | 136 | /** 137 | * 移除通用缓存 138 | * 139 | * @param key 140 | */ 141 | void removeFromCommonCache(String key); 142 | 143 | /** 144 | * 移除通用缓存 145 | * 146 | * @param hashKey 147 | * @param subKey 148 | */ 149 | void removeFromCommonHashCache(String hashKey, String subKey); 150 | 151 | /** 152 | * 清除过期缓存 153 | * 154 | * @param clearInValidCommonCache 是否清除通用缓存标志{true:清除, false:忽略} 155 | */ 156 | void clearInValidateCacheObject(boolean clearInValidCommonCache); 157 | } 158 | -------------------------------------------------------------------------------- /sb-commons/common-db/src/main/java/org/chinasb/common/db/dao/CommonDao.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.db.dao; 2 | 3 | import java.io.Serializable; 4 | import java.util.Collection; 5 | 6 | import org.chinasb.common.db.model.BaseModel; 7 | import org.hibernate.criterion.DetachedCriteria; 8 | 9 | /** 10 | * 通用DAO 11 | * 12 | * @author zhujuan 13 | */ 14 | public interface CommonDao { 15 | /** 16 | * 获取实体 17 | * 18 | * @param id 19 | * @param entityClazz 20 | * @return {@link T} 21 | */ 22 | T get(Serializable id, Class entityClazz); 23 | 24 | /** 25 | * 保存实体 26 | * 27 | * @param entities 28 | */ 29 | @SuppressWarnings("unchecked") 30 | , PK extends Comparable & Serializable> void save(T... entities); 31 | 32 | /** 33 | * 更新实体 34 | * 35 | * @param entities 36 | */ 37 | @SuppressWarnings("unchecked") 38 | void update(T... entities); 39 | 40 | /** 41 | * 更新实体集合 42 | * 43 | * @param entities 44 | */ 45 | void update(Collection entities); 46 | 47 | /** 48 | * 删除实体 49 | * 50 | * @param id 51 | * @param entityClazz 52 | */ 53 | void delete(Serializable id, Class entityClazz); 54 | 55 | /** 56 | * 离线查询 57 | * 58 | * @param detachedCriteria 59 | * @return {@link T} 60 | */ 61 | T execute(DetachedCriteria detachedCriteria); 62 | 63 | /** 64 | * 原生SQL执行 65 | * 66 | * @param sql 67 | * @return {@link T} 68 | */ 69 | int execute(String sql); 70 | 71 | /** 72 | * 原生SQL查询 73 | * 74 | * @param sql 75 | * @return {@link T} 76 | */ 77 | T query(String sql); 78 | 79 | /** 80 | * 原生SQL查询 81 | * 82 | * @param sql 83 | * @param entityClazz 84 | * @return {@link T} 85 | */ 86 | T query(String sql, Class entityClazz); 87 | } 88 | -------------------------------------------------------------------------------- /sb-commons/common-db/src/main/java/org/chinasb/common/db/dialect/MySQLDialect.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.db.dialect; 2 | 3 | import java.sql.Types; 4 | 5 | import org.hibernate.dialect.MySQL5InnoDBDialect; 6 | import org.hibernate.type.BinaryType; 7 | import org.hibernate.type.StringType; 8 | 9 | /** 10 | * 注册自定义类型, 增加MYSQL对Hibernate本地SQL查询结果集中返回 text,longtext,blob,longblob支持 11 | * 12 | * @author zhujuan 13 | * 14 | */ 15 | public class MySQLDialect extends MySQL5InnoDBDialect { 16 | 17 | public MySQLDialect() { 18 | super(); 19 | super.registerHibernateType(Types.LONGNVARCHAR, StringType.INSTANCE.getName()); 20 | super.registerHibernateType(Types.LONGVARCHAR, StringType.INSTANCE.getName()); 21 | super.registerHibernateType(Types.LONGVARBINARY, BinaryType.INSTANCE.getName()); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /sb-commons/common-db/src/main/java/org/chinasb/common/db/executor/DbCallback.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.db.executor; 2 | 3 | /** 4 | * 数据更新回调接口 5 | * 6 | * @author zhujuan 7 | */ 8 | public interface DbCallback { 9 | void doAfter(); 10 | } 11 | -------------------------------------------------------------------------------- /sb-commons/common-db/src/main/java/org/chinasb/common/db/executor/DbService.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.db.executor; 2 | 3 | import org.springframework.context.ApplicationListener; 4 | import org.springframework.context.event.ContextClosedEvent; 5 | 6 | /** 7 | * 数据库服务接口 8 | * 9 | * @author zhujuan 10 | */ 11 | public interface DbService extends ApplicationListener { 12 | /** 13 | * 数据库默认处理线程数量 14 | */ 15 | static final int DEFAULT_DB_THREADS = Runtime.getRuntime().availableProcessors(); 16 | 17 | /** 18 | * 提交实体到更新队列 19 | * 20 | * @param entities 21 | */ 22 | @SuppressWarnings("unchecked") 23 | void submitUpdate2Queue(T... entities); 24 | 25 | /** 26 | * 实时更新实体 27 | * 28 | * @param entities 29 | */ 30 | @SuppressWarnings("unchecked") 31 | void updateEntityIntime(T... entities); 32 | 33 | /** 34 | * 实时更新实体, 并回调处理更新 35 | * 36 | * @param callback 37 | * @param entities 38 | */ 39 | @SuppressWarnings("unchecked") 40 | void updateEntityIntime(DbCallback callback, T... entities); 41 | 42 | /** 43 | * 判断实体是否在更新队列中 44 | * 45 | * @param entity 46 | * @return 47 | */ 48 | boolean isInDbQueue(T entity); 49 | } 50 | -------------------------------------------------------------------------------- /sb-commons/common-db/src/main/java/org/chinasb/common/db/model/BaseModel.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.db.model; 2 | 3 | import java.io.Serializable; 4 | 5 | import org.chinasb.common.lock.IEntity; 6 | 7 | /** 8 | * 实体抽象基类 9 | * 10 | * @author zhujuan 11 | * 12 | * @param 13 | */ 14 | @SuppressWarnings("serial") 15 | public abstract class BaseModel & Serializable> implements IEntity, 16 | Serializable { 17 | 18 | /** 19 | * 获取实体ID 20 | */ 21 | public abstract PK getId(); 22 | 23 | /** 24 | * 设置实体ID 25 | */ 26 | public abstract void setId(PK id); 27 | 28 | @Override 29 | public String toString() { 30 | return getClass().getName() + "[" + getId() + "]"; 31 | } 32 | 33 | @SuppressWarnings("rawtypes") 34 | @Override 35 | public boolean equals(Object o) { 36 | if (o == this) { 37 | return true; 38 | } 39 | if (!(o instanceof BaseModel)) { 40 | return false; 41 | } 42 | if (o.getClass() != getClass()) { 43 | return false; 44 | } 45 | BaseModel rhs = (BaseModel) o; 46 | return (getId() != null) && (rhs.getId() != null) && (getId().equals(rhs.getId())); 47 | } 48 | 49 | @Override 50 | public int hashCode() { 51 | final int prime = 31; 52 | int result = super.hashCode(); 53 | result = prime * result + (getId() == null ? 0 : getId().hashCode()); 54 | return result; 55 | } 56 | 57 | /** 58 | * 获取实体标识 59 | */ 60 | public PK getIdentity() { 61 | return getId(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /sb-commons/common-db/src/main/java/org/chinasb/common/db/model/CacheObject.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.db.model; 2 | 3 | import org.chinasb.common.utility.Constants; 4 | 5 | /** 6 | * 缓存对象 7 | * 8 | * @author zhujuan 9 | */ 10 | public class CacheObject { 11 | /** 12 | * 缓存对象 13 | */ 14 | private Object value; 15 | /** 16 | * 存活时间 17 | */ 18 | private long ttl = 0L; 19 | /** 20 | * 创建时间 21 | */ 22 | private long createTime = System.currentTimeMillis(); 23 | /** 24 | * 过期时间 25 | */ 26 | private long expireTime = createTime + ttl; 27 | 28 | /** 29 | * 将普通对象转换为缓存对象 30 | * 31 | * @param value 普通对象 32 | * @return {@link CacheObject} 33 | */ 34 | public static CacheObject valueOf(Object value) { 35 | CacheObject cacheObject = new CacheObject(); 36 | cacheObject.value = value; 37 | cacheObject.ttl = Constants.ONE_DAY_MILLISECOND; 38 | cacheObject.createTime = System.currentTimeMillis(); 39 | cacheObject.expireTime = (cacheObject.createTime + cacheObject.ttl); 40 | return cacheObject; 41 | } 42 | 43 | /** 44 | * 将普通对象转换为缓存对象 45 | * 46 | * @param value 普通对象 47 | * @param timeToLive 存活时间 48 | * @return {@link CacheObject} 49 | */ 50 | public static CacheObject valueOf(Object value, long timeToLive) { 51 | CacheObject cacheObject = new CacheObject(); 52 | cacheObject.value = value; 53 | cacheObject.ttl = timeToLive; 54 | cacheObject.createTime = System.currentTimeMillis(); 55 | cacheObject.expireTime = (cacheObject.createTime + cacheObject.ttl); 56 | return cacheObject; 57 | } 58 | 59 | /** 60 | * 检查缓存对象的有效性 61 | * 62 | * @return true: 有效; false: 无效 63 | */ 64 | public boolean isValidate() { 65 | return expireTime >= System.currentTimeMillis(); 66 | } 67 | 68 | /** 69 | * 延长缓存对象的过期时间 70 | * 71 | * @param addExpireTime 72 | */ 73 | public void increaseExpireTime(int addExpireTime) { 74 | if (expireTime < (addExpireTime + System.currentTimeMillis())) { 75 | expireTime += addExpireTime; 76 | } 77 | } 78 | 79 | /** 80 | * 获取缓存的实体 81 | * 82 | * @return 83 | */ 84 | public Object getValue() { 85 | return value; 86 | } 87 | 88 | /** 89 | * 获取缓存的存活时间 90 | * 91 | * @return 92 | */ 93 | public long getTtl() { 94 | return ttl; 95 | } 96 | 97 | /** 98 | * 获取缓存的创建时间 99 | * 100 | * @return 101 | */ 102 | public long getCreateTime() { 103 | return createTime; 104 | } 105 | 106 | /** 107 | * 获取缓存的过期时间 108 | * 109 | * @return 110 | */ 111 | public long getExpireTime() { 112 | return expireTime; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /sb-commons/common-jreloader/.gitignore: -------------------------------------------------------------------------------- 1 | /.settings 2 | /.project 3 | /target 4 | /.classpath 5 | -------------------------------------------------------------------------------- /sb-commons/common-jreloader/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | sb-commons-parent 7 | org.chinasb 8 | 0.0.1-SNAPSHOT 9 | 10 | common-jreloader 11 | jar 12 | ${project.artifactId} 13 | The jreloader module of sb-commons project 14 | 15 | true 16 | 17 | 18 | 19 | ${project.groupId} 20 | common-threadpool 21 | ${project.version} 22 | 23 | 24 | org.slf4j 25 | slf4j-api 26 | 27 | 28 | commons-io 29 | commons-io 30 | 31 | 32 | org.springframework 33 | spring-context 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /sb-commons/common-jreloader/src/main/java/org/chinasb/common/jreloader/Reloadable.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.jreloader; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Reloadable. 10 | * 11 | * @author zhujuan 12 | */ 13 | @Target(ElementType.TYPE) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | public @interface Reloadable { 16 | 17 | int module(); 18 | 19 | String description() default ""; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /sb-commons/common-jreloader/src/main/java/org/chinasb/common/jreloader/compiler/Compiler.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.jreloader.compiler; 2 | 3 | /** 4 | * compiler. 5 | * 6 | * @author zhujuan 7 | */ 8 | public interface Compiler { 9 | 10 | /** 11 | * Compile java source code. 12 | * 13 | * @param code Java source code 14 | * @return Compiled class 15 | */ 16 | Class compile(String code); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /sb-commons/common-jreloader/src/main/java/org/chinasb/common/jreloader/compiler/support/AbstractCompiler.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.jreloader.compiler.support; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | import org.chinasb.common.jreloader.compiler.Compiler; 7 | 8 | /** 9 | * Abstract compiler. 10 | * 11 | * @author zhujuan 12 | */ 13 | public abstract class AbstractCompiler implements Compiler { 14 | 15 | private static final Pattern PACKAGE_PATTERN = Pattern 16 | .compile("package\\s+([$_a-zA-Z][$_a-zA-Z0-9\\.]*);"); 17 | 18 | private static final Pattern CLASS_PATTERN = Pattern 19 | .compile("class\\s+([$_a-zA-Z][$_a-zA-Z0-9]*)\\s+"); 20 | 21 | public Class compile(String code) { 22 | code = code.trim(); 23 | Matcher matcher = PACKAGE_PATTERN.matcher(code); 24 | String pkg; 25 | if (matcher.find()) { 26 | pkg = matcher.group(1); 27 | } else { 28 | pkg = ""; 29 | } 30 | matcher = CLASS_PATTERN.matcher(code); 31 | String cls; 32 | if (matcher.find()) { 33 | cls = matcher.group(1); 34 | } else { 35 | throw new IllegalArgumentException("No such class name in " + code); 36 | } 37 | String className = pkg != null && pkg.length() > 0 ? pkg + "." + cls : cls; 38 | if (!code.endsWith("}")) { 39 | throw new IllegalStateException("The java code not endsWith \"}\", code: \n" + code 40 | + "\n"); 41 | } 42 | try { 43 | return doCompile(className, code); 44 | } catch (RuntimeException t) { 45 | throw t; 46 | } catch (Throwable t) { 47 | throw new IllegalStateException("Failed to compile class, cause: " + t.getMessage() 48 | + ", class: " + className + ", code: \n" + code + "\n, stack: " + t); 49 | } 50 | } 51 | 52 | protected abstract Class doCompile(String name, String source) throws Throwable; 53 | 54 | } 55 | -------------------------------------------------------------------------------- /sb-commons/common-jreloader/src/main/java/org/chinasb/common/jreloader/watcher/WatchEventListener.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.jreloader.watcher; 2 | 3 | import java.nio.file.Path; 4 | import java.nio.file.WatchEvent; 5 | 6 | public interface WatchEventListener { 7 | 8 | boolean support(Path file, WatchEvent.Kind kind); 9 | 10 | void onWatchEvent(String dir, Path file, WatchEvent.Kind kind); 11 | } 12 | -------------------------------------------------------------------------------- /sb-commons/common-lock/.gitignore: -------------------------------------------------------------------------------- 1 | /.settings 2 | /.project 3 | /target 4 | /.classpath 5 | -------------------------------------------------------------------------------- /sb-commons/common-lock/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | sb-commons-parent 8 | org.chinasb 9 | 0.0.1-SNAPSHOT 10 | 11 | common-lock 12 | jar 13 | ${project.artifactId} 14 | The lock module of sb-commons project 15 | 16 | true 17 | 18 | 19 | 20 | org.slf4j 21 | slf4j-api 22 | 23 | 24 | com.google.guava 25 | guava 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /sb-commons/common-lock/src/main/java/org/chinasb/common/lock/ChainLock.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.lock; 2 | 3 | import java.util.List; 4 | import java.util.concurrent.TimeUnit; 5 | import java.util.concurrent.locks.Lock; 6 | 7 | /** 8 | * 锁链 9 | * 10 | * @author zhujuan 11 | */ 12 | public class ChainLock { 13 | private final List locks; 14 | /** 获取锁超时时间,单位:毫秒 */ 15 | private static final int TIME_OUT = 5; 16 | /** 获取锁超时时间,次数 */ 17 | private static final int TIMES = 3; 18 | 19 | /** 20 | * 初始化锁链 21 | * 22 | * @param locks 23 | */ 24 | public ChainLock(List locks) { 25 | if ((locks == null) || (locks.isEmpty())) { 26 | throw new IllegalArgumentException("构建锁链的锁数量不能为0"); 27 | } 28 | this.locks = locks; 29 | } 30 | 31 | /** 32 | * 加锁 33 | */ 34 | public void lock() { 35 | boolean relock = false; 36 | do { 37 | relock = false; 38 | for (int i = 0; i < locks.size(); i++) { 39 | int count = 0; 40 | Lock current = locks.get(i); 41 | try { 42 | while (true) { 43 | if (current.tryLock() || current.tryLock(TIME_OUT, TimeUnit.MILLISECONDS)) { 44 | break; 45 | } 46 | 47 | if (count++ >= TIMES) { 48 | relock = true; 49 | break; 50 | } 51 | } 52 | } catch (Exception e) { 53 | relock = true; 54 | } 55 | if (relock) { 56 | unlock(i); 57 | break; 58 | } 59 | } 60 | } while (relock); 61 | } 62 | 63 | /** 64 | * 解锁 65 | */ 66 | public void unlock() { 67 | unlock(locks.size()); 68 | } 69 | 70 | /** 71 | * 解锁 72 | * 73 | * @param end 位置 74 | */ 75 | private void unlock(int end) { 76 | end = Math.min(end, locks.size()); 77 | for (int i = 0; i < end; i++) { 78 | Lock objectLock = locks.get(i); 79 | try { 80 | if (objectLock != null) { 81 | objectLock.unlock(); 82 | } 83 | } catch (Exception e) { 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /sb-commons/common-lock/src/main/java/org/chinasb/common/lock/IEntity.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.lock; 2 | 3 | /** 4 | * 实体标识接口 5 | * 6 | * @author zhujuan 7 | */ 8 | @SuppressWarnings("rawtypes") 9 | public interface IEntity { 10 | /** 11 | * 获取实体标识 12 | * 13 | * @return 14 | */ 15 | public T getIdentity(); 16 | } 17 | -------------------------------------------------------------------------------- /sb-commons/common-lock/src/main/java/org/chinasb/common/lock/LockUtils.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.lock; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.Iterator; 6 | import java.util.List; 7 | import java.util.TreeSet; 8 | import java.util.concurrent.locks.Lock; 9 | 10 | /** 11 | * 锁工具类 12 | * 13 | * @author zhujuan 14 | */ 15 | public class LockUtils { 16 | /** 对象锁持有者,用于避免重复的锁创建 */ 17 | private final static ObjectLockHolder holder = new ObjectLockHolder(); 18 | 19 | /** 20 | * 获取对象实例的锁链 21 | * 22 | * @param objects 23 | * @return 24 | */ 25 | public static ChainLock getLock(Object... objects) { 26 | List locks = loadLocks(objects); 27 | return new ChainLock(locks); 28 | } 29 | 30 | /** 31 | * 加载对象实例的对象锁,并对所有对象锁处理排序 32 | * 33 | * @param objects 34 | * @return 35 | */ 36 | private static List loadLocks(Object... objects) { 37 | List locks = new ArrayList(objects.length); 38 | for (Object obj : objects) { 39 | ObjectLock lock = holder.getLock(obj); 40 | if (lock != null && !locks.contains(lock)) { 41 | locks.add(lock); 42 | } 43 | } 44 | Collections.sort(locks); 45 | 46 | TreeSet idx = new TreeSet(); 47 | Integer start = null; 48 | for (int i = 0; i < locks.size(); ++i) { 49 | if (start == null) { 50 | start = i; 51 | } else { 52 | ObjectLock lock1 = locks.get(start.intValue()); 53 | ObjectLock lock2 = locks.get(i); 54 | if (lock1.isTie(lock2)) { 55 | idx.add(start); 56 | } else { 57 | start = i; 58 | } 59 | } 60 | } 61 | if (idx.isEmpty()) { 62 | return locks; 63 | } 64 | 65 | List newLocks = new ArrayList(locks.size() + idx.size()); 66 | newLocks.addAll(locks); 67 | Iterator it = idx.descendingIterator(); 68 | while (it.hasNext()) { 69 | Integer i = (Integer) it.next(); 70 | ObjectLock lock = locks.get(i.intValue()); 71 | Lock tieLock = holder.getTieLock(lock.getClz()); 72 | newLocks.add(i.intValue(), tieLock); 73 | } 74 | return newLocks; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /sb-commons/common-lock/src/main/java/org/chinasb/common/lock/ObjectLock.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.lock; 2 | 3 | import java.util.concurrent.locks.ReentrantLock; 4 | 5 | /** 6 | * 对象锁
7 | * 8 | *
  9 |  * 排序顺序说明:
 10 |  * 1.非实体在前,实体{@link IEntity}在后
 11 |  * 2.不同类型的锁对象,按类型{@link Class}的hashCode值的大小进行排序
 12 |  * 3.不同类型的锁对象,当不幸遇到hashCode值相同的情况,用完整类名做字符串排序
 13 |  * 4.类型相同时,使用{@link ObjectLock#value}进行排序
 14 |  * 5.{@link ObjectLock#value}对于非实体而言,为System.identityHashCode(instance)
 15 |  * 6.{@link ObjectLock#value}对于实体而言,为{@link IEntity#getIdentity()}
 16 |  * 
17 | * 18 | * @author zhujuan 19 | */ 20 | @SuppressWarnings("rawtypes") 21 | public class ObjectLock extends ReentrantLock implements Comparable { 22 | 23 | private static final long serialVersionUID = 1L; 24 | private static final Class IENTITY_CLASS = IEntity.class; 25 | /** 26 | * 对象锁的类型 27 | */ 28 | private final Class clz; 29 | /** 30 | * 对象锁用于排序的元素 31 | */ 32 | private final Comparable value; 33 | 34 | /** 35 | * 构造一个对象实例的对象锁 36 | * 37 | * @param object 38 | */ 39 | public ObjectLock(Object object) { 40 | this(object, true); 41 | } 42 | 43 | /** 44 | * 构造一个对象实例的对象锁 45 | * 46 | * @param object 47 | * @param fair {@link ReentrantLock#isFair()} 48 | */ 49 | public ObjectLock(Object object, boolean fair) { 50 | super(fair); 51 | this.clz = object.getClass(); 52 | if (object instanceof IEntity) 53 | this.value = ((IEntity) object).getIdentity(); 54 | else { 55 | this.value = new Integer(System.identityHashCode(object)); 56 | } 57 | } 58 | 59 | /** 60 | * 加时锁检查(检查当前对象锁与指定对象锁是否可以保证获取顺序) 61 | * 62 | * @param other 63 | * @return 64 | */ 65 | @SuppressWarnings("unchecked") 66 | public boolean isTie(ObjectLock other) { 67 | if (this.clz != other.clz) { 68 | return false; 69 | } 70 | if (this.value.compareTo(other.value) == 0) { 71 | return true; 72 | } 73 | return false; 74 | } 75 | 76 | /** 77 | * 获取对象锁的类型 78 | * 79 | * @return 80 | */ 81 | public Class getClz() { 82 | return clz; 83 | } 84 | 85 | /** 86 | * 获取对象锁的排序元素 87 | * 88 | * @return 89 | */ 90 | public Comparable getValue() { 91 | return value; 92 | } 93 | 94 | /** 95 | * 检查当前对象锁是否是实体的对象锁 96 | * 97 | * @return 98 | */ 99 | public boolean isEntity() { 100 | return IENTITY_CLASS.isAssignableFrom(clz); 101 | } 102 | 103 | @SuppressWarnings("unchecked") 104 | @Override 105 | public int compareTo(ObjectLock o) { 106 | if (this.isEntity() && !o.isEntity()) { 107 | return 1; 108 | } 109 | if (!this.isEntity() && o.isEntity()) { 110 | return -1; 111 | } 112 | if (this.clz != o.clz) { 113 | if (this.clz.hashCode() < o.clz.hashCode()) { 114 | return -1; 115 | } 116 | if (this.clz.hashCode() > o.clz.hashCode()) { 117 | return 1; 118 | } 119 | return this.clz.getName().compareTo(o.clz.getName()); 120 | } 121 | return this.value.compareTo(o.value); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /sb-commons/common-lock/src/main/java/org/chinasb/common/lock/ObjectLockHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.lock; 2 | 3 | import java.util.concurrent.locks.Lock; 4 | import java.util.concurrent.locks.ReentrantLock; 5 | 6 | import com.google.common.cache.CacheBuilder; 7 | import com.google.common.cache.CacheLoader; 8 | import com.google.common.cache.LoadingCache; 9 | 10 | /** 11 | * 对象锁持有者 12 | * 13 | * @author zhujuan 14 | */ 15 | @SuppressWarnings("rawtypes") 16 | public class ObjectLockHolder { 17 | /** 18 | * 所有类的对象锁持有者缓存 19 | */ 20 | private final LoadingCache HOLDERS = CacheBuilder.newBuilder().maximumSize(1000) 21 | .build(new CacheLoader() { 22 | @Override 23 | public Holder load(Class clz) { 24 | return new Holder(clz); 25 | } 26 | }); 27 | 28 | /** 29 | * 类的对象锁持有者 30 | * 31 | * @author zhujuan 32 | * 33 | */ 34 | public class Holder { 35 | /** 36 | * 对象锁持有者的类型 37 | */ 38 | @SuppressWarnings("unused") 39 | private final Class clz; 40 | /** 41 | * 加时锁,用于当对象的hash值(或实现自Entity接口的getIdentity())一样时保证锁的获取顺序 42 | */ 43 | private final Lock tieLock = new ReentrantLock(); 44 | /** 45 | * 实例的对象锁缓存 46 | */ 47 | private final LoadingCache locks = CacheBuilder.newBuilder().weakKeys() 48 | .build(new CacheLoader() { 49 | @Override 50 | public ObjectLock load(Object object) { 51 | return new ObjectLock(object); 52 | } 53 | }); 54 | 55 | public Holder(Class clz) { 56 | this.clz = clz; 57 | } 58 | 59 | /** 60 | * 获取对象锁 61 | * 62 | * @param object 63 | * @return 64 | */ 65 | public ObjectLock getLock(Object object) { 66 | return locks.getUnchecked(object); 67 | } 68 | 69 | /** 70 | * 获取加时锁 71 | * 72 | * @return 73 | */ 74 | public Lock getTieLock() { 75 | return tieLock; 76 | } 77 | 78 | /** 79 | * 获取锁的数量 80 | * 81 | * @return 82 | */ 83 | public long count() { 84 | return locks.size(); 85 | } 86 | } 87 | 88 | /** 89 | * 获取类的对象锁持有者 90 | * 91 | * @param clz 92 | * @return 93 | */ 94 | private Holder getHolder(Class clz) { 95 | return HOLDERS.getUnchecked(clz); 96 | } 97 | 98 | /** 99 | * 获取对象实例的对象锁 100 | * 101 | * @param object 102 | * @return 103 | */ 104 | public ObjectLock getLock(Object object) { 105 | if (object == null) 106 | return null; 107 | return getHolder(object.getClass()).getLock(object); 108 | } 109 | 110 | /** 111 | * 获取类的对象锁持有者的加时锁(tie-breaker) 112 | * 113 | * @param clz 114 | * @return 115 | */ 116 | public Lock getTieLock(Class clz) { 117 | return getHolder(clz).getTieLock(); 118 | } 119 | 120 | /** 121 | * 获取类的对象锁持有者的锁的数量 122 | * 123 | * @param clz 124 | * @return 125 | */ 126 | public long count(Class clz) { 127 | Holder holder = HOLDERS.getIfPresent(clz); 128 | if (holder != null) { 129 | return holder.count(); 130 | } 131 | return 0; 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /sb-commons/common-rhino/.gitignore: -------------------------------------------------------------------------------- 1 | /.settings 2 | /.project 3 | /target 4 | /.classpath 5 | -------------------------------------------------------------------------------- /sb-commons/common-rhino/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | sb-commons-parent 8 | org.chinasb 9 | 0.0.1-SNAPSHOT 10 | 11 | common-rhino 12 | jar 13 | ${project.artifactId} 14 | The rhino module of sb-commons project 15 | 16 | true 17 | 18 | 19 | 20 | org.slf4j 21 | slf4j-api 22 | 23 | 24 | ${project.groupId} 25 | common-utility 26 | ${project.version} 27 | 28 | 29 | com.google.guava 30 | guava 31 | 32 | 33 | org.mozilla 34 | rhino 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /sb-commons/common-rhino/src/main/java/org/chinasb/common/rhino/MapWarperFactory.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.rhino; 2 | 3 | import java.util.Map; 4 | 5 | import org.mozilla.javascript.Context; 6 | import org.mozilla.javascript.Scriptable; 7 | import org.mozilla.javascript.WrapFactory; 8 | 9 | /** 10 | * 公式参数包装器工厂 - Map 包装器 11 | */ 12 | @SuppressWarnings("rawtypes") 13 | public class MapWarperFactory extends WrapFactory { 14 | 15 | @Override 16 | public Object wrap(Context cx, Scriptable scope, Object obj, Class staticType) { 17 | if (obj instanceof Map) { 18 | return NativeJavaMap.wrap((Map) obj); 19 | } 20 | return super.wrap(cx, scope, obj, staticType); 21 | } 22 | 23 | @Override 24 | public Scriptable wrapNewObject(Context cx, Scriptable scope, Object obj) { 25 | if (obj instanceof Map) { 26 | return NativeJavaMap.wrap((Map) obj); 27 | } 28 | return super.wrapNewObject(cx, scope, obj); 29 | } 30 | 31 | @Override 32 | public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, Object obj, Class staticType) { 33 | if (obj instanceof Map) { 34 | return NativeJavaMap.wrap((Map) obj); 35 | } 36 | return super.wrapAsJavaObject(cx, scope, obj, staticType); 37 | } 38 | 39 | @Override 40 | public Scriptable wrapJavaClass(Context cx, Scriptable scope, 41 | Class javaClass) { 42 | return super.wrapJavaClass(cx, scope, javaClass); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /sb-commons/common-rhino/src/main/java/org/chinasb/common/rhino/NativeJavaMap.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.rhino; 2 | 3 | import java.lang.reflect.ParameterizedType; 4 | import java.lang.reflect.Type; 5 | import java.util.Map; 6 | 7 | import org.mozilla.javascript.NativeJavaObject; 8 | import org.mozilla.javascript.Scriptable; 9 | 10 | /** 11 | * Map 对象参数包装类 12 | */ 13 | @SuppressWarnings({ "rawtypes", "unchecked" }) 14 | public class NativeJavaMap extends NativeJavaObject { 15 | private static final long serialVersionUID = 3960951059804772962L; 16 | 17 | /** 18 | * Map的泛型类型 19 | */ 20 | private Type[] kvType; 21 | 22 | @Override 23 | public String getClassName() { 24 | return "JavaMap"; 25 | } 26 | 27 | private Map getValuesMap() { 28 | return (Map) javaObject; 29 | } 30 | 31 | public static NativeJavaMap wrap(Map obj) { 32 | NativeJavaMap map = new NativeJavaMap(); 33 | map.javaObject = obj; 34 | return map; 35 | } 36 | 37 | /** 38 | * 获取Map的<键, 值>泛型类型 39 | * @return 40 | */ 41 | private Type[] getKVType() { 42 | if (kvType == null) { 43 | Type[] genericInterfaces = getValuesMap().getClass().getGenericInterfaces(); 44 | for (Type t : genericInterfaces) { 45 | if (t instanceof ParameterizedType) { 46 | ParameterizedType pt = (ParameterizedType) t; 47 | Type rawType = pt.getRawType(); 48 | if (rawType.equals(Map.class)) { 49 | kvType = pt.getActualTypeArguments(); 50 | break; 51 | } 52 | } 53 | } 54 | } 55 | 56 | if(kvType == null) { 57 | kvType = new Type[] { Object.class, Object.class }; 58 | } 59 | return kvType; 60 | } 61 | 62 | /** 63 | * 检测是否合法Map的键类型 64 | * 65 | * @param 66 | * @param clz 67 | * @return 68 | */ 69 | private boolean isKeyType(Class clz) { 70 | Type[] kvType = this.getKVType(); 71 | return kvType[0] == Object.class || kvType[0] == clz || ((Class)kvType[0]).isAssignableFrom(clz); 72 | } 73 | 74 | @Override 75 | public Object get(String name, Scriptable start) { 76 | if (isKeyType(String.class)) { 77 | return getValuesMap().get(name); 78 | } 79 | return null; 80 | } 81 | 82 | @Override 83 | public Object get(int index, Scriptable start) { 84 | if (isKeyType(Integer.class)) { 85 | return getValuesMap().get(index); 86 | } 87 | return null; 88 | } 89 | 90 | @Override 91 | public boolean has(String name, Scriptable start) { 92 | if (isKeyType(String.class)) { 93 | return getValuesMap().containsKey(name); 94 | } 95 | return false; 96 | } 97 | 98 | @Override 99 | public boolean has(int index, Scriptable start) { 100 | if (isKeyType(String.class)) { 101 | return getValuesMap().containsKey(index); 102 | } 103 | return false; 104 | } 105 | 106 | @Override 107 | public void put(String name, Scriptable start, Object value) { 108 | if (isKeyType(String.class)) { 109 | getValuesMap().put(name, value); 110 | } 111 | } 112 | 113 | @Override 114 | public void put(int index, Scriptable start, Object value) { 115 | if (isKeyType(Integer.class)) { 116 | getValuesMap().put(index, value); 117 | } 118 | } 119 | 120 | @Override 121 | public void delete(String name) { 122 | if (isKeyType(String.class)) { 123 | getValuesMap().remove(name); 124 | } 125 | } 126 | 127 | @Override 128 | public void delete(int index) { 129 | if (isKeyType(Integer.class)) { 130 | getValuesMap().remove(index); 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /sb-commons/common-rhino/src/main/java/org/chinasb/common/rhino/Rhino.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.rhino; 2 | 3 | import java.util.Map; 4 | 5 | import org.mozilla.javascript.Context; 6 | import org.mozilla.javascript.ContextFactory; 7 | import org.mozilla.javascript.Script; 8 | import org.mozilla.javascript.Scriptable; 9 | 10 | import com.google.common.cache.CacheBuilder; 11 | import com.google.common.cache.CacheLoader; 12 | import com.google.common.cache.LoadingCache; 13 | 14 | /** 15 | * Mozilla Rhino 公式解析器 16 | * 17 | * @author zhujuan 18 | */ 19 | public class Rhino { 20 | private static final ThreadLocal THREAD_LOCALS = new ThreadLocal(); 21 | private static final LoadingCache SCRIPT_CACHE = CacheBuilder.newBuilder() 22 | .maximumSize(512).build(new CacheLoader() { 23 | @Override 24 | public Script load(String expression) { 25 | Context context = Context.enter(); 26 | Script exp = context.compileString(expression, "", -1, null); 27 | return exp; 28 | } 29 | }); 30 | 31 | /** 32 | * 获得当前线程的脚本作用域 33 | * 34 | * @return 35 | */ 36 | private static Scriptable getScope() { 37 | Scriptable scope = THREAD_LOCALS.get(); 38 | if (scope == null) { 39 | ContextFactory global = ContextFactory.getGlobal(); 40 | Context context = global.enterContext(); 41 | context.setWrapFactory(new MapWarperFactory()); 42 | scope = context.initStandardObjects(); 43 | THREAD_LOCALS.set(scope); 44 | } 45 | return scope; 46 | } 47 | 48 | /** 49 | * 计算公式 50 | * 51 | * @param expression 公式 52 | * @param ctx 上下文 53 | * @return {@link Object} 返回值 54 | */ 55 | public static Object invoke(String expression, Map ctx) { 56 | Script exp = SCRIPT_CACHE.getUnchecked(expression); 57 | Context context = Context.enter(); 58 | try { 59 | Scriptable args = context.newObject(getScope()); 60 | if (ctx != null && !ctx.isEmpty()) { 61 | for (Map.Entry e : ctx.entrySet()) { 62 | args.put(e.getKey(), args, e.getValue()); 63 | } 64 | } 65 | return exp.exec(context, args); 66 | } finally { 67 | Context.exit(); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /sb-commons/common-rhino/src/main/java/org/chinasb/common/rhino/RhinoHelper.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.rhino; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import org.chinasb.common.utility.NumberUtils; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import com.google.common.base.Strings; 11 | 12 | /** 13 | * 公式帮助类 14 | * 15 | * @author zhujuan 16 | */ 17 | public class RhinoHelper { 18 | private static Logger LOGGER = LoggerFactory.getLogger(RhinoHelper.class); 19 | 20 | /** 21 | * 执行公式表达式 22 | * 23 | * @param expression 公式表达式 24 | * @param ctx 公式执行上下文 25 | * @return {@link Number} 公式表达式执行结果 26 | */ 27 | private static Object execute(String expression, Map ctx) { 28 | if (!Strings.isNullOrEmpty(expression)) { 29 | try { 30 | return Rhino.invoke(expression, ctx); 31 | } catch (Exception ex) { 32 | LOGGER.error("公式: [{}], 参数[{}]执行错误 - ", expression, ctx); 33 | LOGGER.error("", ex); 34 | } 35 | } 36 | return null; 37 | } 38 | 39 | /** 40 | * 执行公式表达式 41 | * 42 | * @param expression 公式表达式 43 | * @param ctx 公式执行上下文 44 | * @return {@link Number} 公式表达式执行结果 45 | */ 46 | public static Number invoke(String expression, Map ctx) { 47 | Object value = execute(expression, ctx); 48 | return value == null ? 0 : (Number) value; 49 | } 50 | 51 | /** 52 | * 执行公式表达式 53 | * 54 | * @param expression 公式表达式 55 | * @param ctx 公式执行上下文 56 | * @param resultType 执行结果类型 57 | * @return T 公式表达式执行结果 58 | */ 59 | @SuppressWarnings("unchecked") 60 | public static T invoke(String expression, Map ctx, Class resultType) { 61 | Object value = execute(expression, ctx); 62 | if(resultType == Boolean.class || resultType == boolean.class) { 63 | return (T) (value == null ? false : value); 64 | } else { 65 | Number numberValue = value == null ? 0 : (Number) value; 66 | return NumberUtils.valueOf(resultType, numberValue); 67 | } 68 | } 69 | 70 | /** 71 | * 执行数值表达式 72 | * 73 | * @param expression 公式表达式 74 | * @param numbers 公式参数 75 | * @return {@link Number} 公式表达式执行结果 76 | */ 77 | public static Number invoke(String expression, Number... numbers) { 78 | int len = numbers.length; 79 | Map ctx = new HashMap(); 80 | for (int i = 0; i < len; i++) { 81 | ctx.put("n" + (i + 1), numbers[i]); 82 | } 83 | Object value = execute(expression, ctx); 84 | return value == null ? 0 : (Number) value; 85 | } 86 | 87 | /** 88 | * 执行公式表达式 89 | * 90 | * @param expression 公式表达式 91 | * @param numbers 公式参数 92 | * @param resultType 执行结果类型 93 | * @return T 公式表达式执行结果 94 | */ 95 | @SuppressWarnings("unchecked") 96 | public static T invoke(String expression, Class resultType, Number... numbers) { 97 | int len = numbers.length; 98 | Map ctx = new HashMap(); 99 | for (int i = 0; i < len; i++) { 100 | ctx.put("n" + (i + 1), numbers[i]); 101 | } 102 | 103 | Object value = execute(expression, ctx); 104 | if(resultType == Boolean.class || resultType == boolean.class) { 105 | return (T) (value == null ? false : value); 106 | } else { 107 | Number numberValue = value == null ? 0 : (Number) value; 108 | return NumberUtils.valueOf(resultType, numberValue); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /sb-commons/common-socket/.gitignore: -------------------------------------------------------------------------------- 1 | /.settings 2 | /.project 3 | /target 4 | /.classpath 5 | -------------------------------------------------------------------------------- /sb-commons/common-socket/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | sb-commons-parent 8 | org.chinasb 9 | 0.0.1-SNAPSHOT 10 | 11 | common-socket 12 | jar 13 | ${project.artifactId} 14 | The socket module of sb-commons project 15 | 16 | true 17 | 18 | 19 | 20 | org.slf4j 21 | slf4j-api 22 | 23 | 24 | ${project.groupId} 25 | common-jreloader 26 | ${project.version} 27 | 28 | 29 | ${project.groupId} 30 | common-threadpool 31 | ${project.version} 32 | 33 | 34 | ${project.groupId} 35 | common-utility 36 | ${project.version} 37 | 38 | 39 | org.apache.commons 40 | commons-digester3 41 | 42 | 43 | io.netty 44 | netty-all 45 | 46 | 47 | com.adobe.blazeds 48 | blazeds-common 49 | 50 | 51 | com.adobe.blazeds 52 | blazeds-core 53 | 54 | 55 | com.google.guava 56 | guava 57 | 58 | 59 | org.aeonbits.owner 60 | owner-java8 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/codec/CodecContext.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.codec; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 编解码上下文信息 7 | * 8 | * @author zhujuan 9 | * 10 | */ 11 | public class CodecContext implements Serializable { 12 | private static final long serialVersionUID = 1L; 13 | /** 14 | * 数据包所需字节数量 15 | */ 16 | private int bytesNeeded = 0; 17 | /** 18 | * 解码状态 19 | */ 20 | private DecoderState state = DecoderState.WAITING_DATA; 21 | 22 | /** 23 | * 获取数据包所需字节数量 24 | * 25 | * @return 26 | */ 27 | public int getBytesNeeded() { 28 | return this.bytesNeeded; 29 | } 30 | 31 | /** 32 | * 设置数据包所需字节数量 33 | * 34 | * @param bytesNeeded 35 | */ 36 | public void setBytesNeeded(int bytesNeeded) { 37 | this.bytesNeeded = bytesNeeded; 38 | } 39 | 40 | /** 41 | * 获取解码状态 42 | * 43 | * @return 44 | */ 45 | public DecoderState getState() { 46 | return this.state; 47 | } 48 | 49 | /** 50 | * 设置解码状态 51 | * 52 | * @param state 53 | */ 54 | public void setState(DecoderState state) { 55 | this.state = state; 56 | } 57 | 58 | /** 59 | * 比较解码状态是否相同 60 | * 61 | * @param state 62 | * @return 63 | */ 64 | public boolean isSameState(DecoderState state) { 65 | return (this.state != null) && (state != null) && (this.state == state); 66 | } 67 | 68 | /** 69 | * 返回一个新的编解码上下文对象 70 | * 71 | * @param byteNeeded 数据包所需字节数量 72 | * @param state 解码状态 73 | * @return 74 | */ 75 | public static CodecContext valueOf(int byteNeeded, DecoderState state) { 76 | CodecContext codecContext = new CodecContext(); 77 | codecContext.setBytesNeeded(byteNeeded); 78 | codecContext.setState(state); 79 | return codecContext; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/codec/DecoderState.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.codec; 2 | 3 | /** 4 | * 解码器状态 5 | * 6 | * @author zhujuan 7 | * 8 | */ 9 | public enum DecoderState { 10 | /** 11 | * 等待数据:解码过程中数据不完整,等待接收数据 12 | */ 13 | WAITING_DATA, 14 | /** 15 | * 解码就绪:进入解码就绪状态,等待新的解码开始 16 | */ 17 | READY; 18 | } 19 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/codec/MessageType.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.codec; 2 | 3 | /** 4 | * 消息类型 5 | * 6 | * @author zhujuan 7 | * 8 | */ 9 | public enum MessageType { 10 | /** 11 | * Amf3 Object 12 | */ 13 | AMF3, 14 | /** 15 | * Java Pojo Object 16 | */ 17 | JAVA, 18 | /** 19 | * Json Object 20 | */ 21 | JSON; 22 | } 23 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/codec/ResponseEncoder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.codec; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.DataOutputStream; 5 | import java.io.IOException; 6 | 7 | import org.apache.commons.logging.Log; 8 | import org.apache.commons.logging.LogFactory; 9 | import org.chinasb.common.socket.message.Response; 10 | import org.chinasb.common.socket.type.ResponseCode; 11 | import org.springframework.stereotype.Component; 12 | 13 | import io.netty.buffer.ByteBuf; 14 | import io.netty.buffer.Unpooled; 15 | import io.netty.channel.ChannelHandlerContext; 16 | import io.netty.handler.codec.MessageToByteEncoder; 17 | 18 | /** 19 | * 返回消息编码器 20 | * 21 | * @author zhujuan 22 | * 23 | */ 24 | @Component 25 | public class ResponseEncoder extends MessageToByteEncoder { 26 | 27 | private static final Log LOGGER = LogFactory.getLog(RequestDecoder.class); 28 | 29 | @Override 30 | protected void encode(ChannelHandlerContext ctx, Object message, ByteBuf out) throws Exception { 31 | if (message == null) { 32 | return; 33 | } 34 | 35 | if (message instanceof ByteBuf) { 36 | out.writeBytes((ByteBuf) message); 37 | } else if (message instanceof byte[]) { 38 | byte[] bytes = (byte[]) message; 39 | out.writeBytes(bytes); 40 | } else { 41 | ByteBuf buf = transform(message); 42 | if (buf != null) { 43 | out.writeBytes(buf); 44 | } 45 | } 46 | } 47 | 48 | /** 49 | * 消息编码 50 | * 51 | * @param message 消息对象 52 | * @return 53 | */ 54 | public ByteBuf transform(Object message) { 55 | return transformByteArray(encodeResponse(message)); 56 | } 57 | 58 | /** 59 | * 消息编码 60 | * 61 | * @param bytes 消息字节数据 62 | * @return 63 | */ 64 | public ByteBuf transformByteArray(byte[] bytes) { 65 | if ((bytes == null) || (bytes.length == 0)) { 66 | return null; 67 | } 68 | int messageLength = bytes.length; 69 | ByteBuf bytebuf = Unpooled.buffer(messageLength + RequestDecoder.PACKAGE_HEADER_LEN); 70 | bytebuf.writeInt(RequestDecoder.PACKAGE_HEADER_ID); 71 | bytebuf.writeInt(messageLength); 72 | bytebuf.writeBytes(bytes); 73 | return bytebuf; 74 | } 75 | 76 | /** 77 | * 消息对象转换成字节数组 78 | * 79 | * @param message 消息对象 80 | * @return 81 | */ 82 | public byte[] encodeResponse(Object message) { 83 | if (message instanceof Response) { 84 | Response response = (Response) message; 85 | response.setTime(System.currentTimeMillis()); 86 | ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 87 | DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream); 88 | try { 89 | int sn = response.getSn(); 90 | int messageType = response.getMessageType(); 91 | int module = response.getModule(); 92 | int cmd = response.getCmd(); 93 | 94 | dataOutputStream.writeInt(sn); 95 | dataOutputStream.writeShort(module); 96 | dataOutputStream.writeShort(cmd); 97 | dataOutputStream.writeByte(messageType); 98 | dataOutputStream.writeLong(response.getTime()); 99 | 100 | Object value = response.getValue(); 101 | if (value != null) { 102 | byte[] bytes = transferByteArray(messageType, value); 103 | if (bytes == null) { 104 | response.setStatus(ResponseCode.RESPONSE_CODE_ERROR); 105 | dataOutputStream.writeInt(response.getStatus()); 106 | } else { 107 | dataOutputStream.writeInt(response.getStatus()); 108 | dataOutputStream.write(bytes); 109 | } 110 | } else { 111 | dataOutputStream.writeInt(response.getStatus()); 112 | } 113 | return byteArrayOutputStream.toByteArray(); 114 | } catch (Exception ex) { 115 | LOGGER.error("ERROR", ex); 116 | } finally { 117 | try { 118 | dataOutputStream.close(); 119 | } catch (IOException ex) { 120 | LOGGER.error("ERROR", ex); 121 | } 122 | try { 123 | byteArrayOutputStream.close(); 124 | } catch (IOException ex) { 125 | LOGGER.error("ERROR", ex); 126 | } 127 | dataOutputStream = null; 128 | byteArrayOutputStream = null; 129 | } 130 | } 131 | return null; 132 | } 133 | 134 | /** 135 | * 转换消息字节数据 136 | * 137 | * @param messageType 消息类型 138 | * @param obj 消息内容 139 | * @return 140 | */ 141 | protected byte[] transferByteArray(int messageType, Object obj) { 142 | if (messageType == MessageType.AMF3.ordinal()) { 143 | return ObjectCodec.asObject2ByteArray(obj); 144 | } 145 | if (messageType == MessageType.JAVA.ordinal()) { 146 | return ObjectCodec.object2ByteArray(obj); 147 | } 148 | if (messageType == MessageType.JSON.ordinal()) { 149 | return ObjectCodec.jsonObject2ByteArray(obj); 150 | } 151 | return null; 152 | } 153 | 154 | } 155 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/config/ServerConfig.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.config; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.regex.Pattern; 5 | 6 | import org.aeonbits.owner.Config; 7 | import org.aeonbits.owner.Config.Sources; 8 | import org.aeonbits.owner.ConfigCache; 9 | import org.aeonbits.owner.Converter; 10 | 11 | import com.google.common.base.Strings; 12 | 13 | /** 14 | * 服务器配置 15 | * 16 | * @author zhujuan 17 | * 18 | */ 19 | @Sources({"classpath:server.properties"}) 20 | public interface ServerConfig extends Config { 21 | /** 22 | * 管理后台IP 23 | */ 24 | @Key("server.mis.ip") 25 | @DefaultValue("127.0.0.1") 26 | @ConverterClass(MisRegexConverter.class) 27 | Pattern[] misRegex(); 28 | 29 | /** 30 | * 公共队列大小 31 | */ 32 | @Key("common.queue.size") 33 | @DefaultValue("5") 34 | int commonQueueSize(); 35 | 36 | /** 37 | * 默认端口 38 | */ 39 | @Key("server.socket.port") 40 | @DefaultValue("9999") 41 | int socketPort(); 42 | 43 | /** 44 | * 读缓冲大小 45 | */ 46 | @Key("server.socket.buffer.read") 47 | @DefaultValue("2048") 48 | int readBufferSize(); 49 | 50 | /** 51 | * 接收缓冲大小 52 | */ 53 | @Key("server.socket.buffer.receive") 54 | @DefaultValue("40960") 55 | int receiveBufferSize(); 56 | 57 | /** 58 | * 写缓冲大小 59 | */ 60 | @Key("server.socket.buffer.write") 61 | @DefaultValue("4096") 62 | int writeBufferSize(); 63 | 64 | /** 65 | * 是否启用nagle算法,TcpNoDelay=false为启用nagle算法,Nagle算法的立意是良好的,避免网络中充塞小封包,提高网络的利用率 66 | */ 67 | @Key("server.tcp.nodelay") 68 | @DefaultValue("false") 69 | boolean tcpNodelay(); 70 | 71 | /** 72 | * 默认值为读取自系统的/proc/sys/net/core/somaxconn 73 | */ 74 | @Key("server.max.backlog") 75 | @DefaultValue("1024") 76 | int serverMaxBacklog(); 77 | 78 | class MisRegexConverter implements Converter { 79 | public Pattern convert(Method targetMethod, String text) { 80 | String str = text.trim().replace(".", "[.]").replace("*", "[0-9]*"); 81 | return Pattern.compile(str); 82 | } 83 | } 84 | 85 | public static boolean isAllowMisIp(String ip) { 86 | ServerConfig sc = ConfigCache.getOrCreate(ServerConfig.class); 87 | Pattern[] misRegex = sc.misRegex(); 88 | if (misRegex == null) { 89 | return false; 90 | } 91 | if (Strings.isNullOrEmpty(ip)) { 92 | return false; 93 | } 94 | for (Pattern pattern : misRegex) { 95 | if (pattern != null) { 96 | if (pattern.matcher(ip).matches()) { 97 | return true; 98 | } 99 | } 100 | } 101 | return false; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/context/ApplicationContext.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.context; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.context.ConfigurableApplicationContext; 6 | import org.springframework.context.support.ClassPathXmlApplicationContext; 7 | 8 | /** 9 | * 应用环境上下文 10 | * 11 | * @author zhujuan 12 | * 13 | */ 14 | public class ApplicationContext { 15 | private final Logger logger = LoggerFactory.getLogger(getClass()); 16 | 17 | private ConfigurableApplicationContext ctx; 18 | 19 | private ConfigurableApplicationContext getApplicationContext() { 20 | if (ctx != null) { 21 | return ctx; 22 | } 23 | throw new RuntimeException("ServerContext did not initialized!"); 24 | } 25 | 26 | public ApplicationContext() { 27 | initialize(); 28 | } 29 | 30 | /** 31 | * 应用环境初始化 32 | */ 33 | public void initialize() { 34 | ctx = new ClassPathXmlApplicationContext(new String[] {"applicationContext*.xml"}); 35 | ctx.registerShutdownHook(); 36 | } 37 | 38 | /** 39 | * 获取应用环境实例 40 | * 41 | * @param name 实例名称 42 | * @return 43 | */ 44 | public Object getBean(String name) { 45 | return getApplicationContext().getBean(name); 46 | } 47 | 48 | /** 49 | * 获取应用环境实例 50 | * 51 | * @param beanClazz 实例类 52 | * @return 53 | */ 54 | @SuppressWarnings("unchecked") 55 | public T getBean(Class beanClazz) { 56 | String[] names = getApplicationContext().getBeanNamesForType(beanClazz); 57 | if ((names != null) && (names.length > 0)) { 58 | if (names.length == 1) { 59 | return (T) getBean(names[0]); 60 | } 61 | logger.error("interface class[{}] too many implements bound !!", beanClazz); 62 | } else { 63 | logger.error("bean or interface class[{}] NOT bound !!", beanClazz); 64 | } 65 | return null; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/controller/Dispatcher.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.controller; 2 | 3 | import io.netty.channel.Channel; 4 | 5 | import org.chinasb.common.socket.handler.CommandHandler; 6 | import org.chinasb.common.socket.message.Request; 7 | 8 | /** 9 | * 消息处理接口 10 | * 11 | * @author zhujuan 12 | * 13 | */ 14 | public interface Dispatcher { 15 | 16 | /** 17 | * 添加消息处理器 18 | * 19 | * @param moduleKey 模块标识 20 | * @param paramHandler 消息处理器 21 | */ 22 | void put(int moduleKey, CommandHandler handler); 23 | 24 | /** 25 | * 删除消息处理器 26 | * 27 | * @param moduleKey 28 | */ 29 | void remove(int moduleKey); 30 | 31 | /** 32 | * 分发处理 33 | * 34 | * @param session 35 | * @param paramRequest 36 | */ 37 | void dispatch(Channel session, Request request); 38 | 39 | } 40 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/controller/impl/DispatcherImpl.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.controller.impl; 2 | 3 | import io.netty.channel.Channel; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | import org.apache.commons.logging.Log; 9 | import org.apache.commons.logging.LogFactory; 10 | import org.chinasb.common.socket.controller.Dispatcher; 11 | import org.chinasb.common.socket.handler.CommandHandler; 12 | import org.chinasb.common.socket.message.Request; 13 | import org.springframework.stereotype.Component; 14 | 15 | /** 16 | * 消息处理器 17 | * 18 | * @author zhujuan 19 | * 20 | */ 21 | @Component 22 | public class DispatcherImpl implements Dispatcher { 23 | 24 | private static final Log LOGGER = LogFactory.getLog(DispatcherImpl.class); 25 | private static final Map MODULE_HANDLERS = 26 | new HashMap(); 27 | 28 | @Override 29 | public void put(int moduleKey, CommandHandler handler) { 30 | if (handler != null) { 31 | if (MODULE_HANDLERS.containsKey(Integer.valueOf(moduleKey))) { 32 | throw new RuntimeException(String.format("Error: duplicated key [%d]", 33 | new Object[] {Integer.valueOf(moduleKey)})); 34 | } 35 | MODULE_HANDLERS.put(Integer.valueOf(moduleKey), handler); 36 | } 37 | } 38 | 39 | @Override 40 | public void remove(int moduleKey) { 41 | MODULE_HANDLERS.remove(moduleKey); 42 | } 43 | 44 | @Override 45 | public void dispatch(Channel session, Request request) { 46 | if ((session == null) || (request == null)) { 47 | return; 48 | } 49 | 50 | int module = request.getModule(); 51 | CommandHandler handler = MODULE_HANDLERS.get(Integer.valueOf(module)); 52 | if (handler == null) { 53 | LOGGER.error(String.format("No handler for module [%d]", 54 | new Object[] {Integer.valueOf(module)})); 55 | return; 56 | } 57 | 58 | handler.dispatch(session, request); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/firewall/ByteAttackFilter.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.firewall; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.chinasb.common.socket.SessionManager; 6 | import org.chinasb.common.socket.type.SessionType; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Component; 9 | 10 | import io.netty.buffer.ByteBuf; 11 | import io.netty.channel.Channel; 12 | import io.netty.channel.ChannelHandler.Sharable; 13 | import io.netty.channel.ChannelHandlerContext; 14 | import io.netty.channel.ChannelInboundHandlerAdapter; 15 | 16 | /** 17 | * 防火墙字节数据过滤处理 18 | * 19 | * @author zhujuan 20 | * 21 | */ 22 | @Sharable 23 | @Component 24 | public class ByteAttackFilter extends ChannelInboundHandlerAdapter { 25 | 26 | private static final Log LOGGER = LogFactory.getLog(ByteAttackFilter.class); 27 | 28 | @Autowired 29 | private Firewall firewall; 30 | @Autowired 31 | private SessionManager sessionManager; 32 | 33 | @Override 34 | public void channelRead(final ChannelHandlerContext ctx, final Object message) throws Exception { 35 | Channel session = ctx.channel(); 36 | if (firewall.getClientType(session) != ClientType.MIS) { 37 | boolean blocked = firewall.isBlocked(session); 38 | if ((!blocked) && ((message instanceof ByteBuf))) { 39 | ByteBuf byteBuf = (ByteBuf) message; 40 | int length = byteBuf.readableBytes(); 41 | if (LOGGER.isDebugEnabled()) { 42 | LOGGER.debug(String.format("%s", new Object[] {message})); 43 | } 44 | blocked = firewall.blockedByBytes(session, length); 45 | } 46 | 47 | if (blocked) { 48 | String remoteIp = sessionManager.getRemoteIp(session); 49 | long playerId = sessionManager.getPlayerId(session).longValue(); 50 | if (LOGGER.isDebugEnabled()) { 51 | LOGGER.debug(String.format("%s", new Object[] {message})); 52 | } 53 | LOGGER.error(String.format("In blacklist: [ip: %s, playerId: %d]", new Object[] { 54 | remoteIp, Long.valueOf(playerId)})); 55 | sessionManager.closeSession(session); 56 | return; 57 | } 58 | } 59 | ctx.fireChannelRead(message); 60 | } 61 | 62 | @Override 63 | public void channelRegistered(ChannelHandlerContext ctx) throws Exception { 64 | Channel session = ctx.channel(); 65 | int currClients = firewall.increaseClients(); 66 | if ((firewall.getClientType(session) != ClientType.MIS) && (firewall.isBlocked(session))) { 67 | String remoteIp = sessionManager.getRemoteIp(session); 68 | Long playerId = sessionManager.getPlayerId(session); 69 | LOGGER.error(String.format("In blacklist: [ip: %s, playerId: %d]", new Object[] { 70 | remoteIp, playerId})); 71 | sessionManager.closeSession(session); 72 | return; 73 | } 74 | if (firewall.isMaxClientLimit(currClients)) { 75 | LOGGER.error(String.format("Connections limit, close session...: SESSION[%s]", 76 | new Object[] {session.id()})); 77 | sessionManager.closeSession(session); 78 | return; 79 | } 80 | session.attr(SessionType.WHICH_CLIENTS).set(Integer.valueOf(currClients));; 81 | ctx.fireChannelRegistered(); 82 | } 83 | 84 | @Override 85 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 86 | Channel session = ctx.channel(); 87 | Integer whichClient = session.attr(SessionType.WHICH_CLIENTS).getAndRemove(); 88 | if (firewall.getClientType(session) != ClientType.MIS) { 89 | if ((whichClient != null) && (firewall.isMaxClientActives(whichClient.intValue())) 90 | && (firewall.isMaxClientActive())) { 91 | LOGGER.error(String.format( 92 | "Active connections limit, close session...: SESSION[%s]", 93 | new Object[] {session.id()})); 94 | sessionManager.closeSession(session); 95 | return; 96 | } 97 | } 98 | ctx.fireChannelActive(); 99 | } 100 | 101 | @Override 102 | public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { 103 | firewall.decreaseClients(); 104 | ctx.fireChannelUnregistered(); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/firewall/ClientType.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.firewall; 2 | 3 | public enum ClientType { 4 | /** 5 | * 管理后台 6 | */ 7 | MIS, 8 | /** 9 | * 匿名用户 10 | */ 11 | ANONYMOUS, 12 | /** 13 | * 登陆用户 14 | */ 15 | LOGIN_USER; 16 | } 17 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/firewall/CmdAttackFilter.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.firewall; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.chinasb.common.socket.SessionManager; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Component; 8 | 9 | import io.netty.channel.Channel; 10 | import io.netty.channel.ChannelHandler.Sharable; 11 | import io.netty.channel.ChannelHandlerContext; 12 | import io.netty.channel.ChannelInboundHandlerAdapter; 13 | 14 | /** 15 | * 防火墙指令数据过滤处理 16 | * 17 | * @author zhujuan 18 | * 19 | */ 20 | @Sharable 21 | @Component 22 | public class CmdAttackFilter extends ChannelInboundHandlerAdapter { 23 | 24 | private static final Log LOGGER = LogFactory.getLog(CmdAttackFilter.class); 25 | 26 | @Autowired 27 | private Firewall firewall; 28 | @Autowired 29 | private SessionManager sessionManager; 30 | 31 | @Override 32 | public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception { 33 | Channel session = ctx.channel(); 34 | if ((firewall.getClientType(session) != ClientType.MIS) 35 | && (firewall.blockedByPacks(ctx.channel(), 1))) { 36 | String remoteIp = sessionManager.getRemoteIp(session); 37 | long playerId = sessionManager.getPlayerId(session).longValue(); 38 | LOGGER.error(String.format("In blacklist: [ip: %s, playerId: %d]", new Object[] { 39 | remoteIp, Long.valueOf(playerId)})); 40 | sessionManager.closeSession(session); 41 | return; 42 | } 43 | ctx.fireChannelRead(msg); 44 | } 45 | 46 | @Override 47 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 48 | Channel session = ctx.channel(); 49 | if ((firewall.getClientType(session) != ClientType.MIS) && (firewall.isBlocked(session))) { 50 | String remoteIp = sessionManager.getRemoteIp(session); 51 | Long playerId = sessionManager.getPlayerId(session); 52 | LOGGER.error(String.format("In blacklist: [ip: %s, playerId: %d]", new Object[] { 53 | remoteIp, playerId})); 54 | sessionManager.closeSession(session); 55 | return; 56 | } 57 | ctx.fireChannelActive(); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/firewall/FloodRecord.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.firewall; 2 | 3 | /** 4 | * 防火墙流量记录 5 | * 6 | * @author zhujuan 7 | * 8 | */ 9 | public class FloodRecord { 10 | /** 11 | * 最近一次消息流量记录时间 12 | */ 13 | private long lastSizeTime = 0L; 14 | /** 15 | * 最近一次消息数量记录时间 16 | */ 17 | private long lastPackTime = 0L; 18 | /** 19 | * 最近一秒钟的消息数量 20 | */ 21 | private int lastSecondPacks = 0; 22 | /** 23 | * 最近一秒钟的消息流量 24 | */ 25 | private int lastSecondSizes = 0; 26 | /** 27 | * 最近一分钟的消息数量 28 | */ 29 | private int lastMinutePacks = 0; 30 | /** 31 | * 最近一分钟的消息流量 32 | */ 33 | private int lastMinuteSizes = 0; 34 | /** 35 | * 最近一次的校验错误时间 36 | */ 37 | private long lastAuthCodeTime = 0L; 38 | /** 39 | * 最近一秒钟的校验错误次数 40 | */ 41 | private int lastSecondAuthCodes = 0; 42 | /** 43 | * 最近一分钟的校验错误次数 44 | */ 45 | private int lastMinuteAuthCodes = 0; 46 | 47 | public long getLastSizeTime() { 48 | return lastSizeTime; 49 | } 50 | 51 | public void setLastSizeTime(long lastSizeTime) { 52 | this.lastSizeTime = lastSizeTime; 53 | } 54 | 55 | public void addLastSizeTime(long lastSizeTime) { 56 | this.lastSizeTime += lastSizeTime; 57 | } 58 | 59 | public long getLastPackTime() { 60 | return lastPackTime; 61 | } 62 | 63 | public void setLastPackTime(long lastPackTime) { 64 | this.lastPackTime = lastPackTime; 65 | } 66 | 67 | public void addLastPackTime(long lastPackTime) { 68 | this.lastPackTime += lastPackTime; 69 | } 70 | 71 | public int getLastSecondPacks() { 72 | return lastSecondPacks; 73 | } 74 | 75 | public void setLastSecondPacks(int lastSecondPacks) { 76 | this.lastSecondPacks = lastSecondPacks; 77 | } 78 | 79 | public void addLastSecondPacks(int lastSecondPacks) { 80 | this.lastSecondPacks += lastSecondPacks; 81 | } 82 | 83 | public int getLastSecondSizes() { 84 | return lastSecondSizes; 85 | } 86 | 87 | public void setLastSecondSizes(int lastSecondSizes) { 88 | this.lastSecondSizes = lastSecondSizes; 89 | } 90 | 91 | public void addLastSecondSizes(int lastSecondSizes) { 92 | this.lastSecondSizes += lastSecondSizes; 93 | } 94 | 95 | public int getLastMinutePacks() { 96 | return lastMinutePacks; 97 | } 98 | 99 | public void setLastMinutePacks(int lastMinutePacks) { 100 | this.lastMinutePacks = lastMinutePacks; 101 | } 102 | 103 | public void addLastMinutePacks(int lastMinutePacks) { 104 | this.lastMinutePacks += lastMinutePacks; 105 | } 106 | 107 | public int getLastMinuteSizes() { 108 | return lastMinuteSizes; 109 | } 110 | 111 | public void setLastMinuteSizes(int lastMinuteSizes) { 112 | this.lastMinuteSizes = lastMinuteSizes; 113 | } 114 | 115 | public void addLastMinuteSizes(int lastMinuteSizes) { 116 | this.lastMinuteSizes += lastMinuteSizes; 117 | } 118 | 119 | public long getLastAuthCodeTime() { 120 | return lastAuthCodeTime; 121 | } 122 | 123 | public void setLastAuthCodeTime(long lastAuthCodeTime) { 124 | this.lastAuthCodeTime = lastAuthCodeTime; 125 | } 126 | 127 | public void addLastAuthCodeTime(long lastAuthCodeTime) { 128 | this.lastAuthCodeTime += lastAuthCodeTime; 129 | } 130 | 131 | public int getLastSecondAuthCodes() { 132 | return lastSecondAuthCodes; 133 | } 134 | 135 | public void setLastSecondAuthCodes(int lastSecondAuthCodes) { 136 | this.lastSecondAuthCodes = lastSecondAuthCodes; 137 | } 138 | 139 | public void addLastSecondAuthCodes(int lastSecondAuthCodes) { 140 | this.lastSecondAuthCodes += lastSecondAuthCodes; 141 | } 142 | 143 | public int getLastMinuteAuthCodes() { 144 | return lastMinuteAuthCodes; 145 | } 146 | 147 | public void setLastMinuteAuthCodes(int lastMinuteAuthCodes) { 148 | this.lastMinuteAuthCodes = lastMinuteAuthCodes; 149 | } 150 | 151 | public void addLastMinuteAuthCodes(int lastMinuteAuthCodes) { 152 | this.lastMinuteAuthCodes += lastMinuteAuthCodes; 153 | } 154 | 155 | public String toString() { 156 | return "FloodRecode [lastSizeTime=" + lastSizeTime + ", lastPackTime=" + lastPackTime 157 | + ", lastSecondPacks=" + lastSecondPacks + ", lastSecondSizes=" + lastSecondSizes 158 | + ", lastMinutePacks=" + lastMinutePacks + ", lastMinuteSizes=" + lastMinuteSizes 159 | + ", lastAuthCodeTime=" + lastAuthCodeTime + ", lastSecondAuthCodes=" 160 | + lastSecondAuthCodes + ", lastMinuteAuthCodes=" + lastMinuteAuthCodes + "]"; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/AbstractCommandHandler.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler; 2 | 3 | import io.netty.channel.Channel; 4 | 5 | import java.util.Map; 6 | import java.util.Map.Entry; 7 | import java.util.concurrent.ConcurrentHashMap; 8 | 9 | import javax.annotation.PostConstruct; 10 | import javax.annotation.PreDestroy; 11 | 12 | import org.chinasb.common.socket.SessionManager; 13 | import org.chinasb.common.socket.controller.Dispatcher; 14 | import org.chinasb.common.socket.message.Request; 15 | import org.chinasb.common.socket.message.Response; 16 | import org.chinasb.common.socket.type.ResponseCode; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | 21 | /** 22 | * 一个抽象的指令处理器 23 | * 24 | * @author zhujuan 25 | */ 26 | public abstract class AbstractCommandHandler implements CommandHandler { 27 | protected final Logger logger = LoggerFactory.getLogger(getClass()); 28 | /** 29 | * 指令解析器集合 30 | */ 31 | protected Map COMMAND_RESOLVER = 32 | new ConcurrentHashMap(); 33 | @Autowired 34 | protected Dispatcher dispatcher; 35 | @Autowired 36 | protected SessionManager sessionManager; 37 | @Autowired 38 | protected CommandWorkerContainer commandWorkerContainer; 39 | 40 | /** 41 | * 获取模块标识 42 | */ 43 | protected abstract int getModule(); 44 | 45 | @PostConstruct 46 | protected void initialize() { 47 | Map resolvers = commandWorkerContainer.analyzeClass(getClass()); 48 | if (resolvers.size() > 0) { 49 | for (Entry entry : resolvers.entrySet()) { 50 | if (entry.getValue() != null) { 51 | if (COMMAND_RESOLVER.containsKey(entry.getKey())) { 52 | logger.error(String.format("Error: duplicated key [%d]", 53 | new Object[] {entry.getKey()})); 54 | } 55 | COMMAND_RESOLVER.put(entry.getKey(), entry.getValue()); 56 | } 57 | } 58 | } 59 | dispatcher.put(getModule(), this); 60 | } 61 | 62 | @PreDestroy 63 | protected void destory() { 64 | dispatcher.remove(getModule()); 65 | } 66 | 67 | @Override 68 | public void dispatch(Channel session, Request request) { 69 | if (request != null) { 70 | int sn = request.getSn(); 71 | int module = request.getModule(); 72 | int cmd = request.getCmd(); 73 | Response response = Response.valueOf(sn, module, cmd); 74 | response.setMessageType(request.getMessageType()); 75 | CommandResolver commandResolver = COMMAND_RESOLVER.get(Integer.valueOf(cmd)); 76 | if (commandResolver != null) { 77 | if (logger.isDebugEnabled()) { 78 | logger.debug(String.format("角色:[%d], module:[%d], cmd:[%d]", 79 | new Object[] {sessionManager.getPlayerId(session), 80 | Integer.valueOf(module), Integer.valueOf(cmd)})); 81 | } 82 | try { 83 | commandResolver.execute(session, request, response); 84 | } catch (Exception e) { 85 | logger.error(String.format("角色:[%d], module:[%d], cmd:[%d], stack:[%s]", 86 | new Object[] {sessionManager.getPlayerId(session), 87 | Integer.valueOf(module), Integer.valueOf(cmd), e})); 88 | } 89 | } else { 90 | if (logger.isDebugEnabled()) { 91 | logger.error(String.format("No Invoker for module:[%d], cmd:[%d]", 92 | new Object[] {Integer.valueOf(module), Integer.valueOf(cmd)})); 93 | } 94 | response.setStatus(ResponseCode.RESPONSE_CODE_ERROR); 95 | if (session.isActive()) { 96 | session.writeAndFlush(response); 97 | } 98 | } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/CommandHandler.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler; 2 | 3 | import io.netty.channel.Channel; 4 | 5 | import org.chinasb.common.socket.message.Request; 6 | 7 | /** 8 | * 指令处理器接口 9 | * 10 | * @author zhujuan 11 | */ 12 | public interface CommandHandler { 13 | 14 | /** 15 | * 分发处理 16 | * 17 | * @param session 18 | * @param request 19 | */ 20 | public void dispatch(Channel session, Request request); 21 | } 22 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/CommandResolver.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler; 2 | 3 | import org.chinasb.common.socket.message.Request; 4 | import org.chinasb.common.socket.message.Response; 5 | 6 | import io.netty.channel.Channel; 7 | 8 | /** 9 | * 指令解析器接口 10 | * 11 | * @author zhujuan 12 | */ 13 | public interface CommandResolver { 14 | 15 | /** 16 | * 解析执行 17 | * 18 | * @param session 19 | * @param request 20 | * @param response 21 | * @throws Exception 22 | */ 23 | public void execute(Channel session, Request request, Response response) throws Exception; 24 | } 25 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/CommandWorkerContainer.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * 指令工作器容器 7 | * 8 | * @author zhujuan 9 | */ 10 | public interface CommandWorkerContainer { 11 | /** 12 | * 模块分析 13 | * 14 | * @param clazz 15 | * @return 16 | */ 17 | public Map analyzeClass(Class clazz); 18 | 19 | /** 20 | * 获得指令工作器实例 21 | * 22 | * @param workerClazz 23 | * @return 24 | */ 25 | public T getWorker(Class workerClazz); 26 | } 27 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/CommandWorkerMeta.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler; 2 | 3 | import java.util.List; 4 | 5 | import org.chinasb.common.socket.handler.configuration.CommandInterceptorConfig; 6 | 7 | /** 8 | * 指令工作器元数据接口 9 | * 10 | * @author zhujuan 11 | */ 12 | public interface CommandWorkerMeta { 13 | /** 14 | * 获取热加载模块标识 15 | * 16 | * @return 17 | */ 18 | public int getReloadModuleId(); 19 | 20 | /** 21 | * 获取全局拦截器集合 22 | * 23 | * @return 24 | */ 25 | public List globalInterceptors(); 26 | } 27 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/DefaultCommandResolver.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.List; 5 | 6 | import org.chinasb.common.socket.handler.Interceptor.Interceptor; 7 | import org.chinasb.common.socket.message.Request; 8 | import org.chinasb.common.socket.message.Response; 9 | 10 | import io.netty.channel.Channel; 11 | 12 | /** 13 | * 一个默认的指令解析器 14 | * 15 | * @author zhujuan 16 | */ 17 | public class DefaultCommandResolver implements CommandResolver { 18 | 19 | /** 20 | * 模块标识 21 | */ 22 | private int module; 23 | /** 24 | * 指令标识 25 | */ 26 | private int cmd; 27 | /** 28 | * 指令描述 29 | */ 30 | private String description; 31 | /** 32 | * 实例方法 33 | */ 34 | private Method m; 35 | /** 36 | * 实例对象 37 | */ 38 | private Object target; 39 | /** 40 | * 全局拦截器集合 41 | */ 42 | private List globalInterceptors; 43 | /** 44 | * 模块拦截器集合 45 | */ 46 | private List classInterceptors; 47 | /** 48 | * 指令拦截器集合 49 | */ 50 | private List methodInterceptors; 51 | 52 | public DefaultCommandResolver(int module, int cmd, String description, Method m, Object target, 53 | List globalInterceptors, List classInterceptors, 54 | List methodInterceptors) { 55 | this.module = module; 56 | this.cmd = cmd; 57 | this.description = description; 58 | this.m = m; 59 | this.target = target; 60 | this.globalInterceptors = globalInterceptors; 61 | this.classInterceptors = classInterceptors; 62 | this.methodInterceptors = methodInterceptors; 63 | } 64 | 65 | @Override 66 | public void execute(Channel session, Request request, Response response) throws Exception { 67 | if (globalInterceptors != null) { 68 | for (Interceptor interceptor : globalInterceptors) { 69 | if (!interceptor.before(session, request, response)) 70 | return; 71 | } 72 | } 73 | if (classInterceptors != null) { 74 | for (Interceptor interceptor : classInterceptors) { 75 | if (!interceptor.before(session, request, response)) 76 | return; 77 | } 78 | } 79 | if (methodInterceptors != null) { 80 | for (Interceptor interceptor : methodInterceptors) { 81 | if (!interceptor.before(session, request, response)) 82 | return; 83 | } 84 | } 85 | 86 | m.invoke(target, new Object[] {session, request, response}); 87 | 88 | if (methodInterceptors != null) { 89 | for (Interceptor interceptor : methodInterceptors) { 90 | if (!interceptor.after(session, request, response)) 91 | return; 92 | } 93 | } 94 | if (classInterceptors != null) { 95 | for (Interceptor interceptor : classInterceptors) { 96 | if (!interceptor.after(session, request, response)) 97 | return; 98 | } 99 | } 100 | if (globalInterceptors != null) { 101 | for (Interceptor interceptor : globalInterceptors) { 102 | if (!interceptor.after(session, request, response)) 103 | return; 104 | } 105 | } 106 | } 107 | 108 | @Override 109 | public String toString() { 110 | return "DefaultCommandResolver [module=" + module + ", cmd=" + cmd + ", description=" 111 | + description + ", globalInterceptors=" + globalInterceptors 112 | + ", classInterceptors=" + classInterceptors + ", methodInterceptors=" 113 | + methodInterceptors + "]"; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/DefaultCommandWorkMeta.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler; 2 | 3 | import java.util.List; 4 | 5 | import javax.annotation.PostConstruct; 6 | 7 | import org.apache.commons.digester3.Digester; 8 | import org.chinasb.common.socket.handler.configuration.CommandInterceptorConfig; 9 | import org.chinasb.common.socket.handler.configuration.CommandWorkerConfig; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.beans.factory.annotation.Qualifier; 12 | import org.springframework.stereotype.Component; 13 | 14 | /** 15 | * 一个默认的指令工作器元数据解析器 16 | * 17 | * @author zhujuan 18 | */ 19 | @Component 20 | public class DefaultCommandWorkMeta implements CommandWorkerMeta { 21 | @Autowired(required = false) 22 | @Qualifier("commandworker.config_location") 23 | private String executorConfigLocation = "worker/commandworker-config.xml"; 24 | private CommandWorkerConfig commandWorkerConfig; 25 | 26 | @PostConstruct 27 | protected void initialize() { 28 | Digester digester = new Digester(); 29 | digester.setValidating(false); 30 | digester.addObjectCreate("executor", CommandWorkerConfig.class); 31 | digester.addSetProperties("executor", "reloadModuleId", "reloadModuleId"); 32 | digester.addObjectCreate("executor/worker-global-interceptor", 33 | CommandInterceptorConfig.class); 34 | digester.addSetProperties("executor/worker-global-interceptor"); 35 | digester.addSetNext("executor/worker-global-interceptor", "addGlobalInterceptor"); 36 | try { 37 | commandWorkerConfig = 38 | ((CommandWorkerConfig) digester.parse(DefaultCommandWorkMeta.class 39 | .getResourceAsStream("/" + executorConfigLocation))); 40 | } catch (Exception e) { 41 | throw new RuntimeException("FAILED TO PARSE[' " + executorConfigLocation + " ']", e); 42 | } 43 | } 44 | 45 | @Override 46 | public int getReloadModuleId() { 47 | return commandWorkerConfig.getReloadModuleId(); 48 | } 49 | 50 | @Override 51 | public List globalInterceptors() { 52 | return commandWorkerConfig.getGlobalInterceptorClasses(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/Interceptor/Interceptor.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler.Interceptor; 2 | 3 | import io.netty.channel.Channel; 4 | 5 | import org.chinasb.common.socket.message.Request; 6 | import org.chinasb.common.socket.message.Response; 7 | 8 | /** 9 | * 拦截器接口 10 | * 11 | * @author zhujuan 12 | */ 13 | public interface Interceptor { 14 | /** 15 | * 拦截前处理 16 | * 17 | * @param session 18 | * @param request 19 | * @param response 20 | * @return true:继续流程; false:流程中断 21 | */ 22 | public boolean before(Channel session, Request request, Response response); 23 | 24 | /** 25 | * 拦截后处理 26 | * 27 | * @param session 28 | * @param request 29 | * @param response 30 | * @return true:继续流程; false:流程中断 31 | */ 32 | public boolean after(Channel session, Request request, Response response); 33 | } 34 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/ServerInboundHandler.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.chinasb.common.socket.SessionManager; 6 | import org.chinasb.common.socket.controller.Dispatcher; 7 | import org.chinasb.common.socket.firewall.ClientType; 8 | import org.chinasb.common.socket.firewall.Firewall; 9 | import org.chinasb.common.socket.message.Request; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Component; 12 | 13 | import io.netty.channel.Channel; 14 | import io.netty.channel.ChannelHandlerContext; 15 | import io.netty.channel.ChannelInboundHandlerAdapter; 16 | import io.netty.handler.timeout.IdleState; 17 | import io.netty.handler.timeout.IdleStateEvent; 18 | 19 | /** 20 | * ServerInboundHandler 21 | * 22 | * @author zhujuan 23 | * 24 | */ 25 | @Component 26 | public class ServerInboundHandler extends ChannelInboundHandlerAdapter { 27 | 28 | private static final Log LOGGER = LogFactory.getLog(ServerInboundHandler.class); 29 | 30 | @Autowired 31 | private Firewall firewall; 32 | @Autowired 33 | protected Dispatcher dispatcher; 34 | @Autowired 35 | protected SessionManager sessionManager; 36 | 37 | @Override 38 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 39 | StringBuilder sb = new StringBuilder(); 40 | Throwable ex = cause; 41 | while (ex != null) { 42 | StackTraceElement[] stackTrace = ex.getStackTrace(); 43 | for (StackTraceElement st : stackTrace) { 44 | sb.append("\t").append(st.toString()).append("\n"); 45 | } 46 | if (ex == ex.getCause()) { 47 | break; 48 | } 49 | ex = ex.getCause(); 50 | if (ex != null) { 51 | sb.append("CAUSE\n").append(ex.getMessage()).append(ex).append("\n"); 52 | } 53 | } 54 | LOGGER.error(String.format("Error: %s\n%s", 55 | new Object[] {cause.getMessage(), sb.toString()})); 56 | } 57 | 58 | @Override 59 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 60 | if (firewall.getClientType(ctx.channel()) == ClientType.MIS) { 61 | sessionManager.put2MisList(ctx.channel()); 62 | } else { 63 | sessionManager.put2AnonymousList(ctx.channel()); 64 | } 65 | } 66 | 67 | @Override 68 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 69 | sessionManager.removeFromMisList(ctx.channel()); 70 | sessionManager.removeFromOnlineList(ctx.channel()); 71 | sessionManager.removeFromAnonymousList(ctx.channel()); 72 | } 73 | 74 | @Override 75 | public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { 76 | if (evt instanceof IdleStateEvent) { 77 | Channel session = ctx.channel(); 78 | if (firewall.getClientType(session) == ClientType.MIS) { 79 | return; 80 | } 81 | 82 | IdleStateEvent e = (IdleStateEvent) evt; 83 | if (e.state() == IdleState.READER_IDLE) { 84 | sessionManager.closeSession(session); 85 | if (LOGGER.isDebugEnabled()) { 86 | LOGGER.debug(String.format("会话:[%s] 进入空闲状态关闭", new Object[] {session})); 87 | } 88 | } 89 | } 90 | } 91 | 92 | @Override 93 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 94 | if ((msg != null) && ((msg instanceof Request))) { 95 | long startTime = System.currentTimeMillis(); 96 | Request request = (Request) msg; 97 | dispatcher.dispatch(ctx.channel(), request); 98 | long endTime = System.currentTimeMillis(); 99 | if (LOGGER.isDebugEnabled()) { 100 | Long playerId = sessionManager.getPlayerId(ctx.channel()); 101 | LOGGER.debug(String.format( 102 | "角色:[%d] 发送Module:[%d] Cmd:[%d] 响应请求耗时:[%d] 毫秒", 103 | new Object[] {playerId, Integer.valueOf(request.getModule()), 104 | Integer.valueOf(request.getCmd()), 105 | Long.valueOf(endTime - startTime)})); 106 | } 107 | } else { 108 | LOGGER.error("Wrong message type!"); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/ServerOutboundHandler.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.chinasb.common.socket.message.Response; 6 | 7 | import io.netty.channel.ChannelHandlerContext; 8 | import io.netty.channel.ChannelOutboundHandlerAdapter; 9 | import io.netty.channel.ChannelPromise; 10 | 11 | /** 12 | * ServerOutboundHandler 13 | * 14 | * @author zhujuan 15 | * 16 | */ 17 | public class ServerOutboundHandler extends ChannelOutboundHandlerAdapter { 18 | 19 | private static final Log LOGGER = LogFactory.getLog(ServerOutboundHandler.class); 20 | 21 | @Override 22 | public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) 23 | throws Exception { 24 | if ((msg != null) && (msg.getClass() == Response.class) && (LOGGER.isDebugEnabled())) { 25 | Response response = (Response) msg; 26 | int cmd = response.getCmd(); 27 | int module = response.getModule(); 28 | LOGGER.debug(String.format( 29 | "Module: [%d] Cmd: [%d], 包大小:[%d 字节]", 30 | new Object[] {Integer.valueOf(module), Integer.valueOf(cmd), 31 | Integer.valueOf(msg.toString().getBytes().length)})); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/annotation/CommandInterceptor.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | import org.chinasb.common.socket.handler.Interceptor.Interceptor; 9 | 10 | /** 11 | * 指令拦截器注解 12 | * 13 | * @author zhujuan 14 | * 15 | */ 16 | @Target(ElementType.ANNOTATION_TYPE) 17 | @Retention(RetentionPolicy.RUNTIME) 18 | public @interface CommandInterceptor { 19 | /** 20 | * 拦截器类 21 | * 22 | * @return 23 | */ 24 | Class value(); 25 | 26 | /** 27 | * 拦截器描述 28 | * 29 | * @return 30 | */ 31 | String description() default ""; 32 | } 33 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/annotation/CommandMapping.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * 指令映射注解 10 | * 11 | * @author zhujuan 12 | * 13 | */ 14 | @Target(ElementType.METHOD) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | public @interface CommandMapping { 17 | /** 18 | * 指令标识 19 | * 20 | * @return 21 | */ 22 | int cmd(); 23 | 24 | /** 25 | * 指令描述 26 | * 27 | * @return 28 | */ 29 | String description() default ""; 30 | } 31 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/annotation/CommandWorker.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * 指令工作器注解 10 | * 11 | * @author zhujuan 12 | * 13 | */ 14 | @Target(ElementType.TYPE) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | public @interface CommandWorker { 17 | /** 18 | * 模块标识 19 | * 20 | * @return 21 | */ 22 | int module(); 23 | 24 | /** 25 | * 模块描述 26 | * 27 | * @return 28 | */ 29 | String description() default ""; 30 | } 31 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/annotation/interceptors/ClassInterceptors.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler.annotation.interceptors; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | import org.chinasb.common.socket.handler.annotation.CommandInterceptor; 9 | 10 | /** 11 | * 模块拦截器注解 12 | * 13 | * @author zhujuan 14 | * 15 | */ 16 | @Target(ElementType.TYPE) 17 | @Retention(RetentionPolicy.RUNTIME) 18 | public @interface ClassInterceptors { 19 | /** 20 | * 拦截器 21 | * 22 | * @return 23 | */ 24 | CommandInterceptor[] value(); 25 | } 26 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/annotation/interceptors/MethodInterceptors.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler.annotation.interceptors; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | import org.chinasb.common.socket.handler.annotation.CommandInterceptor; 9 | 10 | /** 11 | * 指令拦截器注解 12 | * 13 | * @author zhujuan 14 | * 15 | */ 16 | @Target(ElementType.METHOD) 17 | @Retention(RetentionPolicy.RUNTIME) 18 | public @interface MethodInterceptors { 19 | /** 20 | * 拦截器 21 | * 22 | * @return 23 | */ 24 | CommandInterceptor[] value(); 25 | } 26 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/configuration/CommandInterceptorConfig.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler.configuration; 2 | 3 | /** 4 | * 指令拦截器配置 5 | * 6 | * @author zhujuan 7 | */ 8 | public class CommandInterceptorConfig { 9 | /** 10 | * 拦截器的类名 11 | */ 12 | private String className; 13 | 14 | /** 15 | * 获取拦截器的类名 16 | * 17 | * @return 18 | */ 19 | public String getClassName() { 20 | return className; 21 | } 22 | 23 | /** 24 | * 设置拦截器的类名 25 | * 26 | * @param className 27 | */ 28 | public void setClassName(String className) { 29 | this.className = className; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/handler/configuration/CommandWorkerConfig.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.handler.configuration; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 指令工作器配置 8 | */ 9 | public class CommandWorkerConfig { 10 | /** 11 | * 热加载模块标识 12 | */ 13 | private int reloadModuleId; 14 | 15 | /** 16 | * 全局拦截器集合 17 | */ 18 | private List globalInterceptorClasses = 19 | new ArrayList(); 20 | 21 | /** 22 | * 获取热加载模块标识 23 | * @return 24 | */ 25 | public int getReloadModuleId() { 26 | return reloadModuleId; 27 | } 28 | 29 | /** 30 | * 设置热加载模块标识 31 | * @param reloadModuleId 32 | */ 33 | public void setReloadModuleId(int reloadModuleId) { 34 | this.reloadModuleId = reloadModuleId; 35 | } 36 | 37 | /** 38 | * 添加全局拦截器 39 | * 40 | * @param interceptor 41 | */ 42 | public void addGlobalInterceptor(CommandInterceptorConfig interceptor) { 43 | globalInterceptorClasses.add(interceptor); 44 | } 45 | 46 | /** 47 | * 获取全局拦截器集合 48 | * 49 | * @return 50 | */ 51 | public List getGlobalInterceptorClasses() { 52 | return globalInterceptorClasses; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/message/Message.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.message; 2 | 3 | import java.io.Serializable; 4 | 5 | import org.chinasb.common.socket.codec.MessageType; 6 | 7 | /** 8 | * 消息抽象 9 | * 10 | * @author zhujuan 11 | * 12 | */ 13 | @SuppressWarnings("serial") 14 | public abstract class Message implements Serializable { 15 | 16 | /** 17 | * 默认消息流水号 18 | */ 19 | public static final int DEFAULT_SN = -1; 20 | 21 | /** 22 | * 消息流水号 23 | */ 24 | private int sn = DEFAULT_SN; 25 | /** 26 | * 功能模块 27 | */ 28 | private int module; 29 | /** 30 | * 模块指令 31 | */ 32 | private int cmd; 33 | /** 34 | * 消息编码类型 35 | */ 36 | private int messageType = MessageType.AMF3.ordinal(); 37 | /** 38 | * 消息内容 39 | */ 40 | private Object value; 41 | 42 | /** 43 | * 获取消息流水号 44 | * 45 | * @return 46 | */ 47 | public int getSn() { 48 | return sn; 49 | } 50 | 51 | /** 52 | * 设置消息流水号 53 | * 54 | * @param sn 55 | */ 56 | public void setSn(int sn) { 57 | this.sn = sn; 58 | } 59 | 60 | /** 61 | * 获取功能模块 62 | * 63 | * @return 64 | */ 65 | public int getModule() { 66 | return module; 67 | } 68 | 69 | /** 70 | * 设置功能模块 71 | * 72 | * @param module 73 | */ 74 | public void setModule(int module) { 75 | this.module = module; 76 | } 77 | 78 | /** 79 | * 获取模块指令 80 | * 81 | * @return 82 | */ 83 | public int getCmd() { 84 | return cmd; 85 | } 86 | 87 | /** 88 | * 设置模块指令 89 | * 90 | * @param cmd 91 | */ 92 | public void setCmd(int cmd) { 93 | this.cmd = cmd; 94 | } 95 | 96 | 97 | /** 98 | * 获取消息类型 99 | * 100 | * @return 101 | */ 102 | public int getMessageType() { 103 | return messageType; 104 | } 105 | 106 | /** 107 | * 设置消息类型 108 | * 109 | * @param messageType 110 | */ 111 | public void setMessageType(int messageType) { 112 | this.messageType = messageType; 113 | } 114 | 115 | /** 116 | * 获取消息内容 117 | * 118 | * @return 119 | */ 120 | public Object getValue() { 121 | return value; 122 | } 123 | 124 | /** 125 | * 设置消息内容 126 | * 127 | * @param value 128 | */ 129 | public void setValue(Object value) { 130 | this.value = value; 131 | } 132 | 133 | public String toString() { 134 | return "[module=" + this.module + ", cmd=" + this.cmd + ", messageType=" + this.messageType 135 | + ", sn=" + this.sn + ", value=" + this.value + "]"; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/message/Request.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.message; 2 | 3 | /** 4 | * 请求消息 5 | * 6 | * @author zhujuan 7 | * 8 | */ 9 | public class Request extends Message { 10 | 11 | private static final long serialVersionUID = 1L; 12 | 13 | /** 14 | * 获取一个消息对象 15 | * 16 | * @param sn 消息序列号 17 | * @param module 功能模块 18 | * @param cmd 模块指令 19 | * @return 20 | */ 21 | public static Request valueOf(int sn, int module, int cmd) { 22 | Request request = new Request(); 23 | request.setSn(sn); 24 | request.setModule(module); 25 | request.setCmd(cmd); 26 | return request; 27 | } 28 | 29 | /** 30 | * 获取一个消息对象 31 | * 32 | * @param sn 消息序列号 33 | * @param module 功能模块 34 | * @param cmd 模块指令 35 | * @param messageType 消息类型 36 | * @return 37 | */ 38 | public static Request valueOf(int sn, int module, int cmd, int messageType) { 39 | Request request = valueOf(sn, module, cmd); 40 | request.setMessageType(messageType); 41 | return request; 42 | } 43 | 44 | /** 45 | * 获取一个消息对象 46 | * 47 | * @param sn 消息序列号 48 | * @param module 功能模块 49 | * @param cmd 模块指令 50 | * @param messageType 消息类型 51 | * @param value 消息内容 52 | * @return 53 | */ 54 | public static Request valueOf(int sn, int module, int cmd, int messageType, Object value) { 55 | Request request = valueOf(sn, module, cmd, messageType); 56 | request.setValue(value); 57 | return request; 58 | } 59 | 60 | @Override 61 | public String toString() { 62 | return "Request" + super.toString(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/message/Response.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.message; 2 | 3 | import java.io.Serializable; 4 | 5 | import org.chinasb.common.socket.type.ResponseCode; 6 | 7 | /** 8 | * 返回消息 9 | * 10 | * @author zhujuan 11 | * 12 | */ 13 | public class Response extends Message implements Serializable { 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | /** 18 | * 消息状态 19 | */ 20 | private int status = ResponseCode.RESPONSE_CODE_SUCCESS; 21 | 22 | /** 23 | * 消息时间 24 | */ 25 | private long time = System.currentTimeMillis(); 26 | 27 | /** 28 | * 获取消息时间 29 | * 30 | * @return 31 | */ 32 | public long getTime() { 33 | return time; 34 | } 35 | 36 | /** 37 | * 设置消息时间 38 | * 39 | * @param time 40 | */ 41 | public void setTime(long time) { 42 | this.time = time; 43 | } 44 | 45 | /** 46 | * 获取消息状态 47 | * 48 | * @return 49 | */ 50 | public int getStatus() { 51 | return this.status; 52 | } 53 | 54 | /** 55 | * 设置消息状态 56 | * 57 | * @param status 58 | * @return 59 | */ 60 | public Response setStatus(int status) { 61 | this.status = status; 62 | return this; 63 | } 64 | 65 | /** 66 | * 获取一个默认的消息对象 67 | * 68 | * @param module 功能模块 69 | * @param cmd 模块指令 70 | * @return 71 | */ 72 | public static Response defaultResponse(int module, int cmd) { 73 | Response response = new Response(); 74 | response.setSn(DEFAULT_SN); 75 | response.setModule(module); 76 | response.setCmd(cmd); 77 | return response; 78 | } 79 | 80 | /** 81 | * 获取一个默认的消息对象 82 | * 83 | * @param module 功能模块 84 | * @param cmd 模块指令 85 | * @param value 消息内容 86 | * @return 87 | */ 88 | public static Response defaultResponse(int module, int cmd, Object value) { 89 | Response response = defaultResponse(module, cmd); 90 | response.setValue(value); 91 | return response; 92 | } 93 | 94 | /** 95 | * 获取一个消息返回对象 96 | * 97 | * @param sn 消息序列号 98 | * @param module 功能模块 99 | * @param cmd 模块指令 100 | * @return 101 | */ 102 | public static Response valueOf(int sn, int module, int cmd) { 103 | Response response = new Response(); 104 | response.setSn(sn); 105 | response.setModule(module); 106 | response.setCmd(cmd); 107 | return response; 108 | } 109 | 110 | /** 111 | * 获取一个消息返回对象 112 | * 113 | * @param sn 消息序列号 114 | * @param module 功能模块 115 | * @param cmd 模块指令 116 | * @param value 消息内容 117 | * @return 118 | */ 119 | public static Response valueOf(int sn, int module, int cmd, Object value) { 120 | Response response = valueOf(sn, module, cmd); 121 | response.setValue(value); 122 | return response; 123 | } 124 | 125 | /** 126 | * 获取一个消息返回对象 127 | * 128 | * @param sn 消息序列号 129 | * @param module 功能模块 130 | * @param cmd 模块指令 131 | * @param messageType 消息类型 132 | * @param status 消息状态 133 | * @return 134 | */ 135 | public static Response valueOf(int sn, int module, int cmd, int messageType, int status) { 136 | Response response = valueOf(sn, module, cmd); 137 | response.setStatus(status); 138 | response.setMessageType(messageType); 139 | return response; 140 | } 141 | 142 | /** 143 | * 获取一个消息返回对象 144 | * 145 | * @param sn 消息序列号 146 | * @param module 功能模块 147 | * @param cmd 模块指令 148 | * @param messageType 消息类型 149 | * @param status 消息状态 150 | * @param value 消息内容 151 | * @return 152 | */ 153 | public static Response valueOf(int sn, int module, int cmd, int messageType, int status, 154 | Object value) { 155 | Response response = valueOf(sn, module, cmd, messageType, status); 156 | response.setValue(value); 157 | return response; 158 | } 159 | 160 | @Override 161 | public String toString() { 162 | return "Response" + super.toString(); 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/push/PushContext.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.push; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | import java.util.HashSet; 6 | import java.util.concurrent.atomic.AtomicLong; 7 | 8 | import org.chinasb.common.socket.message.Response; 9 | 10 | /** 11 | * 消息推送上下文 12 | * 13 | * @author zhujuan 14 | * 15 | */ 16 | public class PushContext { 17 | private long pusherId; 18 | private Response response; 19 | private PushType type = PushType.ALL; 20 | private Collection playerIdList = null; 21 | 22 | public Response getResponse() { 23 | return response; 24 | } 25 | 26 | public void setResponse(Response response) { 27 | this.response = response; 28 | } 29 | 30 | public PushType getType() { 31 | return type; 32 | } 33 | 34 | public void setType(PushType type) { 35 | this.type = type; 36 | } 37 | 38 | public Collection getPlayerIdList() { 39 | return playerIdList; 40 | } 41 | 42 | public void setPlayerIdList(Collection playerIdList) { 43 | this.playerIdList = playerIdList; 44 | } 45 | 46 | public long getPusherId() { 47 | return pusherId; 48 | } 49 | 50 | private static final AtomicLong automicId = new AtomicLong(); 51 | 52 | private static long getAtomicId() { 53 | if (automicId.get() >= Long.MAX_VALUE) { 54 | automicId.set(1L); 55 | } 56 | return automicId.getAndIncrement(); 57 | } 58 | 59 | /** 60 | * 返回一个推送至所有在线玩家的消息上下文对象 61 | * 62 | * @param response 消息内容 63 | * @return 64 | */ 65 | public static PushContext push2AllOnline(Response response) { 66 | PushContext context = new PushContext(); 67 | context.type = PushType.ALL; 68 | context.response = response; 69 | context.pusherId = getAtomicId(); 70 | return context; 71 | } 72 | 73 | /** 74 | * 返回一个推送至指定玩家的消息上下文对象 75 | * 76 | * @param playerId 玩家 77 | * @param response 消息内容 78 | * @return 79 | */ 80 | public static PushContext push2Player(long playerId, Response response) { 81 | PushContext context = new PushContext(); 82 | context.pusherId = playerId; 83 | context.response = response; 84 | context.type = PushType.GROUP; 85 | context.playerIdList = Arrays.asList(new Long[] {Long.valueOf(playerId)}); 86 | return context; 87 | } 88 | 89 | /** 90 | * 返回一个推送至指定玩家的消息上下文对象 91 | * 92 | * @param playerIdList 玩家列表 93 | * @param response 消息内容 94 | * @return 95 | */ 96 | public static PushContext push2Players(Collection playerIdList, Response response) { 97 | PushContext context = new PushContext(); 98 | context.response = response; 99 | context.type = PushType.GROUP; 100 | context.pusherId = getAtomicId(); 101 | if (playerIdList != null) { 102 | context.playerIdList = new HashSet(playerIdList); 103 | } 104 | return context; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/push/PushType.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.push; 2 | 3 | public enum PushType { 4 | ALL, GROUP; 5 | } 6 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/type/ResponseCode.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.type; 2 | 3 | /** 4 | * 消息返回状态代码 5 | * 6 | * @author zhujuan 7 | */ 8 | public interface ResponseCode { 9 | /** 10 | * 错误 11 | */ 12 | public static final int RESPONSE_CODE_ERROR = -1; 13 | /** 14 | * 成功 15 | */ 16 | public static final int RESPONSE_CODE_SUCCESS = 0; 17 | /** 18 | * 没有结果 19 | */ 20 | public static final int RESPONSE_CODE_NO_RESULTS = 1; 21 | /** 22 | * 协议解析错误 23 | */ 24 | public static final int RESPONSE_CODE_RESOLVE_ERROR = 2; 25 | /** 26 | * 拒绝访问 27 | */ 28 | public static final int RESPONSE_CODE_FORBIDDEN = 3; 29 | /** 30 | * FVN Hash不匹配 31 | */ 32 | public static final int RESPONSE_CODE_AUTH_CODE_ERROR = 4; 33 | } 34 | -------------------------------------------------------------------------------- /sb-commons/common-socket/src/main/java/org/chinasb/common/socket/type/SessionType.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.socket.type; 2 | 3 | import io.netty.util.AttributeKey; 4 | 5 | import org.chinasb.common.socket.codec.CodecContext; 6 | import org.chinasb.common.socket.context.ApplicationContext; 7 | import org.chinasb.common.socket.firewall.ClientType; 8 | import org.chinasb.common.socket.firewall.FloodRecord; 9 | 10 | /** 11 | * 会话存储相关数据类型 12 | * 13 | * @author zhujuan 14 | * 15 | */ 16 | public interface SessionType { 17 | /** 18 | * 应用程序上下文信息 19 | */ 20 | public static final AttributeKey APPLICATION_CONTEXT_KEY = AttributeKey 21 | .valueOf("applicationContext"); 22 | /** 23 | * 编解码器上下文信息 24 | */ 25 | public static final AttributeKey CODEC_CONTEXT_KEY = AttributeKey 26 | .valueOf("codecContext"); 27 | /** 28 | * 连接首次请求状态 29 | */ 30 | public static final AttributeKey FIRST_REQUEST_KEY = AttributeKey 31 | .valueOf("firstRequest"); 32 | /** 33 | * 玩家ID 34 | */ 35 | public static final AttributeKey PLAYER_ID_KEY = AttributeKey.valueOf("playerId"); 36 | /** 37 | * 客户端IP地址 38 | */ 39 | public static final AttributeKey REMOTE_HOST_KEY = AttributeKey.valueOf("remoteHost"); 40 | /** 41 | * 防火墙流量记录 42 | */ 43 | public static final AttributeKey FLOOD_RECORD_KEY = AttributeKey 44 | .valueOf("floodRecordKey"); 45 | /** 46 | * 客户端连接类型 47 | */ 48 | public static final AttributeKey CLIENT_TYPE_KEY = AttributeKey 49 | .valueOf("CLIENT_TYPE_KEY"); 50 | /** 51 | * 客户端当前连接数量 52 | */ 53 | public static final AttributeKey WHICH_CLIENTS = AttributeKey.valueOf("whichClients"); 54 | /** 55 | * 最后一次聊天时间 56 | */ 57 | public static final AttributeKey LAST_CHAT_KEY = AttributeKey.valueOf("lastChat"); 58 | 59 | public static final AttributeKey HANDSHAKE_COMPLETE = AttributeKey.valueOf("handshake_complete"); 60 | } 61 | -------------------------------------------------------------------------------- /sb-commons/common-threadpool/.gitignore: -------------------------------------------------------------------------------- 1 | /.settings 2 | /.project 3 | /target 4 | /.classpath 5 | -------------------------------------------------------------------------------- /sb-commons/common-threadpool/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | sb-commons-parent 7 | org.chinasb 8 | 0.0.1-SNAPSHOT 9 | 10 | common-threadpool 11 | jar 12 | ${project.artifactId} 13 | The threadpool module of sb-commons project 14 | 15 | true 16 | 17 | 18 | 19 | org.slf4j 20 | slf4j-api 21 | 22 | 23 | ${project.groupId} 24 | common-utility 25 | ${project.version} 26 | 27 | 28 | com.lmax 29 | disruptor 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /sb-commons/common-threadpool/src/main/java/org/chinasb/common/threadpool/Task.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.threadpool; 2 | 3 | /** 4 | * 任务 5 | * 6 | * @author zhujuan 7 | * 8 | */ 9 | public interface Task { 10 | /** 11 | * 重置 12 | */ 13 | void reset(); 14 | /** 15 | * 执行 16 | */ 17 | void execute(); 18 | } -------------------------------------------------------------------------------- /sb-commons/common-threadpool/src/main/java/org/chinasb/common/threadpool/ordered/AbstractDelayTask.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.threadpool.ordered; 2 | 3 | /** 4 | * 延时任务抽象 5 | * 6 | * @author zhujuan 7 | * 8 | */ 9 | public abstract class AbstractDelayTask extends AbstractTask { 10 | 11 | protected long delayTime; 12 | protected long execTime; 13 | 14 | public AbstractDelayTask(TaskQueue taskQueue, int delayTime) { 15 | super(taskQueue); 16 | this.delayTime = delayTime; 17 | this.execTime = System.currentTimeMillis() + delayTime; 18 | } 19 | 20 | public boolean canExec(long currentTime) { 21 | if (currentTime >= execTime) { 22 | taskQueue.enqueue(this); 23 | return true; 24 | } 25 | return false; 26 | } 27 | 28 | @Override 29 | public void execute() { 30 | this.execTime = System.currentTimeMillis() + delayTime; 31 | super.execute(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sb-commons/common-threadpool/src/main/java/org/chinasb/common/threadpool/ordered/AbstractTask.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.threadpool.ordered; 2 | 3 | import org.chinasb.common.threadpool.Task; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | /** 8 | * 普通任务抽象 9 | * 10 | * @author zhujuan 11 | * 12 | */ 13 | public abstract class AbstractTask implements Task { 14 | 15 | private final Logger logger = LoggerFactory.getLogger(getClass()); 16 | 17 | /** 18 | * 任务队列 19 | */ 20 | protected final TaskQueue taskQueue; 21 | 22 | public AbstractTask(TaskQueue taskQueue) { 23 | this.taskQueue = taskQueue; 24 | } 25 | 26 | /** 27 | * 获取任务队列 28 | * @return 29 | */ 30 | public TaskQueue getTaskQueue() { 31 | return taskQueue; 32 | } 33 | 34 | @Override 35 | public void reset() { 36 | 37 | } 38 | 39 | @Override 40 | public void execute() { 41 | long startTime = System.currentTimeMillis(); 42 | run(); 43 | long endTime = System.currentTimeMillis(); 44 | long interval = endTime - startTime; 45 | if (interval >= 1000) { 46 | logger.warn("Execute task : " + this.toString() + ", interval : " + interval + ", task size : " + taskQueue.size()); 47 | } 48 | } 49 | 50 | public abstract void run(); 51 | } 52 | -------------------------------------------------------------------------------- /sb-commons/common-threadpool/src/main/java/org/chinasb/common/threadpool/ordered/OrderedTaskQueue.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.threadpool.ordered; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | /** 10 | * 任务队列 11 | * 12 | * @author zhujuan 13 | * 14 | */ 15 | public class OrderedTaskQueue implements TaskQueue { 16 | 17 | private static final Logger LOGGER = LoggerFactory.getLogger(OrderedTaskQueue.class); 18 | 19 | private final Queue taskQueue; 20 | private final OrderedTaskQueueExecutor executor; 21 | private final Runnable runner; 22 | private boolean running; 23 | 24 | public OrderedTaskQueue(final OrderedTaskQueueExecutor executor) { 25 | if (executor == null) { 26 | throw new NullPointerException(); 27 | } 28 | 29 | this.taskQueue = new LinkedList(); 30 | this.executor = executor; 31 | this.runner = new Runnable() { 32 | public void run() { 33 | for (;;) { 34 | AbstractTask task = taskQueue.poll(); 35 | if (task == null) { 36 | synchronized (taskQueue) { 37 | task = taskQueue.poll(); 38 | if (task == null) { 39 | running = false; 40 | return; 41 | } 42 | } 43 | } 44 | try { 45 | task.execute(); 46 | } catch (Throwable t) { 47 | LOGGER.error("Execute Task[{}] Caught unexpected Throwable[{}]", task, t); 48 | } finally { 49 | task.reset(); 50 | } 51 | } 52 | } 53 | }; 54 | } 55 | 56 | @Override 57 | public TaskQueue getTaskQueue() { 58 | return this; 59 | } 60 | 61 | @Override 62 | public boolean enqueue(AbstractTask task) { 63 | boolean result = false; 64 | synchronized (taskQueue) { 65 | result = taskQueue.offer(task); 66 | if (result) { 67 | if (!running) { 68 | running = true; 69 | executor.execute(runner); 70 | } 71 | } else { 72 | LOGGER.error("添加任务失败"); 73 | } 74 | } 75 | return result; 76 | } 77 | 78 | @Override 79 | public void enDelayQueue(AbstractDelayTask delayTask) { 80 | executor.enDelayQueue(delayTask); 81 | } 82 | 83 | @Override 84 | public int size() { 85 | synchronized (taskQueue) { 86 | return taskQueue.size(); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /sb-commons/common-threadpool/src/main/java/org/chinasb/common/threadpool/ordered/OrderedTaskQueueExecutor.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.threadpool.ordered; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | import java.util.concurrent.TimeUnit; 6 | 7 | import org.chinasb.common.threadpool.ringbuffer.DisruptorExecutor; 8 | import org.chinasb.common.threadpool.ringbuffer.Event; 9 | import org.chinasb.common.threadpool.ringbuffer.EventConsumer; 10 | import org.chinasb.common.utility.NamedThreadFactory; 11 | import org.chinasb.common.utility.ThreadPoolUtils; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | /** 16 | * 基于有序任务队列的线程池 17 | * 18 | * @author zhujuan 19 | * 20 | */ 21 | public class OrderedTaskQueueExecutor { 22 | private static final Logger LOGGER = LoggerFactory.getLogger(OrderedTaskQueueExecutor.class); 23 | private static final EventConsumer> DELAY_TASK_CONSUMER = 24 | new EventConsumer>() { 25 | 26 | @Override 27 | public void accept(Event event) { 28 | AbstractDelayTask task = event.getData(); 29 | long start = System.currentTimeMillis(); 30 | if (!task.canExec(start)) { 31 | task.getTaskQueue().enDelayQueue(task); 32 | } 33 | long end = System.currentTimeMillis(); 34 | long interval = end - start; 35 | if (interval > 1000) { 36 | LOGGER.warn("DelayEventConsumer is spent too much time:" + interval + "ms"); 37 | } 38 | } 39 | }; 40 | 41 | private final ExecutorService taskExecutor; 42 | private final DisruptorExecutor delayTaskExecutor; 43 | private final TaskQueue defaultQueue; 44 | 45 | public OrderedTaskQueueExecutor() { 46 | this(null); 47 | } 48 | 49 | public OrderedTaskQueueExecutor(String name) { 50 | this(Runtime.getRuntime().availableProcessors(), name); 51 | } 52 | 53 | public OrderedTaskQueueExecutor(int corePoolSize, String name) { 54 | String prefix = name == null ? "OrderedTaskQueueExecutor" : name; 55 | taskExecutor = Executors.newFixedThreadPool(corePoolSize, new NamedThreadFactory(prefix)); 56 | delayTaskExecutor = new DisruptorExecutor(prefix + "-延时任务处理器"); 57 | defaultQueue = new OrderedTaskQueue(this); 58 | } 59 | 60 | /** 61 | * 获取任务队列 62 | * @return 63 | */ 64 | public TaskQueue getDefaultQueue() { 65 | return defaultQueue; 66 | } 67 | 68 | /** 69 | * 添加任务 70 | * @param task 71 | */ 72 | public void enDefaultQueue(AbstractTask task) { 73 | defaultQueue.enqueue(task); 74 | } 75 | 76 | /** 77 | * 添加延时任务 78 | * @param delayTask 79 | */ 80 | public void enDelayQueue(AbstractDelayTask delayTask) { 81 | delayTaskExecutor.dispatch(Event.wrap(delayTask), DELAY_TASK_CONSUMER); 82 | } 83 | 84 | /** 85 | * 执行{@link Runnable} 86 | * @param action 87 | */ 88 | public void execute(Runnable runnable) { 89 | taskExecutor.execute(runnable); 90 | } 91 | 92 | /** 93 | * 立即关闭 94 | */ 95 | public void shutdownNow() { 96 | delayTaskExecutor.halt(); 97 | ThreadPoolUtils.shutdownNow(taskExecutor); 98 | } 99 | 100 | /** 101 | * 超时关闭 102 | * @param timeout 103 | */ 104 | public void shutdown(long timeout) { 105 | delayTaskExecutor.shutdown(timeout, TimeUnit.MILLISECONDS); 106 | ThreadPoolUtils.shutdownGraceful(taskExecutor, timeout); 107 | } 108 | 109 | /** 110 | * 阻塞完成所有任务之后关闭 111 | */ 112 | public void shutdown() { 113 | delayTaskExecutor.shutdown(); 114 | ThreadPoolUtils.shutdownGraceful(taskExecutor, Integer.MAX_VALUE); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /sb-commons/common-threadpool/src/main/java/org/chinasb/common/threadpool/ordered/TaskQueue.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.threadpool.ordered; 2 | 3 | /** 4 | * 任务队列接口 5 | * @author zhujuan 6 | * 7 | */ 8 | public interface TaskQueue { 9 | /** 10 | * 获取任务队列 11 | * @return 12 | */ 13 | TaskQueue getTaskQueue(); 14 | 15 | /** 16 | * 添加普通任务 17 | * @param task 18 | * @return 19 | */ 20 | boolean enqueue(AbstractTask task); 21 | 22 | /** 23 | * 添加延时任务 24 | * @param delayTask 25 | */ 26 | void enDelayQueue(AbstractDelayTask delayTask); 27 | 28 | /** 29 | * 获取任务数量 30 | * @return 31 | */ 32 | int size(); 33 | } 34 | -------------------------------------------------------------------------------- /sb-commons/common-threadpool/src/main/java/org/chinasb/common/threadpool/ringbuffer/BasePublisher.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.threadpool.ringbuffer; 2 | 3 | import java.util.concurrent.atomic.AtomicBoolean; 4 | 5 | import org.chinasb.common.threadpool.Task; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | /** 10 | * 事件发布者抽象 11 | * 12 | * @author zhujuan 13 | */ 14 | public abstract class BasePublisher implements EventPublisher { 15 | 16 | protected final AtomicBoolean alive = new AtomicBoolean(true); 17 | 18 | @Override 19 | public boolean alive() { 20 | return alive.get(); 21 | } 22 | 23 | @Override 24 | public > void dispatch(E event) { 25 | dispatch(event, null, null); 26 | } 27 | 28 | @Override 29 | public > void dispatch(E event, EventConsumer consumer) { 30 | dispatch(event, consumer, null); 31 | } 32 | 33 | @Override 34 | public > void dispatch(E event, EventConsumer consumer, 35 | EventConsumer errorConsumer) { 36 | if (!alive()) { 37 | throw new IllegalStateException("This Dispatcher has been shutdown"); 38 | } 39 | EventTask task = createTask(); 40 | task.setEvent(event); 41 | task.setConsumer(consumer); 42 | task.setErrorConsumer(errorConsumer); 43 | task.submit(); 44 | } 45 | 46 | @Override 47 | public > boolean tryDispatch(E event) { 48 | return tryDispatch(event, null, null); 49 | } 50 | 51 | @Override 52 | public > boolean tryDispatch(E event, EventConsumer consumer) { 53 | return tryDispatch(event, consumer, null); 54 | } 55 | 56 | @Override 57 | public > boolean tryDispatch(E event, EventConsumer consumer, 58 | EventConsumer errorConsumer) { 59 | if (!alive()) { 60 | return false; 61 | } 62 | EventTask task = tryCreateTask(); 63 | if (task == null) { 64 | return false; 65 | } 66 | task.setEvent(event); 67 | task.setConsumer(consumer); 68 | task.setErrorConsumer(errorConsumer); 69 | task.submit(); 70 | return true; 71 | } 72 | 73 | protected abstract > EventTask createTask(); 74 | protected abstract > EventTask tryCreateTask(); 75 | 76 | protected abstract class EventTask> implements Task { 77 | private final Logger logger = LoggerFactory.getLogger(getClass()); 78 | 79 | private volatile E event; 80 | private volatile EventConsumer consumer; 81 | private volatile EventConsumer errorConsumer; 82 | 83 | EventTask setEvent(E event) { 84 | this.event = event; 85 | return this; 86 | } 87 | 88 | EventTask setConsumer(EventConsumer consumer) { 89 | this.consumer = consumer; 90 | return this; 91 | } 92 | 93 | EventTask setErrorConsumer(EventConsumer errorConsumer) { 94 | this.errorConsumer = errorConsumer; 95 | return this; 96 | } 97 | 98 | protected abstract void submit(); 99 | 100 | @Override 101 | public void reset() { 102 | event = null; 103 | consumer = null; 104 | errorConsumer = null; 105 | } 106 | 107 | @Override 108 | public void execute() { 109 | if (null != consumer) { 110 | try { 111 | consumer.accept(event); 112 | } catch (Exception e) { 113 | if (null != errorConsumer) { 114 | errorConsumer.accept(e); 115 | } else { 116 | logger.error("Consumer {} failed: {}", consumer, e.getMessage(), e); 117 | } 118 | } 119 | } else { 120 | Object runable = event.getData(); 121 | if (runable instanceof Runnable) { 122 | ((Runnable) runable).run(); 123 | } else { 124 | logger.error("runnable {} failed", runable); 125 | } 126 | } 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /sb-commons/common-threadpool/src/main/java/org/chinasb/common/threadpool/ringbuffer/Event.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.threadpool.ringbuffer; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 事件对象 7 | * 8 | * @author zhujuan 9 | * @param 10 | */ 11 | public class Event implements Serializable { 12 | 13 | private static final long serialVersionUID = 7447332262815727338L; 14 | 15 | /** 16 | * An {@code Event} with {@code null} data. 17 | */ 18 | public static final Event NULL_EVENT = new Event(null); 19 | 20 | private volatile T data; 21 | 22 | public Event(T data) { 23 | this.data = data; 24 | } 25 | 26 | public static Event wrap(T obj) { 27 | return new Event(obj); 28 | } 29 | 30 | public T getData() { 31 | return data; 32 | } 33 | 34 | public Event setData(T data) { 35 | this.data = data; 36 | return this; 37 | } 38 | 39 | public Event copy() { 40 | return copy(data); 41 | } 42 | 43 | public Event copy(E data) { 44 | return new Event(data); 45 | } 46 | 47 | @Override 48 | public String toString() { 49 | return "Event{" + "data=" + data + '}'; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /sb-commons/common-threadpool/src/main/java/org/chinasb/common/threadpool/ringbuffer/EventConsumer.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.threadpool.ringbuffer; 2 | 3 | /** 4 | * 事件消费者 5 | * 6 | * @author zhujuan 7 | * 8 | * @param 9 | */ 10 | public interface EventConsumer { 11 | 12 | /** 13 | * 执行 14 | * 15 | * @param t 16 | */ 17 | void accept(T t); 18 | 19 | } -------------------------------------------------------------------------------- /sb-commons/common-threadpool/src/main/java/org/chinasb/common/threadpool/ringbuffer/EventPublisher.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.threadpool.ringbuffer; 2 | 3 | /** 4 | * 事件发布者 5 | * 6 | * @author zhujuan 7 | */ 8 | public interface EventPublisher { 9 | /** 10 | * 判断事件发布者存活状态 11 | * @return 12 | */ 13 | boolean alive(); 14 | 15 | /** 16 | * 包装一个{@link Runnable}事件进行分发消费 17 | * @param event 18 | * @param consumer 19 | */ 20 | > void dispatch(E event); 21 | 22 | /** 23 | * 分发事件给指定的事件消费者 24 | * @param event 25 | * @param consumer 26 | */ 27 | > void dispatch(E event, EventConsumer consumer); 28 | 29 | /** 30 | * 分发事件给指定的事件消费者,处理消费异常 31 | * @param event 32 | * @param consumer 33 | * @param errorConsumer 34 | */ 35 | > void dispatch(E event, EventConsumer consumer, EventConsumer errorConsumer); 36 | 37 | /** 38 | * 包装一个{@link Runnable}事件,尝试进行分发消费 39 | * @param event 40 | * @param consumer 41 | */ 42 | > boolean tryDispatch(E event); 43 | 44 | /** 45 | * 尝试分发事件给指定的事件消费者 46 | * @param event 47 | * @param consumer 48 | */ 49 | > boolean tryDispatch(E event, EventConsumer consumer); 50 | 51 | /** 52 | * 尝试分发事件给指定的事件消费者,处理消费异常 53 | * @param event 54 | * @param consumer 55 | * @param errorConsumer 56 | */ 57 | > boolean tryDispatch(E event, EventConsumer consumer, EventConsumer errorConsumer); 58 | } 59 | -------------------------------------------------------------------------------- /sb-commons/common-utility/.gitignore: -------------------------------------------------------------------------------- 1 | /.settings 2 | /.project 3 | /target 4 | /.classpath 5 | -------------------------------------------------------------------------------- /sb-commons/common-utility/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | sb-commons-parent 8 | org.chinasb 9 | 0.0.1-SNAPSHOT 10 | 11 | common-utility 12 | jar 13 | ${project.artifactId} 14 | The utility module of sb-commons project 15 | 16 | true 17 | 18 | 19 | 20 | org.slf4j 21 | slf4j-api 22 | 23 | 24 | com.google.guava 25 | guava 26 | 27 | 28 | commons-beanutils 29 | commons-beanutils 30 | 31 | 32 | org.springframework 33 | spring-context 34 | 35 | 36 | com.fasterxml.jackson.core 37 | jackson-databind 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/ConcurrentHashSet.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility; 2 | 3 | import java.util.AbstractSet; 4 | import java.util.ConcurrentModificationException; 5 | import java.util.Iterator; 6 | import java.util.Set; 7 | import java.util.concurrent.ConcurrentHashMap; 8 | 9 | public class ConcurrentHashSet extends AbstractSet implements Set, java.io.Serializable { 10 | 11 | private static final long serialVersionUID = 1L; 12 | 13 | private static final Object PRESENT = new Object(); 14 | 15 | private final ConcurrentHashMap map; 16 | 17 | public ConcurrentHashSet() { 18 | map = new ConcurrentHashMap(); 19 | } 20 | 21 | public ConcurrentHashSet(int initialCapacity) { 22 | map = new ConcurrentHashMap(initialCapacity); 23 | } 24 | 25 | /** 26 | * Returns an iterator over the elements in this set. The elements are returned in no particular 27 | * order. 28 | * 29 | * @return an Iterator over the elements in this set 30 | * @see ConcurrentModificationException 31 | */ 32 | public Iterator iterator() { 33 | return map.keySet().iterator(); 34 | } 35 | 36 | /** 37 | * Returns the number of elements in this set (its cardinality). 38 | * 39 | * @return the number of elements in this set (its cardinality) 40 | */ 41 | public int size() { 42 | return map.size(); 43 | } 44 | 45 | /** 46 | * Returns true if this set contains no elements. 47 | * 48 | * @return true if this set contains no elements 49 | */ 50 | public boolean isEmpty() { 51 | return map.isEmpty(); 52 | } 53 | 54 | /** 55 | * Returns true if this set contains the specified element. More formally, returns 56 | * true if and only if this set contains an element e such that 57 | * (o==null ? e==null : o.equals(e)). 58 | * 59 | * @param o element whose presence in this set is to be tested 60 | * @return true if this set contains the specified element 61 | */ 62 | public boolean contains(Object o) { 63 | return map.containsKey(o); 64 | } 65 | 66 | /** 67 | * Adds the specified element to this set if it is not already present. More formally, adds the 68 | * specified element e to this set if this set contains no element e2 such 69 | * that (e==null ? e2==null : e.equals(e2)). If this set already 70 | * contains the element, the call leaves the set unchanged and returns false. 71 | * 72 | * @param e element to be added to this set 73 | * @return true if this set did not already contain the specified element 74 | */ 75 | public boolean add(E e) { 76 | return map.put(e, PRESENT) == null; 77 | } 78 | 79 | /** 80 | * Removes the specified element from this set if it is present. More formally, removes an 81 | * element e such that (o==null ? e==null : o.equals(e)), 82 | * if this set contains such an element. Returns true if this set contained the element 83 | * (or equivalently, if this set changed as a result of the call). (This set will not contain 84 | * the element once the call returns.) 85 | * 86 | * @param o object to be removed from this set, if present 87 | * @return true if the set contained the specified element 88 | */ 89 | public boolean remove(Object o) { 90 | return map.remove(o) == PRESENT; 91 | } 92 | 93 | /** 94 | * Removes all of the elements from this set. The set will be empty after this call returns. 95 | */ 96 | public void clear() { 97 | map.clear(); 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/EnumUtils.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | public class EnumUtils { 9 | private static Logger LOGGER = LoggerFactory.getLogger(EnumUtils.class); 10 | 11 | /** 12 | * 根据枚举类名和Key的名字获得枚举对象 13 | * 14 | * @param 15 | * @param enumClass 枚举类对象 16 | * @param fieldName 类型名 17 | * @return T 18 | */ 19 | public static > T valueOf(Class enumClass, String fieldName) { 20 | return Enum.valueOf(enumClass, fieldName); 21 | } 22 | 23 | /** 24 | * 根据枚举的类名和一个常量值构建枚举对象 25 | * 26 | * @param 27 | * @param enumClass 枚举类对象 28 | * @param value 需要查询的值 29 | * @return 30 | */ 31 | @SuppressWarnings("unchecked") 32 | public static > T getEnum(Class enumClass, int value) { 33 | try { 34 | if (value < 0) { 35 | return null; 36 | } 37 | Method method = enumClass.getMethod("values"); 38 | T[] values = (T[]) method.invoke(enumClass); 39 | if (values != null && values.length > value) { 40 | return values[value]; 41 | } 42 | return null; 43 | } catch (Exception e) { 44 | LOGGER.error("构建枚举 [Class: {} - Value: {} ] 出现异常", new Object[] { enumClass, value, e}); 45 | return null; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/GenericsUtils.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility; 2 | 3 | import java.lang.reflect.ParameterizedType; 4 | import java.lang.reflect.Type; 5 | 6 | 7 | public class GenericsUtils { 8 | 9 | /** 10 | * 获得指定类的父类的泛型参数的实际类型 11 | * 12 | * @param clazz Class 13 | * @param index 泛型参数所在索引,从0开始 14 | * @return {@link Class} 15 | */ 16 | @SuppressWarnings("rawtypes") 17 | public static Class getSuperClassGenricType(Class clazz, int index) { 18 | if (clazz == null) { 19 | return null; 20 | } 21 | 22 | Type genericType = clazz.getGenericSuperclass(); 23 | if (!(genericType instanceof ParameterizedType)) { 24 | return Object.class; 25 | } 26 | 27 | Type[] params = ((ParameterizedType) genericType).getActualTypeArguments(); 28 | if (params != null && index >= 0 && index < params.length ) { 29 | if (params[index] instanceof Class) { 30 | return (Class) params[index]; 31 | } 32 | } 33 | return Object.class; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/HashUtils.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility; 2 | 3 | 4 | /** 5 | * 由来:FNV哈希算法全名为Fowler-Noll-Vo算法,是以三位发明人Glenn Fowler,Landon Curt Noll,Phong Vo的名字来命名的,最早在1991年提出。 6 | * 特点和用途:FNV能快速hash大量数据并保持较小的冲突率,它的高度分散使它适用于hash一些非常相近的字符串,比如URL,hostname,文件名,text,IP地址等。 7 | * 算法版本:FNV算法有三个版本:FNV-0(已废弃)、FNV-1和FNV-1a FNV-1和FNV-1a算法对于最终生成的哈希值(hash)有一定限制 8 | * 9 | *  1,hash是无符号整型  2,hash的位数(bits),应该是2的n次方(32,64,128,256,512,1024),一般32位的就够用了。 10 | * 11 | * 算法描述: 相关变量: hash值:一个n位的unsigned int型hash值 offset_basis:初始的哈希值 FNV_prime:FNV用于散列的质数 12 | * octet_of_data:8位数据(即一个字节) FNV-1描述: hash = offset_basis for each octet_of_data to be hashed hash = 13 | * hash * FNV_prime hash = hash xor octet_of_data return hash FNV-1a描述: hash = offset_basis for each 14 | * octet_of_data to be hashed hash = hash xor octet_of_data hash = hash * FNV_prime return hash 15 | * 16 | * FNV-1a和FNV-1的唯一区别就是xor和multiply的顺序不同,他们所采用的FNV_prime和offset_basis都相同,有人认为FNV-1a在进行小数据(小于4个字节) 17 | * 哈希时有更好的性能。 for each octet_of_data to be hashed 意思是对于你要算哈希值的数,它的每一个字节。 hash = hash * 18 | * FNV_prime,是包含取模运算的,具体看你采用多少位的哈希函数。例如,你用32为哈希,hash = hash * FNV_prime % (2的32次方); hash = hash xor 19 | * octet_of_data,意思是把当前取来的字节和当前的hash值的第八位做抑或运算。 20 | * 21 | * FNV_prime的取值: 32 bit FNV_prime = 2^24 + 2^8 + 0x93 = 16777619 64 bit FNV_prime = 2^40 + 2^8 + 22 | * 0xb3 = 1099511628211 128 bit FNV_prime = 2^88 + 2^8 + 0x3b = 309485009821345068724781371 256 bit 23 | * FNV_prime = 2^168 + 2^8 + 0x63 =374144419156711147060143317175368453031918731002211 512 bit 24 | * FNV_prime = 2^344 + 2^8 + 0x57 = 25 | * 35835915874844867368919076489095108449946327955754392558399825615420669938882575 26 | * 126094039892345713852759 1024 bit FNV_prime = 2^680 + 2^8 + 0x8d = 27 | * 50164565101131186554345988110352789550307653454047907443030175238311120551081474 28 | * 51509157692220295382716162651878526895249385292291816524375083746691371804094271 29 | * 873160484737966720260389217684476157468082573 30 | * 31 | * offset_basis的取值: 32 bit offset_basis = 2166136261 64 bit offset_basis = 14695981039346656037 128 32 | * bit offset_basis = 144066263297769815596495629667062367629 256 bit offset_basis = 33 | * 100029257958052580907070968620625704837092796014241193945225284501741471925557 512 bit 34 | * offset_basis = 96593031294966694980094354007163104660904187456726378961083743294344626579945829 35 | * 32197716438449813051892206539805784495328239340083876191928701583869517785 1024 bit offset_basis 36 | * = 14197795064947621068722070641403218320880622795441933960878474914617582723252296 37 | * 73230371772215086409652120235554936562817466910857181476047101507614802975596980 38 | * 40773201576924585630032153049571501574036444603635505054127112859663616102678680 39 | * 82893823963790439336411086884584107735010676915 40 | * 41 | * 42 | */ 43 | public class HashUtils { 44 | 45 | /** Initial seed for 32-bit hashes. */ 46 | public static final long FNV1_32_INIT = 0x811c9dc5L; 47 | /** Initial seed for 64-bit hashes. */ 48 | public static final long FNV1_64_INIT = 0xcbf29ce484222325L; 49 | 50 | /** 51 | * limited to the lower 32 bits. 52 | * 53 | * @param buf 54 | * @param offset 55 | * @param len 56 | * @return 57 | */ 58 | public static long fnv32(byte[] buf, int offset, int len) { 59 | long seed = FNV1_32_INIT; 60 | for (int i = offset; i < offset + len; i++) { 61 | seed += (seed << 1) + (seed << 4) + (seed << 7) + (seed << 8) + (seed << 24); 62 | seed ^= buf[i]; 63 | } 64 | return (seed & 0x00000000ffffffffL); 65 | } 66 | 67 | /** 68 | * limited to the lower 32 bits. 69 | * 70 | * @param buf 71 | * @param offset 72 | * @param len 73 | * @return 74 | */ 75 | public long fnv32a(byte[] buf, int offset, int len) { 76 | long seed = FNV1_32_INIT; 77 | for (int i = offset; i < offset + len; i++) { 78 | seed ^= buf[i]; 79 | seed += (seed << 1) + (seed << 4) + (seed << 7) + (seed << 8) + (seed << 24); 80 | } 81 | return (seed & 0x00000000ffffffffL); 82 | } 83 | 84 | /** 85 | * limited to the lower 64 bits. 86 | * 87 | * @param buf 88 | * @param offset 89 | * @param len 90 | * @return 91 | */ 92 | public long fnv64(byte[] buf, int offset, int len) { 93 | long seed = FNV1_64_INIT; 94 | for (int i = offset; i < offset + len; i++) { 95 | seed += 96 | (seed << 1) + (seed << 4) + (seed << 5) + (seed << 7) + (seed << 8) 97 | + (seed << 40); 98 | seed ^= buf[i]; 99 | } 100 | return seed; 101 | } 102 | 103 | /** 104 | * limited to the lower 64 bits. 105 | * 106 | * @param buf 107 | * @param offset 108 | * @param len 109 | * @return 110 | */ 111 | public long fnv64a(byte[] buf, int offset, int len) { 112 | long seed = FNV1_64_INIT; 113 | for (int i = offset; i < offset + len; i++) { 114 | seed ^= buf[i]; 115 | seed += 116 | (seed << 1) + (seed << 4) + (seed << 5) + (seed << 7) + (seed << 8) 117 | + (seed << 40); 118 | } 119 | return seed; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/HexDumpUtils.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility; 2 | 3 | /** 4 | * 十六进制工具类 5 | * 6 | * @author zhujuan 7 | * 8 | */ 9 | public class HexDumpUtils { 10 | private final static char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 11 | 'A', 'B', 'C', 'D', 'E', 'F'}; 12 | 13 | public static String dumpHexString(byte[] array) { 14 | return dumpHexString(array, 0, array.length); 15 | } 16 | 17 | public static String dumpHexString(byte[] array, int offset, int length) { 18 | StringBuilder result = new StringBuilder(); 19 | 20 | byte[] line = new byte[16]; 21 | int lineIndex = 0; 22 | 23 | result.append("\n0x"); 24 | result.append(toHexString(offset)); 25 | 26 | for (int i = offset; i < offset + length; i++) { 27 | if (lineIndex == 16) { 28 | result.append(" "); 29 | 30 | for (int j = 0; j < 16; j++) { 31 | if (line[j] > ' ' && line[j] < '~') { 32 | result.append(new String(line, j, 1)); 33 | } else { 34 | result.append("."); 35 | } 36 | } 37 | 38 | result.append("\n0x"); 39 | result.append(toHexString(i)); 40 | lineIndex = 0; 41 | } 42 | 43 | byte b = array[i]; 44 | result.append(" "); 45 | result.append(HEX_DIGITS[(b >>> 4) & 0x0F]); 46 | result.append(HEX_DIGITS[b & 0x0F]); 47 | 48 | line[lineIndex++] = b; 49 | } 50 | 51 | if (lineIndex != 16) { 52 | int count = (16 - lineIndex) * 3; 53 | count++; 54 | for (int i = 0; i < count; i++) { 55 | result.append(" "); 56 | } 57 | 58 | for (int i = 0; i < lineIndex; i++) { 59 | if (line[i] > ' ' && line[i] < '~') { 60 | result.append(new String(line, i, 1)); 61 | } else { 62 | result.append("."); 63 | } 64 | } 65 | } 66 | 67 | return result.toString(); 68 | } 69 | 70 | public static String toHexString(byte b) { 71 | return toHexString(toByteArray(b)); 72 | } 73 | 74 | public static String toHexString(byte[] array) { 75 | return toHexString(array, 0, array.length); 76 | } 77 | 78 | public static String toHexString(byte[] array, int offset, int length) { 79 | char[] buf = new char[length * 2]; 80 | 81 | int bufIndex = 0; 82 | for (int i = offset; i < offset + length; i++) { 83 | byte b = array[i]; 84 | buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F]; 85 | buf[bufIndex++] = HEX_DIGITS[b & 0x0F]; 86 | } 87 | 88 | return new String(buf); 89 | } 90 | 91 | public static String toHexString(int i) { 92 | return toHexString(toByteArray(i)); 93 | } 94 | 95 | public static byte[] toByteArray(byte b) { 96 | byte[] array = new byte[1]; 97 | array[0] = b; 98 | return array; 99 | } 100 | 101 | public static byte[] toByteArray(int i) { 102 | byte[] array = new byte[4]; 103 | 104 | array[3] = (byte) (i & 0xFF); 105 | array[2] = (byte) ((i >> 8) & 0xFF); 106 | array[1] = (byte) ((i >> 16) & 0xFF); 107 | array[0] = (byte) ((i >> 24) & 0xFF); 108 | 109 | return array; 110 | } 111 | 112 | private static int toByte(char c) { 113 | if (c >= '0' && c <= '9') 114 | return (c - '0'); 115 | if (c >= 'A' && c <= 'F') 116 | return (c - 'A' + 10); 117 | if (c >= 'a' && c <= 'f') 118 | return (c - 'a' + 10); 119 | 120 | throw new RuntimeException("Invalid hex char '" + c + "'"); 121 | } 122 | 123 | public static byte[] hexStringToByteArray(String hexString) { 124 | int length = hexString.length(); 125 | byte[] buffer = new byte[length / 2]; 126 | 127 | for (int i = 0; i < length; i += 2) { 128 | buffer[i / 2] = 129 | (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString.charAt(i + 1))); 130 | } 131 | 132 | return buffer; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/JSONUtils.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.io.Writer; 7 | import java.nio.charset.Charset; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import com.fasterxml.jackson.core.JsonFactory; 12 | import com.fasterxml.jackson.core.JsonGenerator; 13 | import com.fasterxml.jackson.core.JsonParseException; 14 | import com.fasterxml.jackson.core.JsonParser; 15 | import com.fasterxml.jackson.core.JsonProcessingException; 16 | import com.fasterxml.jackson.databind.DeserializationFeature; 17 | import com.fasterxml.jackson.databind.JsonMappingException; 18 | import com.fasterxml.jackson.databind.JsonNode; 19 | import com.fasterxml.jackson.databind.ObjectMapper; 20 | import com.fasterxml.jackson.databind.ObjectWriter; 21 | import com.fasterxml.jackson.databind.type.TypeFactory; 22 | 23 | /** 24 | * 25 | *
 26 |  * json工具类
 27 |  * 
 28 |  * @author zhujuan
 29 |  * 
30 | */ 31 | public class JSONUtils { 32 | 33 | public static final String EMPTY_JSON = "{}"; 34 | public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); 35 | 36 | private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); 37 | private static final ObjectWriter WRITER = OBJECT_MAPPER.writer(); 38 | private static final ObjectWriter PRETTY_WRITER = 39 | OBJECT_MAPPER.writerWithDefaultPrettyPrinter(); 40 | 41 | static { 42 | OBJECT_MAPPER.configure(JsonParser.Feature.ALLOW_COMMENTS, true); 43 | OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 44 | } 45 | 46 | public static String toJsonPrettyString(Object value) { 47 | if (value == null) { 48 | return EMPTY_JSON; 49 | } 50 | try { 51 | return PRETTY_WRITER.writeValueAsString(value); 52 | } catch (Exception e) { 53 | throw new IllegalStateException(e); 54 | } 55 | } 56 | 57 | public static String toJsonString(Object value) { 58 | if (value == null) { 59 | return EMPTY_JSON; 60 | } 61 | try { 62 | return WRITER.writeValueAsString(value); 63 | } catch (Exception e) { 64 | throw new IllegalStateException(e); 65 | } 66 | } 67 | 68 | public static T fromJsonString(String json, Class clazz) { 69 | if (json == null || clazz == null) { 70 | return null; 71 | } 72 | try { 73 | return OBJECT_MAPPER.readValue(json, clazz); 74 | } catch (Exception e) { 75 | throw new RuntimeException("Unable to parse Json String.", e); 76 | } 77 | } 78 | 79 | public static List fromJsonString2List(String json, Class clazz) { 80 | if (json == null || clazz == null) { 81 | return null; 82 | } 83 | try { 84 | return OBJECT_MAPPER.readValue(json, 85 | TypeFactory.defaultInstance().constructCollectionType(List.class, clazz)); 86 | } catch (Exception e) { 87 | throw new RuntimeException("Unable to parse Json String.", e); 88 | } 89 | } 90 | 91 | public static Map fromJsonString2Map(String json, Class keyClazz, Class valueClazz) { 92 | if (json == null || keyClazz == null || valueClazz == null) { 93 | return null; 94 | } 95 | try { 96 | return OBJECT_MAPPER.readValue(json, TypeFactory.defaultInstance().constructMapType(Map.class, keyClazz, valueClazz)); 97 | } catch (Exception e) { 98 | throw new RuntimeException("Unable to parse Json String.", e); 99 | } 100 | } 101 | 102 | public static JsonNode jsonNodeOf(String json) { 103 | return fromJsonString(json, JsonNode.class); 104 | } 105 | 106 | public static JsonGenerator jsonGeneratorOf(Writer writer) throws IOException { 107 | return new JsonFactory().createGenerator(writer); 108 | } 109 | 110 | public static T loadFrom(File file, Class clazz) throws IOException { 111 | try { 112 | return OBJECT_MAPPER.readValue(file, clazz); 113 | } catch (IOException e) { 114 | throw e; 115 | } catch (Exception e) { 116 | throw new IllegalStateException(e); 117 | } 118 | } 119 | 120 | public static void load(InputStream input, Object obj) 121 | throws IOException, JsonProcessingException { 122 | OBJECT_MAPPER.readerForUpdating(obj).readValue(input); 123 | } 124 | 125 | public static T loadFrom(InputStream input, Class clazz) 126 | throws JsonParseException, JsonMappingException, IOException { 127 | return OBJECT_MAPPER.readValue(input, clazz); 128 | } 129 | 130 | public static ObjectMapper getObjectMapper() { 131 | return OBJECT_MAPPER; 132 | } 133 | 134 | public static ObjectWriter getWriter() { 135 | return WRITER; 136 | } 137 | 138 | public static ObjectWriter getPrettyWriter() { 139 | return PRETTY_WRITER; 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/LRUCache.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.concurrent.locks.Lock; 5 | import java.util.concurrent.locks.ReentrantLock; 6 | 7 | public class LRUCache extends LinkedHashMap { 8 | 9 | private static final long serialVersionUID = 1L; 10 | 11 | private static final float DEFAULT_LOAD_FACTOR = 0.75f; 12 | 13 | private static final int DEFAULT_MAX_CAPACITY = 1000; 14 | 15 | private volatile int maxCapacity; 16 | 17 | private final Lock lock = new ReentrantLock(); 18 | 19 | public LRUCache() { 20 | this(DEFAULT_MAX_CAPACITY); 21 | } 22 | 23 | public LRUCache(int maxCapacity) { 24 | super(16, DEFAULT_LOAD_FACTOR, true); 25 | this.maxCapacity = maxCapacity; 26 | } 27 | 28 | @Override 29 | protected boolean removeEldestEntry(java.util.Map.Entry eldest) { 30 | return size() > maxCapacity; 31 | } 32 | 33 | @Override 34 | public boolean containsKey(Object key) { 35 | try { 36 | lock.lock(); 37 | return super.containsKey(key); 38 | } finally { 39 | lock.unlock(); 40 | } 41 | } 42 | 43 | @Override 44 | public V get(Object key) { 45 | try { 46 | lock.lock(); 47 | return super.get(key); 48 | } finally { 49 | lock.unlock(); 50 | } 51 | } 52 | 53 | @Override 54 | public V put(K key, V value) { 55 | try { 56 | lock.lock(); 57 | return super.put(key, value); 58 | } finally { 59 | lock.unlock(); 60 | } 61 | } 62 | 63 | @Override 64 | public V remove(Object key) { 65 | try { 66 | lock.lock(); 67 | return super.remove(key); 68 | } finally { 69 | lock.unlock(); 70 | } 71 | } 72 | 73 | @Override 74 | public int size() { 75 | try { 76 | lock.lock(); 77 | return super.size(); 78 | } finally { 79 | lock.unlock(); 80 | } 81 | } 82 | 83 | @Override 84 | public void clear() { 85 | try { 86 | lock.lock(); 87 | super.clear(); 88 | } finally { 89 | lock.unlock(); 90 | } 91 | } 92 | 93 | public int getMaxCapacity() { 94 | return maxCapacity; 95 | } 96 | 97 | public void setMaxCapacity(int maxCapacity) { 98 | this.maxCapacity = maxCapacity; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/NamedDaemonThreadFactory.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility; 2 | 3 | import java.util.concurrent.ThreadFactory; 4 | import java.util.concurrent.atomic.AtomicInteger; 5 | 6 | /** 7 | * 自定义命合的守护ThreadFactory 8 | * 9 | * @author zhujuan 10 | * 11 | */ 12 | public class NamedDaemonThreadFactory implements ThreadFactory { 13 | 14 | private static final AtomicInteger COUNTER = new AtomicInteger(0); 15 | 16 | private final String prefix; 17 | 18 | public NamedDaemonThreadFactory(String prefix) { 19 | this.prefix = prefix; 20 | } 21 | 22 | @Override 23 | public Thread newThread(Runnable runnable) { 24 | Thread t = new Thread(runnable); 25 | t.setName(prefix + "-" + COUNTER.incrementAndGet()); 26 | t.setDaemon(true); 27 | return t; 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/NamedThreadFactory.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility; 2 | 3 | import java.util.concurrent.ThreadFactory; 4 | import java.util.concurrent.atomic.AtomicInteger; 5 | 6 | /** 7 | * 自定义命名的ThreadFactory 8 | * 9 | * @author zhujuan 10 | */ 11 | public class NamedThreadFactory implements ThreadFactory { 12 | private static final AtomicInteger poolNumber = new AtomicInteger(1); 13 | private final AtomicInteger threadNumber = new AtomicInteger(1); 14 | private final ThreadGroup group; 15 | private final String namePrefix; 16 | 17 | public NamedThreadFactory(String prefix) { 18 | SecurityManager s = System.getSecurityManager(); 19 | group = (s != null) ? s.getThreadGroup() : 20 | Thread.currentThread().getThreadGroup(); 21 | namePrefix = prefix + 22 | poolNumber.getAndIncrement() + 23 | "-thread-"; 24 | } 25 | 26 | public Thread newThread(Runnable r) { 27 | Thread t = new Thread(group, r, 28 | namePrefix + threadNumber.getAndIncrement(), 29 | 0); 30 | if (t.isDaemon()) 31 | t.setDaemon(false); 32 | if (t.getPriority() != Thread.NORM_PRIORITY) 33 | t.setPriority(Thread.NORM_PRIORITY); 34 | return t; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/PackageUtils.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility; 2 | 3 | import java.io.IOException; 4 | import java.util.Collection; 5 | import java.util.HashSet; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.core.io.Resource; 10 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 11 | import org.springframework.core.io.support.ResourcePatternResolver; 12 | import org.springframework.core.type.classreading.CachingMetadataReaderFactory; 13 | import org.springframework.core.type.classreading.MetadataReader; 14 | import org.springframework.core.type.classreading.MetadataReaderFactory; 15 | import org.springframework.util.ClassUtils; 16 | import org.springframework.util.SystemPropertyUtils; 17 | 18 | /** 19 | * 类包工具类 20 | * 21 | * @author zhujuan 22 | */ 23 | public class PackageUtils { 24 | private static final Logger LOGGER = LoggerFactory.getLogger(PackageUtils.class); 25 | private static final ResourcePatternResolver resourcePatternResolver = 26 | new PathMatchingResourcePatternResolver(); 27 | private static final MetadataReaderFactory metadataReaderFactory = 28 | new CachingMetadataReaderFactory(resourcePatternResolver); 29 | // 资源的格式 ant匹配符号格式 30 | private static final String DEFAULT_RESOURCE_PATTERN = "**/*.class"; 31 | 32 | /** 33 | * 扫描指定包中所有的类(包括子类) 34 | * 35 | * @param packageNames 包名支持权限定包名和ant风格匹配符(同spring) 36 | * @return 37 | */ 38 | public static Collection> scanPackages(String... packageNames) { 39 | Collection> clazzCollection = new HashSet>(); 40 | 41 | String[] arrayOfString = packageNames; 42 | int j = packageNames.length; 43 | for (int i = 0; i < j; i++) { 44 | String packageName = arrayOfString[i]; 45 | try { 46 | String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX 47 | + resolveBasePackage(packageName) + "/" + DEFAULT_RESOURCE_PATTERN; 48 | Resource[] resources = resourcePatternResolver.getResources(packageSearchPath); 49 | for (Resource resource : resources) { 50 | String className = ""; 51 | try { 52 | if (resource.isReadable()) { 53 | MetadataReader metaReader = 54 | metadataReaderFactory.getMetadataReader(resource); 55 | className = metaReader.getClassMetadata().getClassName(); 56 | 57 | Class clazz = Class.forName(className); 58 | clazzCollection.add(clazz); 59 | } 60 | } catch (ClassNotFoundException e) { 61 | LOGGER.error("类 {} 不存在!", className); 62 | throw new RuntimeException(e); 63 | } 64 | } 65 | } catch (IOException e) { 66 | LOGGER.error("扫描包 {} 出错!", packageName); 67 | throw new RuntimeException(e); 68 | } 69 | } 70 | return clazzCollection; 71 | } 72 | 73 | /** 74 | * 将包名转换成目录名(com.xxx-->com/xxx) 75 | * 76 | * @param basePackage 包名 77 | * @return 78 | */ 79 | private static String resolveBasePackage(String basePackage) { 80 | String placeHolderReplace = SystemPropertyUtils.resolvePlaceholders(basePackage); 81 | return ClassUtils.convertClassNameToResourcePath(placeHolderReplace); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/Splitable.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility; 2 | 3 | /** 4 | * 包含可分割字符串属性的对象 5 | */ 6 | public interface Splitable { 7 | 8 | /** 9 | * : 10 | */ 11 | String DELIMITER_ARGS = ":"; 12 | 13 | /** 14 | * , 15 | */ 16 | String BETWEEN_ITEMS = ","; 17 | 18 | /** 19 | * \\| 20 | */ 21 | String ELEMENT_SPLIT = "\\|"; 22 | 23 | /** 24 | * | 25 | */ 26 | String ELEMENT_DELIMITER = "|"; 27 | 28 | /** 29 | * _ 30 | */ 31 | String ATTRIBUTE_SPLIT = "_"; 32 | 33 | /** 34 | * [ 35 | */ 36 | String LEFT_PARENTH_SPLIT = "["; 37 | 38 | /** 39 | * ] 40 | */ 41 | String RIGHT_PARENTH_SPLIT = "]"; 42 | 43 | /** 44 | * _[ 45 | */ 46 | String LEFT_ELEMENT_SPLIT = "_["; 47 | 48 | /** 49 | * # 50 | */ 51 | String ATTRIBUTE_SPLITE_1 = "#"; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/StopWatch.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one or more contributor license 3 | * agreements. See the NOTICE file distributed with this work for additional information regarding 4 | * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the 5 | * "License"); you may not use this file except in compliance with the License. You may obtain a 6 | * copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software distributed under the License 11 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 12 | * or implied. See the License for the specific language governing permissions and limitations under 13 | * the License. 14 | */ 15 | package org.chinasb.common.utility; 16 | 17 | /** 18 | * A very simple stop watch. 19 | *

20 | * This implementation is not thread safe and can only time one task at any given time. 21 | */ 22 | public final class StopWatch { 23 | 24 | private long start; 25 | private long stop; 26 | 27 | /** 28 | * Starts the stop watch 29 | */ 30 | public StopWatch() { 31 | this(true); 32 | } 33 | 34 | /** 35 | * Creates the stop watch 36 | * 37 | * @param started whether it should start immediately 38 | */ 39 | public StopWatch(boolean started) { 40 | if (started) { 41 | restart(); 42 | } 43 | } 44 | 45 | /** 46 | * Starts or restarts the stop watch 47 | */ 48 | public void restart() { 49 | start = System.currentTimeMillis(); 50 | stop = 0; 51 | } 52 | 53 | /** 54 | * Stops the stop watch 55 | * 56 | * @return the time taken in milliseconds. 57 | */ 58 | public long stop() { 59 | stop = System.currentTimeMillis(); 60 | return taken(); 61 | } 62 | 63 | /** 64 | * Returns the time taken in milliseconds. 65 | * 66 | * @return time in milliseconds 67 | */ 68 | public long taken() { 69 | if (start > 0 && stop > 0) { 70 | return stop - start; 71 | } else if (start > 0) { 72 | return System.currentTimeMillis() - start; 73 | } else { 74 | return 0; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/TimeUtils.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility; 2 | 3 | import java.text.DecimalFormat; 4 | import java.text.DecimalFormatSymbols; 5 | import java.text.NumberFormat; 6 | import java.time.Instant; 7 | import java.time.LocalDate; 8 | import java.time.LocalDateTime; 9 | import java.time.ZoneId; 10 | import java.time.format.DateTimeFormatter; 11 | import java.time.temporal.ChronoUnit; 12 | import java.util.Locale; 13 | 14 | /** 15 | * 时间工具类 16 | * 17 | * @author zhujuan 18 | * 19 | */ 20 | public class TimeUtils { 21 | 22 | private TimeUtils() {} 23 | 24 | /** 25 | * Prints the duration in a human readable format as X days Y hours Z minutes etc. 26 | * 27 | * @param uptime the up-time in milliseconds 28 | * 29 | * @return the time used for displaying on screen or in logs 30 | */ 31 | public static String printDuration(double uptime) { 32 | // Code taken from Karaf 33 | // https://svn.apache.org/repos/asf/karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/InfoAction.java 34 | 35 | NumberFormat fmtI = new DecimalFormat("###,###", new DecimalFormatSymbols(Locale.ENGLISH)); 36 | NumberFormat fmtD = 37 | new DecimalFormat("###,##0.000", new DecimalFormatSymbols(Locale.ENGLISH)); 38 | 39 | uptime /= 1000; 40 | if (uptime < 60) { 41 | return fmtD.format(uptime) + " seconds"; 42 | } 43 | uptime /= 60; 44 | if (uptime < 60) { 45 | long minutes = (long) uptime; 46 | String s = fmtI.format(minutes) + (minutes > 1 ? " minutes" : " minute"); 47 | return s; 48 | } 49 | uptime /= 60; 50 | if (uptime < 24) { 51 | long hours = (long) uptime; 52 | long minutes = (long) ((uptime - hours) * 60); 53 | String s = fmtI.format(hours) + (hours > 1 ? " hours" : " hour"); 54 | if (minutes != 0) { 55 | s += " " + fmtI.format(minutes) + (minutes > 1 ? " minutes" : " minute"); 56 | } 57 | return s; 58 | } 59 | uptime /= 24; 60 | long days = (long) uptime; 61 | long hours = (long) ((uptime - days) * 24); 62 | String s = fmtI.format(days) + (days > 1 ? " days" : " day"); 63 | if (hours != 0) { 64 | s += " " + fmtI.format(hours) + (hours > 1 ? " hours" : " hour"); 65 | } 66 | 67 | return s; 68 | } 69 | 70 | /** 71 | * 判断日期是否今天 72 | * 73 | * @param date 74 | * @return 75 | */ 76 | public static boolean isToday(LocalDate date) { 77 | return date.compareTo(LocalDate.now()) == 0; 78 | } 79 | 80 | /** 81 | * 计算两个相隔时间 82 | * 83 | * @param start 开始时间 84 | * @param end 结束时间 85 | * @param unit 时间类型 86 | * @return 87 | */ 88 | public static long between(LocalDateTime start, LocalDateTime end, ChronoUnit unit) { 89 | return unit.between(start, end); 90 | } 91 | 92 | /** 93 | * 计算开始时间到今天相隔时间 94 | * 95 | * @param start 开始时间 96 | * @param unit 时间类型 97 | * @return 98 | */ 99 | public static long betweenAtToday(LocalDateTime start, ChronoUnit unit) { 100 | return between(start, LocalDateTime.now(), unit); 101 | } 102 | 103 | /** 104 | * 计算今天零点开始到现在的相隔时间 105 | * 106 | * @param unit 时间类型 107 | * @return 108 | */ 109 | public static long betweenAtStartOfDay(ChronoUnit unit) { 110 | return between(LocalDate.now().atStartOfDay(), LocalDateTime.now(), unit); 111 | } 112 | 113 | /** 114 | * 将时间毫秒单位转换成秒单位 115 | * 116 | * @param millis 117 | * @return 118 | */ 119 | public static long toSecond(long... millis) { 120 | long second = 0L; 121 | if ((millis != null) && (millis.length > 0)) { 122 | for (long time : millis) { 123 | second += time / 1000L; 124 | } 125 | } 126 | return second; 127 | } 128 | 129 | /** 130 | * 将时间毫秒单位转换成LocalDateTime 131 | * 132 | * @param time 133 | * @return 134 | */ 135 | public static LocalDateTime of(long timeInMilli) { 136 | Instant instant = Instant.ofEpochMilli(timeInMilli); 137 | return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); 138 | } 139 | 140 | public static long of(LocalDateTime time) { 141 | return time.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); 142 | } 143 | 144 | public static String date2String(LocalDateTime time, String format) { 145 | DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format); 146 | return time.format(formatter); 147 | } 148 | 149 | public static LocalDateTime string2Date(String time, String format) { 150 | DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format); 151 | return LocalDateTime.parse(time, formatter); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/UUIDUtils.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility; 2 | 3 | import java.math.BigInteger; 4 | import java.security.SecureRandom; 5 | import java.util.Random; 6 | import java.util.UUID; 7 | import java.util.concurrent.locks.ReentrantLock; 8 | 9 | /** 10 | * Helper for creating random and Type 1 (time-based) UUIDs. 11 | * 12 | * @author Jon Brisbin 13 | */ 14 | public abstract class UUIDUtils { 15 | 16 | private static boolean IS_THREADLOCALRANDOM_AVAILABLE = false; 17 | private static Random random; 18 | private static final long leastSigBits; 19 | private static final ReentrantLock lock = new ReentrantLock(); 20 | private static long lastTime; 21 | 22 | static { 23 | try { 24 | IS_THREADLOCALRANDOM_AVAILABLE = 25 | null != UUIDUtils.class.getClassLoader().loadClass( 26 | "java.util.concurrent.ThreadLocalRandom"); 27 | } catch (ClassNotFoundException e) { 28 | } 29 | 30 | byte[] seed = new SecureRandom().generateSeed(8); 31 | leastSigBits = new BigInteger(seed).longValue(); 32 | if (!IS_THREADLOCALRANDOM_AVAILABLE) { 33 | random = new Random(leastSigBits); 34 | } 35 | } 36 | 37 | private UUIDUtils() {} 38 | 39 | /** 40 | * Create a new random UUID. 41 | * 42 | * @return the new UUID 43 | */ 44 | public static UUID random() { 45 | byte[] randomBytes = new byte[16]; 46 | if (IS_THREADLOCALRANDOM_AVAILABLE) { 47 | java.util.concurrent.ThreadLocalRandom.current().nextBytes(randomBytes); 48 | } else { 49 | random.nextBytes(randomBytes); 50 | } 51 | 52 | long mostSigBits = 0; 53 | for (int i = 0; i < 8; i++) { 54 | mostSigBits = (mostSigBits << 8) | (randomBytes[i] & 0xff); 55 | } 56 | long leastSigBits = 0; 57 | for (int i = 8; i < 16; i++) { 58 | leastSigBits = (leastSigBits << 8) | (randomBytes[i] & 0xff); 59 | } 60 | 61 | return new UUID(mostSigBits, leastSigBits); 62 | } 63 | 64 | /** 65 | * Create a new time-based UUID. 66 | * 67 | * @return the new UUID 68 | */ 69 | public static UUID create() { 70 | long timeMillis = (System.currentTimeMillis() * 10000) + 0x01B21DD213814000L; 71 | 72 | lock.lock(); 73 | try { 74 | if (timeMillis > lastTime) { 75 | lastTime = timeMillis; 76 | } else { 77 | timeMillis = ++lastTime; 78 | } 79 | } finally { 80 | lock.unlock(); 81 | } 82 | 83 | // time low 84 | long mostSigBits = timeMillis << 32; 85 | 86 | // time mid 87 | mostSigBits |= (timeMillis & 0xFFFF00000000L) >> 16; 88 | 89 | // time hi and version 90 | mostSigBits |= 0x1000 | ((timeMillis >> 48) & 0x0FFF); // version 1 91 | 92 | return new UUID(mostSigBits, leastSigBits); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/BigDecimalHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | import java.math.BigDecimal; 4 | 5 | /** 6 | * A holder for BigDecimals. 7 | * 8 | * @author zhujuan 9 | */ 10 | public final class BigDecimalHolder implements Holder { 11 | private BigDecimal value; 12 | 13 | public BigDecimalHolder() { 14 | 15 | } 16 | 17 | public BigDecimalHolder(BigDecimal value) { 18 | this.value = value; 19 | } 20 | 21 | public BigDecimal get() { 22 | return value; 23 | } 24 | 25 | public void set(BigDecimal value) { 26 | this.value = value; 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return String.valueOf(value); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/BigIntegerHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | import java.math.BigInteger; 4 | 5 | /** 6 | * A holder for BigIntegers. 7 | * 8 | * @author zhujuan 9 | */ 10 | public final class BigIntegerHolder implements Holder { 11 | private BigInteger value; 12 | 13 | public BigIntegerHolder() { 14 | 15 | } 16 | 17 | public BigIntegerHolder(BigInteger value) { 18 | this.value = value; 19 | } 20 | 21 | public BigInteger get() { 22 | return value; 23 | } 24 | 25 | public void set(BigInteger value) { 26 | this.value = value; 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return String.valueOf(value); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/BooleanHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for booleans. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class BooleanHolder implements Holder { 9 | private boolean value; 10 | 11 | public BooleanHolder() { 12 | 13 | } 14 | 15 | public BooleanHolder(boolean value) { 16 | this.value = value; 17 | } 18 | 19 | public boolean get() { 20 | return value; 21 | } 22 | 23 | public void set(boolean value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return String.valueOf(value); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/BooleanWrapperHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for Booleans. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class BooleanWrapperHolder implements Holder { 9 | private Boolean value; 10 | 11 | public BooleanWrapperHolder() { 12 | 13 | } 14 | 15 | public BooleanWrapperHolder(Boolean value) { 16 | this.value = value; 17 | } 18 | 19 | public Boolean get() { 20 | return value; 21 | } 22 | 23 | public void set(Boolean value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return value.toString(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/ByteArrayHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for byte[]s. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class ByteArrayHolder implements Holder { 9 | private byte[] value; 10 | 11 | public ByteArrayHolder() { 12 | 13 | } 14 | 15 | public ByteArrayHolder(byte[] value) { 16 | this.value = value; 17 | } 18 | 19 | public byte[] get() { 20 | return value; 21 | } 22 | 23 | public void set(byte[] value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return new String(value); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/ByteHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for bytes. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class ByteHolder implements Holder { 9 | private byte value; 10 | 11 | public ByteHolder() { 12 | 13 | } 14 | 15 | public ByteHolder(byte value) { 16 | this.value = value; 17 | } 18 | 19 | public byte get() { 20 | return value; 21 | } 22 | 23 | public void set(byte value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return String.valueOf(value); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/ByteWrapperHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for Bytes. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class ByteWrapperHolder implements Holder { 9 | private Byte value; 10 | 11 | public ByteWrapperHolder() { 12 | 13 | } 14 | 15 | public ByteWrapperHolder(Byte value) { 16 | this.value = value; 17 | } 18 | 19 | public Byte get() { 20 | return value; 21 | } 22 | 23 | public void set(Byte value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return value.toString(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/DoubleHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for doubles. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class DoubleHolder implements Holder { 9 | private double value; 10 | 11 | public DoubleHolder() { 12 | 13 | } 14 | 15 | public DoubleHolder(double value) { 16 | this.value = value; 17 | } 18 | 19 | public double get() { 20 | return value; 21 | } 22 | 23 | public void set(double value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return String.valueOf(value); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/DoubleWrapperHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for Doubles. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class DoubleWrapperHolder implements Holder { 9 | private Double value; 10 | 11 | public DoubleWrapperHolder() { 12 | 13 | } 14 | 15 | public DoubleWrapperHolder(Double value) { 16 | this.value = value; 17 | } 18 | 19 | public Double get() { 20 | return value; 21 | } 22 | 23 | public void set(Double value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return value.toString(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/FloatHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for floats. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class FloatHolder implements Holder { 9 | private float value; 10 | 11 | public FloatHolder() { 12 | 13 | } 14 | 15 | public FloatHolder(float value) { 16 | this.value = value; 17 | } 18 | 19 | public float get() { 20 | return value; 21 | } 22 | 23 | public void set(float value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return String.valueOf(value); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/FloatWrapperHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for Floats. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class FloatWrapperHolder implements Holder { 9 | private Float value; 10 | 11 | public FloatWrapperHolder() { 12 | 13 | } 14 | 15 | public FloatWrapperHolder(Float value) { 16 | this.value = value; 17 | } 18 | 19 | public Float get() { 20 | return value; 21 | } 22 | 23 | public void set(Float value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return value.toString(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/Holder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * 5 | * @author zhujuan 6 | */ 7 | public interface Holder { 8 | } 9 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/IntHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for ints. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class IntHolder implements Holder { 9 | private int value; 10 | 11 | public IntHolder() { 12 | 13 | } 14 | 15 | public IntHolder(int value) { 16 | this.value = value; 17 | } 18 | 19 | public int get() { 20 | return value; 21 | } 22 | 23 | public void set(int value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return String.valueOf(value); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/IntegerWrapperHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for Integers. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class IntegerWrapperHolder implements Holder { 9 | private Integer value; 10 | 11 | public IntegerWrapperHolder() { 12 | 13 | } 14 | 15 | public IntegerWrapperHolder(Integer value) { 16 | this.value = value; 17 | } 18 | 19 | public Integer get() { 20 | return value; 21 | } 22 | 23 | public void set(Integer value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return value.toString(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/LongHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for longs. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class LongHolder implements Holder { 9 | private long value; 10 | 11 | public LongHolder() { 12 | 13 | } 14 | 15 | public LongHolder(long value) { 16 | this.value = value; 17 | } 18 | 19 | public long get() { 20 | return value; 21 | } 22 | 23 | public void set(long value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return String.valueOf(value); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/LongWrapperHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for Longs. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class LongWrapperHolder implements Holder { 9 | private Long value; 10 | 11 | public LongWrapperHolder() { 12 | 13 | } 14 | 15 | public LongWrapperHolder(Long value) { 16 | this.value = value; 17 | } 18 | 19 | public Long get() { 20 | return value; 21 | } 22 | 23 | public void set(Long value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return value.toString(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/ObjectHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for Objects. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class ObjectHolder implements Holder { 9 | private T value; 10 | 11 | public ObjectHolder() { 12 | 13 | } 14 | 15 | public ObjectHolder(T value) { 16 | this.value = value; 17 | } 18 | 19 | public T get() { 20 | return value; 21 | } 22 | 23 | public void set(T value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return value.toString(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/ShortHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for shorts. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class ShortHolder implements Holder { 9 | private short value; 10 | 11 | public ShortHolder() { 12 | 13 | } 14 | 15 | public ShortHolder(short value) { 16 | this.value = value; 17 | } 18 | 19 | public short get() { 20 | return value; 21 | } 22 | 23 | public void set(short value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return String.valueOf(value); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/ShortWrapperHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for Shorts. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class ShortWrapperHolder implements Holder { 9 | private Short value; 10 | 11 | public ShortWrapperHolder() { 12 | 13 | } 14 | 15 | public ShortWrapperHolder(Short value) { 16 | this.value = value; 17 | } 18 | 19 | public Short get() { 20 | return value; 21 | } 22 | 23 | public void set(Short value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return value.toString(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/common-utility/src/main/java/org/chinasb/common/utility/holders/StringHolder.java: -------------------------------------------------------------------------------- 1 | package org.chinasb.common.utility.holders; 2 | 3 | /** 4 | * A holder for Strings. 5 | * 6 | * @author zhujuan 7 | */ 8 | public final class StringHolder implements Holder { 9 | private String value; 10 | 11 | public StringHolder() { 12 | 13 | } 14 | 15 | public StringHolder(String value) { 16 | this.value = value; 17 | } 18 | 19 | public String get() { 20 | return value; 21 | } 22 | 23 | public void set(String value) { 24 | this.value = value; 25 | } 26 | 27 | @Override 28 | public String toString() { 29 | return value; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /sb-commons/sb-commons/.gitignore: -------------------------------------------------------------------------------- 1 | /.settings 2 | /.project 3 | /target 4 | /.classpath 5 | -------------------------------------------------------------------------------- /sb-commons/sb-commons/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.chinasb 8 | sb-commons-parent 9 | 0.0.1-SNAPSHOT 10 | 11 | sb-commons 12 | jar 13 | ${project.artifactId} 14 | The all in one project of sb-commons 15 | 16 | false 17 | 18 | 19 | 20 | ${project.groupId} 21 | common-basedb 22 | ${project.version} 23 | 24 | 25 | ${project.groupId} 26 | common-db 27 | ${project.version} 28 | 29 | 30 | ${project.groupId} 31 | common-jreloader 32 | ${project.version} 33 | 34 | 35 | ${project.groupId} 36 | common-lock 37 | ${project.version} 38 | 39 | 40 | ${project.groupId} 41 | common-rhino 42 | ${project.version} 43 | 44 | 45 | ${project.groupId} 46 | common-socket 47 | ${project.version} 48 | 49 | 50 | ${project.groupId} 51 | common-threadpool 52 | ${project.version} 53 | 54 | 55 | ${project.groupId} 56 | common-utility 57 | ${project.version} 58 | 59 | 60 | 61 | 62 | 63 | maven-source-plugin 64 | 65 | 66 | attach-sources 67 | verify 68 | 69 | jar-no-fork 70 | 71 | 72 | 73 | 74 | 75 | maven-javadoc-plugin 76 | 77 | 78 | attach-javadoc 79 | deploy 80 | 81 | jar 82 | 83 | 84 | 85 | 86 | public 87 | ${file_encoding} 88 | ${file_encoding} 89 | ${file_encoding} 90 | org.chinasb.org.* 91 | 92 | http://docs.oracle.com/javase/6/docs/api 93 | 94 | 95 | 96 | 97 | org.apache.maven.plugins 98 | maven-shade-plugin 99 | 1.4 100 | 101 | 102 | package 103 | 104 | shade 105 | 106 | 107 | true 108 | true 109 | 110 | 111 | org.chinasb:common-basedb 112 | org.chinasb:common-db 113 | org.chinasb:common-jreloader 114 | org.chinasb:common-lock 115 | org.chinasb:common-rhino 116 | org.chinasb:common-socket 117 | org.chinasb:common-threadpool 118 | org.chinasb:common-utility 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | --------------------------------------------------------------------------------