文章目录
前言
access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。
一、导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.73</version>
</dependency>
二、编写配置
1.personal.yaml配置文件
我的微信小程序ID和小程序密匙都放在配置文件中。
personal.yaml文件放在resources文件夹中
wechat:
appid: AppID
secret: AppSecret
2.WeChatBean实体类
@Data
@Component
@PropertySource(value = "classpath:personal.yaml")
@ConfigurationProperties(prefix = "wechat")
public class WeChatBean {
@Value("${appid}")
private String appId;
@Value("${secret}")
private String secret;
}
3.编写RestTemplateConfig
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate (ClientHttpRequestFactory clientHttpRequestFactory) {
return new RestTemplate(clientHttpRequestFactory);
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(15000);
factory.setReadTimeout(5000);
return factory;
}
}
4. 开启定时任务
在主启动类中开始定时任务。
@EnableAsync
@MapperScan("top.ddandang.*.mapper")
@SpringBootApplication
@EnableScheduling
public class BlogBackApplication {
public static void main(String[] args) {
SpringApplication.run(BlogBackApplication.class, args);
}
}
三、实现生成和存储access_token
使用定时任务每1小时50分钟发送一次请求,然后在Redis中设置有效时间为1小时55分钟,这样可以保证不会出现不能用的情况,也不会出现Redis中不存在此Key值(除非Redis服务崩了)
1.基本介绍
接口示例:
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
RestTemplate带参发送Get请求两种方式。
方式一:
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=你的AppID&secret=你的App密匙";
ResponseEntity<String> forObject = restTemplate.getForEntity(url, String.class);
方式二:
String url = "https://api.weixin.qq.com/cgi-bin/token";
// 这里的参数要和下面的Map Key值对应
String path = "?grant_type={grant_type}&appid={appid}&secret={secret}";
Map<String, String> params = new HashMap<>(3);
params.put("grant_type", "client_credential");
params.put("appid", 你的AppID);
params.put("secret", 你的App密匙);
ResponseEntity<String> forObject = restTemplate.getForEntity(url + path, String.class, params);
2.编写Server层—WeChatServerImpl
package top.ddandang.blog.service.impl;
import com.alibaba.fastjson.JSONObject;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import top.ddandang.blog.bean.WeChatBean;
import top.ddandang.blog.service.WeChatServer;
import top.ddandang.blog.utils.RedisUtil;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* <p>
*
* </p>
*
* @author: D
* @since: 2020/9/6
* @version: 1
*/
@Service
public class WeChatServerImpl implements WeChatServer {
@Resource
WeChatBean weChatBean;
@Resource
RestTemplate restTemplate;
@Resource
RedisUtil redisUtil;
/**
* redis中存放access_token的key值
*/
private final static String ACCESS_TOKEN_KEY = "accessToken";
/**
* redis中存放获取失败的错误信息的key值
*/
private final static String ERROR_KEY = "accessToken";
@Scheduled(initialDelay = 10000,fixedRate = 6600000)
@Override
public void creatAccessToken() {
String url = "https://api.weixin.qq.com/cgi-bin/token";
String path = "?grant_type={grant_type}&appid={appid}&secret={secret}";
Map<String, String> params = new HashMap<>(3);
params.put("grant_type", "client_credential");
params.put("appid", weChatBean.getAppId());
params.put("secret", weChatBean.getSecret());
ResponseEntity<String> forObject = restTemplate.getForEntity(url + path, String.class, params);
System.out.println(forObject.getBody());
JSONObject jsonObject = JSONObject.parseObject(forObject.getBody());
String accessToken = jsonObject.getString("access_token");
System.out.println(accessToken);
// accessToken获取成功
if (accessToken != null) {
//有效期设置1小时55分钟
redisUtil.set(ACCESS_TOKEN_KEY, accessToken, 115, TimeUnit.MINUTES);
} else {
redisUtil.set(ERROR_KEY, forObject.getBody());
}
}
@Override
public String getAccessToken() {
//这大概率不会运行 除非redis连接失败或者蹦了
if (!redisUtil.hasKey(ACCESS_TOKEN_KEY)) {
throw new RuntimeException("获取失败,请稍后重试");
}
return (String) redisUtil.get(ACCESS_TOKEN_KEY);
}
}
3.编写Controller层—WeChatController
@RestController
@RequestMapping("/we_chat")
public class WeChatController {
@Resource
WeChatServer weChatServer;
@GetMapping("/getAccessToken")
public GlobalResponse getAccessToken() {
try {
String accessToken = weChatServer.getAccessToken();
return GlobalResponse.success().data("accessToken", accessToken);
} catch (RuntimeException e) {
return GlobalResponse.failed().message("获取失败,请稍后再试!");
}
}
}
4.简单解析
//单位毫秒
@Scheduled(initialDelay = 10000,fixedRate = 6600000)
项目运行的时候然后延迟10秒第一次执行这个方法,然后之后每隔1小时50分钟再次执行这方法。
ResponseEntity<String> forObject = restTemplate.getForEntity(url + path, String.class, params);
System.out.println(forObject.getBody());
getForEntity:获取全部的响应内容,包含响应头,响应码,和响应体,这里也可以直接换成getForObject只获取响应体。
响应体:
返回的响应体是一个Json格式的字符串这里使用阿里巴巴的fastjson进行转换。
String accessToken = jsonObject.getString(“access_token”);
jsonObject.getString(“access_token”)可以获取到access_token的数据,如果是错误返回的话这个就是为null后面只需要进行判断accessToken为null就是错误返回了。
将数据存放到Redis中:
这里存放时间设置为1小时55分钟,因为有效期为2小时,然后方法的自动调用为每隔1小时50分钟进行调用。这里存放错误信息只是为了方便进行在Redis中进行查看。
这里使用了Redis工具类:可以参考:Redis工具类
// accessToken获取成功
if (accessToken != null) {
//有效期设置1小时55分钟
redisUtil.set(ACCESS_TOKEN_KEY, accessToken, 115, TimeUnit.MINUTES);
} else {
redisUtil.set(ERROR_KEY, forObject.getBody());
}
总结
基本上个人的密匙之类的都放在一个配置文件中,不会直接写到类里面,花了近两个小时进行编写有什么不足之处欢迎进行交流,有什么问题也可以直接在讨论区提问。