微信 java token_Java微信公众平台开发(六)--微信开发中的token获取

(一)token的介绍

引用:access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效!

(二)token的获取参考文档

10bea9a33455fcd8f84547b07dea1ca9.png

085c64b0a248fc052affad8a7ba63123.png

(三)token获取流程分析

从公众平台获取账号的AppID和AppSecret;

token获取并解析存储执行体;

采用任务调度每隔两小时执行一次token获取执行体;

(四)token的获取流程的具体实现

①获取appid和appsecret

在微信公众平台接口测试工具中可以查看到我们需要的两个参数:

67db266af6de321a93364fa530e74aff.png

这里我们将appid 和secret 定义到配置文件【wechat.properties】,在src目录下新建【wechat.properties】文件,大致代码为:

#开发者的appid

appid=wx7e32765bc24XXXX

#开发者的AppSecret

AppSecret=d58051564fe9d86093f9XXXXX

②token获取并解析存储执行体的代码编写

由于在这里我们需要通过http的get请求向微信服务器获取时效性为7200秒的token,所以我在这里写了一个http请求的工具类HttpUtils,以方便我们的使用,如下:(这里需要导入文末的http协议包)

1 packagecom.gede.wechat.util;2 importjava.io.BufferedInputStream;3 importjava.io.BufferedReader;4 importjava.io.IOException;5 importjava.io.InputStream;6 importjava.io.InputStreamReader;7 importjava.io.OutputStreamWriter;8 importjava.net.MalformedURLException;9 importjava.net.URI;10 importjava.net.URL;11 importjava.net.URLConnection;12 importjava.util.ArrayList;13 importjava.util.List;14 importjava.util.Map;15 importjava.util.Set;16 importjava.util.zip.GZIPInputStream;17

18 importorg.apache.http.HttpResponse;19 importorg.apache.http.NameValuePair;20 importorg.apache.http.client.ClientProtocolException;21 importorg.apache.http.client.HttpClient;22 importorg.apache.http.client.entity.UrlEncodedFormEntity;23 importorg.apache.http.client.methods.HttpGet;24 importorg.apache.http.client.methods.HttpPost;25 importorg.apache.http.entity.StringEntity;26 importorg.apache.http.impl.client.DefaultHttpClient;27 importorg.apache.http.message.BasicNameValuePair;28 importorg.apache.http.protocol.HTTP;29 importorg.apache.http.util.EntityUtils;30 /**

31 *@authorgede32 *@versiondate:2019年5月26日 下午5:43:3633 * @description :34 */

35 public classHttpUtils {36

37 /**

38 * @Description: http get请求共用方法39 *@param @paramreqUrl40 *@param @paramparams41 *@param @return

42 *@param @throwsException43 */

44 @SuppressWarnings("resource")45 public static String sendGet(String reqUrl, Mapparams)46 throwsException {47 InputStream inputStream = null;48 HttpGet request = newHttpGet();49 try{50 String url =buildUrl(reqUrl, params);51 HttpClient client = newDefaultHttpClient();52

53 request.setHeader("Accept-Encoding", "gzip");54 request.setURI(newURI(url));55

56 HttpResponse response =client.execute(request);57

58 inputStream =response.getEntity().getContent();59 String result =getJsonStringFromGZIP(inputStream);60 returnresult;61 } finally{62 if (inputStream != null) {63 inputStream.close();64 }65 request.releaseConnection();66 }67

68 }69

70 @SuppressWarnings("resource")71 public static String sendPost(String reqUrl, Mapparams)72 throwsException {73 try{74 Set set =params.keySet();75 List list = new ArrayList();76 for(String key : set) {77 list.add(newBasicNameValuePair(key, params.get(key)));78 }79 if (list.size() > 0) {80 try{81 HttpClient client = newDefaultHttpClient();82 HttpPost request = newHttpPost(reqUrl);83

84 request.setHeader("Accept-Encoding", "gzip");85 request.setEntity(newUrlEncodedFormEntity(list, HTTP.UTF_8));86

87 HttpResponse response =client.execute(request);88

89 InputStream inputStream =response.getEntity().getContent();90 try{91 String result =getJsonStringFromGZIP(inputStream);92

93 returnresult;94 } finally{95 inputStream.close();96 }97 } catch(Exception ex) {98 ex.printStackTrace();99 throw new Exception("网络连接失败,请连接网络后再试");100 }101 } else{102 throw new Exception("参数不全,请稍后重试");103 }104 } catch(Exception ex) {105 ex.printStackTrace();106 throw new Exception("发送未知异常");107 }108 }109

110 public staticString sendPostBuffer(String urls, String params)111 throwsClientProtocolException, IOException {112 HttpPost request = newHttpPost(urls);113

114 StringEntity se = newStringEntity(params, HTTP.UTF_8);115 request.setEntity(se);116 //发送请求

117 @SuppressWarnings("resource")118 HttpResponse httpResponse = newDefaultHttpClient().execute(request);119 //得到应答的字符串,这也是一个 JSON 格式保存的数据

120 String retSrc =EntityUtils.toString(httpResponse.getEntity());121 request.releaseConnection();122 returnretSrc;123

124 }125

126 public staticString sendXmlPost(String urlStr, String xmlInfo) {127 //xmlInfo xml具体字符串

128

129 try{130 URL url = newURL(urlStr);131 URLConnection con =url.openConnection();132 con.setDoOutput(true);133 con.setRequestProperty("Pragma:", "no-cache");134 con.setRequestProperty("Cache-Control", "no-cache");135 con.setRequestProperty("Content-Type", "text/xml");136 OutputStreamWriter out = newOutputStreamWriter(137 con.getOutputStream());138 out.write(new String(xmlInfo.getBytes("utf-8")));139 out.flush();140 out.close();141 BufferedReader br = new BufferedReader(newInputStreamReader(142 con.getInputStream()));143 String lines = "";144 for (String line = br.readLine(); line != null; line =br145 .readLine()) {146 lines = lines +line;147 }148 return lines; //返回请求结果

149 } catch(MalformedURLException e) {150 e.printStackTrace();151 } catch(IOException e) {152 e.printStackTrace();153 }154 return "fail";155 }156

157 private staticString getJsonStringFromGZIP(InputStream is) {158 String jsonString = null;159 try{160 BufferedInputStream bis = newBufferedInputStream(is);161 bis.mark(2);162 //取前两个字节

163 byte[] header = new byte[2];164 int result =bis.read(header);165 //reset输入流到开始位置

166 bis.reset();167 //判断是否是GZIP格式

168 int headerData =getShort(header);169 //Gzip 流 的前两个字节是 0x1f8b

170 if (result != -1 && headerData == 0x1f8b) {171 //LogUtil.i("HttpTask", " use GZIPInputStream ");

172 is = newGZIPInputStream(bis);173 } else{174 //LogUtil.d("HttpTask", " not use GZIPInputStream");

175 is =bis;176 }177 InputStreamReader reader = new InputStreamReader(is, "utf-8");178 char[] data = new char[100];179 intreadSize;180 StringBuffer sb = newStringBuffer();181 while ((readSize = reader.read(data)) > 0) {182 sb.append(data, 0, readSize);183 }184 jsonString =sb.toString();185 bis.close();186 reader.close();187 } catch(Exception e) {188 e.printStackTrace();189 }190

191 returnjsonString;192 }193

194 private static int getShort(byte[] data) {195 return (data[0] << 8) | data[1] & 0xFF;196 }197

198 /**

199 * 构建get方式的url200 *201 *@paramreqUrl202 * 基础的url地址203 *@paramparams204 * 查询参数205 *@return构建好的url206 */

207 public static String buildUrl(String reqUrl, Mapparams) {208 StringBuilder query = newStringBuilder();209 Set set =params.keySet();210 for(String key : set) {211 query.append(String.format("%s=%s&", key, params.get(key)));212 }213 return reqUrl + "?" +query.toString();214 }215

216 }

我们在做http请求的时候需要目标服务器的url,这里在项目中为了方便对url的管理我们src目录下建立了interface_url.properties用于存放目标url,这里我们将请求token的url存入:

#获取token的url

tokenUrl=https://api.weixin.qq.com/cgi-bin/token

我们需要将我们配置的配置文件在项目初始化后能得到启动,所以我在这里加入一个项目初始化的代码InterfaceUrlIntiServlet来实现,用于项目启动初始化interface_url.properties和wechat.properties中的配置:

1 packagecom.gede.web.start;2 importjavax.servlet.ServletConfig;3 importjavax.servlet.ServletException;4 importjavax.servlet.http.HttpServlet;5 /**

6 *@authorgede7 *@versiondate:2019年5月26日 下午7:42:148 * @description :9 */

10 public class InterfaceUrlIntiServlet extendsHttpServlet {11

12 private static final long serialVersionUID = 1L;13

14 @Override15 public void init(ServletConfig config) throwsServletException {16 InterfaceUrlInti.init();17 }18 }

初始化的具体实现,将初始化过后的方法都存入到GlobalConstants中方便项目中随意调用,如下:

1 packagecom.gede.web.start;2 importjava.io.IOException;3 importjava.io.InputStream;4 importjava.util.Properties;5 importcom.gede.web.util.GlobalConstants;6 /**

7 *@authorgede8 *@versiondate:2019年5月26日 下午7:42:379 * @description :10 */

11 public classInterfaceUrlInti {12

13 public synchronized static voidinit(){14 ClassLoader cl =Thread.currentThread().getContextClassLoader();15 Properties props = newProperties();16 if(GlobalConstants.interfaceUrlProperties==null){17 GlobalConstants.interfaceUrlProperties = newProperties();18 }19 InputStream in = null;20 try{21 in = cl.getResourceAsStream("interface_url.properties");22 props.load(in);23 for(Object key : props.keySet()){24 GlobalConstants.interfaceUrlProperties.put(key, props.get(key));25 }26

27 props = newProperties();28 in = cl.getResourceAsStream("wechat.properties");29 props.load(in);30 for(Object key : props.keySet()){31 GlobalConstants.interfaceUrlProperties.put(key, props.get(key));32 }33

34 } catch(IOException e) {35 e.printStackTrace();36 }finally{37 if(in!=null){38 try{39 in.close();40 } catch(IOException e) {41 e.printStackTrace();42 }43 }44 }45 return;46 }47

48 }

这里用到的GlobalConstants,我们新建在web.util包里面,代码如下:

packagecom.gede.web.util;importjava.util.Properties;/***@authorgede

*@versiondate:2019年5月26日 下午7:45:27

* @description :*/

public classGlobalConstants {public staticProperties interfaceUrlProperties;/*** @Description: TODO

*@param @paramkey

*@param @return

*/

public staticString getInterfaceUrl(String key) {return(String) interfaceUrlProperties.get(key);

}

}

当我们把所有的准备工作都做好了之后我们可以开始真正的去获取token了,这里我们将获取到的token解析之后依然存储到GlobalConstants中方便使用,简单代码如下:(这里需要导入我们附件中的json包)

1 packagecom.gede.wechat.common;2 importjava.text.SimpleDateFormat;3 importjava.util.Date;4 importjava.util.HashMap;5 importjava.util.Map;6

7 importcom.gede.web.util.GlobalConstants;8 importcom.gede.wechat.util.HttpUtils;9

10 importnet.sf.json.JSONObject;11 /**

12 *@authorgede13 *@versiondate:2019年5月26日 下午7:50:3814 * @description :15 */

16 public classWeChatTask {17 /**

18 * @Description: 任务执行体19 *@param @throwsException20 */

21 public void getToken_getTicket() throwsException {22 Map params = new HashMap();23 params.put("grant_type", "client_credential");24 params.put("appid", GlobalConstants.getInterfaceUrl("appid"));25 params.put("secret", GlobalConstants.getInterfaceUrl("AppSecret"));26 String jstoken =HttpUtils.sendGet(27 GlobalConstants.getInterfaceUrl("tokenUrl"), params);28 String access_token =JSONObject.fromObject(jstoken).getString(29 "access_token"); //获取到token并赋值保存

30 GlobalConstants.interfaceUrlProperties.put("access_token", access_token);31 System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+"token为=============================="+access_token);32 }33

34 }

(三)采用任务调度每隔两小时执行一次token获取执行体

我们阅读过微信的文档会发现我们的token获取的接口每天是有调用次数限制的,为了防止我们业务量比较大的情况下token的直接调用的接口次数不够用,所以我们需要根据token的时效性(7200s)在自己的业务服务器上做到token的缓存并定时获取,我这里用到的任务调度的方式是采用quartz,下面具体代码的实现:

1 packagecom.gede.wechat.quartz;2 importorg.apache.log4j.Logger;3 importcom.gede.wechat.common.WeChatTask;4

5 /**

6 *@authorgede7 *@versiondate:2019年5月26日 下午8:00:438 * @description :9 */

10 public classQuartzJob{11 private static Logger logger = Logger.getLogger(QuartzJob.class);12 /**

13 * @Description: 任务执行获取token14 *@param

15 */

16 public voidworkForToken() {17 try{18 WeChatTask timer = newWeChatTask();19 timer.getToken_getTicket();20 } catch(Exception e) {21 logger.error(e, e);22 }23 }24 }

这里新建配置文件spring-quartz.xml以方便quartz任务的管理和启用,这里将我们需要用到的workForToken()加入到执行任务中:

1 <?xml version="1.0" encoding="UTF-8"?>

2

3

4

5

6

7

8

9 class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

10

11

12

13

14

15

16 workForToken

17

18

19

20

21

22

23

24

25

26 0 0/1 * * * ?

27

28

29

30

31 class="org.springframework.scheduling.quartz.SchedulerFactoryBean">

32

33

34

35

36

37

38

这里我为了测试将执行间隔时间设置成了1分钟一次,根据需要可以自行修改执行时间。

好了到这里我们就已经大功告成,就差初始化加载InterfaceUrlIntiServlet和开启quartz的使用:修改web.xml ,加入相关语句,代码如下:

1 <?xml version="1.0" encoding="UTF-8"?>

2

3 mychat

4

5 org.springframework.web.context.ContextLoaderListener

6

7

8 contextConfigLocation

9 classpath:applicationContext.xml,classpath:spring-quartz.xml

10

11

12

13 appServlet

14 org.springframework.web.servlet.DispatcherServlet

15

16 contextConfigLocation

17

18 classpath:appServlet.xml19

20

21 1

22

23

24

25 log4jConfigLocation

26 classpath:log4j.properties

27

28

29 org.springframework.web.util.Log4jConfigListener

30

31

32

33 interface_url-init_servlet

34 com.gede.web.start.InterfaceUrlIntiServlet

35 1

36

37

38

39 appServlet

40 /

41

42

当这一切都准备完毕之后我们启动项目,会发现每间隔一分钟就会有token获取到,这里我是将其存储在项目变量中,这里看一下我们的效果图和项目总的目录结构:

ee706d66a3088ac34ad660cb0406d205.png

cbae406e8a00469ece08102ecbf0c374.png

附件:今天需要导入的包有很多,最后我就给大家打一个压缩包,大家在运行之前将包全部导入即可。点击下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值