最新发布
-
Java多线程基础实操题解析:实现Runnable接口的线程创建 Java多线程基础实操题解析:实现Runnable接口的线程创建 一、原题代码呈现 13.png图片 以下是计算机二级Java实操题的原题代码,包含4处需要填写的空白(标记为//*********Found**********): //*********Found********** public class Java_2 ___________________{ private int x=0; private int y=0; public static void main(String[]args){ Java_2 r = new Java_2(); //*********Found********** Thread t = new Thread( ___________________ ); t.start(); } public void run() { //*********Found********** int ___________________ = 0; for(;;){ x++; //*********Found********** ___________________; k++; if (k>5) break; System.out.println("x=" + x + ",y ="+ y); } } }二、空白处分析与解答 1. 第一处空白:类的继承/实现声明 //*********Found********** public class Java_2 implements Runnable { 解析: 程序中定义了run()方法,这是Runnable接口的核心方法。Java中实现多线程的方式之一是实现Runnable接口,因此类需要声明implements Runnable,否则run()方法无法被线程正确调用。 2. 第二处空白:Thread构造方法的参数 //*********Found********** Thread t = new Thread( r );解析: Thread类的构造方法可以接收Runnable类型的参数(即实现了Runnable接口的对象)。此处r是Java_2类的实例(已实现Runnable接口),将其作为参数传入,线程启动后会执行r对象的run()方法。 3. 第三处空白:循环控制变量的声明 //*********Found********** int k = 0;解析: 后续代码中出现了k++和if (k>5) break,说明k是循环计数器。此处需要声明int类型的变量k并初始化(通常初始化为0),否则会报“变量未定义”错误。 4. 第四处空白:y变量的自增操作 //*********Found********** y++; 解析: 程序的逻辑是在循环中对x和y进行操作,然后输出它们的值。观察代码结构,x++后缺少对y的操作,而输出语句包含y,因此此处应添加y++使y随循环自增,保证输出逻辑完整。 三、完整正确代码 隐藏内容,请前往内页查看详情 四、程序运行逻辑与多线程知识点 运行结果 程序启动后,线程会执行run()方法中的循环,共输出5行结果(k从1到5): x=1,y=1 x=2,y=2 x=3,y=3 x=4,y=4 x=5,y=5核心知识点解析 Runnable接口实现多线程的原理 Runnable接口是函数式接口,仅包含run()方法,用于定义线程执行体。 实现Runnable接口的类需要重写run()方法,将线程逻辑放入其中。 必须通过Thread类包装(new Thread(runnable))才能启动线程,调用start()方法而非直接调用run()。 start()与run()的区别 start():启动线程,由JVM调用run()方法,真正实现多线程运行。 run():普通方法调用,若直接调用则不会创建新线程,仅在当前线程中执行。 循环控制与变量作用域 此处使用for(;;)创建无限循环,通过k的计数器控制退出条件(k>5时break)。 变量k声明在run()方法内部,属于局部变量,仅在该方法中有效。 五、常见错误与应试技巧 常见错误 第一处空白误写为extends Thread:虽然继承Thread也能实现多线程,但本题中类已定义run()方法且无Thread的其他方法调用,更符合implements Runnable的场景。 第二处空白传入this或Java_2:this在main方法(静态方法)中无法使用,而Java_2是类名,不能直接作为参数(需传入实例)。 第四处空白误写为x--或y=k:不符合输出结果中x和y同步增长的逻辑。 应试技巧 遇到多线程题目时,先观察是否有run()方法,再判断是实现Runnable接口还是继承Thread类。 注意静态方法(如main)中不能直接使用this,需通过创建对象实例调用非静态方法/属性。 变量未定义的错误通常是由于缺少声明,可根据后续使用的变量名(如k)补全声明。 通过本题可以掌握Java多线程的基础实现方式,理解Runnable接口的应用场景,以及线程启动的核心逻辑。在实际开发中,实现Runnable接口比继承Thread类更灵活(可避免单继承限制),是更推荐的多线程实现方式。
-
Java字符串操作与 JOptionPane 应用详解(计算机二级真题解析) Java字符串操作与 JOptionPane 应用详解(计算机二级真题解析) 一、原题呈现 12.png图片 以下是计算机二级Java实操题的原题代码,包含三处需要填写的空白(标记为//*********Found**********): //*********Found********** import javax.________________.JOptionPane; public class Java_1{ public static void main( String args[] ){ String s1, s2, s3, s4, output; s1 = new String( "hello" ); s2 = new String( "good bye" ); s3 = new String( "Happy Birthday" ); s4 = new String( "happy birthday" ); output = "s1 = " + s1 + "\ns2 = " + s2 + "\ns3 = " + s3 + "\ns4 = " + s4 + "\n\n"; //测试字符串相等 if ( s1.equals( "hello" ) ) //*********Found********** output = output + "_________________________"; else output = output + "s1 does not equal \"hello\"\n"; //用==测试相等 if ( s1 == "hello" ) output += "s1 equals \"hello\"\n"; else output += "s1 does not equal \"hello\"\n"; //忽略字符格式测试相等 if ( s3.equalsIgnoreCase( s4 ) ) output += "s3 equals s4\n"; else output += "s3 does not equal s4\n"; //内容比较 output += "\ns1.compareTo( s2 ) is " + s1.compareTo( s2 ) + "\ns2.compareTo( s1 ) is " + s2.compareTo( s1 ) + "\ns1.compareTo( s1 ) is " + s1.compareTo( s1 ) + "\ns3.compareTo( s4 ) is " + s3.compareTo( s4 ) + "\ns4.compareTo( s3 ) is " + s4.compareTo( s3 ) + "\n\n"; //测试包含字符格式的域匹配 if ( s3.regionMatches( 0, s4, 0, 5 ) ) output += "First 5 characters of s3 and s4 match\n"; else output += "First 5 characters of s3 and s4 do not match\n"; //忽略字符格式的域匹配 if ( s3.regionMatches( true, 0, s4, 0, 5 ) ) output += "First 5 characters of s3 and s4 match"; else output += "First 5 characters of s3 and s4 do not match"; //*********Found********** JOptionPane.______________________( null, output, "字符串构造方法示例", JOptionPane.INFORMATION_MESSAGE ); System.exit( 0 ); } }二、空白处分析与解答 1. 第一处空白:导入JOptionPane类 //*********Found********** import javax.swing.JOptionPane;解析: JOptionPane是Swing组件库中的类,用于创建标准对话框,其完整包路径为javax.swing。因此需要导入javax.swing.JOptionPane才能使用该类。 2. 第二处空白:字符串相等判断的输出内容 //*********Found********** output = output + "s1 equals \"hello\"\n";解析: 此处是if (s1.equals("hello"))条件为true时的执行语句。根据程序逻辑的对称性(与else分支对比),当条件成立时应输出s1 equals "hello"。注意字符串中的双引号需要用转义字符\"表示,\n用于换行。 3. 第三处空白:JOptionPane的显示方法 //*********Found********** JOptionPane.showMessageDialog( null, output, "字符串构造方法示例", JOptionPane.INFORMATION_MESSAGE );解析: showMessageDialog是JOptionPane的静态方法,用于显示信息对话框。其参数含义如下: 第一个参数:父组件(null表示使用默认窗口) 第二个参数:要显示的消息内容 第三个参数:对话框标题 第四个参数:消息类型(此处为信息图标) 三、完整正确代码 隐藏内容,请前往内页查看详情 四、程序运行结果与知识点总结 运行结果说明 程序运行后会弹出一个对话框,显示以下内容: 四个字符串的初始值 s1.equals("hello")的结果为true(内容相等) s1 == "hello"的结果为false(引用不同) s3.equalsIgnoreCase(s4)的结果为true(忽略大小写相等) 字符串比较的compareTo结果(基于Unicode值的差值) 区域匹配的测试结果(区分大小写时不匹配,忽略大小写时匹配) 核心知识点 字符串比较的两种方式: equals():比较字符串内容是否相同 ==:比较对象引用是否指向同一个内存地址 字符串常用方法: equalsIgnoreCase():忽略大小写比较内容 compareTo():按字典顺序比较,返回差值 regionMatches():比较指定区域的子字符串 Swing对话框: JOptionPane.showMessageDialog():快速创建信息提示框 适用于简单的用户交互场景 五、备考建议 这道题考察了Java字符串操作的核心概念和Swing组件的基本使用,是计算机二级Java考试的重点内容。备考时应注意: 区分equals()和==在字符串比较中的不同作用 掌握字符串类的常用方法及其返回值含义 了解Swing基本组件的使用,尤其是对话框相关类 通过这类题目,可以加深对Java面向对象特性的理解,特别是字符串作为对象的特殊处理方式。实际编程中,正确使用字符串方法能有效避免常见的逻辑错误。
-
IP+手机定位系统开源发布:基于高德地图API的精准定位解决方案 IP+手机定位系统开源发布:基于高德地图API的精准定位解决方案 项目背景 在当今互联网应用中,位置服务已成为许多平台的核心功能之一。今天我要向大家分享一个基于高德地图API开发的IP+手机定位系统,该系统可以帮助开发者快速集成精准定位功能到自己的项目中。 系统概述 这个定位系统具有以下特点: 基于高德地图API,定位精准可靠 支持IP定位和手机定位两种方式 简洁美观的前端界面 完善的后台管理系统 完全开源,可自由二次开发 系统功能 核心功能 IP定位:通过访问者IP地址获取大致地理位置 手机定位:通过手机GPS或基站信息获取精确位置 位置可视化:在地图上直观显示定位结果 历史记录:保存查询历史,方便回溯 后台管理 用户管理 定位记录查询 系统配置 数据统计与分析 快速开始 下载源码 隐藏内容,请前往内页查看详情 环境要求 PHP 5.6+ MySQL 5.5+ 高德地图开发者账号(免费注册) 高德Key获取教程 访问高德开放平台 注册开发者账号(如已有账号请跳过) 创建新应用 获取Key(Web服务API Key) 详细教程可百度搜索"高德地图Key获取教程" 安装步骤 上传源码:将下载的源码上传至您的Web服务器 解析域名:将您的域名解析到服务器IP 配置Key: 打开process_location.php文件,第6行替换为您的高德Key 打开admin/index.php文件,第35行替换为您的高德Key 修改管理员账号(可选): 打开login.php文件,第16-17行修改默认管理员账号密码 访问地址 前端访问:https://您的域名 后台管理:https://您的域名/admin.php 默认账号:admin 默认密码:123456(建议首次登录后立即修改) 系统截图 i1.png图片 i2.jpg图片 i3.jpg图片 i4.png图片 技术实现 核心代码解析 IP定位处理(process_location.php) // 高德地图API请求 $key = '您的高德Key'; // 第6行需替换 $ip = $_SERVER['REMOTE_ADDR']; $url = "https://restapi.amap.com/v3/ip?ip=$ip&key=$key"; $response = file_get_contents($url); $result = json_decode($response, true); // 处理返回结果 if($result['status'] == '1') { // 定位成功处理逻辑 } else { // 定位失败处理逻辑 }后台管理验证(login.php) // 第16-17行可修改默认账号密码 $admin_user = 'admin'; $admin_pass = '123456';安全建议 修改默认凭证:务必修改默认管理员账号密码 代码加密:建议使用PHP代码加密保护您的源码 推荐免费加密平台:PHP代码加密平台 支持多种加密方式:Sg16、Deck3、Ic12、goto、enphp、noname等 HTTPS部署:确保使用HTTPS协议保障数据传输安全 定期备份:定期备份数据库和源码 常见问题解答 Q:定位不准确怎么办? A:1. 检查高德Key是否正确配置 确认使用的IP地址是用户真实IP(注意代理情况) 手机定位需要用户授权GPS权限 Q:后台无法登录怎么办? A:1. 检查账号密码是否正确 确认login.php中的默认账号密码是否修改 检查服务器是否正常解析PHP文件 Q:如何提高系统性能? A:1. 添加缓存机制,减少API调用 优化数据库查询 使用CDN加速静态资源 二次开发建议 多地图平台支持:可扩展支持百度地图、腾讯地图等 数据可视化:添加更丰富的数据统计图表 报警功能:当定位到特定区域时触发报警 API接口:开发RESTful API供其他系统调用 结语 本IP+手机定位系统基于高德地图API开发,功能完善且易于二次开发。无论是用于商业项目还是学习研究,都是一个不错的起点。系统完全开源,开发者可以根据自己的需求自由修改和扩展。 如果在使用过程中遇到任何问题,或者有改进建议,欢迎在评论区留言交流。也欢迎各位开发者共同参与项目改进,让这个定位系统变得更加强大! 注意事项:使用高德地图API请遵守高德开放平台的相关协议,商业使用请注意调用频次限制。
-
深入解析Pikachu Delete注入漏洞:从代码分析到报错注入实战 深入解析Pikachu Delete注入漏洞:从代码分析到报错注入实战 在Web安全渗透测试中,SQL注入始终是最常见且危害极大的漏洞类型之一。今天我们以Pikachu漏洞练习平台的Delete注入题目为例,深入剖析漏洞成因,并通过实战演示如何利用报错注入获取数据库敏感信息。 一、漏洞背景与环境说明 Pikachu是一款广受安全学习者欢迎的漏洞练习平台,其中的“Delete注入”题目模拟了实际开发中因不当处理用户输入而导致的SQL注入风险。该场景通常出现在数据删除功能中,攻击者可通过构造特殊请求,篡改SQL语句实现未授权操作或信息泄露。 本次分析的核心场景是一个消息删除功能——用户点击删除按钮时,前端会向服务器传递消息ID,服务器根据该ID执行删除操作。看似简单的功能,却因代码缺陷埋下了安全隐患。 二、漏洞源代码深度分析 我们先来看存在漏洞的核心代码: // 原始代码(存在漏洞) if(array_key_exists('id', $_GET)){ $query="delete from message where id={$_GET['id']}"; $result=execute($link, $query); if(mysqli_affected_rows($link)==1){ header("location:sqli_del.php"); }else{ $html.="<p style='color: red'>删除失败,检查下数据库是不是挂了</p>"; } }漏洞关键成因: 输入未做任何过滤 代码直接使用$_GET['id']拼接SQL语句,未进行类型验证(如is_numeric()判断)或转义处理。这意味着用户传入的id参数可直接控制SQL语句结构。 SQL语句拼接方式不安全 delete语句采用字符串拼接:"delete from message where id={$_GET['id']}"。由于id参数未加引号包裹(直接作为数值拼接),攻击者可轻松注入恶意SQL代码改变语句逻辑。 对比安全版本的差异 注释中提到的安全写法if(array_key_exists('id', $_GET) && is_numeric($_GET['id']))明确要求id必须为数字,而漏洞代码删除了这一验证,直接导致注入风险。 三、漏洞利用原理:从删除操作到信息泄露 Delete注入的特殊性在于:它本身是删除数据的操作,但通过构造注入语句,我们可将其转化为信息查询工具。核心思路是利用SQL语句的逻辑拼接,在执行删除操作的同时执行查询语句,并通过报错信息获取结果。 以本题为例,正常的删除SQL为: delete from message where id=1当我们传入恶意id参数时,SQL语句会被篡改。例如传入1 or 1=1,语句变为: delete from message where id=1 or 1=1 -- 删除所有消息(危险!)但在实际测试中,我们更关注如何在不破坏数据的前提下获取信息,报错注入正是最佳选择。 四、实战:基于报错注入的数据库信息获取 1. 报错注入原理 报错注入利用了MySQL的函数特性:当某些函数(如updatexml()、extractvalue())的参数不符合语法规范时,会抛出错误并显示参数内容。通过在参数中嵌入查询语句,即可将查询结果通过报错信息泄露。 核心函数updatexml()的语法: updatexml(XML_document, XPath_string, new_value)当XPath_string包含非XML规范字符(如~)时,MySQL会报错并显示该字符串,这就是我们泄露信息的关键。 2. 构造Delete注入的报错Payload 针对本题的漏洞代码,有效的报错注入Payload为: 隐藏内容,请前往内页查看详情 Payload解析: 1:作为初始id值,确保语句前半部分语法正确 or:逻辑运算符,用于拼接后续恶意代码(只要前后有一个为真,整个条件就为真) updatexml(1,concat(0x7e,database()),0):核心注入代码 concat(0x7e,database()):将波浪号(0x7e是~的十六进制编码)与数据库名拼接 updatexml因~不符合XML规范而报错,同时显示拼接后的内容(如~pikachu) 3. 执行注入与结果分析 将Payload作为id参数传入URL: http://[目标地址]/sqli_del.php?id=1 or updatexml(1,concat(0x7e,database()),0)在浏览器上访问就行了,抓包分析的话需要url转码 屏幕截图 2025-08-06 232957.png图片 delete注入.png图片 执行后,页面会返回类似以下的错误信息: XPATH syntax error: '~pikachu'其中pikachu就是当前数据库的名称,证明注入成功。 4. 扩展:获取更多敏感信息 通过修改Payload中的查询语句,可进一步获取表名、列名等信息: 获取当前用户:1 or updatexml(1,concat(0x7e,user()),0) 获取消息表的表名(假设已知库名pikachu): 1 or updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu' limit 0,1)),0) 获取表中列名(假设已知表名message): 隐藏内容,请前往内页查看详情 五、漏洞修复建议 Delete注入的本质是用户输入未被安全处理就拼接进SQL语句,修复需从根本上避免这种风险: 严格验证输入类型 恢复代码中对id的数值验证,确保仅接受数字: if(array_key_exists('id', $_GET) && is_numeric($_GET['id'])){...} 使用参数化查询 采用预处理语句分离SQL结构与用户输入,彻底杜绝注入: $stmt = mysqli_prepare($link, "delete from message where id=?"); mysqli_stmt_bind_param($stmt, 'i', $_GET['id']); // 'i'表示参数为整数 mysqli_stmt_execute($stmt); 最小权限原则 数据库账号仅授予必要权限(如删除操作所需权限),限制注入后的破坏范围。 六、总结 Pikachu的Delete注入题目生动展示了“信任用户输入”带来的风险。通过本次实战,我们不仅掌握了报错注入的原理与Payload构造方法,更深刻理解了“参数化查询”对于防御SQL注入的重要性。在实际开发中,任何与数据库交互的功能都应严格过滤用户输入,这是保障Web安全的基础防线。
-
解决Go项目关闭终端后停止运行的3种实用方案(附完整操作指南) 解决Go项目关闭终端后停止运行的3种实用方案(附完整操作指南) 在Go项目部署过程中,很多开发者都会遇到一个共性问题:通过终端启动程序后,一旦关闭终端,程序就会随之停止运行。这本质上是因为程序运行在前台进程中,终端作为父进程被关闭时,子进程会被系统终止。本文将介绍3种可靠方案,彻底解决这一问题,确保Go程序在服务器上稳定运行。 go.jpg图片 一、问题根源:前台进程与终端的依赖关系 当我们通过./shuha(假设程序名为shuha)直接启动Go程序时,程序会作为前台进程运行,其生命周期与终端绑定: 终端关闭时,系统会向关联的所有进程发送SIGHUP(挂起信号) 前台进程收到该信号后会默认终止运行 这就是为什么关闭终端后程序会停止的核心原因 二、解决方案详解 方案1:使用nohup命令(最简单直接) nohup(no hang up)命令的作用是忽略终端关闭时发送的SIGHUP信号,让程序脱离终端独立运行,同时将输出日志重定向到文件。 操作步骤: 进入程序目录 cd /www/wwwroot/auth-shuha-api # 替换为你的项目路径 创建日志目录(可选但推荐) 为避免日志散落在项目根目录,建议创建专门的日志文件夹: mkdir -p logs # 创建logs目录 chmod 755 logs # 赋予读写权限 后台启动程序 nohup ./shuha > logs/run.log 2>&1 & 命令解析: nohup:忽略终端关闭信号 ./shuha:启动Go程序 > logs/run.log:将标准输出(stdout)写入日志文件 2>&1:将错误输出(stderr)合并到标准输出,统一写入日志 &:将程序放入后台运行 验证程序是否运行 ps -ef | grep shuha # 查看进程若输出包含./shuha,说明程序已在后台稳定运行。 查看实时日志 tail -f logs/run.log # 实时监控日志输出 停止程序(如需) 先通过ps命令获取进程ID(PID),再用kill终止: ps -ef | grep shuha # 找到进程ID(第二列数字) kill -9 12345 # 替换12345为实际PID 方案2:使用screen创建虚拟终端(适合频繁调试) screen是一款终端复用工具,可创建独立的虚拟终端会话。关闭终端后,会话仍在后台运行,重新连接终端后可恢复会话继续操作。 操作步骤: 安装screen(首次使用) CentOS系统: yum install -y screen Ubuntu/Debian系统: apt-get install -y screen 创建新会话 screen -S go_shuha # 创建名为go_shuha的会话(名称可自定义)执行后会进入一个全新的虚拟终端。 启动程序 在虚拟终端中正常启动Go程序: cd /www/wwwroot/auth-shuha-api ./shuha # 前台启动(可直接看到输出日志) 脱离会话(保持程序运行) 按Ctrl + A后再按D(先按Ctrl+A,松开后按D),此时会回到原终端,程序在虚拟会话中继续运行。 重新连接会话 关闭终端后,再次登录服务器,执行以下命令恢复会话: screen -r go_shuha # 重新进入名为go_shuha的会话 终止程序与会话 在会话中按Ctrl + C终止程序 输入exit可关闭当前虚拟会话 方案3:使用systemd配置系统服务(最稳定,推荐生产环境) 将Go程序注册为系统服务,可通过systemctl命令管理,支持开机自启,是生产环境的最佳选择。 操作步骤: 创建服务配置文件 vim /etc/systemd/system/shuha.service # 用vim编辑服务文件 写入配置内容 按i进入编辑模式,粘贴以下内容(根据实际路径修改): [Unit] Description=Auth Shuha API Service # 服务描述 After=network.target mysql.service # 依赖网络和MySQL服务(可选) [Service] User=root # 运行用户(建议用非root用户,如www) WorkingDirectory=/www/wwwroot/auth-shuha-api # 程序目录 ExecStart=/www/wwwroot/auth-shuha-api/shuha # 程序绝对路径 Restart=always # 程序崩溃时自动重启 RestartSec=3 # 重启间隔3秒 StandardOutput=append:/www/wwwroot/auth-shuha-api/logs/run.log # 标准输出日志 StandardError=append:/www/wwwroot/auth-shuha-api/logs/error.log # 错误日志 [Install] WantedBy=multi-user.target # 多用户模式下启动按Esc后输入:wq保存退出。 刷新系统服务 systemctl daemon-reload # 重新加载服务配置 启动服务 systemctl start shuha # 启动服务 设置开机自启(可选) systemctl enable shuha # 开机自动启动 服务管理常用命令 systemctl status shuha # 查看服务状态 systemctl stop shuha # 停止服务 systemctl restart shuha # 重启服务 journalctl -u shuha # 查看系统日志(包含服务启动信息) 三、方案对比与选择建议 方案优点缺点适用场景nohup简单易用,无需额外配置无开机自启,管理不够规范临时测试、短期运行screen支持会话恢复,适合调试配置稍复杂,不支持开机自启开发环境、需要频繁交互的场景systemd稳定可靠,支持开机自启和重启配置相对复杂生产环境、长期运行的服务四、常见问题排查 程序后台运行后无法访问 检查程序是否监听0.0.0.0(而非127.0.0.1),确保外部可访问 确认服务器防火墙和云安全组已开放程序端口(如8080) 日志文件无内容 检查日志目录权限是否正确(程序是否有写入权限) 确认启动命令中的日志路径与程序实际输出路径一致 systemd服务启动失败 用systemctl status shuha查看具体错误 检查ExecStart路径是否正确,程序是否有执行权限(chmod +x shuha) 通过以上方案,可彻底解决Go程序关闭终端后停止运行的问题。根据实际场景选择合适的方案,既能保证程序稳定运行,又能简化管理成本。生产环境优先推荐systemd方案,兼顾稳定性和可维护性。