Java反射实现策略模式(改进)

优点

  • 不用考虑业务多或者同一个业务中创建很多类,导致后面的人一时看不懂
  • 可扩展性强
  • 可通过注解命名来约束多级路由,一个类即可管理一个大的业务接口

疑点

  • 至于控制层中的method参数是怎么实现多级路由的,可看我的上一篇(SpringBoot实现过滤器更改请求地址)
  • 比如:http://应用服务地址:8080/api/test/xxx/sss/ddssa/fsa/d表示d是方法名而xxxSssDdssaFsa(驼峰命名)可表示一个大的业务类的名称,最终更改请求路径:http://应用服务地址:8080/api/test/xxx$sss$ddssa$fsa$d
  • 将xxx$sss$ddssa$fsa$d变成一个字符串(也就是method参数),具体怎么改路径,从哪开始截取看业务场合需要

控制层 

 

 @PostMapping("{method}")
    public Object gateway(@PathVariable String method, HttpServletRequest request) {
  
        JSONObject reqParamJSON = OpenApiUtil.getReqParamJSON(request);
      
        Object o;
        try {
          
            if (gatewayService.isSupport(业务应用)) {
                o = gatewayService.execute(method, reqParamJSON);
            } else {
                throw BizException.FORMAT_PARAMETER_ERROR;
            }
      
        } catch (Exception e) {
        
        }
        return o;

    }

本文重点讲解execute方法,实现思想,一些基础入口代码怎么实现都行

 接口层 


public interface IApiGatewayService {

    /**
     * 前置校验
     */
    boolean isSupport(AcApp app);

    /**
     * 业务逻辑执行方法
     */
    Object execute(String method, JSONObject jsonObject) throws Exception;


}

 前置校验方法可选择不看,执行方法里有异常抛出、入参的json、返回的实体对象

  核心代码

  1. 继承该抽象类
  2. 编写自己的业务逻辑方法(方法名需要跟路由的最后名称相同)
  3. 如果出现多级路由,加上@Service(name="xxxSssDdssaFsa")
public abstract class AbstractApiGatewayService implements IApiGatewayService {

    protected Logger log = LoggerFactory.getLogger(this.getClass());

    @Override
    public boolean isSupport(AcApp app) {
        return true;
    }

    @Override
    public Object execute(String method, JSONObject jsonObject) throws Exception {
        Pair<Class<?>, String> ret = findClass(method);
        Class<?> c = ret.getLeft();
        String newMethod = ret.getRight();
        Method methods = c.getDeclaredMethod(newMethod, JSONObject.class);
        methods.setAccessible(true);
        return methods.invoke(SpringContextHolder.getBean(c), jsonObject);
    }

    /**
     * 根据路由名称获取对应的实现类
     */
    private Pair<Class<?>, String> findClass(String method) {
        List<Class<?>> ret = ListUtil.newArrayList();
        Map<String, IApiGatewayService> beans = SpringContextHolder.getBeansOfType(IApiGatewayService.class);
        List<IApiGatewayService> serviceList = ListUtil.newArrayList(beans.values());
        // 查找方法名称
        String selectMethod = method;
        // 是否存在多级路由
        if (CharSequenceUtil.contains(method, StringPool.DOLLAR)) {
            String[] split = method.split("\\" + StringPool.DOLLAR);
            List<String> methodAllList = ListUtil.newArrayList(Arrays.asList(split));
            selectMethod = ListUtil.getLast(methodAllList);
            methodAllList.remove(methodAllList.size() - 1);
            // 得到beanName(驼峰命名),不连续名称不进行转换,比如:(多个)user,name => userName | (单个)user => user
            String beanName = CharSequenceUtil.toCamelCase(String.join(StringPool.UNDERSCORE, methodAllList));
            // 过滤
            serviceList = serviceList.stream()
                    .filter(item -> {
                        Class<? extends IApiGatewayService> aClass = item.getClass();
                        Service annotation = aClass.getAnnotation(Service.class);
                        return null != annotation
                                && CharSequenceUtil.isNotBlank(annotation.value())
                                && CharSequenceUtil.equals(annotation.value(), beanName);
                    })
                    .collect(Collectors.toList());
        }

        String finalSelectMethod = selectMethod;
        serviceList.forEach(item -> {
            Method[] methods = item.getClass().getDeclaredMethods();
            for (Method items : methods) {
                if (CharSequenceUtil.equals(items.getName(), finalSelectMethod)) {
                    ret.add(items.getDeclaringClass());
                }
            }
        });
        return Pair.of(ListUtil.getFirst(ret), finalSelectMethod);
    }
}

前提是服务层的类都需要注入到Spring容器中,不然通过注解找不到类,就会报错

 服务层

@Service
@Primary
public class ApiCommonServiceImpl extends AbstractApiGatewayService {

    private Object count(JSONObject reqParamJSON) {
        return 66666;
    }

}

 表示请求路径:http://应用服务地址:8080/api/test/count

如果多个业务方法方法名称保持跟路径最后相同即可(解决了策略模式需要建很多类)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值