真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

值得收藏的SpringBoot實(shí)用的小技巧

前言

成都創(chuàng)新互聯(lián)公司是一家以重慶網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)、品牌設(shè)計(jì)、軟件運(yùn)維、seo優(yōu)化、小程序App開(kāi)發(fā)等移動(dòng)開(kāi)發(fā)為一體互聯(lián)網(wǎng)公司。已累計(jì)為成都酒樓設(shè)計(jì)等眾行業(yè)中小客戶提供優(yōu)質(zhì)的互聯(lián)網(wǎng)建站和軟件開(kāi)發(fā)服務(wù)。

最近分享的一些源碼、框架設(shè)計(jì)的東西。我發(fā)現(xiàn)大家熱情不是特別高,想想大多數(shù)應(yīng)該還是正兒八經(jīng)寫(xiě)代碼的居多;這次就分享一點(diǎn)接地氣的: SpringBoot 使用中的一些小技巧。

算不上多高大上的東西,但都還挺有用。

屏蔽外部依賴

第一個(gè)是屏蔽外部依賴,什么意思呢?

比如大家日常開(kāi)發(fā)時(shí)候有沒(méi)有這樣的煩惱:

項(xiàng)目是基于 SpringCloud 或者是 dubbo 這樣的分布式服務(wù),你需要依賴許多基礎(chǔ)服務(wù)。

比如說(shuō)某個(gè)訂單號(hào)的生成、獲取用戶信息等。

由于服務(wù)拆分,這些功能都是在其他應(yīng)用中以接口的形式提供,單測(cè)還好我還可以利用 Mock 把它屏蔽掉。

但如果自己想把應(yīng)用啟動(dòng)起來(lái)同時(shí)把自己相關(guān)的代碼跑一遍呢?

通常有幾種做法:

•本地把所有的服務(wù)都啟動(dòng)起來(lái)。
•把注冊(cè)中心換為開(kāi)發(fā)環(huán)境,依賴開(kāi)發(fā)環(huán)境的服務(wù)。
•直接把代碼推送到開(kāi)發(fā)環(huán)境自測(cè)。

看起來(lái)三種都可以,以前我也是這么干的。但還是有幾個(gè)小問(wèn)題:

•本地啟動(dòng)有可能服務(wù)很多,全部起來(lái)電腦能不能撐住還兩說(shuō),萬(wàn)一服務(wù)有問(wèn)題就進(jìn)行不下去了。
•依賴開(kāi)發(fā)環(huán)境的前提是網(wǎng)絡(luò)打通,還有一個(gè)問(wèn)題就是開(kāi)發(fā)環(huán)境代碼很不穩(wěn)定很大可能會(huì)影響你的測(cè)試。
•推送到開(kāi)發(fā)環(huán)境應(yīng)該是比較靠譜的方案,但如果想調(diào)試只有日志大法,沒(méi)有本地 debug 的效率高效。

那如何解決問(wèn)題呢?既可以在本地調(diào)試也不用啟動(dòng)其他服務(wù)。

其實(shí)也可以利用單測(cè)的做法,把其他外部依賴 Mock 掉就行了。

大致的流程分為以下幾步:

•SpringBoot 啟動(dòng)之后在 Spring 中找出你需要屏蔽的那個(gè) API 的 bean(通常情況下這個(gè)接口都是交給 Spring 管理的)。
•手動(dòng)從 bean 容器中刪除該 bean。
•重新創(chuàng)建一個(gè)該 API 的對(duì)象,只不過(guò)是通過(guò) Mock 出來(lái)的。
•再手動(dòng)注冊(cè)進(jìn) bean 容器中。

以下面這段代碼為例:

 @Override
 public BaseResponse getUserByHystrix(@RequestBody UserReqVO userReqVO) {

  OrderNoReqVO vo = new OrderNoReqVO();
  vo.setAppId(123L);
  vo.setReqNo(userReqVO.getReqNo());
  BaseResponse orderNo = orderServiceClient.getOrderNo(vo);
  return orderNo;
 }

這是一個(gè) SpringCloud 應(yīng)用。

它依賴于 orderServiceClient 獲取一個(gè)訂單號(hào)。

其中的 orderServiceClient 就是一個(gè)外部 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 {

  // 非本地環(huán)境不做處理
  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());
 }
}

其中實(shí)現(xiàn)了 CommandLineRunner 接口,可以在 Spring 容器初始化完成之后調(diào)用 run() 方法。

代碼非常簡(jiǎn)單,簡(jiǎn)單來(lái)說(shuō)首先判斷下是什么環(huán)境,畢竟除開(kāi)本地環(huán)境其余的都是需要真正調(diào)用遠(yuǎn)程服務(wù)的。

之后就是獲取 bean 然后手動(dòng)刪除掉。

關(guān)鍵的一步:

OrderServiceClient mockOrderApi = PowerMockito.mock(OrderServiceClient.class,
    invocationOnMock -> BaseResponse.createSuccess(DateUtil.getLongTime() + "", "mock orderNo success"));
defaultListableBeanFactory.registerSingleton(OrderServiceClient.class.getCanonicalName(), mockOrderApi);

創(chuàng)建了一個(gè)新的 OrderServiceClient 對(duì)象并手動(dòng)注冊(cè)進(jìn)了 Spring 容器中。

第一段代碼使用的是 PowerMockito.mock 的 API,他可以創(chuàng)建一個(gè)代理對(duì)象,讓所有調(diào)用 OrderServiceClient 的方法都會(huì)做默認(rèn)的返回。

BaseResponse.createSuccess(DateUtil.getLongTime() + "", "mock orderNo success"))

測(cè)試一下,當(dāng)我們沒(méi)有替換時(shí)調(diào)用剛才那個(gè)接口并且本地也沒(méi)有啟動(dòng) OrderService:

值得收藏的SpringBoot 實(shí)用的小技巧

因?yàn)闆](méi)有配置 fallback 所以會(huì)報(bào)錯(cuò),表示找不到這個(gè)服務(wù)。

替換掉 bean 時(shí):

值得收藏的SpringBoot 實(shí)用的小技巧

再次請(qǐng)求沒(méi)有報(bào)錯(cuò),并且獲得了我們默認(rèn)的返回。

值得收藏的SpringBoot 實(shí)用的小技巧

通過(guò)日志也會(huì)發(fā)現(xiàn) OrderServiceClient 最后已經(jīng)被 Mock 代理了,并不會(huì)去調(diào)用真正的方法。

配置加密

下一個(gè)則是配置加密,這應(yīng)該算是一個(gè)基本功能。

比如我們配置文件中的一些賬號(hào)和密碼,都應(yīng)該是密文保存的。

因此這次使用了一個(gè)開(kāi)源組件來(lái)實(shí)現(xiàn)加密與解密,并且對(duì) SpringBoot 非常友好只需要幾段代碼即可完成。

•首先根據(jù)加密密碼將需要加密的配置加密為密文。
•替換原本明文保存的配置。
•再使用時(shí)進(jìn)行解密。

使用該包也只需要引入一個(gè)依賴即可:


 com.github.ulisesbocchio
 jasypt-spring-boot-starter
 1.14

同時(shí)寫(xiě)一個(gè)單測(cè)根據(jù)密碼生成密文,密碼也可保存在配置文件中:

jasypt.encryptor.password=123456

接著在單測(cè)中生成密文。

 @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 + "----------------");
 }

之后只需要使用密文就行。

由于我這里是對(duì)數(shù)據(jù)庫(kù)用戶名和密碼加密,所以還得有一個(gè)解密的過(guò)程。

利用 Spring Bean 的一個(gè)增強(qiáng)接口即可實(shí)現(xiàn):

@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;
 }
}

這樣就可以在真正使用時(shí)還原為明文。

同時(shí)也可以在啟動(dòng)命令中配置剛才的密碼:

java -Djasypt.encryptor.password=password -jar target/jasypt-spring-boot-demo-0.0.1-SNAPSHOT.jar

總結(jié)

上文的一些實(shí)例代碼可以在這里找到:

https://github.com/crossoverJie/springboot-cloud

以上所述是小編給大家介紹的值得收藏的SpringBoot 實(shí)用的小技巧,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)創(chuàng)新互聯(lián)網(wǎng)站的支持!


網(wǎng)頁(yè)名稱:值得收藏的SpringBoot實(shí)用的小技巧
本文來(lái)源:http://weahome.cn/article/gjesse.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部