继续上次的操作系统课设,这次需要设计一个简单的任务管理器,大部分人选择GTK来实现,我剑走偏锋,使用Qt来完成这个任务。

用户和应用程序可以通过/proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是动态从系统内核读出所需信息并提交的。

我们要显示系统信息,只需进行相应的文件操作就行了。

首先需要下载一份Qt的SDK,这是Qt的英文官网:http://qt.nokia.com/,当然也有中文版的:http://qt.nokia.com/title-cn/

别问我为什么有个nokia,那是因为Qt是诺基亚开发的一个跨平台的C++图形用户界面应用程序框架。

Qt商业版只能试用30天,不过有GPL版的,可以免费使用。官网上还有一个非常不错的免费Qt集成开发环境Qt Creator IDE。我使用的就是这个软件:

打开相应的文件,读取所需要的信息,将其显示在控件上就可以了。

我采用的是Qt来实现图形界面。

工程文件夹:

编译完成后的实现效果:

这个实验总的来讲还是比较简单的,源码如下:

main.cpp

  1. #include <QtGui/QApplication>
  2. #include "mainwindow.h"
  3. int main(int argc, char *argv[])
  4. {
  5. QApplication a(argc, argv); //应用程序类,每个应用程序有且只有一个
  6. MainWindow w; //实例化MainWindow类
  7. w.show(); //显示界面
  8. return a.exec(); //进入应用程序的循环中,直到程序退出
  9. }

mainwindow.h

  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3. #include <QMainWindow>
  4. namespace Ui {
  5. class MainWindow;
  6. }
  7. class MainWindow : public QMainWindow
  8. {
  9. Q_OBJECT
  10. public:
  11. explicit MainWindow(QWidget *parent = 0);
  12. ~MainWindow();
  13. private:
  14. Ui::MainWindow *ui; //界面资源类,所有的界面元素都是通过该类来调用
  15. QTimer *timer; //计时器
  16. private slots:
  17. void on_pushButton_pkill_clicked();
  18. void on_pushButton_prefresh_clicked();
  19. void on_pushButton_Model_install_clicked();
  20. void on_pushButton_Model_remove_clicked();
  21. void on_pushButton_Model_refresh_clicked();
  22. void on_pushButton_reboot_clicked();
  23. void on_pushButton_halt_clicked();
  24. void on_tabWidget_INFO_currentChanged(int index);
  25. void timer_update_currentTabInfo();
  26. //显示tab中的内容
  27. void show_tabWidgetInfo(int index);
  28. };
  29. #endif // MAINWINDOW_H

mainwindow.cpp

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. #include <QFile>
  4. #include <QMessageBox>
  5. #include <QDir>
  6. #include <QListWidget>
  7. #include <QListWidgetItem>
  8. #include <QStringList>
  9. #include <QTimer>
  10. int a0 = 0, a1 = 0, b0 = 0, b1 = 0;
  11. MainWindow::MainWindow(QWidget *parent) : //构造函数,初始化ui,计时器
  12. QMainWindow(parent),
  13. ui(new Ui::MainWindow)
  14. {
  15. ui->setupUi(this);
  16. timer = new QTimer(this);
  17. QWidget::connect( timer, SIGNAL( timeout() ), this, SLOT( timer_update_currentTabInfo() ) );
  18. QWidget::connect( ui->tabWidget_INFO, SIGNAL( currentChanged() ),
  19. this, SLOT( on_tabWidget_currentChanged() ) );
  20. timer->start(1000);
  21. }
  22. MainWindow::~MainWindow()
  23. {
  24. delete ui;
  25. delete timer;
  26. }
  27. void MainWindow::timer_update_currentTabInfo()
  28. {
  29. int index = ui->tabWidget_INFO->currentIndex();
  30. //定时器只刷新内存tab页面,用于进度条动态显示
  31. if (index == 0)
  32. {
  33. show_tabWidgetInfo(index);
  34. }
  35. }
  36. void MainWindow::show_tabWidgetInfo(int index)
  37. {
  38. QString tempStr; //读取文件信息字符串
  39. QFile tempFile; //用于打开系统文件
  40. int pos; //读取文件的位置
  41. if (index == 0) //内存資源
  42. {
  43. tempFile.setFileName("/proc/meminfo"); //打开内存信息文件
  44. if ( !tempFile.open(QIODevice::ReadOnly) )
  45. {
  46. QMessageBox::warning(this, tr("warning"), tr("The meminfo file can not open!"), QMessageBox::Yes);
  47. return ;
  48. }
  49. QString memTotal;
  50. QString memFree;
  51. QString memUsed;
  52. QString swapTotal;
  53. QString swapFree;
  54. QString swapUsed;
  55. int nMemTotal, nMemFree, nMemUsed, nSwapTotal, nSwapFree, nSwapUsed;
  56. while (1)
  57. {
  58. tempStr = tempFile.readLine();
  59. pos = tempStr.indexOf("MemTotal");
  60. if (pos != -1)
  61. {
  62. memTotal = tempStr.mid(pos+10, tempStr.length()-13);
  63. memTotal = memTotal.trimmed();
  64. nMemTotal = memTotal.toInt()/1024;
  65. }
  66. else if (pos = tempStr.indexOf("MemFree"), pos != -1)
  67. {
  68. memFree = tempStr.mid(pos+9, tempStr.length()-12);
  69. memFree = memFree.trimmed();
  70. nMemFree = memFree.toInt()/1024;
  71. }
  72. else if (pos = tempStr.indexOf("SwapTotal"), pos != -1)
  73. {
  74. swapTotal = tempStr.mid(pos+11, tempStr.length()-14);
  75. swapTotal = swapTotal.trimmed();
  76. nSwapTotal = swapTotal.toInt()/1024;
  77. }
  78. else if (pos = tempStr.indexOf("SwapFree"), pos != -1)
  79. {
  80. swapFree = tempStr.mid(pos+10,tempStr.length()-13);
  81. swapFree = swapFree.trimmed();
  82. nSwapFree = swapFree.toInt()/1024;
  83. break;
  84. }
  85. }
  86. nMemUsed = nMemTotal - nMemFree;
  87. nSwapUsed = nSwapTotal - nSwapFree;
  88. memUsed = QString::number(nMemUsed, 10);
  89. swapUsed = QString::number(nSwapUsed, 10);
  90. memFree = QString::number(nMemFree, 10);
  91. memTotal = QString::number(nMemTotal, 10);
  92. swapFree = QString::number(nSwapFree, 10);
  93. swapTotal = QString::number(nSwapTotal, 10);
  94. ui->label_RAM_Used->setText(memUsed+" MB");
  95. ui->label_RAM_Left->setText(memFree+" MB");
  96. ui->label_RAM_Total->setText(memTotal+" MB");
  97. ui->label_SWAP_Used->setText(swapUsed+" MB");
  98. ui->label_SWAP_Left->setText(swapFree+" MB");
  99. ui->label_SWAP_Total->setText(swapTotal+" MB");
  100. ui->progressBar_RAM->setValue(nMemUsed*100/nMemTotal);
  101. ui->progressBar_SWAP->setValue(nSwapUsed*100/nSwapTotal);
  102. tempFile.close(); //关闭内存信息文件
  103.   //wsj这段计算cpu使用率的方法有问题,使用另一篇中的方法:https://www.cnblogs.com/liushui-sky/p/9258101.html
  104. int tt = 2; //取2个点采样计算cpu当前利用律
  105. int cpuInfo[2][7];
  106. int cpuTotal[2][2];
  107. while (tt)
  108. {
  109. tempFile.setFileName("/proc/stat"); //打开CPU使用状态信息
  110. if ( !tempFile.open(QIODevice::ReadOnly) )
  111. {
  112. QMessageBox::warning(this, tr("warning"), tr("The stat file can not open!"), QMessageBox::Yes);
  113. return;
  114. }
  115. tempStr = tempFile.readLine();
  116. for (int i = 0; i < 7; i++)
  117. {
  118. cpuInfo[2-tt][i] = tempStr.section(" ", i+1, i+1).toInt();
  119. cpuTotal[1][2-tt] += cpuInfo[2-tt][i];
  120. if (i == 3)
  121. {
  122. cpuTotal[0][2-tt] += cpuInfo[2-tt][i];
  123. }
  124. }
  125. tt--;
  126. tempFile.close(); //关闭stat文件
  127. }
  128. int a = cpuTotal[0][1] - cpuTotal[0][0];
  129. int b = cpuTotal[1][1] - cpuTotal[1][0];
  130. if (a < 0)
  131. {
  132. a = -a;
  133. }
  134. if (b < 0)
  135. {
  136. b = -b;
  137. }
  138. ui->progressBar_CPU->setValue(a*100/b);
  139. tempFile.setFileName("/proc/stat");
  140. if ( !tempFile.open(QIODevice::ReadOnly) )
  141. {
  142. QMessageBox::warning(this, tr("warning"), tr("The stat file can not open!"), QMessageBox::Yes);
  143. return;
  144. }
  145. tempStr = tempFile.readLine();
  146. a0 = a1;
  147. b0 = b1;
  148. a1 = b1 = 0;
  149. int gg;
  150. for (int i = 0; i < 7; i++)
  151. {
  152. b1 += tempStr.section(" ", i+2, i+2).toInt();
  153. gg = b1;
  154. if (i == 3)
  155. {
  156. a1 += tempStr.section(" ", i+2, i+2).toInt();
  157. }
  158. }
  159. int m, n;
  160. m = a1 - a0;
  161. n = b1 - b0;
  162. if (m < 0)
  163. {
  164. m = -m;
  165. }
  166. if (n < 0)
  167. {
  168. n = -n;
  169. }
  170. ui->progressBar_CPU->setValue( (n-m)*100/n );
  171. tempFile.close(); //关闭stat文件
  172. }
  173. else if (index == 1) //进程信息
  174. {
  175. ui->listWidget_process->clear();
  176. QDir qd("/proc");
  177. QStringList qsList = qd.entryList();
  178. QString qs = qsList.join("\n");
  179. QString id_of_pro;
  180. bool ok;
  181. int find_start = 3;
  182. int a, b;
  183. int nProPid; //进程PID
  184. int number_of_sleep = 0, number_of_run = 0, number_of_zombie = 0;
  185. int totalProNum = 0; //进程总数
  186. QString proName; //进程名
  187. QString proState; //进程状态
  188. QString proPri; //进程优先级
  189. QString proMem; //进程占用内存
  190. QListWidgetItem *title = new QListWidgetItem("PID\t" + QString::fromUtf8("名称") + "\t\t" +
  191. QString::fromUtf8("状态") + "\t" +
  192. QString::fromUtf8("优先级") + "\t" +
  193. QString::fromUtf8("占用内存"), ui->listWidget_process);
  194. //循环读取进程
  195. while (1)
  196. {
  197. //获取进程PID
  198. a = qs.indexOf("\n", find_start);
  199. b = qs.indexOf("\n", a+1);
  200. find_start = b;
  201. id_of_pro = qs.mid(a+1, b-a-1);
  202. totalProNum++;
  203. nProPid = id_of_pro.toInt(&ok, 10);
  204. if(!ok)
  205. {
  206. break;
  207. }
  208. //打开PID所对应的进程状态文件
  209. tempFile.setFileName("/proc/" + id_of_pro + "/stat");
  210. if ( !tempFile.open(QIODevice::ReadOnly) )
  211. {
  212. QMessageBox::warning(this, tr("warning"), tr("The pid stat file can not open!"), QMessageBox::Yes);
  213. return;
  214. }
  215. tempStr = tempFile.readLine();
  216. if (tempStr.length() == 0)
  217. {
  218. break;
  219. }
  220. a = tempStr.indexOf("(");
  221. b = tempStr.indexOf(")");
  222. proName = tempStr.mid(a+1, b-a-1);
  223. proName.trimmed(); //删除两端的空格
  224. proState = tempStr.section(" ", 2, 2);
  225. proPri = tempStr.section(" ", 17, 17);
  226. proMem = tempStr.section(" ", 22, 22);
  227. switch ( proState.at(0).toLatin1() )
  228. {
  229. case 'S':   number_of_sleep++; break; //Sleep
  230. case 'R':   number_of_run++; break; //Running
  231. case 'Z':   number_of_zombie++; break; //Zombie
  232. default :   break;
  233. }
  234. if (proName.length() >= 12)
  235. {
  236. QListWidgetItem *item = new QListWidgetItem(id_of_pro + "\t" +
  237. proName + "\t" +
  238. proState + "\t" +
  239. proPri + "\t" +
  240. proMem, ui->listWidget_process);
  241. }
  242. else
  243. {
  244. QListWidgetItem *item = new QListWidgetItem(id_of_pro + "\t" +
  245. proName + "\t\t" +
  246. proState + "\t" +
  247. proPri + "\t" +
  248. proMem, ui->listWidget_process);
  249. }
  250. }
  251. QString temp;
  252. temp = QString::number(totalProNum, 10);
  253. ui->label_pNum->setText(temp);
  254. temp = QString::number(number_of_run, 10);
  255. ui->label_pRun->setText(temp);
  256. temp = QString::number(number_of_sleep, 10);
  257. ui->label_pSleep->setText(temp);
  258. temp = QString::number(number_of_zombie, 10);
  259. ui->label_pZombie->setText(temp);
  260. tempFile.close(); //关闭该PID进程的状态文件
  261. }
  262. else if (index == 2) //模块信息
  263. {
  264. ui->listWidget_model->clear();
  265. tempFile.setFileName("/proc/modules"); //打开模块信息文件
  266. if ( !tempFile.open(QIODevice::ReadOnly) )
  267. {
  268. QMessageBox::warning(this, tr("warning"), tr("The modules file can not open!"), QMessageBox::Yes);
  269. return ;
  270. }
  271. //设置模块首行项目
  272. QListWidgetItem *title = new QListWidgetItem( QString::fromUtf8("名称") + "\t\t\t" +
  273. QString::fromUtf8("使用内存数") + "\t\t" +
  274. QString::fromUtf8("使用次數"), ui->listWidget_model);
  275. QString mod_Name, mod_Mem, mod_Num;
  276. //循环读取文件内容,查找需要的信息
  277. while (1)
  278. {
  279. tempStr = tempFile.readLine();
  280. if (tempStr.length() == 0)
  281. {
  282. break;
  283. }
  284. mod_Name = tempStr.section(" ", 0, 0);
  285. mod_Mem = tempStr.section(" ", 1, 1);
  286. mod_Num = tempStr.section(" ", 2, 2);
  287. if (mod_Name.length() > 10)
  288. {
  289. QListWidgetItem *item = new QListWidgetItem(mod_Name + "\t\t" +
  290. mod_Mem + "\t\t" +
  291. mod_Num, ui->listWidget_model);
  292. }
  293. else
  294. {
  295. QListWidgetItem *item = new QListWidgetItem(mod_Name + "\t\t\t" +
  296. mod_Mem + "\t\t" +
  297. mod_Num, ui->listWidget_model);
  298. }
  299. }
  300. tempFile.close(); //关闭模块信息文件
  301. }
  302. else if (index == 3) //系统信息
  303. {
  304. //int ok;
  305. tempFile.setFileName("/proc/cpuinfo"); //打开CPU信息文件
  306. if ( !tempFile.open(QIODevice::ReadOnly) )
  307. {
  308. QMessageBox::warning(this, tr("warning"), tr("The cpuinfo file can not open!"), QMessageBox::Yes);
  309. return;
  310. }
  311. //循环读取文件内容,查找需要的信息
  312. while (1)
  313. {
  314. tempStr = tempFile.readLine();
  315. pos = tempStr.indexOf("model name");
  316. if (pos != -1)
  317. {
  318. pos += 13; //跳过前面的"model name:"所占用的字符
  319. QString *cpu_name = new QString( tempStr.mid(pos, tempStr.length()-13) );
  320. ui->label_CPUName->setText(*cpu_name);
  321. }
  322. else if (pos = tempStr.indexOf("vendor_id"), pos != -1)
  323. {
  324. pos += 12; //跳过前面的"vendor_id:"所占用的字符
  325. QString *cpu_type = new QString( tempStr.mid(pos, tempStr.length()-12) );
  326. ui->label_CPUType->setText(*cpu_type);
  327. }
  328. else if (pos = tempStr.indexOf("cpu MHz"), pos != -1)
  329. {
  330. pos += 11; //跳过前面的"cpu MHz:"所占用的字符
  331. QString *cpu_frq = new QString( tempStr.mid(pos, tempStr.length()-11) );
  332. double cpufrq = cpu_frq->toDouble(); //4核CPU
  333. cpu_frq->setNum(cpufrq*4);
  334. ui->label_CPUFrequency->setText(*cpu_frq + " HZ");
  335. }
  336. else if (pos = tempStr.indexOf("cache size"), pos!=-1)
  337. {
  338. pos += 13; //跳过前面的"cache size:"所占用的字符
  339. QString *cache_size = new QString( tempStr.mid(pos, tempStr.length()-16) );
  340. int cachesize = cache_size->toInt(); //4核CPU
  341. cache_size->setNum(cachesize*4);
  342. ui->label_CatheCapacity->setText(*cache_size + " KB");
  343. }
  344. else //跳过其他的内容
  345. {
  346. }
  347. }
  348. tempFile.close(); //关闭CPU信息文件
  349. //打开操作系统信息文件
  350. tempFile.setFileName("/proc/version");
  351. if ( !tempFile.open(QIODevice::ReadOnly) )
  352. {
  353. QMessageBox::warning(this, tr("warning"), tr("The version file can not open!"), QMessageBox::Yes);
  354. return ;
  355. }
  356. tempStr = tempFile.readLine();
  357. pos = tempStr.indexOf("version");
  358. QString *os_version = new QString( tempStr.mid(0, pos-1) );
  359. ui->label_SystemType->setText(*os_version);
  360. int pos1 = tempStr.indexOf("(");
  361. QString *os_type = new QString( tempStr.mid(pos, pos1-pos-1) );
  362. ui->label_SystemVersion->setText(*os_type);
  363. pos = tempStr.indexOf("gcc version");
  364. pos1 = tempStr.indexOf("#");
  365. QString *gcc_info = new QString( tempStr.mid(pos+12, pos1-pos-14) );
  366. ui->label_GCCVersion->setText(*gcc_info);
  367. tempFile.close(); //关闭操作系统信息文件
  368. }
  369. else //说明
  370. {
  371. }
  372. return;
  373. }
  374. void MainWindow::on_pushButton_halt_clicked()
  375. {
  376. system("halt");
  377. }
  378. void MainWindow::on_pushButton_reboot_clicked()
  379. {
  380. system("reboot");
  381. }
  382. void MainWindow::on_tabWidget_INFO_currentChanged(int index)
  383. {
  384. show_tabWidgetInfo(index); //显示tab中的内容
  385. return ;
  386. }
  387. void MainWindow::on_pushButton_pkill_clicked()
  388. {
  389. //获得进程号
  390. QListWidgetItem *item = ui->listWidget_process->currentItem();
  391. QString pro = item->text();
  392. pro = pro.section("\t", 0, 0);
  393. system("kill " + pro.toLatin1());
  394. QMessageBox::warning(this, tr("kill"), QString::fromUtf8("该进程已被杀死!"), QMessageBox::Yes);
  395. //回到进程信息tab表
  396. show_tabWidgetInfo(1);
  397. }
  398. void MainWindow::on_pushButton_prefresh_clicked()
  399. {
  400. show_tabWidgetInfo(1);
  401. }
  402. void MainWindow::on_pushButton_Model_install_clicked()
  403. {
  404. show_tabWidgetInfo(2); //安装模块还不知道如何实现
  405. }
  406. void MainWindow::on_pushButton_Model_remove_clicked()
  407. {
  408. show_tabWidgetInfo(2); //卸载模块还不知道如何实现
  409. }
  410. void MainWindow::on_pushButton_Model_refresh_clicked()
  411. {
  412. show_tabWidgetInfo(2);
  413. }

转自http://blog.51cto.com/rangercyh/521262

linux系统Qt实现简单的任务管理器的更多相关文章

  1. 使用SecureCRT操作linux系统时候的简单设置

    因为第一次访问一台虚拟机的时候会出现这样的情况;   底色为白色和乱码的情况 需要在选项----->会话选项中进行一些设置 用来解决乱码问题的这个设置为:

  2. 直接远程下载或上传文件到linux系统中的简单办法

    如果执行sz 或者rz 没有这个命令,则安装lrzsz包执行:yum install lrzsz 等待安装完毕,然后一直输入Y即可. sz:将选定的文件发送(send)到本地机器 -a 以文本方式传输 ...

  3. 查看当前linux系统位数

    linux系统也有位数之分,所以在linux上安装一些软件,比如jdk之类的就需要注意下版本. 查看linux系统位数最简单的命令(这里以redhat为例,不同版本linux命令也许不同) 命令1:g ...

  4. Linux基础教程(一)——Linux系统简介

    Linux的概述 Linux是基于Unix的开源免费的操作系统,由于系统的稳定性和安全性几乎成为程序代码运行的最佳系统环境.Linux是由Linus Torvalds(林纳斯·托瓦兹)起初开发的,由于 ...

  5. Linux 系统报错 rcu_preempt detected stalls on CPUs/tasks

    说在前面的一些废话: 这是什么错误我不知道,为什么出现我不知道! 那为什么还要把他写出来了,只是因为这个错误遇到了,而且浪费了我很多时间和精力. 故事留给自己看,解决办法就是,重新升级一下Linux系 ...

  6. 读书笔记之Linux系统编程与深入理解Linux内核

    前言 本人再看深入理解Linux内核的时候发现比较难懂,看了Linux系统编程一说后,觉得Linux系统编程还是简单易懂些,并且两本书都是讲Linux比较底层的东西,只不过侧重点不同,本文就以Linu ...

  7. 学习Linux系统的方法经验

    Linux系统是一个开源的高效的以命令行为主的操作系统,主要用于服务器操作系统领域.对于Linux操作系统更多详细准确的解释大家可以网上找到<Linux就该这么学>的第0章介绍的比较详细: ...

  8. Linux内核设计第三周——构造一个简单的Linux系统

    Linux内核设计第三周 ——构造一个简单的Linux系统 一.知识点总结 计算机三个法宝: 存储程序计算机 函数调用堆栈 中断 操作系统两把宝剑: 中断上下文的切换 进程上下文的切换 linux内核 ...

  9. 《Linux内核分析》第三周 构建一个简单的Linux系统MenuOS

    [刘蔚然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK THREE ...

随机推荐

  1. 模态推出 全屏 隐藏tabbar

    SearchVC * vc = [[SearchVC alloc] init]; /* 底部向上  UIModalTransitionStyleCoverVertical // 淡入     UIMo ...

  2. C++生成斐波拉其数列

    该方法作为一种演示功能左右,运行较慢. #include <iostream> using namespace std; class Fibonacci{ public: int a, b ...

  3. Modelsim添加Lattice库

    Step 1 安装好modelsim,并将modelsim的目录添加到系统PATH中. (确认方法:在任意位置同时按下Shift+鼠标右键,在出来的菜单里选择“在此处打开命令窗口”,然后输入vsim, ...

  4. Sql Server 查询库表记录数

    ), RowCnt INT) EXEC sp_MSforeachtable 'INSERT INTO #temp SELECT ''?'', COUNT(*) FROM ?' desc DROP TA ...

  5. latex基本语法

    一直想着学会latex,但是自学起来太麻烦,总是出现各种不理解的错误,也没那么多时间钻研,就学了忘,忘了再学,这里就先摘录下它的基本命令吧.学好了是一件利器!(虽然不常用,但要尽量学会) LaTex基 ...

  6. 监听的instance status blocked分析

    对于处于NOMOUNT状态的数据库,PMON还没有将服务注册到监听上,这个时候服务的状态是BLOCKED的,对于来自远程的任何连接都会报ORA-12528错误.如下: [oracle@dbtest ~ ...

  7. Animation.setFillAfter and Animation.setFillBefore的作用

    转:http://blog.csdn.net/yangweigbh/article/details/9788531 setFillAfter(boolean fillAfter)  在Android ...

  8. STM32内部flash存储小数——别样的C语言技巧

    今天在进行STM32内部falsh存储的时候,发现固件库历程的函数原型是这样的: 第一个是地址,在我的STM32中是2K一页的,第二个是要写入的数据. 问题就来了,存储一个小数该怎么办呢?固件库给的是 ...

  9. JAVA-JSP内置对象之response对象实现页面跳转

    相关资料:<21天学通Java Web开发> response对象 实现页面跳转1.可以通过response对象的sendRedirect()方法设置页面重定向,从而实现页面跳转.2.这种 ...

  10. mysql防止误删除的方法

    为了防止在更新和删除的时候,没有写where条件而对全部数据进行操作,mysql提供了一个参数来防止此情况的发生 需要在启动mysql的时候,增加参数--i-am-a-dummy含义是我是新手,或者使 ...