【苍穹外卖】Day 6 HttpClient、wx小程序

1 HttpClient

HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议

HttpClient 是一个用于发送 HTTP 请求并接收响应的类或库,在不同的编程语言中有不同的实现。它通常用于与 Web 服务进行交互,尤其是在 RESTful API 的场景下。HttpClient 能够处理各种类型的 HTTP 请求,如 GETPOSTPUTDELETE 等,还可以设置请求头、超时、身份验证等

XML 复制代码
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>

核心API:

  • HttpClient
  • HttpClients
  • CloseableHttpClient
  • HttpGet
  • HttpPost

发送请求步骤:

  1. 创建 HttpClient 对象
  2. 创建 Http 请求对象(如GET、POST)
  3. 调用 HttpClient 的 execute 方法发送请求

1.1 GET

首先运行springboot,然后开启redis server

运行测试类:

如果改成访问 admin,就会失败,因为没有 jwt 令牌

1.2 POST

2 wx小程序

使用 微信开发者工具

2.1 入门案例

小程序目录结构:

包含一个描述整体程序的 app 和多个描述各自页面的 page

一个小程序 主体部分由三个文件组成,必须放在项目的根目录:

文件 是否必需 作用
app.js 小程序逻辑
app.json 小程序公共配置
app.wxss 小程序公共样式表

wxss:wx Style Sheets

css:Cascading Style Sheets 层叠样式表,CSS 用于控制网页的外观和布局,通过为 HTML 元素设置样式属性(如颜色、字体、排版和布局等),从而实现网页的美化与响应式设计

一个小程序 页面由四个文件组成:

文件类型 是否必需 作用
js 页面逻辑
wxml 页面结构
json 页面配置
wxss 页面样式表

页面逻辑

javascript 复制代码
// index.js
Page({
    data: {
        msg: 'hello',
        nickName: '',
        img: '',
        authorizationCode: '',
        status: ''
    },
    //获取用户头像和昵称
    getUserInfo() {
        wx.getUserProfile({
            desc: '获取用户头像和昵称',
            success: (res) => {
                console.info(res.userInfo)

                this.setData({
                    nickName: res.userInfo.nickName,
                    img: res.userInfo.avatarUrl
                })
            }
        })
    },

    login() {
        wx.login({
            success: (res) => {
                this.setData({
                    authorizationCode: res.code
                })
            },
        })
    },

    sendRequest() {
        wx.request({
            url: 'http://localhost:8080/user/shop/status',
            method: 'GET',
            success: (res) => {
                console.log(res.data)
                this.setData({
                    status: res.data
                })
            }
        })
    }
})

页面结构

XML 复制代码
<!--index.wxml-->
<navigation-bar title="Weixin" back="{{false}}" color="black" background="#FFF"></navigation-bar>
<views>
    <view class="container">
        {{msg}}
    </view>

    <view>
        <button type="primary" bind:tap="getUserInfo">get user info</button>
        nickname:{{nickName}}
        <image style="width: 30px ;height: 30px;" src="{{img}}"></image>
    </view>

    <view>
        <button bind:tap="login" type="default">login</button>
        authorizationCode: {{authorizationCode}}
    </view>

    <view>
        <button bind:tap="sendRequest" type="warn">send request to get status</button>
        status is [{{status}}]
    </view>
</views>

效果:

审核中

2.2 微信登录 接口设计

时序图

https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html

接口设计:

第一个 user 代表 用户端

第二个 user 代表 用户模块

实现:

配置wx

配置客户端的 jwt 校验

在配置属性类里面已经规定好了

数据封装

DTO

要传输的数据

VO

要展示、要返回的数据

2.3 实现

小程序登录 / 小程序登录 (qq.com)

controller

java 复制代码
package com.sky.controller.user;

import com.sky.constant.JwtClaimsConstant;
import com.sky.dto.UserLoginDTO;
import com.sky.entity.User;
import com.sky.properties.JwtProperties;
import com.sky.result.Result;
import com.sky.service.UserService;
import com.sky.utils.JwtUtil;
import com.sky.vo.UserLoginVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

@RestController
@RequestMapping("/user/user")
@Api(tags = "用户相关接口")
public class UserController {
    @Autowired
    private UserService userService;

    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 用户微信登录
     *
     * @return
     */
    @PostMapping("/login")
    @ApiOperation("用户微信登录")
    public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO) {
        // 微信登录
        User user = userService.wxLogin(userLoginDTO);

        // 为微信用户生成 jwt 令牌
        HashMap<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

java 复制代码
package com.sky.service.impl;

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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Service
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) {
        //调用微信接口服务,获得当前微信用户的 openid
        Map<String, String> map = new HashMap<>();
        map.put("appid", weChatProperties.getAppid());
        map.put("secret", weChatProperties.getSecret());
        map.put("js_code", userLoginDTO.getCode());
        map.put("grant_type", "authorization_code");
        String string = HttpClientUtil.doGet(WX_LOGIN, map);

        // fastJSON 解析 JSON 对象
        JSONObject jsonObject = JSONObject.parseObject(string);
        // 通过 key,访问 openid
        String openid = jsonObject.getString("openid");
        //判断 openid 是否为空,如果为空,要抛出登录失败异常
        if (openid == null) {
            throw new LoginFailedException(MessageConstant.LOGIN_FAILED);
        }

        //判断当前用户是否为新用户(数据库查询是否包含openid)
        User user = userMapper.getByOpenid(openid);

        //新用户要注册
        if (user == null) {
            user = User.builder()
                    .openid(openid)
                    .createTime(LocalDateTime.now())
                    .build();

            userMapper.add(user);
        }

        return user;
    }
}

mapper

java 复制代码
package com.sky.mapper;

import com.sky.entity.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface UserMapper {
    /**
     * 根据 openid 查询用户
     *
     * @param openid
     * @return
     */
    @Select("select * from sky_take_out.user where openid = #{openid}")
    User getByOpenid(String openid);

    /**
     * 新增用户
     * 这里要注意要返回主键
     *
     * @param newUser
     */
    void add(User newUser);
}

xml

XML 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >

<mapper namespace="com.sky.mapper.UserMapper">

    <insert id="add" useGeneratedKeys="true" keyProperty="id">
        insert into sky_take_out.user
            (openid, name, phone, sex, id_number, avatar, create_time)
        values (#{openid}, #{name}, #{phone}, #{sex}, #{idNumber}, #{avatar}, #{createTime})

    </insert>
</mapper>

2.4 测试

3 商品浏览

注意这里,名称要 与前端保持一致

相关推荐
神明不懂浪漫41 分钟前
【第五章】Java中的继承与多态
java·开发语言
AI多Agent协作实战派3 小时前
AI多Agent协作系统实战(十七):凌晨4点,我的AI系统在“假装工作“——3个bug同时爆炸的5小时
java·前端·bug
gaolei_eit3 小时前
Java+Ai+vue
java·spring·maven
qq_2518364573 小时前
基于java Web 动漫视频网站毕业论文
java·开发语言·前端
LayZhangStrive3 小时前
JUC相关的函数、注解、变量杂记
java·面试·多线程·juc
未秃头的程序猿3 小时前
给公司做了个AI客服Agent,用的Spring AI 1.0,3天上线领导拍板了
java·后端·ai编程
曹牧3 小时前
Eclipse 批量文本替换
java·ide·eclipse
程序员清风3 小时前
OpenAI官方发布最新提示词技巧!
java·后端·面试
一只枫林3 小时前
MySQL内、外连接知识点汇总
java·前端·数据库
梅头脑3 小时前
写了3年CRUD,volatile和synchronized的区别还是答不清——直到我画出了这张三性两锁边界图
java