Java微信公众号提醒开发【保姆级教程】

1.微信公众平台

(1)打开测试号管理:

微信公众平台

(2)关注自己对应的公众号:

这里的微信号即为open_id,但正式开发一定要自己获取open_id

(3)获取用户open_id【代码示例已给出】

有问题可自行查询策略:通过java方式获取微信用户openId_java获取openid-CSDN博客

注意:与微信公众号测试交互,必须内网穿透

启动内网穿透:ngork http 7676ngrok | API Gateway, IoT Device Gateway, Secure Tunnels for Containers, Apps & APIs,开放对应的后端端口

填写域名:09f7-2408-8226-8f12-aab0-b1-c083-28f4-f8ab.ngrok-free.app,没有http

(4)添加测试模板【自行设计消防微信报警提醒模板】

例如:

标题:

对接进度提醒

内容:

对接内容:{{AchievementName.DATA}} 
成果方:{{SchoolName.DATA}} 
需求方:{{EnterpriseName.DATA}} 
备注:{{Remark.DATA}} 
时间:{{JoinTime.DATA}}

反馈如下:

2.微信开发实现示例【消防请写成接口】

(1)导入依赖

        <!-- WxJava公众号 -->
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-mp</artifactId>
            <version>3.6.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>3.17</version>
        </dependency>

(2)添加微信公众号配置

(3)配置类

package com.tyut.co_school.config;

import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.config.WxMpConfigStorage;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author xh
 * @Date 2022/7/14
 */
@Configuration
public class WxConfig {
    private final WxMpProperties wxMpProperties;

    /**
     * 构造注入
     *
     * @param wxMpProperties
     */
    WxConfig(WxMpProperties wxMpProperties) {
        this.wxMpProperties = wxMpProperties;
    }

    /**
     * 微信客户端配置存储
     *
     * @return
     */
    @Bean
    public WxMpConfigStorage wxMpConfigStorage() {
        WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
        // 公众号appId
        configStorage.setAppId(wxMpProperties.getAppId());
        // 公众号appSecret
        configStorage.setSecret(wxMpProperties.getSecret());
        // 公众号Token
//        configStorage.setToken(wxMpProperties.getToken());
        // 公众号EncodingAESKey
//        configStorage.setAesKey(wxMpProperties.getAesKey());
        return configStorage;
    }

    /**
     * 声明实例
     *
     * @return
     */
    @Bean
    public WxMpService wxMpService() {
        WxMpService wxMpService = new WxMpServiceImpl();
        wxMpService.setWxMpConfigStorage(wxMpConfigStorage());
        return wxMpService;
    }
}
package com.tyut.co_school.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @author xh
 * @Date 2022/7/14
 */
@Data
@Component
@ConfigurationProperties(prefix = "wx")
public class WxMpProperties {
    /**
     * 公众号appId
     */
    private String appId;

    /**
     * 公众号appSecret
     */
    private String secret;

    /**
     * 服务器地址
     */
    private String url;

    /**
     * 前端服务器地址
     */
    private String frontUrl;
    /**
     * 公众号token
     */
//    private String token;

    /**
     * 公众号aesKey
     */
//    private String aesKey;
}

(4)controller

package com.tyut.co_school.controller;

import com.google.gson.Gson;
import com.tyut.co_school.config.WxMpProperties;

import com.tyut.co_school.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.*;

/**
 * @author xh
 * @Date 2022/7/14
 */
//@RestController
@Slf4j
@Controller
public class WxMsgController {

    /**
     * 获取微信配置信息
     */
    @Autowired
    private WxMpProperties wxMpProperties;
    @GetMapping("/index")
    public String index(){
        return "/index";
    }



    /**
     * 测试接收微信官方通知
     *
     * @param request
     * @return
     */
    @GetMapping(value = "/weChatToken", produces = {"application/json;charset=utf-8"})
    @ResponseBody
    public String notify(HttpServletRequest request) {
        String token = "heart";
        // 判断是否是Get请求
        boolean isGet = request.getMethod().toLowerCase().equals("get");
        if (isGet) {
            // 微信加密签名
            String signature = request.getParameter("signature");
            // 时间戳
            String timestamp = request.getParameter("timestamp");
            // 随机数
            String nonce = request.getParameter("nonce");
            log.info("signature:{}, timestamp:{}, nonce:{}", signature, timestamp, nonce);
            // 随机字符串
            String echostr = request.getParameter("echostr");


            // 1)将token、timestamp、nonce三个参数进行字典序排序
            List<String> list = Arrays.asList(token, timestamp, nonce);
            Collections.sort(list);
            // 2)将三个参数字符串拼接成一个字符串进行sha1加密
            StringBuilder stringBuilder = new StringBuilder();
            for (String s : list){
                stringBuilder.append(s);
            }

            try {
                // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
                MessageDigest instance =
                        MessageDigest.getInstance("sha1");
                //使⽤sha1进⾏加密,获得byte数组
                byte[] digest =
                        instance.digest(stringBuilder.toString().getBytes());
                StringBuilder sum = new StringBuilder();
                for (byte b : digest) {
                    sum.append(Integer.toHexString((b >> 4) & 15));
                    sum.append(Integer.toHexString(b & 15));
                }
                // 3)开发者获得加密后的字符串可与 signature 对⽐,标识该请求来源于微信
                if (!com.baomidou.mybatisplus.core.toolkit.StringUtils.isEmpty(signature) &&
                        signature.equals(sum.toString())) {
                    return echostr;
                }

            } catch (Exception e) {
                log.info("测试微信公众号的接口配置信息发生异常:", e);
                return "系统异常!";
            }
        } else {
            return "非法请求!疑似黑客攻击,列入黑名单";
        }
        return null;
    }

    /**
     * 获取access_token,access_token是公众号的全局唯一接口调用凭据
     */
    @GetMapping("/get_wx_token")
    @ResponseBody
    public Map<String, Long> getWxToken() {
        RestTemplate restTemplate = new RestTemplate();
        Map<String, String> map = new HashMap<>();
        map.put("AppId", wxMpProperties.getAppId());
        map.put("AppSecret", wxMpProperties.getSecret());
        // 调用微信公众号接口
        ResponseEntity<String> forEntity = restTemplate.getForEntity("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={AppId}&secret={AppSecret}", String.class, map);
        // 解析JSON
        String body = forEntity.getBody();
        log.info("发送token获得到的body:{}", body);
        Gson gson = new Gson();
        HashMap<String, Object> jsonObject = gson.fromJson(body, HashMap.class);
        String accessToken = String.valueOf(jsonObject.get("access_token"));
        Double expiresIn = Double.parseDouble(String.valueOf(jsonObject.get("expires_in")));//时效--7200s
        return new HashMap<String, Long>() {{put(accessToken, expiresIn.longValue());}};
    }



    /**
     * 获取微信用户code,并重定向获取用户openId
     *
     * @return
     */
    @GetMapping("/getOpenIdUrl")
    @ResponseBody
    public R getOpenIdUrl() {
        String url = wxMpProperties.getUrl();
        String backUrl = url + "/api/getUserOpenId";
        String getOpenIdUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=" + backUrl + "&response_type=code&scope=snsapi_userinfo&state=1,0#wechat_redirect";
        getOpenIdUrl = getOpenIdUrl.replace("APPID", wxMpProperties.getAppId());
        return R.ok(getOpenIdUrl);
    }

    @GetMapping("/wxlogin")
    public String wxlogin(){
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wxMpProperties.getAppId() +
                "&redirect_uri=" + wxMpProperties.getUrl()+ "/api/getUserOpenId" +
                "&response_type=code" +
                "&scope=snsapi_userinfo" +
                "&state=STATE#wechat_redirect";
        return "redirect:"+url;
    }

    /**
     * 获取用户openId
     *
     * @return
     * @throws IOException
     */
    @GetMapping("/getUserOpenId")
    public void getUserOpenId(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //获取code
        String code = request.getParameter("code");
        log.info("获取到微信授权后:code:{}", code);
        //换取用户openid
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
        url = url.replace("APPID", wxMpProperties.getAppId()).replace("SECRET", wxMpProperties.getSecret()).replace("CODE", code);
        RestTemplate restTemplate = new RestTemplate();
        //解决乱码,以utf-8编码格式获取,不加这个会乱码
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);
        // 解析JSON
        String body = forEntity.getBody();
        log.info("body:{}", body);
        Gson gson = new Gson();
        HashMap<String, Object> jsonObject = gson.fromJson(body, HashMap.class);
        String openid = String.valueOf(jsonObject.get("openid"));
        response.sendRedirect(wxMpProperties.getFrontUrl() + "?openId=" + openid);
//        return "redirect:?openid=" + openid;
    }
}

(5)微信公众号提醒模板entity

package com.tyut.co_school.entity.vo.wx;

import lombok.Data;

import java.util.Date;

/**
 * Created with IntelliJ IDEA.
 *
 */
@Data
public class SendMsgReq {

    /**
     * 对接成果
     */
    private String achievementName;

    /**
     * 成果方
     */
    private String schoolName;

    /**
     * 需求方
     */
    private String enterpriseName;

    /**
     * 时间
     */
    private String joinTime;
    /**
     * 备注
     */
    private String remark;

    /**
     * 用户openId
     */
    private String openId;

    /**
     * 模板ID
     */
    private String templateId = "WT2nYHIvZtxR4oIcwFkjJ2uw5fGDDcQ2KzoW3xnjKWA";

    /**
     * 跳转网页
     */
    private String url = "http://47.100.198.147:7777/#/app/join_view/";
}

(6)service实现类

package com.tyut.co_school.service.impl;


import com.tyut.co_school.entity.vo.wx.SendMsgReq;
import com.tyut.co_school.service.WxMsgService;
import com.tyut.co_school.utils.BusinessException;
import com.tyut.co_school.utils.enums.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author xh
 * @Date 2022/7/14
 */
@Service
@Slf4j
public class WxMsgServiceImpl implements WxMsgService {
    /**
     * 微信公众号API的Service
     */
    @Autowired
    private WxMpService wxMpService;

    @Override
    public Boolean SendWxMsg(SendMsgReq sendMsgReq) {
        // 发送模板消息接口
        WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                // 接收者openid
                .toUser(sendMsgReq.getOpenId())
                // 模板id
                .templateId(sendMsgReq.getTemplateId())
                // 模板跳转链接,预约平台地址
                .url(sendMsgReq.getUrl())
                .build();
        // 获取发送数据
        // 添加模板数据
        templateMessage
                .addData(new WxMpTemplateData("AchievementName", sendMsgReq.getAchievementName(), "#FF00FF"))
                .addData(new WxMpTemplateData("SchoolName", sendMsgReq.getSchoolName(), "#A9A9A9"))
                .addData(new WxMpTemplateData("EnterpriseName", sendMsgReq.getEnterpriseName(), "#FF00FF"))
                .addData(new WxMpTemplateData("JoinTime", sendMsgReq.getJoinTime().toString(), "#000000"))
                .addData(new WxMpTemplateData("Remark", sendMsgReq.getRemark(), "#000000"))
        ;
        String msgId = null;
        try {
            // 发送模板消息
            msgId = wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
        } catch (WxErrorException e) {
            e.printStackTrace();
        }
        log.warn("·==++--·推送微信模板信息:{}·--++==·", msgId != null ? "成功" : "失败");
        return msgId != null;
    }

    @Override
    public Boolean SendWxMsgBatchs(List<SendMsgReq> sendMsgReqs) {
        if(sendMsgReqs == null || sendMsgReqs.size() == 0) return false;
        // 并行流处理
        sendMsgReqs.stream().forEach(sendMsgReq -> {
            String openid = sendMsgReq.getOpenId(); // 微信openid
            String templateId = sendMsgReq.getTemplateId(); // 模板id
            String url = sendMsgReq.getUrl();
            // 发送模板消息接口
            WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
                    // 接收者openid
                    .toUser(openid)
                    // 模板id
                    .templateId(templateId)
                    // 模板跳转链接
                    .url(url)
                    .build();
            // 添加模板数据
            String achievementName = sendMsgReq.getAchievementName();
            String schoolName = sendMsgReq.getSchoolName();
            String enterpriseName = sendMsgReq.getEnterpriseName();
            String joinTime = sendMsgReq.getJoinTime().toString();
            templateMessage
                    .addData(new WxMpTemplateData("AchievementName", achievementName, "#FF00FF"))
                    .addData(new WxMpTemplateData("SchoolName", schoolName, "#A9A9A9"))
                    .addData(new WxMpTemplateData("EnterpriseName", enterpriseName, "#FF00FF"))
                    .addData(new WxMpTemplateData("JoinTime", joinTime, "#000000"))
                    .addData(new WxMpTemplateData("Remark", sendMsgReq.getRemark(), "#000000"))
            ;

            try {
                // 发送模板消息
                wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
            } catch (WxErrorException e) {
                e.printStackTrace();
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "发送模板消息出错");
            }
        });
        return true;
    }
}

(7)微信提醒测试

填入自己的open_id和模板数据进行测试

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值