第一版:
1.前言
经常遇到这样的一个需求,前端传的实体类型相同,后端需要根据实体类中的某一个字符串,动态地调用某一个类的方法。
在SpringBoot中,我们可以理解成,一个Controller接口对应多个ServiceImpl,使用这种方式,如果后期需要添加一个功能,仅仅创建一个ServiceImpl就可以满足需求,而不用再额外创建一个Controller接口。
现在假设一个情景,前端传入不同的用户类型,后端返回该用户的任务。
你可能问我,为什么不直接把(用户类型,用户任务)存入数据库?
现在只是一个简单的场景而已,实际中更为复杂,无法直接存入数据库。
2.代码演示
1.定义一个上架接口
public interface UpAndDowmService {
void upProduct();
}
2.定义上架接口调用步骤
public interface UpProductCommonStrategy {
void check();
void process();
void addLog();
}
3.定义抽象类
public abstract class AbstractUpProductCommonStrategy implements UpProductCommonStrategy {
@Override
public void check() {
//相同验证逻辑
System.out.println("相同验证逻辑");
otherCheck();
System.out.println("不同验证逻辑");
}
//主入口
@Override
public void process() {
check();
//不同逻辑方法 other
other();
addLog();
}
@Override
public void addLog() {
}
abstract void other();
abstract void otherCheck();
}
4.个性化实现类1
@Service("barcodeUpProductCommonStrategy")
public class BarcodeUpProductCommonStrategy extends AbstractUpProductCommonStrategy{
//个性化的逻辑
@Override
void other() {
}
//个性化验证
@Override
void otherCheck() {
}
}
5.个性化实现类2
@Service("tscUpProductCommonStrategy")
public class TscUpProductCommonStrategy extends AbstractUpProductCommonStrategy{
@Override
void other() {
}
@Override
void otherCheck() {
}
}
6.枚举(具体某个策略)
public enum StrategyEnum {
barcodeUpProductCommonStrategy,
tscUpProductCommonStrategy
;
}
7.获取某个个性化实现类
@Component
public class UpProdcutContext {
@Resource
Map<String, UpProductCommonStrategy> upProductStrategyMap;
public UpProductCommonStrategy getUpProductCommonStrategy(String type){
return upProductStrategyMap.get(type);
}
}
注:Spring会自动地将形如(@Component后面的名称,实现该接口的类)注入到该upProductStrategyMap中
在启动后,upProductStrategyMap中就存在两个元素,("barcodeUpProductCommonStrategy",TscUpProductCommonStrategy )与("tscUpProductCommonStrategy",TscUpProductCommonStrategy )
getUpProductCommonStrategy方法返回upProductStrategyMap中key=type的UpAndDowmService对象
8.接口实现类
@Service
public class UpAndDowmServiceImpl implements UpAndDowmService {
@Resource
UpProdcutContext upProdcutContext;
@Override
public void upProduct() {
//1.判断策略类型
String strategyType = StrategyEnum.tscUpProductCommonStrategy.toString();
UpProductCommonStrategy upProductStrategy = upProdcutContext.getUpProductCommonStrategy(strategyType);
upProductStrategy.process();
System.out.println(upProductStrategy.getClass());
}
}
第二版:
1.前言
使用反射,以发送订阅消息为例,涉及到多个小程序多个模板id
2.代码演示
@Slf4j
public enum MiniProgramEnum {
EXHIBITION("XINONE","XINONEACCESSTOKENSTRATEGY",
"com.kering.cus.rsvp.subscription.message.center.service.impl.ExhibitionMessageServiceImpl"),
STORE("CRM","CRMACCESSTOKENSTRATEGY",
"com.kering.cus.rsvp.subscription.message.center.service.impl.StoreMessageServiceImpl"),
;
@Getter
private String miniapp;
@Getter
private String strategy;
@Getter
private String clazz;
MiniProgramEnum(String miniapp, String strategy, String clazz) {
this.miniapp = miniapp;
this.strategy = strategy;
this.clazz = clazz;
}
public static String getStrategyByMiniapp(String miniapp){
MiniProgramEnum[] values = MiniProgramEnum.values();
for (MiniProgramEnum t : values) {
if (miniapp.equals(t.getMiniapp())) {
return t.getStrategy();
}
}
return null;
}
public static MessageService getMessageService(String miniapp){
MiniProgramEnum[] values = MiniProgramEnum.values();
try{
for (MiniProgramEnum t : values) {
if (miniapp.equals(t.getMiniapp())) {
Class<?> clazz = Class.forName(t.getClazz());
Object object = SpringUtil.getBean(clazz);
return (MessageService)object;
}
}
}catch (ClassNotFoundException e){
log.error("MiniProgramEnum.getMessageService error:{}",e);
}
return null;
}
}
@Slf4j
public enum MessageActionEnum {
RESERVED("Reserved","getReservedData","预约成功通知"),
EVENT_START("EventStart","getEventStartData","活动开始通知"),
CANCELED("Canceled","getCanceledData","取消预约通知"),
;
@Getter
private String action;
@Getter
private String method;
@Getter
private String desc;
MessageActionEnum(String action,String method, String desc) {
this.action = action;
this.method = method;
this.desc = desc;
}
public static String getMethod(String action){
MessageActionEnum[] values = MessageActionEnum.values();
for (MessageActionEnum t : values) {
if (action.equals(t.getAction())) {
return t.getMethod();
}
}
return null;
}
public static String getDesc(String action){
MessageActionEnum[] values = MessageActionEnum.values();
for (MessageActionEnum t : values) {
if (action.equals(t.getAction())) {
return t.getDesc();
}
}
return null;
}
}
public interface TemplateService {
void sendMessage(BizSubscriptionRecord record, String action);
void sendEventStartMessage(Integer minute,String tenantId);
}
public interface MessageService {
String getReservedData(MessageAccessVo vo);
String getEventStartData(MessageAccessVo vo);
String getCanceledData(MessageAccessVo vo);
}
@Service
@Slf4j
public class ExhibitionMessageServiceImpl implements MessageService {
@Override
public String getReservedData(MessageAccessVo vo) {
//todo业务逻辑。。。
}
@Override
public String getEventStartData(MessageAccessVo vo) {
//todo业务逻辑。。。
}
@Override
public String getCanceledData(MessageAccessVo vo) {
//todo业务逻辑。。。
}
@Service
@Slf4j
public class StoreMessageServiceImpl implements MessageService {
@Override
public String getReservedData(MessageAccessVo vo) {
//todo业务逻辑。。。
}
@Override
public String getEventStartData(MessageAccessVo vo) {
//todo业务逻辑。。。
}
@Override
public String getCanceledData(MessageAccessVo vo) {
//todo业务逻辑。。。
}
}
@Override
@Async
public void sendMessage(BizSubscriptionRecord record,String action){
//todo 省略。。。
try{
MessageService service = MiniProgramEnum.getMessageService("XINONE"));
Method method = service.getClass().getMethod(MessageActionEnum.getMethod(action), MessageAccessVo.class);
log.info("sendMessage Method:{}",MessageActionEnum.getMethod(action));
String data = (String)method.invoke(service,vo);
log.info("sendMessage data:{}",data);
String accessToken = qrcodeMgmtService.getAccessToken(MiniProgramEnum.getStrategyByMiniapp(tpl.getMiniapp())).getData();
String url =String.format(WechatConstant.WEIXIN_MESSAGE,accessToken) ;
String respones = HttpUtil.post(url,data);
log.info("sendMessage respones:{}",respones);
JSONObject responesObject = JSONUtil.parseObj(respones);
if(responesObject.getStr("errcode").equals("0")) {
updateRecord(record,SubscriptionMessageSendStatusEnum.SUCCESS.getValue(), null);
insertMessageLog(record,SubscriptionMessageSendStatusEnum.SUCCESS.getValue(), tpl,data,null);
}else{
updateRecord(record,SubscriptionMessageSendStatusEnum.FAILED.getValue(), respones);
insertMessageLog(record,SubscriptionMessageSendStatusEnum.FAILED.getValue(),tpl,data, respones);
}
}catch (Exception e){
log.info("sendMessage error :{}",e);
}
}