Java生成微信小程序二维码、上传至阿里云OSS
依赖
<!-- 阿里云oss依赖 --><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.8.1</version></dependency><!-- 工具类 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.13</version></dependency>
controller
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;@Slf4j
@RestController
@RequestMapping("/wx/api/user")
public class QRCodeController {@Autowiredprivate OSSUtil ossUtil;/*** 生成二维码** @param userId 用户id* @param path 生成二维码的url* @return*/@PostMapping("/createQRcode")public String createQRcode(String userId, String path) {// 获取调用凭证accessTokenString accessToken = AccessToken.getAccessToken();RestTemplate rest = new RestTemplate();InputStream inputStream = null;OutputStream outputStream = null;String imgUrl = "";try {String url = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token="+accessToken;log.info("url: "+url);Map<String,Object> param = new HashMap<>();param.put("path", path);
// param.put("page", "pages/index/index"); // 路径 如果没有默认跳转到首页面微信小程序发布后才可以使用不能添加参数param.put("width", 430); //二维码尺寸param.put("is_hyaline", true); // 是否需要透明底色, is_hyaline 为true时,生成透明底色的小程序码 参数仅对小程序码生效param.put("auto_color", true); // 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调 参数仅对小程序码生效Map<String,Object> line_color = new HashMap<>();line_color.put("r", 0);line_color.put("g", 0);line_color.put("b", 0);param.put("line_color", line_color);log.info("调用生成微信URL接口传参:" + param);MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();HttpEntity requestEntity = new HttpEntity(param, headers);ResponseEntity<byte[]> entity = rest.exchange(url, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);log.info("调用小程序生成微信永久小程序码URL接口返回结果:" + entity.getBody());byte[] result = entity.getBody();log.info(Base64.encodeBase64String(result));inputStream = new ByteArrayInputStream(result);SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");// 最后上传生成的文件名String finalFileName = System.currentTimeMillis() + "" + new SecureRandom().nextInt(0x0400) + ".jpg";// oss中的文件夹名String objectName = sdf.format(new Date()) + "/" + finalFileName;// 上传ossossUtil.uploadFile2OSS(inputStream, objectName);//获取文件的URl地址imgUrl = ossUtil.getImgUrl(objectName);log.info("imgUrl: "+imgUrl);// // 生成返回的二维码更新到数据库
// WxUser wxUser = new WxUser();
// wxUser.setId(qrCodeVo.getId());
// wxUser.setQRCode(imgUrl);
// wxUserMapper.updateWxUser(wxUser);} catch (Exception e) {log.error("调用小程序生成微信永久小程序码URL接口异常",e);} finally {if(inputStream != null){try {inputStream.close();} catch (IOException e) {e.printStackTrace();}}if(outputStream != null){try {outputStream.close();} catch (IOException e) {e.printStackTrace();}}}return "操作成功";}
}
TokenBean
@Data
public class TokenBean {private String token;private Date date;
}
AccessToken
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import org.springframework.stereotype.Component;import java.util.Date;@Component
public class AccessToken {public static TokenBean tokenBean = new TokenBean();/*** 获取微信模板发送所需Token* 每次获取有效期为2个小时* @return token*/public static String getAccessToken(){if (tokenBean == null || tokenBean.getDate() == null || tokenBean.getDate().getTime() < new Date().getTime()){//发送模板请求接口String result = HttpRequest.get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=xxx&secret=xxx").header(Header.USER_AGENT, "Mozilla/5.0 (Linux; Android 8.0.0; SM-N9500 Build/R16NW; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/63.0.3239.83 Mobile Safari/537.36 T7/10.13 baiduboxapp/10.13.0.11 (Baidu; P1 8.0.0)")//头信息,多个头信息多次调用此方法即可.timeout(10000)//超时,毫秒.execute().body();JSONObject jsonObject = JSONUtil.parseObj(result);String access_token = (String) jsonObject.get("access_token");tokenBean.setToken(access_token);Date date = new Date(new Date().getTime() + 7200 * 1000);tokenBean.setDate(date);return access_token;}else{return tokenBean.getToken();}}
}
OSSUtil
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;@Slf4j
@Component
public class OSSUtil {private static final String endpoint = "oss-cn-shenzhen.aliyuncs.com";private static final String accessKeyId = "";private static final String accessKeySecret = "";private static final String bucketName = "wxcall-xiaobanben";private static final String FOLDER = "image/";/*** 获取oss** @return*/public static OSS getOSSClient() {return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);}/*** 上传图片** @param url* @throws*/public void uploadImg2Oss(String url) throws IOException {File fileOnServer = new File(url);FileInputStream fin;try {fin = new FileInputStream(fileOnServer);String[] split = url.split("/");this.uploadFile2OSS(fin, split[split.length - 1]);} catch (FileNotFoundException e) {throw new IOException("图片上传失败");}}public String uploadImg2Oss(MultipartFile file) throws IOException {if (file.getSize() > 5 * 1024 * 1024) {throw new IOException("上传图片大小不能超过5M!");}SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");// 获取文件名String originalFilename = file.getOriginalFilename();// 获取文件后缀名String suffixName = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();// 最后上传生成的文件名String finalFileName = System.currentTimeMillis() + "" + new SecureRandom().nextInt(0x0400) + suffixName;// oss中的文件夹名String objectName = sdf.format(new Date()) + "/" + finalFileName;// name = DateUtils.dateStr(new Date(), "yyyy/MM/dd") + "/" + System.currentTimeMillis() + substring;try {InputStream inputStream = file.getInputStream();this.uploadFile2OSS(inputStream, objectName);return objectName;} catch (Exception e) {e.printStackTrace();throw new IOException("图片上传失败");}}/*** 获得图片路径** @param fileUrl* @return*/public String getImgUrl(String fileUrl) {System.out.println(fileUrl);if (!StringUtils.isEmpty(fileUrl)) {
// String[] split = fileUrl.split("/");return this.getUrl(this.FOLDER + fileUrl);}return "";}/*** 上传到OSS服务器 如果同名文件会覆盖服务器上的** @param instream 文件流* @param fileName 文件名称 包括后缀名* @return 出错返回"" ,唯一MD5数字签名*/public String uploadFile2OSS(InputStream instream, String fileName) {String ret = "";try {OSS ossClient = getOSSClient();// 创建上传Object的MetadataObjectMetadata objectMetadata = new ObjectMetadata();objectMetadata.setContentLength(instream.available());objectMetadata.setCacheControl("no-cache");objectMetadata.setContentType(getContentType(fileName.substring(fileName.lastIndexOf("."))));objectMetadata.setHeader("Pragma", "no-cache");
// objectMetadata.setContentDisposition("inline;filename=" + fileName);// 上传文件PutObjectResult putResult = ossClient.putObject(bucketName, FOLDER + fileName, instream, objectMetadata);ret = putResult.getETag();} catch (IOException e) {log.error(e.getMessage(), e);} finally {try {if (instream != null) {instream.close();}} catch (IOException e) {e.printStackTrace();}}return ret;}/*** 通过文件名判断并获取OSS服务文件上传时文件的contentType** @param filenameExtension 文件名* @return 文件的contentType*/public static final String getContentType(String filenameExtension) {if (filenameExtension.equalsIgnoreCase(".bmp")) {return "application/x-bmp";}if (filenameExtension.equalsIgnoreCase(".gif")) {return "image/gif";}if (filenameExtension.equalsIgnoreCase(".jpeg") ||filenameExtension.equalsIgnoreCase(".jpg") ||filenameExtension.equalsIgnoreCase(".png")) {return "image/jpg";}if (filenameExtension.equalsIgnoreCase(".html")) {return "text/html";}if (filenameExtension.equalsIgnoreCase(".txt")) {return "text/plain";}if (filenameExtension.equalsIgnoreCase(".vsd")) {return "application/vnd.visio";}if (filenameExtension.equalsIgnoreCase(".pptx") ||filenameExtension.equalsIgnoreCase(".ppt")) {return "application/vnd.ms-powerpoint";}if (filenameExtension.equalsIgnoreCase(".docx") ||filenameExtension.equalsIgnoreCase(".doc")) {return "application/msword";}if (filenameExtension.equalsIgnoreCase(".xla") ||filenameExtension.equalsIgnoreCase(".xlc") ||filenameExtension.equalsIgnoreCase(".xlm") ||filenameExtension.equalsIgnoreCase(".xls") ||filenameExtension.equalsIgnoreCase(".xlt") ||filenameExtension.equalsIgnoreCase(".xlw")) {return "application/vnd.ms-excel";}if (filenameExtension.equalsIgnoreCase(".xlsx")) {return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";}if (filenameExtension.equalsIgnoreCase(".xml")) {return "text/xml";}if (filenameExtension.equalsIgnoreCase(".pdf")) {return "application/pdf";}if (filenameExtension.equalsIgnoreCase(".zip")) {return "application/zip";}if (filenameExtension.equalsIgnoreCase(".tar")) {return "application/x-tar";}if (filenameExtension.equalsIgnoreCase(".avi")) {return "video/avi";}if (filenameExtension.equalsIgnoreCase(".mp4")) {return "video/mpeg4";}if (filenameExtension.equalsIgnoreCase(".mp3")) {return "audio/mp3";}if (filenameExtension.equalsIgnoreCase(".mp2")) {return "audio/mp2";}// 默认下载
// return "application/octet-stream";return "image/jpg";}/*** 获得url链接** @param key* @return*/public String getUrl(String key) {// 设置URL过期时间为10年 3600l* 1000*24*365*10OSS ossClient = getOSSClient();Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);// 生成URLURL url = ossClient.generatePresignedUrl(bucketName, key, expiration);System.out.println("url: "+url);if (url != null) {String host = "https://" + url.getHost() + url.getPath();System.out.println("host: "+host);// http://wxcall-xiaobanben.oss-cn-shenzhen.aliyuncs.com/image/20220129/1643469496754508.jpgreturn host;}return "";}/*** 获取文件夹** @param fileName* @return*/public List<String> fileFolder(String fileName) {// 创建OSSClient实例。OSS ossClient = getOSSClient();// 构造ListObjectsRequest请求。ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);// 设置正斜线(/)为文件夹的分隔符。listObjectsRequest.setDelimiter("/");// 设置prefix参数来获取fun目录下的所有文件。if (!StringUtils.isEmpty(fileName)) {listObjectsRequest.setPrefix(fileName + "/");}// 列出文件ObjectListing listing = ossClient.listObjects(listObjectsRequest);// 遍历所有commonPrefixList<String> list = new ArrayList<>();for (String commonPrefix : listing.getCommonPrefixes()) {String newCommonPrefix = commonPrefix.substring(0, commonPrefix.length() - 1);String[] s = newCommonPrefix.split("/");if (!StringUtils.isEmpty(fileName)) {list.add(s[s.length - 1]);} else {list.add(s[0]);}}// 关闭OSSClientossClient.shutdown();return list;}/*** 列举文件下所有的文件url信息*/public ObjectListing listFile2(String fileHost, String nextMarker) {// 创建OSSClient实例。OSS ossClient = getOSSClient();// 构造ListObjectsRequest请求。ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);// 设置正斜线(/)为文件夹的分隔符。listObjectsRequest.setDelimiter("/");// 列出fun目录下的所有文件和文件夹。listObjectsRequest.setPrefix(fileHost + "/");ObjectListing listing = ossClient.listObjects(listObjectsRequest);// 遍历所有文件。System.out.println("Objects:");// objectSummaries的列表中给出的是fun目录下的文件。for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {System.out.println(objectSummary.getKey());}// 遍历所有commonPrefix。System.out.println("\nCommonPrefixes:");// commonPrefixs列表中显示的是fun目录下的所有子文件夹。由于fun/movie/001.avi和fun/movie/007.avi属于fun文件夹下的movie目录,因此这两个文件未在列表中。for (String commonPrefix : listing.getCommonPrefixes()) {System.out.println(commonPrefix);}// 关闭OSSClient。ossClient.shutdown();return listing;}/*** 列举文件下所有的文件url信息*/public List<String> listFile(String fileHost, String nextMarker) {// 创建OSSClient实例。OSS ossClient = getOSSClient();// 构造ListObjectsRequest请求ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);// 设置prefix参数来获取fun目录下的所有文件。listObjectsRequest.setPrefix(fileHost + "/");listObjectsRequest.setMarker(nextMarker);// 列出文件。ObjectListing listing = ossClient.listObjects(listObjectsRequest);// 遍历所有文件。List<String> list = new ArrayList<>();for (int i = 0; i < listing.getObjectSummaries().size(); i++) {String FILE_URL = "http://" + bucketName + "." + endpoint + "/" + listing.getObjectSummaries().get(i).getKey();list.add(FILE_URL);}// 关闭OSSClient。ossClient.shutdown();// ObjectListing objectListing = null;
// int total = 0;
// HashMap<Integer, String> markerMap = new HashMap<>();
// try {
// ObjectListing objectListing2 = null;
// do {
// String nextMarker2 = objectListing2 != null ? objectListing2.getNextMarker() : null;
// ListObjectsRequest listObjectsRequest2 = new ListObjectsRequest(bucketName).withMarker(nextMarker2).withMaxKeys(100);
// listObjectsRequest2.setPrefix(fileHost + "/");
// objectListing2 = ossClient.listObjects(listObjectsRequest2);
// total += (objectListing2 != null && objectListing2.getObjectSummaries() != null ? objectListing2.getObjectSummaries().size() : 0);
// markerMap.put(markerMap.size() + 1, nextMarker2);
// } while (objectListing2 != null && !StringUtils.isEmpty(objectListing2.getNextMarker()));
//
// ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName).withMarker(nextMarker).withMaxKeys(100);
//
// listObjectsRequest.setPrefix(fileHost + "/");
//
// objectListing = ossClient.listObjects(listObjectsRequest);
// for (int i = 0; i < objectListing.getObjectSummaries().size(); i++) {
// String FILE_URL = "https://" + bucketName + "." + endpoint + "/" + objectListing.getObjectSummaries().get(i).getKey();
// list.add(FILE_URL);
// }
//
// } catch (Exception e) {
//
// } finally {
// // 关闭client
// ossClient.shutdown();
// }return list;}/*** 删除文件* objectName key 地址** @param filePath*/public Boolean delFile(String filePath) {// 创建OSSClient实例。OSS ossClient = getOSSClient();// 删除Object.boolean exist = ossClient.doesObjectExist(bucketName, filePath);if (!exist) {return false;}ossClient.deleteObject(bucketName, filePath);ossClient.shutdown();return true;}/*** 批量删除** @param keys*/public Boolean delFileList(List<String> keys) {// 创建OSSClient实例。OSS ossClient = getOSSClient();try {// 删除文件。DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(keys));List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();} catch (Exception e) {e.printStackTrace();return false;} finally {ossClient.shutdown();}return true;}/*** 创建文件夹** @param folder* @return*/public String createFolder(String folder) {// 创建OSSClient实例。OSS ossClient = getOSSClient();// 文件夹名final String keySuffixWithSlash = folder;// 判断文件夹是否存在,不存在则创建if (!ossClient.doesObjectExist(bucketName, keySuffixWithSlash)) {// 创建文件夹ossClient.putObject(bucketName, keySuffixWithSlash, new ByteArrayInputStream(new byte[0]));// 得到文件夹名OSSObject object = ossClient.getObject(bucketName, keySuffixWithSlash);String fileDir = object.getKey();ossClient.shutdown();return fileDir;}return keySuffixWithSlash;}/*** 通过文件名下载文件** @param objectName 要下载的文件名* @param localFileName 本地要创建的文件名*/public void downloadFile(HttpServletResponse response, String objectName, String localFileName) throws Exception {// 创建OSSClient实例。OSS ossClient = getOSSClient();try {// ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。OSSObject ossObject = ossClient.getObject(bucketName, objectName);// 读去Object内容 返回BufferedInputStream in = new BufferedInputStream(ossObject.getObjectContent());BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());//通知浏览器以附件形式下载response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(objectName, "utf-8"));//BufferedOutputStream out=new BufferedOutputStream(new FileOutputStream(new File("f:\\a.txt")));byte[] car = new byte[1024];int L = 0;while ((L = in.read(car)) != -1) {out.write(car, 0, L);}if (out != null) {out.flush();out.close();}if (in != null) {in.close();}} catch (Exception e) {e.printStackTrace();} finally {// 关闭OSSClient。ossClient.shutdown();}}public String onlineSee(String key) {// 创建OSSClient实例。OSS ossClient = getOSSClient();// 设置URL过期时间为1小时Date expiration = new Date(new Date().getTime() + 3600 * 1000);// 临时地址URL url = ossClient.generatePresignedUrl(bucketName, key, expiration);// 关闭OSSClient。ossClient.shutdown();return url.toString();}public Object onlinePreview(String key) {// 创建OSSClient实例。OSS ossClient = getOSSClient();// 设置视频截帧操作。文档页数默认是200,EndPage_-1任意String style = "imm/previewdoc,EndPage_-1";String filenameExtension = key.substring(key.lastIndexOf("."));if (filenameExtension.equalsIgnoreCase(".pdf")) {style = "imm/previewdoc,EndPage_-1,PdfVector_true";}// 指定过期时间为1小时。Date expiration = new Date(new Date().getTime() + 1000 * 60 * 60);GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, key, HttpMethod.GET);req.setExpiration(expiration);req.setProcess(style);URL signedUrl = ossClient.generatePresignedUrl(req);return signedUrl;}}
成功生成小程序二维码
微信官方文档.小程序链接:
https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.createQRCode.html
Java生成微信小程序二维码、上传至阿里云OSS相关推荐
- Java生成微信小程序二维码
Java生成微信小程序二维码 import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.Byt ...
- Java生成微信小程序二维码,5种实现方式,一个比一个简单
文章目录 前言 先看官网 一.JDK自带的URLConnection方式 二.Apache的HttpClient方式 三.okhttp3方式 四.Unirest方式 五.RestTemplate方式 ...
- 【java】Java生成微信小程序二维码
文章目录 前言 应用场景 微信小程序官网 1.RestTemplate方式 核心代码 getAccessToken 2. Unirest方式 Maven依赖 核心代码 3. okhttp3方式 Mav ...
- java生成微信小程序二维码(自定义带参)
准备工作: 1:获取微信小程序apiKey 2:获取微信小程序密钥 3:获取微信小程序页面链接 pom依赖: <dependency><groupId>com.alibaba& ...
- java获取微信小程序二维码
java获取微信小程序二维码 近期正好遇到了,随手记录下 首先获取微信小程序二维码需要小程序的appid 以及secret 然后根据appid和secret去获取小程序的token 即 access_ ...
- java获取微信小程序二维码图片并保存到本地
java获取微信小程序二维码保存到本地并返回图片,下次如果检查到本地有图片,那么就返回本地的图片,不再发起请求,否则重新发起请求并保存到本地,直接看代码吧. 获取access_token的方法可以参考 ...
- 生成微信小程序二维码(携带参数跳转指定页面)
需求:生成微信小程序二维码并携带参数,扫码跳转指定页面 获取WxMaService对象 WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl ...
- java创建微信小程序二维码
创建微信小程序二维码有两个接口需要 一个是获取tocken的接口 一个是生成二维码的接口 获取tocken接口 //**********填写你的小程序appid 和 secret public sta ...
- c# 生成微信小程序二维码
二维码生成 CreateWxCode("id=117", "pages/bookcheck/bookchecktime/bookchecktime", &quo ...
最新文章
- 如何成为一名对话系统工程师
- 中国Nature第一人,居然是清朝的他
- 大脑与数学——利用代数拓扑研究模拟大脑 第一部分
- Mysql表并联_SQL多表查询 表联结
- CI/CD大幅减少甩锅!
- 使用anconada 的conda更换环境
- 马云向日本捐赠100万只口罩:这是许多中国人的心意!
- 面向对象下计算器的编码实现
- 【linux】两个线程实现出库与入库操作
- Core Animation演示
- Ubuntu 16.04 安装QQ, TIM
- kindle亚马逊个人文档不显示_Kindle的PC版如何看个人文档
- SAN和NAS、ISCSI存储有什么区别,SAN和NAS设备哪个更好?
- [Filco]蓝牙连接键盘
- 【其它笔记】驾考科目四笔记
- Java高并发处理:请求合并
- 怎么用计算机隐藏应用程序,win7 隐藏应用程序 电脑如何隐藏程序_win7教程_uc电脑园...
- 鸿蒙系统预计什么时候上市,鸿蒙系统什么时候上市?鸿蒙系统什么时候用于手机(图文)...
- ios底部栏设计规范_iPhone6界面设计尺寸规范大全【含原型设计规范】
- 手眼标定,9点标定过程及其运算
热门文章
- springboot毕设项目汽车销售管理系统3ytu1(java+VUE+Mybatis+Maven+Mysql)
- 快乐地打牢基础(5)——割点和桥
- 如何找到你喜欢的Premiere的动态图形模板
- java使用itextpdf将图片转换成pdf时DPI的问题
- 熔岩羊驼LLaVA:社区又一个多模态大模型,像GPT-4一样可以看图聊天
- (七)卷积层——填充和步幅
- 几个效果比较好的臀部训练动作,帮你更好的锻炼臀部肌肉
- 中东欧歌舞齐聚昆山春晚 不出国门置身欧洲
- 【BZOJ3265】志愿者招募加强版 线性规划 单纯形法 对偶原理
- 【华为机试真题详解 Python实现】最差产品奖【2023 Q1 | 100分】