您的位置:首页 > 移动开发 > 微信开发

采用java单例模式实现微信AccessToken和Jsapi_ticket缓存支持

2016-02-22 09:58 661 查看
一、单例模式介绍

java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。
  单例模式有以下特点:
  1、单例类只能有一个实例。
  2、单例类必须自己创建自己的唯一实例。
  3、单例类必须给所有其他对象提供这一实例。
  单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer
Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。

二、实现

public
class JSSDKTicket {

 public static Logger logger=LogManager.getLogger(JSSDKTicket.class);

 private String ticket;

 private int expires_in;

 private long timeStamp=System.currentTimeMillis()/1000;

 //单例模式实现

 private static JSSDKTicket JSAPI_TICKET;

 public static String getTicket(){

  if (JSAPI_TICKET==null) {

   try {

    JSAPI_TICKET=getJsTicket();

   } catch (Exception e) {

    

    e.printStackTrace();

    return null;

   }

  }

  if(JSAPI_TICKET.isExpire()){

   try {

    JSAPI_TICKET=getJsTicket();

   } catch (Exception e) {

   

    e.printStackTrace();

    return null;

   }

   return getTicket();

  }else{

   return JSAPI_TICKET.ticket;

  }

  

  

  

 }

 private JSSDKTicket(){

  super();

 }

 public int getExpires_in() {

  return expires_in;

 }

 public void setExpires_in(int expires_in) {

  this.expires_in = expires_in;

 }

 public long getTimeStamp() {

  return timeStamp;

 }

 public void setTimeStamp(long timeStamp) {

  this.timeStamp = timeStamp;

 }

 public void setTicket(String ticket) {

  this.ticket = ticket;

 }

 public boolean isExpire(){

  return System.currentTimeMillis()/1000<(timeStamp+expires_in)?false:true;

 }

 private static JSSDKTicket getJsTicket() throws Exception{

  

  try(AsyncHttpClient client=new AsyncHttpClient()){

   Response response=client.prepareGet("https://api.weixin.qq.com/cgi-bin/ticket/getticket")

     .addQueryParam("access_token", WeChatAccessToken.getAccessToken()).addQueryParam("type", "jsapi").execute().get();

   Map<String,Object> result=JSONUtils.readJsonValue(response.getResponseBodyAsStream(), new TypeReference<Map<String,Object>>() {});

   logger.debug(result);

   if((int)result.get("errcode")==0){

    JSSDKTicket t=new JSSDKTicket();

    t.setTicket((String) result.get("ticket"));

    t.setExpires_in((int) result.get("expires_in"));

    return t;

   }else{

    throw new Exception(result.get("access_token missing").toString());

   }

  }

 }

}



accessToken单例模式实现

public
class WeChatAccessToken {

 private String access_token;

 private int expires_in;

 private Date time = new Date();

 

 public boolean isExpires() {

  long secends = System.currentTimeMillis() - this.time.getTime();

  return secends > this.expires_in * 1000 ? true : false;

 }

 //类静态对象

 private static WeChatAccessToken accessToken;

 

 //单例模式实现

 public static String getAccessToken() throws Exception {

  if (accessToken == null) {

   try {

    getWeChatAccessToken();

   } catch (IOException e) {

    e.printStackTrace();

   }

  } else if (accessToken.isExpires()) {

   try {

    getWeChatAccessToken();

   } catch (IOException e) {

    e.printStackTrace();

   }

  }

  return accessToken.getAccess_token();

 }

 @Override

 public String toString() {

  return "WeChatAccessToken [access_token=" + access_token

    + ", expires_in=" + expires_in + ", time=" + time

    + ", isExpires()=" + isExpires() + "]";

 }

 private
static void getWeChatAccessToken() throws Exception {

  ObjectMapper mapper = new ObjectMapper();

  try(AsyncHttpClient client=new AsyncHttpClient()){

   Response response=client.prepareGet(WeChatConfiguration.URL_GET_ACCESS_TOKEN)

     .addQueryParam("grant_type", "client_credential")

     .addQueryParam("appid", WeChatConfiguration.getInstance().getAppId())

     .addQueryParam("secret", WeChatConfiguration.getInstance().getAppKey())

     .execute().get();

     Map<String,Object> result=JSONUtils.readJsonValue(response.getResponseBodyAsStream(), new TypeReference<Map<String,Object>>() {});

     if(result.containsKey("access_token")){

      String value = mapper.writeValueAsString(result);

      accessToken = mapper.readValue(value, WeChatAccessToken.class);

     }else{

      throw new Exception(result.get("errcode").toString());

     }

     

  } 

  

 }

 

 public String getAccess_token() {

  return access_token;

 }

 public
void setAccess_token(String access_token) {

  this.access_token = access_token;

 }

 public
int getExpires_in() {

  return expires_in;

 }

 public
void setExpires_in(int expires_in) {

  this.expires_in = expires_in;

 }

}



三、存在问题

这种实现对单个应用系统实用,如果是分布式部署的多个系统就不在实用,而是应用缓存系统实现更为妥当,例如memcached


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  缓存 单例模式