当前位置: 首页 > news >正文

登录功能login.html

文章目录

  • 前言
  • 一、login.html
  • 二、getVerify()
  • controller
  • login() 登录功能
  • encodePwd(pwd,key)
  • login.do
  • 验证是否异地登录
  • 找回账号
  • verifySubmit()


前言

登录login.html,验证码获取verifycode,登陆函数login()


一、login.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body ><div aglin="center"><h1>NJUPT登录系统</h1><div>用户名:<input type="text" id="sno"/><br>密 码:   <input type="password" id="pwd"/><br>  验证 码:<input type="text" id="code"/><label id="verifycode"></label><button onclick="getVerify()">获取验证码</button><br>  <button onclick="login()">登录</button></div></div>
</body>
</html>

打开浏览器,可以得到如下页面
在这里插入图片描述
由于我们还没写getVerify()和login(),点击这两个button无反应,验证码的位置也没有显示VerifyCode此id对应的验证码。

二、getVerify()

首先复制这段代码

function getVerify(){if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safarixmlhttp=new XMLHttpRequest(); } else {// code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } }

创建一个用于进行异步 HTTP 请求的对象,也就是常说的 XMLHttpRequest 对象,根据不同的浏览器创建不同的对象,现代版本浏览器一般都是if分支。

xmlhttp.open("get","getcode.do",false);

用这个请求的对象的open,第一个参数请求方法 " get " 或者 " post ";第二个参数URL,对应controller中相同@RequestMapping注释的方法。最后一个参数是否异步请求,这里选择false。

	xmlhttp.onreadystatechange=function () { if (xmlhttp.readyState==4 && xmlhttp.status==200) { key=xmlhttp.responseTextconsole.log(key);document.getElementById("verifycode").innerHTML=key} else {console.error(xmlhttp.status);}} 

onreadystatechange 是 XMLHttpRequest 对象的一个事件处理属性,当 XMLHttpRequest 对象的状态发生变化时,会触发这个事件处理函数。

readyState:值为4表示已完成,响应数据已经完全接收。
xmlhttp.status:表示 HTTP 响应的状态码,200 表示请求成功。

然后编写对于响应消息的操作,比如这里我们需要相应的到一个验证码,responseText肯定返回一个Integer,用key去接收,javascript会自动解析key是怎样的类型,就算是数组也可以解析。

然后在控制台显示key,并且将key填入id为" verifycode"的html元素,也就是获取验证码按钮之前的< label id=“verifycode”>

响应失败就在控制台显示xmlhttp.status状态码。

xmlhttp.send(); 

其主要作用是向服务器发送 HTTP 请求,请求类型和请求URL根据open里面的参数决定。也就是说,执行到send()才把请求发送到服务器。open () 只是起一个连接作用。send发送请求成功之后,才会执行function。这里的function没有名字


controller

getcode.do这条URL对应的方法在哪里呢?我们在src新建一个com.njupt.controller包->StudentController.java类。

@RestController
public class StudentController {@RequestMapping(value="getcode.do",method=RequestMethod.GET)public Integer getCode() {Integer code=(int)(Math.random()*10000);if (code<1000) code+=1000;return code;}}

使用 Spring Boot 框架创建了一个 RESTful 风格的控制器类 StudentController,其主要功能是处理客户端发起的特定 GET 请求,并返回一个 4 位随机整数。

@RestController 注解的类会被Spring识别为Controller控制器,并且类中所有处理请求的方法返回值会直接作为 HTTP 响应体,无需额外的视图解析。

@RequestMapping:用于将 HTTP 请求映射到控制器的处理方法。

生成一个0-9999的随机数,如果小于1000,就加1000,保证验证码是四位,返回code。
在这里插入图片描述
key就会接收code,再填入id为verifycode的元素。

验证 码:<input type="text" id="code"/><label id="verifycode"></label><button onclick="getVerify()">获取验证码</button><br>  

点击获取验证码按钮,就会获得验证码。
在这里插入图片描述
以firefox浏览器为例,点击右上角三条横线,点击更多工具。
在这里插入图片描述
选择开发者工具,打开控制台
在这里插入图片描述
就能看到console.log(key)显示的验证码,这里我点了很多下 “获取验证码”,最下面的1499是最近一次获取的。
在这里插入图片描述
如果我们希望每次进入login.html页面会自动生成验证码,无需手动点击,可以在< body >里面添加 load = getVerify() 每次进入login.html页面首先执行getVerify(),就会有验证码显示,同样的,点击获取验证码,可以获取新的验证码。

login() 登录功能

function login(){if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safarixmlhttp=new XMLHttpRequest(); } else {// code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.open();xmlhttp.onreadystatechange=function () { if (xmlhttp.readyState==4 && xmlhttp.status==200) { } else {console.error(xmlhttp.status);}} xmlhttp.send(); 
}

先写出每个javascript function里面一样的结构,如上。

xmlhttp.open()
open()里面的参数如何确定,我们肯定要把sno学号和pwd密码传过去和数据库里面的数据进行比对,如果一致,则登陆成功。要传参数肯定是post请求,这里用异步。
xmlhttp.open(“post”,“login.do”,true);建立连接之后,把sno和pwd存入变量stuID,pwd。然后设置请求头,密码传输肯定不能明文传输,我们要进行加密。再把stuID和pwd通过post传过去。

stuID=document.getElementById("sno").value;
pwd=document.getElementById("pwd").value;
pwd=encodePwd(pwd,key);alert(pwd)
xmlhttp.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");xmlhttp.send("stuID="+stuID+"&pwd="+pwd);

设置请求头代码每次复制即可。
encodePwd加密函数我们通过key验证码对pwd加密,于是在登录界面就不显示验证码,我们把输入验证码注释掉。
在这里插入图片描述
因为要用到getVerify()里面的key,所以key要设置为全局变量。
在这里插入图片描述

encodePwd(pwd,key)

加密函数,类似于C语言小练习专栏里面的加密逻辑,通过key加密,再通过-key解密。
在这里插入图片描述

我们可以在WebContent里新建文件夹js,js里面创建my.js文件。里面存放需要的js函数。再把my.js导入login.html。

<head>
<meta charset="UTF-8">
<title>login</title>
<script src="js/my.js"></script>
<script type="text/javascript">
function encodePwd(str,key)
{result="";for( i=0;i<str.length;i++){if(str[i]>='A'&&str[i]<='Z'){key1=key%26;index=(str.charCodeAt(i)-65+26+key1)%26;result=result+String.fromCharCode(index+65)}else if(str[i]>='a'&&str[i]<='z'){key1=key%26;index=(str.charCodeAt(i)-97+26+key1)%26;result=result+String.fromCharCode(index+97)}else if(str[i]>='0'&&str[i]<='9'){key1=key%10;index=(str.charCodeAt(i)-48+10+key1)%10;result=result+String.fromCharCode(index+48)}else result=result+str[i]}return result  
}

加密过程不多赘述。
比如输入密码123,通过随机key加密得到901
在这里插入图片描述

login.do

在StudentController里面写一个login.do对应的方法。返回一个什么类型给响应呢。不妨返回一个VO类:
VO类主要用来显示信息,像从前端向后端传递用户输入数据,或后端向前端返回处理结果等。它聚焦于数据本身,不包含业务逻辑。

比如我们创建一个LoginVo类
在src/com/njupt.voPackage包里创建LoginVo类

public class LoginVo {private Integer code;private String message;public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}
}

code用来表示登录情况的种类,比如登录成功,学号密码错误,有人在异地登录等等。
message用来展示给客户。

我们需要code来对pwd进行解密,可以选择增加参数code传过来,也可以选择在getcode.do里面把code设置在HttpSession session里面。

@RequestMapping(value="getcode.do",method=RequestMethod.GET)
public Integer getCode(HttpSession session) {Integer code=(int)(Math.random()*10000);if (code<1000) code+=1000;session.setAttribute("code", code);return code;
}

将生成的验证码存储到HttpSession中,键为"code",后续在同一个会话内的其他方法可以通过这个键获取到验证码。

然后在login.do就可以把code调出来。

@RequestMapping(value="login.do",method=RequestMethod.POST)
public LoginVo login(@RequestParam("stuID")String stuID,@RequestParam("pwd")String pwd,HttpSession session) {LoginVo vo=new LoginVo();Integer key=(Integer)session.getAttribute("code");return vo;
}

解密方法写在哪里?刚才的加密方法是javascript,controller是java文件,二者不通。不妨创建一个util工具类,把自己写的工具都放在里面
在这里插入图片描述

public class MyUtil {public static String encodePwd(String s, int key){if(s==null) return null;char str[]=s.toCharArray();for(int i=0;i<str.length;i++){if(str[i]>='A'&&str[i]<='Z'){int key1=key%26;int index=(str[i]-'A'+26+key1)%26;str[i]=(char)(index+'A');}else if(str[i]>='a'&&str[i]<='z'){int key1=key%26;int index=(str[i]-'a'+26+key1)%26;str[i]=(char)(index+'a');}else if(str[i]>='0'&&str[i]<='9'){int key1=key%10;int index=(str[i]-'0'+10+key1)%10;str[i]=(char)(index+'0');}}return new String(str);}
}

工具都是静态方法。解码规则同加密规则,不多赘述。

解密之后,带着stuID和pwd去和数据库里找出对应的学生。用找到的stu信息判别是否有该用户,是否有异地登录。

因为要去数据库,我们通过studentService去调用Service层的方法

Student stu=studentService.login(stuID, pwd);

当然在StudentController开头要增加属性

@Resource
private StudentService studentService;

StudentService是一个业务逻辑层的服务类,用于处理与学生相关的业务操作,比如学生信息的增删改查等。

@Resource其默认按名称进行注入,即会根据被注入对象的名称在 Spring 容器中查找匹配的 Bean 进行注入。不写注解studentService堆上申请空间为null,调用其方法会报空指针异常。

这个时候再去写src/com.njupt.service/StudentService Interface接口

public interface StudentService {public Student login();
}

以及src/com.njupt.service/StudentService.impl接口实现类

@Service
public class StudentServiceImpl implements StudentService{@Resourceprivate StudentMapper studentmapper;@Overridepublic Student login(String userID, String pwd) {// TODO Auto-generated method stubreturn studentmapper.login(stuID,pwd);}
}

@Service:这是 Spring 框架的注解,用于将该类标记为一个服务组件,Spring 容器会自动扫描并将其实例化,纳入 Spring 的管理体系。

@Resource:这是 JSR - 250 规范中的注解,用于资源注入,类似于 Spring 的@Autowired。这里将StudentMapper类型的对象注入到studentmapper变量中。

StudentMapper是一个 MyBatis 的 Mapper 接口,用于执行数据库操作。

编写StudentMapper

public interface StudentMapper 
{@Select("select * from student where stuID=#{stuID} and pwd=#{pwd2}")public Student login(@Param("stuID")String stuID,@Param("pwd2")String pwd);}

原来还要写一个StudentMapperImpl接口实现类,以及studentmapper.xml配置文件,但是@Select(“select * from student where stuID=#{stuID} and pwd=#{pwd2}”)省略了这一步骤。这是 MyBatis 的注解,用于指定 SQL 查询语句。@param注释的id写入#{ }里,相当于社会语句里面的占位符。可以任意取名字,只要对应即可,比如把pwd参数取名pwd2,社会语句里面也用pwd2。

#{stuID}和#{pwd2}是 MyBatis 的占位符,在执行 SQL 时会被实际传入的参数值替换。

再从mapper层往上看。如果查询到就返回Student类,没查询到就返回null。service层返回mapper层的返回值到controller。最终才实现这一句话

Student stu=studentService.login(stuID, pwd);

我们先来测试一下对不对,输入一个错误学号密码
login.html

xmlhttp.onreadystatechange=function () { if (xmlhttp.readyState==4 && xmlhttp.status==200) { json=eval("("+xmlhttp.responseText+ ")")console.log(json)if(json.code==100)alert("用户名或密码错误!")	} else {console.error(xmlhttp.status);}} 

StudentController

if(stu==null) {vo.setCode(100);vo.setMessage("userID or pwd is error!");return vo;
}

在这里插入图片描述
说明代码可行,从数据库获取数据正确。

验证是否异地登录

要验证是否有其他人登录,必然要在登陆后进行一些操作,让登录和没登陆有区别。每次登录肯定都有一个stuID学号,HttpSession session,请求就会有唯一的session,还可以有登陆时间,登陆地点(IP地址)。
于是我们可以创建一个UserNode,每次登录就把这些信息存在一个UserNode,并且把这些Node用hashmap存起来,当然也可以用链表。

		UserNode node=HavingLogin.check(stuID);if(node==null) {node=new UserNode();node.setStuID(stuID);node.setSession(session);node.setLoginTime(MyUtil.getTime());node.setIp(request.getRemoteAddr());HavingLogin.add(node);vo.setCode(200);vo.setMessage("success");return vo;}

比如我们先检查是否被登录HavinfgLogin.check(stuID),如果没有被登录,那就登录并且写好vo类的code和message,返回 vo类。

UserNode
由于UserNode并不对应数据库的每张表,也就是不是po类,也不和显示有关,故不是vo类,所以可以放在工具类。

public class UserNode
{String stuID;HttpSession session;String ip;String  loginTime;public UserNode() {}public UserNode(String stuID,HttpSession session,String ip,String loginTime){this.session=session;this.stuID=stuID;this.ip=ip;this.loginTime=loginTime;}public String getStuID() {return stuID;}public void setStuID(String stuID) {this.stuID = stuID;}public HttpSession getSession() {return session;}public void setSession(HttpSession session) {this.session = session;}public String getIp() {return ip;}public void setIp(String ip) {this.ip = ip;}public String getLoginTime() {return loginTime;}public void setLoginTime(String loginTime) {this.loginTime = loginTime;}
}

MyUtil.getTime () 我们要在MyUtil里写获取时间函数。工具方法都用static方便调用。可以用SimpleDataFormat类创建时间

public static String getTime() {SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");return sdf.format(new Date());
}

获取Ip地址
request.getRemoteAddr():在 Java Web 开发中,request是HttpServletRequest类型的对象(比如在 Servlet 或基于 Spring - MVC 等框架的开发中),getRemoteAddr()是HttpServletRequest的一个方法,用于获取发送请求的客户端的 IP 地址。

我们要在login.do参数再加一个HttpServletRequest request

@RequestMapping(value="login.do",method=RequestMethod.POST)
public LoginVo login(@RequestParam("stuID")String stuID,@RequestParam("pwd")String pwd,HttpSession session,HttpServletRequest request) {

设置好UserNode信息后,调用HavingLogin.add(node)存起来。

com.njupt.util里面创建HavingLogin.java

public class HavingLogin
{// key 对应的是学号, value是对应的登录信息private  static HashMap<String, UserNode> havingPools=new HashMap<String, UserNode>();public static UserNode check(String stuID){return  havingPools.get(stuID);}public static void removeNode(String stuID){havingPools.remove(stuID);}public static boolean add(UserNode node){return havingPools.put(node.stuID,node)==null;}}

HashMap havingPools KV存储key是学号,value是UserNode,即登录信息。add就是把设置好信息的node存入havingPools,那么检查登录就是get(stuID),get方法只是得到stuID键对应的value,并不会把stuID和对应的value从hashmap里面删去,删去用remove。如果查出stuID已经存进去了,说明有异地登录,如果是null,说明没有异地登陆。

登陆成功vo.code设置为200,message设置为success,已经有人登录设置code为300,message为登录时间和Ip

controller

vo.setCode(300);
vo.setMessage(node.getLoginTime()+node.getIp());

login.html

json=eval("("+xmlhttp.responseText+ ")")console.log(json)if(json.code==100)alert(jsno.message);else if(json.code==200)alert(json.message);location.href="success.html";else if(json.code==300)alert(json.message);

第一句json=eval()每次复制即可,这行代码主要用于将服务器返回的 JSON 格式的字符串数据转换为 JavaScript 对象。当然了json会自动解析为一个类,我们可以在login.html里调用json.code,json.message。

登陆成功跳转到success.html,只不过我们没写success.html
在这里插入图片描述
再次登陆同一个账号,显示登陆时间和IP地址。
在这里插入图片描述

找回账号

如果是陌生人登陆了我们的账号,我们要验证找回账号。常见的有回答问题。在数据库里建立问题表:
在这里插入图片描述
示例
在这里插入图片描述
id:问题序号
question:问题
answer:答案
stuID:学号

当login.html里json.code==300时弹出确认框,问是否验证。如果要找回账号,按道理,要把stuID传过去回答对应的问题。如果在verify中获得stuID,我们可以用uuid。
uuid
保证数据全球唯一性与一致性,通过uuid生成算法能够保证全球唯一;避免数据冲突等好处。

给每一个登录操作vo类都设置一个uuid。

public class LoginVo {private Integer code;private String message;private String uuid;

每次异地验证返回vo类前都设置一个vo.uuid

vo.setCode(300);
String uuid=UUID.randomUUID().toString();
vo.setUuid(uuid);
session.setAttribute(uuid, stuID);
vo.setMessage(node.getLoginTime()+node.getIp());
return vo;

由于UUID.randomUUID()返回的是一个UUID类,我们要把它转化成String,才能在session.setAttribute里面用uuid字符串把stuID存起来,这个唯一的uuid就对应这个stuID。

login.html

   else if(json.code==300){if (confirm("该账号已在其他设备登录:"+json.message+" 是否要验证拿回?"))location.href="verify.html?"+json.uuid;

把uuid传到verify.html

verify.html

uuid="";
count=0;
function getParam()
{value=location.search;value=value.substring(1);uuid=value;if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safarixmlhttp=new XMLHttpRequest(); } else {// code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.open("get","question.do?uuid="+value,true);xmlhttp.onreadystatechange=function () { if (xmlhttp.readyState==4 && xmlhttp.status==200) { problems=eval("("+xmlhttp.responseText+")")count=problems.length;document.getElementById("infos").innerHTML=display(problems);} } xmlhttp.send();
}

设置全局变量uuid,count表示问题数量。
value获取uuid,因为location.search是"?uuid",所以要把第一个字符略去才是uuid。

get请求uuid对应学号的问题,响应problems是问题数组,count记录problems的数量。再把problems显示在id为infos的HTML元素。

显示结果如下
在这里插入图片描述
第一个问题的答案框 id 为p1,第二个问题答案 id 为p2。
最后点击验证进入verifySubmit()。

verifySubmit()

要验证问题,肯定要把答案传过去请求,我们可以把答案写成json字符串数组,格式为[ “123”,“spring”,“China”]。

function verifySubmit(){answer="[";for(i=0;i<count;i++)answer+="\""+document.getElementById("p"+(i+1))+"\"";answer+="\""+uuid+"\"]";if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safarixmlhttp=new XMLHttpRequest(); } else {// code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange=function () { if (xmlhttp.readyState==4 && xmlhttp.status==200) } xmlhttp.open("post","question.do",true);xmlhttp.setRequestHeader("Content-type","application/json");xmlhttp.send(answer);
}

首先是json格式的左括号 [ ,然后每一条答案都有双引号 " " 围起来,最后再添加uuid,也封装成字符串格式。

把answer post请求过去,带有参数故要设置请求头。

URL为 “question.do”,虽然名字和getParam()里面的一样,但是请求方式不一样,所以不会冲突。

刚刚在getSafeQuestions里已经把List< SafeProblem > lists用uuid作为key存在了session里。我们这个时候不需要再次访问数据库,直接通过uuid就获取到所有SafeProblem,用answer里的值和SafeProblem预存的答案进行比对,只要有不匹配的,设置vo.code=400。如果所有答案都匹配,设置code为500,返回vo。

@RequestMapping(value="question.do",method=RequestMethod.POST)
public LoginVo getSafeQuestions(@RequestBody String[] answer,HttpSession session){String uuid=answer[answer.length-1];LoginVo vo=new LoginVo();List<SafeProblem> lists=(List<SafeProblem>)session.getAttribute(uuid);for(int i=0;i<lists.size();i++) {SafeProblem sp=lists.get(i);if(!sp.getAnswer().equals(answer[i])) {vo.setCode(400);vo.setMessage("回答不正确");return vo;}}uuid=UUID.randomUUID().toString();SafeProblem sp=lists.get(0);session.setAttribute(uuid, sp.getStuID());vo.setCode(500);vo.setMessage("验证成功");vo.setUuid(uuid);return vo;

@RequestBody String[] answer
@RequestBody注解用来处理json格式的请求参数。

如果验证成功给一个全新的uuid。

对应javascript代码

xmlhttp.onreadystatechange=function () { if (xmlhttp.readyState==4 && xmlhttp.status==200) {json=eval("("+xmlhttp.responseText+")")if(json.code==500){alert("verify success,please change your pwd right now.")location.href="changePwd.html?"+json.uuid;} else {alert("不要窃取密码")location.href="login.html";}}else{console.error(xmlhttp.status);}

输入正确答案:南邮;青菜
在这里插入图片描述
错误答案
在这里插入图片描述

相关文章:

登录功能login.html

文章目录 前言一、login.html二、getVerify()controllerlogin() 登录功能encodePwd(pwd,key)login.do验证是否异地登录找回账号verifySubmit() 前言 登录login.html&#xff0c;验证码获取verifycode&#xff0c;登陆函数login() 一、login.html <!DOCTYPE html> <h…...

将 AMD Zynq™ RFSoC 扩展到毫米波领域

目录 将 AMD Zynq™ RFSoC 扩展到毫米波领域Avnet XRF RFSoC 系统级模块适用于 MATLAB 的 Avnet RFSoC Explorer 工具箱5G mmWave PAAM 开发平台突破性的宽带毫米波波束成形特征&#xff1a;OTBF103 Mathworks Simulink 模型优化毫米波应用中的射频信号路径 用于宽带毫米波上/下…...

2.10..

#include "widget.h" #include "ui_widget.h" #include <QFontDialog> #include <QFont> #include <QMessageBox> #include <QColorDialog> #include <QColor> // #include <QFileDialog> //文件对话框…...

Struts2 命令执行漏洞 S2-045 复现:深入剖析与实战演练

前言 在当今网络安全形势日益严峻的大环境下&#xff0c;Web 应用框架的安全问题始终是信息安全领域关注的焦点。Struts2 作为一款广泛应用于 Java Web 开发的开源框架&#xff0c;其安全性直接关系到众多 Web 应用的稳定运行。今天&#xff0c;我们将深入探讨并实战复现 Stru…...

Spark 源码 | 脚本分析总结

前言 最初是想学习一下Spark提交流程的源码&#xff0c;比如 Spark On Yarn 、Standalone。之前只是通过网上总结的文章大概了解整体的提交流程&#xff0c;但是每个文章描述的又不太一样&#xff0c;弄不清楚到底哪个说的准确&#xff0c;比如Client 和 CLuster 模式的区别&a…...

2025.2.9 每日学习记录2:技术报告写了一半+一点点读后感

0.近期主任务线 1.完成小论文准备 目标是3月份完成实验点1的全部实验和论文。 2.准备教资笔试 打算留个十多天左右&#xff0c;一次性备考笔试的三个科目 1.实习申请技术准备&#xff1a;微调、Agent、RAG 1.今日完成任务 1.电子斗蛐蛐&#xff08;文本书写领域&am…...

6、使用one-api管理统一管理大模型,并开始使用本地大模型

文章目录 本节内容介绍集中接入&#xff1a;将大模型统一管理起来当使用了大模型代理大模型代理示例 开源模型&#xff1a;如何使用Hugging Face上的模型modelscope使用 pipeline 调用模型用底层实现调用模型流式输出 如何在项目中使用开源模型使用 LangChain使用集中接入开始使…...

DFS+回溯+剪枝(深度优先搜索)——搜索算法

DFS也就是深度优先搜索&#xff0c;比如二叉树的前&#xff0c;中&#xff0c;后序遍历都属于DFS。其本质是递归&#xff0c;要学好DFS首先需要掌握递归。接下来咱们就一起来学习DFS涉及的算法。 一、递归 1.什么是递归&#xff1f; 递归可以这样理解把它拆分出来&#xff0…...

【数据结构】_堆的实现

目录 1. 堆的实现 1.1 Heap.h 1.2 Heap.c 1.3 Test_Heap.c 专栏前文中&#xff0c;已经介绍了入堆及向上调整算法&#xff0c;出堆及向下调整算法&#xff0c;详情见下文&#xff1a; 【数据结构】_堆的结构及向上、向下调整算法-CSDN博客文章浏览阅读352次&#xff0c;点…...

读书笔记《左耳听风》

读书笔记《左耳听风》 从今年开始&#xff0c;打算给自己定一下在看完书后整理成博客的计划。以往很多看完的书仅仅停留在看完&#xff0c;再回顾的时候总感觉已经不甚清晰了&#xff0c;希望能坚持下去。 《左耳听风》是今年我看完的第一本书&#xff0c;内容针对的是程序员…...

Axure原型图怎么通过链接共享

一、进入Axure 二、点击共享 三、弹出下面弹框&#xff0c;点击发布就可以了 发布成功后&#xff0c;会展示链接&#xff0c;复制即可共享给他人 四、发布失败可能的原因 Axure未更新&#xff0c;首页菜单栏点击帮助选择Axure更新&#xff0c;完成更新重复以上步骤即可...

本地部署DeepSeek,并使用UI界面进行快速交互

一.需要本地部署的原因 1.我们在deepseek的官网界面进行交互时&#xff0c;经常会出现如下问题&#xff0c;不能正常交互&#xff0c;很是困扰&#xff1a; 2.本地部署的好处 就是能够很流畅的与deepseek进行交互&#xff1b;也有缺点&#xff0c;现在官网交互的版本更高一点…...

ESP32S3读取数字麦克风INMP441的音频数据

ESP32S3 与 INMP441 麦克风模块的集成通常涉及使用 I2S 接口进行数字音频数据的传输。INMP441 是一款高性能的数字麦克风&#xff0c;它通过 I2S 接口输出音频数据。在 Arduino 环境中&#xff0c;ESP32S3 的开发通常使用 ESP-IDF&#xff08;Espressif IoT Development Framew…...

移动(新)魔百盒刷机教程[M301A_YS]

刚刚成功刷了一个坏的魔百盒&#xff0c;简单记录一下。 刷电视盒子有两种&#xff1a;卡刷和线刷。 线刷 一、线刷准备 1.刷机工具 Amlogic USB Burning Tool 晶晨线刷烧录工具 2.固件 根据盒子的型号、代工等找到对应的固件 二、线刷步骤 电脑打开下好的 Amlogic US…...

15 大 AWS 服务

在不断发展的云计算世界中&#xff0c;Amazon Web Services (AWS) 已成为一股主导力量&#xff0c;提供许多服务以满足各种应用程序开发、部署和管理方面的需求。本文将探讨 15 项 AWS 服务。这些服务对于构建可扩展、可靠且高效的系统至关重要。 1.Amazon EC2&#xff08;弹性…...

【C++】命名空间

&#x1f31f; Hello&#xff0c;我是egoist2023&#xff01; &#x1f30d; 种一棵树最好是十年前&#xff0c;其次是现在&#xff01; 目录 背景知识 命名空间(namespace) 为何引入namespace namespace的定义 namespace的使用 背景知识 C的起源要追溯到1979年&#xff0…...

项目实战(11)-双通道气体压力计V1.0

一. 产品简介&#xff1a; 1、项目背景是在实际应用中需要监控通道内气体的压力&#xff0c;压力计分为两个通道&#xff1b;通道一时实时监控&#xff1b;通道二是保压&#xff0c;设定保压值得上下限后通道内得气体压力值会一直保持在这个范围内。 二. 应用场景&#xff1a…...

python+unity落地方案实现AI 换脸融合

先上效果再说技术结论&#xff0c;使用的是自行搭建的AI人脸融合库&#xff0c;可以离线不受限制无限次生成&#xff0c;有需要的可以后台私信python ai换脸融合。 TODO 未来的方向&#xff1a;3D人脸融合和AI数据训练 这个技术使用的是openvcinsighface&#xff0c;openvc…...

开启对话式智能分析新纪元——Wyn商业智能 BI 携手Deepseek 驱动数据分析变革

2月18号&#xff0c;Wyn 商业智能 V8.0Update1 版本将重磅推出对话式智能分析&#xff0c;集成Deepseek R1大模型&#xff0c;通过AI技术的深度融合&#xff0c;致力于打造"会思考的BI系统"&#xff0c;让数据价值触手可及&#xff0c;助力企业实现从数据洞察到决策执…...

数据结构——【二叉树模版】

#思路 1、二叉树不同于数的构建&#xff0c;在树节点类中&#xff0c;有数据&#xff0c;左子结点&#xff0c;右子节点三个属性&#xff0c;在树类的构造函数中&#xff0c;添加了变量maxNodes&#xff0c;用于后续列表索引的判断 2.GetTreeNode()函数是常用方法&#xff0c;…...

DeepSeek之于心理学的一点思考

模型和硬件参数对应关系参考 模型参数规模 典型用途 CPU建议 GPU建议 最小内存建议 磁盘空间建议 适用场景 1.5b(15亿) 小型推理、轻量级任务 4核以上(Intel i5/AMD Ryzen5) 可选&#xff0c;入门级GPU(如NVIDIA GTX1650 4GB显存) 8GB 10GB以上SSD 小型NLP任务、文…...

mysql 存储过程和自定义函数 详解

首先创建存储过程或者自定义函数时&#xff0c;都要使用use database 切换到目标数据库&#xff0c;因为存储过程和自定义函数都是属于某个数据库的。 存储过程是一种预编译的 SQL 代码集合&#xff0c;封装在数据库对象中。以下是一些常见的存储过程的关键字&#xff1a; 存…...

数据结构:单链表

1.概念&#xff1a; 单链表&#xff08;Singly Linked List&#xff09;是一种常见的数据结构&#xff0c;它由一系列节点&#xff08;Node&#xff09;组成&#xff0c;每个节点包含两个部分&#xff1a; 数据域&#xff08;Data&#xff09;&#xff1a;存储节点的值或数据。…...

部署项目(ubantu服务器,配置jdk,启动项目,及测试)

目录 1、ubantu安装jdk 2、部署项目 ​ 解决 java -jar 报错&#xff1a;xxx.jar 中没有主清单属性 ​ 3、测试 4、查看系统部署的应用 1、ubantu安装jdk #压缩文件jdk文件&#xff1a;tar -czvf jdk17.tar.gz jdk17 #解压jdk文件&#xff1a;tar -xzvf jdk17.tar.gz 参…...

deepseek本地部署教程

第一步&#xff1a;进入Ollama官网 &#xff08;Download Ollama on macOS&#xff09;&#xff0c;下载ollama(注意需要Window10或更高的版本&#xff09;&#xff0c;安装&#xff08;OllamaSetup.exe&#xff09;&#xff0c;默认在c盘 第二步&#xff1a;点击Models,再点击…...

MySQL主从同步+binlog

一、简介 MySQL内建的复制功能是构建大型&#xff0c;高性能应用程序的基础 通过将MySQL的某一台主机&#xff08;master&#xff09;的数据复制到其他主机&#xff08;slaves&#xff09;上&#xff0c;并重新执行一遍来执行 复制过程中一台服务器充当主服务器&#xff0c;而…...

防火墙术语大全( Firewalld Glossary of Terms)

防火墙术语大全 防火墙作为网络安全中不可或缺的设备&#xff0c;在各种网络架构中扮演着至关重要的角色。无论是企业级防火墙、云防火墙还是家用路由器内置的防火墙&#xff0c;它们的工作原理和配置策略都离不开一系列专业术语的支撑。对于网络工程师来说&#xff0c;掌握这…...

LeetCode刷题---数组---697

数组的度 697. 数组的度 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 给定一个非空且只包含非负数的整数数组 nums&#xff0c;数组的 度 的定义是指数组里任一元素出现频数的最大值。 你的任务是在 nums 中找到与 nums 拥有相同大小的度的最短连续子数组&am…...

C语言基础08:运算符+流程控制总结

运算符 算术运算符 结果&#xff1a;数值 、-、*、\、%、&#xff08;正&#xff09;、-&#xff08;负&#xff09;、、-- i和i 相同点&#xff1a;i自身都会增1 不同点&#xff1a;它们运算的最终结果是不同的。i&#xff1a;先使用&#xff0c;后计算&#xff1b;i&am…...

[安装FlashAttention] CUDA版本 和 Nvidia驱动版本

nvidia-smi 查看driver api 的CUDA版本 听说这个是本机能装到的最高版本 那这样看来我最高能装到12.4。 nvcc -V 查看当前runtime api的CUDA版本 还是古老的11.5版本&#xff0c;没办法啊&#xff0c;FlashAttention老是说不支持&#xff1f; 安装Torch时选择的CUDA版本 p…...

Android图片加载框架Coil,Kotlin

Android图片加载框架Coil&#xff0c;Kotlin implementation("io.coil-kt:coil:1.4.0") import android.os.Bundle import android.widget.ImageView import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import coil.Coil i…...

Win11下搭建Kafka环境

目录 一、环境准备 二、安装JDK 1、下载JDK 2、配置环境变量 3、验证 三、安装zookeeper 1、下载Zookeeper安装包 2、配置环境变量 3、修改配置文件zoo.cfg 4、启动Zookeeper服务 4.1 启动Zookeeper客户端验证 4.2 启动客户端 四、安装Kafka 1、下载Kafka安装包…...

从大规模恶意攻击 DeepSeek 事件看 AI 创新隐忧:安全可观测体系建设刻不容缓

作者&#xff1a;羿莉&#xff08;萧羿&#xff09; 全球出圈的中国大模型 DeepSeek 作为一款革命性的大型语言模型&#xff0c;以其卓越的自然语言处理能力和创新性成本控制引领行业前沿。该模型不仅在性能上媲美 OpenAI-o1&#xff0c;而且在推理模型的成本优化上实现了突破…...

模拟(典型算法思想)—— OJ例题算法解析思路

目录 一、1576. 替换所有的问号 - 力扣(LeetCode) 运行代码: 1. 输入和输出 2. 变量初始化 3. 遍历字符串 4. 替换逻辑 5. 返回结果 整体分析 1. 思路总结 2. 为什么要这样设计 3. 时间复杂度与空间复杂度 4. 边界情况 二、495. 提莫攻击 - 力扣(LeetCode) …...

pgsql最快的数据导入BeginBinaryImport

PostgreSQL 的 BeginBinaryImport 是 libpq&#xff08;PostgreSQL 的 C 语言客户端库&#xff09; 中的一个函数&#xff0c;用于高效实现二进制数据的大批量导入。以下是详细介绍及适用语言说明&#xff1a; BeginBinaryImport 的作用 功能 它是 PostgreSQL C 接口库&#xf…...

【进程与线程】如何编写一个守护进程

如何编写一个守护进程。我们首先需要理解守护进程是什么。守护进程是在后台运行的进程&#xff0c;通常没有控制终端&#xff0c;用于执行系统任务&#xff0c;比如服务器或者定时任务。 用户可能想创建一个长期运行的服务&#xff0c;比如Web服务器或者日志监控程序。 首先&a…...

Docker容器访问外网:启动时的网络参数配置指南

在启动Docker镜像时,可以通过设置网络参数来确保容器能够访问外网。以下是几种常见的方法: 1. 使用默认的bridge网络 Docker的默认网络模式是bridge,它会创建一个虚拟网桥,将容器连接到宿主机的网络上。在大多数情况下,使用默认的bridge网络配置即可使容器访问外网。 启动…...

大数据-259 离线数仓 - Griffin架构 修改配置 pom.xml sparkProperties 编译启动

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; 目前开始更新 MyBatis&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff0…...

DeepSeek神经网络:技术架构与实现原理探析

以下是一篇关于DeepSeek神经网络的研究及实现原理的综述性文章&#xff0c;结合其技术架构、训练范式及创新点展开分析&#xff1a; 1. 核心架构设计 DeepSeek的神经网络架构以**混合专家模型&#xff08;Mixture of Experts, MOE&#xff09;**为基础&#xff0c;结合轻量化…...

KTOR:高效的Linux横向移动与无文件落地HTTP服务扫描工具

地址:https://github.com/MartinxMax/KTOR 简介 KTOR 是一款专为 Linux 横向渗透设计的工具。通过该工具&#xff0c;您可以快速扫描内部 HTTP 服务&#xff0c;以便进一步进行网络渗透&#xff0c;且实现无文件落地扫描。 在CTF中通常需要利用本地其他端口HTTP服务或其他主…...

C++ Primer 类型转换

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…...

2025新的一年网络营销推广该怎么干?

2025年&#xff0c;全球网民数量预计突破60亿&#xff0c;但流量红利消退、用户注意力稀缺、技术迭代加速……企业网络营销正面临前所未有的“生存战”。如何在竞争中突围&#xff1f;小马识途营销机构基于十五年实战经验&#xff0c;总结出2025年企业必须抢占的五大核心战场&a…...

java实现Http请求方式的几种常见方式

背景 在实际开发过程中&#xff0c;我们经常需要调用对方提供的接口或测试自己写的接口是否合适。很多项目都会封装规定好本身项目的接口规范&#xff0c;所以大多数需要去调用对方提供的接口或第三方接口&#xff08;短信、天气等&#xff09;。若是普通java工程推荐使用OkHt…...

安卓开发,底部导航栏

1、创建导航栏图标 使用系统自带的矢量图库文件&#xff0c;鼠标右键点击res->New->Vector Asset 修改 Name , Clip art 和 Color 再创建一个 同样的方法再创建四个按钮 2、添加百分比布局依赖 app\build.gradle.kts 中添加百分比布局依赖&#xff0c;并点击Sync Now …...

Spring Boot中实现多租户架构

文章目录 Spring Boot中实现多租户架构多租户架构概述核心思想多租户的三种模式优势挑战租户识别机制1. 租户标识(Tenant Identifier)2. 常见的租户识别方式3. 实现租户识别的关键点4. 租户识别示例代码5. 租户识别机制的挑战数据库隔离的实现1. 数据库隔离的核心目标2. 数据…...

SpringBoot源码解析(十):应用上下文AnnotationConfigServletWebServerApplicationContext构造方法

SpringBoot源码系列文章 SpringBoot源码解析(一)&#xff1a;SpringApplication构造方法 SpringBoot源码解析(二)&#xff1a;引导上下文DefaultBootstrapContext SpringBoot源码解析(三)&#xff1a;启动开始阶段 SpringBoot源码解析(四)&#xff1a;解析应用参数args Sp…...

vue3+vite全局loading

vue3vite全局loading j-loading.vue组件 <template><transition enter-active-class"animate__animated animate__fadeIn"leave-active-class"animate__animated animate__fadeOut"><div class"root-box" v-if"show"…...

比亚迪发布智能化战略,天神之眼开创全民智驾

2月10日&#xff0c;比亚迪在深圳隆重召开智能化战略发布会&#xff0c;正式向全球发布了其最新的智驾技术——“天神之眼”。这一技术的发布&#xff0c;标志着比亚迪在智能驾驶领域迈出了坚实的一步&#xff0c;稳居行业第一梯队&#xff0c;真正实现了端到端的智能驾驶体验&…...

在 MySQL 中,通过存储过程结合条件判断来实现添加表字段时,如果字段已存在则不再重复添加

-- 创建存储过程 DELIMITER $$ CREATE PROCEDURE add_column(IN db_name VARCHAR(255),IN table_name VARCHAR(255),IN column_name VARCHAR(255),IN column_definition VARCHAR(255),IN column_comment VARCHAR(255) ) BEGINDECLARE column_exists INT;-- 检查字段是否存在SEL…...

UP-VLA:具身智体的统一理解与预测模型

25年1月来自清华大学和上海姚期智研究院的论文“UP-VLA: A Unified Understanding and Prediction Model for Embodied Agent”。 视觉-语言-动作 (VLA) 模型的最新进展&#xff0c;利用预训练的视觉语言模型 (VLM) 来提高泛化能力。VLM 通常经过视觉语言理解任务的预训练&…...