Java项目-苍穹外卖-Day06-微信小程序开发

前言

本篇主要是主要是wx小程序开发入门和HttpClient的使用介绍
完成了苍穹外卖用户端的 微信登陆 和 导入商品浏览功能代码(没写跟之前day04的类似)

1.HttpClient

httpclient是什么

简而言之,该工具包可以使我们使用java编码的方式发送http请求,之前我们都是接收浏览器的http请求的,现在是发送
在这里插入图片描述
然后我们配置依赖项的话
我们使用的aliyun.oss已经通过依赖传递传过来了这个jar包
所以可以直接用
在这里插入图片描述

入门案例

发送GET请求

    @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();
    }

测试结果
测试记得保证redis开启
在这里插入图片描述

发送POST请求

    /**
     * 测试通过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();
    }

测试结果
在这里插入图片描述

Httpclient工具类

可以看到之前的操作还是比较的机械式的
所以我们创建一个工具类
基本上就是封装一下我们之前写的代码

/**
 * 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();
    }

}

2.微信小程序

介绍

以个人形式注册不能开放支付功能的
在这里插入图片描述
在这里插入图片描述

准备工作

在这里插入图片描述

注册小程序和完善对应信息

注册微信小程序
注册选择个人
然后你把小程序信息和分类项目填好就OK了
在这里插入图片描述
然后点击开发管理的开发设置选项

在这里插入图片描述
获取对应的id和秘钥即可

下载开发者工具

在这里插入图片描述
下载完就是一个exe程序
直接一直点下一步,选个安装路径就行
登录进后的画面
在这里插入图片描述
新建项目
小程序AppID用自己的!
在这里插入图片描述
点击确定就会生成对应的模拟器和开发工具
主要就是三个组件
编辑器,调试器和模拟器
在这里插入图片描述
在详情里面的本地设置
把这个勾选上,如果不勾选,请求是发送不出去的

在这里插入图片描述

入门案例

小程序开发其实本质上还是前端开发
主要用到的语言就是js
编码风格类似vue
在这里插入图片描述
page对应小程序页面,一个页面下又包含四个文件
在这里插入图片描述
app.js
pages里面把所有的page包含即可
titletext对应关系图里也标识了
在这里插入图片描述
index.wxml对应关系
也可以动态获取index.js的值进行动态展示
在这里插入图片描述
在index.js 定义变量和方法
在index.wxml进变量操作和方法绑定等
在这里插入图片描述
接下来也有点逆天
感觉对后端学习用处不大
主要是微信的一些内部方法

注意一下微信登陆那个方法,会返回一个授权码
然后回用这个码调用微信的接口就能拿到用户的唯一标识OPENId
一个授权码只能使用一次,每次登录授权码不同

在这里插入图片描述

发送请求-wx.request
在这里插入图片描述
发布小程序
上传
在这里插入图片描述
然后再版本管理看
提交审核
审核完成才可以发布
在这里插入图片描述

导入微信小程序代码

因为主后端,所以就略过开发微信小程序代码的阶段,直接导入即可
找一下黑马的资料

3.微信登陆功能开发

微信登陆官方流程

微信登陆功能要符合该流程图
OpenID是用户的唯一标识!
下次返回openid才能直接对应到数据库的openid才能进行数据同步(因为本质上是和微信账号绑定的)
而自定义登陆态,是用来在一次登陆后的多次请求操作的存储
在这里插入图片描述
在这里插入图片描述
请求微信接口的规范
在这里插入图片描述
在这里插入图片描述

可以自己去用postman测试一下
在这里插入图片描述

需求分析

基于微信登陆的话就不用那个自己注册账号密码了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码开发

先配置一下
在这里插入图片描述
设置一下用户端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;
        }
    }
}

然后在配置类注册一下
在这里插入图片描述
就OK了
测试这里就略了

4.导入商品浏览功能代码

产品原型
第一张图和第二张图:有口味表的菜可以选规格,没有的话只能直接点
第三张和第四张就是套餐下单
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
自己找一下导入一下
然后测试一下
在这里插入图片描述

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小袁拒绝摆烂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值