[JAVA实现]微信公众号网页授权登录,java开发面试笔试题

Java实现基于微信测试公众号授权扫码登录自建项目 如果网页授权作用域为snsapi_userinfo,则此时开发者可以通过access_token和openid拉取用户信息了。请求方法access_token=第三步获取到的access_token&openid=测试公众号的OPENID&lang=zh_CN"sex": 1,三、自建项目:前端二维码生成,后端接口进行登录验证授权。 阅读详情


我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家。
扫描二维码或搜索下图红色VX号,加VX好友,拉你进【程序员面试学习交流群】免费领取。也欢迎各位一起在群里探讨技术。
推荐文章:Java 面试知识点解析;Mysql优化技巧(数据库设计、命名规范、索引优化

 

网上搜资料时,网友都说官方文档太垃圾了不易看懂,如何如何的。现在个人整理了一个通俗易懂易上手的,希望可以帮助到刚接触微信接口的你。

 

请看流程图!看懂图,就懂了一半了:

其实整体流程大体只需三步:用户点击登录按钮(其实就相当于一个链接) ---》 用户点击授权登录 ----》 实现获取用户信息代码。

然后获取用户信息代码只需三步:获取code ----》 通过code获取access_token和openId ---》 通过access_token和openId获取用户信息(包含union)。

以上便是整体套路,当然官网上也有,但具体如何实现呢?

不着急,咱们一步一步来!

第一步:微信登录按钮

它其实就是一个连接,不过想得到这个链接,有一点点麻烦。

1、设置。 微信公众平台---》接口权限---》网页授权---》修改 ---》设置网页授权域名(域名,不含http://),其实就是微信调你的java方法的项目路径或项目域名,如:www.zzff.net/pp ---》点击设置后弹出页面(大致意思,将MP_verify_31qRIDcjN8ZD1lVJ.txt放在你项目路径下面,如:www.ffzz.net/pp/MP_verify_31qRIDcjN8ZD1lVJ.txt 能访问到) ---》点击确认,授权回调页面域名设置成功!

2、拼链接。 https://open.weixin.qq.com/connect/oauth2/authorize?appid=xxx公众号IDxxxxx & redirect_uri = 授权回调页面域名/你的action(即微信授权后跳向的地址)

& response_type=code(固定的) & scope = snsapi_userinfo(或者snsapi_base默认授权) & state=STATE#wechat_redirect

如:https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

这个链接中参数的具体含义,官方解释如下:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

参数是否必须说明
appid是公众号的唯一标识
redirect_uri是授权后重定向的回调链接地址,请使用urlencode对链接进行处理
response_type是返回类型,请填写code
scope是应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息)
state否重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
#wechat_redirect是无论直接打开还是做页面302重定向时候,必须带此参数

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

第二步:授权确认登录

这一步最简单,第一步登录链接拼好后,在手机微信中打开,微信便会跳转到确认授权页面,点击确认授权即可。(这一步,不用开发者做处理!)

第三步:获取用户信息 (重点)
这一步便是真正的代码实现的地方。开篇便讲了,它只需三步:获取code ----》 通过code获取access_token和openId ---》 通过access_token和openId获取用户信息。

First: 获取code

Second: 获取网页授权access_token和openId

Third:通过access_token和openId获取用户信息。

关于union机制的细节:如果开发者需要公众号微信登录和APP微信登录共用一个微信ID,那个就需要union机制了。其实很简单,只需在微信开放平台(open.weixin.qq.com)绑定公众号,获取用户信息时就会返回union字段。

具体代码实现为:实体 ---- 方法 --- 工具

实体Oauth2Token:



 

 1 package com.wfcm.wxUitls;

 2 

 3 /**

 4 * 类名: WeixinOauth2Token </br>

 5 * 描述:  网页授权信息  </br>

 6 * 创建时间:  2015-11-27 </br>

 7 * 发布版本:V1.0  </br>

 8  */

 9 public class Oauth2Token {

10     // 网页授权接口调用凭证

11     private String accessToken;

12     // 凭证有效时长

13     private int expiresIn;

14     // 用于刷新凭证

15     private String refreshToken;

16     // 用户标识

17     private String openId;

18     // 用户授权作用域

19     private String scope;

20 

21     public String getAccessToken() {

22         return accessToken;

23     }

24 

25     public void setAccessToken(String accessToken) {

26         this.accessToken = accessToken;

27     }

28 

29     public int getExpiresIn() {

30         return expiresIn;

31     }

32 

33     public void setExpiresIn(int expiresIn) {

34         this.expiresIn = expiresIn;

35     }

36 

37     public String getRefreshToken() {

38         return refreshToken;

39     }

40 

41     public void setRefreshToken(String refreshToken) {

42         this.refreshToken = refreshToken;

43     }

44 

45     public String getOpenId() {

46         return openId;

47     }

48 

49     public void setOpenId(String openId) {

50         this.openId = openId;

51     }

52 

53     public String getScope() {

54         return scope;

55     }

56 

57     public void setScope(String scope) {

58         this.scope = scope;

59     }

60 }





View Code

实体SNSUserInfo:



 

  1 package com.wfcm.wxUitls;

  2 

  3 import java.util.List;

  4 

  5 /**

  6 * 类名: SNSUserInfo </br>

  7 * 描述: 通过网页授权获取的用户信息 </br>

  8 * 开发人员: wzf </br>

  9 * 创建时间:  2015-11-27 </br>

 10 * 发布版本:V1.0  </br>

 11  */

 12 public class SNSUserInfo {

 13     // 用户标识

 14     private String openId;

 15     // 用户昵称

 16     private String nickname;

 17     // 性别(1是男性,2是女性,0是未知)

 18     private int sex;

 19     // 国家

 20     private String country;

 21     // 省份

 22     private String province;

 23     // 城市

 24     private String city;

 25     // 用户头像链接

 26     private String headImgUrl;

 27     // 用户特权信息

 28     private List<String> privilegeList;

 29     

 30     private String unionid;

 31 

 32     public String getUnionid() {

 33         return unionid;

 34     }

 35 

 36     public void setUnionid(String unionid) {

 37         this.unionid = unionid;

 38     }

 39 

 40     public String getOpenId() {

 41         return openId;

 42     }

 43 

 44     public void setOpenId(String openId) {

 45         this.openId = openId;

 46     }

 47 

 48     public String getNickname() {

 49         return nickname;

 50     }

 51 

 52     public void setNickname(String nickname) {

 53         this.nickname = nickname;

 54     }

 55 

 56     public int getSex() {

 57         return sex;

 58     }

 59 

 60     public void setSex(int sex) {

 61         this.sex = sex;

 62     }

 63 

 64     public String getCountry() {

 65         return country;

 66     }

 67 

 68     public void setCountry(String country) {

 69         this.country = country;

 70     }

 71 

 72     public String getProvince() {

 73         return province;

 74     }

 75 

 76     public void setProvince(String province) {

 77         this.province = province;

 78     }

 79 

 80     public String getCity() {

 81         return city;

 82     }

 83 

 84     public void setCity(String city) {

 85         this.city = city;

 86     }

 87 

 88     public String getHeadImgUrl() {

 89         return headImgUrl;

 90     }

 91 

 92     public void setHeadImgUrl(String headImgUrl) {

 93         this.headImgUrl = headImgUrl;

 94     }

 95 

 96     public List<String> getPrivilegeList() {

 97         return privilegeList;

 98     }

 99 

100     public void setPrivilegeList(List<String> privilegeList) {

101         this.privilegeList = privilegeList;

102     }

103 }





View Code

方法WxController(其中authorize() 方法就是请求第一步获取的链接):



 

  1 package com.wfcm.controller;

  2 

  3 import java.io.BufferedReader;

  4 import java.io.IOException;

  5 import java.io.InputStreamReader;

  6 import java.io.UnsupportedEncodingException;

  7 import java.net.URL;

  8 import java.net.URLConnection;

  9 import java.net.URLEncoder;

 10 import java.security.MessageDigest;

 11 import java.security.NoSuchAlgorithmException;

 12 import java.util.ArrayList;

 13 import java.util.Formatter;

 14 import java.util.HashMap;

 15 import java.util.List;

 16 import java.util.Map;

 17 import java.util.UUID;

 18 

 19 import javax.servlet.http.HttpServletRequest;

 20 import javax.servlet.http.HttpServletResponse;

 21 

 22 import org.apache.http.client.utils.URLEncodedUtils;

 23 import org.json.JSONObject;

 24 import org.slf4j.Logger;

 25 import org.slf4j.LoggerFactory;

 26 import org.springframework.beans.factory.annotation.Autowired;

 27 import org.springframework.stereotype.Controller;

 28 import org.springframework.web.bind.annotation.RequestMapping;

 29 import org.springframework.web.bind.annotation.ResponseBody;

 30 

 31 import com.alibaba.fastjson.JSON;

 32 import com.alibaba.fastjson.JSONArray;

 33 import com.alibaba.fastjson.util.IOUtils;

 34 import com.wfcm.annotation.IgnoreSign;

 35 import com.wfcm.annotation.IgnoreToken;

 36 import com.wfcm.entity.WfMemberEntity;

 37 import com.wfcm.service.WfMemberService;

 38 import com.wfcm.service.WfMemberSessionService;

 39 import com.wfcm.utils.FastJSONUtils;

 40 import com.wfcm.utils.NetUtil;

 41 import com.wfcm.utils.R;

 42 import com.wfcm.wxUitls.AccessToken;

 43 import com.wfcm.wxUitls.JsapiTicket;

 44 import com.wfcm.wxUitls.Oauth2Token;

 45 import com.wfcm.wxUitls.SNSUserInfo;

 46 

 47 @Controller

 48 @RequestMapping("/wx")

 49 @ResponseBody

 50 public class WxController {

 51 

 52     private static  Logger log = LoggerFactory.getLogger(WxController.class);

 53      

 54     

 55     /**

 56      * 向指定URL发送GET方法的请求

 57      * 

 58      * @param url

 59      *            发送请求的URL

 60      * @param param

 61      *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。

 62      * @return URL 所代表远程资源的响应结果

 63      * 

 64      * 用户同意授权,获取code

 65      */ 

 66     @RequestMapping("/authorize")

 67     @ResponseBody

 68     @IgnoreToken

 69     public static R authorize() {

 70         String appid = "wxbb000000000e";

 71         //String uri ="wftest.zzff.net/wx/weixinLogin"; 

 72         String uri = urlEncodeUTF8("wftest.zzff.net/api/wx/weixinLogin");

 73         String result = "";

 74         BufferedReader in = null;

 75         try {

 76             String urlNameString = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="+appid+"&redirect_uri="+uri+"&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";

 77             

 78             URL realUrl = new URL(urlNameString);

 79             // 打开和URL之间的连接

 80             URLConnection connection = realUrl.openConnection();

 81             // 设置通用的请求属性

 82             connection.setRequestProperty("accept", "*/*");

 83             connection.setRequestProperty("connection", "Keep-Alive");

 84             connection.setRequestProperty("user-agent",

 85                     "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");

 86             // 建立实际的连接

 87             connection.connect();

 88             // 获取所有响应头字段

 89             Map<String, List<String>> map = connection.getHeaderFields();

 90             // 遍历所有的响应头字段

 91             for (String key : map.keySet()) {

 92                 System.out.println(key + "--->" + map.get(key));

 93             }

 94             // 定义 BufferedReader输入流来读取URL的响应

 95             in = new BufferedReader(new InputStreamReader(

 96                     connection.getInputStream()));

 97             String line =null;

 98             while ((line = in.readLine()) != null) {

 99                 result += line;

100             }

101             /*  com.alibaba.fastjson.JSONObject jsonObj= FastJSONUtils.getJSONObject(result);  

102                 String access_token = jsonObj.getString("access_token");

103                 long expires_in = Long.valueOf(jsonObj.getString("expires_in"));

104             */

105         } catch (Exception e) {

106             System.out.println("发送GET请求出现异常!" + e);

107             e.printStackTrace();

108         }

109         // 使用finally块来关闭输入流

110         finally {

111             try {

112                 if (in != null) {

113                     in.close();

114                 }

115             } catch (Exception e2) {

116                 e2.printStackTrace();

117             }

118         }

119         return  R.ok(result);

120     }    

121     

122     @RequestMapping("/weixinLogin")

123     @ResponseBody

124     @IgnoreToken

125     @IgnoreSign

126     public void weixinLogin(HttpServletRequest request,HttpServletResponse response) throws Exception {  

127         // 用户同意授权后,能获取到code

128         Map<String, String[]> params = request.getParameterMap();//针对get获取get参数  

129         String[] codes = params.get("code");//拿到code的值 

130         String code = codes[0];//code  

131         //String[] states = params.get("state");

132         //String state = states[0];//state 

133         

134         System.out.println("****************code:"+code);          

135         // 用户同意授权

136         if (!"authdeny".equals(code)) {

137              // 获取网页授权access_token

138             Oauth2Token oauth2Token = getOauth2AccessToken("wxb0000000000e", "4c22222233333335555a9", code);

139             System.out.println("***********************************oauth2Token信息:"+oauth2Token.toString());

140             // 网页授权接口访问凭证

141             String accessToken = oauth2Token.getAccessToken();

142             // 用户标识

143             String openId = oauth2Token.getOpenId();

144             // 获取用户信息

145             SNSUserInfo snsUserInfo = getSNSUserInfo(accessToken, openId);

146             System.out.println("***********************************用户信息unionId:"+snsUserInfo.getUnionid()+"***:"+snsUserInfo.getNickname());

147             // 设置要传递的参数

148             

149             //具体业务start

150 

151            //具体业务end

152 

153             String url = "http://wftest.zzff.net/#/biddd?from=login&tokenId="+snsUserInfo.getUnionid();

154             

155             response.sendRedirect(url); 

156             return ;

157         }

158     }  

159 

160     

161     /**

162      * 获取网页授权凭证

163      * 

164      * @param appId 公众账号的唯一标识

165      * @param appSecret 公众账号的密钥

166      * @param code

167      * @return WeixinAouth2Token

168      */

169     public static Oauth2Token getOauth2AccessToken(String appId, String appSecret, String code) {

170         Oauth2Token wat = null;

171         // 拼接请求地址

172         String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";

173         requestUrl = requestUrl.replace("APPID", appId);

174         requestUrl = requestUrl.replace("SECRET", appSecret);

175         requestUrl = requestUrl.replace("CODE", code);

176         // 获取网页授权凭证

177         com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(NetUtil.get(requestUrl));

178         if (null != jsonObject) {

179             try {

180                 wat = new Oauth2Token();

181                 wat.setAccessToken(jsonObject.getString("access_token"));

182                 wat.setExpiresIn(jsonObject.getInteger("expires_in"));

183                 wat.setRefreshToken(jsonObject.getString("refresh_token"));

184                 wat.setOpenId(jsonObject.getString("openid"));

185                 wat.setScope(jsonObject.getString("scope"));

186             } catch (Exception e) {

187                 wat = null;

188                 int errorCode = jsonObject.getInteger("errcode");

189                 String errorMsg = jsonObject.getString("errmsg");

190                 log.error("获取网页授权凭证失败 errcode:{} errmsg:{}", errorCode, errorMsg);

191             }

192         }

193         return wat;

194     }

195     

196     /**

197      * 通过网页授权获取用户信息

198      * 

199      * @param accessToken 网页授权接口调用凭证

200      * @param openId 用户标识

201      * @return SNSUserInfo

202      */

203     public static SNSUserInfo getSNSUserInfo(String accessToken, String openId) {

204         SNSUserInfo snsUserInfo = null;

205         // 拼接请求地址

206         String requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";

207         requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);

208         // 通过网页授权获取用户信息

209         com.alibaba.fastjson.JSONObject jsonObject =  JSON.parseObject(NetUtil.get(requestUrl));

210 

211         if (null != jsonObject) {

212             try {

213                 snsUserInfo = new SNSUserInfo();

214                 // 用户的标识

215                 snsUserInfo.setOpenId(jsonObject.getString("openid"));

216                 // 昵称

217                 snsUserInfo.setNickname(jsonObject.getString("nickname"));

218                 // 性别(1是男性,2是女性,0是未知)

219                 snsUserInfo.setSex(jsonObject.getInteger("sex"));

220                 // 用户所在国家

221                 snsUserInfo.setCountry(jsonObject.getString("country"));

222                 // 用户所在省份

223                 snsUserInfo.setProvince(jsonObject.getString("province"));

224                 // 用户所在城市

225                 snsUserInfo.setCity(jsonObject.getString("city"));

226                 // 用户头像

227                 snsUserInfo.setHeadImgUrl(jsonObject.getString("headimgurl"));

228                 // 用户特权信息

229                 List<String> list = JSON.parseArray(jsonObject.getString("privilege"),String.class);

230                 snsUserInfo.setPrivilegeList(list);

231                 //与开放平台共用的唯一标识,只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。

232                 snsUserInfo.setUnionid(jsonObject.getString("unionid"));

233             } catch (Exception e) {

234                 snsUserInfo = null;

235                 int errorCode = jsonObject.getInteger("errcode");

236                 String errorMsg = jsonObject.getString("errmsg");

237                 log.error("获取用户信息失败 errcode:{} errmsg:{}", errorCode, errorMsg);

238             }

239         }

240         return snsUserInfo;

241     }

242    

243     /**

244      * URL编码(utf-8)

245      * 

246      * @param source

247      * @return

248      */

249     public static String urlEncodeUTF8(String source) {

250         String result = source;

251         try {

252             result = java.net.URLEncoder.encode(source, "utf-8");

253         } catch (UnsupportedEncodingException e) {

254             e.printStackTrace();

255         }

256         return result;

257     }

258     

259     private static String byteToHex(final byte[] hash) {

260         Formatter formatter = new Formatter();

261         for (byte b : hash)

262         {

263             formatter.format("%02x", b);

264         }

265         String result = formatter.toString();

266         formatter.close();

267         return result;

268     }

269 

270     private static String create_nonce_str() {

271         return UUID.randomUUID().toString();

272     }

273 

274     private static String create_timestamp() {

275         return Long.toString(System.currentTimeMillis() / 1000);

276     }

277 }





View Code

工具NetUtil:



 

 1 package com.wfcm.utils;

 2 

 3 import java.io.BufferedInputStream;

 4 import java.io.IOException;

 5 import java.io.InputStreamReader;

 6 import java.io.UnsupportedEncodingException;

 7 import java.util.ArrayList;

 8 import java.util.Collection;

 9 import java.util.List;

10 import java.util.Map;

11 

12 import org.apache.commons.httpclient.NameValuePair;

13 import org.apache.http.HttpEntity;

14 import org.apache.http.HttpResponse;

15 import org.apache.http.client.entity.UrlEncodedFormEntity;

16 import org.apache.http.client.methods.HttpGet;

17 import org.apache.http.client.methods.HttpPost;

18 import org.apache.http.impl.client.CloseableHttpClient;

19 import org.apache.http.impl.client.HttpClientBuilder;

20 import org.apache.http.message.BasicNameValuePair;

21 

22 /**

23  * Created by Song on 2016/11/28.

24  * 基于HttpClient提供网络访问工具

25  */

26 public final class NetUtil {

27     public static CloseableHttpClient httpClient = HttpClientBuilder.create().build();

28 

29     /**

30      * get请求获取String类型数据

31      * @param url 请求链接

32      * @return

33      */

34     public static String get(String url){

35         StringBuffer sb = new StringBuffer();

36         HttpGet httpGet = new HttpGet(url);

37         try {

38             HttpResponse response = httpClient.execute(httpGet);           //1

39 

40             HttpEntity entity = response.getEntity();

41             InputStreamReader reader = new InputStreamReader(entity.getContent(),"utf-8");

42             char [] charbufer;

43             while (0<reader.read(charbufer=new char[10])){

44                 sb.append(charbufer);

45             }

46         }catch (IOException e){//1

47             e.printStackTrace();

48         }finally {

49             httpGet.releaseConnection();

50         }

51         return sb.toString();

52     }

53 

54     /**

55      * post方式请求数据

56      * @param url 请求链接

57      * @param data post数据体

58      * @return

59      */

60     @SuppressWarnings("unchecked")

61     public static String post(String url, Map<String,String> data){

62         StringBuffer sb = new StringBuffer();

63         HttpPost httpPost = new HttpPost(url);

64         List<NameValuePair> valuePairs = new ArrayList<NameValuePair>();

65         if(null != data) {

66             for (String key : data.keySet()) {

67                 valuePairs.addAll((Collection<? extends NameValuePair>) new BasicNameValuePair(key, data.get(key)));

68             }

69         }

70         try {

71             httpPost.setEntity(new UrlEncodedFormEntity((List<? extends org.apache.http.NameValuePair>) valuePairs));

72             HttpResponse response = httpClient.execute(httpPost);

73             HttpEntity httpEntity = response.getEntity();

74             BufferedInputStream bis = new BufferedInputStream(httpEntity.getContent());

75             byte [] buffer;

76             while (0<bis.read(buffer=new byte[128])){

77                 sb.append(new String(buffer,"utf-8"));

78             }

79         }catch (UnsupportedEncodingException e){//数据格式有误

80             e.printStackTrace();

81         }catch (IOException e){//请求出错

82             e.printStackTrace();

83         }finally {

84             httpPost.releaseConnection();

85         }

86         return sb.toString();

87     }

88     

89     

90  }





View Code

R类:



 

package com.wfcm.utils;

import java.util.HashMap;

import java.util.Map;

/**

 * 返回数据

 * 

 * @author xlf

 * @email xlfbe696@gmail.com

 * @date 2017年4月19日 上午11:58:56

 */

public class R extends HashMap<String, Object> {

    private static final long serialVersionUID = 1L;

    public static final String SUCCESS = "success";

    

    public static final String EXCEPTION = "exception";

    

    public static final Integer SUCCESSCODE = 0;

        

    public static final Integer EXCEPTIONCODE = 500;

    

    public R() {

        put("errCode", 0);

        put("msg", SUCCESS);

    }

    

    public R(int code, String msg){

           put("errCode", code);

            put("msg", msg);

    }

    public static R error() {

        return error(500, "未知异常,请联系管理员");

    }

    public static R error(String msg) {

        return error(500, msg);

    }

    public static R error(int code, String msg) {

        R r = new R();

        r.put("errCode", code);

        r.put("msg", msg);

        return r;

    }

    public static R ok(String msg) {

        R r = new R();

        r.put("msg", msg);

        return r;

    }

    public static R ok(Map<String, Object> map) {

        R r = new R();

        r.putAll(map);

        return r;

    }

    public static R ok() {

        return new R();

    }

    public R put(String key, Object value) {

        super.put(key, value);

        return this;

    }

}





View Code

OK,大功告成!整体流程已经搭建起来,读懂了这些代码差不多就明白了整个流程了,然后再看官方文档,你会觉得读起来很顺畅,而不是刚开始那种味同嚼蜡的感觉。你只需再根据官方文档仔细检查检查流程,有没有需要完善的地方,就可以了。

还等什么呢,赶快敲实现功能吧!!!

 


转载:https://www.cnblogs.com/hero123/p/9010506.html

推荐内容:
java的@PostConstruct注解
转:Java后端面试自我学习
java加载properties文件的几种方式
java 一次CPU占用过高问题的排查及解决
java后台导出excel代码详细讲解
Java方向如何准备BAT技术面试答案(汇总版)
两道面试题,带你解析Java类加载机制
2018 java BAT最新面试宝典
JAVA日志的前世今生
Java并发之线程池ThreadPoolExecutor源码分析学习

 

手把手教你用WF100DPZ数字压力传感器搞定I2C/SPI通信(附完整寄存器解析) 本文详细解析了WF100DPZ数字压力传感器的I2C与SPI通信驱动方法,涵盖硬件连接、寄存器配置、数据读取流程及常见问题排查。该传感器内置24位ADC和出厂校准,通过实战代码演示了如何稳定获取高精度压力与温度数据,帮助开发者快速集成到嵌入式项目中。 阅读详情

相关推荐

干扰管理学习日志4-------信道估计方法 LS(最小二乘)、MMSE(最小均方误差)

信道估计,就是从接收数据中将假定的某个信道模型的模型参数估计出来的过程。如果信道是线性的话,那么信道估计就是对系统冲激响应进行估计。需强调的是信道估计是信道对输入信号影响的一种数学表示,而“好”的信道估计则是使得某种估计误差最小化的估计算法。本文主要讲述非盲信道估计中的LS估计和MMSE估计。LS全称为,即估计的信道参数与实际信道参数的差,进行平方求和后得到的误差累积最小。MMSE估计是LS估计的改进,在LS估计的最终结果的基础上乘以加权矩阵,使之与实际信道参数更为接近。

taiyuezyh的博客 1万+

微信扫码登录实战(附代码)

作者 | 来碗Java编辑 | 王久一公号 | Java葵花宝典导读:由于微信端流量比较足,所以扫码登录系统功能也受到了很多系统的青睐,本文就来详细的解开该技术的面纱。...

公众号:Java后端 3491

人形机器人系列——硬件介绍

人形机器人是多领域交叉技术的产物,主要由三大系统组成:感知系统、决策系统和执行系统。感知系统感知系统是人形机器人获取外界信息的途径,主要由各种传感器组成。其中,视觉传感器用于获取图像信息,如摄像头、激光雷达等;触觉传感器用于感知触碰和压力,如力/力矩传感器、声学传感器等。这些传感器收集到的信息为机器人的决策和执行提供基础。决策系统决策系统是人形机器人的大脑,负责处理和决策各种信息。它由芯片和算法组成。芯片是硬件基础,提供计算能力;算法是软件基础,用于处理和分析传感器收集到的信息,并做出相应的决策。执行系统。

liangwqi的博客 1万+

JAVA实现微信授权登录(详解)

JAVA实现微信授权登录(详解) 第一步:(前期设置)登录微信公众号接口测试平台设置信息 链接:http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login 登录成功后可以看到测试用的appid和appsecret,稍后再后台我们要用到这两个ID,如下图 紧接着需要设置网页授权(体验接口权限表 —》 网页服务 —》网页帐号 —》 ...

Ellis_li 的博客 2万+

ESP32-C5硬件设计全链路指南:ADC/SDIO/USB/RF PCB实战

模数转换器(ADC)和高速外设接口是嵌入式系统硬件设计的核心基础。理解ADC通道映射、输入阻抗特性与抗干扰布线,是保障传感器采样精度的前提;掌握SDIO、USB差分信号的阻抗控制、端接策略与电源去耦方法,则直接决定通信可靠性与EMC性能。在Wi-Fi 6/Bluetooth 5.3双模SoC如ESP32-C5中,ADC复用约束、USB与SDIO管脚冲突、RF匹配网络调校、四层板叠层规划等工程细节,共同构成高成功率PCB落地的关键技术栈。本文聚焦ESP32-C5平台,系统梳理从模拟前端到射频输出的硬件设计规范

weixin_35756130的博客 345

汇川AM系列PLC玩转CNC:手把手教你用File模式读取G代码文件(附避坑指南)

本文详细介绍了如何使用汇川AM系列PLC的File模式读取G代码文件,涵盖从CAD设计到PLC配置的全流程。特别针对路径格式、文件类型等常见问题提供避坑指南,帮助工程师快速实现CNC加工的自动化控制。

weixin_33582311的博客 407

java如何实现微信授权登录

要在 Java 中实现微信授权登录,需要按照以下步骤操作: 在微信开放平台(https://open.weixin.qq.com/)申请微信登录的第三方平台资格,并获取相应的 AppID 和 AppSecret。 使用 Java 的网络编程库(如 HttpClient)向微信的授权服务器发送请求,获取临时登录凭证(code)。 使用 AppID 和 AppSecret 向微信的授权服务器发送...

weixin_35753291的博客 2996

LoRa双端通信稳定性核心:同步字配置与LLCC68工程实践

LoRa是一种基于扩频调制的远距离低功耗无线通信技术,其物理层鲁棒性依赖于发射端与接收端在频率、带宽、扩频因子及同步字等关键参数上的严格一致。同步字作为LoRa帧结构中位于前导码之后的2字节标识字段,承担着物理层帧过滤与网络隔离的核心作用,直接影响通信成功率与抗干扰能力。在实际嵌入式开发中,尤其采用LLCC68等专用射频芯片时,同步字配置错误或双端不一致是导致‘能发不能收’‘间歇性丢包’等典型问题的首要原因。本文面向STM32等Cortex-M平台开发者,结合硬件一致性约束、驱动移植方法论与寄存器级调试手段

weixin_36019375的博客 130

微信oauth2授权登录实践

1、准备工作 微信公众平台测试号申请一个帐号,扫码登录 扫码关注一下,否则获取授权码时报错 授权成功回调地址redirect_url配置,可配置baidu.com,有些域名会有问题 绑定微信开发者账号 二、按照文档走oauth2授权码流程 1.获取授权码。scope为snsapi_base为静默模式及自动授权不会弹框,而snsapi_userinfo则必须显示点击确认授权按钮。redirecurl需要URLencode一下。 https://open.weixin.qq.com

MJ的博客 1万+

面向边缘计算的YOLOv12模型剪枝-蒸馏联合优化实战教程**

这套剪枝-蒸馏联合方案的优势在于其系统性和可靠性。它不是单一的技巧,而是一套完整的工程流程,确保了从研发到部署的无缝衔接。

FJN110的博客 159

从一个 ASIN 看透亚马逊:商品模型背后的增长飞轮

在亚马逊电商体系中,每件商品背后都有一套严密的商品建模逻辑。本篇文章以“ASIN 的一生”为线索,系统拆解了亚马逊的商品模型:从飞轮战略出发,剖析 SDP(Single Detail Page)机制如何实现标准化展示;再到 ASIN 编码、父子变体结构与 Offer 分离模型,逐层解析商品信息如何被建构、聚合与呈现。通过图解与案例,文章帮助读者理解商品建品流程、同款聚合原则、价格控制机制等核心逻辑,避免常见运营误区,是一份面向运营、产品、技术人员的实用参考指南。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 13万+

前端实习生微信笔试题(附笔者答案)/ 深圳 day:1.10

前端面试题 请简单描述html、css、js(2分) 1.1:html是超文本标记语言,是用来描述网页的一种语言 1.2:CSS是层叠样式表,用于对HTML的元素进行渲染,美化页面 1.3:JavaScript是一种脚本语言,是单线程的。源代码在发往客户端运行之前不需经过编译,而是将文本格式的字符代码发送给浏览器由浏览器解释运行。可用来实现网页上的交互。 js有哪些数据类型(3分) 基本数据类型: String、Number、Boolean、Null、Undefined。 引用数据类型:Object、Arr

weixin_46915259的博客 1250

Allegro负片层不显示反盘的原因和解决办法

在用Allegro做PCB设计的时候,负片设计是较为常用的一种方式,有时会出现打开负片层却看不到反盘的情况,如下图。如何才能看到反盘显示的效果,具体操作如下。负片层不显示反盘的原因和解决办法。L2层仍然只能看到盘。

weixin_54787054的博客 2160

Java实现微信网页授权,java初级面试笔试题

我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家。 扫描二维码或搜索下图红色VX号,加VX好友,拉你进【程序员面试学习交流群】免费领取。也欢迎各位一起在群里探讨技术。 推荐文章:Java 面试知识点解析;Mysql优化技巧(数据库设计、命名规范、索引优化 开发前的准备: 1、需要有一个公众号(我这里用的测试号),拿到AppI...

ccc_ccc8的博客 418

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Java微信公众平台开发之OAuth2.0网页授权

根据官方文档在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的“开发 - 接口权限 - 网页服务 - 网页帐号 - 网页授权获取用户基本信息”的配置选项中,修改授权回调域名。请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加 http:// 等协议头,也不需要加具体的项目名,在域名空间的根目录放一个txt文件才能验证通过 一、两种scope授权方式 以snsa...

weixin_30625691的博客 210

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Java微信公众号开发之OAuth2.0网页授权

这里记录自己爬过的微信坑。。。。切记切记,开发之前一定仔细看官方文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&amp;id=mp1421140842我这里使用的是微信公众号-测试账号,比如微信端用户确认的页面没有出来(可能是测试号必须关注,但是关注的话确认页面就出不来。。。。),但是用户信息已经获取到了。。。。做了以后发现OAuth2.0...

fanxiangru999的专栏 4639

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

JAVA-企业微信H5自建应用之OAuth2授权登录

直接上代码 @GetMapping(value = "/oAuth2Url") public String oAuth2Url(HttpServletRequest request, @RequestParam("url") String url) throws IOException { //目前url为前端传,不需要后端做拼接 String orgId = "企业id"; String oauth2Url = "https://open.weixin.

weixin_46690278的博客 5200

微信公众号的面试题

转载:https://blog.youkuaiyun.com/qq_42611547/article/details/86294317 1.订阅号,服务号,企业号的区别? 1)业务侧重点 订阅号侧重互动 服务号侧重功能交互和企业展示(比如支持微信支付,微店推广功能) 企业号侧重企业应用或企业移动互联(简化管理流程,提高组织协同效率) 2)适用人群 订阅号:所有 服务号:企业,...

FlyPigYe的博客 8447

面试真题解析公众号,JavaScript学习6—(1),再不了解你就out啦

=就答题情况而言,第一问100%都可以回答正确,第二问大概只有50%正确率,第三问能回答正确的就不多了,第四问再正确就非常非常少了。其实此题并没有太多刁钻匪夷所思的用法,都是一些可能会遇到的场景,而大多数人但凡有1年到2年的工作经验都应该完全正确才对。只能说有一些人太急躁太轻视了,希望大家通过此文了解js一些特性。并祝愿大家在新的一年找工作面试中胆大心细,发挥出最好的水平,找到一份理想的工作。一个人可以走的很快,但一群人才能走的更远。

2401_83621136的博客 524

java微信公众号面试题_使用微信公众号开发模拟面试功能

最近在整理我在大厂面试以及平时工作中遇到的问题,记录在 shfshanyue/Daily-Question 中,但觉得对于时时回顾,常常复习仍然做的不够。于是在微信公众号中开发了随机生成模拟面试的功能,由于觉得比较简单且有趣,于是分享了出来需求先来谈一谈需求点:在公众号中回复面试,随机生成 N 道大厂面试题每道面试题指向一个超链接,可以查看答案需求很简单,如图下所示。你也可以去我的公众号 全栈成长...

weixin_36170766的博客 681

【java技术面试第八十一讲】Java面试题81 . 微信公众号分类和微信开发原理

不要为了看文章而看文章,带着疑问来 , 怀着收获知识的喜悦离去 ,点击关注上方“java大数据修炼之道”,设为“置顶或星标”,你想要的技术干货第一时间送达。Java面试题81:微...

hello world! 450

Oauth2授权模式访问之授权码模式(authorization_code)访问

Oauth2授权模式访问之授权码模式(authorization_code)访问 获取code redirect_uri可以随便写,在浏览器输入(注意是get请求方式): http://localhost:8080/oauth/authorize?response_type=code&amp;amp;amp;amp;amp;client_id=pair&amp;amp;amp;amp;amp;redirect_uri=http://bai...

面朝大海,春暖花开 9万+

java调用授权接口oauth2_微信授权就是这个原理,Spring Cloud OAuth2 授权码模式

上一篇文章Spring Cloud OAuth2 实现单点登录介绍了使用 password 模式进行身份认证和单点登录。本篇介绍 Spring Cloud OAuth2 的另外一种授权模式-授权码模式。授权码模式的认证过程是这样的:1、用户客户端请求认证服务器的认证接口,并附上回调地址;2、认证服务接口接收到认证请求后调整到自身的登录界面;3、用户输入用户名和密码,点击确认,跳转到授权、拒绝提示页...

weixin_35690449的博客 1528

微信OAuth授权获取用户OpenId-JAVA(个人经验)

ttp://mp.weixin.qq.com/wiki这个是官网的接口文档 微信授权获取用户openid-JAVA 第一步:用户同意授权,获取code 在确保微信公众账号拥有授权作用域(scope参数)的权限的前提下(服务号获得高级接口后,默认带有scope参数中的snsapi_base和snsapi_userinfo),引导关注者打开如下页面: https://open.wei

小帅丶的专栏 4万+

java微信授权实现

1.获取用户code /** * 用户同意授权,获取code * * @return java.lang.String * @date 2022/2/15 **/ @Override public void wxAuthorizeUrl(String redirectUri, HttpServletResponse response) { String urlString = ""; String url = ""; try{ urlString = .

qq_42376785的博客 2420
上一篇: Java分布式锁看这篇就够了,java基础面试笔试题
下一篇: Java集合框架之四大接口、常用实现类,java基础面试笔试题
agoodcoder777
博客等级 码龄8年 24粉丝 54原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值