# fabric-framework **Repository Path**: wisecoach/fabric-framework ## Basic Information - **Project Name**: fabric-framework - **Description**: 自己开发的一些很简单的配合Spring框架使用的fabric工具框架 - **Primary Language**: Java - **License**: MulanPSL-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 0 - **Created**: 2023-04-13 - **Last Updated**: 2025-03-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # fabric-framework <<<<<<< HEAD ### 介绍 主要包含fabric-security和fabric-gateway-plus两个框架,主要实现以下功能: 1. fabric-security:对读取当前登录用户信息,并根据当前登录用户信息(UserInfo接口)取得与Fabric交互所需的信息(User接口)的流程进行了封装。此外,这个框架还会将信息存入到一个ThreadLocal对象中,供全局使用; 2. fabric-gateway: 1. 对取得Grpc连接、产生Gateway对象、调用链码的过程进行了封装。允许类似Mybatis调用sql语句一样地调用Fabric的链码; 2. 对Grpc连接进行了池化,并且允许设置不同的节点连接级别(如全部使用单个peer节点,一个组织使用一个peer节点) 3. 对提交链码的过程提供了一定的事务机制,如(直接异步提交、直接同步提交、异步等待整个事务最后提交、异步等待整个事务最后提交并用上锁中心化解决双花问题) ### 使用说明 #### fabric-security 1. 首先导入fabric-security-spring-boot-starter包 ```xml com.wisecoach fabric-security-spring-boot-starter ${fabric-framework.version} ``` 2. 配置自定义的UserInfoProvider,这个是必须的,也是对外的接口,可以考虑从SpringSecurity中取得信息,也可以自己实现自己的UserInfo,来提供额外的信息 ```java public class CustomUserInfoProvider extends AbstractUserInfoProvider { @Override protected UserInfo fetchUserInfo(Object obj, Method method, Object[] args) { return new UserInfoImpl("admin", "adminpw"); } } ``` 3. 配置自定义的UserProvider,可以在support方法中要求第二步中自定义的UserInfo,getPriority决定了provider被调用的顺序,越小越先执行。所有UserProvider只要注册到Spring容器中,就会被自动加入到provider队列中,按序被调用尝试取得user ```java public class CustomUserProvider implements UserProvider { private final static String pvtPath = "/mnt/F/fabric-samples/fabric-samples-2.4.8/fabric-samples/test-network/" + "organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/priv_key"; private final static String signerCert = "/mnt/F/fabric-samples/fabric-samples-2.4.8/fabric-samples/test-network" + "/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/cert.pem"; @Override public User getUser(UserInfo userInfo) { Signer signer = null; X509Certificate certificate = null; try { BufferedReader privateKeyReader = Files.newBufferedReader(Paths.get(pvtPath), StandardCharsets.UTF_8); PrivateKey privateKey = Identities.readPrivateKey(privateKeyReader); signer = Signers.newPrivateKeySigner(privateKey); BufferedReader certReader = Files.newBufferedReader(Paths.get(signerCert), StandardCharsets.UTF_8); certificate = Identities.readX509Certificate(certReader); } catch (IOException | InvalidKeyException | CertificateException e) { throw new RuntimeException(e); } return new UserImpl("Org1MSP", signer, certificate); } @Override public boolean support(UserInfo userInfo) { return userInfo instanceof UserInfoImpl; } @Override public int getPriority() { return 0; } } ``` 4. 给需要fabric交互的service和方法加上注解@FabricService和@FabricTransaction ```java @FabricService public class TestServiceImpl implements TestService { @Autowired private BasicContract basicContract; @Override @FabricTransaction @ChaincodeTransaction // 这个是另一个框架的 public String test() { UserContextHolder.getContext().getUser() // 可以取得创建好的User对象 basicContract.initLedger(); AssetCO assetCO = basicContract.readAsset("asset1"); return JSONUtils.serialize(assetCO); } } ``` #### fabric-gateway-plus 1. 导入fabric-gateway-plus-spring-boot-starter ```xml com.wisecoach fabric-gateway-plus-spring-boot-starter ${fabric-framework.version} ``` 2. 进行一些基础的配置 ```yaml fabric: gatewayplus: default-channel: mychannel # 可以配置所有链码的默认channel conn: single-peer-info: # 配置全部使用单个peer节点的端点、tls证书、authority等信息 tls-cert-path: /mnt/F/fabric-samples/fabric-samples-2.4.8/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt endpoint: localhost:7051 authority: peer0.org1.example.com pool: # 配置是否使用grpc连接池,默认开启,还可以修改一些关于连接池的配置 use-pool: true ``` 3. 自己实现一个GatewayInfoProvider,从另一个框架里面拿出User就行了,GatewayInfo和User一样的,我只是为了将两个框架独立开来 ```java public class CustomGatewayInfoProvider extends AbstractGatewayInfoProvider { @Override protected GatewayInfo fetchGatewayInfo(Object obj, Method method, Object[] args) { User user = UserContextHolder.getContext().getUser(); return new GatewayInfoImpl(user.getMspId(), user.getSigner(), user.getCertificate()); } } ``` 4. 跟Mybatis一样创建一个接口,用来调链码 ```java @Repository @ContractMapper("basic") // 可以指定channelID、chaincodeName、contractName public interface BasicContract { @Evalute("ReadAsset") // @Evaluate 只是找一个节点背书一下得到链码执行结果的调用方式,里面写TransactionName AssetCO readAsset(String assetId); @Submit("InitLedger") // @Submit 背书提交给事务 void initLedger(); } ``` 5. 给Service方法几个注解 ```java @FabricTransaction @ChaincodeTransaction(TransactionStrategy.SUBMIT_ASYNC) // 加上这个注解,强化方法才会生效。还可以设置事务策略,表示这个service方法 // 会采用什么策略,详细看TransactionStrategy上的注释 public String test() { basicContract.initLedger(); AssetCO assetCO = basicContract.readAsset("asset1"); return JSONUtils.serialize(assetCO); } ``` ### 原理介绍 #### fabric-security 核心就是通过AOP将加强方法切入到被FabricService注解的类和FabricTransaction注解的方法,加强方法大致如下: 1. 判断注解,是否需要加强 2. 取得UserInfo 3. 根据UserInfo取得User 4. 将User存入UserContextHolder 5. 执行被加强方法 6. 清空UserContextHolder #### fabric-gateway-plus 主要分为对Service方法的加强,加强原理跟fabric-security一样;对Contract接口的加强。 service,由于原理一致,只介绍加强方法: 1. 判断注解ChaincodeTransaction 2. 根据注解中的事务策略,创建对应的事务上下文 3. 取得GatewayInfo,根据gatewayInfo获取gateway,并存入GatewayContextHolder 4. 根据不同策略执行不同的执行前加强方法 5. 执行被加强代码 6. 根据不同策略执行不同的执行后加强方法 7. 如果报错,根据不同策略执行不同的执行报错加强方法 8. 返回结果 contract会通过spring提供的BeanDefinitionRegistryPostProcessor,来对Contract接口修改BeanDefinition,将其具体实现 ======= #### 介绍 {**以下是 Gitee 平台说明,您可以替换此简介** Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台 无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)} #### 软件架构 软件架构说明 #### 安装教程 1. xxxx 2. xxxx 3. xxxx #### 使用说明 1. xxxx 2. xxxx 3. xxxx #### 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request #### 特技 1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md 2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) 3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) 6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) >>>>>>> 1843df1f4859051f01a6ef2fe871e8b14914eb2c