-
Notifications
You must be signed in to change notification settings - Fork 34
Pillar
Yizzuide edited this page Nov 3, 2020
·
10 revisions
The Pillar provide various solutions to the if/else split problem. it can be apply in both pure java and Spring MVC.
Pillar模块提供了各种用于拆分if/else嵌套地狱的问题,可以应用在纯Java环境或Spring MVC。
<dependency>
<groupId>com.github.yizzuide</groupId>
<artifactId>milkomeda-spring-boot-starter</artifactId>
<version>${milkomeda-last-version}</version>
</dependency>
@EnablePillar
@SpringBootApplication
public class MilkomedaDemoApplication {
public static void main(String[] args) {
SpringApplication.run(MilkomedaDemoApplication.class, args);
}
}
// Add `@PillarEntryHandler` for handle entry point, the tag `market` can be using arbitrary business name.
// 添加`@PillarEntryHandler`用于处理节点派发,`market`的tag名可以是任意的业务名。
@PillarEntryHandler(tag = "market")
@Component
public class MarketServiceImpl implements MarketService {
@PillarEntryPoint(code = "api.v1.check")
public String check(Map<String, Object> params) {
log.info("check: {}", params);
return "OK";
}
@PillarEntryPoint(code = "api.v1.push")
public String push(Map<String, Object> params) {
log.info("push: {}", params);
return "OK";
}
}
@RequestMapping("market/api/{method}")
public String handleCallback(@RequestParam Map<String, Object> params, @PathVariable("method") String code) {
// The first param "market" is corresponds to the business name above,second param "code" is corresponds to the entry point above.
// 第一个参数“market”对应上面的业务名(business name),第二个参数“code”对应上面的入口点(entry point)。
return PillarEntryDispatcher.dispatch("market", code, params);
}
The interface PillarType
map identifier
for key and pillarType
name for value.
PillarType
接口绑定了identifier
标识符和pillarType
路径名。
@Getter
@AllArgsConstructor
public enum TradeType implements PillarType {
PAY(1, "PAY"),
RECHARGE(2, "RECHARGE"),
;
private final Integer type;
private final String typeName;
@Override
public Object identifier() {
return type;
}
@Override
public String pillarType() {
return typeName;
}
}
The Pillar<P, R>
is a branch of a different business path which P
is in parameter,R
is out result, the PillarExecutor
is path executor.
Pillar<P, R>
是是一个不同业务路径分支,其中的P
表示入参,R
表示结果数据,PillarExecutor
为路径执行器。
@Configuration
public class PillarConfig {
// Auto inject Pillar type component
@Autowired
private List<Pillar<Map<String, String>, ReturnData>> pillars;
@Bean
public PillarExecutor<Map<String, String>, ReturnData> pillarExecutor() {
PillarExecutor<Map<String, String>, ReturnData> pillarExecutor = new PillarExecutor<>();
pillarExecutor.addPillarList(pillars);
return pillarExecutor;
}
}
@Component
public class PayPillar implements Pillar<Map<String, String>, ReturnData> {
@Override
public String supportType() {
// return current pillar type name in this hook method
// 返回勾方法需要的pillarType路径名
return TradeType.PAY.getTypeName();
}
@Override
public void process(Map<String, String> params, ReturnData result) {
log.info("invoke for pay:{}", params);
// Some bussiness code..
// Add response data
result.setCode("200");
result.setSuccess(true);
}
}
@Component
public class RechargePillar implements Pillar<Map<String, String>, ReturnData> {
@Override
public String supportType() {
return TradeType.RECHARGE.getTypeName();
}
@Override
public void process(Map<String, String> params, ReturnData result) {
log.info("invoke for recharge:{}", params);
// Some bussiness code..
// Add response data
result.setCode("200");
result.setSuccess(true);
}
}
@Autowired
private PillarExecutor<Map<String, String>, ReturnData> pillarExecutor;
@RequestMapping("bankcardPrepay")
public ResponseEntity<ReturnData> bankcardPrepay(@RequestParam Map<String, String> params) {
// Get pillar identifier
// 获取标识符
String type = params.get("type");
// Get pillar type name from pillar identifier
// 通过标识符从类型映射中解析出路径名
String pillarType = PillarRecognizer.typeOf(TradeType.values(), type);
ReturnData returnData = new ReturnData();
if (pillarType == null) {
returnData.setCode("400");
returnData.setSuccess(false);
returnData.setMsg("type param error");
return ResponseEntity.ok(returnData);
}
// Execute pillar type path
// 执行业务路径分流
pillarExecutor.execute(pillarType, params, returnData);
return ResponseEntity.ok(returnData);
}
public enum MarketCallbackState implements PillarState {
approveFeedback(0) {
@Override
public Map<String, Object> buildParams(Map<String, Object> data) {
// build and return params map...
}
},
orderFeedback(2) {
@Override
public Map<String, Object> buildParams(Map<String, Object> data) {
// build and return params map...
}
};
private final int state;
MarketCallbackState(int state) {
this.state = state;
}
@Override
public String getState() {
return String.valueOf(state);
}
public abstract Map<String, Object> buildParams(Map<String, Object> data);
}
Map<String, Object> data = new HashMap<>();
// The method `getDynamicType` is example of get from data source, such as mysql.
// 方法`getDynamicType`是从数据源获取记录type,比如: mysql。
// Add business data...
Map<String, Object> params = PillarState.of(String.valueOf(getDynamicType()), MarketCallbackState.class,
MarketCallbackState.values()).buildParams(data);