本篇主要是主要是wx小程序开发入门和HttpClient的使用介绍
完成了苍穹外卖用户端的 微信登陆 和 导入商品浏览功能代码(没写跟之前day04的类似)
简而言之,该工具包可以使我们使用java编码的方式发送http请求,之前我们都是接收浏览器的http请求的,现在是发送
然后我们配置依赖项的话
我们使用的aliyun.oss已经通过依赖传递传过来了这个jar包
所以可以直接用
@Test
public void testGet() throws Exception{
//创建httpClient对象
CloseableHttpClient aDefault = HttpClients.createDefault();
//创建请求对象
HttpGet httpGet = new HttpGet("http://localhost:8080/user/shop/status");
//发送请求
CloseableHttpResponse response = aDefault.execute(httpGet);
//获取服务端返回的状态码
int statusCode = response.getStatusLine().getStatusCode();
System.out.println("服务器返回的状态码为: "+statusCode);
HttpEntity entity = response.getEntity();
String body = EntityUtils.toString(entity);
System.out.println("服务端返回的数据为: "+body);
//关闭资源
response.close();
aDefault.close();
}
/**
* 测试通过httpclient发送POST方式的请求
*/
@Test
public void testPost() throws Exception {
//创建httpclient对象
CloseableHttpClient client = HttpClients.createDefault();
//创建请求对象
HttpPost httpPost = new HttpPost("http://localhost:8080/admin/employee/login");
//这个请求需要请求体,里面是JSON形式的命名和用户名
JSONObject jsonObject = new JSONObject();
jsonObject.put("username","admin");
jsonObject.put("password","123456");
StringEntity stringEntity = new StringEntity(jsonObject.toString());
//指定编码方式
stringEntity.setContentEncoding("utf-8");
//指定传输数据格式
stringEntity.setContentType("application/json");
httpPost.setEntity(stringEntity);
//发送请求
CloseableHttpResponse response = client.execute(httpPost);
//解析返回结果
int statusCode = response.getStatusLine().getStatusCode();
System.out.println("响应码: "+statusCode);
HttpEntity entity = response.getEntity();
String s = EntityUtils.toString(entity);
System.out.println("响应数据为: "+s);
//关闭资源
response.close();
client.close();
}
可以看到之前的操作还是比较的机械式的
所以我们创建一个工具类
基本上就是封装一下我们之前写的代码
/**
* Http工具类
*/
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;
}
/**
* 发送POST方式请求
* @param url
* @param paramMap
* @return
* @throws IOException
*/
public static String doPost(String url, Map<String, String> paramMap) throws IOException {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建参数列表
if (paramMap != null) {
List<NameValuePair> paramList = new ArrayList();
for (Map.Entry<String, String> param : paramMap.entrySet()) {
paramList.add(new BasicNameValuePair(param.getKey(), param.getValue()));
}
// 模拟表单
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
httpPost.setEntity(entity);
}
httpPost.setConfig(builderRequestConfig());
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
} catch (Exception e) {
throw e;
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
/**
* 发送POST方式请求
* @param url
* @param paramMap
* @return
* @throws IOException
*/
public static String doPost4Json(String url, Map<String, String> paramMap) throws IOException {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
if (paramMap != null) {
//构造json格式数据
JSONObject jsonObject = new JSONObject();
for (Map.Entry<String, String> param : paramMap.entrySet()) {
jsonObject.put(param.getKey(),param.getValue());
}
StringEntity entity = new StringEntity(jsonObject.toString(),"utf-8");
//设置请求编码
entity.setContentEncoding("utf-8");
//设置数据类型
entity.setContentType("application/json");
httpPost.setEntity(entity);
}
httpPost.setConfig(builderRequestConfig());
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
} catch (Exception e) {
throw e;
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
private static RequestConfig builderRequestConfig() {
return RequestConfig.custom()
.setConnectTimeout(TIMEOUT_MSEC)
.setConnectionRequestTimeout(TIMEOUT_MSEC)
.setSocketTimeout(TIMEOUT_MSEC).build();
}
}
注册微信小程序
注册选择个人
然后你把小程序信息和分类项目填好就OK了
然后点击开发管理的开发设置选项
下载完就是一个exe程序
直接一直点下一步,选个安装路径就行
登录进后的画面
新建项目
小程序AppID用自己的!
点击确定就会生成对应的模拟器和开发工具
主要就是三个组件
编辑器,调试器和模拟器
在详情里面的本地设置
把这个勾选上,如果不勾选,请求是发送不出去的
小程序开发其实本质上还是前端开发
主要用到的语言就是js
编码风格类似vue
page对应小程序页面,一个页面下又包含四个文件
app.js
pages里面把所有的page包含即可
titletext对应关系图里也标识了
index.wxml对应关系
也可以动态获取index.js的值进行动态展示
在index.js 定义变量和方法
在index.wxml进变量操作和方法绑定等
接下来也有点逆天
感觉对后端学习用处不大
主要是微信的一些内部方法
注意一下微信登陆那个方法,会返回一个授权码
然后回用这个码调用微信的接口就能拿到用户的唯一标识OPENId
一个授权码只能使用一次,每次登录授权码不同
发送请求-wx.request
发布小程序
上传
然后再版本管理看
提交审核
审核完成才可以发布
因为主后端,所以就略过开发微信小程序代码的阶段,直接导入即可
找一下黑马的资料
微信登陆功能要符合该流程图
OpenID是用户的唯一标识!
下次返回openid才能直接对应到数据库的openid才能进行数据同步(因为本质上是和微信账号绑定的)
而自定义登陆态,是用来在一次登陆后的多次请求操作的存储
请求微信接口的规范
先配置一下
设置一下用户端JWT令牌
这个user-token-name是和前端沟通的,不能随便写
有对应类已经定义
controller
@RestController
@RequestMapping("/user/user")
@Api(tags = "C端用户相关接口")
@Slf4j
public class UserController {
@Autowired
private UserService userService;
@Autowired
private JwtProperties jwtProperties;
/**
* 微信登录
* @param userLoginDTO
* @return
*/
@PostMapping("/login")
@ApiOperation("微信登录")
public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO){
log.info("微信用户登录:{}",userLoginDTO.getCode());
//微信登录
User user = userService.wxLogin(userLoginDTO);
//为微信用户生成JWT令牌
Map<String,Object> claims = new HashMap<>();
claims.put(JwtClaimsConstant.USER_ID,user.getId());
String token = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), claims);
UserLoginVO userLoginVO = UserLoginVO.builder()
.id(user.getId())
.openid(user.getOpenid())
.token(token)
.build();
return Result.success(userLoginVO);
}
}
service
@Service
@Slf4j
public class UserServiceImpl implements UserService {
//微信服务接口地址
public static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";
@Autowired
private WeChatProperties weChatProperties;
@Autowired
private UserMapper userMapper;
/**
* 微信登录
* @param userLoginDTO
* @return
*/
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()
.openid(openid)
.createTime(LocalDateTime.now())
.build();
userMapper.insert(user);
}
//返回用户对象
return user;
}
/**
* 获取openid
* @param code
* @return
*/
private String getOpenid(String code){
//调用微信接口,获得openid
Map<String, String> map = new HashMap<>();
map.put("appid",weChatProperties.getAppid());
map.put("secret",weChatProperties.getSecret());
map.put("js_code",code);
map.put("grant_type","authorization_code");
String json = HttpClientUtil.doGet(WX_LOGIN, map);
JSONObject jsonObject = JSON.parseObject(json);
String openid = jsonObject.getString("openid");
return openid;
}
}
<insert id="insert" useGeneratedKeys="true" keyProperty="id">-- 返回赋值对应user中的id
insert into user (openid,name,phone,sex,id_number,avatar,create_time)
values (#{openid},#{name},#{phone},#{sex},#{idNumber},#{avatar},#{createTime})
insert>
然后还要做一个用户端的jwt拦截器
拦截器定义
和管理端差不多,把属性改成用户端的
@Slf4j
@Component
public class JwtTokenUserInterceptor implements HandlerInterceptor {
@Autowired
private JwtProperties jwtProperties;
/**
* 校验jwt
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//判断当前拦截到的是Controller的方法还是其他资源
if (!(handler instanceof HandlerMethod)) {
//当前拦截到的不是动态方法,直接放行
return true;
}
//1、从请求头中获取令牌
String token = request.getHeader(jwtProperties.getUserTokenName());
//2、校验令牌
try {
log.info("jwt校验:{}", token);
Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
Long userId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
log.info("当前员用户id:{}", userId);
//拦截器把当前id存入ThreadLocal对象
BaseContext.setCurrentId(userId);
//3、通过,放行
return true;
} catch (Exception ex) {
//4、不通过,响应401状态码
response.setStatus(401);
return false;
}
}
}