当前位置:   article > 正文

在使用wx-java-mp-starter 中理解springboot-starter笔记_wx-java-mp-spring-boot-starter

wx-java-mp-spring-boot-starter

一. 简介:

当我们使用一个spring外部组件时,通常需要依赖多个不同的jar包,spring-boot-starter能够整合所需要的依赖组件,通过根据模块内的环境进行自动配置,使用者只需要引入starter坐标,不需要过多的依赖及配置就可以使用

  1. 1.它整合了这个模块需要的依赖库;
  2. 2.提供对模块的配置项给使用者;
  3. 3.提供自动配置类对模块内的Bean进行自动装配;

例如:使用微信公众号开源脚手架只需要引入下面的wx-java-mp-starter依赖即可,不需要手动对其其他组件依赖

二. 编写starter开发步骤

 1.新建maven项目,并添加以下依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-autoconfigure</artifactId>
  5. <version>${spring.boot.version}</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.springframework.boot</groupId>
  9. <artifactId>spring-boot-configuration-processor</artifactId>
  10. <version>${spring.boot.version}</version>
  11. <optional>true</optional>
  12. </dependency>
  13. <dependency>

 

其中 spring-boot-configuration-processor 的作用是编译时生成 spring-configuration-metadata.json ,此文件主要给IDE使用。如当配置此jar相关配置属性在 application.yml ,你可以用ctlr+鼠标左键点击属性名,IDE会跳转到你配置此属性的类中。

spring官方starter一般采取spring-boot-starter-{name}的命名方式,如spring-boot-starter-web,非官方建议artifactId命名遵循{name}-spring-boot-starter, wx-java-mp-starter的命名如下:

wx-java-mp-starter

2. 新建配置类(微信app相关信息配置类)

  1. package com.binarywang.spring.starter.wxjava.mp;
  2. import lombok.Data;
  3. import org.springframework.boot.context.properties.ConfigurationProperties;
  4. import java.io.Serializable;
  5. import static com.binarywang.spring.starter.wxjava.mp.WxMpProperties.PREFIX;
  6. import static com.binarywang.spring.starter.wxjava.mp.WxMpProperties.StorageType.memory;
  7. /**
  8. * 微信接入相关配置属性
  9. */
  10. @Data
  11. @ConfigurationProperties(PREFIX)
  12. public class WxMpProperties {
  13. public static final String PREFIX = "wx.mp";
  14. /**
  15. * 设置微信公众号的appid
  16. */
  17. private String appId;
  18. /**
  19. * 设置微信公众号的app secret
  20. */
  21. private String secret;
  22. /**
  23. * 设置微信公众号的token
  24. */
  25. private String token;
  26. /**
  27. * 设置微信公众号的EncodingAESKey
  28. */
  29. private String aesKey;
  30. /**
  31. * 存储策略, memory, redis
  32. */
  33. private ConfigStorage configStorage = new ConfigStorage();
  34. @Data
  35. public static class ConfigStorage implements Serializable {
  36. private StorageType type = memory;
  37. private RedisProperties redis = new RedisProperties();
  38. }
  39. public enum StorageType {
  40. memory, redis
  41. }
  42. }
  1. package com.binarywang.spring.starter.wxjava.mp;
  2. import lombok.Data;
  3. import org.springframework.boot.context.properties.ConfigurationProperties;
  4. import java.io.Serializable;
  5. import static com.binarywang.spring.starter.wxjava.mp.WxMpProperties.PREFIX;
  6. import static com.binarywang.spring.starter.wxjava.mp.WxMpProperties.StorageType.memory;
  7. /**
  8. * 微信接入相关配置属性
  9. */
  10. @Data
  11. @ConfigurationProperties(PREFIX)
  12. public class WxMpProperties {
  13. public static final String PREFIX = "wx.mp";
  14. /**
  15. * 设置微信公众号的appid
  16. */
  17. private String appId;
  18. /**
  19. * 设置微信公众号的app secret
  20. */
  21. private String secret;
  22. /**
  23. * 设置微信公众号的token
  24. */
  25. private String token;
  26. /**
  27. * 设置微信公众号的EncodingAESKey
  28. */
  29. private String aesKey;
  30. /**
  31. * 存储策略, memory, redis
  32. */
  33. private ConfigStorage configStorage = new ConfigStorage();
  34. @Data
  35. public static class ConfigStorage implements Serializable {
  36. private StorageType type = memory;
  37. private RedisProperties redis = new RedisProperties();
  38. }
  39. public enum StorageType {
  40. memory, redis
  41. }
  42. }

3. 新建总配置类,用于springboot 加载配置

第一步:  SpringBoot 在启动时会去依赖的starter包中寻找 resources/META-INF/spring.factories 文件,然后根据文件中配置的Jar包去扫描项目所依赖的Jar包,这类似于 Java 的 SPI 机制,此类将配置在spring.factories中

第二步:  根据 spring.factories配置加载AutoConfigure类。

最后,根据 @Conditional注解的条件,进行自动配置并将Bean注入Spring Context 上下文当中。

我们也可以使用@ImportAutoConfiguration({MyServiceAutoConfiguration.class}) 指定自动配置哪些类。

  1. package com.binarywang.spring.starter.wxjava.mp;
  2. import org.springframework.boot.context.properties.EnableConfigurationProperties;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.context.annotation.Import;
  5. @Configuration
  6. @EnableConfigurationProperties(WxMpProperties.class)
  7. @Import({WxMpStorageAutoConfiguration.class, WxMpServiceAutoConfiguration.class})
  8. public class WxMpAutoConfiguration {
  9. }

4.新建导入配置类即第三步中的Import所导入的类,因application包扫描扫描并未配置第三方jar引用,所以通过import的方式将实例注到spring容器

  1. package com.binarywang.spring.starter.wxjava.mp;
  2. import me.chanjar.weixin.mp.api.WxMpConfigStorage;
  3. import me.chanjar.weixin.mp.api.WxMpService;
  4. import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
  7. import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
  8. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
  9. import org.springframework.context.ApplicationContext;
  10. import org.springframework.context.annotation.Bean;
  11. import org.springframework.context.annotation.Configuration;
  12. /**
  13. * 微信公众号相关服务自动注册
  14. */
  15. @Configuration
  16. public class WxMpServiceAutoConfiguration {
  17. @Autowired
  18. private ApplicationContext ctx;
  19. @Bean
  20. @ConditionalOnMissingBean//通过此注解,可以自已实现一个WxMpConfigStorage来替换此存储策略
  21. public WxMpService wxMpService(WxMpConfigStorage configStorage) {
  22. WxMpService wxMpService = new WxMpServiceImpl();
  23. wxMpService.setWxMpConfigStorage(configStorage);
  24. registerWxMpSubService(wxMpService);
  25. return wxMpService;
  26. }
  27. @ConditionalOnBean(WxMpService.class)
  28. public Object registerWxMpSubService(WxMpService wxMpService) {
  29. //进行bean单例注册,注册后可注入使用
  30. ConfigurableListableBeanFactory factory = (ConfigurableListableBeanFactory) ctx.getAutowireCapableBeanFactory();
  31. factory.registerSingleton("wxMpKefuService", wxMpService.getKefuService());
  32. factory.registerSingleton("wxMpMaterialService", wxMpService.getMaterialService());
  33. factory.registerSingleton("wxMpMenuService", wxMpService.getMenuService());
  34. factory.registerSingleton("wxMpUserService", wxMpService.getUserService());
  35. factory.registerSingleton("wxMpUserTagService", wxMpService.getUserTagService());
  36. factory.registerSingleton("wxMpQrcodeService", wxMpService.getQrcodeService());
  37. factory.registerSingleton("wxMpCardService", wxMpService.getCardService());
  38. factory.registerSingleton("wxMpDataCubeService", wxMpService.getDataCubeService());
  39. factory.registerSingleton("wxMpUserBlacklistService", wxMpService.getBlackListService());
  40. factory.registerSingleton("wxMpStoreService", wxMpService.getStoreService());
  41. factory.registerSingleton("wxMpTemplateMsgService", wxMpService.getTemplateMsgService());
  42. factory.registerSingleton("wxMpSubscribeMsgService", wxMpService.getSubscribeMsgService());
  43. factory.registerSingleton("wxMpDeviceService", wxMpService.getDeviceService());
  44. factory.registerSingleton("wxMpShakeService", wxMpService.getShakeService());
  45. factory.registerSingleton("wxMpMemberCardService", wxMpService.getMemberCardService());
  46. factory.registerSingleton("wxMpMassMessageService", wxMpService.getMassMessageService());
  47. return Boolean.TRUE;
  48. }
  49. }
  1. package com.binarywang.spring.starter.wxjava.mp;
  2. import me.chanjar.weixin.mp.api.WxMpConfigStorage;
  3. import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
  4. import me.chanjar.weixin.mp.api.WxMpInRedisConfigStorage;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9. import redis.clients.jedis.JedisPool;
  10. import redis.clients.jedis.JedisPoolConfig;
  11. /**
  12. * 微信公众号存储策略自动配置
  13. */
  14. @Configuration
  15. public class WxMpStorageAutoConfiguration {
  16. @Autowired
  17. private WxMpProperties properties;
  18. @Autowired(required = false)
  19. private JedisPool jedisPool;
  20. @Bean
  21. @ConditionalOnMissingBean(WxMpConfigStorage.class)
  22. public WxMpConfigStorage wxMpInMemoryConfigStorage() {
  23. WxMpProperties.ConfigStorage storage = properties.getConfigStorage();
  24. WxMpProperties.StorageType type = storage.getType();
  25. if (type == WxMpProperties.StorageType.redis) {
  26. return getWxMpInRedisConfigStorage();
  27. }
  28. return getWxMpInMemoryConfigStorage();
  29. }
  30. private WxMpInMemoryConfigStorage getWxMpInMemoryConfigStorage() {
  31. WxMpInMemoryConfigStorage config = new WxMpInMemoryConfigStorage();
  32. setWxMpInfo(config);
  33. return config;
  34. }
  35. private WxMpInRedisConfigStorage getWxMpInRedisConfigStorage() {
  36. JedisPool poolToUse = jedisPool;
  37. if (poolToUse == null) {
  38. poolToUse = getJedisPool();
  39. }
  40. WxMpInRedisConfigStorage config = new WxMpInRedisConfigStorage(poolToUse);
  41. setWxMpInfo(config);
  42. return config;
  43. }
  44. private void setWxMpInfo(WxMpInMemoryConfigStorage config) {
  45. config.setAppId(properties.getAppId());
  46. config.setSecret(properties.getSecret());
  47. config.setToken(properties.getToken());
  48. config.setAesKey(properties.getAesKey());
  49. }
  50. private JedisPool getJedisPool() {
  51. WxMpProperties.ConfigStorage storage = properties.getConfigStorage();
  52. RedisProperties redis = storage.getRedis();
  53. JedisPoolConfig config = new JedisPoolConfig();
  54. if (redis.getMaxActive() != null) {
  55. config.setMaxTotal(redis.getMaxActive());
  56. }
  57. if (redis.getMaxIdle() != null) {
  58. config.setMaxIdle(redis.getMaxIdle());
  59. }
  60. if (redis.getMaxWaitMillis() != null) {
  61. config.setMaxWaitMillis(redis.getMaxWaitMillis());
  62. }
  63. if (redis.getMinIdle() != null) {
  64. config.setMinIdle(redis.getMinIdle());
  65. }
  66. config.setTestOnBorrow(true);
  67. config.setTestWhileIdle(true);
  68. JedisPool pool = new JedisPool(config, redis.getHost(), redis.getPort(),
  69. redis.getTimeout(), redis.getPassword(), redis.getDatabase());
  70. return pool;
  71. }
  72. }

5. 最后一步,在resources/META-INF/下创建spring.factories文件,并添加如下内容:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.binarywang.spring.starter.wxjava.mp.WxMpAutoConfiguration

 org.springframework.boot.autoconfigure.EnableAutoConfiguration后面的类名为装配的配置类,引入多个使用逗号分开;
springboot启动时会通过org.springframework.core.io.support.SpringFactoriesLoader读取classpath下每个Starter的spring.factories文件,加载自动装配类进行Bean的自动装配

6. 关于配置中的注解解释

        6.1 conditions相关注解

Conditions描述
@ConditionalOnBean在存在某个bean的时候
@ConditionalOnMissingBean不存在某个bean的时候
@ConditionalOnClass当前classpath可以找到某个类型的类时
@ConditionalOnMissingClass当前classpath不可以找到某个类型的类时
@ConditionalOnResource当前classpath是否存在某个资源文件
@ConditionalOnProperty当前jvm是否包含某个系统属性为某个值
@ConditionalOnWebApplication当前spring context是否是web应用程序

        6.2 其他注解       

@EnableConfigurationProperties 作用是:使ConfigurationProperties注解生效

@ConfigurationProperties 将配置文件中的属性值映射到类中

           @Import  通过导入的方式实现把实例加入springIOC容器中

 

三. 使用方式

  1. <dependency>
  2. <groupId>com.github.binarywang</groupId>
  3. <artifactId>wx-java-mp-starter</artifactId>
  4. <version>${weixin-java-mp.version}</version>
  5. </dependency>
  1. package com.rograndec.crm.service.wxcoupon.impl;
  2. import com.rograndec.crm.service.wxcoupon.WeiXinCouponService;
  3. import me.chanjar.weixin.mp.api.WxMpCardService;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. /**
  6. * @author ping.zhu
  7. * @date 2019-06-03 20:08
  8. * @description
  9. */
  10. public class WeiXinCouponServiceImpl implements WeiXinCouponService {
  11. @Autowired
  12. private WxMpCardService wxMpCardService;
  13. }

  

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/232825
推荐阅读
相关标签
  

闽ICP备14008679号