├── .gitignore ├── LICENSE ├── README.md ├── saas-mongo ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── hitler │ └── core │ ├── beans │ ├── BaseDTO.java │ ├── BaseDocument.java │ ├── BaseVO.java │ └── Opations.java │ ├── db │ ├── entity │ │ ├── Docs.java │ │ └── SequenceId.java │ ├── enums │ │ └── BaseEnums.java │ └── mongo │ │ ├── BHBMongoMappingContext.java │ │ ├── BHBMongoTemplate.java │ │ ├── MongoConfiguation.java │ │ ├── RoutingDBContextHolder.java │ │ ├── RoutingDBFactory.java │ │ ├── StringToDateConverter.java │ │ └── sequence │ │ ├── IDNo.java │ │ └── SequenceOption.java │ ├── ex │ ├── BHBException.java │ ├── ConfigException.java │ ├── DataNotFoundBHBException.java │ ├── HttpException.java │ ├── OrderHookBHBException.java │ ├── OrderHookUnknowBHBException.java │ └── UserNotFoundBHBException.java │ ├── executor │ └── CoreExecutor.java │ ├── resp │ ├── Code.java │ ├── MsgCode.java │ └── Result.java │ ├── services │ ├── BaseService.java │ └── GenericService.java │ └── utils │ └── EncryptUtil.java └── saas-mycat ├── README.md ├── pom.xml └── saas ├── pom.xml └── src ├── main ├── java │ ├── META-INF │ │ ├── MANIFEST.MF │ │ ├── dubbo │ │ │ └── com.alibaba.dubbo.rpc.Filter │ │ └── persistence.xml │ └── com │ │ └── hitler │ │ ├── common │ │ ├── aop │ │ │ ├── CheageSchemaInterceptor.java │ │ │ ├── RetriableTransaction.java │ │ │ ├── RetriableTransactionInterceptor.java │ │ │ └── ServiceInterceptor.java │ │ ├── dozer │ │ │ └── converters │ │ │ │ └── DateTimeConverter.java │ │ ├── dto │ │ │ ├── PersistentDTO.java │ │ │ ├── TransientDTO.java │ │ │ ├── annotation │ │ │ │ └── DisallowedField.java │ │ │ └── support │ │ │ │ ├── GenericDTO.java │ │ │ │ ├── GenericTable.java │ │ │ │ ├── IGenericDTO.java │ │ │ │ ├── IGenericTable.java │ │ │ │ └── PaginationAoDataDTO.java │ │ ├── dubbo │ │ │ ├── RpcContextAttachment.java │ │ │ └── filter │ │ │ │ └── AuthenticationFilter.java │ │ ├── exception │ │ │ ├── BusinessException.java │ │ │ └── EntityNotExistsException.java │ │ ├── model │ │ │ ├── annotation │ │ │ │ ├── Checkable.java │ │ │ │ └── Checked.java │ │ │ ├── auditing │ │ │ │ └── DefaultAuditorAware.java │ │ │ ├── enumeration │ │ │ │ ├── DataType.java │ │ │ │ └── support │ │ │ │ │ ├── PersistEnum.java │ │ │ │ │ └── TopEnumType.java │ │ │ ├── json │ │ │ │ └── serialize │ │ │ │ │ └── CurrencySerializer.java │ │ │ ├── listener │ │ │ │ └── CheckingEntityListener.java │ │ │ ├── menu │ │ │ │ └── NavMenu.java │ │ │ ├── security │ │ │ │ └── ShiroUser.java │ │ │ └── support │ │ │ │ ├── AuditableEntity.java │ │ │ │ ├── CheckableEntity.java │ │ │ │ ├── CustomPKPersistableEntity.java │ │ │ │ ├── PersistableEntity.java │ │ │ │ ├── UserRelationEntity.java │ │ │ │ └── UserTreeRelationEntity.java │ │ ├── repository │ │ │ ├── AggregateExpression.java │ │ │ ├── IPageResults.java │ │ │ ├── IPageable.java │ │ │ ├── PageResultsImpl.java │ │ │ ├── PageableImpl.java │ │ │ ├── SearchFilter.java │ │ │ └── Sorter.java │ │ └── util │ │ │ ├── ArrayUtils.java │ │ │ ├── Base64EncryptUtil.java │ │ │ ├── BeanConverter.java │ │ │ ├── BeanMapper.java │ │ │ ├── DateUtil.java │ │ │ ├── EumnUtil.java │ │ │ ├── HttpUtils.java │ │ │ ├── MD5Utils.java │ │ │ ├── MathUtils.java │ │ │ ├── PreProperties.java │ │ │ ├── SaltUtil.java │ │ │ ├── SerializeUtil.java │ │ │ ├── StringUtils.java │ │ │ ├── TransactionTemplateUtils.java │ │ │ ├── TransformUtils.java │ │ │ └── UnicodeUtils.java │ │ ├── model │ │ ├── User.java │ │ └── business │ │ │ └── Record.java │ │ ├── repository │ │ ├── business │ │ │ └── IRecordRepository.java │ │ └── support │ │ │ ├── DefaultRepositoryFactory.java │ │ │ ├── DefaultRepositoryFactoryBean.java │ │ │ ├── DynamicSpecifications.java │ │ │ ├── GenericRepository.java │ │ │ └── GenericRepositoryImpl.java │ │ ├── server │ │ ├── DAOConsumer.java │ │ └── DAOProvider.java │ │ └── service │ │ ├── business │ │ ├── IRecordService.java │ │ └── impl │ │ │ └── RecordService.java │ │ └── support │ │ ├── GenericService.java │ │ └── IGenericService.java └── resources │ ├── conf │ ├── consumer │ │ ├── consumer-context.xml │ │ ├── consumer-service.xml │ │ └── consumer.properties │ └── provider │ │ ├── db-core.properties │ │ ├── db-core.xml │ │ ├── db-provider.xml │ │ ├── ehcache.xml │ │ ├── ha-db-context.xml │ │ └── jdbc.properties │ └── pak │ └── provider │ ├── hitler-provider-jar.bat │ └── provider-assembly.xml └── test └── java └── com └── hitler └── test ├── BaseTest.java └── dao └── RecordTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | /.project 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Z_SOUL 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of ha-db nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## @Deprecated 2 | ## SAAS 原型 3 | ## saas-mycat 4 | 5 | > 这是15年选择的预研方案,程序框架采用了spring、doubbo、mycat、mysql. 6 | > 整体方案采用mycat做为数据路由,由spring应用在执行SQL前加入mycat的路由注解。以达到数据库动态切换的目的. 7 | > 但是在实践过程中,发现mycat的框架体系把结构化数据库的事务性完全丢失,还包括MYSQL的存储过程无法得到有效满足. 8 | > 所以整个应用 在doubbo的上下文传递线程变量存在一些参考价值.也许mycat 2.0 或者 TiDB 可以解决这个问题. 9 | 10 | 11 | ## saas-mongo 12 | 13 | > 近期采用的SAAS结构. 14 | > 依赖于mongodb API的高度扩展与可用,加上spring boot/spring data mongo底层采用了netty实现,在数据连接管理上已完美实现动态切换。 15 | 16 | > 所以我们简单实现了通过线程变量传递DB NAME,并重写掉mongoTemplate,此组件具有了以下功能提供参考。 17 | 18 | - mongo docment 可任意加字段读出写入.实际上是重写映射结构. 19 | - 可配合前端域名动态切换数据库. 20 | - 注解式实现mongodb在自增主键上的缺陷. 21 | 22 | -------------------------------------------------------------------------------- /saas-mongo/.gitignore: -------------------------------------------------------------------------------- 1 | /.classpath 2 | .settings 3 | .project 4 | /target -------------------------------------------------------------------------------- /saas-mongo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.hitler 7 | saas-mongo 8 | 0.1.0 9 | jar 10 | 11 | saas-mongo 12 | saas platform mongo 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.4.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.data 30 | spring-data-mongodb 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-web 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-websocket 39 | 40 | 41 | 42 | org.springframework.retry 43 | spring-retry 44 | 45 | 46 | org.aspectj 47 | aspectjweaver 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-thymeleaf 53 | 54 | 55 | 56 | org.apache.commons 57 | commons-pool2 58 | 59 | 60 | 61 | com.alibaba 62 | fastjson 63 | 1.2.47 64 | 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-starter-test 69 | test 70 | 71 | 72 | 73 | 74 | io.springfox 75 | springfox-swagger2 76 | 2.8.0 77 | 78 | 79 | io.springfox 80 | springfox-swagger-ui 81 | 2.8.0 82 | 83 | 84 | com.jayway.jsonpath 85 | json-path 86 | 87 | 88 | 89 | org.springframework.batch 90 | spring-batch-test 91 | test 92 | 93 | 94 | 95 | 96 | com.auth0 97 | java-jwt 98 | 3.4.0 99 | 100 | 101 | 102 | cn.hutool 103 | hutool-all 104 | 4.0.9 105 | 106 | 107 | 108 | 109 | 110 | lixingxing 111 | lixingxing@doupai.cc 112 | https://github.com/onsoul 113 | 114 | 115 | 116 | saas-mongo 117 | 118 | 119 | org.apache.maven.plugins 120 | maven-source-plugin 121 | 3.0.1 122 | 123 | true 124 | 125 | 126 | 127 | compile 128 | 129 | jar 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/beans/BaseDTO.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.beans; 2 | 3 | import java.io.Serializable; 4 | 5 | 6 | /** 7 | * 基础DTO,用于装载定制的返回结果 8 | * @author onsoul 9 | * 2018年8月3日 下午2:19:00 10 | */ 11 | public class BaseDTO implements Serializable{ 12 | 13 | private static final long serialVersionUID = -7726234035360130786L; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/beans/BaseDocument.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.beans; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | 6 | import org.springframework.data.annotation.CreatedBy; 7 | import org.springframework.data.annotation.CreatedDate; 8 | import org.springframework.data.annotation.Id; 9 | import org.springframework.data.annotation.LastModifiedDate; 10 | 11 | 12 | /** 13 | * 所有Entity的基础类 14 | * @author onsoul 15 | * 2018年7月31日 下午2:09:39 16 | */ 17 | public abstract class BaseDocument implements Serializable { 18 | 19 | private static final long serialVersionUID = 7540028943332264289L; 20 | 21 | @Id 22 | protected PK id; 23 | 24 | @CreatedDate 25 | protected Date createdAt; 26 | 27 | @LastModifiedDate 28 | protected Date updatedAt; 29 | 30 | @CreatedBy 31 | protected String createdBy; 32 | 33 | 34 | public String getCreatedBy() { 35 | return createdBy; 36 | } 37 | 38 | public void setCreatedBy(String createdBy) { 39 | this.createdBy = createdBy; 40 | } 41 | 42 | public PK getId() { 43 | return id; 44 | } 45 | 46 | public void setId(PK id) { 47 | this.id = id; 48 | } 49 | public Date getCreatedAt() { 50 | return createdAt; 51 | } 52 | public void setCreatedAt(Date createdAt) { 53 | this.createdAt = createdAt; 54 | } 55 | public Date getUpdatedAt() { 56 | return updatedAt; 57 | } 58 | public void setUpdatedAt(Date updatedAt) { 59 | this.updatedAt = updatedAt; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/beans/BaseVO.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.beans; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 用于装载所有上行请求参数数据 7 | * @author onsoul 8 | * 2018年8月3日 下午2:19:20 9 | */ 10 | public abstract class BaseVO implements Serializable{ 11 | 12 | private static final long serialVersionUID = -1706756978999951244L; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/beans/Opations.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.beans; 2 | 3 | /** 4 | * 数据操作静态字段 5 | * 6 | * @author onsoul 2018年8月2日 下午6:15:04 7 | */ 8 | public class Opations { 9 | 10 | public static final String ID_FIELD = "_id"; 11 | public static final String CREATED_BY = "DP"; 12 | 13 | public static final String DOC_USER = "_USER"; 14 | public static final String DOC_ROLE = "_ROLE"; 15 | public static final String DOC_PERMISSION = "_PERMISSION"; 16 | 17 | public static final String CREATED_FIELD = "createdAt"; 18 | public static final String UPDATED_FIELD = "updatedAt"; 19 | public static final String CREATED_BY_FIELD = "createdBy"; 20 | 21 | /** 22 | * 应用token 23 | */ 24 | public static final String APP_TOKEN = "app-token"; 25 | /** 26 | * 会话token 27 | */ 28 | public static final String SEESION_TOKEN = "session-token"; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/db/entity/Docs.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.db.entity; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | 6 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 7 | 8 | /** 9 | * 此类以集合类型的方式声明持久类到Mongo Context,以提供高度自由的查询结果装载 简单说,可以使用它装载所有MongoDB 10 | * Doc(DBCollection=>DBObject) 11 | * 12 | */ 13 | @JsonIgnoreProperties 14 | public class Docs extends LinkedHashMap implements Map { 15 | 16 | private static final long serialVersionUID = -5701882427325141906L; 17 | } -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/db/entity/SequenceId.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.db.entity; 2 | 3 | import java.io.Serializable; 4 | 5 | import org.springframework.data.mongodb.core.mapping.Document; 6 | 7 | /** 8 | * 自增序列化ID 9 | * @author onsoul 10 | * 2018年7月31日 下午2:10:07 11 | */ 12 | @Document(collection = "_SEQUENCE_ID") 13 | public class SequenceId implements Serializable { 14 | 15 | private static final long serialVersionUID = 1L; 16 | public static String SEQUENCE_ID_COL_NAME = "_SEQUENCE_ID"; 17 | public static String COLLNAME = "collName"; 18 | public static String ROW = "row"; 19 | public static String SEQ = "seq"; 20 | 21 | private String collName; 22 | private String row; 23 | private Long seq; 24 | 25 | public String getCollName() { 26 | return collName; 27 | } 28 | 29 | public void setCollName(String collName) { 30 | this.collName = collName; 31 | } 32 | 33 | public String getRow() { 34 | return row; 35 | } 36 | 37 | public void setRow(String row) { 38 | this.row = row; 39 | } 40 | 41 | public Long getSeq() { 42 | return seq; 43 | } 44 | 45 | public void setSeq(Long seq) { 46 | this.seq = seq; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/db/enums/BaseEnums.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.db.enums; 2 | 3 | import java.util.Arrays; 4 | import java.util.Map; 5 | import java.util.stream.Collectors; 6 | 7 | /** 8 | * @Author: wanhao 9 | * @Description 10 | * @Date: Created in 10:56 2018/8/3 11 | */ 12 | public interface BaseEnums { 13 | Integer getCode(); 14 | 15 | String getMsg(); 16 | 17 | /** 18 | * key code,value msg 19 | */ 20 | static Map toMap(BaseEnums[] enums) { 21 | return Arrays.stream(enums).collect(Collectors.toMap(BaseEnums::getCode, BaseEnums::getMsg)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/db/mongo/BHBMongoMappingContext.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.db.mongo; 2 | 3 | import org.springframework.data.mongodb.core.mapping.MongoMappingContext; 4 | 5 | import com.hitler.core.db.entity.Docs; 6 | 7 | /** 8 | * 9 | * 重写MongoContext 以注入自定义的Persistable 10 | * 11 | * @author lixingxing@doupai.cc by DP 12 | * @version 1.0 13 | * @date 2017年5月17日 上午11:09:55 14 | */ 15 | public class BHBMongoMappingContext extends MongoMappingContext { 16 | 17 | public BHBMongoMappingContext() { 18 | super(); 19 | addPersistentEntity(Docs.class); //ORM 3天 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/db/mongo/BHBMongoTemplate.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.db.mongo; 2 | 3 | import org.springframework.data.mongodb.MongoDbFactory; 4 | import org.springframework.data.mongodb.core.MongoTemplate; 5 | import org.springframework.data.mongodb.core.convert.MongoConverter; 6 | import org.springframework.util.Assert; 7 | 8 | import com.hitler.core.db.mongo.sequence.SequenceOption; 9 | 10 | /** 11 | * 重写mongo模板 定制自增序列 12 | * @author DELL 13 | * 14 | */ 15 | public class BHBMongoTemplate extends MongoTemplate { 16 | 17 | private SequenceOption sequenceOption; 18 | 19 | public BHBMongoTemplate(MongoDbFactory mongoDbFactory,MongoConverter mongoConverter ,SequenceOption sequenceOption) { 20 | super(mongoDbFactory,mongoConverter); 21 | this.sequenceOption = sequenceOption; 22 | } 23 | 24 | @Override 25 | public void save(Object entity, String collectionName) { 26 | sequenceOption.purperSequence(this, collectionName, entity); 27 | super.save(entity, collectionName); 28 | } 29 | 30 | @Override 31 | public void insert(Object entity, String collectionName) { 32 | Assert.notNull(entity, "ObjectToSave must not be null!"); 33 | Assert.notNull(collectionName, "CollectionName must not be null!"); 34 | ensureNotIterable(entity); 35 | sequenceOption.purperSequence(this, collectionName, entity); 36 | super.doInsert(collectionName, entity, getConverter()); 37 | } 38 | 39 | public void setSequenceOption(SequenceOption sequenceOption) { 40 | this.sequenceOption = sequenceOption; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/db/mongo/MongoConfiguation.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.db.mongo; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.data.mongodb.MongoDbFactory; 10 | import org.springframework.data.mongodb.core.MongoTemplate; 11 | import org.springframework.data.mongodb.core.convert.DbRefResolver; 12 | import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; 13 | import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper; 14 | import org.springframework.data.mongodb.core.convert.MappingMongoConverter; 15 | import org.springframework.data.mongodb.core.convert.MongoCustomConversions; 16 | import org.springframework.data.mongodb.core.mapping.MongoMappingContext; 17 | 18 | import com.hitler.core.db.mongo.sequence.SequenceOption; 19 | import com.mongodb.MongoClientURI; 20 | 21 | /** 22 | * 注入mongo基础环境 23 | * 24 | * @author onsoul 2018年4月23日 25 | */ 26 | @Configuration 27 | public class MongoConfiguation { 28 | 29 | @Value("${spring.data.mongodb.uri}") 30 | private String mongoURI = "mongodb://saas:pwd@127.0.0.1:27017"; 31 | 32 | @Bean 33 | public MongoDbFactory mongoDbFactory(MongoClientURI uri) { 34 | return new RoutingDBFactory(uri); 35 | } 36 | 37 | @Bean 38 | public MongoClientURI mongoClientURI() { 39 | return new MongoClientURI(mongoURI); 40 | } 41 | 42 | @Bean 43 | public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory, SequenceOption sequenceOption) { 44 | DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory); 45 | 46 | MongoCustomConversions conversions = new MongoCustomConversions(resolverConverter()); 47 | MongoMappingContext mappingContext = new BHBMongoMappingContext(); 48 | mappingContext.setSimpleTypeHolder(conversions.getSimpleTypeHolder()); 49 | mappingContext.afterPropertiesSet(); 50 | MappingMongoConverter converter = new MappingMongoConverter(dbRefResolver, mappingContext); 51 | // _class 剔除 52 | converter.setTypeMapper(new DefaultMongoTypeMapper(null)); 53 | converter.setCustomConversions(conversions); 54 | converter.afterPropertiesSet(); 55 | 56 | // 需要自增时 57 | // MongoTemplate template=new DTXDMongoTemplate(mongoDbFactory,converter, 58 | // sequenceOption); 59 | MongoTemplate template = new MongoTemplate(mongoDbFactory, converter); 60 | return template; 61 | } 62 | 63 | private List resolverConverter() { 64 | return Collections.singletonList(new StringToDateConverter()); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/db/mongo/RoutingDBContextHolder.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.db.mongo; 2 | 3 | /** 4 | * 动态切换数据库 5 | * ThreadLocal 数据上下文 6 | * @author onsoul 2018年4月23日 7 | */ 8 | public class RoutingDBContextHolder { 9 | 10 | private static final ThreadLocal contextHolder = new ThreadLocal(); 11 | 12 | public static void setDBName(String dbName) { 13 | contextHolder.set(dbName); 14 | } 15 | 16 | public static String getDBName() { 17 | return contextHolder.get(); 18 | } 19 | 20 | public static void clearDBName() { //注意传播 21 | contextHolder.remove(); 22 | } 23 | } -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/db/mongo/RoutingDBFactory.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.db.mongo; 2 | 3 | import java.net.UnknownHostException; 4 | 5 | import org.springframework.beans.factory.DisposableBean; 6 | import org.springframework.dao.DataAccessException; 7 | import org.springframework.dao.support.PersistenceExceptionTranslator; 8 | import org.springframework.data.mongodb.MongoDbFactory; 9 | import org.springframework.data.mongodb.core.MongoExceptionTranslator; 10 | import org.springframework.data.mongodb.core.SimpleMongoDbFactory; 11 | import org.springframework.lang.Nullable; 12 | import org.springframework.util.Assert; 13 | import org.springframework.util.StringUtils; 14 | 15 | import com.mongodb.DB; 16 | import com.mongodb.MongoClient; 17 | import com.mongodb.MongoClientURI; 18 | import com.mongodb.WriteConcern; 19 | import com.mongodb.client.MongoDatabase; 20 | 21 | 22 | /** 23 | * 重写SimpleMongoDBFactory 24 | * 加入动态路由部分 25 | * @author onsoul 2018年4月23日 26 | */ 27 | public class RoutingDBFactory implements DisposableBean, MongoDbFactory { 28 | 29 | private final MongoClient mongoClient; 30 | private final String databaseName; 31 | private final boolean mongoInstanceCreated; 32 | private final PersistenceExceptionTranslator exceptionTranslator; 33 | 34 | private @Nullable WriteConcern writeConcern; 35 | 36 | /** 37 | * Creates a new {@link SimpleMongoDbFactory} instance from the given 38 | * {@link MongoClientURI}. 39 | * 40 | * @param uri 41 | * must not be {@literal null}. 42 | * @throws UnknownHostException 43 | * @since 1.7 44 | */ 45 | public RoutingDBFactory(MongoClientURI uri) { 46 | this(new MongoClient(uri), uri.getDatabase(), true); 47 | } 48 | 49 | /** 50 | * Creates a new {@link SimpleMongoDbFactory} instance from the given 51 | * {@link MongoClient}. 52 | * 53 | * @param mongoClient 54 | * must not be {@literal null}. 55 | * @param databaseName 56 | * must not be {@literal null}. 57 | * @since 1.7 58 | */ 59 | public RoutingDBFactory(MongoClient mongoClient, String databaseName) { 60 | this(mongoClient, databaseName, false); 61 | } 62 | 63 | /** 64 | * @param client 65 | * @param databaseName 66 | * @param mongoInstanceCreated 67 | * @since 1.7 68 | */ 69 | private RoutingDBFactory(MongoClient mongoClient, String databaseName, boolean mongoInstanceCreated) { 70 | 71 | Assert.notNull(mongoClient, "MongoClient must not be null!"); 72 | Assert.hasText(databaseName, "Database name must not be empty!"); 73 | Assert.isTrue(databaseName.matches("[\\w-]+"), 74 | "Database name must only contain letters, numbers, underscores and dashes!"); 75 | 76 | this.mongoClient = mongoClient; 77 | this.databaseName = databaseName; 78 | this.mongoInstanceCreated = mongoInstanceCreated; 79 | this.exceptionTranslator = new MongoExceptionTranslator(); 80 | } 81 | 82 | /** 83 | * Configures the {@link WriteConcern} to be used on the {@link DB} instance 84 | * being created. 85 | * 86 | * @param writeConcern 87 | * the writeConcern to set 88 | */ 89 | public void setWriteConcern(WriteConcern writeConcern) { 90 | this.writeConcern = writeConcern; 91 | } 92 | 93 | @Override 94 | public MongoDatabase getDb() throws DataAccessException { 95 | String dbName = RoutingDBContextHolder.getDBName(); 96 | if (!StringUtils.isEmpty(dbName)) { 97 | return getDb(dbName); 98 | } 99 | // Thread local中获取数据库的变量 100 | return getDb(databaseName); 101 | } 102 | 103 | @Override 104 | public MongoDatabase getDb(String dbName) throws DataAccessException { 105 | Assert.hasText(dbName, "Database name must not be empty."); 106 | 107 | MongoDatabase db = mongoClient.getDatabase(dbName); 108 | 109 | if (writeConcern == null) { 110 | return db; 111 | } 112 | return db.withWriteConcern(writeConcern); 113 | } 114 | 115 | @Override 116 | public PersistenceExceptionTranslator getExceptionTranslator() { 117 | return this.exceptionTranslator; 118 | } 119 | 120 | @SuppressWarnings("deprecation") 121 | @Override 122 | public DB getLegacyDb() { 123 | return mongoClient.getDB(databaseName); 124 | } 125 | 126 | @Override 127 | public void destroy() throws Exception { 128 | if (mongoInstanceCreated) { 129 | mongoClient.close(); 130 | } 131 | 132 | } 133 | 134 | } 135 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/db/mongo/StringToDateConverter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014 GZJF Corp. All rights reserved. 3 | * This software is proprietary to and embodies the confidential 4 | * technology of 深圳市大头兄弟文化传播有限公司 Corp. Possession, use, or copying 5 | * of this software and media is authorized only pursuant to a 6 | * valid written license from 深圳市大头兄弟文化传播有限公司 Corp or an authorized sublicensor. 7 | */ 8 | package com.hitler.core.db.mongo; 9 | 10 | 11 | import cn.hutool.core.convert.ConvertException; 12 | import cn.hutool.core.date.DatePattern; 13 | import cn.hutool.core.date.format.FastDateFormat; 14 | import cn.hutool.core.util.StrUtil; 15 | import org.slf4j.Logger; 16 | import org.slf4j.LoggerFactory; 17 | import org.springframework.core.convert.converter.Converter; 18 | import org.springframework.data.convert.ReadingConverter; 19 | 20 | import java.text.ParseException; 21 | import java.util.Date; 22 | import java.util.Optional; 23 | 24 | /** 25 | * 1.空字符串返回null 26 | * 2.进行yyyy-MM-dd HH:mm:ss转换,失败抛出异常 27 | * description: 字符串转换为日期转换器 28 | * Author Date Changes 29 | * DouPai-LiuYang 2018/8/23 Created 30 | * @author DouPai-LiuYang 31 | */ 32 | @ReadingConverter 33 | public class StringToDateConverter implements Converter { 34 | private final Logger log = LoggerFactory.getLogger(StringToDateConverter.class); 35 | 36 | @Override 37 | public Date convert(String source) { 38 | if (StrUtil.isBlank(source)) { 39 | return null; 40 | } 41 | log.info("source:{}", source); 42 | Optional optional = convertPattern(source); 43 | return optional.orElseThrow(() -> new ConvertException(source)); 44 | } 45 | 46 | /** 47 | * 转换为date 48 | * @param source yyyy-MM-dd HH:mm:ss格式的字符串 49 | */ 50 | private Optional convertPattern(String source) { 51 | try { 52 | Date date = FastDateFormat.getInstance(DatePattern.NORM_DATETIME_PATTERN).parse(source); 53 | return Optional.of(date); 54 | } catch (ParseException e) { 55 | log.error(String.format("source:%s ,message:%s", source, e.getMessage()), e); 56 | } 57 | return Optional.empty(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/db/mongo/sequence/IDNo.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.db.mongo.sequence; 2 | 3 | import static java.lang.annotation.ElementType.ANNOTATION_TYPE; 4 | import static java.lang.annotation.ElementType.FIELD; 5 | import static java.lang.annotation.ElementType.METHOD; 6 | 7 | import java.lang.annotation.Documented; 8 | import java.lang.annotation.Inherited; 9 | import java.lang.annotation.Retention; 10 | import java.lang.annotation.RetentionPolicy; 11 | import java.lang.annotation.Target; 12 | 13 | /** 14 | * 自增ID注解 15 | * @author onsoul 16 | * 17 | * 类型必须为Long 18 | * 19 | */ 20 | @Documented 21 | @Inherited 22 | @Retention(RetentionPolicy.RUNTIME) 23 | @Target(value = { FIELD, METHOD, ANNOTATION_TYPE }) 24 | public @interface IDNo { 25 | 26 | } 27 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/db/mongo/sequence/SequenceOption.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.db.mongo.sequence; 2 | 3 | import java.lang.reflect.Field; 4 | import java.util.Optional; 5 | 6 | import org.springframework.context.annotation.Lazy; 7 | import org.springframework.data.mongodb.core.FindAndModifyOptions; 8 | import org.springframework.data.mongodb.core.MongoTemplate; 9 | import org.springframework.data.mongodb.core.query.Criteria; 10 | import org.springframework.data.mongodb.core.query.Query; 11 | import org.springframework.data.mongodb.core.query.Update; 12 | import org.springframework.data.util.ReflectionUtils; 13 | import org.springframework.data.util.ReflectionUtils.AnnotationFieldFilter; 14 | import org.springframework.stereotype.Component; 15 | 16 | import com.hitler.core.db.entity.SequenceId; 17 | 18 | /** 19 | * 替换掉自增值 20 | * 21 | * @author onsoul 22 | * 23 | */ 24 | @Component 25 | @Lazy 26 | public class SequenceOption { 27 | 28 | private static final AnnotationFieldFilter IDNO_FILTER = new AnnotationFieldFilter(IDNo.class); 29 | 30 | public void purperSequence(MongoTemplate template, String collectionName, Object entity) { 31 | Optional noField = Optional.ofNullable(ReflectionUtils.findField(entity.getClass(), IDNO_FILTER)); 32 | noField.ifPresent(f -> { 33 | try { 34 | String fieldName = noField.get().getName(); 35 | Long increment = generate(template, collectionName, fieldName, 1l); 36 | f.setAccessible(true); 37 | f.set(entity, increment); 38 | } catch (Exception e) { 39 | e.printStackTrace(); 40 | } 41 | }); 42 | } 43 | 44 | private long generate(MongoTemplate template, String collectionName, String rowName, Long incrementVal) { 45 | Criteria criteria = Criteria.where(SequenceId.COLLNAME).is(collectionName); 46 | if (rowName != null) { 47 | criteria.and(SequenceId.ROW).is(rowName); 48 | } else { 49 | criteria.and(SequenceId.ROW).ne("").ne(null); 50 | } 51 | Query query = new Query(criteria); 52 | 53 | Update update = new Update(); 54 | update.inc(SequenceId.SEQ, incrementVal); 55 | FindAndModifyOptions options = new FindAndModifyOptions(); 56 | options.upsert(false); // 不做插入,所有的自增键由表维护 57 | options.returnNew(true); 58 | SequenceId seqId = template.findAndModify(query, update, options, SequenceId.class, 59 | SequenceId.SEQUENCE_ID_COL_NAME); 60 | 61 | return seqId.getSeq(); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/ex/BHBException.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.ex; 2 | 3 | import com.hitler.core.resp.Code; 4 | 5 | 6 | /** 7 | * 业务级异常 8 | * 异常信息统一归集至 msg_code.json, 会在应用初始化时加载至hashMap 9 | * @author onsoul 10 | * 2018年8月2日 上午9:39:04 11 | */ 12 | public class BHBException extends Exception { 13 | 14 | private static final long serialVersionUID = 3514055481085104305L; 15 | private Code code = Code.MSG_1; // 默认系统异常 16 | 17 | //不需要msg,因为msg工整到msg_code.json文件中,抛出异常时只需要由代码来跟踪 18 | 19 | public BHBException(Code code) { 20 | this.code = code; 21 | } 22 | 23 | public Code getCode() { 24 | return code; 25 | } 26 | 27 | public void setCode(Code code) { 28 | this.code = code; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/ex/ConfigException.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.ex; 2 | 3 | import com.hitler.core.resp.Code; 4 | 5 | /** 6 | * 文件名:cn.bhbapp.push.common.exception 7 | * 修改人:liufumin 8 | * 修改时间:2018/9/13 9 | */ 10 | public class ConfigException extends RuntimeException { 11 | private static final long serialVersionUID = 1L; 12 | private Code code; 13 | 14 | public ConfigException(Code code) { 15 | this.code = code; 16 | } 17 | 18 | public ConfigException() { 19 | this.code = Code.MSG_1; 20 | } 21 | 22 | public Code getCode() { 23 | return this.code; 24 | } 25 | 26 | public void setCode(Code code) { 27 | this.code = code; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/ex/DataNotFoundBHBException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014 GZJF Corp. All rights reserved. 3 | * This software is proprietary to and embodies the confidential 4 | * technology of 深圳市大头兄弟文化传播有限公司 Corp. Possession, use, or copying 5 | * of this software and media is authorized only pursuant to a 6 | * valid written license from 深圳市大头兄弟文化传播有限公司 Corp or an authorized sublicensor. 7 | */ 8 | package com.hitler.core.ex; 9 | 10 | import com.hitler.core.resp.Code; 11 | 12 | /** 13 | * description: 数据找不到异常 14 | * Author Date Changes 15 | * DouPai-LiuYang 2018/8/15 Created 16 | * @author DouPai-LiuYang 17 | */ 18 | public class DataNotFoundBHBException extends BHBException { 19 | public DataNotFoundBHBException() { 20 | super(Code.MSG_147); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/ex/HttpException.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.ex; 2 | 3 | import com.hitler.core.resp.Code; 4 | 5 | /** 6 | * 文件名:cn.bhbapp.ush.common.exception 7 | * 修改人:liufumin 8 | * 修改时间:2018/9/13 9 | */ 10 | public class HttpException extends ConfigException { 11 | private static final long serialVersionUID = 1L; 12 | 13 | public HttpException(Code code) { 14 | super(code); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/ex/OrderHookBHBException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014 GZJF Corp. All rights reserved. 3 | * This software is proprietary to and embodies the confidential 4 | * technology of 深圳市大头兄弟文化传播有限公司 Corp. Possession, use, or copying 5 | * of this software and media is authorized only pursuant to a 6 | * valid written license from 深圳市大头兄弟文化传播有限公司 Corp or an authorized sublicensor. 7 | */ 8 | package com.hitler.core.ex; 9 | 10 | import com.hitler.core.resp.Code; 11 | 12 | /** 13 | * @Author: wanhao 14 | * @Description 15 | * @Date: Created in 11:37 2018/8/24 16 | */ 17 | public class OrderHookBHBException extends BHBException { 18 | public OrderHookBHBException() { 19 | super(Code.MSG_2010); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/ex/OrderHookUnknowBHBException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014 GZJF Corp. All rights reserved. 3 | * This software is proprietary to and embodies the confidential 4 | * technology of 深圳市大头兄弟文化传播有限公司 Corp. Possession, use, or copying 5 | * of this software and media is authorized only pursuant to a 6 | * valid written license from 深圳市大头兄弟文化传播有限公司 Corp or an authorized sublicensor. 7 | */ 8 | package com.hitler.core.ex; 9 | 10 | import com.hitler.core.resp.Code; 11 | 12 | /** 13 | * @Author: wanhao 14 | * @Description 15 | * @Date: Created in 11:37 2018/8/24 16 | */ 17 | public class OrderHookUnknowBHBException extends BHBException { 18 | public OrderHookUnknowBHBException(Code code) { 19 | super(code); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/ex/UserNotFoundBHBException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright © 2014 GZJF Corp. All rights reserved. 3 | * This software is proprietary to and embodies the confidential 4 | * technology of 深圳市大头兄弟文化传播有限公司 Corp. Possession, use, or copying 5 | * of this software and media is authorized only pursuant to a 6 | * valid written license from 深圳市大头兄弟文化传播有限公司 Corp or an authorized sublicensor. 7 | */ 8 | package com.hitler.core.ex; 9 | 10 | import com.hitler.core.resp.Code; 11 | 12 | /** 13 | * description: 数据找不到异常 14 | * Author Date Changes 15 | * DouPai-LiuYang 2018/8/15 Created 16 | * @author DouPai-LiuYang 17 | */ 18 | public class UserNotFoundBHBException extends BHBException { 19 | public UserNotFoundBHBException() { 20 | super(Code.MSG_211); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/executor/CoreExecutor.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.executor; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 7 | 8 | import java.util.concurrent.Executor; 9 | import java.util.concurrent.ThreadPoolExecutor; 10 | 11 | /** 12 | * 线程池配置 13 | */ 14 | @Configuration 15 | @EnableAsync 16 | public class CoreExecutor { 17 | 18 | private int corePoolSize = 10; 19 | private int maxPoolSize = 200; 20 | private int queueCapacity = 10; 21 | 22 | @Bean("saasAsync") 23 | public Executor taskAsync() { 24 | ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 25 | executor.setCorePoolSize(corePoolSize); 26 | executor.setMaxPoolSize(maxPoolSize); 27 | executor.setQueueCapacity(queueCapacity); 28 | executor.setThreadNamePrefix("SAAS-"); 29 | // rejection-policy:当pool已经达到max size的时候,如何处理新任务 30 | // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行 31 | executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); 32 | executor.initialize(); 33 | return executor; 34 | } 35 | } -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/resp/Code.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.resp; 2 | 3 | 4 | /** 5 | * 信息代码码表,详细信息内容见 classpath/msg_code.json 6 | * @author onsoul 7 | * 2018年8月1日 下午3:07:29 8 | */ 9 | public enum Code { 10 | MSG_1, // MSG_1 11 | MSG_2, 12 | MSG_3, 13 | MSG_10, 14 | MSG_40, 15 | MSG_41, 16 | MSG_100, // MSG_100 17 | MSG_101, // MSG_101 18 | MSG_102, 19 | MSG_103, // MSG_103 20 | MSG_104, // MSG_104 21 | MSG_105, // MSG_105 22 | MSG_106, // MSG_106 23 | MSG_107, // MSG_107 24 | MSG_108, // MSG_108 25 | MSG_109, // MSG_109 26 | MSG_111, // MSG_111 27 | MSG_112, // MSG_112 28 | MSG_113, // MSG_113 29 | MSG_114, // MSG_114 30 | MSG_116, // MSG_116 31 | MSG_117, // MSG_117 32 | MSG_119, // MSG_119 33 | MSG_120, // MSG_120 34 | MSG_121, // MSG_121 35 | MSG_122, // MSG_122 36 | MSG_123, // MSG_123 37 | MSG_124, // MSG_124 38 | MSG_125, // MSG_125 39 | MSG_126, // MSG_126 40 | MSG_127, // MSG_127 41 | MSG_128, // MSG_128 42 | MSG_137, // MSG_137 43 | MSG_139, // MSG_139 44 | MSG_140, // MSG_140 45 | MSG_141, // MSG_141 46 | MSG_142, // MSG_142 47 | MSG_145, // MSG_145 48 | MSG_146, 49 | MSG_147, 50 | MSG_148, 51 | MSG_150, // MSG_150 52 | MSG_154, // MSG_154 53 | MSG_160, // MSG_160 54 | MSG_198, // MSG_198 55 | MSG_199, // MSG_199 56 | MSG_200, // MSG_200 57 | MSG_201, // MSG_201 58 | MSG_202, // MSG_202 59 | MSG_203, // MSG_203 60 | MSG_204, // MSG_204 61 | MSG_205, // MSG_205 62 | MSG_206, // MSG_206 63 | MSG_207, // MSG_207 64 | MSG_208, // MSG_208 65 | MSG_210, // MSG_210 66 | MSG_211, // MSG_211 67 | MSG_212, // MSG_212 68 | MSG_213, // MSG_213 69 | MSG_214, // MSG_214 70 | MSG_215, // MSG_215 71 | MSG_216, // MSG_216 72 | MSG_217, // MSG_217 73 | MSG_218, // MSG_218 74 | MSG_219, // MSG_219 75 | MSG_250, // MSG_250 76 | MSG_251, // MSG_251 77 | MSG_252, // MSG_252 78 | MSG_300, // MSG_300 79 | MSG_301, // MSG_301 80 | MSG_302, // MSG_302 81 | MSG_303, // MSG_303 82 | MSG_304, // MSG_304 83 | MSG_305, // MSG_305 84 | MSG_401, // MSG_401 85 | MSG_403, // MSG_403 86 | MSG_429, // MSG_429 87 | MSG_430, // MSG_430 88 | MSG_431, // MSG_431 89 | MSG_502, // MSG_502 90 | MSG_503, // MSG_503 91 | MSG_511, // MSG_511 92 | MSG_524, // MSG_524 93 | MSG_600, // MSG_600 94 | MSG_601, // MSG_601 95 | MSG_602, // MSG_602 96 | MSG_603, // MSG_603 97 | MSG_604, // MSG_604 98 | MSG_605, // MSG_605 99 | MSG_606, // MSG_606 100 | MSG_700, // MSG_700 101 | MSG_2000, 102 | MSG_2001, 103 | MSG_2002, 104 | MSG_2003, 105 | MSG_2004, 106 | MSG_2005, 107 | MSG_2006, 108 | MSG_2007, 109 | MSG_2008, 110 | MSG_2009, 111 | MSG_2010, 112 | MSG_2011, 113 | MSG_2012, 114 | MSG_2013, 115 | MSG_2014, 116 | MSG_2015, 117 | MSG_2016, 118 | MSG_2017, 119 | MSG_2018, 120 | MSG_2019, 121 | MSG_2020, 122 | MSG_2021, 123 | MSG_3000, 124 | MSG_3001, 125 | MSG_3002, 126 | MSG_3003, 127 | MSG_3004, 128 | MSG_3005, 129 | MSG_3006, 130 | MSG_3007, 131 | MSG_4010, 132 | MSG_4011, 133 | MSG_4012, 134 | MSG_4013, 135 | MSG_4014, 136 | MSG_5000, 137 | MSG_5001, 138 | MSG_5002, 139 | MSG_5003, 140 | MSG_5004, 141 | MSG_5005, 142 | MSG_5006, 143 | MSG_5007, 144 | MSG_5008, 145 | MSG_5009, 146 | MSG_5010, 147 | MSG_5011, 148 | MSG_5012, 149 | MSG_5013, 150 | MSG_5014, 151 | MSG_5015} 152 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/resp/MsgCode.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.resp; 2 | 3 | import java.io.InputStream; 4 | import java.util.LinkedHashMap; 5 | import java.util.Map; 6 | import java.util.Scanner; 7 | 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.core.io.Resource; 10 | import org.springframework.stereotype.Component; 11 | 12 | import com.alibaba.fastjson.JSON; 13 | 14 | 15 | 16 | /** 17 | * 消息代码处理 18 | * 在应用内某一消息触发加载时,从文件中加载出所有消息列表。 19 | * 20 | * @author onsoul 21 | * 2018年8月3日 下午2:28:20 22 | */ 23 | @Component 24 | public class MsgCode { 25 | 26 | @Value(value = "classpath:/msg_code.json") 27 | private Resource data; 28 | 29 | private static Map queue = new LinkedHashMap(); 30 | 31 | public Object code(Code code) { 32 | return code(code.toString()); 33 | } 34 | 35 | @SuppressWarnings("unchecked") 36 | public Object code(String code) { 37 | try { 38 | if (null == queue || queue.size() < 1) { 39 | String jsonData = this.jsonRead(data.getInputStream()); 40 | queue = JSON.parseObject(jsonData, LinkedHashMap.class); 41 | } 42 | return queue.get(code); 43 | } catch (Exception e) { 44 | e.printStackTrace(); 45 | return null; 46 | } 47 | } 48 | 49 | 50 | public Object makeSuccess() { 51 | return code(Code.MSG_100); //请求成功 52 | } 53 | 54 | 55 | /** 56 | * 读取文件内容为字符串 57 | * 58 | * @param file 59 | * @return 60 | */ 61 | private String jsonRead(InputStream is) { 62 | Scanner scanner = null; 63 | StringBuilder buffer = new StringBuilder(); 64 | try { 65 | scanner = new Scanner(is, "utf-8"); 66 | while (scanner.hasNextLine()) { 67 | buffer.append(scanner.nextLine()); 68 | } 69 | } catch (Exception e) { 70 | e.printStackTrace(); 71 | } finally { 72 | if (scanner != null) { 73 | scanner.close(); 74 | } 75 | } 76 | return buffer.toString(); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/resp/Result.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.resp; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | 6 | import java.io.Serializable; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * 统一的结果集返回形式 12 | * 13 | * @author onsoul 2018年8月2日 上午9:01:23 14 | */ 15 | @ApiModel(description = "统一的结果集返回形式") 16 | public class Result implements Serializable { 17 | 18 | private static final long serialVersionUID = 796464608076507729L; 19 | @ApiModelProperty("响应信息") 20 | private Object msg; 21 | @ApiModelProperty("数量-分页场景使用") 22 | private Long count; 23 | @ApiModelProperty("响应数据(一般包含entity或者DTO)") 24 | private List data; 25 | 26 | private String sid; 27 | 28 | public Result() { 29 | } 30 | 31 | public Result(Object msg) { // 链接MsgCode 32 | this.msg = msg; 33 | } 34 | 35 | public Result(Object msg, T t) { // 链接MsgCode 36 | this.data = new ArrayList<>(); // 如果是单体 37 | this.data.add(t); 38 | this.msg = msg; 39 | } 40 | 41 | public Result(Object msg, List data) { // 链接MsgCode 42 | this.data = data; 43 | this.msg = msg; 44 | } 45 | 46 | public Object getMsg() { 47 | return msg; 48 | } 49 | 50 | public void setMsg(Object msg) { 51 | this.msg = msg; 52 | } 53 | 54 | public Long getCount() { 55 | return count; 56 | } 57 | 58 | public void setCount(Long count) { 59 | this.count = count; 60 | } 61 | 62 | public List getData() { 63 | return data; 64 | } 65 | 66 | public void setData(T t) { 67 | if (this.data == null || this.data.isEmpty()) { 68 | this.data = new ArrayList<>(); // 如果是单体 69 | } 70 | this.data.add(t); 71 | } 72 | 73 | public void setData(List data) { 74 | this.data = data; 75 | } 76 | 77 | public String getSid() { 78 | return sid; 79 | } 80 | 81 | public void setSid(String sid) { 82 | this.sid = sid; 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/services/BaseService.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.services; 2 | 3 | import java.lang.reflect.ParameterizedType; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import org.bson.Document; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.data.domain.Page; 12 | import org.springframework.data.domain.PageImpl; 13 | import org.springframework.data.domain.PageRequest; 14 | import org.springframework.data.domain.Pageable; 15 | import org.springframework.data.mongodb.core.MongoTemplate; 16 | import org.springframework.data.mongodb.core.query.BasicQuery; 17 | import org.springframework.data.mongodb.core.query.Criteria; 18 | import org.springframework.data.mongodb.core.query.Query; 19 | import org.springframework.data.mongodb.core.query.Update; 20 | import org.springframework.stereotype.Service; 21 | 22 | import com.hitler.core.beans.Opations; 23 | import com.hitler.core.db.entity.Docs; 24 | import com.mongodb.client.result.DeleteResult; 25 | 26 | /** 27 | * 所有Serivce 的基础类型 28 | * 29 | * @author onsoul 2018年8月1日 下午5:16:27 30 | */ 31 | @SuppressWarnings("ALL") 32 | @Service 33 | public abstract class BaseService { 34 | 35 | @Autowired 36 | protected MongoTemplate mongoTemplate; 37 | 38 | protected final Logger log = LoggerFactory.getLogger(this.getClass()); 39 | 40 | public Document save(Document t, String collectionName) { 41 | mongoTemplate.save(t, collectionName); 42 | return t; 43 | } 44 | 45 | public T update(String id, Document updoc, T t) { 46 | Update update = Update.fromDocument(updoc, ""); 47 | Query query = Query.query(Criteria.where(Opations.ID_FIELD).is(id)); 48 | T result = (T) mongoTemplate.findAndModify(query, update, t.getClass()); 49 | return result; 50 | } 51 | 52 | public boolean delete(String collectionName, String id) { 53 | Query query = Query.query(Criteria.where(Opations.ID_FIELD).is(id)); 54 | DeleteResult result = mongoTemplate.remove(query, collectionName); 55 | return result.getDeletedCount() > 0; 56 | } 57 | 58 | public Document findById(String collectionName, String id) { 59 | Document result = mongoTemplate.findById(id, Document.class, collectionName); 60 | return result; 61 | } 62 | 63 | 64 | public abstract T findById(String id); 65 | 66 | public List findALL(String collectionName, Document queryDoc, T claz, Pageable pageable) { 67 | Query query = new BasicQuery(queryDoc); 68 | query.with(pageable); 69 | List result = mongoTemplate.find(query, (Class) claz, collectionName); 70 | return result; 71 | } 72 | 73 | public Page query(Query query) { 74 | Class tClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()) 75 | .getActualTypeArguments()[0]; 76 | long count = mongoTemplate.count(query, tClass); 77 | List list = count > 0 ? mongoTemplate.find(query, tClass) : new ArrayList<>(); 78 | return new PageImpl(list, 79 | PageRequest.of(Math.toIntExact(query.getSkip() / query.getLimit()), query.getLimit()), count); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/services/GenericService.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.services; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import org.bson.Document; 7 | import org.springframework.data.domain.Pageable; 8 | import org.springframework.data.mongodb.core.query.BasicQuery; 9 | import org.springframework.data.mongodb.core.query.Criteria; 10 | import org.springframework.data.mongodb.core.query.Query; 11 | import org.springframework.data.mongodb.core.query.Update; 12 | import org.springframework.stereotype.Service; 13 | 14 | import com.hitler.core.beans.Opations; 15 | import com.hitler.core.db.entity.Docs; 16 | import com.hitler.core.resp.Result; 17 | 18 | /** 19 | * 通用集合处理Service,此类为整个SAAS的核心部分. 完成所有模型的操作 20 | * 21 | * @author onsoul 2018年8月6日 下午5:59:58 22 | */ 23 | @Service 24 | public class GenericService extends BaseService { 25 | 26 | private Class clasz = Docs.class; // 声明装载类型 27 | 28 | // repository是针对单体的,所以在此不再适用。 29 | 30 | @Override 31 | public Docs findById(String id) { 32 | return null; 33 | } 34 | 35 | public Docs findByIdAndQuery(String doc, String id, Document query) { 36 | Query q = new BasicQuery(new Document(), query); 37 | q.addCriteria(Criteria.where(Opations.ID_FIELD).is(id)); 38 | return mongoTemplate.findOne(q, clasz , doc); 39 | } 40 | 41 | 42 | @Override 43 | public Document save(Document t, String collectionName) { 44 | if (!t.isEmpty()) { 45 | t.put(Opations.CREATED_FIELD, new Date()); // 创建时间 46 | t.put(Opations.UPDATED_FIELD, new Date()); // 更新时间 47 | } 48 | return super.save(t, collectionName); 49 | } 50 | 51 | /** 52 | * 更新通用集合表 53 | * 54 | * @param doc 55 | * @param id 56 | * @param updata 57 | * @return 58 | */ 59 | public Docs update(String doc, String id, Docs updata) { 60 | Update update = new Update(); 61 | updata.forEach((key, value) -> { 62 | update.set(key, value); 63 | }); 64 | 65 | update.set(Opations.UPDATED_FIELD, new Date()); // 更新时间 66 | Query query = Query.query(Criteria.where(Opations.ID_FIELD).is(id)); 67 | Docs docs = mongoTemplate.findAndModify(query, update, clasz, doc); 68 | return docs; 69 | } 70 | 71 | public Result page(String collectionName, Document queryDoc, Pageable pageable) { 72 | Result result = new Result<>(); // 结果集 73 | Query query = new BasicQuery(new Document() , queryDoc); // 组装query 74 | query.with(pageable); // 组装分页 75 | Long count = mongoTemplate.count(query, collectionName); // 统计 76 | List dtos = (List) mongoTemplate.find(query, clasz, collectionName); // 映射结果集 77 | result.setData(dtos); // 组装返回 78 | result.setCount(count); // 填充统计 79 | return result; 80 | } 81 | 82 | public List pageNoCount(String collectionName, Document queryDoc, Pageable pageable) { 83 | Query query = new BasicQuery(new Document() , queryDoc); // 组装query 84 | query.with(pageable); // 组装分页 85 | List dtos = (List) mongoTemplate.find(query, clasz, collectionName); // 映射结果集 86 | return dtos; 87 | } 88 | 89 | 90 | public Long count(String collectionName, Document queryDoc) { 91 | Query query = new BasicQuery(new Document() , queryDoc); // 组装query 92 | Long count = mongoTemplate.count(query, collectionName); // 统计 93 | return count; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /saas-mongo/src/main/java/com/hitler/core/utils/EncryptUtil.java: -------------------------------------------------------------------------------- 1 | package com.hitler.core.utils; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.math.BigInteger; 5 | import java.security.MessageDigest; 6 | import java.security.NoSuchAlgorithmException; 7 | import java.util.Base64; 8 | import java.util.Random; 9 | import java.util.UUID; 10 | 11 | import org.springframework.util.StringUtils; 12 | 13 | 14 | /** 15 | * 加密工具类 16 | * @author onsoul 17 | * 2018年8月3日 下午2:28:03 18 | */ 19 | public class EncryptUtil { 20 | 21 | private static final int MAX_LENGTH = 32; 22 | 23 | /** 24 | * user pwd sha512 25 | * @param text 26 | * salt+password 27 | * @return result 28 | */ 29 | public static String sha512(String text) { 30 | MessageDigest sha512Digest; 31 | try { 32 | sha512Digest = MessageDigest.getInstance("SHA-512"); 33 | byte[] result = sha512Digest.digest(text.getBytes()); 34 | for (int i = 0; i < 512; i++) { 35 | result = sha512Digest.digest(result); 36 | } 37 | return Base64.getEncoder().encodeToString(result); 38 | } catch (NoSuchAlgorithmException e) { 39 | e.printStackTrace(); 40 | return null; 41 | } 42 | } 43 | 44 | // 构建盐 45 | public static String salt(String text) { 46 | if (!StringUtils.isEmpty(text)) { 47 | text += System.currentTimeMillis(); 48 | String encode = Base64.getEncoder().encodeToString(text.getBytes()); 49 | return (encode.length() > MAX_LENGTH) ? encode.substring(0, MAX_LENGTH) : encode; 50 | } 51 | return null; 52 | } 53 | 54 | public static String makeToken() { 55 | String id = UUID.randomUUID().toString().replace("-", ""); 56 | return md5(id); 57 | } 58 | 59 | /** 60 | * 对字符串md5加密 61 | * 62 | * @param str 63 | * @return 64 | */ 65 | public static String md5(String str) { 66 | try { 67 | // 生成一个MD5加密计算摘要 68 | MessageDigest md = MessageDigest.getInstance("MD5"); 69 | // 计算md5函数 70 | md.update(str.getBytes()); 71 | // digest()最后确定返回md5 hash值,返回值为8为字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符 72 | // BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值 73 | return new BigInteger(1, md.digest()).toString(16); 74 | } catch (Exception e) { 75 | e.printStackTrace(); 76 | } 77 | return null; 78 | } 79 | 80 | /** 81 | * base64加密方法 82 | * @param plainText 83 | * @return 84 | */ 85 | public static String encodedBase64(String plainText) { 86 | String encoded = null; 87 | try { 88 | byte[] bytes = plainText.getBytes("UTF-8"); 89 | encoded = Base64.getEncoder().encodeToString(bytes); 90 | } catch (UnsupportedEncodingException e) { 91 | // TODO Auto-generated catch block 92 | e.printStackTrace(); 93 | } 94 | 95 | return encoded; 96 | } 97 | 98 | /** 99 | * base64解密方法 100 | * @param plainText 101 | * @return 102 | */ 103 | public static String decodedBase64(String plainText) { 104 | byte[] decoded = null; 105 | try { 106 | byte[] bytes = plainText.getBytes("UTF-8"); 107 | decoded = Base64.getDecoder().decode(bytes); 108 | return new String(decoded); 109 | } catch (Exception e) { 110 | e.printStackTrace(); 111 | } 112 | return null; 113 | } 114 | 115 | /** 116 | * description: 订单code生成器 117 | * @param 118 | * @return {@link } 119 | * createdBy:wanhao 120 | * created:2018年08月02日 121 | * */ 122 | public static void getOrderId(){ 123 | Integer hashCodeV = UUID.randomUUID().toString().hashCode(); 124 | if (hashCodeV < 0) {//有可能是负数 125 | hashCodeV = -hashCodeV; 126 | } 127 | // 0 代表前面补充0 128 | // 4 代表长度为4 129 | // d 代表参数为正数型 130 | String orderId= new Random().nextInt(9) + String.format("%015d", System.currentTimeMillis() + hashCodeV); 131 | System.out.println(orderId.length()); 132 | } 133 | 134 | 135 | } 136 | -------------------------------------------------------------------------------- /saas-mycat/README.md: -------------------------------------------------------------------------------- 1 | # SaaS 2 | 3 | 说明: 4 | 多租户模式也就是实现单应用的数据库动态切换.根据前端用户带有的数据库标识访问对应的数据库. 5 | 6 | 整体实现依赖 Mycat的注解方式 /*#mycat:schema=schema_name*/ sql 7 | 8 | 1.schema_name 通过dubbo的RpcContext进行传递至DAO层. @see com.hitler.common.dubbo.filter.AuthenticationFilter 9 | 10 | 2.在DAO 层通过Hibernate jpa 拦截器在所有的 HQL/SQL 执行之前加入MyCat定义的注解. @see com.hitler.common.aop.CheageSchemaInterceptor 11 | 12 | 3.SQL的路由工作交给Mycat完成. 13 | 14 | 15 | 环境说明: 16 | 17 | 1.项目由maven构建.于pom内修改私服地址,当然不修改也没关系.默认会索引中心库.打包运行脚本已实现,可一键运行maven命令 :clean install 18 | 19 | 2.项目 框架组成: mysql、mycat、spring、jpa (hibernate jpa)、dubbo. 20 | 21 | 3.项目内有JPA与spring结合的基础应用环境.需要对JPA与spring 有一定了解. 22 | 23 | 4.dubbo,http://dubbo.io ,此项目用的注册中心是zookeeper.所以最少需要安装一个节点的zookeeper. 24 | 25 | 5.当然最重要的点是mycat,需要安装mycat并配置出多个schema出来. 可自行查找文档配置. 26 | 27 | 28 | -------------------------------------------------------------------------------- /saas-mycat/saas/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | 6 | com.hitler 7 | seed 8 | 0.0.1 9 | 10 | 11 | saas 12 | jar 13 | 14 | 15 | 16 | com.alibaba 17 | fastjson 18 | 1.2.6 19 | 20 | 21 | 22 | com.alibaba 23 | druid 24 | 0.2.22 25 | 26 | 27 | 28 | javax.servlet 29 | servlet-api 30 | provided 31 | 32 | 33 | 34 | jstl 35 | jstl 36 | 1.2 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | src/main/java 45 | 46 | **/* 47 | **/*.xml 48 | **/*.txt 49 | 50 | 51 | 52 | src/main/resources 53 | 54 | src/main/resources/bin 55 | 56 | 57 | 58 | src/main/resources/bin 59 | true 60 | bin 61 | 62 | 63 | 64 | 65 | 66 | org.apache.maven.plugins 67 | maven-jar-plugin 68 | 2.6 69 | 70 | 71 | com/ 72 | 73 | 74 | 75 | 76 | 77 | 78 | DAO 79 | package 80 | 81 | jar 82 | 83 | 84 | 85 | -dao-${project.version} 86 | ${project.artifactId} 87 | 88 | com/hitler/line 89 | 90 | 91 | 92 | com.hitler.server.DAOProvider 93 | true 94 | lib/ 95 | false 96 | 97 | 98 | . 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | maven-assembly-plugin 109 | 110 | 111 | package 112 | 113 | single 114 | 115 | 116 | 117 | 118 | 119 | 120 | src/main/resources/pak/provider/provider-assembly.xml 121 | 122 | 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Class-Path: 3 | 4 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter: -------------------------------------------------------------------------------- 1 | scma = com.hitler.common.dubbo.filter.AuthenticationFilter -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/META-INF/persistence.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | org.hibernate.jpa.HibernatePersistenceProvider 8 | 9 | com.hitler.model.User 10 | com.hitler.model.business.Record 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/aop/CheageSchemaInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.aop; 2 | 3 | import org.apache.commons.lang.StringUtils; 4 | import org.hibernate.EmptyInterceptor; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import com.alibaba.dubbo.rpc.RpcContext; 9 | import com.hitler.common.dubbo.RpcContextAttachment; 10 | 11 | /** 12 | * Mycat结合dubbo消费端域名动态改变schema 13 | * @author JT 14 | * @date 2016/04/07 18:33:00 15 | */ 16 | public class CheageSchemaInterceptor extends EmptyInterceptor { 17 | 18 | private static final long serialVersionUID = 1L; 19 | private static Logger logger = LoggerFactory 20 | .getLogger(CheageSchemaInterceptor.class); 21 | 22 | @Override 23 | public String onPrepareStatement(String sql) { 24 | String schema_name = followRpcSchemaName(); 25 | String full_sql = sql; 26 | if (StringUtils.isNotEmpty(schema_name)) { 27 | String mycat_annotation = "/*#mycat:schema=" + schema_name + "*/ "; 28 | full_sql = mycat_annotation + sql; 29 | } 30 | logger.info("prepare " + sql); 31 | return super.onPrepareStatement(full_sql); 32 | } 33 | 34 | private String followRpcSchemaName() { 35 | String tenant_region = RpcContext.getContext().getAttachment( 36 | RpcContextAttachment.ATTR_T_SCHEMA); 37 | return tenant_region; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/aop/RetriableTransaction.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.aop; 2 | 3 | import static java.lang.annotation.ElementType.METHOD; 4 | 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | import javax.persistence.OptimisticLockException; 10 | 11 | import org.springframework.orm.ObjectOptimisticLockingFailureException; 12 | 13 | /** 14 | * 15 | * 事务重试注解 16 | * @author onsoul@qq.com 17 | * @date 2016-4-12下午4:16:04 18 | * 19 | */ 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Target(value = { METHOD }) 22 | public @interface RetriableTransaction { 23 | 24 | int maxRetries() default 100; 25 | 26 | Class[] retryFor() default {ObjectOptimisticLockingFailureException.class, OptimisticLockException.class}; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/aop/RetriableTransactionInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.aop; 2 | 3 | import java.lang.reflect.Method; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | import org.apache.commons.logging.Log; 8 | import org.apache.commons.logging.LogFactory; 9 | import org.aspectj.lang.ProceedingJoinPoint; 10 | import org.aspectj.lang.annotation.Around; 11 | import org.aspectj.lang.annotation.Aspect; 12 | import org.aspectj.lang.reflect.MethodSignature; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.stereotype.Component; 15 | import org.springframework.transaction.PlatformTransactionManager; 16 | import org.springframework.transaction.TransactionDefinition; 17 | import org.springframework.transaction.TransactionStatus; 18 | import org.springframework.transaction.support.DefaultTransactionDefinition; 19 | 20 | 21 | 22 | /** 23 | * 事务重试拦截器 24 | * @author onsoul@qq.com 25 | * @date 2016-4-12下午4:18:11 26 | */ 27 | @Aspect 28 | @Component 29 | public class RetriableTransactionInterceptor { 30 | 31 | private static final Log LOGGER = LogFactory.getLog(RetriableTransactionInterceptor.class); 32 | 33 | @Autowired 34 | private PlatformTransactionManager transactionManager; 35 | 36 | @Around("@annotation(com.hitler.common.aop.annotation.RetriableTransaction)") 37 | public Object retry(ProceedingJoinPoint pjp) throws Throwable { 38 | MethodSignature signature = (MethodSignature) pjp.getSignature(); 39 | Method method = signature.getMethod(); 40 | RetriableTransaction annotation = method.getAnnotation(RetriableTransaction.class); 41 | int maxAttempts = annotation.maxRetries(); 42 | int attemptCount = 0; 43 | List> exceptions = Arrays.asList(annotation.retryFor()); 44 | Throwable failure = null; 45 | TransactionStatus currentTransactionStatus = null; 46 | String businessName = pjp.getTarget().toString(); 47 | businessName = businessName.substring(0, businessName.lastIndexOf("@")) + "." + method.getName(); 48 | do { 49 | attemptCount++; 50 | try { 51 | DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition(); 52 | transactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); 53 | currentTransactionStatus = transactionManager.getTransaction(transactionDefinition); 54 | Object returnValue = pjp.proceed(); 55 | transactionManager.commit(currentTransactionStatus); 56 | return returnValue; 57 | } catch (Throwable t) { 58 | if (!exceptions.contains(t.getClass())) { 59 | throw t; 60 | } 61 | if (currentTransactionStatus != null && !currentTransactionStatus.isCompleted()) { 62 | transactionManager.rollback(currentTransactionStatus); 63 | failure = t; 64 | } 65 | LOGGER.debug("事务重试:["+businessName+":"+attemptCount+"/"+maxAttempts+"]"); 66 | } 67 | } while (attemptCount < maxAttempts); 68 | LOGGER.debug("事务重试:["+businessName+":已达最大重试次数]"); 69 | throw failure; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/aop/ServiceInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.aop; 2 | 3 | import java.util.Map; 4 | import java.util.concurrent.atomic.AtomicLong; 5 | 6 | import org.apache.commons.lang.time.StopWatch; 7 | import org.apache.commons.logging.Log; 8 | import org.apache.commons.logging.LogFactory; 9 | import org.aspectj.lang.ProceedingJoinPoint; 10 | import org.aspectj.lang.annotation.Around; 11 | import org.aspectj.lang.annotation.Aspect; 12 | import org.springframework.stereotype.Component; 13 | 14 | import com.google.common.collect.Maps; 15 | 16 | /** 17 | * 服务调用次数拦截器 18 | * @author onsoul@qq.com 19 | * @date 2016-4-12下午4:18:28 20 | */ 21 | @Component 22 | @Aspect 23 | public class ServiceInterceptor { 24 | 25 | private static final Log LOGGER = LogFactory.getLog("服务拦截器"); 26 | 27 | private static final Map serviceTimes = Maps.newConcurrentMap(); 28 | 29 | @Around("execution(* com.hitler.service..*.*(..))") 30 | public Object logServiceTime(ProceedingJoinPoint pjp) throws Throwable { 31 | StopWatch watch = new StopWatch(); 32 | watch.start(); 33 | Object retVal = pjp.proceed(); 34 | watch.stop(); 35 | String str = pjp.getTarget().toString(); 36 | String service = str.substring(str.lastIndexOf(".")+1, str.lastIndexOf("@")) + "." + pjp.getSignature().getName(); 37 | AtomicLong times = serviceTimes.get(service); 38 | if (times == null) { 39 | times = new AtomicLong(0L); 40 | serviceTimes.put(service, times); 41 | } 42 | times.incrementAndGet(); 43 | LOGGER.info(String.format("%s [耗时: %dms,调用次数: %d]", service, watch.getTime(), times.longValue())); 44 | return retVal; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/dozer/converters/DateTimeConverter.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.dozer.converters; 2 | 3 | import java.util.Calendar; 4 | import java.util.Date; 5 | 6 | import org.dozer.CustomConverter; 7 | import org.dozer.MappingException; 8 | import org.joda.time.DateTime; 9 | 10 | public class DateTimeConverter implements CustomConverter { 11 | 12 | @Override 13 | public Object convert(Object existingDestinationFieldValue, Object sourceFieldValue, Class destinationClass, Class sourceClass) { 14 | 15 | if (sourceFieldValue == null) { 16 | return null; 17 | } 18 | 19 | if (sourceFieldValue instanceof Date) { 20 | return new DateTime(sourceFieldValue); 21 | } else if (sourceFieldValue instanceof DateTime) { 22 | Calendar result; 23 | if (existingDestinationFieldValue == null) { 24 | result = Calendar.getInstance(); 25 | } else { 26 | result = (Calendar) existingDestinationFieldValue; 27 | } 28 | result.setTimeInMillis(((DateTime) sourceFieldValue).getMillis()); 29 | return result.getTime(); 30 | } 31 | 32 | throw new MappingException("Misconfigured/unsupported mapping"); 33 | 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/dto/PersistentDTO.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.dto; 2 | 3 | import java.io.Serializable; 4 | 5 | import com.hitler.common.dto.support.GenericDTO; 6 | 7 | 8 | /** 9 | * 数据持久对象 10 | * @author onsoul@qq.com 11 | * @date 2016-4-12下午4:20:13 12 | * @param 主键 13 | */ 14 | public abstract class PersistentDTO extends GenericDTO { 15 | 16 | private static final long serialVersionUID = -7604988709496150282L; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/dto/TransientDTO.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.dto; 2 | 3 | import java.io.Serializable; 4 | 5 | import com.hitler.common.dto.support.GenericDTO; 6 | 7 | /** 8 | * @author User 9 | * 瞬态数据传输对象 10 | * @param 11 | */ 12 | public abstract class TransientDTO extends GenericDTO { 13 | 14 | private static final long serialVersionUID = 6693846907130500855L; 15 | 16 | @Override 17 | public PK getId() { 18 | return null; 19 | } 20 | 21 | @Override 22 | public void setId(PK id){ 23 | 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/dto/annotation/DisallowedField.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.dto.annotation; 2 | 3 | import static java.lang.annotation.ElementType.FIELD; 4 | 5 | import java.lang.annotation.Retention; 6 | import java.lang.annotation.RetentionPolicy; 7 | import java.lang.annotation.Target; 8 | 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Target(value = { FIELD }) 11 | public @interface DisallowedField { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/dto/support/GenericDTO.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.dto.support; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | 6 | /** 7 | * @author Lane 8 | * 数据传输对象抽象类 9 | * 10 | */ 11 | public abstract class GenericDTO implements 12 | IGenericDTO { 13 | private static final long serialVersionUID = 2572279813924674692L; 14 | 15 | private String createdBy; 16 | 17 | private Date createdDate; 18 | 19 | private String lastModifiedBy; 20 | 21 | private Date lastModifiedDate; 22 | 23 | public String getCreatedBy() { 24 | return createdBy; 25 | } 26 | 27 | public void setCreatedBy(String createdBy) { 28 | this.createdBy = createdBy; 29 | } 30 | 31 | public Date getCreatedDate() { 32 | return createdDate; 33 | } 34 | 35 | public void setCreatedDate(Date createdDate) { 36 | this.createdDate = createdDate; 37 | } 38 | 39 | public String getLastModifiedBy() { 40 | return lastModifiedBy; 41 | } 42 | 43 | public void setLastModifiedBy(String lastModifiedBy) { 44 | this.lastModifiedBy = lastModifiedBy; 45 | } 46 | 47 | public Date getLastModifiedDate() { 48 | return lastModifiedDate; 49 | } 50 | 51 | public void setLastModifiedDate(Date lastModifiedDate) { 52 | this.lastModifiedDate = lastModifiedDate; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/dto/support/GenericTable.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.dto.support; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import javax.persistence.criteria.CriteriaBuilder; 8 | import javax.persistence.criteria.Path; 9 | import javax.persistence.criteria.Root; 10 | import javax.persistence.criteria.Selection; 11 | 12 | import com.google.common.collect.Lists; 13 | import com.hitler.common.util.BeanMapper; 14 | 15 | /** 16 | * @author Lane 17 | * 18 | * 通用表格抽象类 19 | * 20 | * @param 21 | * @param 22 | */ 23 | public abstract class GenericTable implements IGenericTable { 24 | 25 | private static final long serialVersionUID = 6655607942888642862L; 26 | 27 | private List data; 28 | 29 | private Long recordsTotal; 30 | 31 | private Long recordsFiltered; 32 | 33 | @Override 34 | public List getData() { 35 | return data; 36 | } 37 | 38 | @Override 39 | public void setData(List data) { 40 | this.data = data; 41 | } 42 | 43 | @Override 44 | public Long getRecordsTotal() { 45 | return recordsTotal; 46 | } 47 | 48 | @Override 49 | public void setRecordsTotal(Long recordsTotal) { 50 | this.recordsTotal = recordsTotal; 51 | } 52 | 53 | @Override 54 | public Long getRecordsFiltered() { 55 | return recordsFiltered; 56 | } 57 | 58 | @Override 59 | public void setRecordsFiltered(Long recordsFiltered) { 60 | this.recordsFiltered = recordsFiltered; 61 | } 62 | 63 | @Override 64 | public Map map() throws IllegalAccessException, InvocationTargetException { 65 | return BeanMapper.objectToMap(this); 66 | } 67 | 68 | protected Path getAttributeName(Root root, String attributeName) { 69 | return root.get(attributeName); 70 | } 71 | 72 | protected List> getSelections(Root root, CriteriaBuilder builder, String... attributeNames) { 73 | List> columns = Lists.newArrayList(); 74 | for(String attributeName : attributeNames) { 75 | columns.add(builder.sum(this.getAttributeName(root, attributeName))); 76 | } 77 | return columns; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/dto/support/IGenericDTO.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.dto.support; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * @author Lane 7 | * 8 | * 数据传输对象接口 9 | * 10 | */ 11 | public interface IGenericDTO extends Serializable { 12 | 13 | PK getId(); 14 | 15 | void setId(PK id); 16 | /** 17 | * 构造Create DTO 18 | */ 19 | // public void makeCreateDTO(); 20 | 21 | /** 22 | * 构造Update DTO 23 | */ 24 | // public void makeUpdateDTO(); 25 | } 26 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/dto/support/IGenericTable.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.dto.support; 2 | 3 | import java.io.Serializable; 4 | import java.lang.reflect.InvocationTargetException; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | import com.hitler.common.repository.AggregateExpression; 9 | 10 | /** 11 | * @author Lane 12 | * 13 | * 通用表格接口 14 | * 15 | * @param 数据传输对象类型 16 | * @param 实体类型 17 | */ 18 | public interface IGenericTable extends AggregateExpression, Serializable { 19 | 20 | /** 21 | * 获取表格数据 22 | * @return 23 | */ 24 | List getData(); 25 | 26 | /** 27 | * 设置表格数据 28 | * @param data 29 | */ 30 | void setData(List data); 31 | 32 | /** 33 | * 获取总记录数 34 | * @return 35 | */ 36 | Long getRecordsTotal(); 37 | 38 | /** 39 | * 设置总记录数 40 | * @param recordsTotal 41 | */ 42 | void setRecordsTotal(Long recordsTotal); 43 | 44 | /** 45 | * 获取总记录数 46 | * @return 47 | */ 48 | Long getRecordsFiltered(); 49 | 50 | /** 51 | * 设置总记录数 52 | * @param recordsFiltered 53 | */ 54 | void setRecordsFiltered(Long recordsFiltered); 55 | 56 | /** 57 | * 转为Map对象 58 | * @return 59 | * @throws IllegalAccessException 60 | * @throws InvocationTargetException 61 | */ 62 | Map map() throws IllegalAccessException, InvocationTargetException; 63 | 64 | } 65 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/dto/support/PaginationAoDataDTO.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.dto.support; 2 | 3 | import java.io.Serializable; 4 | 5 | import com.hitler.common.repository.Sorter; 6 | 7 | /** 8 | * @author 传递 9 | * 10 | * 客户端表格(JQuery Datatable)分页传递参数 通用对象 11 | * 12 | */ 13 | public abstract class PaginationAoDataDTO extends GenericDTO { 14 | private static final long serialVersionUID = 2572279813924674692L; 15 | 16 | /** 17 | * 请求次数 18 | */ 19 | private String sEcho; 20 | 21 | /** 22 | * 显示的列数 23 | */ 24 | private Integer iColumns; 25 | 26 | /** 27 | * 服务器返回后显示的列名,格式 , , ,.... 28 | */ 29 | private String sColumns; 30 | 31 | /** 32 | * 显示开始行数 33 | */ 34 | private Integer iDisplayStart; 35 | 36 | /** 37 | * 每页显示行数 38 | */ 39 | private Integer iDisplayLength; 40 | 41 | /** 42 | * 当前排序列索引(从0开始) 43 | */ 44 | private Integer iSortCol_0; 45 | 46 | /** 47 | * 当前排序列排序方向 48 | */ 49 | private String sSortDir_0; 50 | 51 | /** 52 | * 当前排序列个数 53 | */ 54 | private Integer iSortingCols; 55 | 56 | /*未知参数,暂未用到 57 | mDataProp_0: id 58 | sSearch_0: 59 | bRegex_0: false 60 | bSearchable_0: true 61 | bSortable_0: false 62 | mDataProp_1: firstName 63 | sSearch_1: 64 | bRegex_1: false 65 | bSearchable_1: true 66 | bSortable_1: true 67 | mDataProp_2: lastName 68 | sSearch_2: 69 | bRegex_2: false 70 | bSearchable_2: true 71 | bSortable_2: true 72 | mDataProp_3: id 73 | sSearch_3: 74 | bRegex_3: false 75 | bSearchable_3: true 76 | bSortable_3: true 77 | sSearch: 78 | bRegex: false 79 | */ 80 | 81 | public String getsEcho() { 82 | return sEcho; 83 | } 84 | 85 | public void setsEcho(String sEcho) { 86 | this.sEcho = sEcho; 87 | } 88 | 89 | public Integer getiColumns() { 90 | return iColumns; 91 | } 92 | 93 | public void setiColumns(Integer iColumns) { 94 | this.iColumns = iColumns; 95 | } 96 | 97 | public String getsColumns() { 98 | return sColumns; 99 | } 100 | 101 | public void setsColumns(String sColumns) { 102 | this.sColumns = sColumns; 103 | } 104 | 105 | public Integer getiDisplayStart() { 106 | return iDisplayStart; 107 | } 108 | 109 | public void setiDisplayStart(Integer iDisplayStart) { 110 | this.iDisplayStart = iDisplayStart; 111 | } 112 | 113 | public Integer getiDisplayLength() { 114 | return iDisplayLength; 115 | } 116 | 117 | public void setiDisplayLength(Integer iDisplayLength) { 118 | this.iDisplayLength = iDisplayLength; 119 | } 120 | 121 | public Integer getiSortCol_0() { 122 | return iSortCol_0; 123 | } 124 | 125 | public void setiSortCol_0(Integer iSortCol_0) { 126 | this.iSortCol_0 = iSortCol_0; 127 | } 128 | 129 | public String getsSortDir_0() { 130 | return sSortDir_0; 131 | } 132 | 133 | public void setsSortDir_0(String sSortDir_0) { 134 | this.sSortDir_0 = sSortDir_0; 135 | } 136 | 137 | public Integer getiSortingCols() { 138 | return iSortingCols; 139 | } 140 | 141 | public void setiSortingCols(Integer iSortingCols) { 142 | this.iSortingCols = iSortingCols; 143 | } 144 | 145 | /** 146 | * 当前显示页索引(从0开始) 147 | * @return 148 | */ 149 | public Integer getDisplayIndex(){ 150 | return iDisplayStart/iDisplayLength; 151 | } 152 | 153 | /** 154 | * 当前排序列字符串,包含排序方向 155 | * @return 156 | */ 157 | public String getSortColStr(){ 158 | if (sColumns != null && sColumns.length() > 1){ 159 | String[] cols = sColumns.split(","); 160 | if (cols.length >0 && cols.length > iSortCol_0){ 161 | if (cols[iSortCol_0].trim().length() >0){ 162 | return " order by " + cols[iSortCol_0] + " " + getsSortDir_0(); 163 | } 164 | } 165 | } 166 | return ""; 167 | } 168 | 169 | /** 170 | * 当前排序对象 171 | * @return 172 | */ 173 | public Sorter getSorter(){ 174 | if (sColumns != null && sColumns.length() > 1){ 175 | String[] cols = sColumns.split(","); 176 | if (cols.length >0 && cols.length > iSortCol_0){ 177 | if (cols[iSortCol_0].trim().length() >0){ 178 | Sorter sorter = new Sorter(getsSortDir_0(), cols[iSortCol_0]); 179 | return sorter; 180 | } 181 | } 182 | } 183 | return null; 184 | 185 | } 186 | 187 | 188 | } 189 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/dubbo/RpcContextAttachment.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.dubbo; 2 | 3 | public class RpcContextAttachment { 4 | 5 | public static final String ATTR_NAME_USERID = "t.userid"; 6 | public static final String ATTR_NAME_USERNAME = "t.username"; 7 | public static final String ATTR_T_SCHEMA = "t.schema"; 8 | 9 | } 10 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/dubbo/filter/AuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.dubbo.filter; 2 | 3 | import com.alibaba.dubbo.rpc.Filter; 4 | import com.alibaba.dubbo.rpc.Invocation; 5 | import com.alibaba.dubbo.rpc.Invoker; 6 | import com.alibaba.dubbo.rpc.Result; 7 | import com.alibaba.dubbo.rpc.RpcContext; 8 | import com.alibaba.dubbo.rpc.RpcException; 9 | import com.hitler.common.dubbo.RpcContextAttachment; 10 | 11 | /** 12 | * RPC(Dubbo服务)调用传递ThreadLocal变量过滤器 13 | * @author onsoul@qq.com 14 | * @date 2016-4-12下午4:20:54 15 | */ 16 | public class AuthenticationFilter implements Filter { 17 | 18 | public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { 19 | String schema_name="T1"; 20 | System.out.println("消费端调用到过滤器!设置Schema."); 21 | 22 | //此过滤器在执行服务调用时调用,由Hibernate 拦截器 获取出来注入到SQL前辍.以完成Schema切换 23 | RpcContext.getContext().setAttachment(RpcContextAttachment.ATTR_T_SCHEMA, schema_name); 24 | Result result = invoker.invoke(invocation); 25 | return result; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/exception/BusinessException.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.exception; 2 | 3 | public class BusinessException extends Exception { 4 | 5 | private static final long serialVersionUID = 5654145024170831545L; 6 | 7 | private String code; 8 | 9 | public BusinessException(String code) { 10 | this.code = code; 11 | } 12 | 13 | public BusinessException(String code, String msg) { 14 | super(msg); 15 | this.code = code; 16 | } 17 | 18 | public String getCode() { 19 | return code; 20 | } 21 | 22 | @Override 23 | public final String toString() { 24 | String msg = getCode(); 25 | if (getMessage() != null && getMessage().trim().length() > 0) 26 | msg = ":" + getMessage(); 27 | return msg; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/exception/EntityNotExistsException.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.exception; 2 | 3 | import com.hitler.common.exception.BusinessException; 4 | 5 | /** 6 | * 记录不存在 7 | * @author User 8 | * 9 | */ 10 | public class EntityNotExistsException extends BusinessException { 11 | 12 | private static final long serialVersionUID = -563592502981718470L; 13 | 14 | private static final String CODE = EntityNotExistsException.class.getName(); 15 | 16 | public static final EntityNotExistsException ERROR = new EntityNotExistsException(); 17 | 18 | public EntityNotExistsException() { 19 | super(CODE); 20 | } 21 | 22 | public EntityNotExistsException(String code) { 23 | super(code); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/model/annotation/Checkable.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.model.annotation; 2 | 3 | import static java.lang.annotation.ElementType.ANNOTATION_TYPE; 4 | import static java.lang.annotation.ElementType.FIELD; 5 | import static java.lang.annotation.ElementType.METHOD; 6 | 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(value = { FIELD, METHOD, ANNOTATION_TYPE }) 13 | public @interface Checkable { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/model/annotation/Checked.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.model.annotation; 2 | 3 | import static java.lang.annotation.ElementType.ANNOTATION_TYPE; 4 | import static java.lang.annotation.ElementType.FIELD; 5 | import static java.lang.annotation.ElementType.METHOD; 6 | 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(value = { FIELD, METHOD, ANNOTATION_TYPE }) 13 | public @interface Checked { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/model/auditing/DefaultAuditorAware.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.model.auditing; 2 | 3 | import org.springframework.data.domain.AuditorAware; 4 | 5 | import com.alibaba.dubbo.rpc.RpcContext; 6 | import com.hitler.common.dubbo.RpcContextAttachment; 7 | 8 | /** 9 | * 默认操作者字段值填充 10 | * @author onsoul@qq.com 11 | * @date 2016-4-12下午4:22:42 12 | */ 13 | public class DefaultAuditorAware implements AuditorAware { 14 | 15 | public String getCurrentAuditor() { 16 | String username = RpcContext.getContext().getAttachment(RpcContextAttachment.ATTR_NAME_USERNAME); 17 | return null == username ? "SYSTEM" : username; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/model/enumeration/DataType.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.model.enumeration; 2 | 3 | public enum DataType { 4 | NONE, INTEGER, NUMERIC, STRING, BOOLEAN, DATETIME 5 | } 6 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/model/enumeration/support/PersistEnum.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.model.enumeration.support; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * 需要持久化的enum类,都需要实现的接口 7 | * 8 | * @author Kylin 9 | * 2015-7-23 下午4:11:04 10 | * @param 11 | */ 12 | public interface PersistEnum> { 13 | /** 14 | * 获取被持久化字段的值 15 | * 16 | * @return 被持久化字段的值 17 | */ 18 | String getPersistedValue(); 19 | 20 | /** 21 | * 由被持久化的字段的值获取枚举类型 22 | * 23 | * @param persistedValue 24 | * @return 25 | */ 26 | E returnEnum(String persistedValue); 27 | 28 | /** 29 | * 获取枚举的所有枚举项 30 | * 31 | * @return map 32 | */ 33 | Map getAllValueMap(); 34 | } 35 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/model/enumeration/support/TopEnumType.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.model.enumeration.support; 2 | 3 | import java.io.Serializable; 4 | import java.lang.reflect.InvocationTargetException; 5 | import java.lang.reflect.Method; 6 | import java.sql.PreparedStatement; 7 | import java.sql.ResultSet; 8 | import java.sql.SQLException; 9 | import java.sql.Types; 10 | import java.util.Properties; 11 | 12 | import org.hibernate.HibernateException; 13 | import org.hibernate.engine.spi.SessionImplementor; 14 | import org.hibernate.usertype.ParameterizedType; 15 | import org.hibernate.usertype.UserType; 16 | import org.springframework.util.ObjectUtils; 17 | 18 | /** 19 | * 用户持久化枚举类型的用户自定义hibernate映射类型 20 | *

21 | * 使用此类型来进行映射的枚举类,必须实现{@link com.hitler.common.model.enumeration.support.PersistEnum} 接口 22 | * 23 | * @author Kylin 24 | * 2015-7-23 下午4:12:28 25 | */ 26 | public class TopEnumType implements UserType, ParameterizedType { 27 | 28 | private Method returnEnum; 29 | 30 | private Method getPersistedValue; 31 | 32 | private Class> enumClass; 33 | 34 | private Object enumObject; 35 | 36 | @SuppressWarnings("unchecked") 37 | @Override 38 | public void setParameterValues(Properties parameters) { 39 | if (parameters != null) { 40 | try { 41 | enumClass = (Class>) Class.forName(parameters.get("enumClass").toString()); 42 | enumObject = enumClass.getEnumConstants()[0]; 43 | getPersistedValue = enumClass.getMethod("getPersistedValue"); 44 | returnEnum = enumClass.getMethod("returnEnum", 45 | new Class[] { String.class }); 46 | } catch (SecurityException e) { 47 | e.printStackTrace(); 48 | } catch (NoSuchMethodException e) { 49 | e.printStackTrace(); 50 | } catch (ClassNotFoundException e) { 51 | e.printStackTrace(); 52 | } 53 | } 54 | } 55 | 56 | @Override 57 | public int[] sqlTypes() { 58 | return new int[] { Types.VARCHAR }; 59 | } 60 | 61 | @SuppressWarnings("rawtypes") 62 | @Override 63 | public Class returnedClass() { 64 | return enumClass; 65 | } 66 | 67 | @Override 68 | public boolean equals(Object x, Object y) throws HibernateException { 69 | return ObjectUtils.nullSafeEquals(x, y); 70 | } 71 | 72 | @Override 73 | public int hashCode(Object x) throws HibernateException { 74 | return x.hashCode(); 75 | } 76 | 77 | @Override 78 | public Object nullSafeGet(ResultSet rs, String[] names, 79 | SessionImplementor session, Object owner) 80 | throws HibernateException, SQLException { 81 | String value = rs.getString(names[0]); 82 | Object returnVal = null; 83 | 84 | if (value == null) 85 | return null; 86 | else { 87 | try { 88 | returnVal = returnEnum 89 | .invoke(enumObject, new Object[] { value }); 90 | } catch (IllegalArgumentException e) { 91 | e.printStackTrace(); 92 | } catch (IllegalAccessException e) { 93 | e.printStackTrace(); 94 | } catch (InvocationTargetException e) { 95 | e.printStackTrace(); 96 | } 97 | } 98 | return returnVal; 99 | } 100 | 101 | @Override 102 | public void nullSafeSet(PreparedStatement st, Object value, int index, 103 | SessionImplementor session) throws HibernateException, SQLException { 104 | String prepStmtVal = null; 105 | 106 | if (value == null) { 107 | st.setObject(index, null); 108 | } else { 109 | try { 110 | prepStmtVal = getPersistedValue.invoke(value).toString(); 111 | st.setString(index, prepStmtVal); 112 | } catch (IllegalArgumentException e) { 113 | e.printStackTrace(); 114 | } catch (IllegalAccessException e) { 115 | e.printStackTrace(); 116 | } catch (InvocationTargetException e) { 117 | e.printStackTrace(); 118 | } 119 | } 120 | } 121 | 122 | @Override 123 | public Object deepCopy(Object value) throws HibernateException { 124 | return value; 125 | } 126 | 127 | @Override 128 | public boolean isMutable() { 129 | return false; 130 | } 131 | 132 | @Override 133 | public Serializable disassemble(Object value) throws HibernateException { 134 | Object deepCopy = deepCopy(value); 135 | 136 | if (!(deepCopy instanceof Serializable)) 137 | return (Serializable) deepCopy; 138 | 139 | return null; 140 | } 141 | 142 | @Override 143 | public Object assemble(Serializable cached, Object owner) 144 | throws HibernateException { 145 | return deepCopy(cached); 146 | } 147 | 148 | @Override 149 | public Object replace(Object original, Object target, Object owner) 150 | throws HibernateException { 151 | return deepCopy(original); 152 | } 153 | 154 | } 155 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/model/json/serialize/CurrencySerializer.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.model.json.serialize; 2 | 3 | import java.io.IOException; 4 | import java.text.DecimalFormat; 5 | 6 | import com.fasterxml.jackson.core.JsonGenerator; 7 | import com.fasterxml.jackson.core.JsonProcessingException; 8 | import com.fasterxml.jackson.databind.JsonSerializer; 9 | import com.fasterxml.jackson.databind.SerializerProvider; 10 | 11 | public class CurrencySerializer extends JsonSerializer { 12 | 13 | private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.00"); 14 | 15 | @Override 16 | public void serialize(Double value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { 17 | jgen.writeString(DECIMAL_FORMAT.format(value)); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/model/listener/CheckingEntityListener.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.model.listener; 2 | 3 | import java.lang.reflect.Field; 4 | import java.util.ArrayList; 5 | import java.util.Date; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | import javax.persistence.PostLoad; 11 | import javax.persistence.PrePersist; 12 | import javax.persistence.PreUpdate; 13 | 14 | import org.apache.commons.logging.Log; 15 | import org.apache.commons.logging.LogFactory; 16 | import org.springframework.data.util.ReflectionUtils.AnnotationFieldFilter; 17 | import org.springframework.util.ReflectionUtils; 18 | 19 | import com.hitler.common.model.annotation.Checkable; 20 | import com.hitler.common.util.MD5Utils; 21 | 22 | public class CheckingEntityListener { 23 | 24 | private static final Log LOGGER = LogFactory.getLog(CheckingEntityListener.class); 25 | 26 | private static final String MD5_KEY = "19880704"; 27 | 28 | @PrePersist 29 | @PreUpdate 30 | public void encode(Object target) { 31 | AnnotationCheckingMetadata metadata = AnnotationCheckingMetadata.getMetadata(target.getClass()); 32 | if (metadata.isCheckable()) { 33 | StringBuilder sb = new StringBuilder(); 34 | for (Field field : metadata.getCheckedFields()) { 35 | ReflectionUtils.makeAccessible(field); 36 | Object value = ReflectionUtils.getField(field, target); 37 | if (value instanceof Date) { 38 | throw new RuntimeException("不支持时间类型字段加密!"); 39 | } 40 | sb.append(value).append(" - "); 41 | } 42 | sb.append(MD5_KEY); 43 | LOGGER.debug("加密数据:" + sb); 44 | String hex = MD5Utils.encode(sb.toString()); 45 | Field checksumField = metadata.getCheckableField(); 46 | ReflectionUtils.makeAccessible(checksumField); 47 | ReflectionUtils.setField(checksumField, target, hex); 48 | } 49 | } 50 | 51 | @PostLoad 52 | public void checking(Object target) { 53 | AnnotationCheckingMetadata metadata = AnnotationCheckingMetadata.getMetadata(target.getClass()); 54 | if (metadata.isCheckable()) { 55 | StringBuilder sb = new StringBuilder(); 56 | for (Field field : metadata.getCheckedFields()) { 57 | ReflectionUtils.makeAccessible(field); 58 | Object value = ReflectionUtils.getField(field, target); 59 | if (value instanceof Date) { 60 | throw new RuntimeException("不支持时间类型字段解密!"); 61 | } 62 | sb.append(value).append(" - "); 63 | } 64 | sb.append(MD5_KEY); 65 | LOGGER.debug("验证数据:" + sb); 66 | String hex = MD5Utils.encode(sb.toString()); 67 | Field checksumField = metadata.getCheckableField(); 68 | ReflectionUtils.makeAccessible(checksumField); 69 | String checksum = (String) ReflectionUtils.getField(checksumField, target); 70 | if (!checksum.equals(hex)) { 71 | //throw new RuntimeException("数据验证失败!"); 72 | } 73 | } 74 | } 75 | 76 | } 77 | 78 | class AnnotationCheckingMetadata { 79 | 80 | private static final Map, AnnotationCheckingMetadata> METADATA_CACHE = new ConcurrentHashMap, AnnotationCheckingMetadata>(); 81 | 82 | private static final AnnotationFieldFilter CHECKABLE_FILTER = new AnnotationFieldFilter(Checkable.class); 83 | private static final AnnotationFieldFilter CHECKED_FILTER = new AnnotationFieldFilter(Checkable.class); 84 | 85 | private Field checkableField; 86 | private List checkedFields = new ArrayList(); 87 | 88 | public AnnotationCheckingMetadata(Class type) { 89 | while (type != Object.class) { 90 | for (Field field : type.getDeclaredFields()) { 91 | if (CHECKABLE_FILTER.matches(field)) { 92 | this.checkableField = field; 93 | } else if (CHECKED_FILTER.matches(field)) { 94 | this.checkedFields.add(field); 95 | } 96 | } 97 | type = type.getSuperclass(); 98 | } 99 | } 100 | 101 | public static AnnotationCheckingMetadata getMetadata(Class type) { 102 | 103 | if (METADATA_CACHE.containsKey(type)) { 104 | return METADATA_CACHE.get(type); 105 | } 106 | 107 | AnnotationCheckingMetadata metadata = new AnnotationCheckingMetadata(type); 108 | METADATA_CACHE.put(type, metadata); 109 | return metadata; 110 | } 111 | 112 | public boolean isCheckable() { 113 | if (checkableField == null || checkedFields.size() == 0) { 114 | return false; 115 | } 116 | return true; 117 | } 118 | 119 | public Field getCheckableField() { 120 | return checkableField; 121 | } 122 | 123 | public List getCheckedFields() { 124 | return checkedFields; 125 | } 126 | 127 | 128 | } 129 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/model/menu/NavMenu.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.model.menu; 2 | 3 | import java.io.Serializable; 4 | import java.util.Collection; 5 | 6 | /** 7 | * 导航栏菜单vo 8 | * @author Kylin 9 | * 2015-10-10 上午9:44:27 10 | */ 11 | public class NavMenu implements Serializable { 12 | 13 | private static final long serialVersionUID = 1L; 14 | 15 | private Integer id; 16 | /** 17 | * 显示内容 18 | */ 19 | public String text; 20 | /** 21 | * 图标 22 | */ 23 | public String icon; 24 | /** 25 | * 子节点 26 | */ 27 | public Collection children; 28 | 29 | public Integer getId() { 30 | return id; 31 | } 32 | 33 | public void setId(Integer id) { 34 | this.id = id; 35 | } 36 | 37 | public String getText() { 38 | return text; 39 | } 40 | 41 | public void setText(String text) { 42 | this.text = text; 43 | } 44 | 45 | public String getIcon() { 46 | return icon; 47 | } 48 | 49 | public void setIcon(String icon) { 50 | this.icon = icon; 51 | } 52 | 53 | public Collection getChildren() { 54 | return children; 55 | } 56 | 57 | public void setChildren(Collection children) { 58 | this.children = children; 59 | } 60 | 61 | @Override 62 | public int hashCode() { 63 | final int prime = 31; 64 | int result = 1; 65 | result = prime * result + ((text == null) ? 0 : text.hashCode()); 66 | return result; 67 | } 68 | 69 | @Override 70 | public boolean equals(Object obj) { 71 | if (this == obj) 72 | return true; 73 | if (obj == null) 74 | return false; 75 | if (getClass() != obj.getClass()) 76 | return false; 77 | NavMenu other = (NavMenu) obj; 78 | if (text == null) { 79 | if (other.text != null) 80 | return false; 81 | } else if (!text.equals(other.text)) 82 | return false; 83 | return true; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/model/security/ShiroUser.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.model.security; 2 | 3 | import java.io.Serializable; 4 | 5 | import org.apache.commons.lang3.builder.EqualsBuilder; 6 | import org.apache.commons.lang3.builder.HashCodeBuilder; 7 | 8 | /** 9 | * 自定义Authentication对象,使得Subject除了携带用户的登录名外还可以携带更多信息. 10 | * 11 | * @author shujianhui 12 | * 13 | */ 14 | public class ShiroUser implements Serializable { 15 | private static final long serialVersionUID = 1L; 16 | public Integer id; 17 | public String username; 18 | public String password; 19 | public String salt; 20 | 21 | public String getPassword() { 22 | return password; 23 | } 24 | 25 | public void setPassword(String password) { 26 | this.password = password; 27 | } 28 | 29 | public String getSalt() { 30 | return salt; 31 | } 32 | 33 | public void setSalt(String salt) { 34 | this.salt = salt; 35 | } 36 | 37 | public ShiroUser(Integer id, String username,String password,String salt) { 38 | this.id = id; 39 | this.username = username; 40 | this.password=password; 41 | this.salt=salt; 42 | } 43 | 44 | /** 45 | * 本函数输出将作为默认的输出. 46 | */ 47 | @Override 48 | public String toString() { 49 | return username; 50 | } 51 | 52 | @Override 53 | public int hashCode() { 54 | return HashCodeBuilder.reflectionHashCode(this, "username"); 55 | } 56 | 57 | @Override 58 | public boolean equals(Object obj) { 59 | return EqualsBuilder.reflectionEquals(this, obj, "username"); 60 | } 61 | 62 | public Integer getId() { 63 | return id; 64 | } 65 | 66 | public void setId(Integer id) { 67 | this.id = id; 68 | } 69 | 70 | public String getUsername() { 71 | return username; 72 | } 73 | 74 | public void setUsername(String username) { 75 | this.username = username; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/model/support/AuditableEntity.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.model.support; 2 | 3 | import java.io.Serializable; 4 | import java.util.Date; 5 | 6 | import javax.persistence.Column; 7 | import javax.persistence.EntityListeners; 8 | import javax.persistence.MappedSuperclass; 9 | import javax.persistence.PrePersist; 10 | import javax.persistence.Temporal; 11 | import javax.persistence.TemporalType; 12 | 13 | import org.springframework.data.annotation.CreatedDate; 14 | import org.springframework.data.annotation.LastModifiedDate; 15 | import org.springframework.data.jpa.domain.support.AuditingEntityListener; 16 | 17 | import com.hitler.common.model.annotation.Checked; 18 | 19 | @MappedSuperclass 20 | @EntityListeners(AuditingEntityListener.class) 21 | public abstract class AuditableEntity extends PersistableEntity { 22 | 23 | private static final long serialVersionUID = 9150700774816395865L; 24 | 25 | /** 26 | * 创建者 27 | */ 28 | @Checked 29 | /*@CreatedBy*/ 30 | @Column(name="CREATED_BY", columnDefinition="varchar(16) DEFAULT '' COMMENT '创建者'") 31 | private String createdBy; 32 | 33 | /** 34 | * 创建时间 35 | */ 36 | @CreatedDate 37 | @Temporal(TemporalType.TIMESTAMP) 38 | @Column(name="CREATED_DATE", columnDefinition="TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'") 39 | private Date createdDate; 40 | 41 | /** 42 | * 操作者 43 | */ 44 | @Checked 45 | /*@LastModifiedBy*/ 46 | @Column(name="LAST_MODIFIED_BY", columnDefinition="varchar(16) COMMENT '操作者'") 47 | private String lastModifiedBy; 48 | 49 | /** 50 | * 操作时间 51 | */ 52 | @LastModifiedDate 53 | @Temporal(TemporalType.TIMESTAMP) 54 | @Column(name="LAST_MODIFIED_DATE", columnDefinition="TIMESTAMP NULL COMMENT '操作时间'") 55 | private Date lastModifiedDate; 56 | 57 | @PrePersist 58 | public void prePresist() { 59 | this.createdBy = this.lastModifiedBy; 60 | } 61 | 62 | public String getCreatedBy() { 63 | return createdBy; 64 | } 65 | 66 | public void setCreatedBy(String createdBy) { 67 | this.createdBy = createdBy; 68 | } 69 | 70 | public Date getCreatedDate() { 71 | return createdDate; 72 | } 73 | 74 | public void setCreatedDate(Date createdDate) { 75 | this.createdDate = createdDate; 76 | } 77 | 78 | public String getLastModifiedBy() { 79 | return lastModifiedBy; 80 | } 81 | 82 | public void setLastModifiedBy(String lastModifiedBy) { 83 | this.lastModifiedBy = lastModifiedBy; 84 | } 85 | 86 | public Date getLastModifiedDate() { 87 | return lastModifiedDate; 88 | } 89 | 90 | public void setLastModifiedDate(Date lastModifiedDate) { 91 | this.lastModifiedDate = lastModifiedDate; 92 | } 93 | 94 | 95 | 96 | } 97 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/model/support/CheckableEntity.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.model.support; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.MappedSuperclass; 6 | 7 | @MappedSuperclass 8 | //@EntityListeners(CheckingEntityListener.class) 9 | public abstract class CheckableEntity extends AuditableEntity { 10 | 11 | private static final long serialVersionUID = 2469813719494517116L; 12 | } 13 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/model/support/CustomPKPersistableEntity.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.model.support; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.Id; 6 | import javax.persistence.MappedSuperclass; 7 | 8 | import org.springframework.data.domain.Persistable; 9 | 10 | /** 11 | * 主键不需要自增长 12 | * 13 | * @author 14 | * 15 | * @param 16 | */ 17 | @MappedSuperclass 18 | public abstract class CustomPKPersistableEntity implements Persistable { 19 | 20 | 21 | /** 22 | * 23 | */ 24 | private static final long serialVersionUID = 4129264629296054711L; 25 | 26 | @Id 27 | private PK id; 28 | 29 | @Override 30 | public PK getId() { 31 | return id; 32 | } 33 | 34 | public void setId(PK id) { 35 | this.id = id; 36 | } 37 | @Override 38 | public boolean isNew() { 39 | return null == getId(); 40 | } 41 | 42 | @Override 43 | public boolean equals(Object obj) { 44 | if (null == obj) { 45 | return false; 46 | } 47 | if (this == obj) { 48 | return true; 49 | } 50 | if (!getClass().equals(obj.getClass())) { 51 | return false; 52 | } 53 | CustomPKPersistableEntity that = (CustomPKPersistableEntity) obj; 54 | return null == this.getId() ? false : this.getId().equals(that.getId()); 55 | } 56 | 57 | @Override 58 | public int hashCode() { 59 | int hashCode = 17; 60 | hashCode += null == getId() ? 0 : getId().hashCode() * 31; 61 | return hashCode; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/model/support/PersistableEntity.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.model.support; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | import javax.persistence.MappedSuperclass; 9 | 10 | import org.springframework.data.domain.Persistable; 11 | 12 | @MappedSuperclass 13 | public abstract class PersistableEntity implements Persistable { 14 | 15 | private static final long serialVersionUID = 8251232611423298391L; 16 | 17 | @Id 18 | @GeneratedValue(strategy = GenerationType.AUTO) 19 | private PK id; 20 | 21 | public PK getId() { 22 | return id; 23 | } 24 | 25 | public void setId(PK id) { 26 | this.id = id; 27 | } 28 | 29 | public boolean isNew() { 30 | return null == getId(); 31 | } 32 | 33 | @Override 34 | public boolean equals(Object obj) { 35 | if (null == obj) { 36 | return false; 37 | } 38 | if (this == obj) { 39 | return true; 40 | } 41 | if (!getClass().equals(obj.getClass())) { 42 | return false; 43 | } 44 | PersistableEntity that = (PersistableEntity) obj; 45 | return null == this.getId() ? false : this.getId().equals(that.getId()); 46 | } 47 | 48 | @Override 49 | public int hashCode() { 50 | int hashCode = 17; 51 | hashCode += null == getId() ? 0 : getId().hashCode() * 31; 52 | return hashCode; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/model/support/UserRelationEntity.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.model.support; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.MappedSuperclass; 7 | 8 | import com.hitler.common.model.annotation.Checked; 9 | import com.hitler.model.User; 10 | 11 | @MappedSuperclass 12 | public abstract class UserRelationEntity extends CheckableEntity { 13 | 14 | private static final long serialVersionUID = 7405522757503732970L; 15 | 16 | /** 17 | * 用户ID 18 | */ 19 | @Checked 20 | @Column(name = "USER_ID", columnDefinition="INT COMMENT '用户ID'", nullable = false) 21 | private Integer userId; 22 | 23 | /** 24 | * 用户帐号 25 | */ 26 | @Checked 27 | @Column(name = "USER_NAME", columnDefinition="varchar(16) COMMENT '用户帐号'", nullable = false) 28 | private String userName; 29 | 30 | /** 31 | * 上级ID 32 | */ 33 | @Checked 34 | @Column(name = "PARENT_ID", columnDefinition="INT COMMENT '上级ID'") 35 | private Integer parentId; 36 | 37 | /** 38 | * 直属上级帐号 39 | */ 40 | @Checked 41 | @Column(name = "PARENT_NAME", columnDefinition="varchar(16) COMMENT '直属上级帐号'") 42 | private String parentName; 43 | 44 | 45 | public UserRelationEntity() {} 46 | 47 | public UserRelationEntity(User user) { 48 | this.userId = user.getId(); 49 | this.userName = user.getUserName(); 50 | this.parentId = user.getParentId(); 51 | this.parentName = user.getParentName(); 52 | } 53 | 54 | public String getUserName() { 55 | return userName; 56 | } 57 | 58 | public void setUserName(String userName) { 59 | this.userName = userName; 60 | } 61 | 62 | public String getParentName() { 63 | return parentName; 64 | } 65 | 66 | public void setParentName(String parentName) { 67 | this.parentName = parentName; 68 | } 69 | 70 | public Integer getUserId() { 71 | return userId; 72 | } 73 | 74 | public void setUserId(Integer userId) { 75 | this.userId = userId; 76 | } 77 | 78 | public Integer getParentId() { 79 | return parentId; 80 | } 81 | 82 | public void setParentId(Integer parentId) { 83 | this.parentId = parentId; 84 | } 85 | 86 | public User getUser() { 87 | User user = new User(); 88 | user.setId(this.getUserId()); 89 | user.setUserName(this.getUserName()); 90 | user.setParentId(this.getParentId()); 91 | user.setParentName(this.getParentName()); 92 | return user; 93 | } 94 | 95 | /********************************* 96 | * 枚举 97 | *2015-05-08 98 | ***********************************/ 99 | public static enum UserRelationEntity_ { 100 | userId("userId"), 101 | userName("userName"), 102 | parentId("parentId"), 103 | parentName("parentName"); 104 | 105 | private final String _name; 106 | UserRelationEntity_(String _name) { 107 | this._name = _name; 108 | } 109 | public String getName() { 110 | return _name; 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/model/support/UserTreeRelationEntity.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.model.support; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.MappedSuperclass; 7 | 8 | import com.hitler.common.model.annotation.Checked; 9 | import com.hitler.common.model.support.PersistableEntity; 10 | import com.hitler.model.User; 11 | 12 | @MappedSuperclass 13 | public abstract class UserTreeRelationEntity extends PersistableEntity { 14 | 15 | private static final long serialVersionUID = 7405522757503732970L; 16 | 17 | /** 18 | * 用户ID 19 | */ 20 | @Checked 21 | @Column(name = "USER_ID", columnDefinition="INT COMMENT '用户ID'", nullable = false) 22 | private Integer userId; 23 | 24 | /** 25 | * 用户帐号 26 | */ 27 | @Checked 28 | @Column(name = "USER_NAME", columnDefinition="varchar(16) COMMENT '用户帐号'", nullable = false) 29 | private String userName; 30 | 31 | /** 32 | * 上级ID 33 | */ 34 | @Checked 35 | @Column(name = "PARENT_ID", columnDefinition="INT COMMENT '上级ID'") 36 | private Integer parentId; 37 | 38 | /** 39 | * 上级帐号 40 | */ 41 | @Checked 42 | @Column(name = "PARENT_NAME", columnDefinition="varchar(16) COMMENT '直属上级帐号'") 43 | private String parentName; 44 | 45 | /** 所在层级. */ 46 | @Checked 47 | @Column(name = "FLOOR", columnDefinition="TINYINT COMMENT '所在层级'") 48 | private Short floor; 49 | 50 | public UserTreeRelationEntity() {} 51 | 52 | public UserTreeRelationEntity(User user) { 53 | this.userId = user.getId(); 54 | this.userName = user.getUserName(); 55 | this.parentId = user.getParentId(); 56 | this.parentName = user.getParentName(); 57 | } 58 | public String getUserName() { 59 | return userName; 60 | } 61 | 62 | public void setUserName(String userName) { 63 | this.userName = userName; 64 | } 65 | 66 | public String getParentName() { 67 | return parentName; 68 | } 69 | 70 | public void setParentName(String parentName) { 71 | this.parentName = parentName; 72 | } 73 | 74 | public Integer getUserId() { 75 | return userId; 76 | } 77 | 78 | public void setUserId(Integer userId) { 79 | this.userId = userId; 80 | } 81 | 82 | public Integer getParentId() { 83 | return parentId; 84 | } 85 | 86 | public void setParentId(Integer parentId) { 87 | this.parentId = parentId; 88 | } 89 | 90 | public Short getFloor() { 91 | return floor; 92 | } 93 | 94 | public void setFloor(Short floor) { 95 | this.floor = floor; 96 | } 97 | 98 | public User getUser() { 99 | User user = new User(); 100 | user.setId(this.getUserId()); 101 | user.setUserName(this.getUserName()); 102 | user.setParentId(this.getParentId()); 103 | user.setParentName(this.getParentName()); 104 | return user; 105 | } 106 | 107 | /********************************* 108 | * 枚举 109 | *2015-05-08 110 | ***********************************/ 111 | public static enum UserTreeRelationEntity_ { 112 | userId("userId"), 113 | userName("userName"), 114 | parentId("parentId"), 115 | parentName("parentName"), 116 | floor("floor"); 117 | 118 | private final String _name; 119 | UserTreeRelationEntity_(String _name) { 120 | this._name = _name; 121 | } 122 | public String getName() { 123 | return _name; 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/repository/AggregateExpression.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.repository; 2 | 3 | import java.util.List; 4 | 5 | import javax.persistence.criteria.CriteriaBuilder; 6 | import javax.persistence.criteria.CriteriaQuery; 7 | import javax.persistence.criteria.Root; 8 | import javax.persistence.criteria.Selection; 9 | 10 | 11 | /** 12 | * @author Lane 13 | * 14 | * 合计条件接口 15 | * 16 | * @param 实体类型 17 | */ 18 | public interface AggregateExpression { 19 | 20 | List> buildExpression(Root root, CriteriaQuery query, CriteriaBuilder builder); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/repository/IPageResults.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.repository; 2 | 3 | import java.util.Iterator; 4 | import java.util.List; 5 | 6 | /** 7 | * 分页列表接口 8 | * 9 | * @param 10 | */ 11 | public interface IPageResults { 12 | 13 | /** 14 | * 总页数 15 | * 16 | * @return 17 | */ 18 | int getTotalPages(); 19 | 20 | /** 21 | * 是否有下一页 22 | * @return 23 | */ 24 | public boolean hasNext(); 25 | 26 | /** 27 | * 总记录数 28 | * 29 | * @return 30 | */ 31 | long getTotalElements(); 32 | 33 | /** 34 | * 当前页数 35 | * 36 | * @return 37 | */ 38 | public int getNumber(); 39 | 40 | /** 41 | * 是否第一页 42 | * 43 | * @return 44 | */ 45 | public boolean isFirst(); 46 | 47 | /** 48 | * 是否最后一页 49 | * 50 | * @return 51 | */ 52 | public boolean isLast(); 53 | 54 | /** 55 | * 返回所有结果 56 | * 57 | * @return 58 | */ 59 | public List getContent(); 60 | 61 | /** 62 | * 迭代结果列表 63 | * 64 | * @return 65 | */ 66 | public Iterator iterator(); 67 | 68 | /** 69 | * 返回排序对象 70 | * 71 | * @return 72 | */ 73 | public Sorter getSort(); 74 | } 75 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/repository/IPageable.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.repository; 2 | 3 | /** 4 | * 分页接口 5 | * 6 | */ 7 | public interface IPageable { 8 | 9 | /** 10 | * 当前页数,0--> 11 | * @return 12 | */ 13 | int getPageNumber(); 14 | /** 15 | * 每页记录数,默认10 16 | * @return 17 | */ 18 | int getPageSize(); 19 | 20 | /** 21 | * 返回排序条件 22 | * @return 23 | */ 24 | Sorter getSort(); 25 | 26 | /** 27 | * 构造下一页 28 | * @return 29 | */ 30 | IPageable next(); 31 | 32 | /** 33 | * 构造上一页或第一页 34 | * @return 35 | */ 36 | IPageable previousOrFirst(); 37 | 38 | /** 39 | * 构造第一页 40 | * @return 41 | */ 42 | IPageable first(); 43 | /** 44 | * 是否有上一页 45 | * @return 46 | */ 47 | boolean hasPrevious(); 48 | } -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/repository/PageResultsImpl.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.repository; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.Collections; 6 | import java.util.Iterator; 7 | import java.util.List; 8 | 9 | /** 10 | * 分页列表实现类 11 | * 12 | * @param 13 | */ 14 | public class PageResultsImpl implements IPageResults, Serializable { 15 | 16 | private static final long serialVersionUID = 8262911041470573788L; 17 | private final long total; 18 | private List content = new ArrayList(); 19 | private IPageable pageable = null; 20 | 21 | public PageResultsImpl(List content, IPageable pageable) { 22 | this.content.addAll(content); 23 | this.pageable = pageable; 24 | this.total = content.size(); 25 | } 26 | 27 | public PageResultsImpl(List content, IPageable pageable, long totleSize) { 28 | this.content.addAll(content); 29 | this.pageable = pageable; 30 | this.total = totleSize; 31 | } 32 | 33 | @Override 34 | public int getTotalPages() { 35 | return getSize() == 0 ? 1 : (int) Math.ceil((double) total 36 | / (double) getSize()); 37 | } 38 | 39 | @Override 40 | public long getTotalElements() { 41 | return total; 42 | } 43 | 44 | @Override 45 | public int getNumber() { 46 | return pageable == null ? 0 : pageable.getPageNumber(); 47 | } 48 | 49 | @Override 50 | public boolean isFirst() { 51 | return !hasPrevious(); 52 | } 53 | 54 | @Override 55 | public boolean isLast() { 56 | return !hasNext(); 57 | } 58 | 59 | @Override 60 | public boolean hasNext() { 61 | return getNumber() + 1 < getTotalPages(); 62 | } 63 | 64 | @Override 65 | public List getContent() { 66 | return Collections.unmodifiableList(content); 67 | } 68 | 69 | @Override 70 | public Iterator iterator() { 71 | return content.iterator(); 72 | } 73 | 74 | @Override 75 | public Sorter getSort() { 76 | return pageable == null ? null : pageable.getSort(); 77 | } 78 | 79 | private int getSize() { 80 | return pageable == null ? 0 : pageable.getPageSize(); 81 | } 82 | 83 | private boolean hasPrevious() { 84 | return getNumber() > 0; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/repository/PageableImpl.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.repository; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 分页对象,实现分页接口 7 | * 8 | */ 9 | public class PageableImpl implements IPageable, Serializable { 10 | 11 | private static final long serialVersionUID = 1232825578694716871L; 12 | 13 | /** 14 | * 当前页数,0--> 15 | */ 16 | private final int page; 17 | 18 | /** 19 | * 每页记录数,默认10 20 | */ 21 | private final int size; 22 | 23 | private Sorter sort = null; 24 | 25 | public PageableImpl(int page, int size) { 26 | if (page < 0) { 27 | throw new IllegalArgumentException( 28 | "Page index must not be less than zero!"); 29 | } 30 | if (size < 1) { 31 | throw new IllegalArgumentException( 32 | "Page size must not be less than one!"); 33 | } 34 | this.page = page; 35 | this.size = size; 36 | } 37 | 38 | public PageableImpl(int page, int size, Sorter sort) { 39 | this(page, size); 40 | this.sort = sort; 41 | } 42 | 43 | @Override 44 | public int getPageSize() { 45 | return size; 46 | } 47 | 48 | @Override 49 | public int getPageNumber() { 50 | return page; 51 | } 52 | 53 | @SuppressWarnings("unused") 54 | private int getOffset() { 55 | return page * size; 56 | } 57 | 58 | @Override 59 | public boolean hasPrevious() { 60 | return page > 0; 61 | } 62 | 63 | @Override 64 | public IPageable previousOrFirst() { 65 | return hasPrevious() ? previous() : first(); 66 | } 67 | 68 | @Override 69 | public IPageable next() { 70 | return new PageableImpl(getPageNumber() + 1, getPageSize(), getSort()); 71 | } 72 | 73 | public PageableImpl previous() { 74 | return getPageNumber() == 0 ? this : new PageableImpl( 75 | getPageNumber() - 1, getPageSize(), getSort()); 76 | } 77 | 78 | @Override 79 | public IPageable first() { 80 | return new PageableImpl(0, getPageSize(), getSort()); 81 | } 82 | 83 | @Override 84 | public Sorter getSort() { 85 | return sort; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/repository/SearchFilter.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.repository; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.Map.Entry; 7 | 8 | import javax.servlet.ServletRequest; 9 | 10 | import org.apache.commons.lang.StringUtils; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.web.util.WebUtils; 14 | 15 | import com.google.common.collect.Lists; 16 | 17 | public class SearchFilter implements Serializable { 18 | 19 | private static final Logger logger = LoggerFactory 20 | .getLogger(SearchFilter.class); 21 | 22 | private static final long serialVersionUID = 8719997267153871707L; 23 | 24 | public static final String PREFIX = "search_"; 25 | 26 | public enum Operator { 27 | /** 28 | * EQ : 等于 = 29 | * NE : 不等于 != 30 | * LIKE : 相似 = like("%" + value + "%") 31 | * PLIKE : like("%" + value) 32 | * ALIKE : like(value + "%") 33 | * GT : 大于 > 34 | * LT : 小于 < 35 | * GTE : 大于等于 >= 36 | * LTE : 小于等于 <= IN : id in (1,2,3) 37 | */ 38 | EQ, NE, LIKE, PLIKE, ALIKE, GT, LT, GTE, LTE, IN, OR 39 | } 40 | 41 | private String fieldName; 42 | private Object value; 43 | private Operator operator; 44 | 45 | public SearchFilter(String fieldName, Operator operator, Object value) { 46 | logger.debug("###search parameter:"+fieldName + "<[" + operator + "]>" + value); 47 | this.fieldName = fieldName; 48 | this.operator = operator; 49 | this.value = value; 50 | } 51 | 52 | public String getFieldName() { 53 | return fieldName; 54 | } 55 | 56 | public Object getValue() { 57 | return value; 58 | } 59 | 60 | public Operator getOperator() { 61 | return operator; 62 | } 63 | 64 | public static List parse(ServletRequest request) { 65 | return parse(WebUtils.getParametersStartingWith(request, PREFIX)); 66 | } 67 | 68 | public static List parse(Map searchParams) { 69 | List filters = Lists.newArrayList(); 70 | for (Entry entry : searchParams.entrySet()) { 71 | String key = entry.getKey(); 72 | Object value = entry.getValue(); 73 | if (StringUtils.isBlank((String) value)) { 74 | continue; 75 | } 76 | String[] names = StringUtils.split(key, "_"); 77 | if (names.length != 2) { 78 | throw new IllegalArgumentException(key 79 | + " is not a valid search filter name"); 80 | } 81 | String fieldName = names[1]; 82 | Operator operator = Operator.valueOf(names[0]); 83 | SearchFilter filter = new SearchFilter(fieldName, operator, value); 84 | filters.add(filter); 85 | } 86 | return filters; 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/repository/Sorter.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.repository; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.Arrays; 6 | import java.util.List; 7 | 8 | import org.springframework.util.StringUtils; 9 | 10 | public class Sorter implements Serializable { 11 | 12 | private static final long serialVersionUID = 8774379137332701467L; 13 | 14 | public static final String DEFAULT_DIRECTION = "ASC"; 15 | 16 | private final List orders; 17 | 18 | public Sorter(String _direction, String _propertie) { 19 | this(_direction, _propertie == null ? new ArrayList() : Arrays.asList(_propertie)); 20 | } 21 | 22 | public Sorter(String _direction, String... _properties) { 23 | this(_direction, _properties == null ? new ArrayList() : Arrays.asList(_properties)); 24 | } 25 | 26 | public Sorter(String direction, List properties) { 27 | 28 | if (properties == null || properties.isEmpty()) { 29 | throw new IllegalArgumentException("You have to provide at least one property to sort by!"); 30 | } 31 | 32 | this.orders = new ArrayList(properties.size()); 33 | 34 | for (String property : properties) { 35 | this.orders.add(new Order(direction, property)); 36 | } 37 | } 38 | 39 | public Sorter(Order... orders) { 40 | this(Arrays.asList(orders)); 41 | } 42 | 43 | public Sorter(List orders) { 44 | 45 | if (null == orders || orders.isEmpty()) { 46 | throw new IllegalArgumentException("You have to provide at least one sort property to sort by!"); 47 | } 48 | 49 | this.orders = orders; 50 | } 51 | 52 | public Sorter(String... properties) { 53 | this(DEFAULT_DIRECTION, properties); 54 | } 55 | 56 | public List getOrders() { 57 | return orders; 58 | } 59 | 60 | public static class Order implements Serializable { 61 | private static final long serialVersionUID = 2286583688034115153L; 62 | 63 | private final String direction; 64 | private final String property; 65 | 66 | public Order(String direction, String property) { 67 | if (!StringUtils.hasText(property)) { 68 | throw new IllegalArgumentException("Property must not null or empty!"); 69 | } 70 | 71 | this.direction = direction == null ? DEFAULT_DIRECTION : direction; 72 | this.property = property; 73 | } 74 | 75 | public Order(String property) { 76 | this(DEFAULT_DIRECTION, property); 77 | } 78 | 79 | public String getDirection() { 80 | return direction; 81 | } 82 | 83 | public String getProperty() { 84 | return property; 85 | } 86 | 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/util/ArrayUtils.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.HashSet; 6 | import java.util.List; 7 | import java.util.Set; 8 | 9 | public class ArrayUtils extends org.apache.commons.lang.ArrayUtils { 10 | 11 | /** 12 | * 统计arr数组中包含e元素的个数 13 | * 14 | * @param arr 15 | * @param e 16 | * @return 17 | */ 18 | public static int countElements(Object[] arr, Object e) { 19 | int count = 0; 20 | for (Object o : arr) { 21 | if (o.equals(e)) { 22 | count++; 23 | } 24 | } 25 | return count; 26 | } 27 | 28 | public static Object[] sort(Object[] arr) { 29 | Arrays.sort(arr); 30 | return arr; 31 | } 32 | 33 | /** 34 | * 检查one数组是否包含two数组所有元素 35 | * 36 | * @param one 37 | * @param two 38 | * @return 39 | */ 40 | public static boolean containsAll(Object[] one, Object[] two) { 41 | for (Object b : two) { 42 | if (!ArrayUtils.contains(one, b)) { 43 | return false; 44 | } 45 | } 46 | return true; 47 | } 48 | 49 | /** 50 | * 检查数组中是否有相同元素 51 | * 52 | * @param array 53 | * @return 54 | */ 55 | public static boolean duplicate(Object[] array) { 56 | for (int i = 0; i < array.length - 1; i++) { 57 | for (int j = i + 1; j < array.length; j++) { 58 | if (array[i].equals(array[j])) { 59 | return true; 60 | } 61 | } 62 | } 63 | return false; 64 | } 65 | 66 | public static boolean duplicate(Object[] one, Object[] two) { 67 | for (Object a : one) { 68 | for (Object b : two) { 69 | if (a.equals(b)) { 70 | return true; 71 | } 72 | } 73 | } 74 | return false; 75 | } 76 | 77 | public static Object[] intersect(Object[] one, Object[] two) { 78 | Set a = new HashSet(Arrays.asList(one)); 79 | Set b = new HashSet(Arrays.asList(two)); 80 | a.retainAll(b); 81 | return a.toArray(); 82 | } 83 | 84 | public static String join(Object[] array, String str) { 85 | StringBuffer sb = new StringBuffer(); 86 | for (Object element : array) { 87 | sb.append(element).append(str); 88 | } 89 | sb.delete(sb.length() - str.length(), sb.length()); 90 | return sb.toString(); 91 | } 92 | 93 | public static List> splitList(List list, int pageSize) { 94 | int listSize = list.size(); // list的大小 95 | int page = (listSize + (pageSize - 1)) / pageSize; // 页数 96 | List> listArray = new ArrayList>(); // 创建list数组,用来保存分割后的list 97 | for (int i = 0; i < page; i++) { // 按照数组大小遍历 98 | List subList = new ArrayList(); // 数组每一位放入一个分割后的list 99 | for (int j = 0; j < listSize; j++) { // 遍历待分割的list 100 | int pageIndex = ((j + 1) + (pageSize - 1)) / pageSize;// 当前记录的页码(第几页) 101 | if (pageIndex == (i + 1)) { // 当前记录的页码等于要放入的页码时 102 | subList.add(list.get(j)); // 放入list中的元素到分割后的list(subList) 103 | } 104 | if ((j + 1) == ((j + 1) * pageSize)) { // 当放满一页时退出当前循环 105 | break; 106 | } 107 | } 108 | listArray.add(subList); // 将分割后的list放入对应的数组的位中 109 | } 110 | return listArray; 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/util/BeanConverter.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.util; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Method; 5 | import java.util.HashMap; 6 | import java.util.Iterator; 7 | import java.util.Map; 8 | import javax.persistence.Transient; 9 | 10 | /** 11 | *转换器 12 | *1:将JavaBean 转换成Map、JSONObject 13 | *2:将JSONObject 转换成Map 14 | * 15 | * @author onsoul by JT 2015-6-24 下午4:32:23 16 | */ 17 | public class BeanConverter 18 | { 19 | /** 20 | * 将javaBean转换成Map 21 | * 22 | * @param javaBean javaBean 23 | * @return Map对象 24 | */ 25 | public static Map toMap(Object javaBean) 26 | { 27 | Map result = new HashMap(); 28 | Method[] methods = javaBean.getClass().getDeclaredMethods(); 29 | 30 | for (Method method : methods) 31 | { 32 | try 33 | { 34 | if (method.getName().startsWith("get")) 35 | { 36 | String field = method.getName(); 37 | field = field.substring(field.indexOf("get") + 3); 38 | field = field.toLowerCase().charAt(0) + field.substring(1); 39 | 40 | Object value = method.invoke(javaBean, (Object[])null); 41 | result.put(field, null == value ? "" : value.toString()); 42 | } 43 | } 44 | catch (Exception e) 45 | { 46 | } 47 | } 48 | 49 | return result; 50 | } 51 | 52 | /** 53 | * 将javaBean转换成Map 54 | * 过滤掉@Transient的属性 55 | * @param javaBean javaBean 56 | * @return Map对象 57 | */ 58 | public static Map toMapFilter(Object javaBean) 59 | { 60 | Map result = new HashMap(); 61 | Method[] methods = javaBean.getClass().getDeclaredMethods(); 62 | 63 | for (Method method : methods) 64 | { 65 | try 66 | { 67 | if (method.getName().startsWith("get")) 68 | { 69 | String field = method.getName(); 70 | field = field.substring(field.indexOf("get") + 3); 71 | field = field.toLowerCase().charAt(0) + field.substring(1); 72 | 73 | //过滤掉属性中带有注解的字段 74 | Field property=javaBean.getClass().getDeclaredField(field); 75 | System.out.println(property); 76 | if (property.isAnnotationPresent(Transient.class)) { 77 | continue; 78 | } 79 | 80 | Object value = method.invoke(javaBean, (Object[])null); 81 | result.put(field, null == value ? "" : value.toString()); 82 | } 83 | } 84 | catch (Exception e) 85 | { 86 | } 87 | } 88 | 89 | return result; 90 | } 91 | 92 | /** 93 | * 将map转换成Javabean 94 | * 95 | * @param javabean javaBean 96 | * @param data map数据 97 | */ 98 | public static Object toJavaBean(Object javabean, Map data) 99 | { 100 | Method[] methods = javabean.getClass().getDeclaredMethods(); 101 | for (Method method : methods) 102 | { 103 | try 104 | { 105 | if (method.getName().startsWith("set")) 106 | { 107 | String field = method.getName(); 108 | field = field.substring(field.indexOf("set") + 3); 109 | field = field.toLowerCase().charAt(0) + field.substring(1); 110 | method.invoke(javabean, new Object[] 111 | { 112 | data.get(field) 113 | }); 114 | } 115 | } 116 | catch (Exception e) 117 | { 118 | } 119 | } 120 | 121 | return javabean; 122 | } 123 | 124 | } -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/util/BeanMapper.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.util; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | import org.dozer.DozerBeanMapperSingletonWrapper; 7 | import org.dozer.Mapper; 8 | 9 | import com.fasterxml.jackson.databind.ObjectMapper; 10 | import com.google.common.collect.Lists; 11 | 12 | public class BeanMapper { 13 | 14 | private static final Mapper mapper = DozerBeanMapperSingletonWrapper.getInstance(); 15 | private static final ObjectMapper objectMapper = new ObjectMapper(); 16 | 17 | public static void map(Object source, Object destination) { 18 | mapper.map(source, destination); 19 | } 20 | 21 | public static D map(Object source, Class destinationClass) { 22 | return mapper.map(source, destinationClass); 23 | } 24 | 25 | public static List map(List source, Class destinationClass) { 26 | List dest = Lists.newArrayList(); 27 | for (S element : source) { 28 | dest.add(mapper.map(element, destinationClass)); 29 | } 30 | return dest; 31 | } 32 | 33 | @SuppressWarnings("unchecked") 34 | public static Map objectToMap(Object obj) { 35 | return objectMapper.convertValue(obj, Map.class); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/util/DateUtil.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.util; 2 | 3 | import java.text.ParseException; 4 | import java.text.ParsePosition; 5 | import java.text.SimpleDateFormat; 6 | import java.util.Calendar; 7 | import java.util.Date; 8 | import java.util.Locale; 9 | 10 | /* 11 | * 日期时间格式转换 12 | * @author onsoul by JT 2015-6-24 下午4:32:23 13 | * */ 14 | public class DateUtil { 15 | 16 | /** 17 | * 将传入的时间格式化成 yyyy:MM:dd HH:mm:ss 格式 18 | */ 19 | public static String timeStr(Date _Date) { 20 | if (_Date == null) 21 | return ""; 22 | SimpleDateFormat _SimpleDateFormat = new SimpleDateFormat( 23 | "yyyy:MM:dd HH:mm:ss", Locale.SIMPLIFIED_CHINESE); 24 | return _SimpleDateFormat.format(_Date); 25 | } 26 | 27 | /** 28 | * 将传入时间格式化成 yyyy-MM-dd 格式字符串 29 | */ 30 | public static String dateStr(Date _Date) { 31 | if (_Date == null) 32 | return ""; 33 | SimpleDateFormat _SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", 34 | Locale.SIMPLIFIED_CHINESE); 35 | return _SimpleDateFormat.format(_Date); 36 | } 37 | 38 | /** 39 | * 将传入 yyyy-MM-dd字符串 转换成Date对象 40 | * 41 | * @param _Date 42 | * @return 43 | */ 44 | public static Date formatDate(String _Date) throws ParseException { 45 | if (_Date == null) 46 | return new Date(); 47 | SimpleDateFormat _SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", 48 | Locale.SIMPLIFIED_CHINESE); 49 | return _SimpleDateFormat.parse(_Date); 50 | } 51 | 52 | /** 53 | * 将传入的时间字符串转换成时间格式 54 | */ 55 | public static Date formatDate2(String _Date) throws ParseException { 56 | SimpleDateFormat _SimpleDateFormat = new SimpleDateFormat( 57 | "yyyy:MM:dd HH:mm:ss", Locale.SIMPLIFIED_CHINESE); 58 | return _SimpleDateFormat.parse(_Date); 59 | } 60 | 61 | /** 62 | * 将传入时间格式化成 yyyy/MM/dd HH:mm:ss 格式字符串 63 | * 64 | * @param _Date 65 | * @return 66 | */ 67 | public static String formatStr(Date _Date) { 68 | if (_Date == null) 69 | return null; 70 | SimpleDateFormat _SimpleDateFormat = new SimpleDateFormat( 71 | "yyyy/MM/dd HH:mm:ss", Locale.SIMPLIFIED_CHINESE); 72 | return _SimpleDateFormat.format(_Date); 73 | } 74 | 75 | public static String getYesTeday() { 76 | Calendar calendar = Calendar.getInstance();// 此时打印它获取的是系统当前时间 77 | calendar.add(Calendar.DATE, -1); // 得到前一天 78 | String yestedayDate = new SimpleDateFormat("yyyy-MM-dd") 79 | .format(calendar.getTime()); 80 | return yestedayDate; 81 | } 82 | 83 | public static String getToday() { 84 | Calendar calendar = Calendar.getInstance();// 此时打印它获取的是系统当前时间 85 | String today = new SimpleDateFormat("yyyy-MM-dd").format(calendar 86 | .getTime()); 87 | return today; 88 | } 89 | 90 | public static String getAddDay(Date date, int i) { 91 | Calendar calendar = Calendar.getInstance();// 此时打印它获取的是系统当前时间 92 | calendar.setTime(date); 93 | calendar.add(Calendar.DATE, +i); // 得到前一天 94 | String yestedayDate = new SimpleDateFormat("yyyy-MM-dd") 95 | .format(calendar.getTime()); 96 | return yestedayDate; 97 | } 98 | 99 | public static long getTimeSlot(Date date_late, Date date_early) { 100 | try { 101 | long hour = (date_late.getTime() - date_early.getTime()) 102 | / (1000 * 60 * 60); 103 | return hour; 104 | } catch (Exception ex) { 105 | return 0; 106 | } 107 | } 108 | 109 | public static boolean batchTime(Long time, int minute) { 110 | long millis = (long) minute * 60 * 1000; 111 | long currentTime = System.currentTimeMillis(); 112 | if ((currentTime - time) > millis) { 113 | return true; 114 | } 115 | return false; 116 | } 117 | 118 | public static Date addMinute(Date time, int minute) { 119 | Calendar sl_time = Calendar.getInstance(); 120 | sl_time.setTime(time); 121 | sl_time.add(Calendar.MINUTE, minute); 122 | return sl_time.getTime(); 123 | } 124 | 125 | /** 126 | * 将长时间格式字符串转换为时间 yyyy-MM-dd HH:mm:ss 127 | * 128 | * @param strDate 129 | * @return 130 | */ 131 | public static Date strToDate(String strDate) { 132 | SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 133 | ParsePosition pos = new ParsePosition(0); 134 | Date strtodate = formatter.parse(strDate, pos); 135 | return strtodate; 136 | } 137 | 138 | /** 139 | * 将长时间格式时间转换为字符串 yyyy-MM-dd HH:mm:ss 140 | * 141 | * @param dateDate 142 | * @return 143 | */ 144 | public static String dateToStr(java.util.Date dateDate) { 145 | SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 146 | String dateString = formatter.format(dateDate); 147 | return dateString; 148 | } 149 | 150 | public static void main(String[] args) { 151 | System.out.println(strToDate("2015-07-21 17:09:05")); 152 | System.out.println(dateToStr(new Date())); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/util/EumnUtil.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.util; 2 | 3 | import java.beans.IntrospectionException; 4 | import java.beans.PropertyDescriptor; 5 | import java.lang.reflect.InvocationTargetException; 6 | import java.lang.reflect.Method; 7 | import java.util.LinkedHashMap; 8 | import java.util.Map; 9 | import org.apache.commons.lang3.reflect.MethodUtils; 10 | 11 | /* 12 | * 反射机制--枚举类转换Map 13 | * @author onsoul by JT 2015-6-24 下午4:32:23 14 | * */ 15 | public class EumnUtil { 16 | 17 | public static String getText(Class ref, Object code) { 18 | return parseEumn(ref).get(TransformUtils.toString(code)); 19 | } 20 | 21 | // 通过枚举转换成Map(不带数值) 22 | public static Map parseEumn(Class ref) { 23 | Map map = new LinkedHashMap(); 24 | if (ref.isEnum()) { 25 | T[] ts = ref.getEnumConstants(); 26 | for (T t : ts) { 27 | String text = getInvokeValue(t, "getText"); 28 | Enum tempEnum = (Enum) t; 29 | if (text == null) { 30 | text = tempEnum.name(); 31 | } 32 | map.put(text, ""); 33 | } 34 | } 35 | return map; 36 | } 37 | 38 | // 通过枚举转换成Map(带数值) 39 | public static Map parseEumnTextAndValue(Class ref, Object obj) { 40 | 41 | Class clazz = obj.getClass(); 42 | Map map = new LinkedHashMap(); 43 | if (ref.isEnum()) { 44 | T[] ts = ref.getEnumConstants(); 45 | for (T t : ts) { 46 | String text = getInvokeValue(t, "getText"); 47 | Enum tempEnum = (Enum) t; 48 | if (text == null) { 49 | text = tempEnum.name(); 50 | } 51 | try { 52 | PropertyDescriptor pd = new PropertyDescriptor(text, clazz); 53 | Method getMethod = pd.getReadMethod();// 获得get方法 54 | Object value = getMethod.invoke(obj);// 执行get方法返回一个Object 55 | // System.out.println(value); 56 | map.put(text, value.toString()); 57 | } catch (SecurityException e) { 58 | e.printStackTrace(); 59 | } catch (IllegalArgumentException e) { 60 | e.printStackTrace(); 61 | } catch (IntrospectionException e) { 62 | e.printStackTrace(); 63 | } catch (IllegalAccessException e) { 64 | e.printStackTrace(); 65 | } catch (InvocationTargetException e) { 66 | e.printStackTrace(); 67 | } 68 | } 69 | } 70 | return map; 71 | } 72 | 73 | static String getInvokeValue(T t, String methodName) { 74 | try { 75 | Method method = MethodUtils.getAccessibleMethod(t.getClass(), 76 | methodName); 77 | String text = TransformUtils.toString(method.invoke(t)); 78 | return text; 79 | } catch (Exception e) { 80 | return null; 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/util/HttpUtils.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.util; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.io.PrintWriter; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | 11 | /** 12 | * 13 | * @author onsoul@qq.com 14 | * @date 2015-9-22 下午4:01:30 15 | */ 16 | public class HttpUtils { 17 | /** 18 | * 发送GET请求 19 | * @param url 20 | * 目的地址 21 | * @param parameters 22 | * 请求参数,Map类型。 23 | * @return 远程响应结果 24 | */ 25 | public static String sendGet(String url, Map parameters) { 26 | String result = "";// 返回的结果 27 | BufferedReader in = null;// 读取响应输入流 28 | StringBuffer sb = new StringBuffer();// 存储参数 29 | String params = "";// 编码之后的参数 30 | try { 31 | // 编码请求参数 32 | if (parameters.size() == 1) { 33 | for (String name : parameters.keySet()) { 34 | sb.append(name).append("=").append(java.net.URLEncoder.encode( 35 | parameters.get(name), "UTF-8")); 36 | } 37 | params = sb.toString(); 38 | } else { 39 | for (String name : parameters.keySet()) { 40 | sb.append(name).append("=").append(java.net.URLEncoder.encode( 41 | parameters.get(name), "UTF-8")).append("&"); 42 | } 43 | String temp_params = sb.toString(); 44 | params = temp_params.substring(0, temp_params.length() - 1); 45 | } 46 | String full_url = url + "?" + params; 47 | System.out.println(full_url); 48 | // 创建URL对象 49 | java.net.URL connURL = new java.net.URL(full_url); 50 | // 打开URL连接 51 | java.net.HttpURLConnection httpConn = (java.net.HttpURLConnection) connURL 52 | .openConnection(); 53 | // 设置通用属性 54 | httpConn.setRequestProperty("Accept", "*/*"); 55 | httpConn.setRequestProperty("Connection", "Keep-Alive"); 56 | httpConn.setRequestProperty("User-Agent", 57 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)"); 58 | // 建立实际的连接 59 | httpConn.connect(); 60 | // 响应头部获取 61 | Map> headers = httpConn.getHeaderFields(); 62 | // 遍历所有的响应头字段 63 | for (String key : headers.keySet()) { 64 | System.out.println(key + "\t:\t" + headers.get(key)); 65 | } 66 | // 定义BufferedReader输入流来读取URL的响应,并设置编码方式 67 | in = new BufferedReader(new InputStreamReader( 68 | httpConn.getInputStream(), "UTF-8")); 69 | String line; 70 | // 读取返回的内容 71 | while ((line = in.readLine()) != null) { 72 | result += line; 73 | } 74 | } catch (Exception e) { 75 | e.printStackTrace(); 76 | } finally { 77 | try { 78 | if (in != null) { 79 | in.close(); 80 | } 81 | } catch (IOException ex) { 82 | ex.printStackTrace(); 83 | } 84 | } 85 | return result; 86 | } 87 | 88 | /** 89 | * 发送POST请求 90 | * 91 | * @param url 92 | * 目的地址 93 | * @param parameters 94 | * 请求参数,Map类型。 95 | * @return 远程响应结果 96 | */ 97 | public static String sendPost(String url, Map parameters) { 98 | String result = "";// 返回的结果 99 | BufferedReader in = null;// 读取响应输入流 100 | PrintWriter out = null; 101 | StringBuffer sb = new StringBuffer();// 处理请求参数 102 | String params = "";// 编码之后的参数 103 | try { 104 | // 编码请求参数 105 | if (parameters.size() == 1) { 106 | for (String name : parameters.keySet()) { 107 | sb.append(name).append("=").append(java.net.URLEncoder.encode( 108 | parameters.get(name), "UTF-8")); 109 | } 110 | params = sb.toString(); 111 | } else { 112 | for (String name : parameters.keySet()) { 113 | sb.append(name).append("=").append(java.net.URLEncoder.encode( 114 | parameters.get(name), "UTF-8")).append("&"); 115 | } 116 | String temp_params = sb.toString(); 117 | params = temp_params.substring(0, temp_params.length() - 1); 118 | } 119 | // 创建URL对象 120 | java.net.URL connURL = new java.net.URL(url); 121 | // 打开URL连接 122 | java.net.HttpURLConnection httpConn = (java.net.HttpURLConnection) connURL 123 | .openConnection(); 124 | // 设置通用属性 125 | httpConn.setRequestProperty("Accept", "*/*"); 126 | httpConn.setRequestProperty("Connection", "Keep-Alive"); 127 | httpConn.setRequestProperty("User-Agent", 128 | "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)"); 129 | // 设置POST方式 130 | httpConn.setDoInput(true); 131 | httpConn.setDoOutput(true); 132 | // 获取HttpURLConnection对象对应的输出流 133 | out = new PrintWriter(httpConn.getOutputStream()); 134 | // 发送请求参数 135 | out.write(params); 136 | // flush输出流的缓冲 137 | out.flush(); 138 | // 定义BufferedReader输入流来读取URL的响应,设置编码方式 139 | in = new BufferedReader(new InputStreamReader( 140 | httpConn.getInputStream(), "UTF-8")); 141 | String line; 142 | // 读取返回的内容 143 | while ((line = in.readLine()) != null) { 144 | result += line; 145 | } 146 | } catch (Exception e) { 147 | e.printStackTrace(); 148 | } finally { 149 | try { 150 | if (out != null) { 151 | out.close(); 152 | } 153 | if (in != null) { 154 | in.close(); 155 | } 156 | } catch (IOException ex) { 157 | ex.printStackTrace(); 158 | } 159 | } 160 | return result; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/util/MD5Utils.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.util; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.security.MessageDigest; 5 | import java.security.NoSuchAlgorithmException; 6 | 7 | import org.apache.commons.codec.digest.DigestUtils; 8 | 9 | import sun.misc.BASE64Encoder; 10 | 11 | public class MD5Utils { 12 | 13 | private static final String PREFIX = "LANELIFE.CASINO"; 14 | 15 | public static String encode(String str) { 16 | if (str == null) { 17 | return null; 18 | } 19 | return DigestUtils.md5Hex(PREFIX + str); 20 | } 21 | 22 | public static String encodeMD5(String value) { 23 | MessageDigest md; 24 | try { 25 | md = MessageDigest.getInstance("MD5"); 26 | md.update(value.getBytes()); 27 | return toHex(md.digest()); 28 | } catch (NoSuchAlgorithmException e) { 29 | e.printStackTrace(); 30 | } 31 | return null; 32 | } 33 | 34 | private static String toHex(byte buffer[]) { 35 | StringBuffer sb = new StringBuffer(buffer.length * 2); 36 | for (int i = 0; i < buffer.length; i++) { 37 | sb.append(Character.forDigit((buffer[i] & 240) >> 4, 16)); 38 | sb.append(Character.forDigit(buffer[i] & 15, 16)); 39 | } 40 | return sb.toString(); 41 | } 42 | 43 | /** 44 | * 32位加密 45 | * 46 | * @param sourceStr 47 | * @return 48 | */ 49 | public static String MD5(String sourceStr) { 50 | String result = ""; 51 | try { 52 | MessageDigest md = MessageDigest.getInstance("MD5"); 53 | md.update(sourceStr.getBytes()); 54 | byte b[] = md.digest(); 55 | int i; 56 | StringBuffer buf = new StringBuffer(""); 57 | for (int offset = 0; offset < b.length; offset++) { 58 | i = b[offset]; 59 | if (i < 0) 60 | i += 256; 61 | if (i < 16) 62 | buf.append("0"); 63 | buf.append(Integer.toHexString(i)); 64 | } 65 | result = buf.toString(); 66 | 67 | } catch (NoSuchAlgorithmException e) { 68 | System.out.println(e); 69 | } 70 | return result; 71 | } 72 | 73 | /** 74 | * 64位加密 75 | * 76 | * @param str 77 | * @return 78 | */ 79 | @SuppressWarnings("restriction") 80 | public static String EncoderPwdByMd5(String str) { 81 | // 确定计算方法 82 | MessageDigest md5; 83 | String newstr = ""; 84 | try { 85 | md5 = MessageDigest.getInstance("MD5"); 86 | 87 | BASE64Encoder base64en = new BASE64Encoder(); 88 | // 加密后的字符串 89 | newstr = base64en.encode(md5.digest(str.getBytes("utf-8"))); 90 | } catch (NoSuchAlgorithmException e) { 91 | e.printStackTrace(); 92 | } catch (UnsupportedEncodingException e) { 93 | e.printStackTrace(); 94 | } 95 | return newstr; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/util/MathUtils.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.util; 2 | 3 | 4 | public class MathUtils { 5 | 6 | public static int combination(int m, int n) { 7 | if (n == 0 || m == 0) { 8 | return 1; 9 | } 10 | if (n > m) { 11 | return 0; 12 | } 13 | if (n > m / 2) { 14 | n = m - n; 15 | } 16 | double a = 0; 17 | for (int i = m; i >= (m - n + 1); i--) { 18 | a += Math.log(i); 19 | } 20 | for (int i = n; i >= 1; i--) { 21 | a -= Math.log(i); 22 | } 23 | a = Math.exp(a); 24 | return (int) Math.round(a); 25 | } 26 | 27 | public static int getCombinCount(int a, int d) { 28 | if (d > a) { 29 | return 0; 30 | } 31 | if (a == d || d == 0) { 32 | return 1; 33 | } 34 | if (d == 1) { 35 | return a; 36 | } 37 | int b = 1; 38 | int e = 1; 39 | for (int c = 0; c < d; c++) { 40 | b *= a - c; 41 | e *= d - c; 42 | } 43 | return b / e; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/util/PreProperties.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.util; 2 | 3 | import java.io.IOException; 4 | import java.util.Properties; 5 | 6 | 7 | public class PreProperties extends Properties { 8 | /** 9 | * 10 | */ 11 | private static final long serialVersionUID = 1L; 12 | 13 | public PreProperties(String pro_file) { 14 | try { 15 | if (StringUtils.isNotEmpty(pro_file)) { 16 | super.load(getClass().getClassLoader().getResourceAsStream( 17 | pro_file)); 18 | System.out.println("###装载Properties 文件成功." + pro_file); 19 | } 20 | } catch (IOException e) { 21 | System.out.println("###装载Properties 文件失败." + pro_file); 22 | e.printStackTrace(); 23 | } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/util/SaltUtil.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.util; 2 | 3 | import org.apache.commons.lang.RandomStringUtils; 4 | import org.apache.shiro.crypto.hash.Md5Hash; 5 | import org.apache.shiro.crypto.hash.SimpleHash; 6 | 7 | public class SaltUtil { 8 | /** 9 | * Protect from being instance. 10 | */ 11 | private SaltUtil() { 12 | } 13 | 14 | public static String getSalt(String s) { 15 | return getSalt(s, ""); 16 | } 17 | 18 | public static String getSalt(String username, String password) { 19 | StringBuffer sb = null; 20 | sb = new StringBuffer(); 21 | sb.append(username).append(password); 22 | return new Md5Hash(sb.toString(), RandomStringUtils.randomNumeric(6)).toHex(); 23 | } 24 | 25 | public static String encodeMd5Hash(String pwd, String salt) { 26 | return new SimpleHash("md5", pwd, salt, 2).toHex(); 27 | } 28 | 29 | public static void main(String[] args) { 30 | String salt = getSalt("admin", "aaa000"); 31 | String encodedPassword = encodeMd5Hash("000000", salt); 32 | System.out.println(salt+"|"+encodedPassword); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/util/SerializeUtil.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.util; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.ObjectInputStream; 6 | import java.io.ObjectOutputStream; 7 | 8 | /** 9 | * JAVA 默认序列化工具类 10 | * 11 | * @author onsoul by JT 2015-6-24 下午4:32:23 12 | */ 13 | public class SerializeUtil { 14 | 15 | /** 16 | * 对象序列化为字节 17 | * 18 | * @param object 19 | * @return 20 | */ 21 | public static byte[] serialize(Object object) { 22 | ObjectOutputStream oos = null; 23 | ByteArrayOutputStream baos = null; 24 | try { 25 | // 序列化 26 | baos = new ByteArrayOutputStream(); 27 | oos = new ObjectOutputStream(baos); 28 | oos.writeObject(object); 29 | byte[] bytes = baos.toByteArray(); 30 | return bytes; 31 | } catch (Exception e) { 32 | 33 | } 34 | return null; 35 | } 36 | 37 | /** 38 | * 字节反序列化为对象 39 | * 40 | * @param bytes 41 | * @return 42 | */ 43 | public static Object deserialize(byte[] bytes) { 44 | ByteArrayInputStream bais = null; 45 | try { 46 | // 反序列化 47 | bais = new ByteArrayInputStream(bytes); 48 | ObjectInputStream ois = new ObjectInputStream(bais); 49 | return ois.readObject(); 50 | } catch (Exception e) { 51 | 52 | } 53 | return null; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/util/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.util; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.ArrayList; 5 | import java.util.Date; 6 | import java.util.List; 7 | import java.util.StringTokenizer; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | public class StringUtils extends org.apache.commons.lang.StringUtils { 12 | 13 | public static List toIntegerList(String str, String regex) { 14 | StringTokenizer t = new StringTokenizer(str, regex); 15 | List l = new ArrayList(); 16 | while (t.hasMoreElements()) { 17 | String s = t.nextToken(); 18 | if (isNotBlank(s)) { 19 | l.add(Integer.parseInt(s)); 20 | } 21 | } 22 | return l; 23 | } 24 | 25 | public static Integer[] toIntegerArray(String str, String regex) { 26 | List list = toIntegerList(str, regex); 27 | Integer[] arr = new Integer[list.size()]; 28 | return list.toArray(arr); 29 | } 30 | 31 | /** 32 | * 校验字符串是否是不以0开头的纯数字 33 | * @param str 34 | * @return 35 | */ 36 | public static boolean isNumeral(String str) { 37 | return str.matches("^[1-9]\\d*$"); 38 | } 39 | /** 40 | * 校验字符串是否整型(0开头也可以) 41 | * @param str 42 | * @return 43 | */ 44 | public static boolean isInteger(String input){ 45 | Matcher mer = Pattern.compile("^[+-]?[0-9]+$").matcher(input); 46 | return mer.find(); 47 | } 48 | 49 | public static List partition(String str, int partition) { 50 | List parts = new ArrayList(); 51 | int len = str.length(); 52 | for (int i = 0; i < len; i += partition) { 53 | parts.add(str.substring(i, Math.min(len, i + partition))); 54 | } 55 | return parts; 56 | } 57 | 58 | //(c >= 0x0391 && c <= 0xFFE5) //中文字符 59 | //(c>=0x0000 && c<=0x00FF) //英文字符 60 | public static boolean isZH(char c){ 61 | if(c >= 0x0391 && c <= 0xFFE5) 62 | return true; 63 | return false; 64 | } 65 | 66 | public static String[] splitStr(String targetStr){ 67 | String[] paraStr = null; 68 | if(null!=targetStr&&!"".equals(targetStr)){ 69 | paraStr = targetStr.split("\\|",-1); 70 | } 71 | return paraStr; 72 | } 73 | 74 | /** 75 | * 将json字符串Unicode编码转换成中文 76 | * @param str 77 | * @return 78 | */ 79 | public static String convert(String utfString){ 80 | StringBuilder sb = new StringBuilder(); 81 | int i = -1; 82 | int pos = 0; 83 | 84 | while((i=utfString.indexOf("\\u", pos)) != -1){ 85 | sb.append(utfString.substring(pos, i)); 86 | if(i+5 < utfString.length()){ 87 | pos = i+6; 88 | sb.append((char)Integer.parseInt(utfString.substring(i+2, i+6), 16)); 89 | } 90 | } 91 | 92 | return sb.toString(); 93 | } 94 | /** 95 | * 获取当前日期和时间 96 | * @param str 97 | * @return 98 | */ 99 | public static String getCurrentDateStr() { 100 | Date date = new Date(); 101 | String str = null; 102 | SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 103 | str = df.format(date); 104 | return str; 105 | } 106 | 107 | public static int getTimes(String src, String dest) { 108 | int times = 0, index = 0; 109 | do { 110 | index = src.indexOf(dest); 111 | if(index >= 0) { 112 | times++; 113 | src = src.substring(index + dest.length()); 114 | } 115 | } while(index != -1); 116 | 117 | return times; 118 | } 119 | 120 | public static void main(String[] args){ 121 | /*String targetStr="123|abc"; 122 | String[] str = splitStr(targetStr); 123 | System.out.println(str[0]+";"+str[1]);*/ 124 | // System.out.println(getCurrentDateStr()); 125 | System.out.println(getTimes("ajdkfokadsfkajokadjfok", "ok")); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/util/TransactionTemplateUtils.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.util; 2 | 3 | import org.springframework.transaction.PlatformTransactionManager; 4 | import org.springframework.transaction.TransactionDefinition; 5 | import org.springframework.transaction.support.TransactionTemplate; 6 | 7 | public class TransactionTemplateUtils { 8 | 9 | public static TransactionTemplate getTransactionTemplate(PlatformTransactionManager transactionManager, int propagationBehavior, int isolationLevel) { 10 | TransactionTemplate template = new TransactionTemplate(transactionManager); 11 | template.setPropagationBehavior(propagationBehavior); 12 | return template; 13 | } 14 | 15 | public static TransactionTemplate getDefaultTransactionTemplate(PlatformTransactionManager transactionManager) { 16 | return getTransactionTemplate(transactionManager, TransactionDefinition.PROPAGATION_REQUIRED, TransactionDefinition.ISOLATION_READ_COMMITTED); 17 | } 18 | 19 | public static TransactionTemplate getRequiresNewTransactionTemplate(PlatformTransactionManager transactionManager) { 20 | return getTransactionTemplate(transactionManager, TransactionDefinition.PROPAGATION_REQUIRES_NEW, TransactionDefinition.ISOLATION_READ_COMMITTED); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/util/TransformUtils.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.util; 2 | import java.lang.reflect.Field; 3 | import java.math.BigDecimal; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Calendar; 6 | import org.apache.commons.lang3.time.DateUtils; 7 | 8 | /** 9 | * 数据类型转换 10 | * @author onsoul by JT 2015-6-24 下午4:32:23 11 | * */ 12 | @SuppressWarnings("unchecked") 13 | public class TransformUtils { 14 | 15 | public static boolean toBoolean(Object obj) { 16 | 17 | return toBoolean(obj, false); 18 | } 19 | 20 | public static boolean toBoolean(Object obj, boolean defaultValue) { 21 | if (obj == null) { 22 | return defaultValue; 23 | } 24 | try { 25 | return Boolean.parseBoolean(toString(obj)); 26 | } catch (Exception e) { 27 | } 28 | return defaultValue ; 29 | } 30 | 31 | public static byte toByte(Object obj) { 32 | return toByte(obj, (byte) 0); 33 | } 34 | 35 | public static byte toByte(Object obj, byte defaultValue) { 36 | if (obj == null) { 37 | return defaultValue; 38 | } 39 | 40 | if (obj instanceof Number) { 41 | Number number = (Number) obj; 42 | return number.byteValue(); 43 | } 44 | String value = toString(obj) ; 45 | try { 46 | return Byte.parseByte( value ) ; 47 | } catch (Exception e) { 48 | } 49 | return defaultValue ; 50 | } 51 | 52 | public static char toCharacter(Object obj) { 53 | return toCharacter(obj, (char) ' '); 54 | } 55 | 56 | public static char toCharacter(Object obj, char defaultValue) { 57 | if (obj == null) { 58 | return defaultValue; 59 | } 60 | String str = obj.toString().trim(); 61 | if (str.length() == 0) { 62 | return defaultValue; 63 | } 64 | return (char) str.toCharArray()[0]; 65 | } 66 | 67 | public static double toDouble(Object obj) { 68 | return toDouble(obj, 0d); 69 | } 70 | 71 | public static double toDouble(Object obj, double defaultValue) { 72 | if (obj == null) { 73 | return defaultValue; 74 | } 75 | 76 | if (obj instanceof Number) { 77 | Number number = (Number) obj; 78 | return number.doubleValue() ; 79 | } 80 | String value = toString(obj) ; 81 | try { 82 | return Double.parseDouble(value) ; 83 | } catch (Exception e) { 84 | } 85 | return defaultValue ; 86 | } 87 | 88 | public static float toFloat(Object obj) { 89 | return toFloat(obj, 0); 90 | } 91 | 92 | public static float toFloat(Object obj, float defaultValue) { 93 | if (obj == null) { 94 | return defaultValue; 95 | } 96 | 97 | if (obj instanceof Number) { 98 | Number number = (Number) obj; 99 | return number.floatValue(); 100 | } 101 | String value = toString(obj) ; 102 | try { 103 | return Float.parseFloat(value) ; 104 | } catch (Exception e) { 105 | } 106 | return defaultValue ; 107 | } 108 | 109 | public static int toInt(Object obj) { 110 | return toInt(obj, 0); 111 | } 112 | 113 | public static int toInt(Object obj, int defaultValue) { 114 | if (obj == null) { 115 | return defaultValue; 116 | } 117 | 118 | if (obj instanceof Number) { 119 | Number number = (Number) obj; 120 | return number.intValue(); 121 | } 122 | String value = toString(obj) ; 123 | try { 124 | return Integer.parseInt(value) ; 125 | } catch (Exception e) { 126 | } 127 | return defaultValue ; 128 | } 129 | 130 | public static long toLong(Object obj) { 131 | return toLong(obj, 0L); 132 | } 133 | 134 | public static long toLong(Object obj, long defaultValue) { 135 | if (obj == null) { 136 | return defaultValue; 137 | } 138 | 139 | if (obj instanceof Number) { 140 | Number number = (Number) obj; 141 | return number.longValue(); 142 | } 143 | String value = toString(obj) ; 144 | try { 145 | return Long.parseLong(value) ; 146 | } catch (Exception e) { 147 | } 148 | return defaultValue ; 149 | } 150 | 151 | public static short toShort(Object obj) { 152 | return toShort(obj, (byte) 0); 153 | } 154 | 155 | 156 | public static short toShort(Object obj, short defaultValue) { 157 | if (obj == null) { 158 | return defaultValue; 159 | } 160 | 161 | if (obj instanceof Number) { 162 | Number number = (Number) obj; 163 | return number.shortValue(); 164 | } 165 | String value = toString(obj) ; 166 | try { 167 | return Short.parseShort(value) ; 168 | } catch (Exception e) { 169 | return defaultValue; 170 | } 171 | } 172 | 173 | public static String toString(Object value) { 174 | if (value == null) { 175 | return ""; 176 | } 177 | return value.toString().trim(); 178 | } 179 | 180 | public static BigDecimal toBigDecimal(Object value){ 181 | return toBigDecimal(value , new BigDecimal(0)) ; 182 | } 183 | 184 | public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) { 185 | if(value == null){ 186 | return defaultValue ; 187 | } 188 | if(value instanceof BigDecimal){ 189 | BigDecimal decimal = (BigDecimal) value ; 190 | return decimal; 191 | } 192 | return new BigDecimal( toDouble( value ) ); 193 | } 194 | 195 | public static String dateToString(Object value, String pattern){ 196 | java.util.Date date = (java.util.Date) value; 197 | Calendar calendar = Calendar.getInstance(); 198 | calendar.setTime( date ) ; 199 | SimpleDateFormat sdf = new SimpleDateFormat( pattern ); 200 | return sdf.format( date ) ; 201 | } 202 | 203 | public static Object transform(Object obj,Class clazz){ 204 | if(clazz == null){ 205 | return obj ; 206 | } 207 | 208 | if(clazz.isEnum()){ 209 | Field[]fields=clazz.getFields() ; 210 | int tempInt = toInt(obj) ; 211 | if(fields.length > tempInt){ 212 | try { 213 | return Enum.valueOf((Class)clazz , fields[tempInt].getName()); 214 | } catch (Exception e) { 215 | } 216 | } 217 | } 218 | 219 | if(obj.getClass().equals(clazz)){ 220 | return obj ; 221 | } 222 | if(int.class.equals(clazz) || Integer.class.equals(clazz)){ 223 | return toInt(obj) ; 224 | }else if( String.class.equals(clazz) ){ 225 | return toString( obj ) ; 226 | }else if(float.class.equals(clazz) || Float.class.equals(clazz)){ 227 | return toFloat(obj) ; 228 | }else if(double.class.equals(clazz) || Double.class.equals(clazz)){ 229 | return toDouble(obj) ; 230 | }else if(byte.class.equals(clazz) || Byte.class.equals(clazz)){ 231 | return toByte(obj) ; 232 | }else if(char.class.equals(clazz) || Character.class.equals(clazz)){ 233 | return toCharacter(obj) ; 234 | }else if(short.class.equals(clazz) || Short.class.equals(clazz)){ 235 | return toShort(obj) ; 236 | }else if(long.class.equals(clazz) || Long.class.equals(clazz)){ 237 | return toLong(obj) ; 238 | }else if(boolean.class.equals(clazz) || Boolean.class.equals(clazz)){ 239 | return toBoolean(obj) ; 240 | }else if(BigDecimal.class.equals(clazz)){ 241 | return toBigDecimal( obj ) ; 242 | }else if(java.util.Date.class.equals(clazz) || 243 | java.sql.Date.class.equals(clazz) 244 | || java.sql.Timestamp.class.equals(clazz)){ 245 | try { 246 | java.util.Date date = DateUtils.parseDate(obj.toString() 247 | , "yyyyMMdd" , "yyyy-MM-dd" , 248 | "yyyy年MM月dd日" , 249 | "yyyyMMddHHmmss" , 250 | "yyyy-MM-dd HH:mm:ss" , 251 | "yyyy年MM月dd日HH时mm分ss秒" ) ; 252 | if(java.sql.Date.class.equals(clazz)){ 253 | return new java.sql.Date(date.getTime()) ; 254 | }else if(java.sql.Timestamp.class.equals(clazz)){ 255 | return new java.sql.Timestamp(date.getTime()) ; 256 | } 257 | return date ; 258 | } catch (Exception e) { 259 | return null; 260 | } 261 | } 262 | return obj ; 263 | } 264 | } -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/common/util/UnicodeUtils.java: -------------------------------------------------------------------------------- 1 | package com.hitler.common.util; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | 5 | public class UnicodeUtils { 6 | 7 | /** 8 | * 把中文转成Unicode码 9 | * @param str 10 | * @return 11 | */ 12 | public static String chinaToUnicode(String str) { 13 | String result = ""; 14 | for (int i = 0; i < str.length(); i++) { 15 | int chr1 = (char) str.charAt(i); 16 | if (chr1 >= 19968 && chr1 <= 171941) {// 汉字范围 \u4e00-\u9fa5 (中文) 17 | result += "\\u" + Integer.toHexString(chr1); 18 | } else { 19 | result += str.charAt(i); 20 | } 21 | } 22 | return result; 23 | } 24 | 25 | /** 26 | * 判断是否为中文字符 27 | * 28 | * @param c 29 | * @return 30 | */ 31 | public static boolean isChinese(char c) { 32 | Character.UnicodeBlock ub = Character.UnicodeBlock.of(c); 33 | if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS 34 | || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS 35 | || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A 36 | || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION 37 | || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION 38 | || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) { 39 | return true; 40 | } 41 | return false; 42 | } 43 | 44 | public static String string2Unicode(String s) { 45 | try { 46 | StringBuffer out = new StringBuffer(""); 47 | byte[] bytes = s.getBytes("unicode"); 48 | for (int i = 2; i < bytes.length - 1; i += 2) { 49 | out.append("u"); 50 | String str = Integer.toHexString(bytes[i + 1] & 0xff); 51 | for (int j = str.length(); j < 2; j++) { 52 | out.append("0"); 53 | } 54 | String str1 = Integer.toHexString(bytes[i] & 0xff); 55 | 56 | out.append(str); 57 | out.append(str1); 58 | out.append(" "); 59 | } 60 | return out.toString().toUpperCase(); 61 | } catch (UnsupportedEncodingException e) { 62 | e.printStackTrace(); 63 | return null; 64 | } 65 | } 66 | 67 | public static String unicode2String(String unicode) { 68 | 69 | StringBuffer string = new StringBuffer(); 70 | 71 | String[] hex = unicode.split("\\\\u"); 72 | 73 | for (int i = 1; i < hex.length; i++) { 74 | 75 | // 转换出每一个代码点 76 | int data = Integer.parseInt(hex[i], 16); 77 | 78 | // 追加成string 79 | string.append((char) data); 80 | } 81 | 82 | return string.toString(); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/model/business/Record.java: -------------------------------------------------------------------------------- 1 | package com.hitler.model.business; 2 | 3 | import java.util.Date; 4 | 5 | import javax.persistence.Column; 6 | import javax.persistence.Entity; 7 | import javax.persistence.Index; 8 | import javax.persistence.Table; 9 | import javax.persistence.Temporal; 10 | import javax.persistence.TemporalType; 11 | 12 | import org.hibernate.annotations.DynamicInsert; 13 | import org.hibernate.annotations.DynamicUpdate; 14 | 15 | import com.hitler.common.model.annotation.Checked; 16 | import com.hitler.common.model.support.UserTreeRelationEntity; 17 | 18 | /** 19 | * 记录模型 20 | * @author onsoul@qq.com 21 | * @date 2016-4-12下午4:06:33 22 | */ 23 | @Entity 24 | @DynamicInsert 25 | @DynamicUpdate 26 | @Table(name = "TB_RECORD", indexes = { 27 | @Index(name = "IDX_USER_ID", columnList = "USER_ID"), 28 | @Index(name = "IDX_PARENT_ID", columnList = "PARENT_ID") }) 29 | 30 | public class Record extends UserTreeRelationEntity { 31 | 32 | private static final long serialVersionUID = -6378188431615185271L; 33 | 34 | /** 35 | * 金额 36 | */ 37 | @Checked 38 | @Column(name = "AMOUNT", columnDefinition = "DECIMAL(8,3) DEFAULT 0.0 COMMENT '单注金额'", nullable = false) 39 | private Double Amount; 40 | 41 | /** 42 | * 总额 43 | */ 44 | @Checked 45 | @Column(name = "LINE_TOTAL", columnDefinition = "DECIMAL(10,3) DEFAULT 0.0 COMMENT '投注总额'", nullable = false) 46 | private Double Total; 47 | 48 | /** 49 | * 最后修改时间 50 | */ 51 | @Temporal(TemporalType.TIMESTAMP) 52 | @Column(name = "LAST_MODEIFY_TIME", columnDefinition="TIMESTAMP NULL COMMENT '最后登录时间'") 53 | private Date lastModifyTime; 54 | 55 | public Record() { 56 | } 57 | 58 | public Double getAmount() { 59 | return Amount; 60 | } 61 | 62 | public void setAmount(Double amount) { 63 | Amount = amount; 64 | } 65 | 66 | public Double getTotal() { 67 | return Total; 68 | } 69 | 70 | public void setTotal(Double total) { 71 | Total = total; 72 | } 73 | 74 | public Date getLastModifyTime() { 75 | return lastModifyTime; 76 | } 77 | 78 | public void setLastModifyTime(Date lastModifyTime) { 79 | this.lastModifyTime = lastModifyTime; 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return super.toString(); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/repository/business/IRecordRepository.java: -------------------------------------------------------------------------------- 1 | package com.hitler.repository.business; 2 | 3 | import com.hitler.model.business.Record; 4 | import com.hitler.repository.support.GenericRepository; 5 | 6 | public interface IRecordRepository extends GenericRepository { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/repository/support/DefaultRepositoryFactory.java: -------------------------------------------------------------------------------- 1 | package com.hitler.repository.support; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.EntityManager; 6 | 7 | import org.springframework.data.jpa.repository.support.JpaEntityInformation; 8 | import org.springframework.data.jpa.repository.support.JpaRepositoryFactory; 9 | import org.springframework.data.jpa.repository.support.SimpleJpaRepository; 10 | import org.springframework.data.repository.core.RepositoryMetadata; 11 | 12 | public class DefaultRepositoryFactory extends JpaRepositoryFactory { 13 | 14 | public DefaultRepositoryFactory(EntityManager entityManager) { 15 | super(entityManager); 16 | } 17 | 18 | @SuppressWarnings({ "rawtypes", "unchecked" }) 19 | @Override 20 | protected SimpleJpaRepository getTargetRepository(RepositoryMetadata metadata, EntityManager entityManager) { 21 | JpaEntityInformation entityInformation = getEntityInformation(metadata.getDomainType()); 22 | return new GenericRepositoryImpl(entityInformation, entityManager); 23 | } 24 | 25 | @Override 26 | protected Class getRepositoryBaseClass(RepositoryMetadata metadata) { 27 | return GenericRepositoryImpl.class; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/repository/support/DefaultRepositoryFactoryBean.java: -------------------------------------------------------------------------------- 1 | package com.hitler.repository.support; 2 | 3 | import java.io.Serializable; 4 | 5 | import javax.persistence.EntityManager; 6 | 7 | import org.springframework.data.jpa.repository.JpaRepository; 8 | import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean; 9 | import org.springframework.data.repository.core.support.RepositoryFactorySupport; 10 | 11 | public class DefaultRepositoryFactoryBean, S, ID extends Serializable> extends JpaRepositoryFactoryBean { 12 | 13 | @Override 14 | protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) { 15 | return new DefaultRepositoryFactory(entityManager); 16 | } 17 | 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/repository/support/DynamicSpecifications.java: -------------------------------------------------------------------------------- 1 | package com.hitler.repository.support; 2 | 3 | import java.io.Serializable; 4 | import java.text.ParseException; 5 | import java.util.Collection; 6 | import java.util.Date; 7 | import java.util.Iterator; 8 | import java.util.List; 9 | 10 | import javax.persistence.criteria.CriteriaBuilder; 11 | import javax.persistence.criteria.CriteriaBuilder.In; 12 | import javax.persistence.criteria.CriteriaQuery; 13 | import javax.persistence.criteria.Path; 14 | import javax.persistence.criteria.Predicate; 15 | import javax.persistence.criteria.Root; 16 | 17 | import org.apache.commons.lang.StringUtils; 18 | import org.apache.commons.lang.time.DateUtils; 19 | import org.joda.time.DateTime; 20 | import org.joda.time.LocalDate; 21 | import org.springframework.data.jpa.domain.Specification; 22 | 23 | import com.google.common.collect.Lists; 24 | import com.hitler.common.repository.SearchFilter; 25 | import com.hitler.common.repository.SearchFilter.Operator; 26 | 27 | public class DynamicSpecifications { 28 | 29 | public static Specification bySearchFilter(final Collection filters) { 30 | return new SpecificationImpl(filters); 31 | } 32 | 33 | static class SpecificationImpl implements Specification, Serializable { 34 | 35 | private static final long serialVersionUID = 2404310650338699355L; 36 | 37 | private Collection filters; 38 | 39 | public SpecificationImpl(Collection filters) { 40 | this.filters = filters; 41 | } 42 | 43 | @Override 44 | @SuppressWarnings({ "unchecked", "rawtypes" }) 45 | public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder builder) { 46 | if (filters != null && filters.size() > 0 && !(filters.size() == 1 && filters.contains(null))) { 47 | List predicates = Lists.newArrayList(); 48 | for (SearchFilter filter : filters) { 49 | 50 | String[] names = StringUtils.split(filter.getFieldName(), "."); 51 | Path expression = root.get(names[0]); 52 | for (int i = 1; i < names.length; i++) { 53 | expression = expression.get(names[i]); 54 | } 55 | 56 | Object value = filter.getValue(); 57 | if(names.length > 1 && names[1].equals("id")) { 58 | value = Integer.parseInt(value.toString()); 59 | } 60 | if(expression.getJavaType().isAssignableFrom(Integer.class)) { 61 | // 整型 62 | } else if (expression.getJavaType().isEnum()) { 63 | // 枚举 64 | value = Enum.valueOf((Class)expression.getJavaType(), value.toString()); 65 | } else if (expression.getJavaType().isAssignableFrom(Boolean.class)) { 66 | // 布尔 67 | value = Boolean.valueOf(value.toString()); 68 | } else if (expression.getJavaType().isAssignableFrom(Date.class)) { 69 | // 时间 70 | int index = value.toString().indexOf("."); 71 | if(index != -1) { 72 | value = value.toString().substring(0, index); 73 | } 74 | try { 75 | value = DateUtils.parseDate(value.toString(), new String[]{"dd/MM/yyyy", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd"}); 76 | } catch (ParseException e) { 77 | throw new RuntimeException(e); 78 | } 79 | } else if (expression.getJavaType().isAssignableFrom(LocalDate.class)) { 80 | value = new LocalDate(value); 81 | } else if (expression.getJavaType().isAssignableFrom(DateTime.class)) { 82 | // 时间戳 83 | try { 84 | long ms = DateUtils.parseDate(value.toString(), new String[]{"dd/MM/yyyy", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd"}).getTime(); 85 | // DateTime t = new DateTime(Long.parseLong(value.toString())); 86 | DateTime t = new DateTime(ms); 87 | if (filter.getOperator() == Operator.LTE) { 88 | t = t.plus(999); // 增加毫秒数 89 | } 90 | value = t; 91 | } catch (Exception e) { 92 | throw new RuntimeException(e); 93 | } 94 | } 95 | 96 | switch (filter.getOperator()) { 97 | case EQ: 98 | predicates.add(builder.equal(expression, value)); 99 | break; 100 | case NE: 101 | predicates.add(builder.notEqual(expression, value)); 102 | break; 103 | case LIKE: 104 | predicates.add(builder.like(expression, "%" + value + "%")); 105 | break; 106 | case PLIKE: 107 | predicates.add(builder.like(expression, "%" + value)); 108 | break; 109 | case ALIKE: 110 | predicates.add(builder.like(expression, value + "%")); 111 | break; 112 | case GT: 113 | predicates.add(builder.greaterThan(expression, (Comparable) value)); 114 | break; 115 | case LT: 116 | predicates.add(builder.lessThan(expression, (Comparable) value)); 117 | break; 118 | case GTE: 119 | predicates.add(builder.greaterThanOrEqualTo(expression, (Comparable) value)); 120 | break; 121 | case LTE: 122 | predicates.add(builder.lessThanOrEqualTo(expression, (Comparable) value)); 123 | break; 124 | case IN: 125 | In in = builder.in(expression); 126 | if (value != null && ((Collection) value).size() > 0) { 127 | Iterator iterator = ((Collection) value).iterator(); 128 | while(iterator.hasNext()) { 129 | in.value(iterator.next()); 130 | } 131 | predicates.add(in); 132 | } else { 133 | predicates.add(builder.equal(expression, -1)); 134 | } 135 | break; 136 | } 137 | } 138 | 139 | if (!predicates.isEmpty()) { 140 | return builder.and(predicates.toArray(new Predicate[predicates.size()])); 141 | } 142 | } 143 | return builder.conjunction(); 144 | } 145 | 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/repository/support/GenericRepository.java: -------------------------------------------------------------------------------- 1 | package com.hitler.repository.support; 2 | 3 | import java.io.Serializable; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | import javax.persistence.EntityManager; 8 | import javax.persistence.LockModeType; 9 | import javax.persistence.criteria.Path; 10 | import javax.persistence.criteria.Root; 11 | 12 | import org.springframework.data.domain.Persistable; 13 | import org.springframework.data.domain.Sort; 14 | import org.springframework.data.jpa.domain.Specification; 15 | import org.springframework.data.jpa.repository.JpaRepository; 16 | import org.springframework.data.jpa.repository.JpaSpecificationExecutor; 17 | import org.springframework.data.repository.NoRepositoryBean; 18 | 19 | import com.hitler.common.repository.AggregateExpression; 20 | 21 | 22 | @NoRepositoryBean 23 | public interface GenericRepository, PK extends Serializable> extends JpaRepository, JpaSpecificationExecutor { 24 | 25 | EntityManager getEntityManager(); 26 | 27 | E findOne(PK id, LockModeType lockMode); 28 | E findOne(Specification spec, LockModeType lockMode); 29 | 30 | List findTop(int top, Specification spec, Sort sort); 31 | List findTop(int top, Specification spec, Sort sort, LockModeType lockMode); 32 | 33 | S update(S entity); 34 | 35 | Path getAttributeName(Root root, String attributeName); 36 | 37 | 38 | S sum(Class resultClass, Specification spec, String... properties); 39 | S sum(Class resultClass, Specification spec, List properties); 40 | 41 | S sum(Class resultClass, Specification spec, LockModeType lockMode, String... properties); 42 | S sum(Class resultClass, Specification spec, LockModeType lockMode, List properties); 43 | S aggregate(Class resultClass, Specification spec, AggregateExpression expression); 44 | S aggregate(Class resultClass, Specification spec, AggregateExpression expression, LockModeType lockMode); 45 | 46 | List groupBy(Class resultClass,Specification spec, AggregateExpression expression); 47 | 48 | int updateByHQL(String hql, Map parameters); 49 | } 50 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/repository/support/GenericRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.hitler.repository.support; 2 | 3 | import java.io.Serializable; 4 | import java.util.Arrays; 5 | import java.util.Iterator; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.Map.Entry; 9 | 10 | import javax.persistence.EntityManager; 11 | import javax.persistence.LockModeType; 12 | import javax.persistence.NoResultException; 13 | import javax.persistence.Query; 14 | import javax.persistence.criteria.CriteriaBuilder; 15 | import javax.persistence.criteria.CriteriaQuery; 16 | import javax.persistence.criteria.Path; 17 | import javax.persistence.criteria.Predicate; 18 | import javax.persistence.criteria.Root; 19 | import javax.persistence.criteria.Selection; 20 | 21 | import org.hibernate.Session; 22 | import org.springframework.data.domain.Persistable; 23 | import org.springframework.data.domain.Sort; 24 | import org.springframework.data.jpa.domain.Specification; 25 | import org.springframework.data.jpa.repository.support.JpaEntityInformation; 26 | import org.springframework.data.jpa.repository.support.JpaEntityInformationSupport; 27 | import org.springframework.data.jpa.repository.support.SimpleJpaRepository; 28 | 29 | import com.google.common.collect.Lists; 30 | import com.hitler.common.repository.AggregateExpression; 31 | 32 | public class GenericRepositoryImpl, PK extends Serializable> extends SimpleJpaRepository implements GenericRepository { 33 | 34 | protected EntityManager em; 35 | 36 | public GenericRepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager) { 37 | super(entityInformation, entityManager); 38 | this.em = entityManager; 39 | } 40 | 41 | public GenericRepositoryImpl(Class domainClass, EntityManager em) { 42 | this(JpaEntityInformationSupport.getMetadata(domainClass, em), em); 43 | } 44 | 45 | @Override 46 | public EntityManager getEntityManager() { 47 | return em; 48 | } 49 | 50 | @Override 51 | public E findOne(PK id, LockModeType lockMode) { 52 | return em.find(getDomainClass(), id, lockMode); 53 | } 54 | 55 | @Override 56 | public E findOne(Specification spec, LockModeType lockMode) { 57 | try { 58 | return getQuery(spec, (Sort) null).setLockMode(lockMode).getSingleResult(); 59 | } catch (NoResultException e) { 60 | return null; 61 | } 62 | } 63 | 64 | @Override 65 | public List findTop(int top, Specification spec, Sort sort) { 66 | return findTop(top, spec, sort, LockModeType.NONE); 67 | } 68 | 69 | @Override 70 | public List findTop(int top, Specification spec, Sort sort, LockModeType lockMode) { 71 | return getQuery(spec, sort).setLockMode(lockMode).setMaxResults(top).getResultList(); 72 | } 73 | 74 | @Override 75 | public S update(S entity) { 76 | Session session = em.unwrap(Session.class); 77 | session.update(entity); //使用update方法提高效率 78 | return entity; 79 | } 80 | 81 | private S aggregate(CriteriaBuilder builder, CriteriaQuery query, Root root, Specification spec, List> selectionList, LockModeType lockMode) { 82 | if (selectionList != null) { 83 | Predicate predicate = spec.toPredicate(root, query, builder); 84 | if (predicate != null) { 85 | query.where(predicate); 86 | } 87 | query.multiselect(selectionList); 88 | return (S) em.createQuery(query).setLockMode(lockMode).getSingleResult(); 89 | } 90 | return null; 91 | } 92 | 93 | @Override 94 | public S aggregate(Class resultClass, Specification spec, AggregateExpression expression, LockModeType lockMode) { 95 | CriteriaBuilder builder = em.getCriteriaBuilder(); 96 | CriteriaQuery query = builder.createQuery(resultClass); 97 | Root root = query.from(getDomainClass()); 98 | List> selectionList = expression.buildExpression(root, query, builder); 99 | return aggregate(builder, query, root, spec, selectionList, lockMode); 100 | } 101 | 102 | @Override 103 | public S aggregate(Class resultClass, Specification spec, AggregateExpression expression) { 104 | return aggregate(resultClass, spec, expression, LockModeType.NONE); 105 | } 106 | 107 | @Override 108 | public Path getAttributeName(Root root, String attributeName) { 109 | return root.get(attributeName); 110 | } 111 | 112 | @Override 113 | public S sum(Class resultClass, Specification spec, LockModeType lockMode, List properties) { 114 | CriteriaBuilder builder = em.getCriteriaBuilder(); 115 | CriteriaQuery query = builder.createQuery(resultClass); 116 | Root root = query.from(getDomainClass()); 117 | List> selectionList = Lists.newArrayList(); 118 | for (String property : properties) { 119 | selectionList.add(builder.sum(getAttributeName(root, property))); 120 | } 121 | return aggregate(builder, query, root, spec, selectionList, lockMode); 122 | } 123 | 124 | @Override 125 | public S sum(Class resultClass, Specification spec, List properties) { 126 | return sum(resultClass, spec, LockModeType.NONE, properties); 127 | } 128 | 129 | @Override 130 | public S sum(Class resultClass, Specification spec, String... properties) { 131 | return sum(resultClass, spec, Arrays.asList(properties)); 132 | } 133 | 134 | @Override 135 | public S sum(Class resultClass, Specification spec, LockModeType lockMode, String... properties) { 136 | return sum(resultClass, spec, lockMode, Arrays.asList(properties)); 137 | } 138 | 139 | @Override 140 | public int updateByHQL(String hql, Map parameters) { 141 | Query query = em.createQuery(hql); 142 | if(parameters != null) { 143 | Iterator> it = parameters.entrySet().iterator(); 144 | while(it.hasNext()) { 145 | Entry entry = it.next(); 146 | query.setParameter(entry.getKey(), entry.getValue()); 147 | } 148 | } 149 | return query.executeUpdate(); 150 | } 151 | 152 | @Override 153 | public List groupBy(Class resultClass, Specification spec, 154 | AggregateExpression expression) { 155 | // TODO Auto-generated method stub 156 | return null; 157 | } 158 | 159 | } 160 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/server/DAOConsumer.java: -------------------------------------------------------------------------------- 1 | package com.hitler.server; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.context.support.ClassPathXmlApplicationContext; 6 | 7 | import com.hitler.model.business.Record; 8 | import com.hitler.service.business.IRecordService; 9 | 10 | /** 11 | * 初始化Spring Data JPA,并为DAO接口提供Dubbo Provider服务 12 | * 13 | * @author 14 | * @version 1.0 15 | * 16 | */ 17 | 18 | public class DAOConsumer { 19 | 20 | //private static ObjectMapper mapper = new ObjectMapper(); 21 | 22 | public static void main(String[] args) throws Exception { 23 | ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( 24 | "conf/consumer/consumer-context.xml"); 25 | 26 | context.start(); 27 | IRecordService recordService = context.getBean(IRecordService.class); 28 | query(recordService); 29 | System.out.println("Service successfully started"); 30 | // 按任意键退出 31 | System.in.read(); 32 | } 33 | 34 | public static boolean query(IRecordService recordService) throws Exception { 35 | for (int i = 0; i < 1000; i++) { 36 | List full_record = recordService.findAll(); 37 | for (Record record : full_record) { 38 | //String record_json = mapper.writeValueAsString(record); 39 | System.out.println("结果:"+record.getUserName()); 40 | } 41 | 42 | Thread.sleep(1000); 43 | } 44 | 45 | return false; 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/server/DAOProvider.java: -------------------------------------------------------------------------------- 1 | package com.hitler.server; 2 | 3 | import java.io.IOException; 4 | 5 | import org.springframework.context.support.ClassPathXmlApplicationContext; 6 | 7 | import com.hitler.service.business.IRecordService; 8 | 9 | /** 10 | * 初始化Spring Data JPA,并为DAO接口提供Dubbo Provider服务 11 | * @author onsoul 12 | * @version 1.0 13 | * 14 | */ 15 | 16 | public class DAOProvider { 17 | 18 | public static void main(String[] args) throws IOException { 19 | ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( 20 | "conf/provider/ha-db-context.xml"); 21 | context.start(); 22 | IRecordService recordService = context.getBean(IRecordService.class); 23 | int result = recordService.ping(" local."); //本地方法调用 24 | 25 | System.out.println("main method result is:" + result); 26 | System.out.println("Service successfully started"); 27 | // 按任意键退出 28 | System.in.read(); 29 | } 30 | } -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/service/business/IRecordService.java: -------------------------------------------------------------------------------- 1 | package com.hitler.service.business; 2 | 3 | import com.hitler.model.business.Record; 4 | import com.hitler.service.support.IGenericService; 5 | 6 | public interface IRecordService extends IGenericService { 7 | public int ping(String cnd); 8 | public Object testMycatSchemas(String schema_name); 9 | } 10 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/service/business/impl/RecordService.java: -------------------------------------------------------------------------------- 1 | package com.hitler.service.business.impl; 2 | 3 | import javax.annotation.Resource; 4 | import javax.persistence.Query; 5 | 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | import com.hitler.model.business.Record; 10 | import com.hitler.repository.business.IRecordRepository; 11 | import com.hitler.repository.support.GenericRepository; 12 | import com.hitler.service.business.IRecordService; 13 | import com.hitler.service.support.GenericService; 14 | 15 | /** 16 | * 记录服务实现 17 | * @author onsoul by JT 2015-5-26 下午3:38:57 18 | */ 19 | @Service("recordService") 20 | public class RecordService extends GenericService 21 | implements IRecordService { 22 | 23 | @Resource 24 | private IRecordRepository repository; 25 | 26 | @Override 27 | protected GenericRepository getRepository() { 28 | return repository; 29 | } 30 | 31 | @Override 32 | public int ping(String cnd) { 33 | logger.info("cmd=========================:" + cnd); 34 | return 90; 35 | } 36 | 37 | @Override 38 | @Transactional(rollbackFor = Exception.class) 39 | public Object testMycatSchemas(String schema_name) { 40 | String sql ="select * from tb_test"; 41 | Query query = em.createNativeQuery(sql); 42 | Object obj = query.getResultList(); 43 | return obj; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/service/support/GenericService.java: -------------------------------------------------------------------------------- 1 | package com.hitler.service.support; 2 | 3 | import java.io.Serializable; 4 | import java.util.Collection; 5 | import java.util.List; 6 | 7 | import javax.persistence.EntityManager; 8 | import javax.persistence.LockModeType; 9 | import javax.persistence.PersistenceContext; 10 | 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | import org.springframework.data.domain.Persistable; 14 | import org.springframework.transaction.annotation.Propagation; 15 | import org.springframework.transaction.annotation.Transactional; 16 | 17 | import com.hitler.common.repository.AggregateExpression; 18 | import com.hitler.common.repository.SearchFilter; 19 | import com.hitler.repository.support.DynamicSpecifications; 20 | import com.hitler.repository.support.GenericRepository; 21 | 22 | /** 23 | * 服务层基类,实现一些通用功能方法 24 | * @author onsoul@qq.com 25 | * @date 2016-4-12下午4:31:06 26 | * @param 27 | * @param 28 | */ 29 | public abstract class GenericService, ID extends Serializable> 30 | implements IGenericService { 31 | 32 | @PersistenceContext 33 | protected EntityManager em; 34 | 35 | protected Logger logger=LoggerFactory.getLogger(this.getClass()); 36 | 37 | protected abstract GenericRepository getRepository(); 38 | 39 | public GenericService() { 40 | } 41 | 42 | public GenericService(Class class1) { 43 | 44 | } 45 | 46 | @Override 47 | @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) 48 | public long count() { 49 | return getRepository().count(); 50 | } 51 | 52 | @Override 53 | @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) 54 | public long count(Collection filters) { 55 | return getRepository().count( 56 | DynamicSpecifications. bySearchFilter(filters)); 57 | } 58 | 59 | @Override 60 | @Transactional(rollbackFor = Exception.class) 61 | public boolean save(T entity) { 62 | return getRepository().save(entity) != null; 63 | } 64 | 65 | @Override 66 | public int save(Iterable entities) { 67 | return getRepository().save(entities).size(); 68 | } 69 | 70 | @Override 71 | @Transactional(rollbackFor = Exception.class) 72 | public boolean update(T entity) { 73 | return getRepository().update(entity) != null; 74 | } 75 | 76 | @Override 77 | @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) 78 | public boolean exists(ID id) { 79 | return getRepository().exists(id); 80 | } 81 | 82 | @Override 83 | @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) 84 | public T findOne(ID id) { 85 | return getRepository().findOne(id); 86 | } 87 | 88 | @Override 89 | public T findOne(ID id, LockModeType lockMode) { 90 | return getRepository().findOne(id, lockMode); 91 | } 92 | 93 | @Override 94 | @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) 95 | public T findOne(Collection filters) { 96 | return getRepository().findOne( 97 | DynamicSpecifications. bySearchFilter(filters)); 98 | } 99 | 100 | @Override 101 | public T findOne(Collection filters, LockModeType lockMode) { 102 | return getRepository().findOne( 103 | DynamicSpecifications. bySearchFilter(filters), lockMode); 104 | } 105 | 106 | @Override 107 | @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) 108 | public List findAll() { 109 | return getRepository().findAll(); 110 | } 111 | 112 | @Override 113 | @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) 114 | public List findAll(Iterable ids) { 115 | return getRepository().findAll(ids); 116 | } 117 | 118 | @Override 119 | @Transactional(rollbackFor = Exception.class) 120 | public void delete(ID id) { 121 | getRepository().delete(id); 122 | } 123 | 124 | @Override 125 | @Transactional(rollbackFor = Exception.class) 126 | public void delete(T entity) { 127 | getRepository().delete(entity); 128 | } 129 | 130 | @Override 131 | public void delete(Iterable entities) { 132 | getRepository().deleteInBatch(entities); 133 | } 134 | 135 | @Override 136 | @Transactional(rollbackFor = Exception.class) 137 | public void deleteAll() { 138 | getRepository().deleteAll(); 139 | } 140 | 141 | @Override 142 | public S sum(Class resultClass, Collection filters, 143 | String... properties) { 144 | return getRepository().sum(resultClass, 145 | DynamicSpecifications. bySearchFilter(filters), properties); 146 | } 147 | 148 | @Override 149 | public S sum(Class resultClass, Collection filters, 150 | List properties) { 151 | return getRepository().sum(resultClass, 152 | DynamicSpecifications. bySearchFilter(filters), properties); 153 | } 154 | 155 | @Override 156 | public S aggregate(Class resultClass, 157 | Collection filters, AggregateExpression expression) { 158 | return getRepository().aggregate(resultClass, 159 | DynamicSpecifications. bySearchFilter(filters), expression); 160 | } 161 | 162 | public EntityManager getEm() { 163 | return em; 164 | } 165 | 166 | public void setEm(EntityManager em) { 167 | this.em = em; 168 | } 169 | 170 | } -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/java/com/hitler/service/support/IGenericService.java: -------------------------------------------------------------------------------- 1 | package com.hitler.service.support; 2 | 3 | import java.io.Serializable; 4 | import java.util.Collection; 5 | import java.util.List; 6 | 7 | import javax.persistence.LockModeType; 8 | 9 | import com.hitler.common.repository.AggregateExpression; 10 | import com.hitler.common.repository.IPageResults; 11 | import com.hitler.common.repository.IPageable; 12 | import com.hitler.common.repository.SearchFilter; 13 | import com.hitler.common.repository.Sorter; 14 | 15 | /** 16 | * DAO 通用接口,该接口定义DAO的通用方法 17 | * 18 | * @author 2015-04-25 19 | */ 20 | public interface IGenericService { 21 | 22 | /** 23 | * 持久化实体对象到数据库 24 | * 25 | * @param entity 26 | * @return 27 | */ 28 | boolean save(T entity); 29 | 30 | /** 31 | * 持久化实体对象列表到数据库 32 | * 33 | * @param entity 34 | * @return 35 | */ 36 | int save(Iterable entities); 37 | 38 | /** 39 | * 修改数据库的持久化对象 40 | * 41 | * @param entity 42 | * @return 43 | */ 44 | boolean update(T entity); 45 | 46 | /** 47 | * 查找指定主键的对象是否存在数据库 48 | * 49 | * @param entity 50 | * @return 51 | */ 52 | boolean exists(ID id); 53 | 54 | /** 55 | * 查找指定主键的对象并返回 56 | * 57 | * @param entity 58 | * @return 59 | */ 60 | T findOne(ID id); 61 | 62 | /** 63 | * 查找指定主键的对象并返回 64 | * 65 | * @param entity 66 | * @return 67 | */ 68 | T findOne(ID id, LockModeType lockMode); 69 | 70 | T findOne(Collection filters); 71 | 72 | /** 73 | * 采用锁模式查找指定主键的对象并返回 74 | * 75 | * @param entity 76 | * @return 77 | */ 78 | T findOne(Collection filters, LockModeType lockMode); 79 | 80 | List findAll(); 81 | 82 | List findAll(Iterable ids); 83 | 84 | void delete(ID id); 85 | 86 | void delete(T entity); 87 | 88 | void delete(Iterable entities); 89 | 90 | void deleteAll(); 91 | 92 | long count(); 93 | 94 | long count(Collection filters); 95 | 96 | S sum(Class resultClass, Collection filters, 97 | String... properties); 98 | 99 | S sum(Class resultClass, Collection filters, 100 | List properties); 101 | 102 | S aggregate(Class resultClass, Collection filters, 103 | AggregateExpression expression); 104 | 105 | /* public GenericTable findTable(Collection filters, IPageable pageable) throws Exception;*/ 106 | } 107 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/resources/conf/consumer/consumer-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 服务消费方配置(调用数据层) 9 | 10 | 11 | 13 | 14 | 15 | classpath*:conf/consumer/consumer.properties 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/resources/conf/consumer/consumer-service.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | dubbo注册中心配置 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 22 | 23 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/resources/conf/consumer/consumer.properties: -------------------------------------------------------------------------------- 1 | application.name=hiter-application 2 | application.owner=JT 3 | application.ip=127.0.0.1 4 | 5 | dubbo.registry.address=zookeeper://127.0.0.1:2181 6 | dubbo.protocol.name=dubbo 7 | dubbo.protocol.port=20882 8 | dubbo.consumer.check=false 9 | 10 | dubbo.timeout=30000 11 | dubbo.serial=java 12 | 13 | d.consumer.version=0.1.2 -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/resources/conf/provider/db-core.properties: -------------------------------------------------------------------------------- 1 | application.name=hiter-dao-provider 2 | application.ip=127.0.0.1 3 | #application.ip=61.64.58.174 4 | 5 | dubbo.registry.address=zookeeper://127.0.0.1:2181 6 | 7 | dubbo.registry.port=20881 8 | dubbo.protocol=dubbo 9 | dubbo.timeout=60000 10 | dubbo.serial=java 11 | 12 | dubbo.version=0.1.2 13 | 14 | 15 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/resources/conf/provider/db-core.xml: -------------------------------------------------------------------------------- 1 | 2 | 21 | 22 | 数据源配置 23 | 24 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | true 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 57 | 58 | 59 | 60 | 61 | ${database.dialect} 62 | 63 | update 64 | true 65 | true 66 | 67 | 68 | true 69 | org.hibernate.cache.ehcache.EhCacheRegionFactory 70 | 71 | classpath:conf/provider/ehcache.xml 72 | true 73 | com.hitler.common.aop.CheageSchemaInterceptor 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 86 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/resources/conf/provider/db-provider.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | DUBBO 通用配置 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 20 | 21 | 23 | 24 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/resources/conf/provider/ehcache.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/resources/conf/provider/ha-db-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | Spring公共配置 17 | 18 | 19 | 20 | 21 | 23 | 24 | 25 | classpath*:conf/provider/db-core.properties 26 | classpath*:conf/provider/jdbc.properties 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/resources/conf/provider/jdbc.properties: -------------------------------------------------------------------------------- 1 | database.driver = com.mysql.jdbc.Driver 2 | database.dialect = org.hibernate.dialect.MySQLDialect 3 | ##test 4 | #database.url = jdbc:mysql://192.168.0.31:3306/jt02?zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=UTF-8 5 | #database.username = root 6 | #database.password = jt123$%^ 7 | 8 | database.url = jdbc:mysql://192.168.0.200:8066/T1?useUnicode=true&characterEncoding=UTF-8 9 | database.username = root 10 | database.password =123456 -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/resources/pak/provider/hitler-provider-jar.bat: -------------------------------------------------------------------------------- 1 | @title HITLER-HA-DB RUNING %1 2 | 3 | @echo %~dp0 4 | echo off 5 | rem Guess MNIS_HOME if not defined 6 | set "CURRENT_DIR=%cd%" 7 | if not "%MNIS_HOME%" == "" goto gotHome 8 | set "MNIS_HOME=%CURRENT_DIR%" 9 | if exist "%MNIS_HOME%\bin\hitler-provider-jar.bat" goto okHome 10 | set "MNIS_HOME=%~dp0.." 11 | cd "%CURRENT_DIR%" 12 | 13 | :gotHome 14 | if exist "%MNIS_HOME%\bin\hitler-provider-jar.bat" goto okHome 15 | echo The MNIS_HOME environment variable is not defined correctly 16 | echo This environment variable is needed to run this program 17 | goto end 18 | 19 | :okHome 20 | if "%1" == "" goto startup 21 | 22 | :startup 23 | @set classpath=%JAVA_HOME%\lib;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;%MNIS_HOME%\lib; 24 | java -Xms32m -Xmx128m -XX:MaxNewSize=32m -XX:MaxPermSize=128m -jar %MNIS_HOME%\db-proxy-dao-0.0.1.jar %1 & 25 | 26 | echo on 27 | :end 28 | pause -------------------------------------------------------------------------------- /saas-mycat/saas/src/main/resources/pak/provider/provider-assembly.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | DB 7 | 8 | dir 9 | 10 | 11 | 12 | ${project.build.directory}/${artifactId}-dao-${project.version}.jar 13 | / 14 | 15 | 16 | 17 | 18 | ${project.basedir} 19 | / 20 | 21 | README* 22 | 23 | 24 | 25 | 26 | ${project.build.outputDirectory}/pak/provider/ 27 | /bin/ 28 | 29 | *.bat 30 | *.sh 31 | 32 | 33 | 34 | 35 | 36 | lib 37 | runtime 38 | 39 | 40 | -------------------------------------------------------------------------------- /saas-mycat/saas/src/test/java/com/hitler/test/BaseTest.java: -------------------------------------------------------------------------------- 1 | package com.hitler.test; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.test.context.ContextConfiguration; 8 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 9 | 10 | /** 11 | * @author onsoul 12 | */ 13 | @RunWith(SpringJUnit4ClassRunner.class) 14 | @ContextConfiguration({ "classpath:conf/provider/ha-db-context.xml" }) 15 | public class BaseTest { 16 | protected Logger logger = LoggerFactory.getLogger(BaseTest.class); 17 | 18 | 19 | @Test 20 | public void testContext() { 21 | logger.info("ok ."); 22 | } 23 | } -------------------------------------------------------------------------------- /saas-mycat/saas/src/test/java/com/hitler/test/dao/RecordTest.java: -------------------------------------------------------------------------------- 1 | package com.hitler.test.dao; 2 | 3 | import java.util.List; 4 | 5 | import javax.annotation.Resource; 6 | 7 | import org.junit.Test; 8 | 9 | import com.alibaba.dubbo.rpc.RpcContext; 10 | import com.hitler.common.dubbo.RpcContextAttachment; 11 | import com.hitler.model.business.Record; 12 | import com.hitler.service.business.IRecordService; 13 | import com.hitler.test.BaseTest; 14 | 15 | public class RecordTest extends BaseTest { 16 | 17 | @Resource 18 | private IRecordService recordService; 19 | 20 | @Test 21 | public void schemaChangeTest() { 22 | String schema_name="T2"; 23 | Object result =recordService.testMycatSchemas(schema_name); 24 | logger.info("###end"+result.toString()); 25 | } 26 | 27 | @Test 28 | public void saveTest() { 29 | recordService.save(cellRecord()); 30 | } 31 | 32 | @Test 33 | public void findTest() { 34 | 35 | RpcContext.getContext().setAttachment(RpcContextAttachment.ATTR_T_SCHEMA, "T2"); 36 | List result = recordService.findAll(); 37 | for (Record br : result) { 38 | logger.info("#### user name:" + br.getUserName()); 39 | } 40 | } 41 | 42 | private Record cellRecord() { //生成一条记录 43 | Record br = new Record(); 44 | br.setUserName("kind"); 45 | br.setUserId(2); 46 | br.setParentId(1); 47 | br.setParentName("onsoul@qq.com"); 48 | br.setFloor((short) 99); 49 | br.setAmount(1024d); 50 | br.setTotal(10000D); 51 | return br; 52 | } 53 | 54 | } 55 | --------------------------------------------------------------------------------