Skip to content

Commit ca9a337

Browse files
committed
更新一些分享Demo
1 parent e94aae1 commit ca9a337

File tree

127 files changed

+6023
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

127 files changed

+6023
-0
lines changed

source code/buckpal-update/.gitignore

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
HELP.md
2+
.gradle
3+
build/
4+
!gradle/wrapper/gradle-wrapper.jar
5+
6+
### STS ###
7+
.apt_generated
8+
.classpath
9+
.factorypath
10+
.project
11+
.settings
12+
.springBeans
13+
.sts4-cache
14+
15+
### IntelliJ IDEA ###
16+
.idea
17+
*.iws
18+
*.iml
19+
*.ipr
20+
21+
### NetBeans ###
22+
/nbproject/private/
23+
/nbbuild/
24+
/dist/
25+
/nbdist/
26+
/.nb-gradle/
27+
28+
### VS Code ###
29+
.vscode/
+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
plugins {
2+
id 'org.springframework.boot' version '2.4.3'
3+
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
4+
}
5+
6+
7+
group = 'io.reflectoring.buckpal'
8+
version = '0.0.1-SNAPSHOT'
9+
10+
apply plugin: 'java'
11+
apply plugin: 'io.spring.dependency-management'
12+
apply plugin: 'java-library'
13+
14+
repositories {
15+
mavenCentral()
16+
}
17+
18+
compileJava {
19+
sourceCompatibility = 11
20+
targetCompatibility = 11
21+
}
22+
23+
dependencies {
24+
compileOnly 'org.projectlombok:lombok'
25+
annotationProcessor 'org.projectlombok:lombok'
26+
27+
implementation ('org.springframework.boot:spring-boot-starter-web')
28+
implementation 'org.springframework.boot:spring-boot-starter-validation'
29+
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
30+
31+
testImplementation('org.springframework.boot:spring-boot-starter-test') {
32+
exclude group: 'junit' // excluding junit 4
33+
}
34+
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.0.1'
35+
testImplementation 'org.mockito:mockito-junit-jupiter:2.23.0'
36+
testImplementation 'com.tngtech.archunit:archunit:0.16.0'
37+
testImplementation 'org.junit.platform:junit-platform-launcher:1.4.2'
38+
testImplementation 'com.h2database:h2'
39+
40+
runtimeOnly 'com.h2database:h2'
41+
42+
}
43+
44+
test {
45+
useJUnitPlatform()
46+
}
47+
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
distributionBase=GRADLE_USER_HOME
2+
distributionPath=wrapper/dists
3+
#distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip
4+
distributionUrl=file\:///F:/gradle/gradle-6.7-all.zip
5+
zipStoreBase=GRADLE_USER_HOME
6+
zipStorePath=wrapper/dists
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.reflectoring.buckpal;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
6+
@SpringBootApplication
7+
public class BuckPalApplication {
8+
9+
public static void main(String[] args) {
10+
SpringApplication.run(BuckPalApplication.class, args);
11+
}
12+
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package io.reflectoring.buckpal;
2+
3+
import io.reflectoring.buckpal.account.application.service.MoneyTransferProperties;
4+
import io.reflectoring.buckpal.account.domain.Money;
5+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
6+
import org.springframework.context.annotation.Bean;
7+
import org.springframework.context.annotation.Configuration;
8+
9+
@Configuration
10+
@EnableConfigurationProperties(BuckPalConfigurationProperties.class)
11+
public class BuckPalConfiguration {
12+
13+
/**
14+
* Adds a use-case-specific {@link MoneyTransferProperties} object to the application context. The properties
15+
* are read from the Spring-Boot-specific {@link BuckPalConfigurationProperties} object.
16+
*/
17+
@Bean
18+
public MoneyTransferProperties moneyTransferProperties(BuckPalConfigurationProperties buckPalConfigurationProperties){
19+
return new MoneyTransferProperties(Money.of(buckPalConfigurationProperties.getTransferThreshold()));
20+
}
21+
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.reflectoring.buckpal;
2+
3+
import lombok.Data;
4+
import org.springframework.boot.context.properties.ConfigurationProperties;
5+
6+
@Data
7+
@ConfigurationProperties(prefix = "buckpal")
8+
public class BuckPalConfigurationProperties {
9+
10+
private long transferThreshold = Long.MAX_VALUE;
11+
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.reflectoring.buckpal.account.adapter.in.web;
2+
3+
import io.reflectoring.buckpal.account.application.port.in.SendMoneyUseCase;
4+
import io.reflectoring.buckpal.account.application.port.in.SendMoneyCommand;
5+
import io.reflectoring.buckpal.common.WebAdapter;
6+
import io.reflectoring.buckpal.account.domain.Account.AccountId;
7+
import io.reflectoring.buckpal.account.domain.Money;
8+
import lombok.RequiredArgsConstructor;
9+
import org.springframework.web.bind.annotation.PathVariable;
10+
import org.springframework.web.bind.annotation.PostMapping;
11+
import org.springframework.web.bind.annotation.RestController;
12+
13+
@WebAdapter
14+
@RestController
15+
@RequiredArgsConstructor
16+
class SendMoneyController {
17+
18+
private final SendMoneyUseCase sendMoneyUseCase;
19+
20+
@PostMapping(path = "/accounts/send/{sourceAccountId}/{targetAccountId}/{amount}")
21+
void sendMoney(
22+
@PathVariable("sourceAccountId") Long sourceAccountId,
23+
@PathVariable("targetAccountId") Long targetAccountId,
24+
@PathVariable("amount") Long amount) {
25+
26+
SendMoneyCommand command = new SendMoneyCommand(
27+
new AccountId(sourceAccountId),
28+
new AccountId(targetAccountId),
29+
Money.of(amount));
30+
31+
sendMoneyUseCase.sendMoney(command);
32+
}
33+
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package io.reflectoring.buckpal.account.application.port.in;
2+
3+
import io.reflectoring.buckpal.account.domain.Account.AccountId;
4+
import io.reflectoring.buckpal.account.domain.Money;
5+
6+
public interface GetAccountBalanceQuery {
7+
8+
Money getAccountBalance(AccountId accountId);
9+
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package io.reflectoring.buckpal.account.application.port.in;
2+
3+
import io.reflectoring.buckpal.account.domain.Account.AccountId;
4+
import io.reflectoring.buckpal.account.domain.Money;
5+
import io.reflectoring.buckpal.common.SelfValidating;
6+
import lombok.EqualsAndHashCode;
7+
import lombok.Value;
8+
9+
import javax.validation.constraints.NotNull;
10+
11+
@Value
12+
@EqualsAndHashCode(callSuper = false)
13+
public
14+
class SendMoneyCommand extends SelfValidating<SendMoneyCommand> {
15+
16+
@NotNull
17+
private final AccountId sourceAccountId;
18+
19+
@NotNull
20+
private final AccountId targetAccountId;
21+
22+
@NotNull
23+
private final Money money;
24+
25+
public SendMoneyCommand(
26+
AccountId sourceAccountId,
27+
AccountId targetAccountId,
28+
Money money) {
29+
this.sourceAccountId = sourceAccountId;
30+
this.targetAccountId = targetAccountId;
31+
this.money = money;
32+
this.validateSelf();
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package io.reflectoring.buckpal.account.application.port.in;
2+
3+
import io.reflectoring.buckpal.account.domain.Account.AccountId;
4+
import io.reflectoring.buckpal.account.domain.Money;
5+
import io.reflectoring.buckpal.common.SelfValidating;
6+
7+
public interface SendMoneyUseCase {
8+
9+
boolean sendMoney(SendMoneyCommand command);
10+
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package io.reflectoring.buckpal.account.application.service;
2+
3+
import java.time.LocalDateTime;
4+
5+
import io.reflectoring.buckpal.account.application.port.in.GetAccountBalanceQuery;
6+
import io.reflectoring.buckpal.account.application.port.out.LoadAccountPort;
7+
import io.reflectoring.buckpal.account.domain.Account.AccountId;
8+
import io.reflectoring.buckpal.account.domain.Money;
9+
import lombok.RequiredArgsConstructor;
10+
11+
@RequiredArgsConstructor
12+
class GetAccountBalanceService implements GetAccountBalanceQuery {
13+
14+
private final LoadAccountPort loadAccountPort;
15+
16+
@Override
17+
public Money getAccountBalance(AccountId accountId) {
18+
return loadAccountPort.loadAccount(accountId, LocalDateTime.now())
19+
.calculateBalance();
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.reflectoring.buckpal.account.application.service;
2+
3+
import io.reflectoring.buckpal.account.domain.Money;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Data;
6+
import lombok.NoArgsConstructor;
7+
8+
/**
9+
* Configuration properties for money transfer use cases.
10+
*/
11+
@Data
12+
@AllArgsConstructor
13+
@NoArgsConstructor
14+
public class MoneyTransferProperties {
15+
16+
private Money maximumTransferThreshold = Money.of(1_000_000L);
17+
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.reflectoring.buckpal.account.application.service;
2+
3+
import io.reflectoring.buckpal.account.application.port.out.AccountLock;
4+
import io.reflectoring.buckpal.account.domain.Account.AccountId;
5+
import org.springframework.stereotype.Component;
6+
7+
@Component
8+
class NoOpAccountLock implements AccountLock {
9+
10+
@Override
11+
public void lockAccount(AccountId accountId) {
12+
// do nothing
13+
}
14+
15+
@Override
16+
public void releaseAccount(AccountId accountId) {
17+
// do nothing
18+
}
19+
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package io.reflectoring.buckpal.account.application.service;
2+
3+
import io.reflectoring.buckpal.account.application.port.in.SendMoneyCommand;
4+
import io.reflectoring.buckpal.account.application.port.in.SendMoneyUseCase;
5+
import io.reflectoring.buckpal.account.application.port.out.AccountLock;
6+
import io.reflectoring.buckpal.account.application.port.out.LoadAccountPort;
7+
import io.reflectoring.buckpal.account.application.port.out.UpdateAccountStatePort;
8+
import io.reflectoring.buckpal.common.UseCase;
9+
import io.reflectoring.buckpal.account.domain.Account;
10+
import io.reflectoring.buckpal.account.domain.Account.AccountId;
11+
import lombok.RequiredArgsConstructor;
12+
13+
import javax.transaction.Transactional;
14+
import java.time.LocalDateTime;
15+
16+
@RequiredArgsConstructor
17+
@UseCase
18+
@Transactional
19+
public class SendMoneyService implements SendMoneyUseCase {
20+
21+
private final LoadAccountPort loadAccountPort;
22+
private final AccountLock accountLock;
23+
private final UpdateAccountStatePort updateAccountStatePort;
24+
private final MoneyTransferProperties moneyTransferProperties;
25+
26+
@Override
27+
public boolean sendMoney(SendMoneyCommand command) {
28+
29+
checkThreshold(command);
30+
31+
LocalDateTime baselineDate = LocalDateTime.now().minusDays(10);
32+
33+
Account sourceAccount = loadAccountPort.loadAccount(
34+
command.getSourceAccountId(),
35+
baselineDate);
36+
37+
Account targetAccount = loadAccountPort.loadAccount(
38+
command.getTargetAccountId(),
39+
baselineDate);
40+
41+
AccountId sourceAccountId = sourceAccount.getId()
42+
.orElseThrow(() -> new IllegalStateException("expected source account ID not to be empty"));
43+
AccountId targetAccountId = targetAccount.getId()
44+
.orElseThrow(() -> new IllegalStateException("expected target account ID not to be empty"));
45+
46+
accountLock.lockAccount(sourceAccountId);
47+
if (!sourceAccount.withdraw(command.getMoney(), targetAccountId)) {
48+
accountLock.releaseAccount(sourceAccountId);
49+
return false;
50+
}
51+
52+
accountLock.lockAccount(targetAccountId);
53+
if (!targetAccount.deposit(command.getMoney(), sourceAccountId)) {
54+
accountLock.releaseAccount(sourceAccountId);
55+
accountLock.releaseAccount(targetAccountId);
56+
return false;
57+
}
58+
59+
updateAccountStatePort.updateActivities(sourceAccount);
60+
updateAccountStatePort.updateActivities(targetAccount);
61+
62+
accountLock.releaseAccount(sourceAccountId);
63+
accountLock.releaseAccount(targetAccountId);
64+
return true;
65+
}
66+
67+
private void checkThreshold(SendMoneyCommand command) {
68+
if(command.getMoney().isGreaterThan(moneyTransferProperties.getMaximumTransferThreshold())){
69+
throw new ThresholdExceededException(moneyTransferProperties.getMaximumTransferThreshold(), command.getMoney());
70+
}
71+
}
72+
73+
}
74+
75+
76+
77+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package io.reflectoring.buckpal.account.application.service;
2+
3+
import io.reflectoring.buckpal.account.domain.Money;
4+
5+
public class ThresholdExceededException extends RuntimeException {
6+
7+
public ThresholdExceededException(Money threshold, Money actual) {
8+
super(String.format("Maximum threshold for transferring money exceeded: tried to transfer %s but threshold is %s!", actual, threshold));
9+
}
10+
11+
}

0 commit comments

Comments
 (0)