目录
HttpClient介绍
微信小程序登陆
代码编写
导入HttpClient的Maven坐标
微信小程序获得临时Code并将其传至开发者服务器
开发者服务器构建url,并获取openid,并传给微信小程序
HttpClientUtil的封装的doGet方法
参考链接
HttpClient介绍
httpClient是支持HTTP协议的客户端编程工具包,可以用于实现Java客户端向服务端发送HTTP请求并接收响应数据。
主要应用场景:获取微信用户唯一标识openId、查看地图、查看天气等功能的时候,由于开发者服务器并不提供这些功能,需要调用相关服务器以获取相关信息,httpClient可以实现在Java客户端向服务端发送请求并获取响应数据的功能。
使用方法:
- 通过HttpClients创建HttpClient对象。
- 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。
- 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HttpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。
- 通过httpClient的execute发送请求并接收响应数据。
-
调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。
-
释放连接。无论执行方法成功与都都必须释放连接。
微信小程序登陆
微信小程序官方提供的登录时序图:
code是微信小程序端获得的临时登陆凭证,需要传至开发者服务器用以调用微信登陆接口获取微信用户的唯一标识openid。
- 微信小程序调用wx.login()获取临时授权码code,并将其发送到开发者服务器(SpringBoot创建的服务端项目)。
- 开发者服务器通过HttpClient向微信接口服务发起Get请求,同时携带code、appid、appsecret等参数。
- 开发者服务器接收微信接口服务响应的数据,主要包含openId(微信用户唯一标识)。
- 开发者服务器端接收到openId后检查当前微信用户是否为首次登录,如果首次登录则构建用户相关信息并将其插入到MySQL数据库中。随后开发者服务器端利用JWT工具类生成token并且和openId一起发送给小程序端。token方便后续用户身份校验。
- 小程序端收到自定义登录态后存储storage。========完成微信用户小程序登录。
- 后续小程序端通过wx.request()携带token发起业务请求,开发者服务器通过自定义拦截器解析并验证token是否合法并有效,否则不予放行,只有检验通过后开发者服务器才会执行相关业务并响应数据给小程序端。
代码编写
导入HttpClient的Maven坐标
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
微信小程序获得临时Code并将其传至开发者服务器
@PostMapping("/login")
@ApiOperation("用户登录")
public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO){
log.info("用户登录:{}",userLoginDTO.getCode());
User user = userService.wxLogin(userLoginDTO);
xxx......
xxx......
return Result.success();
}
开发者服务器构建url,并获取openid,并传给微信小程序
package com.sky.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sky.constant.MessageConstant;
import com.sky.dto.UserLoginDTO;
import com.sky.entity.User;
import com.sky.exception.LoginFailedException;
import com.sky.mapper.UserMapper;
import com.sky.properties.WeChatProperties;
import com.sky.service.UserService;
import com.sky.utils.HttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Service
public class UserServiceImpl implements UserService {
private static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";
@Autowired
private WeChatProperties weChatProperties;
@Autowired
private UserMapper userMapper;
/**
* 微信登录
* @param userLoginDTO
* @return
*/
@Override
public User wxLogin(UserLoginDTO userLoginDTO) {
String openid = getOpenid(userLoginDTO.getCode());
// 判断openid是否为空,如果为空标识登录失败,抛出业务异常
if(openid == null){
throw new LoginFailedException(MessageConstant.LOGIN_FAILED);
}
// 判断当前用户是否为新用户
User user = userMapper.getByOpenid(openid);
if(user == null){
// 如果是新用户,自动完成注册
user = User.builder()
.createTime(LocalDateTime.now())
.openid(openid)
.build();
userMapper.insert(user);
}
// 返回这个用户对象
return user;
}
private String getOpenid(String code){
// 调用微信接口,获取当前微信用户的openid
Map<String, String> paramMap = new HashMap<>();
paramMap.put("appid", weChatProperties.getAppid());
paramMap.put("secret", weChatProperties.getSecret());
paramMap.put("js_code", code);
paramMap.put("grant_type", "authorization_code");
String respond = HttpClientUtil.doGet(WX_LOGIN, paramMap);
// 调用微信接口后返回的参数是Json格式的,使用JSON解析。
JSONObject jsonObject = JSON.parseObject(respond);
String openid = jsonObject.getString("openid");
return openid;
}
}
HttpClientUtil的封装的doGet方法
public class HttpClientUtil {
static final int TIMEOUT_MSEC = 5 * 1000;
/**
* 发送GET方式请求
* @param url
* @param paramMap
* @return
*/
public static String doGet(String url,Map<String,String> paramMap){
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
String result = "";
CloseableHttpResponse response = null;
try{
URIBuilder builder = new URIBuilder(url);
if(paramMap != null){
for (String key : paramMap.keySet()) {
builder.addParameter(key,paramMap.get(key));
}
}
URI uri = builder.build();
//创建GET请求
HttpGet httpGet = new HttpGet(uri);
//发送请求
response = httpClient.execute(httpGet);
//判断响应状态
if(response.getStatusLine().getStatusCode() == 200){
result = EntityUtils.toString(response.getEntity(),"UTF-8");
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
response.close();
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
}
参考链接
HttpClient用法--这一篇全了解(内含例子)-CSDN博客
开放能力 / 用户信息 / 小程序登录 (qq.com)