Spring Cloud ApiController

在Spring Cloud项目开发中,一般的目录结构


截屏2022-08-09 13.50.44.png

各个模块是做什么的就不用多说了,主要是web模块,比如我们实现一个登陆功能,首先要在Web模块下面新建一个LoginController,然后再后写接口层和实现层,然后我们需要查询用户又要新建一个UserController,新增加一个功能就要新建一个Controller,那么我不想建这么多的Controller,我想用一个Controller来统一调用接口可不可以,答案是可以。这就是我们接下来要讲的ApiController

ApiController

作用,不用每个功能都写一个Controller,只要写在一个公共的模块里面,其他模块引入就可以了

优点:因为是统一的Controller入口,所以可以做一些拦截,鉴权操作

下面只提供一些核心代码和思路供大家参考

@RestController
@RequestMapping({"/api"})
public class ApiController implements ApplicationContextAware {
    private static final Logger log = LoggerFactory.getLogger(ApiController.class);
    private ApplicationContext applicationContext;
    private static Map serviceCache = new HashMap();

    public ApiController() {
    }

    @CrossOrigin
    @RequestMapping(
            value = {"/{serviceName}/{method}"},
            method = {RequestMethod.POST}
    )

    /**
     * Api入口
     */
    public Object post(@PathVariable("serviceName") String serviceName, @PathVariable("method") String method, @RequestBody String params, HttpServletRequest request, HttpServletResponse response) {
        long startTime = System.currentTimeMillis();
        ServletThreadLocal.put(request, response);
        Object object = this.doService(serviceName, method, params);
        long executeTime = System.currentTimeMillis() - startTime;
        log.info("调用服务[{}.{}]执行时间:{}ms", new Object[]{serviceName, method, executeTime});
        return object;
    }

    /**
     * doService
     *
     * @param serviceName
     * @param method
     * @param params
     * @return
     */
    private Object doService(String serviceName, String method, String params) {
        Object serviceBean = this.getServiceBean(serviceName);
        Result commonResult = null;
        if (serviceBean == null) {
            commonResult = Result.fail(ResultCodeEnum.SERVICE_NOT_FOUND.getDesc());
            log.info("调用服务[{}.{}]响应结果:{}", new Object[]{serviceName, method, JSONObject.toJSONString(commonResult.toString())});
            return commonResult;
        } else {
            Method currentMethod = this.getInvokeMethod(serviceBean, method);
            //方法不存在
            if (currentMethod == null) {
                commonResult = Result.fail(ResultCodeEnum.METHOD_NOT_FOUND.getDesc());
                log.info("调用服务[{}.{}]响应结果:{}", new Object[]{serviceName, method, JSONObject.toJSONString(commonResult.toString())});
                return commonResult;
            } else {
                Type[] paramTypes = currentMethod.getGenericParameterTypes();
                if (paramTypes.length != 0 && paramTypes.length <= 1) {
                    CallTypeEnum callType = CallTypeEnum.REAL;
                    BaseParam baseParam = null;

                    try {
                        //获取入参
                        Object inputParam = JSONObject.parseObject(params, paramTypes[0]);
                        baseParam = (BaseParam) inputParam;
                        log.info("调用服务[{}.{}]请求参数:{}", new Object[]{serviceName, method, JSONObject.toJSONString(inputParam)});

                        callType = baseParam.getCallType();
                        //判断是真实调用还是mock调用,mock调用自己实现
                        if (callType == CallTypeEnum.REAL) {
                            //获取返回结果
                            Object callResult = currentMethod.invoke(serviceBean, inputParam);
                            //判断返回结果类型
                            if (!(callResult instanceof Result)) {
                                throw new RuntimeException("接口返回类型必须为[com.xxx.base.bean.Result]类型");
                            }
                            commonResult = (Result) callResult;
                            log.info("调用服务[{}.{}]响应结果:{}", new Object[]{serviceName, method, JSONObject.toJSONString(commonResult)});
                            return commonResult;
                        }
                    } catch (Exception var17) {
                        commonResult = Result.buildFail(ResultCodeEnum.FAIL.getDesc());
                        log.error("服务[{}.{}]处理失败", new Object[]{serviceName, method, var17});
                    }
                } else {
                    log.info("调用服务[{}.{}]响应结果:{}", new Object[]{serviceName, method, "服务定义形参个数只能为一个"});
                    return Result.buildFail("服务定义形参个数只能为一个");
                }
            }
        }
        return commonResult;
    }

    /**
     * 获取ServiceBean
     *
     * @param serviceName
     * @return
     */
    private Object getServiceBean(String serviceName) {
        Object serviceBean = serviceCache.get(serviceName);
        try {
            if (serviceBean == null) {
                if (serviceName.contains(".")) {
                    Class apiClass = null;

                    try {
                        apiClass = Class.forName(serviceName);
                        serviceBean = this.applicationContext.getBean(apiClass);
                    } catch (ClassNotFoundException var5) {
                        log.error("获取服务[" + serviceName + "]出错", var5);
                    } catch (Exception var6) {
                        log.error("获取服务[" + serviceName + "]出错", var6);
                    }
                } else {
                    serviceBean = this.applicationContext.getBean(serviceName);
                }
            }
        } catch (Exception var7) {
            log.error("获取服务[" + serviceName + "]出错", var7);
        }

        if (serviceBean != null) {
            serviceCache.put(serviceName, serviceBean);
        }
        return serviceBean;
    }

    /**
     * 获取方法
     *
     * @param serviceBean
     * @param method
     * @return
     */
    private Method getInvokeMethod(Object serviceBean, String method) {
        Method currentMethod = null;
        Method[] methods = serviceBean.getClass().getDeclaredMethods();
        Method[] var5 = methods;
        int var6 = methods.length;

        for (int var7 = 0; var7 < var6; ++var7) {
            Method method1 = var5[var7];
            if (method1.getName().equals(method)) {
                currentMethod = method1;
            }
        }

        return currentMethod;
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
public class ServletThreadLocal {
    private static ThreadLocal requestThreadLocal = new ThreadLocal();
    private static ThreadLocal responseThreadLocal = new ThreadLocal();

    public ServletThreadLocal() {
    }

    public static HttpServletRequest getRequest() {
        return (HttpServletRequest)requestThreadLocal.get();
    }

    public static HttpServletResponse getResponse() {
        return (HttpServletResponse)responseThreadLocal.get();
    }

    public static void putRequest(HttpServletRequest request) {
        requestThreadLocal.set(request);
    }

    public static void putResponse(HttpServletResponse response) {
        responseThreadLocal.set(response);
    }

    public static void put(HttpServletRequest request, HttpServletResponse response) {
        putRequest(request);
        putResponse(response);
    }
}

Api模块

public interface OrderServiceFacade {
    Result getOrderById(OrderParam param);
}

Service模块

@Service("orderServiceFacade")
public class OrderServiceFacadeImpl implements OrderServiceFacade {

   @Resource
   OrderMainMapper orderMainMapper;

   @Override
   public Result getOrderById(OrderParam param){
}

这样就不需要我们在写Controller了

接口调用

http://localhost:9091/api/orderServiceFacade/getOrderById

你可能感兴趣的:(Spring Cloud ApiController)