《花100块做个摸鱼小网站! 》第七篇—谁访问了我们的网站?

⭐️基础链接导航⭐️

服务器 → ☁️ 阿里云活动地址

看样例 → 🐟 摸鱼小网站地址

学代码 → 💻 源码库地址

一、前言

大家好呀,我是summo,最近发生了些事情(被裁员了,在找工作中)导致断更了,非常抱歉。刚被裁的时候还是有些难受,而且我还有房贷要还,有些压力,不过休息了一段时间,心态也平复了一些,打算一边找工作一边写文,如果有和我一样经历的同学,大家共勉!

《花100块做个摸鱼小网站! 》这个系列的前六篇已经大概把整体的流程写完了,从这篇起我会补充一些细节和组件,让我们的小网站更加丰富一些。这一篇呢我会介绍如何将用户的访问记录留下来,看着自己做的网站被别人访问是一件很有意思和很有成就感的事情。

对应的组件也就是我用红框标出来的那个,如下图:

解释下PV和UV的意思,如下:

  • PV:页面访问量,即PageView,用户每次对网站的访问均被记录,用户对同一页面的多次访问,访问量累计。
  • UV:独立访问用户数:即UniqueVisitor,访问网站的一台电脑客户端为一个访客。

二、用户身份标识

用于表明一个用户身份最好的做法是做登录注册,但是一旦加了这样的逻辑,就会有很多麻烦的问题要处理,比如如何做人机验证啦、接口防刷啦,等等,这些问题不处理的话网站很容易被攻击。像我们这样的小网站,我觉得这个功能没必要,我们只需要知道有多少人访问过我们的网站就可以了。

对于这样的需求,最简单的做法是根据用户的访问IP作为标识,然后根据IP解析一下地域信息,这样就已经很不错了。而目前最常用的IP解析工具就是:ip2region,如何使用这个组件我之前写过一篇文章进行介绍了,文章链接:SpringBoot整合ip2region实现使用ip监控用户访问城市。

核心代码是这段:

package com.example.springbootip.util;import org.apache.commons.io.FileUtils;
import org.lionsoul.ip2region.xdb.Searcher;import java.io.File;
import java.text.MessageFormat;
import java.util.Objects;public class AddressUtil {/*** 当前记录地址的本地DB*/private static final String TEMP_FILE_DIR = "/home/admin/app/";/*** 根据IP地址查询登录来源** @param ip* @return*/public static String getCityInfo(String ip) {try {// 获取当前记录地址位置的文件String dbPath = Objects.requireNonNull(AddressUtil.class.getResource("/ip2region/ip2region.xdb")).getPath();File file = new File(dbPath);//如果当前文件不存在,则从缓存中复制一份if (!file.exists()) {dbPath =    TEMP_FILE_DIR + "ip.db";System.out.println(MessageFormat.format("当前目录为:[{0}]", dbPath));file = new File(dbPath);FileUtils.copyInputStreamToFile(Objects.requireNonNull(AddressUtil.class.getClassLoader().getResourceAsStream("classpath:ip2region/ip2region.xdb")), file);}//创建查询对象Searcher searcher = Searcher.newWithFileOnly(dbPath);//开始查询return searcher.searchByStr(ip);} catch (Exception e) {e.printStackTrace();}//默认返回空字符串return "";}public static void main(String[] args) {System.out.println(getCityInfo("1.2.3.4"));}
}

三、功能实现

为了解耦逻辑,我使用了一个注解:@VisitLog,只要将该注解放在IndexController的index方法上即可。同时为了统计用户的访问数据,我们需要设计一张访问记录表将数据存下来,并设计一个小组件用来展示这些数据,具体流程如下文。

1. 后端部分

(1)访问记录表设计

建表语句
-- `summo-sbmy`.t_sbmy_visit_log definitionCREATE TABLE `t_sbmy_visit_log` (`id` bigint(20) unsigned zerofill NOT NULL AUTO_INCREMENT COMMENT '物理主键',`device_type` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '设备类型,手机还是电脑',`ip` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '访问',`address` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT 'IP地址',`time` int DEFAULT NULL COMMENT '耗时',`method` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '调用方法',`params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '参数',`gmt_create` datetime DEFAULT NULL COMMENT '创建时间',`gmt_modified` datetime DEFAULT NULL COMMENT '更新时间',`creator_id` bigint DEFAULT NULL COMMENT '创建人',`modifier_id` bigint DEFAULT NULL COMMENT '更新人',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=oDEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
DO、Mapper、Repository等文件

还记得我在第三篇介绍的那个DO生成插件吗,在config.properties改下表名和DO名,双击mybatis-generator:generate就可以生成对应的DO、Mapper、xml了。

(2)VisitLog注解

VisitLog.java
package com.summo.sbmy.aspect;/*** 访问标识注解*/
public @interface VisitLog {
}
VisitLogAspect.java
package com.summo.sbmy.aspect.visit;import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;import com.fasterxml.jackson.core.JsonProcessingException;
import com.summo.sbmy.common.util.AddressUtil;
import com.summo.sbmy.common.util.HttpContextUtil;
import com.summo.sbmy.common.util.IpUtil;
import com.summo.sbmy.dao.entity.SbmyVisitLogDO;
import com.summo.sbmy.dao.repository.SbmyVisitLogRepository;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import static com.summo.sbmy.common.util.DeviceUtil.isFromMobile;@Slf4j
@Aspect
@Component
public class VisitLogAspect {@Autowiredprivate SbmyVisitLogRepository sbmyVisitLogRepository;@Pointcut("@annotation(com.summo.sbmy.aspect.visit.Log)")public void pointcut() {// do nothing}@Around("pointcut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {//获取requestHttpServletRequest request = HttpContextUtil.getHttpServletRequest();// 请求的类名MethodSignature signature = (MethodSignature)joinPoint.getSignature();Method method = signature.getMethod();String className = joinPoint.getTarget().getClass().getName();// 请求的方法名String methodName = signature.getName();String ip = IpUtil.getIpAddr(request);String address = AddressUtil.getAddress(ip);SbmyVisitLogDO sbmyVisitLogDO = SbmyVisitLogDO.builder().deviceType(isFromMobile(request) ? "手机" : "电脑").method(className + "." + methodName + "()").ip(ip).address(AddressUtil.getAddress(address)).build();// 请求的方法参数值Object[] args = joinPoint.getArgs();// 请求的方法参数名称LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();String[] paramNames = u.getParameterNames(method);if (args != null && paramNames != null) {// 创建 key-value 映射用于生成 JSON 字符串Map<String, Object> paramMap = new LinkedHashMap<>();for (int i = 0; i < paramNames.length; i++) {if (args[i] instanceof HttpServletRequest || args[i] instanceof HttpServletResponse) {continue;}paramMap.put(paramNames[i], args[i]);}// 使用 Fastjson 将参数映射转换为 JSON 字符串String paramsJson = JSON.toJSONString(paramMap);sbmyVisitLogDO.setParams(paramsJson);}long beginTime = System.currentTimeMillis();Object proceed = joinPoint.proceed();long end = System.currentTimeMillis();sbmyVisitLogDO.setTime((int)(end - beginTime));sbmyVisitLogRepository.save(sbmyVisitLogDO);return proceed;}/*** 参数构造器¬** @param params* @param args* @param paramNames* @return* @throws JsonProcessingException*/private StringBuilder handleParams(StringBuilder params, Object[] args, List paramNames)throws JsonProcessingException {for (int i = 0; i < args.length; i++) {if (args[i] instanceof Map) {Set set = ((Map)args[i]).keySet();List<Object> list = new ArrayList<>();List<Object> paramList = new ArrayList<>();for (Object key : set) {list.add(((Map)args[i]).get(key));paramList.add(key);}return handleParams(params, list.toArray(), paramList);} else {if (args[i] instanceof Serializable) {Class<?> aClass = args[i].getClass();try {aClass.getDeclaredMethod("toString", new Class[] {null});// 如果不抛出 NoSuchMethodException 异常则存在 toString 方法 ,安全的 writeValueAsString ,否则 走 Object的// toString方法params.append(" ").append(paramNames.get(i)).append(": ").append(JSONObject.toJSONString(args[i]));} catch (NoSuchMethodException e) {params.append(" ").append(paramNames.get(i)).append(": ").append(JSONObject.toJSONString(args[i].toString()));}} else if (args[i] instanceof MultipartFile) {MultipartFile file = (MultipartFile)args[i];params.append(" ").append(paramNames.get(i)).append(": ").append(file.getName());} else {params.append(" ").append(paramNames.get(i)).append(": ").append(args[i]);}}}return params;}
}

这里使用到了一些工具类,代码我已经上传到仓库了,大家直接down下来就行。

(3)注解使用

在IndexController.java中加入该注解即可

package com.summo.sbmy.web.controller;import com.summo.sbmy.aspect.visit.VisitLog;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;@Controller
public class IndexController {@GetMapping("/")@VisitLogpublic String index(){return "index";}
}

2. 前端部分

(1)新建VisitorLog组件

代码如下:

<template><div class="stats-card-container"><el-card class="stats-card-main"><!-- 突出显示的今日 PV --><div class="stats-section"><div class="stats-value-main">{{ statsData.todayPv }}</div><div class="stats-label-main">今日 PV</div></div><!-- 其他统计数据,以更紧凑的形式显示 --><div class="stats-section stats-others"><div class="stats-item"><div class="stats-value-small">{{ statsData.todayUv }}</div><div class="stats-label-small">今日 UV</div></div><div class="stats-item"><div class="stats-value-small">{{ statsData.allPv }}</div><div class="stats-label-small">总 PV</div></div><div class="stats-item"><div class="stats-value-small">{{ statsData.allUv }}</div><div class="stats-label-small">总 UV</div></div></div></el-card></div>
</template>
<script>
import apiService from "@/config/apiService.js";
export default {name: "VisitorLog",data() {return {statsData: {todayPv: 0,todayUv: 0,allPv: 0,allUv: 0,},};},created() {this.fetchVisitorCount(); // 组件创建时立即调用一次this.startPolling(); // 启动定时器},beforeDestroy() {this.stopPolling(); // 在组件销毁前清理定时器},methods: {fetchVisitorCount() {apiService.get("/welcome/queryVisitorCount").then((res) => {// 处理响应数据this.statsData = res.data.data;}).catch((error) => {// 处理错误情况console.error(error);});},startPolling() {// 定义一个方法来启动周期性的定时器this.polling = setInterval(() => {this.fetchVisitorCount();}, 1000 * 60 * 60); // 每60000毫秒(1分钟)调用一次},stopPolling() {// 定义一个方法来停止定时器clearInterval(this.polling);},},
};
</script><style scoped>
>>> .el-card__body{padding: 10px;
}
.stats-card-container {max-width: 400px;margin-bottom: 10px;
}.stats-card-main {padding: 12px;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}.stats-section {text-align: center;
}.stats-value-main {font-size: 24px;font-weight: bold;color: #0A74DA;margin-bottom: 4px;
}.stats-label-main {font-size: 14px;color: #333;
}.stats-others {display: flex;justify-content: space-between;margin-top: 12px;
}.stats-item {text-align: center;
}.stats-value-small, .stats-label-small {font-size: 12px; /* 减小字体尺寸以实现更紧凑的布局 */
}.stats-value-small {font-weight: bold;color: #333;margin-bottom: 2px;
}.stats-label-small {color: #666;
}@media (max-width: 400px) {.stats-others {flex-direction: column;align-items: center;}.stats-item {margin-bottom: 8px;}
}
</style>

(2)组件使用

在App.vue组件中引入VisitorLog组件,顺便将布局重新分一下,代码如下:

<template><div id="app"><el-row :gutter="10"><el-col :span="20"><el-row :gutter="10"><el-col :span="6" v-for="(board, index) in hotBoards" :key="index"><hot-search-board:title="board.title":icon="board.icon":fetch-url="board.fetchUrl":type="board.type"/></el-col></el-row></el-col><el-col :span="4"><visitor-log /></el-col></el-row></div>
</template><script>
import HotSearchBoard from "@/components/HotSearchBoard.vue";
import VisitorLog from "@/components/VisitorLog.vue";
export default {name: "App",components: {HotSearchBoard,VisitorLog,},data() {return {hotBoards: [{title: "百度",icon: require("@/assets/icons/baidu-icon.svg"),type: "baidu",},{title: "抖音",icon: require("@/assets/icons/douyin-icon.svg"),type: "douyin",},{title: "知乎",icon: require("@/assets/icons/zhihu-icon.svg"),type: "zhihu",},{title: "B站",icon: require("@/assets/icons/bilibili-icon.svg"),type: "bilibili",},{title: "搜狗",icon: require("@/assets/icons/sougou-icon.svg"),type: "sougou",},],};},
};
</script><style>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;background: #f8f9fa; /* 提供一个柔和的背景色 */min-height: 100vh; /* 使用视口高度确保填满整个屏幕 */padding: 0; /* 保持整体布局紧凑,无额外内边距 */
}
</style>

咱们做出来的效果就是这样的,如下:

这个小组件做起来还是简单的,主要就是监控了别人的访问IP,然后通过IP反解析出所属地域,最后将其存到数据库中。

番外:搜狗热搜爬虫

1. 爬虫方案评估

搜狗的热搜接口返回的一串JSON格式数据,这就很简单了,省的我们去解析dom,访问链接是:https://go.ie.sogou.com/hot_ranks

2. 网页解析代码

SougouHotSearchJob.java

package com.summo.sbmy.job.sougou;import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.summo.sbmy.common.model.dto.HotSearchDetailDTO;
import com.summo.sbmy.dao.entity.SbmyHotSearchDO;
import com.summo.sbmy.service.SbmyHotSearchService;
import com.summo.sbmy.service.convert.HotSearchConvert;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.io.IOException;
import java.util.Calendar;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.stream.Collectors;import static com.summo.sbmy.common.cache.SbmyHotSearchCache.CACHE_MAP;
import static com.summo.sbmy.common.enums.HotSearchEnum.DOUYIN;
import static com.summo.sbmy.common.enums.HotSearchEnum.SOUGOU;/*** @author summo* @version SougouHotSearchJob.java, 1.0.0* @description 搜狗热搜Java爬虫代码* @date 2024年08月09*/
@Component
@Slf4j
public class SougouHotSearchJob {@Autowiredprivate SbmyHotSearchService sbmyHotSearchService;@XxlJob("sougouHotSearchJob")public ReturnT<String> hotSearch(String param) throws IOException {log.info("搜狗热搜爬虫任务开始");try {//查询搜狗热搜数据OkHttpClient client = new OkHttpClient().newBuilder().build();Request request = new Request.Builder().url("https://go.ie.sogou.com/hot_ranks").method("GET", null).build();Response response = client.newCall(request).execute();JSONObject jsonObject = JSONObject.parseObject(response.body().string());JSONArray array = jsonObject.getJSONArray("data");List<SbmyHotSearchDO> sbmyHotSearchDOList = Lists.newArrayList();for (int i = 0, len = array.size(); i < len; i++) {//获取知乎热搜信息JSONObject object = (JSONObject)array.get(i);//构建热搜信息榜SbmyHotSearchDO sbmyHotSearchDO = SbmyHotSearchDO.builder().hotSearchResource(SOUGOU.getCode()).build();//设置知乎三方IDsbmyHotSearchDO.setHotSearchId(object.getString("id"));//设置文章标题sbmyHotSearchDO.setHotSearchTitle(object.getJSONObject("attributes").getString("title"));//设置文章连接sbmyHotSearchDO.setHotSearchUrl("https://www.sogou.com/web?ie=utf8&query=" + sbmyHotSearchDO.getHotSearchTitle());//设置热搜热度sbmyHotSearchDO.setHotSearchHeat(object.getJSONObject("attributes").getString("num"));//按顺序排名sbmyHotSearchDO.setHotSearchOrder(i + 1);sbmyHotSearchDOList.add(sbmyHotSearchDO);}if (CollectionUtils.isEmpty(sbmyHotSearchDOList)) {return ReturnT.SUCCESS;}//数据加到缓存中CACHE_MAP.put(SOUGOU.getCode(), HotSearchDetailDTO.builder()//热搜数据.hotSearchDTOList(sbmyHotSearchDOList.stream().map(HotSearchConvert::toDTOWhenQuery).collect(Collectors.toList()))//更新时间.updateTime(Calendar.getInstance().getTime()).build());//数据持久化sbmyHotSearchService.saveCache2DB(sbmyHotSearchDOList);log.info("搜狗热搜爬虫任务结束");} catch (IOException e) {log.error("获取搜狗数据异常", e);}return ReturnT.SUCCESS;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1560292.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

GS-SLAM论文阅读笔记-CG-SLAM

前言 这是一篇不是最新的工作&#xff0c;我之前没有阅读&#xff0c;但是我前几天阅读GLC-SLAM的时候&#xff0c;发现它的一部分内容参考了CG-SLAM&#xff0c;并且CG-SLAM最近被ECCV2024接收&#xff0c;说明这是一片值得参考的好文章&#xff0c;接下来就阅读一下吧&#…

indeX ParaView插件

适用于 ParaView 的 NVIDIA IndeX 插件 文章目录 前言1. 以交互方式分析整个数据集。更快地取得见解。2. 特性和优势3. 结构化和非结构化立体数据的实时可视化4. 无缝的工作流程5. 快速分析大规模数据6. 开源插件前言 帮助更快获得科学发现的交互式立体可视化功能 1. 以交互方…

【完-网络安全】Shell与脚本

文章目录 1.CLI与GUI2.终端和Shell2.1 Shell 壳层2.2 终端2.3 终端和Shell区别3.标准流 4.PowerShell4.1 管理员与非管理员4.2 指令4.3 重定向4.4 管道 5.环境变量5.1 影响范围5.2环境变量的作用5.3 常见的环境变量 6.脚本 1.CLI与GUI CLI命令行界面(CLl,Command Line Interfa…

qt+opengl 实现纹理贴图,平移旋转,绘制三角形,方形

1 首先qt 已经封装了opengl&#xff0c;那么我们就可以直接用了&#xff0c;这里面有三个函数需要继承 virtual void initializeGL() override; virtual void resizeGL(int w,int h) override; virtual void paintGL() override; 这三个函数是实现opengl的重要函数。 2 我们…

粗糙表面仿真和处理软件

首款基于粗糙表面的仿真和处理软件&#xff0c;该软件具有三种方法&#xff0c;主要是二维数字滤波法&#xff0c;相位频谱法和共轭梯度法。可以分别仿真具有高斯和非高斯分布的粗糙表面&#xff0c;其中非高斯表面利用Johnson转换系统进行变换给定偏度和峰度。对生成的粗糙表面…

k8s网络通信

k8s通信整体架构 k8s通过CNI接口接入其他插件来实现网络通讯。目前比较流行的插件有flannel&#xff0c;calico等 CNI插件存放位置&#xff1a;# cat /etc/cni/net.d/10-flannel.conflist 插件使用的解决方案如下 虚拟网桥&#xff0c;虚拟网卡&#xff0c;多个容器共用一个虚…

YOLO11改进|注意力机制篇|引入局部注意力HaloAttention

目录 一、【HaloAttention】注意力机制1.1【HaloAttention】注意力介绍1.2【HaloAttention】核心代码 二、添加【HaloAttention】注意力机制2.1STEP12.2STEP22.3STEP32.4STEP4 三、yaml文件与运行3.1yaml文件3.2运行成功截图 一、【HaloAttention】注意力机制 1.1【HaloAttent…

同望OA tooneAssistantAttachement.jsp 任意文件读取漏洞复现

0x01 产品简介 同望OA,即同望科技打造的智企云协同管理系统,是一款高效的企业协同移动办公系统。秉承“互联网++企业管理”理念,定位于以移动互联办公为基础的企业协同管理软件平台。它旨在通过内置常用标准模块与专项管理模块应用,安全快速地打通管理与业务通道,实现管理…

科技控的双十一:精选五大热销数码产品,性价比爆表

随着每年一度的“双十一”购物狂欢节的临近&#xff0c;无数科技爱好者们已经开始摩拳擦掌&#xff0c;准备在这场年度大促中大展身手。对于热衷于追逐最新科技趋势的朋友们来说&#xff0c;“双十一”不仅仅是一场简单的购物活动&#xff0c;更是一个探索、发现并拥抱前沿科技…

私域电商新纪元:消费增值模式引领百万业绩飞跃

各位朋友&#xff0c;我是吴军&#xff0c;专注于带领大家深入探索私域电商领域的非凡魅力与潜在机会。 今天&#xff0c;我想与大家分享一个鼓舞人心的真实故事。在短短的一个月内&#xff0c;我们的合作伙伴实现了业绩的飞跃&#xff0c;突破百万大关&#xff0c;并且用户活跃…

大贤3D家谱-一键寻找家谱本源

点击“溯”&#xff0c;您可以追溯到当前节点的家谱本源。 这一功能将帮助您更深入地了解家族的历史和背景。 通过这一操作&#xff0c;系统会自动标注出与您当前节点相关的祖先信息&#xff0c;并以金色字体突出显示&#xff0c;便于您快速识别和查看。 演示如下&#xff1…

协变和逆变、事件、匿名函数

定义:协变(out)和逆变(in)是用于接口和委托中修饰泛型的,定义泛型类型的使用区域。 语法:<out T>那么T的数据类型只能用于返回值。<in T>那么T的数据类型只能用于参数列表。 //自定义委托 public delegate Result Fun<in T, in K, out Result>(…

Klick‘r3.0.4 |智能自动点击,高效省力

Klick’r 是一款专为 Android 设计的开源自动点击工具&#xff0c;能识别屏幕上的图像并进行相应操作。支持游戏中的自动点击、应用测试及日常任务自动化。 大小&#xff1a;27M 百度网盘&#xff1a;https://pan.baidu.com/s/1881Zfevph6_2Zhdc-H_R4A?pwdolxt 夸克网盘&…

shell 脚本批量更新本地git仓库

文章目录 一、问题概述二、解决方法三、运行效果1. windows2. centos 一、问题概述 你是否遇到这样的场景&#xff1a; 本地git仓库克隆了线上的多个项目&#xff0c;需要更新时&#xff0c;无法象svn一样&#xff0c;选中多个项目一起更新。 只能苦逼的一个个选中&#xff0c…

软考《信息系统运行管理员》- 4.3 信息系统软件运维的过程

4.3 信息系统软件运维的过程 文章目录 4.3 信息系统软件运维的过程日常运维日常运维的内容日常运行例行测试维护例行测试流程的关键点例行维护流程的关键点 定期测试维护 缺陷诊断与修复信息系统软件缺陷的概念信息系统软件缺陷的分类信息系统软件缺陷诊断与修复流程缺陷诊断与…

2024百度云智大会|百度大模型内容安全合规探索与实践

9月25日&#xff0c;2024百度云智大会在北京举办。会上&#xff0c;百度智能云分别针对算力、模型、AI 应用&#xff0c;全面升级百舸 AI 异构计算平台 4.0、千帆大模型平台 3.0 两大 AI 基础设施&#xff0c;并升级代码助手、智能客服、数字人三大 AI 原生应用产品。 在大模型…

App测试时常用的adb命令

adb 全称为 Android Debug Bridge&#xff08;Android 调试桥&#xff09;&#xff0c;是 Android SDK 中提供的用于管理 Android 模拟器或真机的工具。 adb 是一种功能强大的命令行工具&#xff0c;可让 PC 端与 Android 设备进行通信。adb 命令可执行各种设备操作&#xff0…

Biomamba求职| 国奖+4篇一作SCI

转眼间我也要参加秋招啦&#xff0c;认真的求职帖&#xff0c;各位老师/老板欢迎联系~其它需要求职的小伙伴也欢迎把简历发给我们&#xff0c;大家一起找工作。 一、基本信息 姓名&#xff1a;Biomamba 性别&#xff1a;男 出厂年份&#xff1a;1998 籍贯&#xff1a;浙江…

如何选择医疗器械管理系统?盘谷医疗符合最新版GSP要求

去年12月7日&#xff0c;新版《医疗器械经营质量管理规范》正式发布&#xff0c;并于今年7月1日正式实施。新版GSP第五十一条提出“经营第三类医疗器械的企业&#xff0c;应当具有符合医疗器械经营质量管理要求的计算机信息系统&#xff0c;保证经营的产品可追溯”&#xff0c;…

【笔记学习篇】一篇文章搞定Mybatis-快速回顾

概述 5.1.1 Mybatis简介 Mybatis是一款优秀的持久层框架&#xff0c;它以sql为中心&#xff0c;支持定制化sql、存储过程以及高级映射。 使用Mybatis框架&#xff0c;可以无需手动编写基础的JDBC代码、无需手动设置参数和转换结果集到对象。 Mybatis可以使用简单的xml或注解来…