EOS Low-Code Platform 8 EOS Low-Code Platform 8
产品简介
学习指南
更新说明
安装与集成
初见EOS
低代码开发手册
专业代码开发手册
专题场景实战
公共服务框架
应用运行治理
升级手册
常见问题
  • sdk集成方案
  • 常见问题
  • SDK开发说明
  • 公共方法说明
  • Afc sdk实现示例说明

# SDK集成方案

应用远程调用模式,即集成SDK,应用集成SDK实际是发送rest请求远程调用AFCenter。

注:应用集成SDK前提是该应用项目为EOS项目且版本为8.1.2版本(包含)以上。

  • 开发依赖包
    <dependency>
		<groupId>com.primeton.gocom</groupId>
		<artifactId>com.primeton.gocom.afcenter.sdk</artifactId>
		<version>8.2.1</version>
	</dependency>
  • 配置详情

    网关集成AFCenter的SDK共有两种模式:

    1.直接在项目配置文件中使用ip加端口模式完成AFCenter的SDK接口调用,如下所示:

afc.application.name=127.0.0.1:8081
afc.application.tenant=sys_tenant
afc.application.appCode=AFCenter
afc.application.appSecret=b771a0ad37c34baeab2b6f73fbebcabd

tenant为系统默认租户,appCode为系统初始化应用编码,appSecret为改应用密匙,都可使用admin账号登录AFCenter平台后获取。

  1. 在项目配置文件中使用nacos服务名模式完成AFCenter的SDK接口调用,如下所示:
afc.application.name=AFCENTER
afc.application.tenant=sys_tenant
afc.application.appCode=AFCenter
afc.application.appSecret=b771a0ad37c34baeab2b6f73fbebcabd

afc.application.name的值为AFCenter服务启动后在nacos中注册的服务名。

注:使用nacos服务名模式集成AFCenter的SDK需要与AFCenter配置同一nacos地址。

  • 接口说明

    com.primeton.gocom.afcenter.sdk.api包中接口即可。

  • 使用方式

直接使用@Autowired 方式注入IAFCClient,再get相应API类后再调用对应的API方法。

也可以使用AFCClientFactory去获取IAFCClient

IAFCClient afcClient=AFCClientFactory.getInstance().createAFCClient();
@RestController
public class TestController {

 	@Autowired
	private IAFCClient afcClient;

	@GetMapping(value = "/api/user")
	public User getAfcApiUser() {
		IUserAPI userApi = afcClient.getUserAPI();
		User user = userApi.findUserByCode("sysadmin");
		return user;
	}

}

# 常见问题

应用集成AFCenter的SDK的过程中容易出现的问题:

1.AFCenter的SDK版本依赖问题:

目前版本已更新为8.2.1-SNAPSHOT,后续版本变更文档中会及时更新。

2.应用项目集成SDK后,调用SDK接口出现401状态码,AFCenter日志打印提示访问该接口前未登录问题:

首先确保AFCenter平台用户账号已登录,通过postman调用应用的接口(headers中传入Authorization,Authorization值是在afc登陆接口返回值中获取的)。

其次遇到session共享的问题,请排查以下几点:

a. 应用与AFCenter是否属于同系统。

b. redis是否使用同一个。

c. user-config.xml中是否开启系统内共享开关。

 <group name="CacheForUserObject">
            <configValue key="IsSystemCache">true</configValue>
            <configValue key="CacheMode">REPL_ASYNC</configValue>
            <configValue key="IsSystemShare">true</configValue>
        </group>

d. 是否加入登录接口过滤白名单

注:afcenter的user-config.xml文件中登录过滤白名单要加入/api/afc/afc-proxy/*;


<group name="Login-Filter">
            <!-- pages that can be accessed by any one including those not login -->
            <configValue
                    key="Exclude">/api/afc/afc-proxy/*,/api/afc/oauth2/*,/api/afc/login/third-party/auth,/api/afc/login/third-party/qrConnect,/afc-proxy/*,/api/afc/validation-code,/swagger-ui.html,/v2/api-docs,/webjars/*,/swagger-resources/*,/afc,/afc/,/api/afc/login,/api/afc/login/password/key,/actuator/*,/om/*,/common.remote,
                /jmxDefault.jmx,/common.download</configValue>
            <!-- <configValue key="Include">*.flow,*.flowx,*.jsp,*.html,*.ajax,*.ext,*.action,*.beanx</configValue> -->
            <configValue key="Include">/*</configValue>
            <!-- the page to display when user not login -->
            <configValue key="LoginPage"></configValue>
        </group>

# SDK开发说明

# 公共方法说明

1、com.primeton.gocom.afcenter.common.sdk.SdkClientFactory:sdk客户端工厂

    /**
	 * 注册本地sdk api实现
	 * 
	 * @param sdkApiClass sdk接口类
	 * @param sdkApiLocalImpl sdk本地实现对象
	 */
	public static void registLocalSdkApiImpl(Class sdkApiClass, Object sdkApiLocalImpl);

    /**
	 * 获取客户端
	 * 
	 * @param clientClass 客户端类
	 * @param starterClassName starter配置的类名,用于判断是本地,还是远程
	 * @param sdkApiRemoteMethodInvocationHandler 远程实现的方法拦截对象
	 * @return 客户端类
	 */
	public static <T> T getClientProxy(Class<T> clientClass, String starterClassName, IMethodInvocationHandler sdkApiRemoteMethodInvocationHandler);

2、com.primeton.gocom.afcenter.common.sdk.AbstractSdkApiRemoteMethodInvocationHandler:sdk api 远程方法调用抽象实现
   
    // 路径前缀
	protected String pathPrefix = null;
	
	// 服务名或者应用名(nacos对应)
	protected String serviceName = null;
	
	// header
	protected Map<String, String> mapHeader = new HashMap<>();

# Afc sdk实现示例说明

1、afc sdk api,使用用户的IUserAPI示例

1) 接口定义(在sdk模块中):
    要求:I+资源名+API

    public interface IUserAPI {

        User findUserByCode(String userCode);

        。。。

    }

2)本地实现(在sdk模块中)

    public class UserLocalImpl implements IUserAPI {


        private IUserService userService;

        public UserLocalImpl() {
            this.userService = EOS8ApplicationContext.INSTANCE.getBean(IUserService.class);
            // 可以在这里注册本地实现,也可以在后续的factory中
            // SdkClientFactory.registLocalSdkApiImpl(IUserAPI.class, this);
        }

        /**
        * 根据用户code 查询用户信息
        *
        * @param userCode 用户code
        * @return 用户实体
        */
        @Override
        public User findUserByCode(String userCode) {
            return userService.findUserByCode(userCode, StatusEum.ENABLE.getCode());
        }

        。。。

    }

3)远程实现(在restproxy模块中):
     要求,httpPath是资源名(小写)/方法名(-连接), http方法是post,参数是MultiRequestBody类型。

    @ApiIgnore
    @RestController
    @RequestMapping(value = SDK_URL_PREFIX + "/user", consumes = {APPLICATION_JSON_UTF8_VALUE}, produces = {APPLICATION_JSON_UTF8_VALUE})
    public class UserProxyController implements IUserAPI {

        @Autowired
        private IUserService userService;

        /**
        * 根据用户code查询可用用户信息
        */
        @PostMapping("/find-user-by-code")
        @Override
        public User findUserByCode(@ApiParam("用户code") @MultiRequestBody String userCode) {
            return userService.findUserByCode(userCode, StatusEum.ENABLE.getCode());
        }
        。。。
    }

2、afc sdk client

1)afc sdk client(在sdk模块中)
    public interface IAFCClient {

        IUserAPI getUserAPI();

        。。。

    }

2)远程调用AfcSdkApiRemoteMethodInvocationHandler(在sdk模块中)

    public class AfcSdkApiRemoteMethodInvocationHandler extends AbstractSdkApiRemoteMethodInvocationHandler {
        
        private static final long serialVersionUID = 1L;
        
        public static final String APPCODE = "afc-appCode";
        public static final String APPSECRET = "afc-appSecret";
        public static final String TENANTID = "afc-tenantId";
        
        public AfcSdkApiRemoteMethodInvocationHandler() {
            // 路径前缀
            this.pathPrefix = "api/afc/afc-proxy";

            //服务名或者应用名
            this.serviceName = EOS8ApplicationContext.INSTANCE.getProperty("afc.application.name");

            // head相关参数
            String tenant = EOS8ApplicationContext.INSTANCE.getProperty("afc.application.tenant");
            String appCode = EOS8ApplicationContext.INSTANCE.getProperty("afc.application.appCode");
            String appSecret = EOS8ApplicationContext.INSTANCE.getProperty("afc.application.appSecret");
            Map<String, String> mapHeader = new HashMap<>();
            if(StringUtils.isBlank(tenant)) {
                HttpServletRequest httpRequest = DataContextService.current().getHttpRequest();
                if (httpRequest != null) {
                    String tenantId = httpRequest.getHeader(CommonConstants.TENANT);
                    if(StringUtils.isBlank(tenantId)) {
                        tenantId = httpRequest.getParameter(CommonConstants.TENANT);
                    }
                    if (StringUtils.isNotBlank(tenantId)) {
                        mapHeader.put(TENANTID, tenantId);
                    }
                }
            } else {
                mapHeader.put(APPCODE, appCode);
                mapHeader.put(APPSECRET, appSecret);
                mapHeader.put(TENANTID, tenant);
            }
        }
    }

3)afc sdk client 工厂(在sdk模块中)

    public class AFCClientFactory {
        
        private static AFCClientFactory instance = null;
        
        private AFCClientFactory() {
            // 注册本地sdk api实现,如果在构造方法中注册,此处可以不用
            SdkClientFactory.registLocalSdkApiImpl(IUserAPI.class, new UserLocalImpl());
            ...
        }
        
        public static AFCClientFactory getInstance() {
            if(instance == null) {
                instance = new AFCClientFactory();
            }
            return instance;
        }
        
        // 获取afc sdk 客户端
        public IAFCClient createAFCClient() {
            return SdkClientFactory.getClientProxy(IAFCClient.class, 
                    "com.primeton.gocom.afcenter.starter.config.AFCServerAutoConfiguration", 
                    new AfcSdkApiRemoteMethodInvocationHandler());
        }

    }

4)AFCSDKConfiguration:sdk中的配置类(在sdk模块中)
    @Configuration
    @ComponentScan(basePackages = "com.primeton.gocom.afcenter")
    public class AFCSDKConfiguration {
        
        @Bean
        public IAFCClient afcClient() {// spring方式使用
            return AFCClientFactory.getInstance().createAFCClient();
        }

        。。。

    }

3、使用

1)直接使用
    IUserAPI userApi = AFCClientFactory.getInstance().createAFCClient().getUserAPI();

2)spring方式使用
  
  @Autowired
  private IAFCClient afcClient;


← starter模式 源代码模式 →