├── .gitignore ├── README.md ├── account ├── api │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── akkafun │ │ └── account │ │ └── api │ │ ├── AccountUrl.java │ │ ├── constants │ │ └── AccountFlowType.java │ │ └── events │ │ └── AskReduceBalance.java ├── core │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── akkafun │ │ │ │ └── account │ │ │ │ ├── context │ │ │ │ └── AccountApplication.java │ │ │ │ ├── dao │ │ │ │ ├── AccountFlowRepository.java │ │ │ │ ├── AccountFlowRepositoryCustom.java │ │ │ │ ├── AccountFlowRepositoryImpl.java │ │ │ │ ├── AccountRepository.java │ │ │ │ ├── AccountRepositoryCustom.java │ │ │ │ └── AccountRepositoryImpl.java │ │ │ │ ├── domain │ │ │ │ ├── Account.java │ │ │ │ └── AccountFlow.java │ │ │ │ ├── handler │ │ │ │ ├── AskReduceBalanceHandler.java │ │ │ │ └── UserCreatedHandler.java │ │ │ │ ├── service │ │ │ │ └── AccountService.java │ │ │ │ └── web │ │ │ │ └── AccountController.java │ │ └── resources │ │ │ ├── bootstrap.yml │ │ │ └── logback.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── akkafun │ │ └── account │ │ └── TestClass.java ├── docs │ ├── account-service.pdm │ └── account-service.sql └── pom.xml ├── apiutils ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── akkafun │ └── base │ ├── Constants.java │ ├── api │ ├── BooleanWrapper.java │ ├── CommonErrorCode.java │ ├── Error.java │ └── ErrorCode.java │ ├── event │ ├── constants │ │ ├── EventType.java │ │ ├── FailureInfo.java │ │ └── FailureReason.java │ └── domain │ │ ├── AskEvent.java │ │ ├── AskResponseEvent.java │ │ ├── BaseEvent.java │ │ ├── NotifyEvent.java │ │ ├── Revokable.java │ │ └── RevokeAskEvent.java │ └── exception │ ├── AppBusinessException.java │ ├── BaseException.java │ ├── RemoteCallException.java │ └── ServiceUnavailableException.java ├── common ├── docs │ ├── common.pdm │ └── common.sql ├── pom.xml └── src │ ├── main │ └── java │ │ └── com │ │ └── akkafun │ │ └── common │ │ ├── dao │ │ └── AbstractRepository.java │ │ ├── domain │ │ ├── AuditEntity.java │ │ ├── LockableEntity.java │ │ └── VersionEntity.java │ │ ├── event │ │ ├── AskEventCallback.java │ │ ├── AskParameter.java │ │ ├── AskParameterBuilder.java │ │ ├── EventRegistry.java │ │ ├── EventUtils.java │ │ ├── config │ │ │ ├── EventConfiguration.java │ │ │ └── InitBindProducer.java │ │ ├── constant │ │ │ ├── AskEventStatus.java │ │ │ ├── EventCategory.java │ │ │ └── ProcessStatus.java │ │ ├── dao │ │ │ ├── AskRequestEventPublishRepository.java │ │ │ ├── AskRequestEventPublishRepositoryCustom.java │ │ │ ├── AskRequestEventPublishRepositoryImpl.java │ │ │ ├── AskResponseEventPublishRepository.java │ │ │ ├── AskResponseEventPublishRepositoryCustom.java │ │ │ ├── AskResponseEventPublishRepositoryImpl.java │ │ │ ├── EventProcessRepository.java │ │ │ ├── EventProcessRepositoryCustom.java │ │ │ ├── EventProcessRepositoryImpl.java │ │ │ ├── EventPublishRepository.java │ │ │ ├── EventWatchProcessRepository.java │ │ │ ├── EventWatchProcessRepositoryCustom.java │ │ │ ├── EventWatchProcessRepositoryImpl.java │ │ │ ├── EventWatchRepository.java │ │ │ ├── EventWatchRepositoryCustom.java │ │ │ ├── EventWatchRepositoryImpl.java │ │ │ ├── NotifyEventPublishRepository.java │ │ │ ├── NotifyEventPublishRepositoryCustom.java │ │ │ ├── NotifyEventPublishRepositoryImpl.java │ │ │ ├── RevokeAskEventPublishRepository.java │ │ │ ├── RevokeAskEventPublishRepositoryCustom.java │ │ │ └── RevokeAskEventPublishRepositoryImpl.java │ │ ├── domain │ │ │ ├── AskRequestEventPublish.java │ │ │ ├── AskResponseEventPublish.java │ │ │ ├── EventProcess.java │ │ │ ├── EventPublish.java │ │ │ ├── EventWatch.java │ │ │ ├── EventWatchProcess.java │ │ │ ├── NotifyEventPublish.java │ │ │ └── RevokeAskEventPublish.java │ │ ├── handler │ │ │ ├── AskEventHandler.java │ │ │ ├── NotifyEventHandler.java │ │ │ └── RevokableAskEventHandler.java │ │ ├── scheduler │ │ │ └── EventScheduler.java │ │ └── service │ │ │ ├── EventActivator.java │ │ │ ├── EventBus.java │ │ │ ├── EventHandlerExecutor.java │ │ │ ├── EventPublishService.java │ │ │ └── EventWatchService.java │ │ ├── exception │ │ └── EventException.java │ │ ├── scheduler │ │ ├── ZkCoordinateScheduledExecutor.java │ │ ├── ZkSchedulerCoordinator.java │ │ └── config │ │ │ └── SchedulerConfiguration.java │ │ ├── spring │ │ ├── ApplicationConstant.java │ │ ├── ApplicationContextHolder.java │ │ ├── BaseConfiguration.java │ │ ├── ServiceClientConfiguration.java │ │ ├── WebApplication.java │ │ ├── cloud │ │ │ └── stream │ │ │ │ ├── CustomBinderAwareChannelResolver.java │ │ │ │ └── CustomChannelBindingService.java │ │ ├── mvc │ │ │ ├── AppErrorController.java │ │ │ └── AppExceptionHandlerController.java │ │ └── utils │ │ │ └── InnerClassPathScanningCandidateComponentProvider.java │ │ └── test │ │ ├── callbacks │ │ ├── AskTestEventFirstCallback.java │ │ ├── AskTestEventSecondCallback.java │ │ ├── CallbackParam.java │ │ └── UnitedTestEventCallback.java │ │ ├── domain │ │ ├── AskTestEvent.java │ │ ├── NotifyFirstTestEvent.java │ │ ├── NotifySecondTestEvent.java │ │ └── RevokableAskTestEvent.java │ │ └── handlers │ │ ├── AskTestEventHandler.java │ │ ├── NotifyFirstTestEventFirstHandler.java │ │ ├── NotifyFirstTestEventSecondHandler.java │ │ ├── NotifySecondTestEventHandler.java │ │ └── RevokableAskTestEventHandler.java │ └── test │ └── java │ └── com │ └── akkafun │ └── common │ ├── event │ ├── EventRegistryTest.java │ ├── EventTestUtils.java │ └── EventUtilsTest.java │ └── test │ ├── BaseControllerTest.java │ └── BaseTest.java ├── config ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── akkafun │ │ └── config │ │ └── ConfigApplication.java │ └── resources │ └── application.yml ├── coupon ├── api │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── akkafun │ │ └── coupon │ │ └── api │ │ ├── CouponUrl.java │ │ ├── constants │ │ └── CouponState.java │ │ ├── dtos │ │ └── CouponDto.java │ │ └── events │ │ └── AskUseCoupon.java ├── core │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── akkafun │ │ │ └── coupon │ │ │ ├── context │ │ │ └── CouponApplication.java │ │ │ ├── dao │ │ │ ├── CouponRepository.java │ │ │ ├── CouponRepositoryCustom.java │ │ │ └── CouponRepositoryImpl.java │ │ │ ├── domain │ │ │ └── Coupon.java │ │ │ ├── handler │ │ │ ├── AskUseCouponHandler.java │ │ │ └── UserCreatedHandler.java │ │ │ ├── service │ │ │ └── CouponService.java │ │ │ └── web │ │ │ └── CouponController.java │ │ └── resources │ │ ├── bootstrap.yml │ │ └── logback.xml ├── docs │ ├── coupon-service.pdm │ └── coupon-service.sql └── pom.xml ├── docs ├── event.asta └── init_database.sql ├── eureka ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── akkafun │ │ └── eureka │ │ └── EurekaApplication.java │ └── resources │ ├── application.yml │ └── logback.xml ├── integration-test ├── pom.xml └── src │ ├── main │ └── resources │ │ ├── application.yml │ │ └── logback.xml │ └── test │ └── java │ └── com │ └── akkafun │ └── integrationtest │ ├── order │ └── OrderIntegrationTest.java │ └── test │ ├── BaseIntegrationTest.java │ └── IntegrationTestApplication.java ├── order ├── api │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── akkafun │ │ └── order │ │ └── api │ │ ├── OrderUrl.java │ │ ├── constants │ │ └── OrderStatus.java │ │ ├── dtos │ │ ├── OrderDto.java │ │ ├── OrderItemDto.java │ │ ├── PlaceOrderDto.java │ │ └── PlaceOrderItemDto.java │ │ └── events │ │ └── OrderCreatePending.java ├── core │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── akkafun │ │ │ │ └── order │ │ │ │ ├── callback │ │ │ │ └── OrderCreateCallback.java │ │ │ │ ├── context │ │ │ │ └── OrderApplication.java │ │ │ │ ├── dao │ │ │ │ ├── OrderCouponRepository.java │ │ │ │ ├── OrderItemRepository.java │ │ │ │ ├── OrderRepository.java │ │ │ │ ├── OrderRepositoryCustom.java │ │ │ │ └── OrderRepositoryImpl.java │ │ │ │ ├── domain │ │ │ │ ├── Order.java │ │ │ │ ├── OrderCoupon.java │ │ │ │ └── OrderItem.java │ │ │ │ ├── service │ │ │ │ ├── OrderService.java │ │ │ │ └── gateway │ │ │ │ │ ├── AccountClient.java │ │ │ │ │ ├── AccountGateway.java │ │ │ │ │ ├── CouponClient.java │ │ │ │ │ ├── CouponGateway.java │ │ │ │ │ ├── ProductClient.java │ │ │ │ │ └── ProductGateway.java │ │ │ │ ├── utils │ │ │ │ └── OrderUtils.java │ │ │ │ └── web │ │ │ │ └── OrderController.java │ │ └── resources │ │ │ ├── bootstrap.yml │ │ │ └── logback.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── akkafun │ │ └── order │ │ ├── service │ │ ├── OrderServiceTest.java │ │ └── gateway │ │ │ └── ProductGatewayTest.java │ │ └── test │ │ ├── OrderBaseControllerTest.java │ │ ├── OrderBaseTest.java │ │ └── TestOrderApplication.java ├── docs │ ├── order-service.pdm │ └── order-service.sql └── pom.xml ├── pom.xml ├── product ├── api │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── akkafun │ │ └── product │ │ └── api │ │ ├── ProductUrl.java │ │ └── dtos │ │ └── ProductDto.java ├── core │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── com │ │ │ └── akkafun │ │ │ └── product │ │ │ ├── context │ │ │ └── ProductApplication.java │ │ │ ├── dao │ │ │ └── ProductRepository.java │ │ │ ├── domain │ │ │ └── Product.java │ │ │ ├── service │ │ │ └── ProductService.java │ │ │ └── web │ │ │ └── ProductController.java │ │ └── resources │ │ ├── bootstrap.yml │ │ └── logback.xml ├── docs │ ├── init-product.sql │ ├── product-service.pdm │ └── product-service.sql └── pom.xml ├── turbine ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── akkafun │ │ └── turbine │ │ └── TurbineApplication.java │ └── resources │ └── application.yml ├── user ├── api │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── akkafun │ │ └── user │ │ └── api │ │ ├── UserErrorCode.java │ │ ├── UserUrl.java │ │ ├── dtos │ │ ├── RegisterDto.java │ │ └── UserDto.java │ │ ├── events │ │ └── UserCreated.java │ │ └── utils │ │ └── RegExpUtils.java ├── core │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── com │ │ │ │ └── akkafun │ │ │ │ └── user │ │ │ │ ├── context │ │ │ │ └── UserApplication.java │ │ │ │ ├── dao │ │ │ │ ├── UserRepository.java │ │ │ │ ├── UserRepositoryCustom.java │ │ │ │ └── UserRepositoryImpl.java │ │ │ │ ├── domain │ │ │ │ └── User.java │ │ │ │ ├── service │ │ │ │ └── UserService.java │ │ │ │ └── web │ │ │ │ └── UserController.java │ │ └── resources │ │ │ ├── bootstrap.yml │ │ │ └── logback.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── akkafun │ │ ├── common │ │ └── event │ │ │ ├── load │ │ │ ├── FakeAskCouponUse.java │ │ │ ├── FakeAskDeductBalance.java │ │ │ ├── FakeAskEvent.java │ │ │ ├── FakeEventBus.java │ │ │ ├── FakeUnitedAskEventCallback.java │ │ │ └── LoadEventClassTest.java │ │ │ └── service │ │ │ └── EventBusTest.java │ │ └── user │ │ ├── service │ │ └── UserServiceTest.java │ │ ├── test │ │ ├── TestUserApplication.java │ │ ├── UserBaseControllerTest.java │ │ └── UserBaseTest.java │ │ └── web │ │ └── UserControllerTest.java ├── docs │ ├── user-service.pdm │ └── user-service.sql └── pom.xml └── utils ├── pom.xml └── src ├── main └── java │ └── com │ └── akkafun │ └── common │ └── utils │ ├── CustomPreconditions.java │ ├── JsonUtils.java │ ├── PasswordHash.java │ ├── SQLUtils.java │ ├── StringUtils.java │ ├── TestUtils.java │ ├── UpdateByIdFunction.java │ ├── ZkUtils.java │ └── spring │ ├── CustomRestTemplate.java │ └── RestTemplateErrorHandler.java └── test └── java └── com └── akkafun └── common └── utils └── StringUtilsTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | logs 2 | project/project 3 | project/target 4 | target 5 | tmp 6 | .history 7 | dist 8 | /.idea 9 | *.iml 10 | /out 11 | /.idea_modules 12 | /.classpath 13 | /.project 14 | /RUNNING_PID 15 | /.settings 16 | *.pdb 17 | **/development.conf 18 | **/application-log.* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mysteam 2 | 3 | mysteam是一个Demo项目, 用来演示Spring Cloud与Netflix OSS在微服务系统中的使用. 4 | 5 | ######主要特点: 6 | 7 | 1. 使用eureka和Netflix Ribbon进行服务注册和服务发现. 8 | 9 | 2. 使用Spring Cloud Stream, zookeeper和kafka实现分布式事务. 10 | 11 | 3. 使用hystrix实现服务隔离, hystrix dashboard和turbine进行服务监控. 12 | 13 | 4. 使用Spring MVC和Swagger实现REST API. 14 | 15 | 5. 使用Spring Cloud Config实现配置集中管理. 16 | 17 | 详细介绍: [Spring Cloud与微服务](http://skaka.me/blog/2016/08/03/springcloud2/) 18 | -------------------------------------------------------------------------------- /account/api/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | account-service-api 6 | jar 7 | 8 | 9 | com.akkafun.mysteam 10 | account-service 11 | 1.0-SNAPSHOT 12 | 13 | 14 | 15 | 16 | 17 | 18 | com.akkafun.mysteam 19 | apiutils 20 | ${project.version} 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /account/api/src/main/java/com/akkafun/account/api/AccountUrl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.account.api; 2 | 3 | /** 4 | * Created by liubin on 2016/5/6. 5 | */ 6 | public interface AccountUrl { 7 | 8 | String SERVICE_NAME = "ACCOUNT"; 9 | 10 | String SERVICE_HOSTNAME = "http://ACCOUNT"; 11 | 12 | String CHECK_ENOUGH_BALANCE = "/accounts/{userId}/enough"; 13 | 14 | String ACCOUNT_BALANCE = "/accounts/{userId}/balance"; 15 | 16 | String ACCOUNT_TRANSACTIONS = "/accounts/{userId}/transactions"; 17 | 18 | static String buildUrl(String url) { 19 | return SERVICE_HOSTNAME + url; 20 | } 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /account/api/src/main/java/com/akkafun/account/api/constants/AccountFlowType.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.account.api.constants; 2 | 3 | /** 4 | * Created by liubin on 2016/4/26. 5 | */ 6 | public enum AccountFlowType { 7 | 8 | ORDER("下单"); 9 | 10 | public String desc; 11 | 12 | AccountFlowType(String desc) { 13 | this.desc = desc; 14 | } 15 | 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /account/api/src/main/java/com/akkafun/account/api/events/AskReduceBalance.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.account.api.events; 2 | 3 | import com.akkafun.base.event.constants.EventType; 4 | import com.akkafun.base.event.domain.AskEvent; 5 | import com.akkafun.base.event.domain.Revokable; 6 | import com.fasterxml.jackson.annotation.JsonCreator; 7 | import com.fasterxml.jackson.annotation.JsonProperty; 8 | 9 | /** 10 | * Created by liubin on 2016/4/8. 11 | */ 12 | public class AskReduceBalance extends AskEvent implements Revokable { 13 | 14 | public static final EventType EVENT_TYPE = EventType.ASK_REDUCE_BALANCE; 15 | 16 | @Override 17 | public EventType getType() { 18 | return EVENT_TYPE; 19 | } 20 | 21 | private Long userId; 22 | 23 | private Long balance; 24 | 25 | @JsonCreator 26 | public AskReduceBalance( 27 | @JsonProperty("userId") Long userId, 28 | @JsonProperty("balance") Long balance) { 29 | this.userId = userId; 30 | this.balance = balance; 31 | } 32 | 33 | public Long getUserId() { 34 | return userId; 35 | } 36 | 37 | public Long getBalance() { 38 | return balance; 39 | } 40 | 41 | @Override 42 | public String toString() { 43 | return "AskReduceBalance{" + 44 | "userId=" + userId + 45 | ", balance=" + balance + 46 | "} " + super.toString(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /account/core/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | account-service-core 6 | jar 7 | 8 | 9 | com.akkafun.mysteam 10 | account-service 11 | 1.0-SNAPSHOT 12 | 13 | 14 | 15 | 16 | com.akkafun.account.context.AccountApplication 17 | 18 | 19 | 20 | 21 | 22 | mysql 23 | mysql-connector-java 24 | runtime 25 | 26 | 27 | 28 | com.akkafun.mysteam 29 | common 30 | ${project.version} 31 | 32 | 33 | 34 | com.akkafun.mysteam 35 | common 36 | ${project.version} 37 | test-jar 38 | test 39 | 40 | 41 | 42 | com.akkafun.mysteam 43 | user-service-api 44 | ${project.version} 45 | 46 | 47 | 48 | com.akkafun.mysteam 49 | account-service-api 50 | ${project.version} 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | org.springframework.boot 59 | spring-boot-maven-plugin 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /account/core/src/main/java/com/akkafun/account/context/AccountApplication.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.account.context; 2 | 3 | import com.akkafun.common.event.config.EventConfiguration; 4 | import com.akkafun.common.scheduler.config.SchedulerConfiguration; 5 | import com.akkafun.common.spring.BaseConfiguration; 6 | import com.akkafun.common.spring.ServiceClientConfiguration; 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.context.annotation.Import; 10 | 11 | /** 12 | * Created by liubin on 2016/3/28. 13 | */ 14 | @SpringBootApplication 15 | @Import({BaseConfiguration.class, EventConfiguration.class, SchedulerConfiguration.class, ServiceClientConfiguration.class}) 16 | public class AccountApplication { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(AccountApplication.class, args); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /account/core/src/main/java/com/akkafun/account/dao/AccountFlowRepository.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.account.dao; 2 | 3 | import com.akkafun.account.domain.AccountFlow; 4 | import org.springframework.data.repository.PagingAndSortingRepository; 5 | 6 | /** 7 | * Created by liubin on 2016/4/26. 8 | */ 9 | public interface AccountFlowRepository extends PagingAndSortingRepository, AccountFlowRepositoryCustom { 10 | } 11 | -------------------------------------------------------------------------------- /account/core/src/main/java/com/akkafun/account/dao/AccountFlowRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.account.dao; 2 | 3 | import com.akkafun.common.dao.AbstractRepository; 4 | 5 | /** 6 | * Created by liubin on 2016/4/26. 7 | */ 8 | public interface AccountFlowRepositoryCustom extends AbstractRepository { 9 | } 10 | -------------------------------------------------------------------------------- /account/core/src/main/java/com/akkafun/account/dao/AccountFlowRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.account.dao; 2 | 3 | import javax.persistence.EntityManager; 4 | import javax.persistence.PersistenceContext; 5 | 6 | /** 7 | * Created by liubin on 2016/4/26. 8 | */ 9 | public class AccountFlowRepositoryImpl implements AccountFlowRepositoryCustom { 10 | 11 | @PersistenceContext 12 | private EntityManager em; 13 | 14 | 15 | @Override 16 | public EntityManager getEm() { 17 | return em; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /account/core/src/main/java/com/akkafun/account/dao/AccountRepository.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.account.dao; 2 | 3 | import com.akkafun.account.domain.Account; 4 | import org.springframework.data.jpa.repository.Query; 5 | import org.springframework.data.repository.PagingAndSortingRepository; 6 | 7 | /** 8 | * Created by liubin on 2016/4/26. 9 | */ 10 | public interface AccountRepository extends PagingAndSortingRepository, AccountRepositoryCustom { 11 | 12 | Account findByUserId(Long userId); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /account/core/src/main/java/com/akkafun/account/dao/AccountRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.account.dao; 2 | 3 | import com.akkafun.common.dao.AbstractRepository; 4 | 5 | /** 6 | * Created by liubin on 2016/4/26. 7 | */ 8 | public interface AccountRepositoryCustom extends AbstractRepository { 9 | } 10 | -------------------------------------------------------------------------------- /account/core/src/main/java/com/akkafun/account/dao/AccountRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.account.dao; 2 | 3 | import javax.persistence.EntityManager; 4 | import javax.persistence.PersistenceContext; 5 | 6 | /** 7 | * Created by liubin on 2016/4/26. 8 | */ 9 | public class AccountRepositoryImpl implements AccountRepositoryCustom { 10 | 11 | @PersistenceContext 12 | private EntityManager em; 13 | 14 | 15 | @Override 16 | public EntityManager getEm() { 17 | return em; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /account/core/src/main/java/com/akkafun/account/domain/Account.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.account.domain; 2 | 3 | import com.akkafun.common.domain.VersionEntity; 4 | 5 | import javax.persistence.*; 6 | 7 | /** 8 | * Created by liubin on 2016/3/28. 9 | */ 10 | @Entity 11 | @Table(name = "account") 12 | public class Account extends VersionEntity { 13 | 14 | @Id 15 | @GeneratedValue(strategy = GenerationType.AUTO) 16 | private Long id; 17 | 18 | @Column 19 | private Long balance; 20 | 21 | @Column 22 | private Long userId; 23 | 24 | public Long getId() { 25 | return id; 26 | } 27 | 28 | public void setId(Long id) { 29 | this.id = id; 30 | } 31 | 32 | public Long getBalance() { 33 | return balance; 34 | } 35 | 36 | public void setBalance(Long balance) { 37 | this.balance = balance; 38 | } 39 | 40 | public Long getUserId() { 41 | return userId; 42 | } 43 | 44 | public void setUserId(Long userId) { 45 | this.userId = userId; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /account/core/src/main/java/com/akkafun/account/domain/AccountFlow.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.account.domain; 2 | 3 | import com.akkafun.account.api.constants.AccountFlowType; 4 | import com.akkafun.common.domain.AuditEntity; 5 | import com.akkafun.common.domain.VersionEntity; 6 | 7 | import javax.persistence.*; 8 | 9 | /** 10 | * Created by liubin on 2016/3/28. 11 | */ 12 | @Entity 13 | @Table(name = "account_flow") 14 | public class AccountFlow extends AuditEntity { 15 | 16 | @Id 17 | @GeneratedValue(strategy = GenerationType.AUTO) 18 | private Long id; 19 | 20 | @Column 21 | private Long balance; 22 | 23 | @Column 24 | private Long accountId; 25 | 26 | @Column 27 | private String description; 28 | 29 | @Column 30 | @Enumerated(EnumType.STRING) 31 | private AccountFlowType type; 32 | 33 | public Long getId() { 34 | return id; 35 | } 36 | 37 | public void setId(Long id) { 38 | this.id = id; 39 | } 40 | 41 | public Long getBalance() { 42 | return balance; 43 | } 44 | 45 | public void setBalance(Long balance) { 46 | this.balance = balance; 47 | } 48 | 49 | public Long getAccountId() { 50 | return accountId; 51 | } 52 | 53 | public void setAccountId(Long accountId) { 54 | this.accountId = accountId; 55 | } 56 | 57 | public String getDescription() { 58 | return description; 59 | } 60 | 61 | public void setDescription(String description) { 62 | this.description = description; 63 | } 64 | 65 | public AccountFlowType getType() { 66 | return type; 67 | } 68 | 69 | public void setType(AccountFlowType type) { 70 | this.type = type; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /account/core/src/main/java/com/akkafun/account/handler/AskReduceBalanceHandler.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.account.handler; 2 | 3 | import com.akkafun.account.api.events.AskReduceBalance; 4 | import com.akkafun.account.service.AccountService; 5 | import com.akkafun.base.api.BooleanWrapper; 6 | import com.akkafun.base.event.constants.FailureInfo; 7 | import com.akkafun.base.exception.AppBusinessException; 8 | import com.akkafun.common.event.handler.RevokableAskEventHandler; 9 | import com.akkafun.common.spring.ApplicationContextHolder; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | /** 14 | * Created by liubin on 2016/6/24. 15 | */ 16 | public class AskReduceBalanceHandler implements RevokableAskEventHandler { 17 | 18 | private static Logger logger = LoggerFactory.getLogger(AskReduceBalanceHandler.class); 19 | 20 | @Override 21 | public void processRevoke(AskReduceBalance originEvent, FailureInfo failureInfo) { 22 | logger.debug("AskReduceBalanceHandler processRevoke, receive AskReduceBalance: " + originEvent); 23 | 24 | AccountService accountService = ApplicationContextHolder.context.getBean(AccountService.class); 25 | accountService.addBalance(originEvent.getUserId(), originEvent.getBalance()); 26 | } 27 | 28 | @Override 29 | public BooleanWrapper processRequest(AskReduceBalance event) { 30 | logger.debug("AskReduceBalanceHandler processRequest, receive AskReduceBalance: " + event); 31 | 32 | if(event.getUserId() == null || event.getBalance() == null) { 33 | return new BooleanWrapper(false, "userId or balance is null"); 34 | } 35 | 36 | AccountService accountService = ApplicationContextHolder.context.getBean(AccountService.class); 37 | accountService.reduceBalance(event.getUserId(), event.getBalance()); 38 | return new BooleanWrapper(true); 39 | } 40 | 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /account/core/src/main/java/com/akkafun/account/handler/UserCreatedHandler.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.account.handler; 2 | 3 | import com.akkafun.account.service.AccountService; 4 | import com.akkafun.common.event.handler.NotifyEventHandler; 5 | import com.akkafun.common.spring.ApplicationContextHolder; 6 | import com.akkafun.user.api.events.UserCreated; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.dao.DataIntegrityViolationException; 10 | 11 | /** 12 | * Created by liubin on 2016/4/14. 13 | */ 14 | public class UserCreatedHandler implements NotifyEventHandler { 15 | 16 | protected Logger logger = LoggerFactory.getLogger(UserCreatedHandler.class); 17 | 18 | @Override 19 | public void notify(UserCreated event) { 20 | 21 | AccountService accountService = ApplicationContextHolder.context.getBean(AccountService.class); 22 | 23 | try { 24 | accountService.initAccount(event.getUserId()); 25 | } catch (DataIntegrityViolationException e) { 26 | logger.warn(String.format("userId=%d的account在数据库已存在, errorMsg: %s", 27 | event.getUserId(), e.getMessage())); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /account/core/src/main/java/com/akkafun/account/web/AccountController.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.account.web; 2 | 3 | import com.akkafun.account.domain.Account; 4 | import com.akkafun.account.service.AccountService; 5 | import com.akkafun.base.api.BooleanWrapper; 6 | import com.akkafun.base.api.CommonErrorCode; 7 | import com.akkafun.base.exception.AppBusinessException; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.http.MediaType; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | import static com.akkafun.account.api.AccountUrl.ACCOUNT_BALANCE; 13 | import static com.akkafun.account.api.AccountUrl.ACCOUNT_TRANSACTIONS; 14 | import static com.akkafun.account.api.AccountUrl.CHECK_ENOUGH_BALANCE; 15 | 16 | /** 17 | * Created by liubin on 2016/3/29. 18 | */ 19 | @RestController 20 | @RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE) 21 | public class AccountController { 22 | 23 | @Autowired 24 | AccountService accountService; 25 | 26 | @RequestMapping(value = CHECK_ENOUGH_BALANCE, method = RequestMethod.GET) 27 | public BooleanWrapper checkAccountBalanceEnough(@PathVariable("userId") Long userId, 28 | @RequestParam("balance") Long balance) { 29 | boolean result = accountService.checkEnoughBalance(userId, balance); 30 | return new BooleanWrapper(result); 31 | } 32 | 33 | @RequestMapping(value = ACCOUNT_BALANCE, method = RequestMethod.GET) 34 | public Long accountBalance(@PathVariable(value = "userId") Long userId) { 35 | 36 | return accountService.getByUserId(userId).getBalance(); 37 | } 38 | 39 | @RequestMapping(value = ACCOUNT_TRANSACTIONS, method = RequestMethod.POST) 40 | public Long operateAccountBalance( 41 | @PathVariable(value = "userId") Long userId, 42 | @RequestParam(value = "amount") Long amount) { 43 | 44 | if(amount >= 0L) { 45 | return accountService.addBalance(userId, amount); 46 | } else { 47 | return accountService.reduceBalance(userId, Math.abs(amount)); 48 | } 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /account/core/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: account 4 | cloud: 5 | config: 6 | uri: ${CONFIG_SERVER_URI:http://localhost:8888} 7 | failFast: true 8 | encrypt: 9 | failOnError: true 10 | -------------------------------------------------------------------------------- /account/core/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | logs/account-service.log 15 | 16 | 17 | logs/account-service-log-%d{yyyy-MM-dd}.gz 18 | 19 | 30 20 | 21 | 22 | %date{yyyy-MM-dd HH:mm:ss} ${PID}: %-5level %logger{0} - %msg%n 23 | 24 | 25 | 26 | 27 | 28 | %date{yyyy-MM-dd HH:mm:ss} ${PID}: %-5level %logger{0} - %msg%n 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /account/core/src/test/java/com/akkafun/account/TestClass.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.account; 2 | 3 | /** 4 | * Created by liubin on 2016/5/6. 5 | */ 6 | public class TestClass{ 7 | 8 | } 9 | -------------------------------------------------------------------------------- /account/docs/account-service.sql: -------------------------------------------------------------------------------- 1 | /*==============================================================*/ 2 | /* DBMS name: MySQL 5.0 */ 3 | /* Created on: 2016/4/26 9:54:25 */ 4 | /*==============================================================*/ 5 | 6 | 7 | drop table if exists account; 8 | 9 | drop table if exists account_flow; 10 | 11 | /*==============================================================*/ 12 | /* Table: account */ 13 | /*==============================================================*/ 14 | create table account 15 | ( 16 | id bigint unsigned not null auto_increment, 17 | balance bigint not null, 18 | userId bigint not null, 19 | optlock int default 0, 20 | createTime datetime, 21 | updateTime datetime, 22 | primary key (id) 23 | ); 24 | 25 | /*==============================================================*/ 26 | /* Table: account_flow */ 27 | /*==============================================================*/ 28 | create table account_flow 29 | ( 30 | id bigint unsigned not null auto_increment, 31 | balance bigint not null, 32 | accountId bigint not null, 33 | description varchar(255), 34 | type varchar(32), 35 | createTime datetime, 36 | updateTime datetime, 37 | primary key (id) 38 | ); 39 | 40 | -------------------------------------------------------------------------------- /account/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | account-service 6 | 7 | api 8 | core 9 | 10 | pom 11 | 12 | 13 | com.akkafun.mysteam 14 | base 15 | 1.0-SNAPSHOT 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /apiutils/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | apiutils 6 | jar 7 | 8 | 9 | com.akkafun.mysteam 10 | base 11 | 1.0-SNAPSHOT 12 | 13 | 14 | 15 | 16 | 17 | org.hibernate 18 | hibernate-validator 19 | 20 | 21 | 22 | com.fasterxml.jackson.core 23 | jackson-annotations 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/Constants.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base; 2 | 3 | /** 4 | * Created by liubin on 2016/6/15. 5 | */ 6 | public interface Constants { 7 | 8 | int ASK_TIMEOUT = 30000; 9 | 10 | int MAX_BATCH_QUERY_SIZE = 100; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/api/BooleanWrapper.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | /** 7 | * Created by liubin on 2016/5/6. 8 | */ 9 | public class BooleanWrapper { 10 | 11 | private boolean success; 12 | 13 | private String message; 14 | 15 | public BooleanWrapper(boolean success) { 16 | this(success, null); 17 | } 18 | 19 | @JsonCreator 20 | public BooleanWrapper( 21 | @JsonProperty("success") boolean success, 22 | @JsonProperty("message") String message) { 23 | this.success = success; 24 | this.message = message; 25 | } 26 | 27 | public boolean isSuccess() { 28 | return success; 29 | } 30 | 31 | public String getMessage() { 32 | return message; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/api/CommonErrorCode.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.api; 2 | 3 | /** 4 | * Created by liubin on 2016/5/3. 5 | */ 6 | public enum CommonErrorCode implements ErrorCode { 7 | 8 | BAD_REQUEST(400, "请求的参数个数或格式不符合要求"), 9 | INVALID_ARGUMENT(400, "请求的参数不正确"), 10 | UNAUTHORIZED(401, "无权访问"), 11 | FORBIDDEN(403, "禁止访问"), 12 | NOT_FOUND(404, "请求的地址不正确"), 13 | METHOD_NOT_ALLOWED(405, "不允许的请求方法"), 14 | NOT_ACCEPTABLE(406, "不接受的请求"), 15 | CONFLICT(409, "资源冲突"), 16 | UNSUPPORTED_MEDIA_TYPE(415, "不支持的Media Type"), 17 | INTERNAL_ERROR(500, "服务器内部错误"), 18 | SERVICE_UNAVAILABLE(503, "服务不可用"), 19 | GATEWAY_TIMEOUT(504, "请求服务超时"); 20 | 21 | private int status; 22 | 23 | private String message; 24 | 25 | CommonErrorCode(int status, String message) { 26 | this.status = status; 27 | this.message = message; 28 | } 29 | 30 | public static CommonErrorCode fromHttpStatus(int httpStatus) { 31 | for(CommonErrorCode errorCode : values()) { 32 | if(errorCode.getStatus() == httpStatus) { 33 | return errorCode; 34 | } 35 | } 36 | return INTERNAL_ERROR; 37 | } 38 | 39 | 40 | @Override 41 | public String getCode() { 42 | return this.name(); 43 | } 44 | 45 | @Override 46 | public int getStatus() { 47 | return status; 48 | } 49 | 50 | @Override 51 | public String getMessage() { 52 | return message; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/api/Error.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | /** 7 | * Created by liubin on 15-8-3. 8 | */ 9 | public class Error { 10 | 11 | private String code; 12 | 13 | private String message; 14 | 15 | private String requestUri; 16 | 17 | @JsonCreator 18 | public Error(@JsonProperty("code") String code, 19 | @JsonProperty("requestUri") String requestUri, 20 | @JsonProperty(value = "message", defaultValue = "") String message) { 21 | this.code = code; 22 | this.requestUri = requestUri; 23 | this.message = message; 24 | } 25 | 26 | public String getCode() { 27 | return code; 28 | } 29 | 30 | public String getMessage() { 31 | return message; 32 | } 33 | 34 | public String getRequestUri() { 35 | return requestUri; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return "Error{" + 41 | "code='" + code + '\'' + 42 | ", message='" + message + '\'' + 43 | ", requestUri='" + requestUri + '\'' + 44 | '}'; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/api/ErrorCode.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.api; 2 | 3 | /** 4 | * Created by liubin on 2016/5/3. 5 | */ 6 | public interface ErrorCode { 7 | 8 | String getCode(); 9 | 10 | int getStatus(); 11 | 12 | String getMessage(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/event/constants/EventType.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.event.constants; 2 | 3 | /** 4 | * Created by liubin on 2016/4/13. 5 | */ 6 | public enum EventType { 7 | 8 | ASK_RESPONSE, 9 | 10 | REVOKE_ASK, 11 | 12 | 13 | //user service 14 | USER_CREATED, 15 | 16 | //order service 17 | ORDER_CREATE_PENDING, 18 | 19 | //account service 20 | ASK_REDUCE_BALANCE, 21 | 22 | //coupon service 23 | ASK_USE_COUPON, 24 | 25 | 26 | NOTIFY_FIRST_TEST_EVENT, 27 | 28 | NOTIFY_SECOND_TEST_EVENT, 29 | 30 | ASK_TEST_EVENT, 31 | 32 | REVOKABLE_ASK_TEST_EVENT; 33 | 34 | 35 | public static EventType valueOfIgnoreCase(String name) { 36 | if(name == null) return null; 37 | return valueOf(name.toUpperCase()); 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/event/constants/FailureInfo.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.event.constants; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | import java.time.LocalDateTime; 7 | 8 | /** 9 | * Created by liubin on 2016/6/3. 10 | */ 11 | public class FailureInfo { 12 | 13 | private FailureReason reason; 14 | 15 | private LocalDateTime failureTime; 16 | 17 | private String message; 18 | 19 | public FailureInfo(FailureReason reason, LocalDateTime failureTime) { 20 | this(reason, failureTime, null); 21 | } 22 | 23 | @JsonCreator 24 | public FailureInfo( 25 | @JsonProperty("reason") FailureReason reason, 26 | @JsonProperty("failureTime") LocalDateTime failureTime, 27 | @JsonProperty("message") String message) { 28 | this.reason = reason; 29 | this.failureTime = failureTime; 30 | this.message = message; 31 | } 32 | 33 | public FailureReason getReason() { 34 | return reason; 35 | } 36 | 37 | public void setReason(FailureReason reason) { 38 | this.reason = reason; 39 | } 40 | 41 | public LocalDateTime getFailureTime() { 42 | return failureTime; 43 | } 44 | 45 | public void setFailureTime(LocalDateTime failureTime) { 46 | this.failureTime = failureTime; 47 | } 48 | 49 | public String getMessage() { 50 | return message; 51 | } 52 | 53 | public void setMessage(String message) { 54 | this.message = message; 55 | } 56 | 57 | @Override 58 | public String toString() { 59 | return "FailureInfo{" + 60 | "reason=" + reason + 61 | ", failureTime=" + failureTime + 62 | ", message='" + message + '\'' + 63 | '}'; 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/event/constants/FailureReason.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.event.constants; 2 | 3 | /** 4 | * Created by liubin on 2016/6/3. 5 | */ 6 | public enum FailureReason { 7 | 8 | TIMEOUT("事件超时"), 9 | 10 | FAILED("事件失败"), 11 | 12 | CANCELLED("事件取消"); 13 | 14 | public String desc; 15 | 16 | FailureReason(String desc) { 17 | this.desc = desc; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/event/domain/AskEvent.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.event.domain; 2 | 3 | /** 4 | * Created by liubin on 2016/6/3. 5 | */ 6 | public abstract class AskEvent extends BaseEvent { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/event/domain/AskResponseEvent.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.event.domain; 2 | 3 | import com.akkafun.base.event.constants.EventType; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | /** 7 | * Created by liubin on 2016/6/3. 8 | */ 9 | public final class AskResponseEvent extends BaseEvent { 10 | 11 | public static final EventType EVENT_TYPE = EventType.ASK_RESPONSE; 12 | 13 | @Override 14 | public EventType getType() { 15 | return EVENT_TYPE; 16 | } 17 | 18 | private boolean success; 19 | 20 | private String message; 21 | 22 | private Long askEventId; 23 | 24 | public AskResponseEvent( 25 | @JsonProperty("success") boolean success, 26 | @JsonProperty("message") String message, 27 | @JsonProperty("askEventId") Long askEventId) { 28 | this.success = success; 29 | this.message = message; 30 | this.askEventId = askEventId; 31 | } 32 | 33 | public boolean isSuccess() { 34 | return success; 35 | } 36 | 37 | public Long getAskEventId() { 38 | return askEventId; 39 | } 40 | 41 | public String getMessage() { 42 | return message; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "AskResponseEvent{" + 48 | "success=" + success + 49 | "message=" + message + 50 | ", askEventId=" + askEventId + 51 | "} " + super.toString(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/event/domain/BaseEvent.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.event.domain; 2 | 3 | 4 | import com.akkafun.base.event.constants.EventType; 5 | import com.sun.javafx.event.EventUtil; 6 | 7 | import java.time.LocalDateTime; 8 | import java.util.Objects; 9 | import java.util.UUID; 10 | 11 | /** 12 | * 子类必须定义static变量EVENT_TYPE 13 | * 例如: public static final EventType EVENT_TYPE = EventType.TEST_EVENT; 14 | * Created by liubin on 2016/4/8. 15 | */ 16 | public abstract class BaseEvent { 17 | 18 | protected Long id; 19 | 20 | protected LocalDateTime createTime; 21 | 22 | public BaseEvent() { 23 | createTime = LocalDateTime.now(); 24 | } 25 | 26 | public void setId(Long id) { 27 | this.id = id; 28 | } 29 | 30 | public Long getId() { 31 | return id; 32 | } 33 | 34 | public LocalDateTime getCreateTime() { 35 | return createTime; 36 | } 37 | 38 | public abstract EventType getType(); 39 | 40 | 41 | 42 | @Override 43 | public boolean equals(Object o) { 44 | if (this == o) return true; 45 | if (!(o instanceof BaseEvent)) return false; 46 | BaseEvent baseEvent = (BaseEvent) o; 47 | return Objects.equals(id, baseEvent.id); 48 | } 49 | 50 | @Override 51 | public int hashCode() { 52 | return Objects.hash(id); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/event/domain/NotifyEvent.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.event.domain; 2 | 3 | /** 4 | * Created by liubin on 2016/6/3. 5 | */ 6 | public abstract class NotifyEvent extends BaseEvent { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/event/domain/Revokable.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.event.domain; 2 | 3 | /** 4 | * Created by liubin on 2016/6/3. 5 | */ 6 | public interface Revokable { 7 | } 8 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/event/domain/RevokeAskEvent.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.event.domain; 2 | 3 | import com.akkafun.base.event.constants.EventType; 4 | import com.akkafun.base.event.constants.FailureInfo; 5 | import com.akkafun.base.event.constants.FailureReason; 6 | import com.fasterxml.jackson.annotation.JsonProperty; 7 | 8 | /** 9 | * Created by liubin on 2016/6/3. 10 | */ 11 | public final class RevokeAskEvent extends BaseEvent { 12 | 13 | public static final EventType EVENT_TYPE = EventType.REVOKE_ASK; 14 | 15 | @Override 16 | public EventType getType() { 17 | return EVENT_TYPE; 18 | } 19 | 20 | private FailureInfo failureInfo; 21 | 22 | private Long askEventId; 23 | 24 | public RevokeAskEvent( 25 | @JsonProperty("failureInfo") FailureInfo failureInfo, 26 | @JsonProperty("askEventId") Long askEventId) { 27 | this.failureInfo = failureInfo; 28 | this.askEventId = askEventId; 29 | } 30 | 31 | public FailureInfo getFailureInfo() { 32 | return failureInfo; 33 | } 34 | 35 | public Long getAskEventId() { 36 | return askEventId; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "RevokeAskEvent{" + 42 | "failureInfo=" + failureInfo + 43 | ", askEventId=" + askEventId + 44 | "} " + super.toString(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/exception/AppBusinessException.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.exception; 2 | 3 | import com.akkafun.base.api.CommonErrorCode; 4 | import com.akkafun.base.api.ErrorCode; 5 | 6 | /** 7 | * Created by liubin on 2016/5/3. 8 | */ 9 | public class AppBusinessException extends BaseException { 10 | 11 | private static final ErrorCode DEFAULT_CODE = CommonErrorCode.INTERNAL_ERROR; 12 | 13 | private String code = DEFAULT_CODE.getCode(); 14 | 15 | //类似Http状态码 16 | private int httpStatus = DEFAULT_CODE.getStatus(); 17 | 18 | public AppBusinessException(String code, int httpStatus, String message) { 19 | super(message); 20 | this.code = code; 21 | this.httpStatus = httpStatus; 22 | } 23 | 24 | public AppBusinessException(String message) { 25 | super(message); 26 | } 27 | 28 | /** 29 | * @param errorCode 状态码, 这个字段会在错误信息里返回给客户端. 30 | * @param message 31 | */ 32 | public AppBusinessException(ErrorCode errorCode, String message) { 33 | this(errorCode.getCode(), errorCode.getStatus(), message); 34 | } 35 | 36 | public AppBusinessException(ErrorCode errorCode) { 37 | this(errorCode, errorCode.getMessage()); 38 | } 39 | 40 | public String getCode() { 41 | return code; 42 | } 43 | 44 | public int getHttpStatus() { 45 | return httpStatus; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/exception/BaseException.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.exception; 2 | 3 | /** 4 | * Created by liubin on 2016/4/14. 5 | */ 6 | public class BaseException extends RuntimeException { 7 | 8 | public BaseException(String message) { 9 | super(message); 10 | } 11 | 12 | public BaseException(String message, Throwable cause) { 13 | super(message, cause); 14 | } 15 | 16 | public BaseException(Throwable cause) { 17 | super(cause); 18 | } 19 | 20 | protected BaseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { 21 | super(message, cause, enableSuppression, writableStackTrace); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/exception/RemoteCallException.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.exception; 2 | 3 | import com.akkafun.base.api.Error; 4 | 5 | /** 6 | * hystrix会忽略这个异常, 不会触发熔断 7 | * Created by liubin on 2016/5/3. 8 | */ 9 | public class RemoteCallException extends AppBusinessException { 10 | 11 | private Error originError; 12 | 13 | public RemoteCallException(Error error, int httpStatus) { 14 | super(error.getCode(), httpStatus, "调用远程服务异常, cause: " + error.getMessage()); 15 | this.originError = error; 16 | } 17 | 18 | public Error getOriginError() { 19 | return originError; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /apiutils/src/main/java/com/akkafun/base/exception/ServiceUnavailableException.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.base.exception; 2 | 3 | import com.akkafun.base.api.CommonErrorCode; 4 | import com.akkafun.base.api.ErrorCode; 5 | 6 | /** 7 | * Created by liubin on 2016/5/3. 8 | */ 9 | public class ServiceUnavailableException extends AppBusinessException { 10 | 11 | private static final ErrorCode ERROR_CODE = CommonErrorCode.SERVICE_UNAVAILABLE; 12 | 13 | public ServiceUnavailableException(String message) { 14 | super(ERROR_CODE.getCode(), ERROR_CODE.getStatus(), " 远程服务不可用: " + message); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/domain/AuditEntity.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.domain; 2 | 3 | import org.springframework.data.annotation.CreatedDate; 4 | import org.springframework.data.annotation.LastModifiedDate; 5 | import org.springframework.data.jpa.domain.support.AuditingEntityListener; 6 | 7 | import javax.persistence.Column; 8 | import javax.persistence.EntityListeners; 9 | import javax.persistence.MappedSuperclass; 10 | import java.time.LocalDateTime; 11 | 12 | /** 13 | * Created by liubin on 2016/3/28. 14 | */ 15 | @MappedSuperclass 16 | @EntityListeners(AuditingEntityListener.class) 17 | public abstract class AuditEntity { 18 | 19 | @CreatedDate 20 | @Column 21 | private LocalDateTime createTime; 22 | 23 | @LastModifiedDate 24 | @Column 25 | private LocalDateTime updateTime; 26 | 27 | public LocalDateTime getCreateTime() { 28 | return createTime; 29 | } 30 | 31 | public void setCreateTime(LocalDateTime createTime) { 32 | this.createTime = createTime; 33 | } 34 | 35 | public LocalDateTime getUpdateTime() { 36 | return updateTime; 37 | } 38 | 39 | public void setUpdateTime(LocalDateTime updateTime) { 40 | this.updateTime = updateTime; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/domain/LockableEntity.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.domain; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.MappedSuperclass; 5 | import javax.persistence.Version; 6 | 7 | /** 8 | * Created by liubin on 2016/3/28. 9 | */ 10 | @MappedSuperclass 11 | public abstract class LockableEntity { 12 | 13 | @Version 14 | @Column(name = "optlock", columnDefinition = "integer DEFAULT 0", nullable = false) 15 | private long version; 16 | 17 | public long getVersion() { 18 | return version; 19 | } 20 | 21 | public void setVersion(long version) { 22 | this.version = version; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/domain/VersionEntity.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.domain; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.MappedSuperclass; 5 | import javax.persistence.Version; 6 | 7 | /** 8 | * Created by liubin on 2016/3/28. 9 | */ 10 | @MappedSuperclass 11 | public abstract class VersionEntity extends AuditEntity { 12 | 13 | @Version 14 | @Column(name = "optlock", columnDefinition = "integer DEFAULT 0", nullable = false) 15 | private long version; 16 | 17 | public long getVersion() { 18 | return version; 19 | } 20 | 21 | public void setVersion(long version) { 22 | this.version = version; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/AskParameter.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event; 2 | 3 | import com.akkafun.base.event.domain.AskEvent; 4 | 5 | import java.time.LocalDateTime; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.Optional; 9 | 10 | /** 11 | * Created by liubin on 2016/6/6. 12 | */ 13 | public class AskParameter { 14 | 15 | private boolean united; 16 | 17 | private List askEvents; 18 | 19 | private Class callbackClass; 20 | 21 | private Map extraParams; 22 | 23 | private Optional timeoutTime; 24 | 25 | protected AskParameter(boolean united, List askEvents, 26 | Class callbackClass, Map extraParams, Optional timeoutTime) { 27 | this.united = united; 28 | this.askEvents = askEvents; 29 | this.callbackClass = callbackClass; 30 | this.extraParams = extraParams; 31 | this.timeoutTime = timeoutTime; 32 | } 33 | 34 | public boolean isUnited() { 35 | return united; 36 | } 37 | 38 | public List getAskEvents() { 39 | return askEvents; 40 | } 41 | 42 | public Class getCallbackClass() { 43 | return callbackClass; 44 | } 45 | 46 | public Map getExtraParams() { 47 | return extraParams; 48 | } 49 | 50 | public Optional getTimeoutTime() { 51 | return timeoutTime; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/config/InitBindProducer.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.config; 2 | 3 | import com.akkafun.base.event.constants.EventType; 4 | import com.akkafun.base.event.domain.AskResponseEvent; 5 | import com.akkafun.base.event.domain.RevokeAskEvent; 6 | import com.akkafun.common.event.EventRegistry; 7 | import org.springframework.beans.factory.InitializingBean; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.cloud.stream.binding.BinderAwareChannelResolver; 10 | 11 | import java.util.HashSet; 12 | import java.util.Set; 13 | 14 | /** 15 | * Created by liubin on 2016/6/28. 16 | */ 17 | public class InitBindProducer implements InitializingBean { 18 | 19 | @Autowired 20 | private BinderAwareChannelResolver binderAwareChannelResolver; 21 | 22 | private Set preInitializeProducers = new HashSet<>(); 23 | 24 | public InitBindProducer() { 25 | preInitializeProducers.add(AskResponseEvent.EVENT_TYPE); 26 | preInitializeProducers.add(RevokeAskEvent.EVENT_TYPE); 27 | } 28 | 29 | @Override 30 | public void afterPropertiesSet() throws Exception { 31 | preInitializeProducers.stream().forEach(x -> binderAwareChannelResolver.resolveDestination(x.name())); 32 | } 33 | 34 | public void addPreInitializeProducers(EventType eventType) { 35 | preInitializeProducers.add(eventType); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/constant/AskEventStatus.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.constant; 2 | 3 | /** 4 | * Created by liubin on 2016/6/3. 5 | */ 6 | public enum AskEventStatus { 7 | 8 | PENDING("请求中"), 9 | 10 | TIMEOUT("已超时"), 11 | 12 | FAILED("已失败"), 13 | 14 | SUCCESS("完成"), 15 | 16 | CANCELLED("已取消"); 17 | 18 | public String desc; 19 | 20 | AskEventStatus(String desc) { 21 | this.desc = desc; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/constant/EventCategory.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.constant; 2 | 3 | /** 4 | * Created by liubin on 2016/6/3. 5 | */ 6 | public enum EventCategory { 7 | 8 | NOTIFY("通知事件"), 9 | 10 | ASK("请求事件"), 11 | 12 | REVOKE("撤销事件"), 13 | 14 | ASKRESP("响应事件"); 15 | 16 | public String desc; 17 | 18 | EventCategory(String desc) { 19 | this.desc = desc; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/constant/ProcessStatus.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.constant; 2 | 3 | /** 4 | * Created by liubin on 2016/4/8. 5 | */ 6 | public enum ProcessStatus { 7 | 8 | NEW("未处理"), 9 | 10 | PROCESSED("已处理"), 11 | 12 | IGNORE("忽略"); 13 | 14 | public String desc; 15 | 16 | ProcessStatus(String desc) { 17 | this.desc = desc; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/AskRequestEventPublishRepository.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.event.domain.AskRequestEventPublish; 4 | 5 | /** 6 | * Created by liubin on 2016/3/29. 7 | */ 8 | public interface AskRequestEventPublishRepository extends 9 | EventPublishRepository, AskRequestEventPublishRepositoryCustom { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/AskRequestEventPublishRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.dao.AbstractRepository; 4 | 5 | /** 6 | * Created by liubin on 2016/3/29. 7 | */ 8 | public interface AskRequestEventPublishRepositoryCustom extends AbstractRepository{ 9 | 10 | } 11 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/AskRequestEventPublishRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import javax.persistence.EntityManager; 4 | import javax.persistence.PersistenceContext; 5 | 6 | /** 7 | * Created by liubin on 2016/3/29. 8 | */ 9 | public class AskRequestEventPublishRepositoryImpl implements AskRequestEventPublishRepositoryCustom { 10 | 11 | @PersistenceContext 12 | private EntityManager em; 13 | 14 | @Override 15 | public EntityManager getEm() { 16 | return em; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/AskResponseEventPublishRepository.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.event.domain.AskResponseEventPublish; 4 | 5 | /** 6 | * Created by liubin on 2016/3/29. 7 | */ 8 | public interface AskResponseEventPublishRepository extends 9 | EventPublishRepository, AskResponseEventPublishRepositoryCustom { 10 | 11 | Long countByAskEventId(Long askEventId); 12 | 13 | AskResponseEventPublish getByAskEventId(Long askEventId); 14 | } 15 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/AskResponseEventPublishRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.dao.AbstractRepository; 4 | 5 | /** 6 | * Created by liubin on 2016/3/29. 7 | */ 8 | public interface AskResponseEventPublishRepositoryCustom extends AbstractRepository{ 9 | 10 | } 11 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/AskResponseEventPublishRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import javax.persistence.EntityManager; 4 | import javax.persistence.PersistenceContext; 5 | 6 | /** 7 | * Created by liubin on 2016/3/29. 8 | */ 9 | public class AskResponseEventPublishRepositoryImpl implements AskResponseEventPublishRepositoryCustom { 10 | 11 | @PersistenceContext 12 | private EntityManager em; 13 | 14 | @Override 15 | public EntityManager getEm() { 16 | return em; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/EventProcessRepository.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.event.constant.ProcessStatus; 4 | import com.akkafun.common.event.domain.EventProcess; 5 | import org.springframework.data.repository.PagingAndSortingRepository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by liubin on 2016/3/29. 11 | */ 12 | public interface EventProcessRepository extends PagingAndSortingRepository, EventProcessRepositoryCustom{ 13 | 14 | List findByStatus(ProcessStatus status); 15 | 16 | EventProcess getByEventId(Long eventId); 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/EventProcessRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.dao.AbstractRepository; 4 | 5 | /** 6 | * Created by liubin on 2016/3/29. 7 | */ 8 | public interface EventProcessRepositoryCustom extends AbstractRepository{ 9 | 10 | } 11 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/EventProcessRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.event.constant.ProcessStatus; 4 | 5 | import javax.persistence.EntityManager; 6 | import javax.persistence.PersistenceContext; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | /** 11 | * Created by liubin on 2016/3/29. 12 | */ 13 | public class EventProcessRepositoryImpl implements EventProcessRepositoryCustom { 14 | 15 | @PersistenceContext 16 | private EntityManager em; 17 | 18 | @Override 19 | public EntityManager getEm() { 20 | return em; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/EventPublishRepository.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.event.constant.ProcessStatus; 4 | import com.akkafun.common.event.domain.EventPublish; 5 | import org.springframework.data.repository.NoRepositoryBean; 6 | import org.springframework.data.repository.PagingAndSortingRepository; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Created by liubin on 2016/3/29. 12 | */ 13 | @NoRepositoryBean 14 | public interface EventPublishRepository extends PagingAndSortingRepository{ 15 | 16 | List findByStatus(ProcessStatus status); 17 | 18 | T getByEventId(Long eventId); 19 | 20 | List findByEventIdIn(List eventIds); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/EventWatchProcessRepository.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.event.constant.ProcessStatus; 4 | import com.akkafun.common.event.domain.EventWatchProcess; 5 | import org.springframework.data.repository.PagingAndSortingRepository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by liubin on 2016/3/29. 11 | */ 12 | public interface EventWatchProcessRepository extends PagingAndSortingRepository, 13 | EventWatchProcessRepositoryCustom{ 14 | 15 | List findByStatus(ProcessStatus status); 16 | } 17 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/EventWatchProcessRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.dao.AbstractRepository; 4 | import com.akkafun.common.event.constant.ProcessStatus; 5 | 6 | /** 7 | * Created by liubin on 2016/3/29. 8 | */ 9 | public interface EventWatchProcessRepositoryCustom extends AbstractRepository{ 10 | 11 | int updateStatusBatch(Long[] ids, ProcessStatus status); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/EventWatchProcessRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.event.constant.ProcessStatus; 4 | import com.akkafun.common.utils.SQLUtils; 5 | 6 | import javax.persistence.EntityManager; 7 | import javax.persistence.PersistenceContext; 8 | import java.time.LocalDateTime; 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | /** 13 | * Created by liubin on 2016/3/29. 14 | */ 15 | public class EventWatchProcessRepositoryImpl implements EventWatchProcessRepositoryCustom { 16 | 17 | @PersistenceContext 18 | private EntityManager em; 19 | 20 | @Override 21 | public EntityManager getEm() { 22 | return em; 23 | } 24 | 25 | 26 | @Override 27 | public int updateStatusBatch(Long[] ids, ProcessStatus status) { 28 | 29 | return SQLUtils.updateByIdBatch(ids, (updateIds) -> { 30 | StringBuilder sql = new StringBuilder( 31 | String.format("update event_watch_process set status ='%s' where id in (", status.toString())); 32 | for (Long id : updateIds) { 33 | sql.append(id).append(","); 34 | } 35 | sql.replace(sql.length()-1, sql.length(), ")"); 36 | return getEm().createNativeQuery(sql.toString()).executeUpdate(); 37 | }); 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/EventWatchRepository.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.event.constant.AskEventStatus; 4 | import com.akkafun.common.event.domain.EventWatch; 5 | import org.springframework.data.repository.PagingAndSortingRepository; 6 | 7 | import java.time.LocalDateTime; 8 | import java.util.List; 9 | 10 | /** 11 | * Created by liubin on 2016/3/29. 12 | */ 13 | public interface EventWatchRepository extends PagingAndSortingRepository, EventWatchRepositoryCustom{ 14 | 15 | 16 | List findByAskEventStatusAndTimeoutTimeBefore(AskEventStatus askEventStatus, LocalDateTime timeoutTime); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/EventWatchRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.dao.AbstractRepository; 4 | 5 | /** 6 | * Created by liubin on 2016/6/6. 7 | */ 8 | public interface EventWatchRepositoryCustom extends AbstractRepository { 9 | } 10 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/EventWatchRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import javax.persistence.EntityManager; 4 | import javax.persistence.PersistenceContext; 5 | 6 | /** 7 | * Created by liubin on 2016/3/29. 8 | */ 9 | public class EventWatchRepositoryImpl implements EventWatchRepositoryCustom { 10 | 11 | @PersistenceContext 12 | private EntityManager em; 13 | 14 | @Override 15 | public EntityManager getEm() { 16 | return em; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/NotifyEventPublishRepository.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.event.domain.NotifyEventPublish; 4 | 5 | /** 6 | * Created by liubin on 2016/3/29. 7 | */ 8 | public interface NotifyEventPublishRepository extends 9 | EventPublishRepository, NotifyEventPublishRepositoryCustom { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/NotifyEventPublishRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.dao.AbstractRepository; 4 | 5 | /** 6 | * Created by liubin on 2016/3/29. 7 | */ 8 | public interface NotifyEventPublishRepositoryCustom extends AbstractRepository{ 9 | 10 | } 11 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/NotifyEventPublishRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import javax.persistence.EntityManager; 4 | import javax.persistence.PersistenceContext; 5 | 6 | /** 7 | * Created by liubin on 2016/3/29. 8 | */ 9 | public class NotifyEventPublishRepositoryImpl implements NotifyEventPublishRepositoryCustom { 10 | 11 | @PersistenceContext 12 | private EntityManager em; 13 | 14 | @Override 15 | public EntityManager getEm() { 16 | return em; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/RevokeAskEventPublishRepository.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.event.domain.RevokeAskEventPublish; 4 | 5 | /** 6 | * Created by liubin on 2016/3/29. 7 | */ 8 | public interface RevokeAskEventPublishRepository extends 9 | EventPublishRepository, RevokeAskEventPublishRepositoryCustom { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/RevokeAskEventPublishRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import com.akkafun.common.dao.AbstractRepository; 4 | 5 | /** 6 | * Created by liubin on 2016/3/29. 7 | */ 8 | public interface RevokeAskEventPublishRepositoryCustom extends AbstractRepository{ 9 | 10 | } 11 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/dao/RevokeAskEventPublishRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.dao; 2 | 3 | import javax.persistence.EntityManager; 4 | import javax.persistence.PersistenceContext; 5 | 6 | /** 7 | * Created by liubin on 2016/3/29. 8 | */ 9 | public class RevokeAskEventPublishRepositoryImpl implements RevokeAskEventPublishRepositoryCustom { 10 | 11 | @PersistenceContext 12 | private EntityManager em; 13 | 14 | @Override 15 | public EntityManager getEm() { 16 | return em; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/domain/AskRequestEventPublish.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.domain; 2 | 3 | import com.akkafun.common.event.constant.AskEventStatus; 4 | 5 | import javax.persistence.*; 6 | import java.time.LocalDateTime; 7 | 8 | /** 9 | * Created by liubin on 2016/3/28. 10 | */ 11 | @Entity 12 | @DiscriminatorValue("ASK") 13 | public class AskRequestEventPublish extends EventPublish { 14 | 15 | @Column 16 | @Enumerated(EnumType.STRING) 17 | private AskEventStatus askEventStatus; 18 | 19 | @Column 20 | private Long watchId; 21 | 22 | public AskEventStatus getAskEventStatus() { 23 | return askEventStatus; 24 | } 25 | 26 | public void setAskEventStatus(AskEventStatus askEventStatus) { 27 | this.askEventStatus = askEventStatus; 28 | } 29 | 30 | public Long getWatchId() { 31 | return watchId; 32 | } 33 | 34 | public void setWatchId(Long watchId) { 35 | this.watchId = watchId; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/domain/AskResponseEventPublish.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.domain; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.DiscriminatorValue; 5 | import javax.persistence.Entity; 6 | 7 | /** 8 | * Created by liubin on 2016/3/28. 9 | */ 10 | @Entity 11 | @DiscriminatorValue("ASKRESP") 12 | public class AskResponseEventPublish extends EventPublish { 13 | 14 | @Column 15 | private boolean success; 16 | 17 | @Column 18 | private Long askEventId; 19 | 20 | public boolean isSuccess() { 21 | return success; 22 | } 23 | 24 | public void setSuccess(boolean success) { 25 | this.success = success; 26 | } 27 | 28 | public Long getAskEventId() { 29 | return askEventId; 30 | } 31 | 32 | public void setAskEventId(Long askEventId) { 33 | this.askEventId = askEventId; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/domain/EventPublish.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.domain; 2 | 3 | import com.akkafun.base.event.constants.EventType; 4 | import com.akkafun.common.domain.VersionEntity; 5 | import com.akkafun.common.event.constant.ProcessStatus; 6 | 7 | import javax.persistence.*; 8 | 9 | /** 10 | * Created by liubin on 2016/3/28. 11 | */ 12 | @Entity 13 | @Inheritance(strategy=InheritanceType.SINGLE_TABLE) 14 | @DiscriminatorColumn(name="eventCategory") 15 | @Table(name = "event_publish") 16 | public abstract class EventPublish extends VersionEntity { 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.AUTO) 20 | private Long id; 21 | 22 | @Column 23 | private String payload; 24 | 25 | @Column 26 | @Enumerated(EnumType.STRING) 27 | private ProcessStatus status = ProcessStatus.NEW; 28 | 29 | @Column(unique = true) 30 | private Long eventId; 31 | 32 | @Column 33 | @Enumerated(EnumType.STRING) 34 | private EventType eventType; 35 | 36 | 37 | public Long getId() { 38 | return id; 39 | } 40 | 41 | public void setId(Long id) { 42 | this.id = id; 43 | } 44 | 45 | public String getPayload() { 46 | return payload; 47 | } 48 | 49 | public void setPayload(String payload) { 50 | this.payload = payload; 51 | } 52 | 53 | public ProcessStatus getStatus() { 54 | return status; 55 | } 56 | 57 | public void setStatus(ProcessStatus status) { 58 | this.status = status; 59 | } 60 | 61 | public Long getEventId() { 62 | return eventId; 63 | } 64 | 65 | public void setEventId(Long eventId) { 66 | this.eventId = eventId; 67 | } 68 | 69 | public EventType getEventType() { 70 | return eventType; 71 | } 72 | 73 | public void setEventType(EventType eventType) { 74 | this.eventType = eventType; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/domain/EventWatchProcess.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.domain; 2 | 3 | import com.akkafun.common.domain.AuditEntity; 4 | import com.akkafun.common.event.constant.ProcessStatus; 5 | 6 | import javax.persistence.*; 7 | 8 | /** 9 | * Created by liubin on 2016/3/28. 10 | */ 11 | @Entity 12 | @Table(name = "event_watch_process") 13 | public class EventWatchProcess extends AuditEntity { 14 | 15 | @Id 16 | @GeneratedValue(strategy = GenerationType.AUTO) 17 | private Long id; 18 | 19 | @Column 20 | private String failureInfo; 21 | 22 | @Column 23 | @Enumerated(EnumType.STRING) 24 | private ProcessStatus status = ProcessStatus.NEW; 25 | 26 | @Column 27 | private Long watchId; 28 | 29 | public Long getId() { 30 | return id; 31 | } 32 | 33 | public void setId(Long id) { 34 | this.id = id; 35 | } 36 | 37 | public String getFailureInfo() { 38 | return failureInfo; 39 | } 40 | 41 | public void setFailureInfo(String failureInfo) { 42 | this.failureInfo = failureInfo; 43 | } 44 | 45 | public ProcessStatus getStatus() { 46 | return status; 47 | } 48 | 49 | public void setStatus(ProcessStatus status) { 50 | this.status = status; 51 | } 52 | 53 | public Long getWatchId() { 54 | return watchId; 55 | } 56 | 57 | public void setWatchId(Long watchId) { 58 | this.watchId = watchId; 59 | } 60 | 61 | 62 | @Override 63 | public String toString() { 64 | return "EventWatchProcess{" + 65 | "watchId=" + watchId + 66 | ", status=" + status + 67 | ", failureInfo='" + failureInfo + '\'' + 68 | ", id=" + id + 69 | "} " + super.toString(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/domain/NotifyEventPublish.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.domain; 2 | 3 | import javax.persistence.DiscriminatorValue; 4 | import javax.persistence.Entity; 5 | 6 | /** 7 | * Created by liubin on 2016/3/28. 8 | */ 9 | @Entity 10 | @DiscriminatorValue("NOTIFY") 11 | public class NotifyEventPublish extends EventPublish { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/domain/RevokeAskEventPublish.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.domain; 2 | 3 | import javax.persistence.Column; 4 | import javax.persistence.DiscriminatorValue; 5 | import javax.persistence.Entity; 6 | 7 | /** 8 | * Created by liubin on 2016/3/28. 9 | */ 10 | @Entity 11 | @DiscriminatorValue("REVOKE") 12 | public class RevokeAskEventPublish extends EventPublish { 13 | 14 | @Column 15 | private Long askEventId; 16 | 17 | public Long getAskEventId() { 18 | return askEventId; 19 | } 20 | 21 | public void setAskEventId(Long askEventId) { 22 | this.askEventId = askEventId; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/handler/AskEventHandler.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.handler; 2 | 3 | import com.akkafun.base.api.BooleanWrapper; 4 | import com.akkafun.base.event.domain.AskEvent; 5 | 6 | /** 7 | * Created by liubin on 2016/6/3. 8 | */ 9 | public interface AskEventHandler { 10 | 11 | BooleanWrapper processRequest(E event); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/handler/NotifyEventHandler.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.handler; 2 | 3 | import com.akkafun.base.event.domain.NotifyEvent; 4 | 5 | /** 6 | * Created by liubin on 2016/6/3. 7 | */ 8 | public interface NotifyEventHandler { 9 | 10 | void notify(E event); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/handler/RevokableAskEventHandler.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.handler; 2 | 3 | import com.akkafun.base.event.constants.FailureInfo; 4 | import com.akkafun.base.event.domain.AskEvent; 5 | import com.akkafun.base.event.domain.Revokable; 6 | 7 | /** 8 | * Created by liubin on 2016/6/3. 9 | */ 10 | public interface RevokableAskEventHandler extends AskEventHandler { 11 | 12 | void processRevoke(E originEvent, FailureInfo failureInfo); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/scheduler/EventScheduler.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.scheduler; 2 | 3 | import com.akkafun.common.event.service.EventBus; 4 | import com.akkafun.common.event.service.EventWatchService; 5 | import org.springframework.scheduling.annotation.Scheduled; 6 | 7 | /** 8 | * Created by liubin on 2016/4/19. 9 | */ 10 | public class EventScheduler{ 11 | 12 | EventBus eventBus; 13 | 14 | public EventScheduler(EventBus eventBus) { 15 | this.eventBus = eventBus; 16 | } 17 | 18 | @Scheduled(fixedRate = 500L) 19 | public void sendUnpublishedEvent() { 20 | eventBus.sendUnpublishedEvent(); 21 | } 22 | 23 | @Scheduled(fixedRate = 500L) 24 | public void searchAndHandleUnprocessedEvent() { 25 | eventBus.searchAndHandleUnprocessedEvent(); 26 | } 27 | 28 | @Scheduled(fixedRate = 500L) 29 | public void handleUnprocessedEventWatchProcess() { 30 | eventBus.handleUnprocessedEventWatchProcess(); 31 | } 32 | 33 | @Scheduled(fixedRate = 1000L) 34 | public void handleTimeoutEventWatch() { 35 | eventBus.handleTimeoutEventWatch(); 36 | } 37 | 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/event/service/EventHandlerExecutor.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.service; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.stereotype.Service; 6 | import org.springframework.transaction.annotation.Propagation; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | import java.util.function.Supplier; 10 | 11 | /** 12 | * Created by liubin on 2016/6/30. 13 | */ 14 | @Service 15 | public class EventHandlerExecutor { 16 | 17 | private static Logger logger = LoggerFactory.getLogger(EventHandlerExecutor.class); 18 | 19 | 20 | /** 21 | * 执行handler处理 22 | * @param supplier 23 | */ 24 | @Transactional(propagation = Propagation.REQUIRES_NEW) 25 | public T executeEventHandler(Supplier supplier){ 26 | 27 | return supplier.get(); 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/exception/EventException.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.exception; 2 | 3 | import com.akkafun.base.exception.BaseException; 4 | 5 | /** 6 | * Created by liubin on 2016/4/14. 7 | */ 8 | public class EventException extends BaseException { 9 | 10 | public EventException(String message) { 11 | super(message); 12 | } 13 | 14 | public EventException(String message, Throwable cause) { 15 | super(message, cause); 16 | } 17 | 18 | public EventException(Throwable cause) { 19 | super(cause); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/scheduler/config/SchedulerConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.scheduler.config; 2 | 3 | import com.akkafun.common.event.scheduler.EventScheduler; 4 | import com.akkafun.common.event.service.EventBus; 5 | import com.akkafun.common.event.service.EventWatchService; 6 | import com.akkafun.common.scheduler.ZkCoordinateScheduledExecutor; 7 | import com.akkafun.common.scheduler.ZkSchedulerCoordinator; 8 | import com.akkafun.common.spring.ApplicationConstant; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.scheduling.TaskScheduler; 11 | import org.springframework.scheduling.annotation.EnableScheduling; 12 | import org.springframework.scheduling.annotation.SchedulingConfigurer; 13 | import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler; 14 | import org.springframework.scheduling.config.ScheduledTaskRegistrar; 15 | 16 | /** 17 | * Created by liubin on 2016/4/8. 18 | */ 19 | @EnableScheduling 20 | public class SchedulerConfiguration implements SchedulingConfigurer { 21 | 22 | 23 | @Bean 24 | public ZkSchedulerCoordinator zkSchedulerCoordinator(ApplicationConstant applicationConstant){ 25 | 26 | return new ZkSchedulerCoordinator(applicationConstant); 27 | 28 | } 29 | 30 | @Bean 31 | public EventScheduler eventScheduler(EventBus eventBus) { 32 | return new EventScheduler(eventBus); 33 | } 34 | 35 | 36 | @Override 37 | public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { 38 | 39 | TaskScheduler taskScheduler = new ConcurrentTaskScheduler(new ZkCoordinateScheduledExecutor(5)); 40 | taskRegistrar.setTaskScheduler(taskScheduler); 41 | 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/spring/ApplicationConstant.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.spring; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | 5 | /** 6 | * Created by liubin on 2016/4/20. 7 | */ 8 | public class ApplicationConstant { 9 | 10 | @Value("${spring.cloud.stream.kafka.binder.zkNodes:}") 11 | public String zkAddress; 12 | 13 | @Value("${spring.application.name}") 14 | public String applicationName; 15 | 16 | @Value("${spring.application.index}") 17 | public int applicationIndex; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/spring/ApplicationContextHolder.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.spring; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | 7 | /** 8 | * Created by liubin on 2016/4/14. 9 | */ 10 | public class ApplicationContextHolder implements ApplicationContextAware { 11 | 12 | public static ApplicationContext context; 13 | 14 | public static ApplicationConstant constant; 15 | 16 | public static final ApplicationContextHolder INSTANCE = new ApplicationContextHolder(); 17 | 18 | private ApplicationContextHolder(){} 19 | 20 | public static ApplicationContextHolder getInstance() { 21 | return INSTANCE; 22 | } 23 | 24 | @Override 25 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 26 | context = applicationContext; 27 | constant = applicationContext.getBean(ApplicationConstant.class); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/spring/BaseConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.spring; 2 | 3 | import com.akkafun.common.utils.JsonUtils; 4 | import com.akkafun.common.utils.spring.CustomRestTemplate; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import org.springframework.boot.orm.jpa.EntityScan; 7 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 8 | import org.springframework.cloud.netflix.hystrix.EnableHystrix; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.ComponentScan; 11 | import org.springframework.context.annotation.Primary; 12 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 13 | import org.springframework.data.jpa.repository.config.EnableJpaRepositories; 14 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 15 | import org.springframework.web.client.RestTemplate; 16 | 17 | /** 18 | * Created by liubin on 2016/3/28. 19 | */ 20 | @EntityScan(basePackages = { 21 | "com.akkafun.**.domain", 22 | "org.springframework.data.jpa.convert.threeten" 23 | }) 24 | @EnableJpaRepositories("com.akkafun.**.dao") 25 | @EnableJpaAuditing 26 | @EnableHystrix 27 | @ComponentScan({"com.akkafun.**.service", "com.akkafun.**.web"}) 28 | public class BaseConfiguration { 29 | 30 | @Bean 31 | public ApplicationConstant applicationConstant() { 32 | return new ApplicationConstant(); 33 | } 34 | 35 | @Bean 36 | public ApplicationContextHolder applicationContextHolder() { 37 | return ApplicationContextHolder.getInstance(); 38 | } 39 | 40 | //customize object mapper 41 | @Bean 42 | @Primary 43 | public ObjectMapper objectMapper() { 44 | return JsonUtils.OBJECT_MAPPER; 45 | } 46 | 47 | @LoadBalanced 48 | @Bean 49 | public RestTemplate restTemplate(MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter) { 50 | 51 | return CustomRestTemplate.assembleRestTemplate(mappingJackson2HttpMessageConverter); 52 | } 53 | 54 | @Bean 55 | public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { 56 | return new MappingJackson2HttpMessageConverter(objectMapper()); 57 | } 58 | 59 | 60 | } -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/spring/ServiceClientConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.spring; 2 | 3 | import com.netflix.appinfo.ApplicationInfoManager; 4 | import com.netflix.discovery.DiscoveryClient; 5 | import com.netflix.discovery.EurekaClient; 6 | import com.netflix.discovery.EurekaClientConfig; 7 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 8 | import org.springframework.cloud.netflix.eureka.CloudEurekaClient; 9 | import org.springframework.cloud.netflix.feign.EnableFeignClients; 10 | import org.springframework.context.ApplicationContext; 11 | import org.springframework.context.annotation.Bean; 12 | 13 | /** 14 | * Created by liubin on 2016/5/30. 15 | */ 16 | @EnableDiscoveryClient 17 | @EnableFeignClients("com.akkafun.**.service") 18 | public class ServiceClientConfiguration { 19 | 20 | @Bean(destroyMethod = "shutdown") 21 | @org.springframework.cloud.context.config.annotation.RefreshScope 22 | public EurekaClient eurekaClient(ApplicationInfoManager manager, 23 | EurekaClientConfig config, 24 | DiscoveryClient.DiscoveryClientOptionalArgs optionalArgs, 25 | ApplicationContext context) { 26 | manager.getInfo(); // force initialization 27 | return new CloudEurekaClient(manager, config, optionalArgs, context); 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/spring/WebApplication.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.spring; 2 | 3 | import com.akkafun.common.spring.mvc.AppErrorController; 4 | import com.akkafun.common.spring.mvc.AppExceptionHandlerController; 5 | import org.springframework.boot.autoconfigure.web.ErrorAttributes; 6 | import org.springframework.boot.autoconfigure.web.ErrorController; 7 | import org.springframework.boot.autoconfigure.web.ServerProperties; 8 | import org.springframework.context.annotation.Bean; 9 | import springfox.documentation.builders.PathSelectors; 10 | import springfox.documentation.spi.DocumentationType; 11 | import springfox.documentation.spring.web.plugins.Docket; 12 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 13 | 14 | import java.time.LocalDate; 15 | import java.time.LocalDateTime; 16 | 17 | /** 18 | * Created by liubin on 2016/3/28. 19 | */ 20 | @EnableSwagger2 21 | public class WebApplication { 22 | 23 | //error page 24 | @Bean 25 | public ErrorController errorController(ErrorAttributes errorAttributes, ServerProperties serverProperties) { 26 | return new AppErrorController(errorAttributes, serverProperties.getError()); 27 | } 28 | 29 | //exception handler 30 | @Bean 31 | public AppExceptionHandlerController appExceptionHandlerController() { 32 | return new AppExceptionHandlerController(); 33 | } 34 | 35 | @Bean 36 | public Docket api() { 37 | return new Docket(DocumentationType.SWAGGER_2) 38 | .directModelSubstitute(LocalDate.class, java.sql.Date.class) 39 | .directModelSubstitute(LocalDateTime.class, java.util.Date.class) 40 | .select() 41 | .apis(requestHandler -> { 42 | String packageName = requestHandler.getHandlerMethod().getMethod() 43 | .getDeclaringClass().getPackage().getName(); 44 | return packageName.startsWith("com.akkafun.") && packageName.contains(".web"); 45 | }) 46 | .paths(PathSelectors.any()) 47 | .build(); 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/spring/utils/InnerClassPathScanningCandidateComponentProvider.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.spring.utils; 2 | 3 | import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; 4 | import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; 5 | import org.springframework.core.env.Environment; 6 | 7 | /** 8 | * 内部类也能查询出来 9 | * Created by liubin on 2016/5/31. 10 | */ 11 | public class InnerClassPathScanningCandidateComponentProvider extends ClassPathScanningCandidateComponentProvider { 12 | 13 | public InnerClassPathScanningCandidateComponentProvider(boolean useDefaultFilters) { 14 | super(useDefaultFilters); 15 | } 16 | 17 | public InnerClassPathScanningCandidateComponentProvider(boolean useDefaultFilters, Environment environment) { 18 | super(useDefaultFilters, environment); 19 | } 20 | 21 | @Override 22 | protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { 23 | return beanDefinition.getMetadata().isConcrete(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/test/callbacks/AskTestEventFirstCallback.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.test.callbacks; 2 | 3 | import com.akkafun.common.test.domain.AskTestEvent; 4 | import com.google.common.collect.Lists; 5 | 6 | import java.util.List; 7 | import java.util.concurrent.CopyOnWriteArrayList; 8 | 9 | /** 10 | * Created by liubin on 2016/6/16. 11 | */ 12 | public class AskTestEventFirstCallback { 13 | 14 | public static final List successParams = new CopyOnWriteArrayList<>(); 15 | 16 | public void onSuccess(AskTestEvent event) { 17 | CallbackParam callbackParam = new CallbackParam(Lists.newArrayList(event), null, null); 18 | successParams.add(callbackParam); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/test/callbacks/AskTestEventSecondCallback.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.test.callbacks; 2 | 3 | import com.akkafun.base.event.constants.FailureInfo; 4 | import com.akkafun.common.test.domain.AskTestEvent; 5 | import com.google.common.collect.Lists; 6 | 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | import java.util.concurrent.CopyOnWriteArrayList; 11 | 12 | /** 13 | * Created by liubin on 2016/6/16. 14 | */ 15 | public class AskTestEventSecondCallback { 16 | 17 | public static final List successParams = new CopyOnWriteArrayList<>(); 18 | public static final List failureParams = new CopyOnWriteArrayList<>(); 19 | 20 | 21 | public void onSuccess(AskTestEvent event, String param1, String param2) { 22 | Map params = new HashMap<>(); 23 | params.put("param1", param1); 24 | params.put("param2", param2); 25 | CallbackParam callbackParam = new CallbackParam(Lists.newArrayList(event), null, params); 26 | successParams.add(callbackParam); 27 | } 28 | 29 | public void onFailure(AskTestEvent event, FailureInfo failureInfo, String param3, String param4) { 30 | Map params = new HashMap<>(); 31 | params.put("param3", param3); 32 | params.put("param4", param4); 33 | CallbackParam callbackParam = new CallbackParam(Lists.newArrayList(event), failureInfo, params); 34 | failureParams.add(callbackParam); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/test/callbacks/CallbackParam.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.test.callbacks; 2 | 3 | import com.akkafun.base.event.constants.FailureInfo; 4 | import com.akkafun.base.event.domain.AskEvent; 5 | 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | /** 11 | * Created by liubin on 2016/6/17. 12 | */ 13 | public class CallbackParam { 14 | 15 | private List askEvents; 16 | 17 | private FailureInfo failureInfo; 18 | 19 | private Map params; 20 | 21 | public CallbackParam(List askEvents, FailureInfo failureInfo, Map params) { 22 | this.askEvents = askEvents; 23 | this.failureInfo = failureInfo; 24 | this.params = params == null ? new HashMap<>() : params; 25 | } 26 | 27 | 28 | public List getAskEvents() { 29 | return askEvents; 30 | } 31 | 32 | public FailureInfo getFailureInfo() { 33 | return failureInfo; 34 | } 35 | 36 | public Map getParams() { 37 | return params; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/test/callbacks/UnitedTestEventCallback.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.test.callbacks; 2 | 3 | import com.akkafun.base.event.constants.FailureInfo; 4 | import com.akkafun.common.test.domain.AskTestEvent; 5 | import com.akkafun.common.test.domain.RevokableAskTestEvent; 6 | import com.google.common.collect.Lists; 7 | 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.concurrent.CopyOnWriteArrayList; 12 | 13 | /** 14 | * Created by liubin on 2016/6/16. 15 | */ 16 | public class UnitedTestEventCallback { 17 | 18 | public static final String SUCCESS_EVENT_NAME = "克尔苏加德"; 19 | 20 | public static final List successParams = new CopyOnWriteArrayList<>(); 21 | public static final List failureParams = new CopyOnWriteArrayList<>(); 22 | 23 | 24 | public void onSuccess(AskTestEvent askTestEvent, RevokableAskTestEvent revokableAskTestEvent, 25 | String param1, String param2) { 26 | Map params = new HashMap<>(); 27 | params.put("param1", param1); 28 | params.put("param2", param2); 29 | CallbackParam callbackParam = new CallbackParam(Lists.newArrayList(askTestEvent, revokableAskTestEvent), 30 | null, params); 31 | successParams.add(callbackParam); 32 | } 33 | 34 | public void onFailure(AskTestEvent askTestEvent, RevokableAskTestEvent revokableAskTestEvent, 35 | FailureInfo failureInfo, String param3, String param4) { 36 | Map params = new HashMap<>(); 37 | params.put("param3", param3); 38 | params.put("param4", param4); 39 | CallbackParam callbackParam = new CallbackParam(Lists.newArrayList(askTestEvent, revokableAskTestEvent), 40 | failureInfo, params); 41 | failureParams.add(callbackParam); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/test/domain/AskTestEvent.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.test.domain; 2 | 3 | import com.akkafun.base.event.constants.EventType; 4 | import com.akkafun.base.event.domain.AskEvent; 5 | import com.fasterxml.jackson.annotation.JsonCreator; 6 | import com.fasterxml.jackson.annotation.JsonProperty; 7 | 8 | public class AskTestEvent extends AskEvent { 9 | 10 | public static final EventType EVENT_TYPE = EventType.ASK_TEST_EVENT; 11 | 12 | @Override 13 | public EventType getType() { 14 | return EVENT_TYPE; 15 | } 16 | 17 | private String name; 18 | 19 | @JsonCreator 20 | public AskTestEvent( 21 | @JsonProperty("name") String name){ 22 | this.name = name; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return "AskTestEvent{" + 32 | "name='" + name + '\'' + 33 | "} " + super.toString(); 34 | } 35 | } -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/test/domain/NotifyFirstTestEvent.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.test.domain; 2 | 3 | import com.akkafun.base.event.constants.EventType; 4 | import com.akkafun.base.event.domain.NotifyEvent; 5 | import com.fasterxml.jackson.annotation.JsonCreator; 6 | import com.fasterxml.jackson.annotation.JsonProperty; 7 | 8 | import java.time.LocalDateTime; 9 | 10 | public class NotifyFirstTestEvent extends NotifyEvent { 11 | 12 | public static final EventType EVENT_TYPE = EventType.NOTIFY_FIRST_TEST_EVENT; 13 | 14 | @Override 15 | public EventType getType() { 16 | return EVENT_TYPE; 17 | } 18 | 19 | private String name; 20 | 21 | private LocalDateTime registerTime; 22 | 23 | @JsonCreator 24 | public NotifyFirstTestEvent( 25 | @JsonProperty("name") String name, 26 | @JsonProperty("registerTime") LocalDateTime registerTime) { 27 | this.name = name; 28 | this.registerTime = registerTime; 29 | } 30 | 31 | public String getName() { 32 | return name; 33 | } 34 | 35 | public LocalDateTime getRegisterTime() { 36 | return registerTime; 37 | } 38 | 39 | @Override 40 | public String toString() { 41 | return "NotifyFirstTestEvent{" + 42 | "name='" + name + '\'' + 43 | ", registerTime=" + registerTime + 44 | "} " + super.toString(); 45 | } 46 | } -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/test/domain/NotifySecondTestEvent.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.test.domain; 2 | 3 | import com.akkafun.base.event.constants.EventType; 4 | import com.akkafun.base.event.domain.NotifyEvent; 5 | import com.fasterxml.jackson.annotation.JsonCreator; 6 | import com.fasterxml.jackson.annotation.JsonProperty; 7 | 8 | public class NotifySecondTestEvent extends NotifyEvent { 9 | 10 | public static final EventType EVENT_TYPE = EventType.NOTIFY_SECOND_TEST_EVENT; 11 | 12 | @Override 13 | public EventType getType() { 14 | return EVENT_TYPE; 15 | } 16 | 17 | private String name; 18 | 19 | @JsonCreator 20 | public NotifySecondTestEvent( 21 | @JsonProperty("name") String name) { 22 | this.name = name; 23 | } 24 | 25 | public String getName() { 26 | return name; 27 | } 28 | 29 | @Override 30 | public String toString() { 31 | return "NotifySecondTestEvent{" + 32 | "name='" + name + '\'' + 33 | "} " + super.toString(); 34 | } 35 | } -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/test/domain/RevokableAskTestEvent.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.test.domain; 2 | 3 | import com.akkafun.base.event.constants.EventType; 4 | import com.akkafun.base.event.domain.AskEvent; 5 | import com.akkafun.base.event.domain.Revokable; 6 | import com.fasterxml.jackson.annotation.JsonCreator; 7 | import com.fasterxml.jackson.annotation.JsonProperty; 8 | 9 | public class RevokableAskTestEvent extends AskEvent implements Revokable { 10 | 11 | public static final EventType EVENT_TYPE = EventType.REVOKABLE_ASK_TEST_EVENT; 12 | 13 | @Override 14 | public EventType getType() { 15 | return EVENT_TYPE; 16 | } 17 | 18 | private String name; 19 | 20 | @JsonCreator 21 | public RevokableAskTestEvent( 22 | @JsonProperty("name") String name){ 23 | this.name = name; 24 | } 25 | 26 | public String getName() { 27 | return name; 28 | } 29 | 30 | @Override 31 | public String toString() { 32 | return "RevokableAskTestEvent{" + 33 | "name='" + name + '\'' + 34 | "} " + super.toString(); 35 | } 36 | } -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/test/handlers/AskTestEventHandler.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.test.handlers; 2 | 3 | import com.akkafun.base.api.BooleanWrapper; 4 | import com.akkafun.common.event.handler.AskEventHandler; 5 | import com.akkafun.common.test.domain.AskTestEvent; 6 | 7 | import java.util.List; 8 | import java.util.concurrent.CopyOnWriteArrayList; 9 | 10 | /** 11 | * Created by liubin on 2016/6/15. 12 | */ 13 | public class AskTestEventHandler implements AskEventHandler { 14 | 15 | public static final String SUCCESS_EVENT_NAME = "克尔苏加德"; 16 | 17 | public static final List events = new CopyOnWriteArrayList<>(); 18 | 19 | @Override 20 | public BooleanWrapper processRequest(AskTestEvent event) { 21 | events.add(event); 22 | return new BooleanWrapper(event.getName().equals(SUCCESS_EVENT_NAME)); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/test/handlers/NotifyFirstTestEventFirstHandler.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.test.handlers; 2 | 3 | import com.akkafun.common.event.handler.NotifyEventHandler; 4 | import com.akkafun.common.test.domain.NotifyFirstTestEvent; 5 | 6 | import java.util.List; 7 | import java.util.concurrent.CopyOnWriteArrayList; 8 | 9 | /** 10 | * Created by liubin on 2016/6/15. 11 | */ 12 | public class NotifyFirstTestEventFirstHandler implements NotifyEventHandler { 13 | 14 | public static final List events = new CopyOnWriteArrayList<>(); 15 | 16 | @Override 17 | public void notify(NotifyFirstTestEvent event) { 18 | events.add(event); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/test/handlers/NotifyFirstTestEventSecondHandler.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.test.handlers; 2 | 3 | import com.akkafun.common.event.handler.NotifyEventHandler; 4 | import com.akkafun.common.test.domain.NotifyFirstTestEvent; 5 | 6 | import java.util.List; 7 | import java.util.concurrent.CopyOnWriteArrayList; 8 | 9 | /** 10 | * Created by liubin on 2016/6/15. 11 | */ 12 | public class NotifyFirstTestEventSecondHandler implements NotifyEventHandler { 13 | 14 | public static final List events = new CopyOnWriteArrayList<>(); 15 | 16 | @Override 17 | public void notify(NotifyFirstTestEvent event) { 18 | events.add(event); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/test/handlers/NotifySecondTestEventHandler.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.test.handlers; 2 | 3 | import com.akkafun.common.event.handler.NotifyEventHandler; 4 | import com.akkafun.common.test.domain.NotifySecondTestEvent; 5 | 6 | /** 7 | * Created by liubin on 2016/6/15. 8 | */ 9 | public class NotifySecondTestEventHandler implements NotifyEventHandler { 10 | 11 | @Override 12 | public void notify(NotifySecondTestEvent event) { 13 | 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /common/src/main/java/com/akkafun/common/test/handlers/RevokableAskTestEventHandler.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.test.handlers; 2 | 3 | import com.akkafun.base.api.BooleanWrapper; 4 | import com.akkafun.base.event.constants.FailureInfo; 5 | import com.akkafun.common.event.handler.RevokableAskEventHandler; 6 | import com.akkafun.common.test.domain.RevokableAskTestEvent; 7 | 8 | import java.util.List; 9 | import java.util.concurrent.CopyOnWriteArrayList; 10 | 11 | /** 12 | * Created by liubin on 2016/6/15. 13 | */ 14 | public class RevokableAskTestEventHandler implements RevokableAskEventHandler { 15 | 16 | 17 | public static final String SUCCESS_EVENT_NAME = "克尔苏加德"; 18 | 19 | public static final List events = new CopyOnWriteArrayList<>(); 20 | public static final List revokeEvents = new CopyOnWriteArrayList<>(); 21 | 22 | 23 | @Override 24 | public void processRevoke(RevokableAskTestEvent originEvent, FailureInfo failureInfo) { 25 | revokeEvents.add(originEvent); 26 | } 27 | 28 | @Override 29 | public BooleanWrapper processRequest(RevokableAskTestEvent event) { 30 | events.add(event); 31 | return new BooleanWrapper(event.getName().equals(SUCCESS_EVENT_NAME)); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /common/src/test/java/com/akkafun/common/event/EventTestUtils.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event; 2 | 3 | import com.akkafun.common.test.callbacks.AskTestEventFirstCallback; 4 | import com.akkafun.common.test.callbacks.AskTestEventSecondCallback; 5 | import com.akkafun.common.test.callbacks.UnitedTestEventCallback; 6 | import com.akkafun.common.test.handlers.AskTestEventHandler; 7 | import com.akkafun.common.test.handlers.NotifyFirstTestEventFirstHandler; 8 | import com.akkafun.common.test.handlers.NotifyFirstTestEventSecondHandler; 9 | import com.akkafun.common.test.handlers.RevokableAskTestEventHandler; 10 | 11 | /** 12 | * Created by liubin on 2016/6/17. 13 | */ 14 | public class EventTestUtils { 15 | 16 | public static void clear() { 17 | AskTestEventFirstCallback.successParams.clear(); 18 | AskTestEventSecondCallback.successParams.clear(); 19 | AskTestEventSecondCallback.failureParams.clear(); 20 | UnitedTestEventCallback.successParams.clear(); 21 | UnitedTestEventCallback.failureParams.clear(); 22 | AskTestEventHandler.events.clear(); 23 | NotifyFirstTestEventFirstHandler.events.clear(); 24 | NotifyFirstTestEventSecondHandler.events.clear(); 25 | RevokableAskTestEventHandler.events.clear(); 26 | RevokableAskTestEventHandler.revokeEvents.clear(); 27 | 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /common/src/test/java/com/akkafun/common/event/EventUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event; 2 | 3 | import com.akkafun.common.test.domain.NotifyFirstTestEvent; 4 | import org.junit.Test; 5 | 6 | import java.time.LocalDateTime; 7 | 8 | import static org.hamcrest.Matchers.is; 9 | import static org.junit.Assert.assertThat; 10 | 11 | 12 | /** 13 | * Created by liubin on 2016/4/11. 14 | */ 15 | public class EventUtilsTest { 16 | 17 | 18 | @Test 19 | public void testSerialize() { 20 | 21 | NotifyFirstTestEvent testEventFirst = new NotifyFirstTestEvent("张三", LocalDateTime.now()); 22 | 23 | String json = EventUtils.serializeEvent(testEventFirst); 24 | 25 | NotifyFirstTestEvent testEventFirstFromJson = EventUtils.deserializeEvent(json, NotifyFirstTestEvent.class); 26 | 27 | assertThat(testEventFirstFromJson, is(testEventFirst)); 28 | 29 | 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /common/src/test/java/com/akkafun/common/test/BaseControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.test; 2 | 3 | import com.akkafun.common.spring.WebApplication; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.boot.test.SpringApplicationConfiguration; 6 | import org.springframework.boot.test.WebIntegrationTest; 7 | import org.springframework.http.HttpEntity; 8 | import org.springframework.http.HttpHeaders; 9 | import org.springframework.http.MediaType; 10 | 11 | /** 12 | * Created by liubin on 2016/3/30. 13 | */ 14 | @WebIntegrationTest(randomPort = true) 15 | @SpringApplicationConfiguration(classes = WebApplication.class) 16 | public abstract class BaseControllerTest extends BaseTest { 17 | 18 | @Value("${local.server.port}") 19 | protected int serverPort; 20 | 21 | protected String localServerUrl(){ 22 | return String.format("http://localhost:%d", serverPort); 23 | } 24 | 25 | protected String buildRequestUrl(String url) { 26 | return String.format("%s/%s", localServerUrl(), url); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /common/src/test/java/com/akkafun/common/test/BaseTest.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.test; 2 | 3 | import com.akkafun.common.event.service.EventBus; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 7 | 8 | /** 9 | * Created by liubin on 2016/3/29. 10 | */ 11 | @RunWith(SpringJUnit4ClassRunner.class) 12 | public abstract class BaseTest { 13 | 14 | @Autowired 15 | protected EventBus eventBus; 16 | 17 | /** 18 | * 发送事件并等待 19 | */ 20 | protected void sendEvent() { 21 | 22 | eventBus.sendUnpublishedEvent(); 23 | try { 24 | Thread.sleep(3000L); 25 | } catch (InterruptedException e) { 26 | throw new RuntimeException(e); 27 | } 28 | 29 | } 30 | 31 | /** 32 | * 异步处理事件并等待 33 | */ 34 | protected void handleEvent() { 35 | 36 | try { 37 | eventBus.searchAndHandleUnprocessedEvent(); 38 | Thread.sleep(3000L); 39 | eventBus.handleUnprocessedEventWatchProcess(); 40 | Thread.sleep(3000L); 41 | } catch (InterruptedException e) { 42 | throw new RuntimeException(e); 43 | } 44 | 45 | } 46 | 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /config/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | config 6 | jar 7 | 8 | 9 | com.akkafun.mysteam 10 | base 11 | 1.0-SNAPSHOT 12 | 13 | 14 | 15 | com.akkafun.config.ConfigApplication 16 | 17 | 18 | 19 | 20 | org.springframework.cloud 21 | spring-cloud-config-server 22 | 23 | 24 | org.springframework.cloud 25 | spring-cloud-config-monitor 26 | 27 | 28 | org.springframework.cloud 29 | spring-cloud-starter-eureka 30 | 31 | 32 | org.springframework.cloud 33 | spring-cloud-starter-stream-kafka 34 | 35 | 36 | 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-maven-plugin 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /config/src/main/java/com/akkafun/config/ConfigApplication.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.config; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.cloud.config.server.EnableConfigServer; 7 | 8 | @SpringBootApplication 9 | @EnableDiscoveryClient 10 | @EnableConfigServer 11 | public class ConfigApplication { 12 | 13 | /** 14 | * Run the application using Spring Boot and an embedded servlet engine. 15 | * 16 | * @param args 17 | * Program arguments - ignored. 18 | */ 19 | public static void main(String[] args) { 20 | SpringApplication.run(ConfigApplication.class, args); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /config/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8888 3 | 4 | spring: 5 | application: 6 | name: config 7 | 8 | cloud: 9 | config: 10 | server: 11 | git: 12 | uri: https://github.com/sunnykaka/mysteam-config-repo 13 | # uri: file:///D:/opensource/workspace/mysteam-config-repo 14 | basedir: target/config 15 | searchPaths: "*" 16 | 17 | stream: 18 | instanceCount: 1 19 | instanceIndex: 0 20 | kafka: 21 | binder: 22 | brokers: 192.168.239.129:9092,192.168.239.129:9093,192.168.239.129:9094 23 | zkNodes: 192.168.239.129:2181 24 | offsetUpdateTimeWindow: 10000 25 | #offsetUpdateCount: 0 26 | requiredAcks: 1 27 | minPartitionCount: 1 28 | replicationFactor: 1 29 | 30 | bindings: 31 | input: 32 | consumer: 33 | autoCommitOffset: true 34 | startOffset: earliest 35 | headerMode: raw 36 | output: 37 | producer: 38 | bufferSize: 16384 39 | sync: true 40 | batchTimeout: 0 41 | 42 | 43 | management: 44 | context-path: /admin 45 | 46 | logging: 47 | level: 48 | com.netflix.discovery: 'OFF' 49 | org.springframework.cloud: 'DEBUG' 50 | 51 | eureka: 52 | instance: 53 | preferIpAddress: true 54 | leaseRenewalIntervalInSeconds: 10 55 | statusPageUrlPath: /admin/info 56 | healthCheckUrlPath: /admin/health 57 | 58 | client: 59 | serviceUrl: 60 | defaultZone: http://localhost:1111/eureka/ 61 | -------------------------------------------------------------------------------- /coupon/api/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | coupon-service-api 6 | jar 7 | 8 | 9 | com.akkafun.mysteam 10 | coupon-service 11 | 1.0-SNAPSHOT 12 | 13 | 14 | 15 | 16 | 17 | 18 | com.akkafun.mysteam 19 | apiutils 20 | ${project.version} 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /coupon/api/src/main/java/com/akkafun/coupon/api/CouponUrl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.coupon.api; 2 | 3 | /** 4 | * Created by liubin on 2016/5/6. 5 | */ 6 | public interface CouponUrl { 7 | 8 | String SERVICE_NAME = "COUPON"; 9 | 10 | String SERVICE_HOSTNAME = "http://COUPON"; 11 | 12 | String CHECK_VALID_URL = "/coupons/{couponId}/valid"; 13 | 14 | String COUPON_LIST_URL = "/coupons"; 15 | 16 | String USER_COUPON_LIST_URL = "/coupons/{userId}"; 17 | 18 | static String buildUrl(String url) { 19 | return SERVICE_HOSTNAME + url; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /coupon/api/src/main/java/com/akkafun/coupon/api/constants/CouponState.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.coupon.api.constants; 2 | 3 | /** 4 | * Created by liubin on 2016/4/26. 5 | */ 6 | public enum CouponState { 7 | 8 | VALID("有效"), 9 | 10 | USED("已使用"), 11 | 12 | INVALID("已失效"); 13 | 14 | public String desc; 15 | 16 | CouponState(String desc) { 17 | this.desc = desc; 18 | } 19 | 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /coupon/api/src/main/java/com/akkafun/coupon/api/events/AskUseCoupon.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.coupon.api.events; 2 | 3 | import com.akkafun.base.event.constants.EventType; 4 | import com.akkafun.base.event.domain.AskEvent; 5 | import com.akkafun.base.event.domain.Revokable; 6 | import com.fasterxml.jackson.annotation.JsonCreator; 7 | import com.fasterxml.jackson.annotation.JsonProperty; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Created by liubin on 2016/4/8. 13 | */ 14 | public class AskUseCoupon extends AskEvent implements Revokable { 15 | 16 | public static final EventType EVENT_TYPE = EventType.ASK_USE_COUPON; 17 | 18 | @Override 19 | public EventType getType() { 20 | return EVENT_TYPE; 21 | } 22 | 23 | private List couponIds; 24 | 25 | private Long userId; 26 | 27 | private Long orderId; 28 | 29 | @JsonCreator 30 | public AskUseCoupon( 31 | @JsonProperty("couponIds") List couponIds, 32 | @JsonProperty("userId") Long userId, 33 | @JsonProperty("orderId") Long orderId) { 34 | this.couponIds = couponIds; 35 | this.userId = userId; 36 | this.orderId = orderId; 37 | } 38 | 39 | public List getCouponIds() { 40 | return couponIds; 41 | } 42 | 43 | public Long getUserId() { 44 | return userId; 45 | } 46 | 47 | public Long getOrderId() { 48 | return orderId; 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | return "AskUseCoupon{" + 54 | "couponIds=" + couponIds + 55 | ", userId=" + userId + 56 | ", orderId=" + orderId + 57 | "} " + super.toString(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /coupon/core/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | coupon-service-core 6 | jar 7 | 8 | 9 | com.akkafun.mysteam 10 | coupon-service 11 | 1.0-SNAPSHOT 12 | 13 | 14 | 15 | 16 | com.akkafun.coupon.context.CouponApplication 17 | 18 | 19 | 20 | 21 | 22 | mysql 23 | mysql-connector-java 24 | runtime 25 | 26 | 27 | 28 | com.akkafun.mysteam 29 | common 30 | ${project.version} 31 | 32 | 33 | 34 | com.akkafun.mysteam 35 | common 36 | ${project.version} 37 | test-jar 38 | test 39 | 40 | 41 | 42 | com.akkafun.mysteam 43 | user-service-api 44 | ${project.version} 45 | 46 | 47 | 48 | com.akkafun.mysteam 49 | coupon-service-api 50 | ${project.version} 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | org.springframework.boot 61 | spring-boot-maven-plugin 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /coupon/core/src/main/java/com/akkafun/coupon/context/CouponApplication.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.coupon.context; 2 | 3 | import com.akkafun.common.event.config.EventConfiguration; 4 | import com.akkafun.common.scheduler.config.SchedulerConfiguration; 5 | import com.akkafun.common.spring.BaseConfiguration; 6 | import com.akkafun.common.spring.ServiceClientConfiguration; 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.context.annotation.Import; 10 | 11 | /** 12 | * Created by liubin on 2016/3/28. 13 | */ 14 | @SpringBootApplication 15 | @Import({BaseConfiguration.class, EventConfiguration.class, SchedulerConfiguration.class, ServiceClientConfiguration.class}) 16 | public class CouponApplication { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(CouponApplication.class, args); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /coupon/core/src/main/java/com/akkafun/coupon/dao/CouponRepository.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.coupon.dao; 2 | 3 | import com.akkafun.coupon.domain.Coupon; 4 | import org.springframework.data.repository.PagingAndSortingRepository; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created by liubin on 2016/4/26. 10 | */ 11 | public interface CouponRepository extends PagingAndSortingRepository, CouponRepositoryCustom { 12 | 13 | List findByUserId(Long userId); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /coupon/core/src/main/java/com/akkafun/coupon/dao/CouponRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.coupon.dao; 2 | 3 | import com.akkafun.common.dao.AbstractRepository; 4 | 5 | /** 6 | * Created by liubin on 2016/4/26. 7 | */ 8 | public interface CouponRepositoryCustom extends AbstractRepository { 9 | } 10 | -------------------------------------------------------------------------------- /coupon/core/src/main/java/com/akkafun/coupon/dao/CouponRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.coupon.dao; 2 | 3 | import javax.persistence.EntityManager; 4 | import javax.persistence.PersistenceContext; 5 | 6 | /** 7 | * Created by liubin on 2016/4/26. 8 | */ 9 | public class CouponRepositoryImpl implements CouponRepositoryCustom { 10 | 11 | @PersistenceContext 12 | private EntityManager em; 13 | 14 | 15 | @Override 16 | public EntityManager getEm() { 17 | return em; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /coupon/core/src/main/java/com/akkafun/coupon/domain/Coupon.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.coupon.domain; 2 | 3 | import com.akkafun.common.domain.VersionEntity; 4 | import com.akkafun.coupon.api.constants.CouponState; 5 | 6 | import javax.persistence.*; 7 | import java.time.LocalDateTime; 8 | 9 | /** 10 | * Created by liubin on 2016/3/28. 11 | */ 12 | @Entity 13 | @Table(name = "coupon") 14 | public class Coupon extends VersionEntity { 15 | 16 | @Id 17 | @GeneratedValue(strategy = GenerationType.AUTO) 18 | private Long id; 19 | 20 | @Column 21 | private Long amount; 22 | 23 | @Column 24 | private Long userId; 25 | 26 | @Column 27 | @Enumerated(value = EnumType.STRING) 28 | private CouponState state; 29 | 30 | @Column 31 | private Long orderId; 32 | 33 | @Column 34 | private LocalDateTime useTime; 35 | 36 | @Column 37 | private String code; 38 | 39 | public Long getId() { 40 | return id; 41 | } 42 | 43 | public void setId(Long id) { 44 | this.id = id; 45 | } 46 | 47 | public Long getAmount() { 48 | return amount; 49 | } 50 | 51 | public void setAmount(Long amount) { 52 | this.amount = amount; 53 | } 54 | 55 | public Long getUserId() { 56 | return userId; 57 | } 58 | 59 | public void setUserId(Long userId) { 60 | this.userId = userId; 61 | } 62 | 63 | public CouponState getState() { 64 | return state; 65 | } 66 | 67 | public void setState(CouponState state) { 68 | this.state = state; 69 | } 70 | 71 | public Long getOrderId() { 72 | return orderId; 73 | } 74 | 75 | public void setOrderId(Long orderId) { 76 | this.orderId = orderId; 77 | } 78 | 79 | public LocalDateTime getUseTime() { 80 | return useTime; 81 | } 82 | 83 | public void setUseTime(LocalDateTime useTime) { 84 | this.useTime = useTime; 85 | } 86 | 87 | public String getCode() { 88 | return code; 89 | } 90 | 91 | public void setCode(String code) { 92 | this.code = code; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /coupon/core/src/main/java/com/akkafun/coupon/handler/AskUseCouponHandler.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.coupon.handler; 2 | 3 | import com.akkafun.base.api.BooleanWrapper; 4 | import com.akkafun.base.event.constants.FailureInfo; 5 | import com.akkafun.base.exception.AppBusinessException; 6 | import com.akkafun.common.event.handler.RevokableAskEventHandler; 7 | import com.akkafun.common.spring.ApplicationContextHolder; 8 | import com.akkafun.coupon.api.events.AskUseCoupon; 9 | import com.akkafun.coupon.service.CouponService; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | /** 14 | * Created by liubin on 2016/6/24. 15 | */ 16 | public class AskUseCouponHandler implements RevokableAskEventHandler { 17 | 18 | private static Logger logger = LoggerFactory.getLogger(AskUseCouponHandler.class); 19 | 20 | 21 | @Override 22 | public void processRevoke(AskUseCoupon originEvent, FailureInfo failureInfo) { 23 | logger.debug("AskUseCouponHandler processRevoke, receive AskUseCoupon: " + originEvent); 24 | 25 | CouponService couponService = ApplicationContextHolder.context.getBean(CouponService.class); 26 | couponService.revokeUse(originEvent.getCouponIds(), originEvent.getUserId(), originEvent.getOrderId()); 27 | } 28 | 29 | @Override 30 | public BooleanWrapper processRequest(AskUseCoupon event) { 31 | logger.debug("AskUseCouponHandler processRequest, receive AskUseCoupon: " + event); 32 | 33 | if(event.getCouponIds() == null || event.getCouponIds().isEmpty() 34 | || event.getUserId() == null || event.getOrderId() == null) { 35 | return new BooleanWrapper(false, "couponId or userId or orderId is null"); 36 | } 37 | 38 | CouponService couponService = ApplicationContextHolder.context.getBean(CouponService.class); 39 | couponService.useCoupon(event.getCouponIds(), event.getUserId(), event.getOrderId()); 40 | return new BooleanWrapper(true); 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /coupon/core/src/main/java/com/akkafun/coupon/handler/UserCreatedHandler.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.coupon.handler; 2 | 3 | import com.akkafun.common.event.handler.NotifyEventHandler; 4 | import com.akkafun.common.spring.ApplicationContextHolder; 5 | import com.akkafun.coupon.service.CouponService; 6 | import com.akkafun.user.api.events.UserCreated; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | /** 11 | * Created by liubin on 2016/4/14. 12 | */ 13 | public class UserCreatedHandler implements NotifyEventHandler { 14 | 15 | protected Logger logger = LoggerFactory.getLogger(UserCreatedHandler.class); 16 | 17 | 18 | @Override 19 | public void notify(UserCreated event) { 20 | CouponService couponService = ApplicationContextHolder.context.getBean(CouponService.class); 21 | couponService.initCoupon(event.getUserId()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /coupon/core/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: coupon 4 | cloud: 5 | config: 6 | uri: ${CONFIG_SERVER_URI:http://localhost:8888} 7 | failFast: true 8 | encrypt: 9 | failOnError: true 10 | -------------------------------------------------------------------------------- /coupon/core/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | logs/coupon-service.log 15 | 16 | 17 | logs/coupon-service-log-%d{yyyy-MM-dd}.gz 18 | 19 | 30 20 | 21 | 22 | %date{yyyy-MM-dd HH:mm:ss} ${PID}: %-5level %logger{0} - %msg%n 23 | 24 | 25 | 26 | 27 | 28 | %date{yyyy-MM-dd HH:mm:ss} ${PID}: %-5level %logger{0} - %msg%n 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /coupon/docs/coupon-service.sql: -------------------------------------------------------------------------------- 1 | /*==============================================================*/ 2 | /* DBMS name: MySQL 5.0 */ 3 | /* Created on: 2016/4/29 15:24:21 */ 4 | /*==============================================================*/ 5 | 6 | 7 | drop table if exists coupon; 8 | 9 | /*==============================================================*/ 10 | /* Table: coupon */ 11 | /*==============================================================*/ 12 | create table coupon 13 | ( 14 | id bigint unsigned not null auto_increment, 15 | amount bigint not null, 16 | userId bigint not null, 17 | state varchar(32) not null, 18 | orderId bigint, 19 | useTime datetime, 20 | code varchar(32), 21 | optlock int default 0, 22 | createTime datetime, 23 | updateTime datetime, 24 | primary key (id) 25 | ); 26 | 27 | -------------------------------------------------------------------------------- /coupon/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | coupon-service 6 | 7 | api 8 | core 9 | 10 | pom 11 | 12 | 13 | com.akkafun.mysteam 14 | base 15 | 1.0-SNAPSHOT 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /docs/event.asta: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangjianbinJAVA/mysteam/8b8abba1f0bdab215e638cdb30ad93f9ef267d6a/docs/event.asta -------------------------------------------------------------------------------- /docs/init_database.sql: -------------------------------------------------------------------------------- 1 | 2 | create database if not exists user_service; 3 | use user_service; 4 | source user/docs/user-service.sql; 5 | source common/docs/common.sql; 6 | 7 | create database if not exists account_service; 8 | use account_service; 9 | source account/docs/account-service.sql; 10 | source common/docs/common.sql; 11 | 12 | create database if not exists coupon_service; 13 | use coupon_service; 14 | source coupon/docs/coupon-service.sql; 15 | source common/docs/common.sql; 16 | 17 | create database if not exists order_service; 18 | use order_service; 19 | source order/docs/order-service.sql; 20 | source common/docs/common.sql; 21 | 22 | create database if not exists product_service; 23 | use product_service; 24 | source product/docs/product-service.sql; 25 | source product/docs/init-product.sql; 26 | source common/docs/common.sql; -------------------------------------------------------------------------------- /eureka/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | eureka 6 | jar 7 | 8 | 9 | com.akkafun.mysteam 10 | base 11 | 1.0-SNAPSHOT 12 | 13 | 14 | 15 | 16 | com.akkafun.eureka.EurekaApplication 17 | 18 | 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter 24 | 25 | 26 | 27 | 28 | org.springframework.cloud 29 | spring-cloud-starter 30 | 31 | 32 | 33 | 34 | org.springframework.cloud 35 | spring-cloud-starter-eureka-server 36 | 37 | 38 | 39 | 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-maven-plugin 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /eureka/src/main/java/com/akkafun/eureka/EurekaApplication.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.eureka; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | /** 8 | * All you need to run a Eureka registration server. 9 | * 10 | * @author Paul Chapman 11 | */ 12 | @SpringBootApplication 13 | @EnableEurekaServer 14 | public class EurekaApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(EurekaApplication.class, args); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /eureka/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | # Configure this Discovery Server 2 | eureka: 3 | instance: 4 | # hostname: localhost 5 | preferIpAddress: true 6 | client: # Not a client, don't register with yourself 7 | registerWithEureka: false 8 | fetchRegistry: false 9 | serviceUrl: 10 | defaultZone: http://localhost:1111/eureka/ 11 | 12 | server: 13 | enable-self-preservation: false 14 | 15 | server: 16 | port: 1111 # HTTP (Tomcat) port 17 | 18 | # Discovery Server Dashboard uses FreeMarker. Don't want Thymeleaf templates 19 | spring: 20 | thymeleaf: 21 | enabled: false # Disable Thymeleaf -------------------------------------------------------------------------------- /eureka/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | ${PID}: %-5level %logger{0} - %msg%n 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /integration-test/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | logs/integration-test.log 15 | 16 | 17 | logs/integration-test-log-%d{yyyy-MM-dd}.gz 18 | 19 | 30 20 | 21 | 22 | %date{yyyy-MM-dd HH:mm:ss} ${PID}: %-5level %logger{0} - %msg%n 23 | 24 | 25 | 26 | 27 | 28 | %date{yyyy-MM-dd HH:mm:ss} ${PID}: %-5level %logger{0} - %msg%n 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /integration-test/src/test/java/com/akkafun/integrationtest/test/BaseIntegrationTest.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.integrationtest.test; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.boot.test.SpringApplicationConfiguration; 7 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 8 | 9 | /** 10 | * Created by liubin on 2016/3/29. 11 | */ 12 | @RunWith(SpringJUnit4ClassRunner.class) 13 | @SpringApplicationConfiguration(classes = IntegrationTestApplication.class) 14 | public abstract class BaseIntegrationTest { 15 | 16 | protected Logger logger = LoggerFactory.getLogger(BaseIntegrationTest.class); 17 | 18 | protected void waitForEventProcessed() { 19 | try { 20 | Thread.sleep(20000L); 21 | } catch (InterruptedException e) { 22 | logger.error("", e); 23 | } 24 | } 25 | 26 | 27 | } 28 | -------------------------------------------------------------------------------- /order/api/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | order-service-api 6 | jar 7 | 8 | 9 | com.akkafun.mysteam 10 | order-service 11 | 1.0-SNAPSHOT 12 | 13 | 14 | 15 | 16 | 17 | 18 | com.akkafun.mysteam 19 | apiutils 20 | ${project.version} 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /order/api/src/main/java/com/akkafun/order/api/OrderUrl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.api; 2 | 3 | /** 4 | * Created by liubin on 2016/5/6. 5 | */ 6 | public interface OrderUrl { 7 | 8 | String SERVICE_NAME = "ORDER"; 9 | 10 | String SERVICE_HOSTNAME = "http://ORDER"; 11 | 12 | String PLACE_ORDER = "/orders/place"; 13 | 14 | String ORDER_INFO = "/orders/{orderId}"; 15 | 16 | static String buildUrl(String url) { 17 | return SERVICE_HOSTNAME + url; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /order/api/src/main/java/com/akkafun/order/api/constants/OrderStatus.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.api.constants; 2 | 3 | /** 4 | * Created by liubin on 2016/4/26. 5 | */ 6 | public enum OrderStatus { 7 | 8 | CREATE_PENDING("正在下单"), 9 | 10 | CREATED("已下单"), 11 | 12 | CREATE_FAILED("下单失败"); 13 | 14 | public String desc; 15 | 16 | OrderStatus(String desc) { 17 | this.desc = desc; 18 | } 19 | 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /order/api/src/main/java/com/akkafun/order/api/dtos/OrderItemDto.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.api.dtos; 2 | 3 | /** 4 | * Created by liubin on 2016/3/28. 5 | */ 6 | public class OrderItemDto { 7 | 8 | private Long id; 9 | 10 | private Long productId; 11 | 12 | private Long price; 13 | 14 | private int quantity; 15 | 16 | public Long getId() { 17 | return id; 18 | } 19 | 20 | public void setId(Long id) { 21 | this.id = id; 22 | } 23 | 24 | public Long getProductId() { 25 | return productId; 26 | } 27 | 28 | public void setProductId(Long productId) { 29 | this.productId = productId; 30 | } 31 | 32 | public Long getPrice() { 33 | return price; 34 | } 35 | 36 | public void setPrice(Long price) { 37 | this.price = price; 38 | } 39 | 40 | public int getQuantity() { 41 | return quantity; 42 | } 43 | 44 | public void setQuantity(int quantity) { 45 | this.quantity = quantity; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /order/api/src/main/java/com/akkafun/order/api/dtos/PlaceOrderDto.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.api.dtos; 2 | 3 | import org.hibernate.validator.constraints.NotEmpty; 4 | 5 | import javax.validation.Valid; 6 | import javax.validation.constraints.NotNull; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | /** 11 | * Created by liubin on 2016/5/6. 12 | */ 13 | public class PlaceOrderDto { 14 | 15 | @NotNull(message = "用户ID不能为空") 16 | private Long userId; 17 | 18 | private List couponIdList = new ArrayList<>(); 19 | 20 | @NotEmpty 21 | @Valid 22 | private List placeOrderItemList = new ArrayList<>(0); 23 | 24 | public Long getUserId() { 25 | return userId; 26 | } 27 | 28 | public void setUserId(Long userId) { 29 | this.userId = userId; 30 | } 31 | 32 | public List getCouponIdList() { 33 | return couponIdList; 34 | } 35 | 36 | public void setCouponIdList(List couponIdList) { 37 | this.couponIdList = couponIdList; 38 | } 39 | 40 | public List getPlaceOrderItemList() { 41 | return placeOrderItemList; 42 | } 43 | 44 | public void setPlaceOrderItemList(List placeOrderItemList) { 45 | this.placeOrderItemList = placeOrderItemList; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /order/api/src/main/java/com/akkafun/order/api/dtos/PlaceOrderItemDto.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.api.dtos; 2 | 3 | import javax.validation.constraints.NotNull; 4 | 5 | /** 6 | * Created by liubin on 2016/5/6. 7 | */ 8 | public class PlaceOrderItemDto { 9 | 10 | private int quantity = 0; 11 | 12 | @NotNull(message = "产品ID不能为空") 13 | private Long productId; 14 | 15 | public int getQuantity() { 16 | return quantity; 17 | } 18 | 19 | public void setQuantity(int quantity) { 20 | this.quantity = quantity; 21 | } 22 | 23 | public Long getProductId() { 24 | return productId; 25 | } 26 | 27 | public void setProductId(Long productId) { 28 | this.productId = productId; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /order/api/src/main/java/com/akkafun/order/api/events/OrderCreatePending.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.api.events; 2 | 3 | import com.akkafun.base.event.constants.EventType; 4 | import com.akkafun.base.event.domain.BaseEvent; 5 | import com.akkafun.base.event.domain.NotifyEvent; 6 | import com.fasterxml.jackson.annotation.JsonCreator; 7 | import com.fasterxml.jackson.annotation.JsonProperty; 8 | 9 | import java.time.LocalDateTime; 10 | 11 | /** 12 | * Created by liubin on 2016/5/9. 13 | */ 14 | public class OrderCreatePending extends NotifyEvent { 15 | 16 | public static final EventType EVENT_TYPE = EventType.ORDER_CREATE_PENDING; 17 | 18 | @Override 19 | public EventType getType() { 20 | return EVENT_TYPE; 21 | } 22 | 23 | private Long orderId; 24 | 25 | private Long orderNo; 26 | 27 | private Long totalAmount; 28 | 29 | private Long payAmount; 30 | 31 | private Long userId; 32 | 33 | @JsonCreator 34 | public OrderCreatePending( 35 | @JsonProperty("orderId") Long orderId, 36 | @JsonProperty("orderNo") Long orderNo, 37 | @JsonProperty("totalAmount") Long totalAmount, 38 | @JsonProperty("payAmount") Long payAmount, 39 | @JsonProperty("userId") Long userId) { 40 | this.orderId = orderId; 41 | this.orderNo = orderNo; 42 | this.totalAmount = totalAmount; 43 | this.payAmount = payAmount; 44 | this.userId = userId; 45 | } 46 | 47 | public Long getOrderId() { 48 | return orderId; 49 | } 50 | 51 | public Long getOrderNo() { 52 | return orderNo; 53 | } 54 | 55 | public Long getTotalAmount() { 56 | return totalAmount; 57 | } 58 | 59 | public Long getPayAmount() { 60 | return payAmount; 61 | } 62 | 63 | public Long getUserId() { 64 | return userId; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/callback/OrderCreateCallback.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.callback; 2 | 3 | import com.akkafun.account.api.events.AskReduceBalance; 4 | import com.akkafun.base.event.constants.FailureInfo; 5 | import com.akkafun.base.exception.AppBusinessException; 6 | import com.akkafun.common.spring.ApplicationContextHolder; 7 | import com.akkafun.coupon.api.events.AskUseCoupon; 8 | import com.akkafun.order.service.OrderService; 9 | import org.apache.commons.lang3.math.NumberUtils; 10 | 11 | /** 12 | * Created by liubin on 2016/6/16. 13 | */ 14 | public class OrderCreateCallback { 15 | 16 | public void onSuccess(AskReduceBalance askReduceBalance, AskUseCoupon askUseCoupon, String orderId) { 17 | 18 | long oId = NumberUtils.toLong(orderId); 19 | if(oId == 0L) { 20 | throw new AppBusinessException("orderId为空: " + orderId); 21 | } 22 | 23 | OrderService orderService = ApplicationContextHolder.context.getBean(OrderService.class); 24 | 25 | orderService.markCreateSuccess(oId); 26 | } 27 | 28 | public void onFailure(AskReduceBalance askReduceBalance, AskUseCoupon askUseCoupon, 29 | String orderId, FailureInfo failureInfo) { 30 | 31 | long oId = NumberUtils.toLong(orderId); 32 | if(oId == 0L) { 33 | throw new AppBusinessException("orderId为空: " + orderId); 34 | } 35 | 36 | OrderService orderService = ApplicationContextHolder.context.getBean(OrderService.class); 37 | 38 | orderService.markCreateFail(oId); 39 | 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/context/OrderApplication.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.context; 2 | 3 | import com.akkafun.base.event.constants.EventType; 4 | import com.akkafun.common.event.config.EventConfiguration; 5 | import com.akkafun.common.event.config.InitBindProducer; 6 | import com.akkafun.common.scheduler.config.SchedulerConfiguration; 7 | import com.akkafun.common.spring.BaseConfiguration; 8 | import com.akkafun.common.spring.ServiceClientConfiguration; 9 | import com.akkafun.common.spring.WebApplication; 10 | import org.springframework.boot.SpringApplication; 11 | import org.springframework.boot.autoconfigure.SpringBootApplication; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.context.annotation.Import; 14 | 15 | /** 16 | * Created by liubin on 2016/3/28. 17 | */ 18 | @SpringBootApplication 19 | @Import({BaseConfiguration.class, EventConfiguration.class, SchedulerConfiguration.class, 20 | ServiceClientConfiguration.class, WebApplication.class}) 21 | public class OrderApplication { 22 | 23 | public static void main(String[] args) { 24 | SpringApplication.run(OrderApplication.class, args); 25 | } 26 | 27 | @Bean 28 | public InitBindProducer initBindProducer() { 29 | 30 | InitBindProducer initBindProducer = new InitBindProducer(); 31 | initBindProducer.addPreInitializeProducers(EventType.ASK_REDUCE_BALANCE); 32 | initBindProducer.addPreInitializeProducers(EventType.ASK_USE_COUPON); 33 | return initBindProducer; 34 | } 35 | 36 | 37 | 38 | } -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/dao/OrderCouponRepository.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.dao; 2 | 3 | import com.akkafun.order.domain.OrderCoupon; 4 | import com.akkafun.order.domain.OrderItem; 5 | import org.springframework.data.repository.PagingAndSortingRepository; 6 | 7 | /** 8 | * Created by liubin on 2016/4/26. 9 | */ 10 | public interface OrderCouponRepository extends PagingAndSortingRepository{ 11 | } 12 | -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/dao/OrderItemRepository.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.dao; 2 | 3 | import com.akkafun.order.domain.OrderItem; 4 | import org.springframework.data.repository.PagingAndSortingRepository; 5 | 6 | /** 7 | * Created by liubin on 2016/4/26. 8 | */ 9 | public interface OrderItemRepository extends PagingAndSortingRepository{ 10 | } 11 | -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/dao/OrderRepository.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.dao; 2 | 3 | import com.akkafun.order.domain.Order; 4 | import org.springframework.data.repository.PagingAndSortingRepository; 5 | 6 | /** 7 | * Created by liubin on 2016/4/26. 8 | */ 9 | public interface OrderRepository extends PagingAndSortingRepository, OrderRepositoryCustom { 10 | } 11 | -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/dao/OrderRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.dao; 2 | 3 | import com.akkafun.common.dao.AbstractRepository; 4 | 5 | /** 6 | * Created by liubin on 2016/4/26. 7 | */ 8 | public interface OrderRepositoryCustom extends AbstractRepository { 9 | } 10 | -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/dao/OrderRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.dao; 2 | 3 | import javax.persistence.EntityManager; 4 | import javax.persistence.PersistenceContext; 5 | 6 | /** 7 | * Created by liubin on 2016/4/26. 8 | */ 9 | public class OrderRepositoryImpl implements OrderRepositoryCustom { 10 | 11 | @PersistenceContext 12 | private EntityManager em; 13 | 14 | 15 | @Override 16 | public EntityManager getEm() { 17 | return em; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/domain/OrderCoupon.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.domain; 2 | 3 | import javax.persistence.*; 4 | 5 | /** 6 | * Created by liubin on 2016/3/28. 7 | */ 8 | @Entity 9 | @Table(name = "order_coupon") 10 | public class OrderCoupon { 11 | 12 | @Id 13 | @GeneratedValue(strategy = GenerationType.AUTO) 14 | private Long id; 15 | 16 | @Column 17 | private Long couponId; 18 | 19 | @Column 20 | private Long couponAmount; 21 | 22 | @Column 23 | private String couponCode; 24 | 25 | @Column 26 | private Long orderId; 27 | 28 | @ManyToOne(fetch = FetchType.LAZY) 29 | @JoinColumn(name = "orderId", insertable = false, updatable = false) 30 | private Order order; 31 | 32 | 33 | public Long getId() { 34 | return id; 35 | } 36 | 37 | public void setId(Long id) { 38 | this.id = id; 39 | } 40 | 41 | public Long getCouponId() { 42 | return couponId; 43 | } 44 | 45 | public void setCouponId(Long couponId) { 46 | this.couponId = couponId; 47 | } 48 | 49 | public Long getCouponAmount() { 50 | return couponAmount; 51 | } 52 | 53 | public void setCouponAmount(Long couponAmount) { 54 | this.couponAmount = couponAmount; 55 | } 56 | 57 | public String getCouponCode() { 58 | return couponCode; 59 | } 60 | 61 | public void setCouponCode(String couponCode) { 62 | this.couponCode = couponCode; 63 | } 64 | 65 | public Long getOrderId() { 66 | return orderId; 67 | } 68 | 69 | public void setOrderId(Long orderId) { 70 | this.orderId = orderId; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/domain/OrderItem.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.domain; 2 | 3 | import com.akkafun.common.domain.LockableEntity; 4 | 5 | import javax.persistence.*; 6 | 7 | /** 8 | * Created by liubin on 2016/3/28. 9 | */ 10 | @Entity 11 | @Table(name = "order_item") 12 | public class OrderItem extends LockableEntity { 13 | 14 | @Id 15 | @GeneratedValue(strategy = GenerationType.AUTO) 16 | private Long id; 17 | 18 | @Column 19 | private Long productId; 20 | 21 | @Column 22 | private Long orderId; 23 | 24 | @ManyToOne(fetch = FetchType.LAZY) 25 | @JoinColumn(name = "orderId", insertable = false, updatable = false) 26 | private Order order; 27 | 28 | @Column 29 | private Long price; 30 | 31 | @Column 32 | private int quantity; 33 | 34 | public Long getId() { 35 | return id; 36 | } 37 | 38 | public void setId(Long id) { 39 | this.id = id; 40 | } 41 | 42 | public Long getProductId() { 43 | return productId; 44 | } 45 | 46 | public void setProductId(Long productId) { 47 | this.productId = productId; 48 | } 49 | 50 | public Long getOrderId() { 51 | return orderId; 52 | } 53 | 54 | public void setOrderId(Long orderId) { 55 | this.orderId = orderId; 56 | } 57 | 58 | public Long getPrice() { 59 | return price; 60 | } 61 | 62 | public void setPrice(Long price) { 63 | this.price = price; 64 | } 65 | 66 | public int getQuantity() { 67 | return quantity; 68 | } 69 | 70 | public void setQuantity(int quantity) { 71 | this.quantity = quantity; 72 | } 73 | 74 | public Order getOrder() { 75 | return order; 76 | } 77 | 78 | public void setOrder(Order order) { 79 | this.order = order; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/service/gateway/AccountClient.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.service.gateway; 2 | 3 | import com.akkafun.account.api.AccountUrl; 4 | import com.akkafun.base.api.BooleanWrapper; 5 | import org.springframework.cloud.netflix.feign.FeignClient; 6 | import org.springframework.web.bind.annotation.PathVariable; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | import org.springframework.web.bind.annotation.RequestParam; 10 | 11 | /** 12 | * Created by liubin on 2016/8/25. 13 | */ 14 | @FeignClient(AccountUrl.SERVICE_HOSTNAME) 15 | public interface AccountClient { 16 | 17 | @RequestMapping(method = RequestMethod.GET, value = AccountUrl.CHECK_ENOUGH_BALANCE) 18 | BooleanWrapper checkEnoughBalance(@PathVariable("userId") Long userId, @RequestParam("balance") Long balance); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/service/gateway/AccountGateway.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.service.gateway; 2 | 3 | import com.akkafun.base.exception.RemoteCallException; 4 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | /** 11 | * Created by liubin on 2016/7/18. 12 | */ 13 | @Service 14 | public class AccountGateway { 15 | 16 | protected Logger logger = LoggerFactory.getLogger(AccountGateway.class); 17 | 18 | @Autowired 19 | AccountClient accountClient; 20 | 21 | @HystrixCommand(ignoreExceptions = RemoteCallException.class) 22 | public boolean isBalanceEnough(Long userId, Long amount) { 23 | return accountClient.checkEnoughBalance(userId, amount).isSuccess(); 24 | } 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/service/gateway/CouponClient.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.service.gateway; 2 | 3 | import com.akkafun.coupon.api.CouponUrl; 4 | import com.akkafun.coupon.api.dtos.CouponDto; 5 | import org.springframework.cloud.netflix.feign.FeignClient; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RequestMethod; 8 | import org.springframework.web.bind.annotation.RequestParam; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Created by liubin on 2016/8/25. 14 | */ 15 | @FeignClient(CouponUrl.SERVICE_HOSTNAME) 16 | public interface CouponClient { 17 | 18 | @RequestMapping(method = RequestMethod.GET, value = CouponUrl.COUPON_LIST_URL) 19 | List findCoupons(@RequestParam("id") List id); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/service/gateway/CouponGateway.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.service.gateway; 2 | 3 | import com.akkafun.base.api.CommonErrorCode; 4 | import com.akkafun.base.exception.AppBusinessException; 5 | import com.akkafun.base.exception.RemoteCallException; 6 | import com.akkafun.coupon.api.constants.CouponState; 7 | import com.akkafun.coupon.api.dtos.CouponDto; 8 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Service; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | import java.util.stream.Collectors; 17 | 18 | /** 19 | * Created by liubin on 2016/7/18. 20 | */ 21 | @Service 22 | public class CouponGateway { 23 | 24 | protected Logger logger = LoggerFactory.getLogger(CouponGateway.class); 25 | 26 | @Autowired 27 | CouponClient couponClient; 28 | 29 | @HystrixCommand(ignoreExceptions = RemoteCallException.class) 30 | public List findCoupons(List couponIds) { 31 | 32 | if(couponIds.isEmpty()) return new ArrayList<>(); 33 | 34 | List couponDtoList = couponClient.findCoupons(couponIds); 35 | 36 | if(!couponDtoList.isEmpty()) { 37 | 38 | //过滤出无效的优惠券 39 | List notValidCouponDtoList = couponDtoList.stream() 40 | .filter(couponDto -> !couponDto.getState().equals(CouponState.VALID)) 41 | .collect(Collectors.toList()); 42 | if (!notValidCouponDtoList.isEmpty()) { 43 | throw new AppBusinessException(CommonErrorCode.NOT_FOUND, 44 | String.format("无效的优惠券信息, 优惠券id: %s", 45 | notValidCouponDtoList.stream().map(CouponDto::getId).collect(Collectors.toList()))); 46 | } 47 | } 48 | 49 | return couponDtoList; 50 | } 51 | 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/service/gateway/ProductClient.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.service.gateway; 2 | 3 | import com.akkafun.product.api.ProductUrl; 4 | import com.akkafun.product.api.dtos.ProductDto; 5 | import org.springframework.cloud.netflix.feign.FeignClient; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RequestMethod; 8 | import org.springframework.web.bind.annotation.RequestParam; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Created by liubin on 2016/8/25. 14 | */ 15 | @FeignClient(ProductUrl.SERVICE_HOSTNAME) 16 | public interface ProductClient { 17 | 18 | @RequestMapping(method = RequestMethod.GET, value = ProductUrl.PRODUCT_LIST_URL) 19 | List findProducts(@RequestParam("id") List id); 20 | 21 | @RequestMapping(method = RequestMethod.GET, value = ProductUrl.ALL_PRODUCT_LIST_URL) 22 | List findAllProducts(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/service/gateway/ProductGateway.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.service.gateway; 2 | 3 | import com.akkafun.base.exception.RemoteCallException; 4 | import com.akkafun.product.api.ProductUrl; 5 | import com.akkafun.product.api.dtos.ProductDto; 6 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | import org.springframework.web.client.RestTemplate; 12 | import org.springframework.web.util.UriComponentsBuilder; 13 | 14 | import java.net.URI; 15 | import java.util.Arrays; 16 | import java.util.List; 17 | 18 | /** 19 | * Created by liubin on 2016/7/18. 20 | */ 21 | @Service 22 | public class ProductGateway { 23 | 24 | protected Logger logger = LoggerFactory.getLogger(ProductGateway.class); 25 | 26 | @Autowired 27 | ProductClient productClient; 28 | 29 | @HystrixCommand(ignoreExceptions = RemoteCallException.class) 30 | public List findProducts(List productIds) { 31 | 32 | return productClient.findProducts(productIds); 33 | } 34 | 35 | @HystrixCommand(ignoreExceptions = RemoteCallException.class) 36 | public List findAllProducts() { 37 | List productDtos = productClient.findAllProducts(); 38 | 39 | try { 40 | Thread.sleep(2000L); 41 | } catch (InterruptedException e) { 42 | e.printStackTrace(); 43 | } 44 | 45 | return productDtos; 46 | 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/utils/OrderUtils.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.utils; 2 | 3 | import com.akkafun.order.api.dtos.OrderDto; 4 | import com.akkafun.order.api.dtos.OrderItemDto; 5 | import com.akkafun.order.domain.Order; 6 | 7 | import java.util.stream.Collectors; 8 | 9 | /** 10 | * Created by liubin on 2016/6/24. 11 | */ 12 | public class OrderUtils { 13 | 14 | 15 | public static OrderDto convertToDto(Order order) { 16 | 17 | OrderDto orderDto = new OrderDto(); 18 | orderDto.setCreateTime(order.getCreateTime()); 19 | orderDto.setId(order.getId()); 20 | orderDto.setOrderNo(order.getOrderNo()); 21 | orderDto.setPayAmount(order.getPayAmount()); 22 | orderDto.setStatus(order.getStatus()); 23 | orderDto.setTotalAmount(order.getTotalAmount()); 24 | orderDto.setUpdateTime(order.getUpdateTime()); 25 | orderDto.setUserId(order.getUserId()); 26 | orderDto.setOrderItemList(order.getOrderItemList().stream().map(orderItem -> { 27 | OrderItemDto orderItemDto = new OrderItemDto(); 28 | orderItemDto.setId(orderItem.getId()); 29 | orderItemDto.setPrice(orderItem.getPrice()); 30 | orderItemDto.setProductId(orderItem.getProductId()); 31 | orderItemDto.setQuantity(orderItem.getQuantity()); 32 | return orderItemDto; 33 | }).collect(Collectors.toList())); 34 | 35 | return orderDto; 36 | 37 | 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /order/core/src/main/java/com/akkafun/order/web/OrderController.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.web; 2 | 3 | import com.akkafun.order.api.dtos.OrderDto; 4 | import com.akkafun.order.api.dtos.PlaceOrderDto; 5 | import com.akkafun.order.domain.Order; 6 | import com.akkafun.order.service.OrderService; 7 | import com.akkafun.order.utils.OrderUtils; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.http.MediaType; 10 | import org.springframework.web.bind.annotation.*; 11 | 12 | import javax.validation.Valid; 13 | 14 | import static com.akkafun.order.api.OrderUrl.ORDER_INFO; 15 | import static com.akkafun.order.api.OrderUrl.PLACE_ORDER; 16 | 17 | /** 18 | * Created by liubin on 2016/3/29. 19 | */ 20 | @RestController 21 | @RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE) 22 | public class OrderController { 23 | 24 | @Autowired 25 | OrderService orderService; 26 | 27 | @RequestMapping(value = PLACE_ORDER, method = RequestMethod.POST) 28 | public OrderDto placeOrder(@Valid @RequestBody PlaceOrderDto placeOrderDto) { 29 | 30 | Order order = orderService.placeOrder(placeOrderDto); 31 | 32 | return OrderUtils.convertToDto(order); 33 | } 34 | 35 | @RequestMapping(value = ORDER_INFO, method = RequestMethod.GET) 36 | public OrderDto orderInfo(@PathVariable("orderId") Long orderId) { 37 | 38 | Order order = orderService.get(orderId); 39 | 40 | return OrderUtils.convertToDto(order); 41 | } 42 | 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /order/core/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: order 4 | cloud: 5 | config: 6 | uri: ${CONFIG_SERVER_URI:http://localhost:8888} 7 | failFast: true 8 | encrypt: 9 | failOnError: true 10 | -------------------------------------------------------------------------------- /order/core/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | logs/order-service.log 15 | 16 | 17 | logs/order-service-log-%d{yyyy-MM-dd}.gz 18 | 19 | 30 20 | 21 | 22 | %date{yyyy-MM-dd HH:mm:ss} ${PID}: %-5level %logger{0} - %msg%n 23 | 24 | 25 | 26 | 27 | 28 | %date{yyyy-MM-dd HH:mm:ss} ${PID}: %-5level %logger{0} - %msg%n 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /order/core/src/test/java/com/akkafun/order/service/OrderServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.service; 2 | 3 | import com.akkafun.order.api.dtos.PlaceOrderDto; 4 | import com.akkafun.order.api.dtos.PlaceOrderItemDto; 5 | import com.akkafun.order.domain.Order; 6 | import com.akkafun.order.test.OrderBaseTest; 7 | import com.google.common.collect.Lists; 8 | import org.junit.Ignore; 9 | import org.junit.Test; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | 12 | /** 13 | * Created by liubin on 2016/5/9. 14 | */ 15 | public class OrderServiceTest extends OrderBaseTest { 16 | 17 | @Autowired 18 | OrderService orderService; 19 | 20 | @Test 21 | @Ignore 22 | public void test() { 23 | 24 | PlaceOrderDto placeOrderDto = new PlaceOrderDto(); 25 | placeOrderDto.setUserId(1L); 26 | PlaceOrderItemDto placeOrderItemDto1 = new PlaceOrderItemDto(); 27 | placeOrderItemDto1.setProductId(1L); 28 | placeOrderItemDto1.setQuantity(1); 29 | PlaceOrderItemDto placeOrderItemDto2 = new PlaceOrderItemDto(); 30 | placeOrderItemDto2.setProductId(2L); 31 | placeOrderItemDto2.setQuantity(2); 32 | placeOrderDto.setPlaceOrderItemList(Lists.newArrayList(placeOrderItemDto1, placeOrderItemDto2)); 33 | 34 | Order order = orderService.placeOrder(placeOrderDto); 35 | System.out.println(order.getId()); 36 | 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /order/core/src/test/java/com/akkafun/order/service/gateway/ProductGatewayTest.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.service.gateway; 2 | 3 | import com.akkafun.order.test.OrderBaseTest; 4 | import com.akkafun.product.api.dtos.ProductDto; 5 | import org.junit.Ignore; 6 | import org.junit.Test; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | 9 | import java.util.List; 10 | 11 | import static org.hamcrest.Matchers.is; 12 | import static org.junit.Assert.assertThat; 13 | 14 | /** 15 | * Created by liubin on 2016/5/9. 16 | */ 17 | public class ProductGatewayTest extends OrderBaseTest { 18 | 19 | @Autowired 20 | ProductGateway productGateway; 21 | 22 | @Test 23 | @Ignore 24 | public void test() { 25 | 26 | List productDtos = productGateway.findAllProducts(); 27 | assertThat(productDtos.isEmpty(), is(false)); 28 | 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /order/core/src/test/java/com/akkafun/order/test/OrderBaseControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.test; 2 | 3 | import com.akkafun.common.test.BaseControllerTest; 4 | import org.springframework.boot.test.SpringApplicationConfiguration; 5 | 6 | /** 7 | * Created by liubin on 2016/3/30. 8 | */ 9 | @SpringApplicationConfiguration(classes = TestOrderApplication.class) 10 | public abstract class OrderBaseControllerTest extends BaseControllerTest { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /order/core/src/test/java/com/akkafun/order/test/OrderBaseTest.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.test; 2 | 3 | import com.akkafun.common.test.BaseTest; 4 | import org.springframework.boot.test.SpringApplicationConfiguration; 5 | 6 | /** 7 | * Created by liubin on 2016/3/29. 8 | */ 9 | @SpringApplicationConfiguration(classes = TestOrderApplication.class) 10 | public abstract class OrderBaseTest extends BaseTest{ 11 | } 12 | -------------------------------------------------------------------------------- /order/core/src/test/java/com/akkafun/order/test/TestOrderApplication.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.order.test; 2 | 3 | import com.akkafun.common.event.config.EventConfiguration; 4 | import com.akkafun.common.spring.BaseConfiguration; 5 | import com.akkafun.common.spring.ServiceClientConfiguration; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.annotation.Import; 8 | 9 | /** 10 | * Created by liubin on 2016/3/28. 11 | */ 12 | @SpringBootApplication 13 | @Import({BaseConfiguration.class, EventConfiguration.class, ServiceClientConfiguration.class}) 14 | public class TestOrderApplication { 15 | 16 | 17 | } -------------------------------------------------------------------------------- /order/docs/order-service.sql: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangjianbinJAVA/mysteam/8b8abba1f0bdab215e638cdb30ad93f9ef267d6a/order/docs/order-service.sql -------------------------------------------------------------------------------- /order/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | order-service 6 | 7 | api 8 | core 9 | 10 | pom 11 | 12 | 13 | com.akkafun.mysteam 14 | base 15 | 1.0-SNAPSHOT 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /product/api/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | product-service-api 6 | jar 7 | 8 | 9 | com.akkafun.mysteam 10 | product-service 11 | 1.0-SNAPSHOT 12 | 13 | 14 | 15 | 16 | 17 | 18 | com.akkafun.mysteam 19 | apiutils 20 | ${project.version} 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /product/api/src/main/java/com/akkafun/product/api/ProductUrl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.product.api; 2 | 3 | /** 4 | * Created by liubin on 2016/5/6. 5 | */ 6 | public interface ProductUrl { 7 | 8 | String SERVICE_NAME = "PRODUCT"; 9 | 10 | String SERVICE_HOSTNAME = "http://PRODUCT"; 11 | 12 | String ALL_PRODUCT_LIST_URL = "/products/all"; 13 | 14 | String PRODUCT_LIST_URL = "/products"; 15 | 16 | static String buildUrl(String url) { 17 | return SERVICE_HOSTNAME + url; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /product/api/src/main/java/com/akkafun/product/api/dtos/ProductDto.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.product.api.dtos; 2 | 3 | /** 4 | * Created by liubin on 2016/5/16. 5 | */ 6 | public class ProductDto { 7 | 8 | private Long id; 9 | 10 | private String name; 11 | 12 | private String description; 13 | 14 | private Long price; 15 | 16 | private String category; 17 | 18 | 19 | public Long getId() { 20 | return id; 21 | } 22 | 23 | public void setId(Long id) { 24 | this.id = id; 25 | } 26 | 27 | public String getName() { 28 | return name; 29 | } 30 | 31 | public void setName(String name) { 32 | this.name = name; 33 | } 34 | 35 | public String getDescription() { 36 | return description; 37 | } 38 | 39 | public void setDescription(String description) { 40 | this.description = description; 41 | } 42 | 43 | public Long getPrice() { 44 | return price; 45 | } 46 | 47 | public void setPrice(Long price) { 48 | this.price = price; 49 | } 50 | 51 | public String getCategory() { 52 | return category; 53 | } 54 | 55 | public void setCategory(String category) { 56 | this.category = category; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /product/core/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | product-service-core 6 | jar 7 | 8 | 9 | com.akkafun.mysteam 10 | product-service 11 | 1.0-SNAPSHOT 12 | 13 | 14 | 15 | 16 | com.akkafun.product.context.ProductApplication 17 | 18 | 19 | 20 | 21 | 22 | mysql 23 | mysql-connector-java 24 | runtime 25 | 26 | 27 | 28 | com.akkafun.mysteam 29 | common 30 | ${project.version} 31 | 32 | 33 | 34 | com.akkafun.mysteam 35 | common 36 | ${project.version} 37 | test-jar 38 | test 39 | 40 | 41 | 42 | com.akkafun.mysteam 43 | product-service-api 44 | ${project.version} 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | org.springframework.boot 53 | spring-boot-maven-plugin 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /product/core/src/main/java/com/akkafun/product/context/ProductApplication.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.product.context; 2 | 3 | import com.akkafun.common.event.config.EventConfiguration; 4 | import com.akkafun.common.scheduler.config.SchedulerConfiguration; 5 | import com.akkafun.common.spring.BaseConfiguration; 6 | import com.akkafun.common.spring.ServiceClientConfiguration; 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.context.annotation.Import; 10 | 11 | /** 12 | * Created by liubin on 2016/3/28. 13 | */ 14 | @SpringBootApplication 15 | @Import({BaseConfiguration.class, EventConfiguration.class, SchedulerConfiguration.class, ServiceClientConfiguration.class}) 16 | public class ProductApplication { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(ProductApplication.class, args); 20 | } 21 | 22 | 23 | } -------------------------------------------------------------------------------- /product/core/src/main/java/com/akkafun/product/dao/ProductRepository.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.product.dao; 2 | 3 | import com.akkafun.product.domain.Product; 4 | import org.springframework.data.repository.PagingAndSortingRepository; 5 | 6 | /** 7 | * Created by liubin on 2016/4/26. 8 | */ 9 | public interface ProductRepository extends PagingAndSortingRepository{ 10 | } 11 | -------------------------------------------------------------------------------- /product/core/src/main/java/com/akkafun/product/domain/Product.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.product.domain; 2 | 3 | import javax.persistence.*; 4 | 5 | /** 6 | * Created by liubin on 2016/3/28. 7 | */ 8 | @Entity 9 | @Table(name = "product") 10 | public class Product { 11 | 12 | @Id 13 | @GeneratedValue(strategy = GenerationType.AUTO) 14 | private Long id; 15 | 16 | @Column 17 | private String name; 18 | 19 | @Column 20 | private String description; 21 | 22 | @Column 23 | private Long price; 24 | 25 | @Column 26 | private String category; 27 | 28 | 29 | public Long getId() { 30 | return id; 31 | } 32 | 33 | public void setId(Long id) { 34 | this.id = id; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public void setName(String name) { 42 | this.name = name; 43 | } 44 | 45 | public String getDescription() { 46 | return description; 47 | } 48 | 49 | public void setDescription(String description) { 50 | this.description = description; 51 | } 52 | 53 | public Long getPrice() { 54 | return price; 55 | } 56 | 57 | public void setPrice(Long price) { 58 | this.price = price; 59 | } 60 | 61 | public String getCategory() { 62 | return category; 63 | } 64 | 65 | public void setCategory(String category) { 66 | this.category = category; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /product/core/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: product 4 | cloud: 5 | config: 6 | uri: ${CONFIG_SERVER_URI:http://localhost:8888} 7 | failFast: true 8 | encrypt: 9 | failOnError: true 10 | -------------------------------------------------------------------------------- /product/core/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | logs/product-service.log 15 | 16 | 17 | logs/product-service-log-%d{yyyy-MM-dd}.gz 18 | 19 | 30 20 | 21 | 22 | %date{yyyy-MM-dd HH:mm:ss} ${PID}: %-5level %logger{0} - %msg%n 23 | 24 | 25 | 26 | 27 | 28 | %date{yyyy-MM-dd HH:mm:ss} ${PID}: %-5level %logger{0} - %msg%n 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /product/docs/init-product.sql: -------------------------------------------------------------------------------- 1 | use product_service; 2 | 3 | insert into product values(null, 'The Witcher 3: Wild Hunt', 'The Witcher is a story-driven, next-generation open world role-playing game, set in a visually stunning fantasy universe, full of meaningful choices and impactful consequences. In The Witcher, you play as Geralt of Rivia, a monster hunter tasked with finding a child from an ancient prophecy', 100, 'RPG'); 4 | insert into product values(null, 'Resident Evil Revelations 2', 'RE Revelations 2 continues the series acclaimed essential survival horror experience, while uncovering startling truths', 200, 'Scariest Game'); 5 | insert into product values(null, 'attack heros', 'attack heros', 300, 'RPG'); 6 | insert into product values(null, 'game4', 'game4', 0, 'RPG'); -------------------------------------------------------------------------------- /product/docs/product-service.sql: -------------------------------------------------------------------------------- 1 | /*==============================================================*/ 2 | /* DBMS name: MySQL 5.0 */ 3 | /* Created on: 2016/5/16 14:30:29 */ 4 | /*==============================================================*/ 5 | 6 | 7 | drop table if exists product; 8 | 9 | /*==============================================================*/ 10 | /* Table: product */ 11 | /*==============================================================*/ 12 | create table product 13 | ( 14 | id bigint unsigned not null auto_increment, 15 | name national varchar(255) not null, 16 | description text, 17 | price bigint, 18 | category varchar(32), 19 | primary key (id) 20 | ); 21 | 22 | -------------------------------------------------------------------------------- /product/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | product-service 6 | 7 | api 8 | core 9 | 10 | pom 11 | 12 | 13 | com.akkafun.mysteam 14 | base 15 | 1.0-SNAPSHOT 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /turbine/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | turbine 6 | jar 7 | 8 | 9 | com.akkafun.mysteam 10 | base 11 | 1.0-SNAPSHOT 12 | 13 | 14 | 15 | com.akkafun.turbine.TurbineApplication 16 | 17 | 18 | 19 | 20 | 21 | org.springframework.cloud 22 | spring-cloud-starter-hystrix 23 | 24 | 25 | 26 | org.springframework.cloud 27 | spring-cloud-starter-hystrix-dashboard 28 | 29 | 30 | 31 | org.springframework.cloud 32 | spring-cloud-starter-turbine 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-maven-plugin 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /turbine/src/main/java/com/akkafun/turbine/TurbineApplication.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.turbine; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; 7 | import org.springframework.cloud.netflix.turbine.EnableTurbine; 8 | 9 | @SpringBootApplication 10 | @EnableDiscoveryClient 11 | @EnableTurbine 12 | @EnableHystrixDashboard 13 | public class TurbineApplication { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(TurbineApplication.class, args); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /turbine/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7777 3 | 4 | spring: 5 | application: 6 | name: turbine 7 | 8 | logging: 9 | level: 10 | org.springframework.cloud: 'INFO' 11 | 12 | turbine: 13 | aggregator: 14 | clusterConfig: USER,ACCOUNT,COUPON,PRODUCT,ORDER 15 | appConfig: user,account,coupon,product,order 16 | instanceUrlSuffix: /hystrix.stream 17 | 18 | # Discovery Server Access 19 | eureka: 20 | instance: 21 | # hostname: localhost 22 | preferIpAddress: true 23 | 24 | client: 25 | serviceUrl: 26 | defaultZone: http://localhost:1111/eureka/ 27 | 28 | -------------------------------------------------------------------------------- /user/api/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | user-service-api 6 | jar 7 | 8 | 9 | com.akkafun.mysteam 10 | user-service 11 | 1.0-SNAPSHOT 12 | 13 | 14 | 15 | 16 | 17 | 18 | com.akkafun.mysteam 19 | apiutils 20 | ${project.version} 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /user/api/src/main/java/com/akkafun/user/api/UserErrorCode.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.user.api; 2 | 3 | import com.akkafun.base.api.ErrorCode; 4 | 5 | /** 6 | * Created by liubin on 2016/5/3. 7 | */ 8 | public enum UserErrorCode implements ErrorCode { 9 | 10 | UsernameExist(409, "用户名已存在"), 11 | PhoneExist(409, "手机已存在"), 12 | EmailExist(409, "邮箱已存在"); 13 | 14 | private int status; 15 | 16 | private String message; 17 | 18 | UserErrorCode(int status, String message) { 19 | this.status = status; 20 | this.message = message; 21 | } 22 | 23 | 24 | @Override 25 | public String getCode() { 26 | return this.name(); 27 | } 28 | 29 | @Override 30 | public int getStatus() { 31 | return status; 32 | } 33 | 34 | @Override 35 | public String getMessage() { 36 | return message; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /user/api/src/main/java/com/akkafun/user/api/UserUrl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.user.api; 2 | 3 | /** 4 | * Created by liubin on 2016/3/30. 5 | */ 6 | public interface UserUrl { 7 | 8 | String SERVICE_NAME = "USER"; 9 | 10 | String SERVICE_HOSTNAME = "http://USER"; 11 | 12 | String USER_REGISTER_URL = "/users/register"; 13 | 14 | static String buildUrl(String url) { 15 | return SERVICE_HOSTNAME + url; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /user/api/src/main/java/com/akkafun/user/api/dtos/RegisterDto.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.user.api.dtos; 2 | 3 | import com.akkafun.user.api.utils.RegExpUtils; 4 | import org.hibernate.validator.constraints.NotBlank; 5 | 6 | import javax.validation.constraints.Pattern; 7 | import javax.validation.constraints.Size; 8 | 9 | /** 10 | * Created by liubin on 2016/3/29. 11 | */ 12 | public class RegisterDto { 13 | 14 | @NotBlank(message = "用户名不能为空") 15 | @Pattern(regexp = RegExpUtils.USERNAME_REG_EXP, message = "用户名请输入2-20位,可由中文、英文或数字组成") 16 | private String username; 17 | 18 | @NotBlank(message = "密码不能为空") 19 | @Size(min = 4, max = 20, message = "密码长度需要为4-20位") 20 | private String password; 21 | 22 | 23 | public String getUsername() { 24 | return username; 25 | } 26 | 27 | public void setUsername(String username) { 28 | this.username = username; 29 | } 30 | 31 | public String getPassword() { 32 | return password; 33 | } 34 | 35 | public void setPassword(String password) { 36 | this.password = password; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /user/api/src/main/java/com/akkafun/user/api/dtos/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.user.api.dtos; 2 | 3 | /** 4 | * Created by liubin on 2016/3/29. 5 | */ 6 | public class UserDto { 7 | 8 | private Long id; 9 | 10 | private String username; 11 | 12 | public Long getId() { 13 | return id; 14 | } 15 | 16 | public void setId(Long id) { 17 | this.id = id; 18 | } 19 | 20 | public String getUsername() { 21 | return username; 22 | } 23 | 24 | public void setUsername(String username) { 25 | this.username = username; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /user/api/src/main/java/com/akkafun/user/api/events/UserCreated.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.user.api.events; 2 | 3 | import com.akkafun.base.event.constants.EventType; 4 | import com.akkafun.base.event.domain.BaseEvent; 5 | import com.akkafun.base.event.domain.NotifyEvent; 6 | import com.fasterxml.jackson.annotation.JsonCreator; 7 | import com.fasterxml.jackson.annotation.JsonProperty; 8 | 9 | import java.time.LocalDateTime; 10 | 11 | /** 12 | * Created by liubin on 2016/4/8. 13 | */ 14 | public class UserCreated extends NotifyEvent { 15 | 16 | public static final EventType EVENT_TYPE = EventType.USER_CREATED; 17 | 18 | @Override 19 | public EventType getType() { 20 | return EVENT_TYPE; 21 | } 22 | 23 | private Long userId; 24 | 25 | private String username; 26 | 27 | private LocalDateTime registerTime; 28 | 29 | @JsonCreator 30 | public UserCreated( 31 | @JsonProperty("userId") Long userId, 32 | @JsonProperty("username") String username, 33 | @JsonProperty("registerTime") LocalDateTime registerTime) { 34 | this.userId = userId; 35 | this.username = username; 36 | this.registerTime = registerTime; 37 | } 38 | 39 | public Long getUserId() { 40 | return userId; 41 | } 42 | 43 | public String getUsername() { 44 | return username; 45 | } 46 | 47 | public LocalDateTime getRegisterTime() { 48 | return registerTime; 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | return "UserCreated{" + 54 | "userId=" + userId + 55 | ", username='" + username + '\'' + 56 | ", registerTime=" + registerTime + 57 | "} " + super.toString(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /user/api/src/main/java/com/akkafun/user/api/utils/RegExpUtils.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.user.api.utils; 2 | 3 | import java.util.regex.Pattern; 4 | 5 | public class RegExpUtils { 6 | 7 | public static final String USERNAME_REG_EXP = "^[A-Za-z0-9_\\-\\u4e00-\\u9fa5]{2,20}$"; 8 | private static final Pattern USERNAME_PATTERN = Pattern.compile(USERNAME_REG_EXP); 9 | 10 | public static final String PHONE_REG_EXP = "^[1][\\d]{10}"; 11 | private static final Pattern PHONE_PATTERN = Pattern.compile(PHONE_REG_EXP); 12 | 13 | public static final String EMAIL_REG_EXP = "\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*"; 14 | private static Pattern EMAIL_PATTERN = Pattern.compile(EMAIL_REG_EXP); 15 | 16 | 17 | public static boolean isPhone(String str) { 18 | return str != null && PHONE_PATTERN.matcher(str).matches(); 19 | 20 | } 21 | 22 | public static boolean isEmail(String str) { 23 | return str != null && EMAIL_PATTERN.matcher(str).matches(); 24 | 25 | } 26 | 27 | public static boolean isUsername(String str) { 28 | return str != null && USERNAME_PATTERN.matcher(str).matches(); 29 | 30 | } 31 | 32 | 33 | public static void main(String[] args) { 34 | String phone1 = "18622223333"; 35 | String email1 = "123@1.com"; 36 | String email2 = "123@.com"; 37 | 38 | System.out.println(isPhone(phone1)); 39 | System.out.println(isEmail(email1)); 40 | System.out.println(isEmail(email2)); 41 | 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /user/core/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 4.0.0 5 | user-service-core 6 | jar 7 | 8 | 9 | com.akkafun.mysteam 10 | user-service 11 | 1.0-SNAPSHOT 12 | 13 | 14 | 15 | 16 | com.akkafun.user.context.UserApplication 17 | 18 | 19 | 20 | 21 | 22 | mysql 23 | mysql-connector-java 24 | runtime 25 | 26 | 27 | 28 | com.akkafun.mysteam 29 | common 30 | ${project.version} 31 | 32 | 33 | 34 | com.akkafun.mysteam 35 | common 36 | ${project.version} 37 | test-jar 38 | test 39 | 40 | 41 | 42 | com.akkafun.mysteam 43 | user-service-api 44 | ${project.version} 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | org.springframework.boot 54 | spring-boot-maven-plugin 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /user/core/src/main/java/com/akkafun/user/context/UserApplication.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.user.context; 2 | 3 | import com.akkafun.base.event.constants.EventType; 4 | import com.akkafun.common.event.config.EventConfiguration; 5 | import com.akkafun.common.event.config.InitBindProducer; 6 | import com.akkafun.common.scheduler.config.SchedulerConfiguration; 7 | import com.akkafun.common.spring.BaseConfiguration; 8 | import com.akkafun.common.spring.ServiceClientConfiguration; 9 | import com.akkafun.common.spring.WebApplication; 10 | import org.springframework.boot.SpringApplication; 11 | import org.springframework.boot.autoconfigure.SpringBootApplication; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.context.annotation.Import; 14 | 15 | /** 16 | * Created by liubin on 2016/3/28. 17 | */ 18 | @SpringBootApplication 19 | @Import({BaseConfiguration.class, EventConfiguration.class, SchedulerConfiguration.class, 20 | ServiceClientConfiguration.class, WebApplication.class}) 21 | public class UserApplication { 22 | 23 | public static void main(String[] args) { 24 | SpringApplication.run(UserApplication.class, args); 25 | } 26 | 27 | @Bean 28 | public InitBindProducer initBindProducer() { 29 | 30 | InitBindProducer initBindProducer = new InitBindProducer(); 31 | initBindProducer.addPreInitializeProducers(EventType.USER_CREATED); 32 | return initBindProducer; 33 | } 34 | 35 | 36 | } -------------------------------------------------------------------------------- /user/core/src/main/java/com/akkafun/user/dao/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.user.dao; 2 | 3 | import com.akkafun.user.domain.User; 4 | import org.springframework.data.repository.PagingAndSortingRepository; 5 | 6 | /** 7 | * Created by liubin on 2016/3/29. 8 | */ 9 | public interface UserRepository extends PagingAndSortingRepository, UserRepositoryCustom { 10 | 11 | 12 | 13 | } 14 | -------------------------------------------------------------------------------- /user/core/src/main/java/com/akkafun/user/dao/UserRepositoryCustom.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.user.dao; 2 | 3 | 4 | import com.akkafun.common.dao.AbstractRepository; 5 | 6 | import java.util.Optional; 7 | 8 | /** 9 | * Created by liubin on 2016/3/29. 10 | */ 11 | public interface UserRepositoryCustom extends AbstractRepository { 12 | 13 | /** 14 | * 用户名是否存在 15 | * @param username 16 | * @param userId 17 | * @return 18 | */ 19 | boolean isUsernameExist(String username, Optional userId); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /user/core/src/main/java/com/akkafun/user/dao/UserRepositoryImpl.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.user.dao; 2 | 3 | import javax.persistence.EntityManager; 4 | import javax.persistence.PersistenceContext; 5 | import java.util.HashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.Optional; 9 | 10 | /** 11 | * Created by liubin on 2016/3/29. 12 | */ 13 | public class UserRepositoryImpl implements UserRepositoryCustom { 14 | 15 | @PersistenceContext 16 | private EntityManager em; 17 | 18 | 19 | @Override 20 | public boolean isUsernameExist(String username, Optional userId) { 21 | 22 | String hql = "select u.id from User u where u.username = :username"; 23 | Map params = new HashMap<>(); 24 | params.put("username", username); 25 | if(userId.isPresent()) { 26 | hql += " and u.userId != :userId "; 27 | params.put("userId", userId); 28 | } 29 | List results = query(hql, params); 30 | return !results.isEmpty(); 31 | } 32 | 33 | 34 | @Override 35 | public EntityManager getEm() { 36 | return em; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /user/core/src/main/java/com/akkafun/user/domain/User.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.user.domain; 2 | 3 | import com.akkafun.common.domain.VersionEntity; 4 | 5 | import javax.persistence.*; 6 | 7 | /** 8 | * Created by liubin on 2016/3/28. 9 | */ 10 | @Entity 11 | @Table(name = "user") 12 | public class User extends VersionEntity { 13 | 14 | @Id 15 | @GeneratedValue(strategy = GenerationType.AUTO) 16 | private Long id; 17 | 18 | @Column 19 | private String username; 20 | 21 | @Column 22 | private String password; 23 | 24 | public Long getId() { 25 | return id; 26 | } 27 | 28 | public void setId(Long id) { 29 | this.id = id; 30 | } 31 | 32 | public String getUsername() { 33 | return username; 34 | } 35 | 36 | public void setUsername(String username) { 37 | this.username = username; 38 | } 39 | 40 | public String getPassword() { 41 | return password; 42 | } 43 | 44 | public void setPassword(String password) { 45 | this.password = password; 46 | } 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /user/core/src/main/java/com/akkafun/user/web/UserController.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.user.web; 2 | 3 | import com.akkafun.user.api.dtos.RegisterDto; 4 | import com.akkafun.user.api.dtos.UserDto; 5 | import com.akkafun.user.domain.User; 6 | import com.akkafun.user.service.UserService; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.http.MediaType; 9 | import org.springframework.web.bind.annotation.RequestBody; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RequestMethod; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import javax.validation.Valid; 15 | 16 | import static com.akkafun.user.api.UserUrl.USER_REGISTER_URL; 17 | 18 | /** 19 | * Created by liubin on 2016/3/29. 20 | */ 21 | @RestController 22 | @RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE) 23 | public class UserController { 24 | 25 | @Autowired 26 | UserService userService; 27 | 28 | @RequestMapping(value = USER_REGISTER_URL, method = RequestMethod.POST) 29 | public UserDto register(@Valid @RequestBody RegisterDto registerDto) { 30 | 31 | User user = userService.register(registerDto); 32 | UserDto userDto = new UserDto(); 33 | userDto.setId(user.getId()); 34 | userDto.setUsername(user.getUsername()); 35 | 36 | return userDto; 37 | } 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /user/core/src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: user 4 | cloud: 5 | config: 6 | uri: ${CONFIG_SERVER_URI:http://localhost:8888} 7 | failFast: true 8 | encrypt: 9 | failOnError: true 10 | -------------------------------------------------------------------------------- /user/core/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | logs/user-service.log 15 | 16 | 17 | logs/user-service-log-%d{yyyy-MM-dd}.gz 18 | 19 | 30 20 | 21 | 22 | %date{yyyy-MM-dd HH:mm:ss} ${PID}: %-5level %logger{0} - %msg%n 23 | 24 | 25 | 26 | 27 | 28 | %date{yyyy-MM-dd HH:mm:ss} ${PID}: %-5level %logger{0} - %msg%n 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /user/core/src/test/java/com/akkafun/common/event/load/FakeAskCouponUse.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.load; 2 | 3 | import org.apache.commons.lang.RandomStringUtils; 4 | 5 | /** 6 | * Created by liubin on 2016/5/30. 7 | */ 8 | public class FakeAskCouponUse extends FakeAskEvent { 9 | 10 | private String id; 11 | 12 | public FakeAskCouponUse() { 13 | this.id = RandomStringUtils.randomAlphanumeric(8); 14 | } 15 | 16 | public String getId() { 17 | return id; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "FakeAskCouponUse{" + 23 | "id='" + id + '\'' + 24 | "} " + super.toString(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /user/core/src/test/java/com/akkafun/common/event/load/FakeAskDeductBalance.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.load; 2 | 3 | import org.apache.commons.lang.RandomStringUtils; 4 | 5 | /** 6 | * Created by liubin on 2016/5/30. 7 | */ 8 | public class FakeAskDeductBalance extends FakeAskEvent { 9 | 10 | private String id; 11 | 12 | public FakeAskDeductBalance() { 13 | this.id = RandomStringUtils.randomAlphanumeric(8); 14 | } 15 | 16 | public String getId() { 17 | return id; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "FakeAskDeductBalance{" + 23 | "id='" + id + '\'' + 24 | "} " + super.toString(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /user/core/src/test/java/com/akkafun/common/event/load/FakeAskEvent.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.load; 2 | 3 | /** 4 | * Created by liubin on 2016/5/30. 5 | */ 6 | public class FakeAskEvent { 7 | } 8 | -------------------------------------------------------------------------------- /user/core/src/test/java/com/akkafun/common/event/load/FakeEventBus.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.load; 2 | 3 | /** 4 | * Created by liubin on 2016/5/30. 5 | */ 6 | public class FakeEventBus { 7 | 8 | public void askUnited(FakeUnitedAskEventCallback callback, FakeAskEvent firstAskEvent, FakeAskEvent secondAskEvent, 9 | FakeAskEvent... remainAskEvents) { 10 | System.out.println(callback.getClass()); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /user/core/src/test/java/com/akkafun/common/event/load/FakeUnitedAskEventCallback.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.event.load; 2 | 3 | /** 4 | * Created by liubin on 2016/5/30. 5 | */ 6 | public interface FakeUnitedAskEventCallback { 7 | 8 | void onSuccess(FakeAskEvent[] askEvents); 9 | 10 | void onFailure(FakeAskEvent[] askEvents); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /user/core/src/test/java/com/akkafun/user/test/TestUserApplication.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.user.test; 2 | 3 | import com.akkafun.base.event.constants.EventType; 4 | import com.akkafun.common.event.config.EventConfiguration; 5 | import com.akkafun.common.event.service.EventActivator; 6 | import com.akkafun.common.spring.BaseConfiguration; 7 | import com.akkafun.common.spring.WebApplication; 8 | import org.springframework.boot.autoconfigure.SpringBootApplication; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Import; 11 | 12 | /** 13 | * Created by liubin on 2016/3/28. 14 | */ 15 | @SpringBootApplication 16 | @Import({BaseConfiguration.class, EventConfiguration.class}) 17 | public class TestUserApplication { 18 | 19 | 20 | /** 21 | * 测试EventBus.sendUnpublishedEvent中调用sendMessage抛出异常会不会导致整个事务回滚 22 | * @param eventActivator 23 | * @return 24 | */ 25 | @Bean 26 | public EventActivator testEventActivator(EventActivator eventActivator) { 27 | 28 | return new EventActivator() { 29 | @Override 30 | public boolean sendMessage(String message, String destination) { 31 | //当遇到TEST_EVENT_SECOND事件时, 抛出异常 32 | if(destination.equals(EventType.NOTIFY_SECOND_TEST_EVENT.toString())) { 33 | throw new RuntimeException("我是异常"); 34 | } 35 | return eventActivator.sendMessage(message, destination); 36 | } 37 | 38 | @Override 39 | public void receiveMessage(Object payload) { 40 | eventActivator.receiveMessage(payload); 41 | } 42 | }; 43 | 44 | 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /user/core/src/test/java/com/akkafun/user/test/UserBaseControllerTest.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.user.test; 2 | 3 | import com.akkafun.common.test.BaseControllerTest; 4 | import org.springframework.boot.test.SpringApplicationConfiguration; 5 | 6 | /** 7 | * Created by liubin on 2016/3/30. 8 | */ 9 | @SpringApplicationConfiguration(classes = TestUserApplication.class) 10 | public abstract class UserBaseControllerTest extends BaseControllerTest { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /user/core/src/test/java/com/akkafun/user/test/UserBaseTest.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.user.test; 2 | 3 | import com.akkafun.common.test.BaseTest; 4 | import org.springframework.boot.test.SpringApplicationConfiguration; 5 | 6 | /** 7 | * Created by liubin on 2016/3/29. 8 | */ 9 | @SpringApplicationConfiguration(classes = TestUserApplication.class) 10 | public abstract class UserBaseTest extends BaseTest{ 11 | } 12 | -------------------------------------------------------------------------------- /user/docs/user-service.sql: -------------------------------------------------------------------------------- 1 | /*==============================================================*/ 2 | /* DBMS name: MySQL 5.0 */ 3 | /* Created on: 2016/8/10 11:33:27 */ 4 | /*==============================================================*/ 5 | 6 | 7 | drop table if exists user; 8 | 9 | /*==============================================================*/ 10 | /* Table: user */ 11 | /*==============================================================*/ 12 | create table user 13 | ( 14 | id bigint unsigned not null auto_increment, 15 | username varchar(100) not null, 16 | password varchar(255) not null, 17 | createTime datetime, 18 | updateTime datetime, 19 | optlock int default 0, 20 | primary key (id) 21 | ); 22 | 23 | -------------------------------------------------------------------------------- /user/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | user-service 6 | 7 | api 8 | core 9 | 10 | pom 11 | 12 | 13 | com.akkafun.mysteam 14 | base 15 | 1.0-SNAPSHOT 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /utils/src/main/java/com/akkafun/common/utils/CustomPreconditions.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.utils; 2 | 3 | import com.akkafun.base.Constants; 4 | import com.akkafun.base.api.CommonErrorCode; 5 | import com.akkafun.base.exception.AppBusinessException; 6 | 7 | /** 8 | * Created by liubin on 2016/6/23. 9 | */ 10 | public class CustomPreconditions { 11 | 12 | public static void assertNotGreaterThanMaxQueryBatchSize(int size) { 13 | if(size > Constants.MAX_BATCH_QUERY_SIZE) throw new AppBusinessException(CommonErrorCode.BAD_REQUEST, 14 | "一次查询的id数量不能超过" + Constants.MAX_BATCH_QUERY_SIZE); 15 | 16 | } 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /utils/src/main/java/com/akkafun/common/utils/StringUtils.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.utils; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | 5 | /** 6 | * Created by liubin on 2016/8/5. 7 | */ 8 | public class StringUtils extends org.apache.commons.lang3.StringUtils { 9 | 10 | 11 | /** 12 | * 截取字符串, 中文按2个字节长度计算 13 | * @param str 14 | * @param n 15 | * @return 16 | */ 17 | public static String abbreviate4Unicode(String str, int n) { 18 | if (str == null)return ""; 19 | if (n <= 0) return str; 20 | try { 21 | return cutString(str, n); 22 | } catch (UnsupportedEncodingException e) { 23 | throw new RuntimeException(e); 24 | } 25 | } 26 | 27 | 28 | private static String cutString(String s, int length) throws UnsupportedEncodingException { 29 | 30 | byte[] bytes = s.getBytes("Unicode"); 31 | int n = 0; // 表示当前的字节数 32 | int i = 2; // 要截取的字节数,从第3个字节开始 33 | for (; i < bytes.length && n < length; i++){ 34 | // 奇数位置,如3、5、7等,为UCS2编码中两个字节的第二个字节 35 | if (i % 2 == 1){ 36 | n++; // 在UCS2第二个字节时n加1 37 | } 38 | else{ 39 | // 当UCS2编码的第一个字节不等于0时,该UCS2字符为汉字,一个汉字算两个字节 40 | if (bytes[i] != 0){ 41 | n++; 42 | } 43 | } 44 | } 45 | // 如果i为奇数时,处理成偶数 46 | if (i % 2 == 1){ 47 | // 该UCS2字符是汉字时,去掉这个截一半的汉字 48 | if (bytes[i - 1] != 0){ 49 | i = i - 1; 50 | } 51 | // 该UCS2字符是字母或数字,则保留该字符 52 | else{ 53 | i = i + 1; 54 | } 55 | } 56 | 57 | String result = new String(bytes, 0, i, "Unicode"); 58 | 59 | if(i < bytes.length && isNotBlank(result)) { 60 | result = result + "..."; 61 | } 62 | 63 | return result; 64 | 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /utils/src/main/java/com/akkafun/common/utils/UpdateByIdFunction.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.utils; 2 | 3 | /** 4 | * Created by liubin on 2016/4/13. 5 | */ 6 | public interface UpdateByIdFunction { 7 | 8 | int execute(Long[] ids, Object... args); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /utils/src/main/java/com/akkafun/common/utils/ZkUtils.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.utils; 2 | 3 | /** 4 | * Created by liubin on 2016/4/20. 5 | */ 6 | public class ZkUtils { 7 | 8 | public static final String ZK_ROOT = "/mysteam"; 9 | 10 | public static String createZkSchedulerLeaderPath(String applicationName) { 11 | return String.format("%s/%s/schedulers", ZK_ROOT, applicationName); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /utils/src/test/java/com/akkafun/common/utils/StringUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.akkafun.common.utils; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.hamcrest.Matchers.is; 6 | import static org.junit.Assert.assertThat; 7 | 8 | /** 9 | * Created by liubin on 2016/8/5. 10 | */ 11 | public class StringUtilsTest { 12 | 13 | @Test 14 | public void test() { 15 | 16 | assertResult("你叫什么名123字啊", 1, ""); 17 | assertResult("你叫什么名123字啊", 2, "你..."); 18 | assertResult("你叫什么名123字啊", 3, "你..."); 19 | assertResult("你叫什么名123字啊", 4, "你叫..."); 20 | assertResult("你叫什么名123字啊", 5, "你叫..."); 21 | assertResult("你叫什么名123字啊", 16, "你叫什么名123字..."); 22 | assertResult("你叫什么名123字啊", 17, "你叫什么名123字啊"); 23 | assertResult("你叫什么名123字啊", 18, "你叫什么名123字啊"); 24 | assertResult("你叫什么名123字啊", 88, "你叫什么名123字啊"); 25 | 26 | assertResult("abcdef", 1, "a..."); 27 | assertResult("abcdef", 2, "ab..."); 28 | assertResult("abcdef", 5, "abcde..."); 29 | assertResult("abcdef", 6, "abcdef"); 30 | assertResult("abcdef", 7, "abcdef"); 31 | 32 | assertResult("你123叫什么名字啊", 3, "你1..."); 33 | assertResult("你123叫什么名字啊", 4, "你12..."); 34 | assertResult("你123叫什么名字啊", 5, "你123..."); 35 | assertResult("你123叫什么名字啊", 6, "你123..."); 36 | assertResult("你123叫什么名字啊", 7, "你123叫..."); 37 | 38 | } 39 | 40 | 41 | private static void assertResult(String str, int n, String result) { 42 | 43 | assertThat(StringUtils.abbreviate4Unicode(str, n), is(result)); 44 | } 45 | 46 | 47 | } 48 | --------------------------------------------------------------------------------