JAVA后端生成图片滑块验证码 springboot+js完整案例

前言

现在大部分网部都是图片滑块验证码,这个得要与后端联动起来才是确保接口安全性
通过我们系统在发送手机短息时都会选进行滑块验证,但是我们要保证发送短息接口的全安,具体路思如下
在这里插入图片描述
那么这个滑块的必须是与后端交互才能保证安全性,而不是前端简单的交互。我们一起来学习一下这个案例怎么实吧
1、验证通过效果如图
在这里插入图片描述
2、验证失败效果如图
在这里插入图片描述

案例开始

1、我们使用java新建一个springboot工程,并准备几张图片,尺寸是390*180,如下图
添加依赖

<dependency><groupId>net.coobird</groupId><artifactId>thumbnailator</artifactId><version>0.4.11</version>
</dependency>

在这里插入图片描述
2、新建三个响应的类
2.1 WebReturn类如下

@Data
public class WebReturn {RetCode code;Object data;public WebReturn(RetCode code, Object data) {this.code = code;this.data = data;}
}

2.2 RetCode类如下


public enum  RetCode {IMAGE_REQ_SUCCESS(1,"图片请求成功"),IMAGE_REQ_FAIL(2,"图片请求失败"),VERIFI_REQ_SUCCESS(3,"图片验证成功"),VERIFI_REQ_FAIL(4,"图片验证失败");int code;String message;RetCode(int code, String message) {this.code = code;this.message = message;}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}

2.3 ImageResult类如下

@Data
public class ImageResult {int xpos;//滑块的坐标x轴int ypos;//滑块的坐标y轴int cutImageWidth;//滑块的宽int cutImageHeight;//滑块的高String  cutImage;//滑块图片String  oriImage;//背景图(初扣掉滑块的图)}

3、新建一个图片滑块生成的工具类

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
@Slf4j
public class ImgUtil {//图片的路径private  String classpath = "classpath*:img/slider/*.*";//图片的最大大小  (可以根据实际需要进行高调整,对应的图片尺寸也得是一致)private  static int IMAGE_MAX_WIDTH = 380;private  static int IMAGE_MAX_HEIGHT = 190;//抠图上面的半径private   static int RADIUS = IMAGE_MAX_WIDTH/38;//抠图区域的高度private   static int CUT_HEIGHT = IMAGE_MAX_WIDTH/7;//抠图区域的宽度private   static int CUT_WIDTH = IMAGE_MAX_WIDTH/7;//被扣地方填充的颜色private   static int FLAG = 0xffffff;//抠图部分凸起的方向private  Location location;ImageResult imageResult = new ImageResult();private  String ORI_IMAGE_KEY = "ORI_IMAGE_KEY";private  String CUT_IMAGE_KEY = "CUT_IMAGE_KEY";private  int XPOS;private  int YPOS;@Dataprivate  class ImageMessage{private int xpos;private int ypos;private int cutImageWidth;private int cutImageHeight;}ImageMessage imageMessage = new ImageMessage();/***功能描述 获取抠图区的坐标原点*/public  void createXYPos(BufferedImage oriImage){int height = oriImage.getHeight();int width = oriImage.getWidth();XPOS = new Random().nextInt(width-CUT_WIDTH-RADIUS);YPOS = new Random().nextInt(height-CUT_HEIGHT-RADIUS-RADIUS)+RADIUS;//确保横坐标位于2/4--3/4int div = (IMAGE_MAX_WIDTH/4);if(XPOS/div ==  0 ){XPOS = XPOS + div*2;}else if(XPOS/div ==  1 ){XPOS = XPOS + div;}else if(XPOS/div ==  3 ){XPOS = XPOS - div;}}/***功能描述 对外提供的接口*/public  ImageResult imageResult() throws IOException{return imageResult(getRandomImage());}public  ImageResult imageResult(BufferedImage oriBufferedImage) throws IOException {//检测图片大小oriBufferedImage = checkImage(oriBufferedImage);//初始化原点坐标createXYPos(oriBufferedImage);//获取被扣图像的标志图int[][] blockData = getBlockData(oriBufferedImage);//printBlockData(blockData);//计算抠图区域的信息createImageMessage();//获取扣了图的原图和被扣部分的图Map<String,BufferedImage> imageMap =  cutByTemplate(oriBufferedImage,blockData);imageResult.setOriImage(ImageBase64(imageMap.get(ORI_IMAGE_KEY)));imageResult.setCutImage(ImageBase64(imageMap.get(CUT_IMAGE_KEY)));imageResult.setXpos(imageMessage.getXpos());imageResult.setYpos(imageMessage.getYpos());imageResult.setCutImageWidth(imageMessage.getCutImageWidth());imageResult.setCutImageHeight(imageMessage.getCutImageHeight());return imageResult;}/***功能描述* @Description 计算抠图的相关参数*/private  void createImageMessage(){int x = 0,y = 0;int w = 0, h = 0;if(location == Location.UP){x = XPOS;y = YPOS - RADIUS;w = CUT_WIDTH;h = CUT_HEIGHT + RADIUS;}else if(location == Location.LEFT){x = XPOS-RADIUS;y = YPOS;w = CUT_WIDTH + RADIUS;h = CUT_HEIGHT;}else if(location == Location.DOWN){x = XPOS;y = YPOS;w = CUT_WIDTH;h = CUT_HEIGHT + RADIUS;}else if(location == Location.RIGHT){x = XPOS;y = YPOS;w = CUT_WIDTH + RADIUS;h = CUT_HEIGHT;}imageMessage.setXpos(x);imageMessage.setYpos(y);imageMessage.setCutImageHeight(h);imageMessage.setCutImageWidth(w);}/***功能描述* @Description  检测图片大小是否符合要求*/private  BufferedImage checkImage(BufferedImage image) throws IOException {if((image.getWidth()  == IMAGE_MAX_WIDTH) || (image.getHeight()  == IMAGE_MAX_HEIGHT)){return image;}else if((image.getWidth()  < IMAGE_MAX_WIDTH) || (image.getHeight()  < IMAGE_MAX_HEIGHT)){log.info("图片太小.不符合要求w*h[380*190]");throw  new IllegalArgumentException("图片太小.不符合要求w*h[380*190]");} else {log.info("压缩图片");return compressImage(image,IMAGE_MAX_WIDTH,IMAGE_MAX_HEIGHT);}}private Color color(int rgb){int b = (0xff & rgb);int g = (0xff & (rgb >> 8));int r = (0xff & (rgb >> 16));return new Color(r, g, b);}/***功能描述 获取抠完图的原图和被扣出来的图*/public  Map<String,BufferedImage> cutByTemplate(BufferedImage oriImage,  int[][] blockData){Map<String,BufferedImage> imgMap = new HashMap<>();BufferedImage cutImage = new BufferedImage(imageMessage.cutImageWidth,imageMessage.cutImageHeight,oriImage.getType());// 获取Graphics2DGraphics2D g2d = cutImage.createGraphics();//透明化整张图cutImage = g2d.getDeviceConfiguration().createCompatibleImage(imageMessage.cutImageWidth,imageMessage.cutImageHeight, Transparency.BITMASK);g2d.dispose();g2d = cutImage.createGraphics();// 背景透明代码结束int xmax = imageMessage.xpos + imageMessage.cutImageWidth;int ymax = imageMessage.ypos + imageMessage.cutImageHeight;for(int x = imageMessage.xpos; x< xmax && x>=0; x++){for(int y = imageMessage.ypos; y < ymax && y>=0; y++){int oriRgb = oriImage.getRGB(x,y);if(blockData[x][y] == FLAG){oriImage.setRGB(x,y,FLAG);//描边   判断是否为边界,如果是边界则填充为白色if(blockData[x-1][y] != FLAG || blockData[x+1][y] != FLAG || blockData[x][y+1] != FLAG || blockData[x][y-1] != FLAG){g2d.setColor(color(0xffffff));}else{g2d.setColor(color(oriRgb));}g2d.setStroke(new BasicStroke(1f));g2d.fillRect(x-imageMessage.xpos, y-imageMessage.ypos, 1, 1);}}}// 释放对象g2d.dispose();imgMap.put(ORI_IMAGE_KEY,oriImage);imgMap.put(CUT_IMAGE_KEY,cutImage);return imgMap;}/***功能描述* @Description 获取抠图数据,被扣的像素点将使用FLAG进行标记* @return:  int[][]*/public  int[][] getBlockData(BufferedImage oriImage){int height = oriImage.getHeight();int width = oriImage.getWidth();int[][] blockData =new int[width][height];Location locations[] = {Location.UP,Location.LEFT,Location.DOWN,Location.RIGHT};//矩形//此处还可以优化,进行区域扫描for(int x = 0; x< width && x>=0; x++){for(int y = 0; y < height && y>=0; y++){blockData[x][y] = 0;if ( (x > XPOS) && (x < (XPOS+CUT_WIDTH))&& (y > YPOS) && (y < (YPOS+CUT_HEIGHT))){blockData[x][y] = FLAG;}}}//圆形突出区域//突出圆形的原点坐标(x,y)int xBulgeCenter=0,yBulgeCenter=0;int xConcaveCenter=0,yConcaveCenter=0;//位于矩形的哪一边,0123--上下左右location = locations[new Random().nextInt(4)];if(location == Location.UP){//上 凸起xBulgeCenter = XPOS +  CUT_WIDTH/2;yBulgeCenter = YPOS;//左 凹陷xConcaveCenter = XPOS ;yConcaveCenter = YPOS + CUT_HEIGHT/2;}else if(location == Location.DOWN){//下 凸起xBulgeCenter = XPOS +  CUT_WIDTH/2;yBulgeCenter = YPOS + CUT_HEIGHT;//右 凹陷xConcaveCenter = XPOS +  CUT_WIDTH;yConcaveCenter = YPOS + CUT_HEIGHT/2;}else if(location == Location.LEFT){//左 凸起xBulgeCenter = XPOS ;yBulgeCenter = YPOS + CUT_HEIGHT/2;//下 凹陷xConcaveCenter = XPOS +  CUT_WIDTH/2;yConcaveCenter = YPOS + CUT_HEIGHT;}else {//Location.RIGHT//右 凸起xBulgeCenter = XPOS +  CUT_WIDTH;yBulgeCenter = YPOS + CUT_HEIGHT/2;//上 凹陷xConcaveCenter = XPOS +  CUT_WIDTH/2;yConcaveCenter = YPOS;}//半径的平方int RADIUS_POW2 = RADIUS * RADIUS;//凸起部分for(int x = xBulgeCenter-RADIUS; x< xBulgeCenter+RADIUS && x>=0; x++){for(int y = yBulgeCenter-RADIUS; y < yBulgeCenter+RADIUS && y>=0; y++){if(Math.pow((x-xBulgeCenter),2) + Math.pow((y-yBulgeCenter),2) < RADIUS_POW2){blockData[x][y] = FLAG;}}}//凹陷部分for(int x = xConcaveCenter-RADIUS; x< xConcaveCenter+RADIUS && x>=0; x++){for(int y = yConcaveCenter-RADIUS; y < yConcaveCenter+RADIUS && y>=0; y++){if(Math.pow((x-xConcaveCenter),2) + Math.pow((y-yConcaveCenter),2) <= RADIUS_POW2){blockData[x][y] = 0;}}}return blockData;}/***功能描述 将图片转为base64存储*/private  String ImageBase64(BufferedImage bufferedImage) throws IOException {ByteArrayOutputStream out = new ByteArrayOutputStream();ImageIO.write(bufferedImage, "png", out);//转成byte数组byte[] bytes = out.toByteArray();Base64.Encoder encoder = Base64.getEncoder();//生成BASE64编码return encoder.encodeToString(bytes);}/*** 随机获取一个图片文件* @return* @throws Exception*/private  BufferedImage getRandomImage() throws IOException {try {//使用resource获取resource文件【注意:即使打成jar包也有效】ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();Resource[] resources = resourcePatternResolver.getResources(classpath);if (resources.length <= 0) {throw new IOException("该文件夹内没有文件!");} else {int index = new Random().nextInt(resources.length);InputStream inputStream = resources[index].getInputStream();BufferedImage marioBufferedImage = ImageIO.read(inputStream);return marioBufferedImage;}} catch (IOException e) {log.info("读取文件失败:{}", e);throw new IOException("读取文件失败!");}}/***功能描述  压缩图片* @author lgj* @Description* @date 3/30/20* @param:* @return:  java.awt.image.BufferedImage**/private  BufferedImage compressImage(BufferedImage image,int width,int height) throws IOException{return  Thumbnails.of(image).forceSize(width,height)//.width(width).height(height).asBufferedImage();}/***功能描述* @Description  抠图部分凸起的区域*/private enum Location {UP,LEFT,DOWN,RIGHT;}
}

4、新建一个controller


@Slf4j
@RestController
@RequestMapping("/slider")
public class SliderController {private  int xPosCache = 0;//生产环境请把这个值存入redis中@RequestMapping("/image")public WebReturn image(){ImageResult imageResult = null;try{imageResult = new ImgUtil().imageResult();//生成图片xPosCache = imageResult.getXpos();//生产环境请把这个值存入redis中imageResult.setXpos(0);//清空x值return new WebReturn(RetCode.IMAGE_REQ_SUCCESS,imageResult);}catch(Exception ex){log.error(ex.getMessage());ex.printStackTrace();return new WebReturn(RetCode.IMAGE_REQ_FAIL,null);}}@RequestMapping("/verification")public WebReturn verification(@RequestParam("moveX") int moveX){log.info("/slider/verification/{}",moveX);int MOVE_CHECK_ERROR = 2;//允许的误差范围,这里设置为2个像素//xPosCache   生产请从redis中读取,使用完并立即请除if(( moveX < ( xPosCache + MOVE_CHECK_ERROR)) && ( moveX >  (xPosCache - MOVE_CHECK_ERROR))){log.info("验证正确");//生产这个可以返回临时授权码return new WebReturn(RetCode.VERIFI_REQ_SUCCESS,true);}return new WebReturn(RetCode.VERIFI_REQ_FAIL,false);}
}

5、最后新建一个页面

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>首页</title><script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script><style >html body {height: 100%;width: 100%;}#captchaContainer{position: absolute;top: 50px;left: 40%;/*  background-color: #f57a7a;*/height: 275px;width: 260px;}.header{position: absolute;top: 0px;left: 0px;background-color: rgb(245, 236, 236);height: 40px;width: 380px;}.headerText{position: absolute;top: 13px;left: 140px;height: 40px;color:#66c523;font:18px/14px Georgia, "Times New Roman", Times, serif;}#captchaImg{position: absolute;left: 0;top: 40px;height: 190px;width: 380px;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;border: none}#oriImg{position: absolute;left: 0px;top: 0px;width: 380px;height: 190px;-webkit-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;border: none}#cutImg{position: absolute;border: none;left: 0px;}.sliderContainer {position: absolute;bottom: 0;left: 0px;text-align: center;width: 380px;height: 40px;line-height: 40px;background: #f7f9fa;color: #45494c;border: 1px solid #e4e7eb;}.sliderContainer_success{border: 1px solid hsl(125, 93%, 44%);}.sliderContainer_fail{border: 1px solid #ec3655;}.slider {position: absolute;top: 0;left: 0px;width: 40px;height: 40px;background: #fff;box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);transition: background .2s linear;cursor: pointer;cursor: grab;}.slider_success{border: 1px solid hsl(125, 93%, 44%);}.slider_fail{border: 1px solid #ec3655;}.sliderContainer_active .slider {height: 38px;top: -1px;border: 1px solid #1991FA;}.sliderContainer_active .sliderMask {height: 38px;border-width: 1px;}.sliderContainer_success .slider {height: 38px;top: -1px;margin-left: -1px;border: 1px solid #52CCBA;background-color: #52CCBA !important;}.sliderContainer_success .sliderMask {height: 38px;border: 1px solid #52CCBA;background-color: #D2F4EF;}.sliderContainer_success .sliderIcon {background-position: 0 0 !important;}.sliderContainer_fail .slider {height: 38px;top: -1px;border: 1px solid #f57a7a;background-color: #f57a7a !important;}.sliderContainer_fail .sliderMask {height: 38px;border: 1px solid #f57a7a;background-color: #fce1e1;}.sliderContainer_fail .sliderIcon {top: 14px;background-position: 0 -82px !important;}.sliderContainer_active .sliderText, .sliderContainer_success .sliderText, .sliderContainer_fail .sliderText {display: none;}.sliderMask {position: absolute;left: 0;top: 0;height: 40px;border: 0 solid #1991FA;background: #D1E9FE;}.slider:active {cursor: grabbing;}.slider:hover {background: #1991FA;}.slider:hover .sliderIcon {background-position: 0 -13px;}.sliderIcon {position: absolute;top: 15px;left: 13px;width: 14px;height: 12px;background: url(http://cstaticdun.126.net//2.6.3/images/icon_light.f13cff3.png) 0 -26px;background-size: 34px 471px;}.refreshIcon {position: absolute;right: 0;top: 0;width: 34px;height: 34px;cursor: pointer;background: url(http://cstaticdun.126.net//2.6.3/images/icon_light.f13cff3.png) 0 -437px;background-size: 34px 471px;}</style></head>
<body><div id="captchaContainer"><!-- 标题栏 --><div class="header"><span class="headerText">图片滑动验证</span><span class="refreshIcon"/></div> <!-- 图片显示区域 --><div id="captchaImg"><img id="oriImg" src="dd" alt="原图"/><img id="cutImg" src="sa" alt="抠图"/></div><!--滑块显示区域--><div class="sliderContainer"><div class="sliderMask"><div class="slider"><span class="sliderIcon"></span></div></div><span class="sliderText">向右滑动填充拼图</span></div> </div></body><script>//图片显示使用base64时的前缀,src=base64PrefixPath + imgBase64Valuevar base64PrefixPath="data:image/png;base64,";var IMAGE_WIDTH = 380;//初始化//滑块初始偏移量var sliderInitOffset = 0;//滑块移动的最值var MIN_MOVE = 0;var MAX_MOVE = 0;//鼠标按下标志var mousedownFlag=false;//滑块移动的距离var moveX;//滑块位置检测允许的误差,正负2var MOVE_CHECK_ERROR = 2;//滑块滑动使能var moveEnable = true;var ImageMsg = {//抠图的坐标xpos: 0,ypos: 0,//抠图的大小cutImageWidth: 0,cutImageHeight: 0,//原图的base64oriImageSrc: 0,//抠图的base64cutImageSrc: 0,}//加载页面时进行初始化function init(){console.log("init")moveEnable = true;mousedownFlag=false;$(".slider").css("left",0+"px");initClass();MAX_MOVE = IMAGE_WIDTH - ImageMsg.cutImageWidth;console.log("ImageMsg = " + ImageMsg)$("#cutImg").css("left",0+"px");$("#oriImg").attr("src",ImageMsg.oriImageSrc)$("#cutImg").attr("src",ImageMsg.cutImageSrc)$("#cutImg").css("width",ImageMsg.cutImageWidth)$("#cutImg").css("height",ImageMsg.cutImageHeight)$("#cutImg").css("top",ImageMsg.ypos)}//加载页面时$(function(){httpRequest.requestImage.request();})var httpRequest={//请求获取图片requestImage:{path: "slider/image",request:function(){$.get(httpRequest.requestImage.path,function(data,status){console.log(data)console.log(data.message);if(data.data != null){ImageMsg.oriImageSrc = base64PrefixPath + data.data.oriImage;ImageMsg.cutImageSrc = base64PrefixPath + data.data.cutImage;ImageMsg.xpos = data.data.xpos;ImageMsg.ypos = data.data.ypos;ImageMsg.cutImageWidth = data.data.cutImageWidth;ImageMsg.cutImageHeight = data.data.cutImageHeight;init();}});},},//请求验证requestVerification:{path: "slider/verification",request:function(){$.get(httpRequest.requestVerification.path,{moveX:(moveX)},function(data,status){console.log(data)console.log(data.code);console.log(data.message);if(data.data == true){checkSuccessHandle();}else{checkFailHandle();}});},},}//刷新图片操作$(".refreshIcon").on("click",function(){httpRequest.requestImage.request();})//滑块鼠标按下$(".slider").mousedown(function(event){console.log("鼠标按下mousedown:"+event.clientX + " " + event.clientY);sliderInitOffset = event.clientX;  mousedownFlag = true;//滑块绑定鼠标滑动事件$(".slider").on("mousemove",function(event){if(mousedownFlag  == false){return;}if(moveEnable == false){return}moveX = event.clientX - sliderInitOffset;moveX<MIN_MOVE?moveX=MIN_MOVE:moveX=moveX;moveX>MAX_MOVE?moveX=MAX_MOVE:moveX=moveX;$(this).css("left",moveX+"px");$("#cutImg").css("left",moveX+"px");})})//滑块鼠标弹起操作$(".slider").mouseup(function(event){console.log("mouseup:"+event.clientX + " " + event.clientY);sliderInitOffset = 0;$(this).off("mousemove");mousedownFlag=false;console.log("moveX = " + moveX)checkLocation();})//检测滑块 位置是否正确function checkLocation(){moveEnable = false;//后端请求检测滑块位置httpRequest.requestVerification.request();}function checkSuccessHandle(){$(".sliderContainer").addClass("sliderContainer_success");$(".slider").addClass("slider_success");}function checkFailHandle(){$(".sliderContainer").addClass("sliderContainer_fail");$(".slider").addClass("slider_success");}function initClass(){$(".sliderContainer").removeClass("sliderContainer_success");$(".slider").removeClass("slider_success");$(".sliderContainer").removeClass("sliderContainer_fail");$(".slider").removeClass("slider_fail");}</script></html>

最后

到这里我们的案例代码已经写好了,运程工程访问就可以了。
http://localhost:9005/home.html
在这里插入图片描述
本文章提供大家学习,欢迎你大家留言提供您的保贵意见
=如果本文对您有帮助,麻烦您给博主点个赞吧!=

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

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

相关文章

机器学习—高级优化方法

梯度下降是机器学习中广泛应用的优化算法&#xff0c;像线性回归和逻辑回归以及神经网络的早期实现&#xff0c;现在有一些其他的优化算法&#xff0c;为了最小化成本函数&#xff0c;甚至比梯度下降的效果更好&#xff0c;这种算法可以用来帮助训练神经网络&#xff0c;比梯度…

【Vue3】知识汇总,附详细定义和源码详解,后续出微信小程序项目(3)

快速跳转&#xff1a; 我的个人博客主页&#x1f449;&#xff1a;Reuuse博客 新开专栏&#x1f449;&#xff1a;Vue3专栏 参考文献&#x1f449;&#xff1a;uniapp官网 免费图标&#x1f449;&#xff1a;阿里巴巴矢量图标库 ❀ 感谢支持&#xff01;☀ 前情提要 &#x…

模型减肥秘籍:模型压缩技术 CNN基础

这里是Datawhale的组队学习活动&#xff0c;主要介绍的是模型压缩技术。后续将以CNN网络为基础点&#xff0c;带领大家领略模型压缩的魅力。首先是回顾一下一些关于CNN的基础知识。 参考链接&#xff1a; 模型减肥秘籍&#xff1a;模型压缩技术-课程详情 | Datawhale datawh…

Ollama的安装以及大模型下载教程

简介 Ollama是一个开源的大型语言模型服务工具&#xff0c;它帮助用户快速在本地运行大模型。通过简单的安装指令&#xff0c;用户可以执行一条命令就在本地运行开源大型语言模型&#xff0c; Ollama极大地简化了在Docker容器内部署和管理LLM的过程&#xff0c;使得用户能够快…

Mysql前言

文章目录 Mysql 数据库简介SQL 基础语法什么是 SQL语句SQL 的作用SQL 语句的分类SQL 通用语法查询状态 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Mysql专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年11月12日18点20分 SQL是数据库…

Spring Boot编程训练系统:设计与实现要点

5系统详细实现 5.1 管理员模块的实现 5.1.1 用户信息管理 管理员对用户信息修改删除以及查询操作。具体界面的展示如图5.1所示。 图5.1 用户信息管理界面 5.1.2 题库资源管理 系统管理员可以对题库资源信息进行添加&#xff0c;修改&#xff0c;删除以及查询操作。具体界面如…

Xcode 16 使用 pod 命令报错解决方案

原文请点击这个跳转 一、问题现象&#xff1a; 有人会遇到 Xcode 升级到 16 后&#xff0c;新建应用然后使用 pod init 命令会报错如下&#xff1a; Stack Ruby : ruby 3.3.5 (2024-09-03 revision ef084cc8f4) [x86_64-darwin23]RubyGems : 3.5.22Host : macOS 15.0 (24A335…

hive中windows子句的使用

概述 1&#xff0c;windows子句是对窗口的结果做更细粒度的划分 2、windows子句中有两种方式 rows &#xff1a;按照相邻的几行进行开窗 range&#xff1a;按照某个值的范围进行开窗 使用方式 (rows | range) between (UNBOUNDED | [num]) PRECEDING AND ([num] PRECEDING…

Unet++改进24:添加DualConv||轻量级深度神经网络的双卷积核

本文内容:添加DualConv 目录 论文简介 1.步骤一 2.步骤二 3.步骤三 4.步骤四 论文简介 卷积神经网络(CNN)架构通常对内存和计算要求很高,这使得它们在硬件资源有限的嵌入式系统中不可行。 我们提出了双卷积核(DualConv)来构建轻量级深度神经网络。DualConv结合3 3和1…

【Vue3】知识汇总,附详细定义和源码详解,后续出微信小程序项目(4)

快速跳转&#xff1a; 我的个人博客主页&#x1f449;&#xff1a;Reuuse博客 新开专栏&#x1f449;&#xff1a;Vue3专栏 参考文献&#x1f449;&#xff1a;uniapp官网 免费图标&#x1f449;&#xff1a;阿里巴巴矢量图标库 ❀ 感谢支持&#xff01;☀ 前情提要 &#x…

微信小程序_小程序视图与逻辑_day3

一、目标 A. 能够知道如何实现页面之间的导航跳转 B. 能够知道如何实现下拉刷新效果 C. 能够知道如何实现上拉加载更多效果 D. 能够知道小程序中常用的生命周期 二、目录 A. 页面导航 B. 页面事件 C. 生命周期 D. WXS脚本 E. 案例-本地生活&#xff08;列表页面&#xff09;…

springboot社团服务系统的设计与实现,计算机毕业设计项目源码316,计算机毕设程序(LW+开题报告、中期报告、任务书等全套方案)

摘 要 社会发展日新月异&#xff0c;用计算机应用实现数据管理功能已经算是很完善的了&#xff0c;但是随着移动互联网的到来&#xff0c;处理信息不再受制于地理位置的限制&#xff0c;处理信息及时高效&#xff0c;备受人们的喜爱。本次开发一套社团服务系统有管理员&#x…

Linux服务管理-kerberos

Kerberos 官网文档‘&#xff1a;Kerberos&#xff1a;网络身份验证协议 (mit.edu) 基本概念&#xff1a;Kerberos基本概念及原理汇总-腾讯云开发者社区-腾讯云 (tencent.com) kerberos概述 Kerberos是一种计算机网络认证协议&#xff0c;由麻省理工学院&#xff08;MIT&#x…

区块链技术在游戏行业的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 区块链技术在游戏行业的应用 区块链技术在游戏行业的应用 区块链技术在游戏行业的应用 引言 区块链技术概述 定义与原理 发展历程…

MooseFS (MFS) 分布式对象存储

一、MFS 优越特性 Free (GPL): 通用文件系统&#xff0c;开源免费。在线扩容: 体系架构具有极强的可伸缩性&#xff0c;支持在线扩容。部署简单。高可用性: 支持设置任意文件冗余(数据分区)程度&#xff0c;提供比RAID10更高的冗余级别&#xff0c;同时不会影响读写性能&#…

【常见问题解答】远程桌面无法复制粘贴的解决方法

提示:文中提出了“远程桌面无法复制粘贴文件到本地”问题的三种解决方法,其中“方法 3:重启 RDP 剪贴板监视程序”亲测有效。 目录 一、问题描述二、解决方法1.方法1:设置远程桌面连接(1)打开远程桌面连接,点击【显示选项】(2)勾选“剪贴板”,并点击【详细信息】(3)…

探索光耦:达林顿光耦的特点与应用

在现代电子设备中&#xff0c;光耦作为信号隔离和传输的核心元件之一&#xff0c;扮演着至关重要的角色。达林顿光耦凭借其独特的电流放大能力和可靠性&#xff0c;在众多应用中脱颖而出。本文将探讨达林顿光耦的特点及其广泛的应用。 达林顿光耦的主要特点 高电流放大倍数&a…

河南省的一级科技查新机构有哪些?

科技查新&#xff0c;简称查新&#xff0c;是指权威机构对查新项目的新颖性作出文献评价的情报咨询服务。这一服务在科研立项、成果鉴定、项目申报等方面发挥着至关重要的作用。河南省作为中国的重要科技和教育基地&#xff0c;拥有多个一级科技查新机构&#xff0c;为本省及全…

数据结构 ——— 层序遍历链式二叉树

目录 链式二叉树示意图​编辑 何为层序遍历 手搓一个链式二叉树 实现层序遍历链式二叉树 链式二叉树示意图 何为层序遍历 和前中后序遍历不同&#xff0c;前中后序遍历链式二叉树需要利用递归才能遍历 而层序遍历是非递归的形式&#xff0c;如上图&#xff1a;层序遍历的…

【故障解决】麒麟系统右下角网络图标取消显示叹号

原文链接&#xff1a;【故障解决】麒麟系统右下角网络图标取消显示叹号 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于如何在麒麟系统中解决网络图标出现感叹号问题的文章。在日常使用麒麟系统的过程中&#xff0c;我们在内网或公网环境下&#xff0c;有时会遇…