请通过浏览器功能收藏网页

微信企业号企业号微信令牌维护模块设计(线程模拟) 公众号开发

发布时间:2018-08-21 10:47:31  作者:本站编辑  来源:本站原创  浏览次数:
www.javainfo.com.cn 上干货 欢迎收藏

企业号令牌维护模块设计的原因:

   微信对于令牌获取有次数限制;于是系统若想正常运行,2000次申请次数是不满足长期运行的要求的,于是系统需要对齐定期维护更新,将更新下来的令牌存储起来,提供给消费者

  模块设计流程图:

  企业号公众号令牌维护模块.jpg

  模块设计代码功能:

  配置系统启动后  令牌维护线程自动启动

 <bean id="accessTokenConfig" class="com.dykj.dyoa.action.weixin_qyh.TimerOfAccesstokenConfig" init-method="init"></bean>

 

 线程体维护模块:

//线程监控线程 随系统启动而启动

public class TimerOfAccesstokenConfig {

public void init() {

new runThread().start();

}

}

class runThread extends Thread {

// 获取运行线程

accessTokenTask thread = null;

// 第几个线程

int i = 1;

boolean threadState = false;

public void run() {

if (thread == null) {

thread = new accessTokenTask();

thread.setDaemon(true);

thread.start();

}

while (true) {

try {

Thread.sleep(30000);

} catch (InterruptedException e) {

e.printStackTrace();

}

threadState = thread.isRunning();

// System.out.println("checking " + threadState);

// 线程终止了 发生了异常

if (threadState == false) {

if (thread.isAlive() || thread.isInterrupted()) {

thread.destroy();

}

i++;

System.out.println("获取微信令牌错误,正在尝试链接 ,第 " + i + " 次");

thread = new accessTokenTask();

thread.setDaemon(true);

thread.start();

}

}

}

}

/**

 * 访问令牌定时请求微信服务器 同步令牌 , 并将令牌存放到 文件内 accesstoken.txt

 */

class accessTokenTask extends Thread {

private String path = this.getClass().getResource("accesstoken.txt").getFile().toString();

private boolean running = true;


public boolean isRunning() {

return running;

}


public void setRunning(boolean running) {

this.running = running;

}


@Override

public void run() {

while (running) {

File file = new File(path);

try {

System.out.println(new SimpleDateFormat("YYYY-MM-dd hh:mm:ss").format(new Date()));

String newAccessToken = WeixinUtil.getAccessToken(WeixinAction.CorpID, WeixinAction.Secret);

// System.out.println(newAccessToken);

// 将此令牌存入 file内

if (!file.exists()) {

file.createNewFile();

}

if (file.canWrite()) {

FileWriter fw = new FileWriter(file);

fw.write(newAccessToken);

fw.flush();

fw.close();

Thread.sleep(60000 * 2); //2分钟一次

}

} catch (Exception e) {

this.running = false;

}

}


}

}

   令牌如何使用呢?  既然搭建的是框架,那么当然需要采用通用的模式来处理令牌数据了, 应用模式为切面模式, 编写过滤器,其内对微信的所有链接进行拦截处理,

  下面的代码只是嵌入过滤器的部分代码:

   

        /**

* 存储令牌信息的文件路径地址

*/

private String path = getClass().getResource("accesstoken.txt").getFile().toString();

/**

* 从文件中读取 访问令牌   工具函数

*/

private synchronized String getTokenFromFile() {

File file = new File(path);

if (file.exists() && file.canRead()) {

try {

FileReader fr = new FileReader(file);

BufferedReader br = new BufferedReader(fr);

String token = br.readLine();

br.close();

fr.close();

return token;

} catch (Exception e) {

e.printStackTrace();

return "no";

}

} else {

try {

Thread.sleep(50000);

this.notify();

getTokenFromFile();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

return "no";

}

   


   //过滤器核心  读取从文件中 读取令牌信息 

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,

ServletException {

HttpServletRequest hRequest = (HttpServletRequest) request;

// 请求的路径

String contextPath = hRequest.getContextPath();

// 这里读取文件获取 访问权限

String tokenFromFile = this.getTokenFromFile();

// 获取了 token的话, 同步到系统级别的缓存中

if (!"no".equals(tokenFromFile)) {

request.getServletContext().setAttribute("accessToken", tokenFromFile);

// 标记为已经读取

} else {

System.out.println("token from file fail ");

}

}


    工具函数: 

          /**

 * 获取AccessToken; 每个secret代表了对应用、通讯录的不同权限;不同的管理组拥有不同的secret。

 * 

 * @param corpid

 *            企业Id

 * @param corpsecret

 *            管理组的凭证密钥

 */

public static String getAccessToken(String corpid, String corpsecret) throws Exception {

String token_url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" + corpid + "&corpsecret="

+ corpsecret;

String access_token = null;


URL url = new URL(token_url);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setDoInput(true);

conn.setRequestMethod("GET");

InputStream inputStream = conn.getInputStream();

Reader in = new InputStreamReader(inputStream);

BufferedReader reader = new BufferedReader(in);

StringBuffer buffer = new StringBuffer();

String str = null;

while ((str = reader.readLine()) != null) {

buffer.append(str);

}

inputStream.close();

in.close();

reader.close();

conn.disconnect();

JSONObject json = JSONObject.fromObject(buffer.toString());

// System.out.println("获取的ACESStoken json str = " + json);

access_token = json.getString("access_token");

if (access_token != null) {

// System.out.println("访问令牌:" + access_token);

} else {

System.out.println("token获取失败!");

}

return access_token;


/* 注:企业号融合过程中该接口输出参数可能略有不同,以下情况均视作获取token成功:

1、能获取到access_token,接口无返回errcode

2、能获取到access_token,接口返回errcode为0, errmsg为空或者"ok"

正确的Json返回结果:

{

   "access_token": "accesstoken000001",

   "expires_in": 7200

}

b)错误的Json返回示例:

{

   "errcode": 43003,

   "errmsg": "require https"

}*/


如有疑问 请留言 欢迎提供建议

评论已有 0