多次调用同一个 Controller 方法,由于 Spring 的 Controller 是单例的,因此如果我们在 Controller 里面修改了属性值,就会破坏我们的逻辑。
场景:实现【用户管理】【网页授权获取用户基本信息】第二步:通过code 换取网页授权 access_token 。
我在 Controller 里声明了一个引导用户在微信客户端打开的 url 链接:
@Controller
public class WeixinController {
@Autowired
private Config config;
/**
* 引导用户用微信客户端打开的链接,以获取 code
*/
private String redirectUrlOpenInWeixin = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
// http://192.168.199.121:8080/openid?weixinName=liwei
@RequestMapping(value="/openid",method=RequestMethod.GET)
public String getOpenid(String weixinName) throws UnsupportedEncodingException{
if("liwei".equals(weixinName)){
System.out.println("获取李威的微信公众号配置");
System.out.println(config.LIWEI_APPID);
System.out.println(config.LIWEI_APPSECRET);
redirectUrlOpenInWeixin = redirectUrlOpenInWeixin.replace("APPID", config.LIWEI_APPID);
redirectUrlOpenInWeixin = redirectUrlOpenInWeixin.replace("REDIRECT_URI", URLEncoder.encode(config.REDIRECT_URI,"utf-8"));
// snsapi_userinfo || snsapi_base
redirectUrlOpenInWeixin = redirectUrlOpenInWeixin.replace("SCOPE", "snsapi_base");
}
return "redirect:" + redirectUrlOpenInWeixin;
}
分析:这样写看起来是没有问题的,但是下面的这行代码
redirectUrlOpenInWeixin = redirectUrlOpenInWeixin.replace("APPID", config.LIWEI_APPID);
redirectUrlOpenInWeixin = redirectUrlOpenInWeixin.replace("REDIRECT_URI", URLEncoder.encode(config.REDIRECT_URI,"utf-8"));
在第 2 次调用的时候,没有起到作用。因为第 2 次调用的时候 ,url 链接里面已经没有了 APPID 和 REDIRECT_URI 这两个“常量”。好在这是一个常量,多次调用返回的是同一个结果,没有问题!
我们打印一下日志,可以分析到:
第 1 次调用时:
即将被替换的 url https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
第 2 次调用时:
即将被替换的 url https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx021dc52436e8f72c&redirect_uri=http%3A%2F%2Fliwei.tunnel.mobi%2FaccessToken&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect
可以看到,由于单利模式的作用,字符串已经被替换,第 2 次调用的时候
redirectUrlOpenInWeixin = redirectUrlOpenInWeixin.replace("APPID", config.LIWEI_APPID);
redirectUrlOpenInWeixin = redirectUrlOpenInWeixin.replace("REDIRECT_URI", URLEncoder.encode(config.REDIRECT_URI,"utf-8"));
这两行代码事实上已经起不到什么作用了。
总结:
1、寻找 bug 的思路不清晰,只关注结果,但没有仔细分析问题出在哪里。