• WxJava使用lettuce的redis实现access_token的共享


    使用WxJava微信开发时,调用接口获取access_token,如果多个服务部署,就需要使用到缓存来保存access_token以达到重复利用,WxJava 也提供了相关的实现类WxMaRedisConfigImpl,但是这个是基于jedis客户端的实现,最新版本的springboot-redis都开始采用lettuce客户端进行连接了,所以我们只能自己手动实现一个类似于WxMaRedisConfigImpl的类

    使用的版本

    
        com.github.binarywang
        weixin-java-miniapp
        3.5.0
    

     WxMaLettuceRedisConfigImpl基于lettuce的工具类

    1. package cn.shiyue.config.ma;
    2. import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
    3. import org.apache.commons.lang3.ObjectUtils;
    4. import org.springframework.data.redis.core.StringRedisTemplate;
    5. import java.util.concurrent.TimeUnit;
    6. public class WxMaLettuceRedisConfigImpl extends WxMaDefaultConfigImpl {
    7. private StringRedisTemplate stringRedisTemplate;
    8. private static final String ACCESS_TOKEN_KEY = "wa:access_token:";
    9. private String accessTokenKey;
    10. public WxMaLettuceRedisConfigImpl(StringRedisTemplate stringRedisTemplate){
    11. this.stringRedisTemplate = stringRedisTemplate;
    12. }
    13. /**
    14. * 每个公众号生成独有的存储key.
    15. */
    16. @Override
    17. public void setAppid(String appId) {
    18. super.setAppid(appId);
    19. this.accessTokenKey = ACCESS_TOKEN_KEY.concat(appId);
    20. }
    21. @Override
    22. public String getAccessToken() {
    23. return stringRedisTemplate.opsForValue().get(accessTokenKey);
    24. }
    25. @Override
    26. public boolean isAccessTokenExpired() {
    27. Long expireTime = stringRedisTemplate.getExpire(accessTokenKey);
    28. if (ObjectUtils.isEmpty(expireTime)) {
    29. return true;
    30. }
    31. // 到期时间小于2秒就算作过期了,就重新调用接口获取
    32. return expireTime < 2;
    33. }
    34. @Override
    35. public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) {
    36. stringRedisTemplate.opsForValue().set(accessTokenKey, accessToken, expiresInSeconds - 200, TimeUnit.SECONDS);
    37. }
    38. @Override
    39. public void expireAccessToken() {
    40. stringRedisTemplate.expire(accessTokenKey, 0, TimeUnit.SECONDS);
    41. }
    42. @Override
    43. public long getExpiresTime() {
    44. Long expire = stringRedisTemplate.getExpire(accessTokenKey);
    45. return expire == null ? 0 : expire;
    46. }
    47. @Override
    48. public void setExpiresTime(long expiresTime) {
    49. stringRedisTemplate.expire(accessTokenKey, expiresTime, TimeUnit.SECONDS);
    50. }
    51. }
    WxMaConfiguration配置
    1. package cn.shiyue.config.ma;
    2. import cn.binarywang.wx.miniapp.api.WxMaService;
    3. import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
    4. import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
    5. import cn.binarywang.wx.miniapp.bean.WxMaTemplateData;
    6. import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage;
    7. import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
    8. import cn.binarywang.wx.miniapp.message.WxMaMessageHandler;
    9. import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
    10. import com.google.common.collect.Lists;
    11. import com.google.common.collect.Maps;
    12. import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
    13. import me.chanjar.weixin.common.error.WxErrorException;
    14. import org.springframework.beans.factory.annotation.Autowired;
    15. import org.springframework.boot.context.properties.EnableConfigurationProperties;
    16. import org.springframework.context.annotation.Configuration;
    17. import org.springframework.data.redis.core.StringRedisTemplate;
    18. import javax.annotation.PostConstruct;
    19. import java.io.File;
    20. import java.util.List;
    21. import java.util.Map;
    22. import java.util.stream.Collectors;
    23. @Configuration
    24. @EnableConfigurationProperties(WxMaProperties.class)
    25. public class WxMaConfiguration {
    26. private WxMaProperties properties;
    27. private static Map routers = Maps.newHashMap();
    28. private static Map maServices = Maps.newHashMap();
    29. // 注入StringRedisTemplate
    30. @Autowired
    31. private StringRedisTemplate stringRedisTemplate;
    32. @Autowired
    33. public WxMaConfiguration(WxMaProperties properties) {
    34. this.properties = properties;
    35. }
    36. public static WxMaService getMaService(String appid) {
    37. WxMaService wxService = maServices.get(appid);
    38. if (wxService == null) {
    39. throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
    40. }
    41. return wxService;
    42. }
    43. public static WxMaMessageRouter getRouter(String appid) {
    44. return routers.get(appid);
    45. }
    46. @PostConstruct
    47. public void init() {
    48. List configs = this.properties.getConfigs();
    49. if (configs == null) {
    50. throw new RuntimeException("大哥,拜托先看下项目首页的说明(readme文件),添加下相关配置,注意别配错了!");
    51. }
    52. maServices = configs.stream()
    53. .map(a -> {
    54. // 在当前引用
    55. WxMaDefaultConfigImpl config = new WxMaLettuceRedisConfigImpl(stringRedisTemplate);
    56. //WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl ();
    57. config.setAppid(a.getAppid());
    58. config.setSecret(a.getSecret());
    59. config.setToken(a.getToken());
    60. config.setAesKey(a.getAesKey());
    61. config.setMsgDataFormat(a.getMsgDataFormat());
    62. WxMaService service = new WxMaServiceImpl();
    63. service.setWxMaConfig(config);
    64. routers.put(a.getAppid(), this.newRouter(service));
    65. return service;
    66. }).collect(Collectors.toMap(s -> s.getWxMaConfig().getAppid(), a -> a));
    67. }
    68. private WxMaMessageRouter newRouter(WxMaService service) {
    69. final WxMaMessageRouter router = new WxMaMessageRouter(service);
    70. router
    71. .rule().handler(logHandler).next()
    72. .rule().async(false).content("模板").handler(templateMsgHandler).end()
    73. .rule().async(false).content("文本").handler(textHandler).end()
    74. .rule().async(false).content("图片").handler(picHandler).end()
    75. .rule().async(false).content("二维码").handler(qrcodeHandler).end();
    76. return router;
    77. }
    78. private final WxMaMessageHandler templateMsgHandler = (wxMessage, context, service, sessionManager) ->{
    79. service.getMsgService().sendTemplateMsg(WxMaTemplateMessage.builder()
    80. .templateId("此处更换为自己的模板id")
    81. .formId("自己替换可用的formid")
    82. .data(Lists.newArrayList(
    83. new WxMaTemplateData("keyword1", "339208499", "#173177")))
    84. .toUser(wxMessage.getFromUser())
    85. .build());
    86. return null;
    87. };
    88. private final WxMaMessageHandler logHandler = (wxMessage, context, service, sessionManager) -> {
    89. System.out.println("收到消息:" + wxMessage.toString());
    90. service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("收到信息为:" + wxMessage.toJson())
    91. .toUser(wxMessage.getFromUser()).build());
    92. return null;
    93. };
    94. private final WxMaMessageHandler textHandler = (wxMessage, context, service, sessionManager) ->{
    95. service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("回复文本消息")
    96. .toUser(wxMessage.getFromUser()).build());
    97. return null;
    98. };
    99. private final WxMaMessageHandler picHandler = (wxMessage, context, service, sessionManager) -> {
    100. try {
    101. WxMediaUploadResult uploadResult = service.getMediaService()
    102. .uploadMedia("image", "png",
    103. ClassLoader.getSystemResourceAsStream("tmp.png"));
    104. service.getMsgService().sendKefuMsg(
    105. WxMaKefuMessage
    106. .newImageBuilder()
    107. .mediaId(uploadResult.getMediaId())
    108. .toUser(wxMessage.getFromUser())
    109. .build());
    110. } catch (WxErrorException e) {
    111. e.printStackTrace();
    112. }
    113. return null;
    114. };
    115. private final WxMaMessageHandler qrcodeHandler = (wxMessage, context, service, sessionManager) -> {
    116. try {
    117. final File file = service.getQrcodeService().createQrcode("123", 430);
    118. WxMediaUploadResult uploadResult = service.getMediaService().uploadMedia("image", file);
    119. service.getMsgService().sendKefuMsg(
    120. WxMaKefuMessage
    121. .newImageBuilder()
    122. .mediaId(uploadResult.getMediaId())
    123. .toUser(wxMessage.getFromUser())
    124. .build());
    125. } catch (WxErrorException e) {
    126. e.printStackTrace();
    127. }
    128. return null;
    129. };
    130. }
    WxMaProperties文件
    1. package cn.shiyue.config.ma;
    2. import org.springframework.boot.context.properties.ConfigurationProperties;
    3. import java.util.List;
    4. @ConfigurationProperties(prefix = "wx.miniapp")
    5. public class WxMaProperties {
    6. private List configs;
    7. public static class Config {
    8. /**
    9. * 设置微信小程序的appid
    10. */
    11. private String appid;
    12. /**
    13. * 设置微信小程序的Secret
    14. */
    15. private String secret;
    16. /**
    17. * 设置微信小程序消息服务器配置的token
    18. */
    19. private String token;
    20. /**
    21. * 设置微信小程序消息服务器配置的EncodingAESKey
    22. */
    23. private String aesKey;
    24. /**
    25. * 消息格式,XML或者JSON
    26. */
    27. private String msgDataFormat;
    28. public String getAppid() {
    29. return appid;
    30. }
    31. public void setAppid(String appid) {
    32. this.appid = appid;
    33. }
    34. public String getSecret() {
    35. return secret;
    36. }
    37. public void setSecret(String secret) {
    38. this.secret = secret;
    39. }
    40. public String getToken() {
    41. return token;
    42. }
    43. public void setToken(String token) {
    44. this.token = token;
    45. }
    46. public String getAesKey() {
    47. return aesKey;
    48. }
    49. public void setAesKey(String aesKey) {
    50. this.aesKey = aesKey;
    51. }
    52. public String getMsgDataFormat() {
    53. return msgDataFormat;
    54. }
    55. public void setMsgDataFormat(String msgDataFormat) {
    56. this.msgDataFormat = msgDataFormat;
    57. }
    58. }
    59. public List getConfigs() {
    60. return configs;
    61. }
    62. public void setConfigs(List configs) {
    63. this.configs = configs;
    64. }
    65. }

     还有一种方式在WxMaConfiguration 文件中配置,这个WxMaRedisBetterConfigImpl类需要高版本的weixin-java-miniapp的jar

    @Autowired

    private StringRedisTemplate stringRedisTemplate;

    // 方式二才需要用上

    @Bean

    public WxRedisOps getWxRedisOps() {

    return new RedisTemplateWxRedisOps(stringRedisTemplate);

    }

    // 方式一:自己实现一个lettuce的redis配置对象

    WxMaDefaultConfigImpl config = new WxMaLettuceRedisConfigImpl(stringRedisTemplate);

    // 方式二: 使用wxRedisOps对象来包装redis连接

    // WxMaDefaultConfigImpl config = new WxMaRedisBetterConfigImpl(getWxRedisOps(), "wa:access_token:");

  • 相关阅读:
    自学Python 60 socketserver编程
    喷码机如何与封箱机配合?
    Node.js 安装配置
    Git入门详解
    软体机器人空间感知技术综述
    深度学习 Day 16——利用卷神经网络实现咖啡豆的识别
    【Android开发】Android请求出现网络请求失败,HTTP请求,安全网络通信与权限管理
    ue4使用Niagara粒子实现下雨效果,使用蓝图调节雨量
    能带你起飞的【数据结构】成王第十篇:二叉树4
    含重复元素取不重复子集[如何取子集?如何去重?]
  • 原文地址:https://blog.csdn.net/SDJN_ONE/article/details/134326361