热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

值得收藏的SpringBoot实用的小技巧

最近分享的一些源码、框架设计的东西。我发现大家热情不是特别高,想想大多数应该还是正儿八经写代码的居多;这次就分享一点接地气的:SpringBoot使用中的一些小技巧,需要的朋友可以参考下

前言

最近分享的一些源码、框架设计的东西。我发现大家热情不是特别高,想想大多数应该还是正儿八经写代码的居多;这次就分享一点接地气的: SpringBoot 使用中的一些小技巧。

算不上多高大上的东西,但都还挺有用。

屏蔽外部依赖

第一个是屏蔽外部依赖,什么意思呢?

比如大家日常开发时候有没有这样的烦恼:

项目是基于 SpringCloud 或者是 dubbo 这样的分布式服务,你需要依赖许多基础服务。

比如说某个订单号的生成、获取用户信息等。

由于服务拆分,这些功能都是在其他应用中以接口的形式提供,单测还好我还可以利用 Mock 把它屏蔽掉。

但如果自己想把应用启动起来同时把自己相关的代码跑一遍呢?

通常有几种做法:

•本地把所有的服务都启动起来。
•把注册中心换为开发环境,依赖开发环境的服务。
•直接把代码推送到开发环境自测。

看起来三种都可以,以前我也是这么干的。但还是有几个小问题:

•本地启动有可能服务很多,全部起来电脑能不能撑住还两说,万一服务有问题就进行不下去了。
•依赖开发环境的前提是网络打通,还有一个问题就是开发环境代码很不稳定很大可能会影响你的测试。
•推送到开发环境应该是比较靠谱的方案,但如果想调试只有日志大法,没有本地 debug 的效率高效。

那如何解决问题呢?既可以在本地调试也不用启动其他服务。

其实也可以利用单测的做法,把其他外部依赖 Mock 掉就行了。

大致的流程分为以下几步:

•SpringBoot 启动之后在 Spring 中找出你需要屏蔽的那个 API 的 bean(通常情况下这个接口都是交给 Spring 管理的)。
•手动从 bean 容器中删除该 bean。
•重新创建一个该 API 的对象,只不过是通过 Mock 出来的。
•再手动注册进 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;
 }

这是一个 SpringCloud 应用。

它依赖于 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:

因为没有配置 fallback 所以会报错,表示找不到这个服务。

替换掉 bean 时:

再次请求没有报错,并且获得了我们默认的返回。

通过日志也会发现 OrderServiceClient 最后已经被 Mock 代理了,并不会去调用真正的方法。

配置加密

下一个则是配置加密,这应该算是一个基本功能。

比如我们配置文件中的一些账号和密码,都应该是密文保存的。

因此这次使用了一个开源组件来实现加密与解密,并且对 SpringBoot 非常友好只需要几段代码即可完成。

•首先根据加密密码将需要加密的配置加密为密文。
•替换原本明文保存的配置。
•再使用时进行解密。

使用该包也只需要引入一个依赖即可:


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

同时写一个单测根据密码生成密文,密码也可保存在配置文件中:

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

总结

上文的一些实例代码可以在这里找到:

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

以上所述是小编给大家介绍的值得收藏的SpringBoot 实用的小技巧,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!


推荐阅读
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 打开文件管理器_【教程】模组管理器3.1食用指南
    文编:byakko最近有部分小伙伴反应还不会使用unity模组管理器,现在我就给大家讲一下unity模组管理器——从下载到使用。完整视频版以下是无WiF ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 【MicroServices】【Arduino】装修甲醛检测,ArduinoDart甲醛、PM2.5、温湿度、光照传感器等,数据记录于SD卡,Python数据显示,UI5前台,微服务后台……
    这篇文章介绍了一个基于Arduino的装修甲醛检测项目,使用了ArduinoDart甲醛、PM2.5、温湿度、光照传感器等硬件,并将数据记录于SD卡,使用Python进行数据显示,使用UI5进行前台设计,使用微服务进行后台开发。该项目还在不断更新中,有兴趣的可以关注作者的博客和GitHub。 ... [详细]
  • 本文介绍了Java的集合及其实现类,包括数据结构、抽象类和具体实现类的关系,详细介绍了List接口及其实现类ArrayList的基本操作和特点。文章通过提供相关参考文档和链接,帮助读者更好地理解和使用Java的集合类。 ... [详细]
  • imx6ull开发板驱动MT7601U无线网卡的方法和步骤详解
    本文详细介绍了在imx6ull开发板上驱动MT7601U无线网卡的方法和步骤。首先介绍了开发环境和硬件平台,然后说明了MT7601U驱动已经集成在linux内核的linux-4.x.x/drivers/net/wireless/mediatek/mt7601u文件中。接着介绍了移植mt7601u驱动的过程,包括编译内核和配置设备驱动。最后,列举了关键词和相关信息供读者参考。 ... [详细]
  • 标题: ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • STL迭代器的种类及其功能介绍
    本文介绍了标准模板库(STL)定义的五种迭代器的种类和功能。通过图表展示了这几种迭代器之间的关系,并详细描述了各个迭代器的功能和使用方法。其中,输入迭代器用于从容器中读取元素,输出迭代器用于向容器中写入元素,正向迭代器是输入迭代器和输出迭代器的组合。本文的目的是帮助读者更好地理解STL迭代器的使用方法和特点。 ... [详细]
author-avatar
手机用户2502854133
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有