使用WxJava微信开发时,调用接口获取access_token,如果多个服务部署,就需要使用到缓存来保存access_token以达到重复利用,WxJava 也提供了相关的实现类WxMaRedisConfigImpl,但是这个是基于jedis客户端的实现,最新版本的springboot-redis都开始采用lettuce客户端进行连接了,所以我们只能自己手动实现一个类似于WxMaRedisConfigImpl的类
使用的版本
com.github.binarywang weixin-java-miniapp 3.5.0
WxMaLettuceRedisConfigImpl基于lettuce的工具类
- package cn.shiyue.config.ma;
-
- import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
- import org.apache.commons.lang3.ObjectUtils;
- import org.springframework.data.redis.core.StringRedisTemplate;
-
- import java.util.concurrent.TimeUnit;
-
- public class WxMaLettuceRedisConfigImpl extends WxMaDefaultConfigImpl {
-
- private StringRedisTemplate stringRedisTemplate;
-
- private static final String ACCESS_TOKEN_KEY = "wa:access_token:";
-
- private String accessTokenKey;
-
- public WxMaLettuceRedisConfigImpl(StringRedisTemplate stringRedisTemplate){
- this.stringRedisTemplate = stringRedisTemplate;
- }
-
- /**
- * 每个公众号生成独有的存储key.
- */
- @Override
- public void setAppid(String appId) {
- super.setAppid(appId);
- this.accessTokenKey = ACCESS_TOKEN_KEY.concat(appId);
- }
-
- @Override
- public String getAccessToken() {
- return stringRedisTemplate.opsForValue().get(accessTokenKey);
- }
-
- @Override
- public boolean isAccessTokenExpired() {
- Long expireTime = stringRedisTemplate.getExpire(accessTokenKey);
- if (ObjectUtils.isEmpty(expireTime)) {
- return true;
- }
- // 到期时间小于2秒就算作过期了,就重新调用接口获取
- return expireTime < 2;
- }
-
- @Override
- public synchronized void updateAccessToken(String accessToken, int expiresInSeconds) {
- stringRedisTemplate.opsForValue().set(accessTokenKey, accessToken, expiresInSeconds - 200, TimeUnit.SECONDS);
- }
-
- @Override
- public void expireAccessToken() {
- stringRedisTemplate.expire(accessTokenKey, 0, TimeUnit.SECONDS);
- }
-
-
- @Override
- public long getExpiresTime() {
- Long expire = stringRedisTemplate.getExpire(accessTokenKey);
- return expire == null ? 0 : expire;
- }
-
- @Override
- public void setExpiresTime(long expiresTime) {
- stringRedisTemplate.expire(accessTokenKey, expiresTime, TimeUnit.SECONDS);
- }
- }
WxMaConfiguration配置
- package cn.shiyue.config.ma;
-
- import cn.binarywang.wx.miniapp.api.WxMaService;
- import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
- import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage;
- import cn.binarywang.wx.miniapp.bean.WxMaTemplateData;
- import cn.binarywang.wx.miniapp.bean.WxMaTemplateMessage;
- import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
- import cn.binarywang.wx.miniapp.message.WxMaMessageHandler;
- import cn.binarywang.wx.miniapp.message.WxMaMessageRouter;
- import com.google.common.collect.Lists;
- import com.google.common.collect.Maps;
- import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
- import me.chanjar.weixin.common.error.WxErrorException;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.context.properties.EnableConfigurationProperties;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.data.redis.core.StringRedisTemplate;
-
- import javax.annotation.PostConstruct;
- import java.io.File;
- import java.util.List;
- import java.util.Map;
- import java.util.stream.Collectors;
-
- @Configuration
- @EnableConfigurationProperties(WxMaProperties.class)
- public class WxMaConfiguration {
- private WxMaProperties properties;
-
- private static Map
routers = Maps.newHashMap(); - private static Map
maServices = Maps.newHashMap(); -
- // 注入StringRedisTemplate
- @Autowired
- private StringRedisTemplate stringRedisTemplate;
-
- @Autowired
- public WxMaConfiguration(WxMaProperties properties) {
- this.properties = properties;
- }
-
- public static WxMaService getMaService(String appid) {
- WxMaService wxService = maServices.get(appid);
- if (wxService == null) {
- throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
- }
-
- return wxService;
- }
-
- public static WxMaMessageRouter getRouter(String appid) {
- return routers.get(appid);
- }
-
- @PostConstruct
- public void init() {
- List
configs = this.properties.getConfigs(); - if (configs == null) {
- throw new RuntimeException("大哥,拜托先看下项目首页的说明(readme文件),添加下相关配置,注意别配错了!");
- }
-
- maServices = configs.stream()
- .map(a -> {
- // 在当前引用
- WxMaDefaultConfigImpl config = new WxMaLettuceRedisConfigImpl(stringRedisTemplate);
- //WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl ();
- config.setAppid(a.getAppid());
- config.setSecret(a.getSecret());
- config.setToken(a.getToken());
- config.setAesKey(a.getAesKey());
- config.setMsgDataFormat(a.getMsgDataFormat());
-
- WxMaService service = new WxMaServiceImpl();
- service.setWxMaConfig(config);
- routers.put(a.getAppid(), this.newRouter(service));
- return service;
- }).collect(Collectors.toMap(s -> s.getWxMaConfig().getAppid(), a -> a));
- }
-
- private WxMaMessageRouter newRouter(WxMaService service) {
- final WxMaMessageRouter router = new WxMaMessageRouter(service);
- router
- .rule().handler(logHandler).next()
- .rule().async(false).content("模板").handler(templateMsgHandler).end()
- .rule().async(false).content("文本").handler(textHandler).end()
- .rule().async(false).content("图片").handler(picHandler).end()
- .rule().async(false).content("二维码").handler(qrcodeHandler).end();
- return router;
- }
-
- private final WxMaMessageHandler templateMsgHandler = (wxMessage, context, service, sessionManager) ->{
- service.getMsgService().sendTemplateMsg(WxMaTemplateMessage.builder()
- .templateId("此处更换为自己的模板id")
- .formId("自己替换可用的formid")
- .data(Lists.newArrayList(
- new WxMaTemplateData("keyword1", "339208499", "#173177")))
- .toUser(wxMessage.getFromUser())
- .build());
- return null;
- };
-
- private final WxMaMessageHandler logHandler = (wxMessage, context, service, sessionManager) -> {
- System.out.println("收到消息:" + wxMessage.toString());
- service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("收到信息为:" + wxMessage.toJson())
- .toUser(wxMessage.getFromUser()).build());
- return null;
- };
-
- private final WxMaMessageHandler textHandler = (wxMessage, context, service, sessionManager) ->{
- service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("回复文本消息")
- .toUser(wxMessage.getFromUser()).build());
- return null;
- };
-
- private final WxMaMessageHandler picHandler = (wxMessage, context, service, sessionManager) -> {
- try {
- WxMediaUploadResult uploadResult = service.getMediaService()
- .uploadMedia("image", "png",
- ClassLoader.getSystemResourceAsStream("tmp.png"));
- service.getMsgService().sendKefuMsg(
- WxMaKefuMessage
- .newImageBuilder()
- .mediaId(uploadResult.getMediaId())
- .toUser(wxMessage.getFromUser())
- .build());
- } catch (WxErrorException e) {
- e.printStackTrace();
- }
- return null;
- };
-
- private final WxMaMessageHandler qrcodeHandler = (wxMessage, context, service, sessionManager) -> {
- try {
- final File file = service.getQrcodeService().createQrcode("123", 430);
- WxMediaUploadResult uploadResult = service.getMediaService().uploadMedia("image", file);
- service.getMsgService().sendKefuMsg(
- WxMaKefuMessage
- .newImageBuilder()
- .mediaId(uploadResult.getMediaId())
- .toUser(wxMessage.getFromUser())
- .build());
- } catch (WxErrorException e) {
- e.printStackTrace();
- }
- return null;
- };
-
- }
WxMaProperties文件
- package cn.shiyue.config.ma;
-
- import org.springframework.boot.context.properties.ConfigurationProperties;
-
- import java.util.List;
-
- @ConfigurationProperties(prefix = "wx.miniapp")
- public class WxMaProperties {
-
- private List
configs; -
- public static class Config {
- /**
- * 设置微信小程序的appid
- */
- private String appid;
-
- /**
- * 设置微信小程序的Secret
- */
- private String secret;
-
- /**
- * 设置微信小程序消息服务器配置的token
- */
- private String token;
-
- /**
- * 设置微信小程序消息服务器配置的EncodingAESKey
- */
- private String aesKey;
-
- /**
- * 消息格式,XML或者JSON
- */
- private String msgDataFormat;
-
- public String getAppid() {
- return appid;
- }
-
- public void setAppid(String appid) {
- this.appid = appid;
- }
-
- public String getSecret() {
- return secret;
- }
-
- public void setSecret(String secret) {
- this.secret = secret;
- }
-
- public String getToken() {
- return token;
- }
-
- public void setToken(String token) {
- this.token = token;
- }
-
- public String getAesKey() {
- return aesKey;
- }
-
- public void setAesKey(String aesKey) {
- this.aesKey = aesKey;
- }
-
- public String getMsgDataFormat() {
- return msgDataFormat;
- }
-
- public void setMsgDataFormat(String msgDataFormat) {
- this.msgDataFormat = msgDataFormat;
- }
- }
-
- public List
getConfigs() { - return configs;
- }
-
- public void setConfigs(List
configs) { - this.configs = configs;
- }
- }
还有一种方式在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:");