この記事の内容は、SpringBoot に関する実用的なヒントを共有することです。必要な友人が参考になれば幸いです。
序文
一部のソース コードとフレームワーク設計は、最近共有されたものです。考えてみると、ほとんどの人がコードを書くことに真剣に取り組んでいるはずであることがわかりました。それは、SpringBoot を使用するためのヒントです。
これは派手なものではありませんが、非常に便利です。
外部依存関係のシールド
最初は、外部依存関係をブロックすることです。これは何を意味しますか?
たとえば、日々の開発中に次のような問題を抱えていませんか:
プロジェクトは SpringCloud や dubbo などの分散サービスに基づいており、多くの基本サービスに依存する必要があります。
例: 注文番号の生成、ユーザー情報の取得など。サービスの分割により、これらの機能は他のアプリケーションのインターフェイスの形式で提供されますが、幸いなことに、Mock を使用して単一のテスト用にブロックすることもできます。
しかし、アプリケーションを起動し、同時に独自の関連コードを実行したい場合はどうすればよいでしょうか?
通常、いくつかのアプローチがあります。
すべてのサービスをローカルで開始します。
登録センターを開発環境に変更し、開発環境のサービスを利用します。
自己テストのためにコードを開発環境に直接プッシュします。
私も以前はこの 3 つをすべて行うことができたようです。しかし、まだ小さな問題がいくつかあります。
ローカル スタートアップには多くのサービスがある可能性があり、そのサービスに問題がある場合、コンピュータがそれらをすべてサポートできるかどうかは不明です。それは続かないでしょう。
開発環境に依存する前提は、ネットワークがオープンであることです。もう 1 つの問題は、開発環境のコードが非常に不安定で、テストに影響を与える可能性があることです。
開発環境にプッシュする方がより信頼性の高い解決策となりますが、デバッグする場合はログを使用する方法しかなく、ローカル デバッグほど効率的ではありません。
それでは、どうすれば問題を解決できるでしょうか?他のサービスを起動せずにローカルでデバッグできます。
実際、単一のテスト メソッドを使用して、他の外部依存関係 Mock
を削除することもできます。
大まかなプロセスは次のステップに分かれています。
SpringBoot が開始したら、Spring でシールドする必要がある API の Bean を見つけます (通常、このインターフェイスはSpring によって管理されます)。
Bean コンテナから Bean を手動で削除します。
この API のオブジェクトを再作成しますが、これは Mock から出たばかりです。
次に、手動で Bean コンテナに登録します。
次のコードを例として取り上げます。
@Override public BaseResponse<ordernoresvo> getUserByHystrix(@RequestBody UserReqVO userReqVO) { OrderNoReqVO vo = new OrderNoReqVO(); vo.setAppId(123L); vo.setReqNo(userReqVO.getReqNo()); BaseResponse<ordernoresvo> orderNo = orderServiceClient.getOrderNo(vo); return orderNo; }</ordernoresvo></ordernoresvo>
orderServiceClient に依存して注文番号を取得します。
orderServiceClient は外部 API であり、Spring によって管理されます。
元の Bean を置き換える
次のステップは、元の Bean を置き換えることです。
@Component public class OrderMockServiceConfig implements CommandLineRunner { private final static Logger logger = LoggerFactory.getLogger(OrderMockServiceConfig.class); @Autowired private ApplicationContext applicationContext; @Value("${excute.env}") private String env; @Override public void run(String... strings) throws Exception { // 非本地环境不做处理 if ("dev".equals(env) || "test".equals(env) || "pro".equals(env)) { return; } DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory(); OrderServiceClient orderServiceClient = defaultListableBeanFactory.getBean(OrderServiceClient.class); logger.info("======orderServiceClient {}=====", orderServiceClient.getClass()); defaultListableBeanFactory.removeBeanDefinition(OrderServiceClient.class.getCanonicalName()); OrderServiceClient mockOrderApi = PowerMockito.mock(OrderServiceClient.class, invocationOnMock -> BaseResponse.createSuccess(DateUtil.getLongTime() + "", "mock orderNo success")); defaultListableBeanFactory.registerSingleton(OrderServiceClient.class.getCanonicalName(), mockOrderApi); logger.info("======mockOrderApi {}=====", mockOrderApi.getClass()); } }
CommandLineRunner インターフェイスが実装されており、Spring コンテナの初期化が完了した後に run() メソッドを呼び出すことができます。
コードは非常に単純です。簡単に言うと、まずローカル環境を除いて、残りは実際にリモート サービスを呼び出す必要があります。
次のステップは、Bean を取得して手動で削除することです。
重要なステップ:
OrderServiceClient mockOrderApi = PowerMockito.mock(OrderServiceClient.class, invocationOnMock -> BaseResponse.createSuccess(DateUtil.getLongTime() + "", "mock orderNo success")); defaultListableBeanFactory.registerSingleton(OrderServiceClient.class.getCanonicalName(), mockOrderApi);
新しい OrderServiceClient オブジェクトを作成し、それを Spring コンテナーに手動で登録します。
コードの最初の部分では、PowerMockito.mock の API を使用します。これにより、OrderServiceClient を呼び出すすべてのメソッドがデフォルトで返されるようにプロキシ オブジェクトを作成できます。
BaseResponse.createSuccess(DateUtil.getLongTime() + "", "mock orderNo success"))
今、置換せずにインターフェイスを呼び出し、ローカルが開始されていない場合にテストしてください。 OrderService
:
##フォールバックが構成されていないため、サービスが見つからないことを示すエラーが報告されます。 Bean を置き換える場合:
再度リクエストしてもエラーは報告されず、デフォルトの戻り値が得られました。
ログから、
OrderServiceClient が最終的に
Mock によってプロキシされたことがわかります。実際のメソッドを呼び出しません。
暗号化の構成
次のステップは暗号化を構成することです。これは基本機能であると考えられます。 たとえば、構成ファイル内の一部のアカウントとパスワードは暗号テキストで保存する必要があります。 そこで、今回は暗号化と復号化の実装にオープン ソース コンポーネントが使用されます。これはSpringBoot に非常に適しており、完了するのに必要なコードはわずか数個だけです。
首先根据加密密码将需要加密的配置加密为密文。
替换原本明文保存的配置。
再使用时进行解密。
使用该包也只需要引入一个依赖即可:
<dependency> <groupid>com.github.ulisesbocchio</groupid> <artifactid>jasypt-spring-boot-starter</artifactid> <version>1.14</version> </dependency>
同时写一个单测根据密码生成密文,密码也可保存在配置文件中:
jasypt.encryptor.password=123456
接着在单测中生成密文。
@Autowired private StringEncryptor encryptor; @Test public void getPass() { String name = encryptor.encrypt("userName"); String password = encryptor.encrypt("password"); System.out.println(name + "----------------"); System.out.println(password + "----------------"); }
之后只需要使用密文就行。
由于我这里是对数据库用户名和密码加密,所以还得有一个解密的过程。
利用 Spring Bean
的一个增强接口即可实现:
@Component public class DataSourceProcess implements BeanPostProcessor { @Autowired private StringEncryptor encryptor; @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof DataSourceProperties){ DataSourceProperties dataSourceProperties = (DataSourceProperties) bean; dataSourceProperties.setUsername(encryptor.decrypt(dataSourceProperties.getUsername())) ; dataSourceProperties.setPassword(encryptor.decrypt(dataSourceProperties.getPassword())); return dataSourceProperties ; } return bean; } }
这样就可以在真正使用时还原为明文。
同时也可以在启动命令中配置刚才的密码:
java -Djasypt.encryptor.password=password -jar target/jasypt-spring-boot-demo-0.0.1-SNAPSHOT.jar
以上がSpringBootの実践スキル共有の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。