SpringBoot接入微信公众号【服务号】
SpringBoot接入微信公众号【服务号】
一、服务号注册
注册地址:https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index&lang=zh_CN
注册流程参考:https://kf.qq.com/touch/faq/150804UVr222150804quq6B7.html?platform=15
二、服务号配置
基本配置
用于服务配置
访问及服务配置
网页授权配置
三、核心代码
- 基于WxJava - 微信开发 Java SDK
- 实现关注、取关逻辑
- 实现消息被动回复
- 实现个人信息网页授权
- 提供基本业务功能
微信开发者文档:https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Overview.html
WxJava开源地址:https://gitee.com/binary/weixin-java-tools?_from=gitee_search
引入pom依赖
<dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-mp</artifactId><version>4.5.0</version>
</dependency>
yml配置文件
# 微信公众号配置
wx:mp:appId: wx1111111appSecret: 111111111111# 配置消息回调地址接入公众号时需要的tokentoken: add2222aesKey: xxxxserver: https://www.baidu.com/
属性配置类
package com.qiangesoft.wechat.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;/*** 微信公众号相关配置属性** @author qiangesoft* @date 2023-09-07*/
@Data
@Component
@ConfigurationProperties(WxMpProperties.PREFIX)
public class WxMpProperties {public static final String PREFIX = "wx.mp";/*** 公众号开发信息:appId*/private String appId;/*** 公众号开发信息:appSecret*/private String appSecret;/*** 服务器配置:token*/private String token;/*** 服务器配置:消息加解密密钥EncodingAESKey*/private String aesKey;/*** 服务器配置:微信服务器地址*/private String server;}
bean配置类
package com.qiangesoft.wechat.config;import com.qiangesoft.wechat.core.handler.LogHandler;
import com.qiangesoft.wechat.core.handler.event.SubscribeHandler;
import com.qiangesoft.wechat.core.handler.event.UnsubscribeHandler;
import com.qiangesoft.wechat.core.handler.message.ImageHandler;
import com.qiangesoft.wechat.core.handler.message.LocationHandler;
import com.qiangesoft.wechat.core.handler.message.MessageHandler;
import com.qiangesoft.wechat.core.handler.message.VoiceHandler;
import com.qiangesoft.wechat.core.interceptor.MessageInterceptor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
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 qiangesoft* @date 2023-09-07*/
@Slf4j
@Configuration
@RequiredArgsConstructor
public class WxMpConfiguration {/*** 微信公众号配置信息*/private final WxMpProperties wxMpProperties;/*** 日志处理器*/private final LogHandler logHandler;/*** 订阅事件处理器*/private final SubscribeHandler subscribeHandler;/*** 取消订阅事件处理器*/private final UnsubscribeHandler unsubscribeHandler;/*** 语音消息处理器*/private final VoiceHandler voiceHandler;/*** 文本消息处理器*/private final MessageHandler messageHandler;/*** 图片消息处理器*/private final ImageHandler imageHandler;/*** 位置消息处理器*/private final LocationHandler locationHandler;/*** 消息拦截器*/private final MessageInterceptor messageInterceptor;/*** 声明实例** @return*/@Beanpublic WxMpService wxMpService() {WxMpService wxMpService = new WxMpServiceImpl();wxMpService.setWxMpConfigStorage(wxMpConfigStorage());return wxMpService;}/*** 配置存储方式** @return*/@Beanpublic WxMpConfigStorage wxMpConfigStorage() {WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();// 公众号appIdconfigStorage.setAppId(wxMpProperties.getAppId());// 公众号appSecretconfigStorage.setSecret(wxMpProperties.getAppSecret());// 公众号TokenconfigStorage.setToken(wxMpProperties.getToken());// 公众号EncodingAESKeyconfigStorage.setAesKey(wxMpProperties.getAesKey());return configStorage;}/*** 配置公众号的事件路由* <p>* 1.用户发消息* 2.关注事件* 3.取消关注事件* ......*/@Beanpublic WxMpMessageRouter messageRouter(WxMpService wxMpService) {WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);// 记录所有消息事件的日志newRouter.rule().async(false).handler(this.logHandler).next();// 文本消息newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.TEXT).interceptor(this.messageInterceptor).handler(this.messageHandler).end();// 语音消息newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.VOICE).handler(this.voiceHandler).end();// 图片消息newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.IMAGE).handler(this.imageHandler).end();// 位置消息newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION).handler(this.locationHandler).end();// 关注事件newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.SUBSCRIBE).handler(this.subscribeHandler).end();// 取消关注事件newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.UNSUBSCRIBE).handler(this.unsubscribeHandler).end();return newRouter;}
}
网页授权接入配置
下载验证文件放于项目目录
package com.qiangesoft.wechat.controller;import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;/*** 微信接入控制器* ps:(JS接口安全域名、网页授权域名需要获取MP_verify_eerrereeee.txt)* <a href="https://mp.weixin.qq.com/cgi-bin/settingpage?t=setting/function&action=function&token=854866943&lang=zh_CN">...</a>** @author qiangesoft* @date 2023-09-11*/
@Slf4j
@Api(tags = "微信接入")
@RestController
@RequestMapping("/wechat")
public class WxAccessController {/*** 获取安全凭证* ps:例如[http://主机:端口/wechat/MP_verify_eerrereeee.txt]** @param fileName* @param response*/@ApiOperation(value = "安全凭证")@GetMapping("/{fileName}")public void security(@PathVariable String fileName, HttpServletResponse response) {InputStream is = null;OutputStream os = null;try {// 获取文件ClassPathResource classPathResource = new ClassPathResource(fileName);String filename = classPathResource.getFilename();is = classPathResource.getInputStream();byte[] bytes = is.readAllBytes();response.setCharacterEncoding("UTF-8");response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8));response.addHeader(HttpHeaders.CONTENT_LENGTH, bytes.length + "");response.setContentType("application/octet-stream");os = response.getOutputStream();os.write(bytes);} catch (IOException e) {e.printStackTrace();} finally {if (os != null) {try {os.close();} catch (IOException e) {e.printStackTrace();}}if (is != null) {try {is.close();} catch (IOException e) {e.printStackTrace();}}}}
}
微信请求验证及被动消息回复
package com.qiangesoft.wechat.controller;import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;/*** 微信消息控制器* ps:请求验证、接收消息被动回复等** @author qiangesoft* @date 2023-09-07*/
@Slf4j
@Api(tags = "微信消息")
@RestController
@RequestMapping("/wechat/message")
public class WxMessageController {@Autowiredprivate WxMpService wxMpService;@Autowiredprivate WxMpMessageRouter wxMpMessageRouter;@ApiOperation(value = "验证接口")@GetMappingpublic String validate(@RequestParam String signature,@RequestParam String timestamp,@RequestParam String nonce,@RequestParam String echostr) {// 校验消息是否来自微信if (!wxMpService.checkSignature(timestamp, nonce, signature)) {throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");}return echostr;}@ApiOperation(value = "接收消息")@PostMapping(produces = "application/xml; charset=UTF-8")public String handleMessage(@RequestBody String requestBody,@RequestParam String signature,@RequestParam String timestamp,@RequestParam String nonce,@RequestParam String openid,@RequestParam(name = "encrypt_type", required = false) String encType,@RequestParam(name = "msg_signature", required = false) String msgSignature) {// 校验消息是否来自微信if (!wxMpService.checkSignature(timestamp, nonce, signature)) {throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");}// 消息处理【被动消息回复】String message = null;if (encType == null) {// 明文传输WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);WxMpXmlOutMessage outMessage = wxMpMessageRouter.route(inMessage);if (outMessage == null) {return null;}message = outMessage.toXml();} else if ("aes".equalsIgnoreCase(encType)) {// aes加密WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, wxMpService.getWxMpConfigStorage(), timestamp, nonce, msgSignature);WxMpXmlOutMessage outMessage = wxMpMessageRouter.route(inMessage);if (outMessage == null) {return null;}message = outMessage.toEncryptedXml(wxMpService.getWxMpConfigStorage());}return message;}
}
用户信息网页授权
package com.qiangesoft.wechat.controller;import com.qiangesoft.wechat.config.WxMpProperties;
import com.qiangesoft.wechat.dto.UserDTO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.service.WxOAuth2Service;
import me.chanjar.weixin.mp.api.WxMpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;/*** 微信用户控制器* ps:获取用户信息、授权网页用户信息等** @author qiangesoft* @date 2023-09-11*/
@Slf4j
@Api(tags = "微信用户")
@Controller
@RequestMapping("/wechat/user")
public class WxUserController {@Autowiredprivate WxMpProperties wxMpProperties;@Autowiredprivate WxMpService wxMpService;@ApiOperation(value = "个人信息")@GetMapping("/mine")public String mine() {WxOAuth2Service oAuth2Service = wxMpService.getOAuth2Service();// 构建授权urlString authorizationUrl = oAuth2Service.buildAuthorizationUrl(wxMpProperties.getServer() + "wechat/user/callback", WxConsts.OAuth2Scope.SNSAPI_USERINFO, null);return "redirect:" + authorizationUrl;}@ApiOperation(value = "个人信息网页授权回调")@GetMapping("/callback")public String callback(String code, Model model) throws WxErrorException {WxOAuth2UserInfo userInfo = this.getUserInfo(code);String openid = userInfo.getOpenid();// todo 通过openid拿取业务系统详细用户信息 IWxUserServiceUserDTO userDTO = new UserDTO();userDTO.setOpenId(openid);userDTO.setNickName(userInfo.getNickname());model.addAttribute("user", userDTO);return "mine";}/*** 获取微信用户信息** @param code* @return* @throws WxErrorException*/private WxOAuth2UserInfo getUserInfo(String code) throws WxErrorException {WxOAuth2Service oAuth2Service = wxMpService.getOAuth2Service();// 利用code获取accessTokenWxOAuth2AccessToken accessToken = oAuth2Service.getAccessToken(code);// 利用accessToken获取用户信息WxOAuth2UserInfo userInfo = oAuth2Service.getUserInfo(accessToken, null);return userInfo;}
}
消息拦截器
package com.qiangesoft.wechat.core.interceptor;import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageInterceptor;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import org.springframework.stereotype.Component;import java.util.Map;/*** 对微信公众号消息进行预处理、过滤等操作,根据具体业务需求决定是否允许继续执行后面的路由处理方法* <p>* 1.如果要中止消息的继续处理,需要返回 false* 2.在执行完当前拦截器操作后,允许消息的继续处理,返回 true** @author qiangesoft* @date 2023-09-07*/
@Component
public class MessageInterceptor implements WxMpMessageInterceptor {@Overridepublic boolean intercept(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {String msgType = wxMessage.getMsgType();String content = wxMessage.getContent();// 文本处理if (msgType.equals(WxConsts.XmlMsgType.TEXT)) {if (content.contains("混蛋")) {String newContent = content.replace("混蛋", "***");wxMessage.setContent(newContent);}return true;}// todo 音频、视频处理return true;}
}
消息事件处理器
1.关注事件处理器
package com.qiangesoft.wechat.core.handler.event;import com.qiangesoft.wechat.core.builder.TextOutMessageBuilder;
import com.qiangesoft.wechat.entity.WxUser;
import com.qiangesoft.wechat.service.IWxUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.stereotype.Component;import java.util.Map;/*** 微信公众号用户关注处理器** @author qiangesoft* @date 2023-09-07*/
@Slf4j
@Component
@RequiredArgsConstructor
public class SubscribeHandler implements WxMpMessageHandler {private final IWxUserService wxUserService;@Overridepublic WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {if (!wxMessage.getMsgType().equals(WxConsts.EventType.SUBSCRIBE)) {return null;}String openId = wxMessage.getFromUser();// 微信关注用户WxUser wxUser = wxUserService.getByOpenId(openId);if (wxUser == null) {wxUser = new WxUser();wxUser.setOpenId(openId);wxUser.setAttentionFlag(true);wxUserService.save(wxUser);} else {wxUser.setAttentionFlag(true);wxUserService.updateById(wxUser);}String outContent = "您好,欢迎关注xxx!";return new TextOutMessageBuilder().build(outContent, wxMessage, wxMpService);}
}
2.取关事件处理器
package com.qiangesoft.wechat.core.handler.event;import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qiangesoft.wechat.core.builder.TextOutMessageBuilder;
import com.qiangesoft.wechat.entity.WxUser;
import com.qiangesoft.wechat.service.IWxUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.stereotype.Component;import java.util.Map;/*** 微信公众号用户取消关注处理器** @author qiangesoft* @date 2023-09-07*/
@Slf4j
@Component
@RequiredArgsConstructor
public class UnsubscribeHandler implements WxMpMessageHandler {private final IWxUserService wxUserService;@Overridepublic WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {if (!wxMessage.getMsgType().equals(WxConsts.EventType.UNSUBSCRIBE)) {return null;}String openId = wxMessage.getFromUser();// 取消关注LambdaUpdateWrapper<WxUser> updateWrapper = new LambdaUpdateWrapper<>();updateWrapper.eq(WxUser::getOpenId, openId).set(WxUser::getAttentionFlag, false);wxUserService.update(updateWrapper);String outContent = "已取消关注xxx,再见!";return new TextOutMessageBuilder().build(outContent, wxMessage, wxMpService);}
}
3.文本消息处理器
package com.qiangesoft.wechat.core.handler.message;import com.qiangesoft.wechat.core.builder.TextOutMessageBuilder;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.stereotype.Component;import java.util.Map;/*** 文本消息处理器** @author qiangesoft* @date 2023-09-07*/
@Slf4j
@Component
public class MessageHandler implements WxMpMessageHandler {@Overridepublic WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {if (!wxMessage.getMsgType().equals(WxConsts.XmlMsgType.TEXT)) {return null;}// 接收的消息内容String content = wxMessage.getContent();log.info("Received wechat text message, content [{}] !", content);String outContent = "您好,欢迎访问xxx!";if (content.contains("你好") || content.contains("您好")) {outContent = "您好";}return new TextOutMessageBuilder().build(outContent, wxMessage, wxMpService);}
}
4.日志记录处理器
package com.qiangesoft.wechat.core.handler;import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.stereotype.Component;import java.util.Map;/*** 微信公众号日志记录处理器** @author qiangesoft* @date 2023-09-07*/
@Slf4j
@Component
public class LogHandler implements WxMpMessageHandler {@Overridepublic WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {log.info("Received wechat message, content is [{}]", JSONObject.toJSONString(wxMessage));return null;}
}
源码地址
地址:https://gitee.com/qiangesoft/boot-business/tree/master/boot-business-wechat
相关文章:

SpringBoot接入微信公众号【服务号】
SpringBoot接入微信公众号【服务号】 一、服务号注册 注册地址:https://mp.weixin.qq.com/cgi-bin/registermidpage?actionindex&langzh_CN 注册流程参考:https://kf.qq.com/touch/faq/150804UVr222150804quq6B7.html?platform15 二、服务号配…...

2023 英特尔On技术创新大会直播 |探索视觉AI的无限可能
2023 英特尔On技术创新大会直播 | 探索视觉AI的无限可能 前言一未来的 AI:释放视觉 AI 真正潜力二AI技术突破、视觉Al挑战及前沿研究创新三全尺度视觉学习全尺度视觉学习示例1.GridConv 实现三维人体姿态估计更高准确率2.KW 预训练及迁移模型性能3.无数据增强稠密对…...

安卓视图基础
目录 设置视图的宽高 设置视图的间隔 设置视图的对齐方式 设置视图的宽高 设置视图的间隔 设置视图的对齐方式 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"a…...

电路设计(10)——超温报警电路的proteus仿真
1.题目背景 在现实生活中,常有一种工程技术,即带有自动温度补偿的设备,能在规定温度内正常工作。但是为了设备安全,需设定工作的上限温度,万一温控补偿失效,设备温度一旦超出上限温度时,便立即切…...
gerrit(1) | gerrit 简介
gerrit(1) | gerrit 简介 1. 目的 之前用过 gitlab CI/CD, github actions, 以及公司的配置管理员配置的 jenkins。 github 的 MR, github 的 PR, 虽然在用, 但仅限于参与开源项目或公司内的开源项目, OEM 项目中完全没在用。 …...

计算机视觉实战项目3(图像分类+目标检测+目标跟踪+姿态识别+车道线识别+车牌识别+无人机检测+A*路径规划+单目测距与测速+行人车辆计数等)
车辆跟踪及测距 该项目一个基于深度学习和目标跟踪算法的项目,主要用于实现视频中的目标检测和跟踪。该项目使用了 YOLOv5目标检测算法和 DeepSORT 目标跟踪算法,以及一些辅助工具和库,可以帮助用户快速地在本地或者云端上实现视频目标检测和…...

redis(5)
文章目录 一、redis 哨兵(sentinel)redis 集群介绍哨兵(Sentinel)工作原理sentinel 架构和故障转移sentinel中的三个定时任务 实时哨兵启动哨兵验证哨兵端口查看哨兵日志当前sentinel状态停止Redis Master测试故障转移恢复故障的m…...

Postgresql体系结构
client连接PostgreSQL过程: 1、客户端发起请求 2、主服务postmaster进程负责服务器是否接受客户端的host通信认证,服务器对客户端进行身份鉴别 3、主服务进程为该客户端单独fork一个客户端工作进程postgres 4、客户端与postgres进程建立通信连接…...

【Rust】——rust前言与安装rust
🎃个人专栏: 🐬 算法设计与分析:算法设计与分析_IT闫的博客-CSDN博客 🐳Java基础:Java基础_IT闫的博客-CSDN博客 🐋c语言:c语言_IT闫的博客-CSDN博客 🐟MySQL:…...

基于SpringBoot的家电销售展示网页的设计与实现
文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式 🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 &…...

【Qt】—— 项⽬⽂件解析
目录 (一).pro⽂件解析 (二)widget.h⽂件解析 (三)main.cpp⽂件解析 (四)widget.cpp⽂件解析 (五)widget.ui⽂件解析 (一).pro⽂…...

【Linux】静态库和动态库
动静态库 一、静态库1. 静态库概念2. 制作静态库(1)朴素方法 --- 不打包(2)对静态库打包 3. 使用静态库(1)朴素方法 --- 直接使用(2)使用打包好的静态库 二、动态库1. 动态库概念2. …...
LeetCode 0292.Nim 游戏:脑筋急转弯
【LetMeFly】292.Nim 游戏:脑筋急转弯 力扣题目链接:https://leetcode.cn/problems/nim-game/ 你和你的朋友,两个人一起玩 Nim 游戏: 桌子上有一堆石头。你们轮流进行自己的回合, 你作为先手 。每一回合,…...

ctfshow-web1~10-WP
web1 右键查看源码就能看到flag web2 打开网页提示无法查看源代码,右键也使用不了,那我们就在url前面加上view-source: view-source:http://83a83588-671e-4a94-9c6f-6857f9e20c2f.chall.ctf.show/ 访问后即可获得flag web3 右键源码也没看到信息,去查看一下请求头和响应…...

集合问题(并查集)
本题链接:登录—专业IT笔试面试备考平台_牛客网 题目: 样例1: 输入 4 5 9 2 3 4 5 输出 YES 0 0 1 1 样例2: 输入 3 3 4 1 2 4 输出 NO 思路: 这道题关键点在于。 当集合中有一个元素均存在于集合 A 和集合 B 的时…...
Ubuntu文件系统结构
Ubuntu文件系统结构 介绍 Ubuntu是一种备受欢迎的Linux发行版,其文件系统结构以及组织方式是每个使用者和系统管理员都应该了解的重要主题。本篇博客将带您深入探索Ubuntu文件系统的结构,以便更好地理解Linux操作系统的工作原理。 1. 根目录ÿ…...

vue element 组件 form深层 :prop 验证失效问题解决
此图源自官网 借鉴。 当我们简单单层验证的时候发现是没有问题的,但是有的时候可能会涉及到深层prop,发现在去绑定的时候就不生效了。例如我们在form单里面循环验证,在去循环数据验证。 就如下图的写法了 :prop"pumplist. i .device…...
前端开发:入门(一)
当我们开始学习前端开发时,首先接触到的是HTML(超文本标记语言)。HTML是构建网页结构的基础。 1. HTML(超文本标记语言) 介绍和基础语法 HTML,即超文本标记语言,是一种用于创建网页结构的标记…...

简单实验 java spring cloud 自定义负载均衡
1.概要 1.1 说明 这个是在前一个测试上的修改,所以这里只体现修改的内容。前一个测试的地址:检查实验 spring cloud nacos nacos-server-2.3.0-CSDN博客 1.2 记忆要点 1.2.1 引入对象 Autowired DiscoveryClient discoveryClient; 1.2.2 获取服务实…...

简单说说redis分布式锁
什么是分布式锁 分布式锁(多服务共享锁)在分布式的部署环境下,通过锁机制来让多客户端互斥的对共享资源进行访问/操作。 为什么需要分布式锁 在单体应用服务里,不同的客户端操作同一个资源,我们可以通过操作系统提供…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...

麒麟系统使用-进行.NET开发
文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的,如果需要进行.NET开发,则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET,所以要进…...

在Zenodo下载文件 用到googlecolab googledrive
方法:Figshare/Zenodo上的数据/文件下载不下来?尝试利用Google Colab :https://zhuanlan.zhihu.com/p/1898503078782674027 参考: 通过Colab&谷歌云下载Figshare数据,超级实用!!࿰…...