vscode通过插件修改编辑器的内容

之前碰到一个需求是这样的:在vsocde编译器中检验用户输入的代码,如果出现中文字符,那么将其替换成相应的英文字符。
好了,进下来直接上代码:

1
2
3
4
5
6
7
8
const fs_1 = require("fs");
//读取文件内容,filePath为文件的路径,如:C:\aaa\bbb\ccc.cpp
var oldFileData = fs_1.readFileSync(filePath) + '';
//然后对齐进行替换
var newFileData = oldFileData.replace(/\’|\‘/g,"'").replace(/\“|\”/g,"\"").replace(/,/g,",").replace(/:/g,":")
.replace(/。/g,".").replace(/;/g,";").replace(/\【/g,"[").replace(/\】/g,"]").replace(/\{/g,"{").replace(/\}/g,"}");
//然后写入文件(此方法有问题)
//fs_1.writeFileSync(filePath, newFileData);

读取cpp文件也就是编辑器的代码,对其进行校验,替换字符,然后再将新的字符写入cpp文件,但是测试会出现问题,时常没法保存vscod编辑器的代码,经过反复测试我发现:
我将cpp文件的内容进行写入之后,磁盘的cpp文件的内容更换,但编辑器没有即时生效,如果这时保存的话会提示当前文件出现冲突,需要手动保存时无法保存,原因是编辑器没有即时生效,
所以我采取一种新的方法:就是不再新的内容写入cpp文件了,而是写入编辑器中,至此编辑器无冲突也可保存;
正确代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
const fs_1 = require("fs");
const vscode_1 = require("vscode");
//读取文件内容,filePath为文件的路径,如:C:\aaa\bbb\ccc.cpp
var oldFileData = fs_1.readFileSync(filePath) + '';
//然后对齐进行替换
var newFileData = oldFileData.replace(/\’|\‘/g,"'").replace(/\“|\”/g,"\"").replace(/,/g,",").replace(/:/g,":")
.replace(/。/g,".").replace(/;/g,";").replace(/\【/g,"[").replace(/\】/g,"]").replace(/\{/g,"{").replace(/\}/g,"}");
//核心代码
vscode_1.window.activeTextEditor.edit(editBuilder => {
// 从开始到结束,全量替换
const end = new vscode_1.Position(vscode_1.window.activeTextEditor.document.lineCount + 1, 0);
editBuilder.replace(new vscode_1.Range(new vscode_1.Position(0, 0), end), newFileData);
});

其实不管你的需求是什么,本文想要讲述的是这段核心代码,也就是通过这段代码将vscode编辑器的内容进行替换。

递归查找

很多时候,我们通过网络请求返回后台数据之后,需要在前端页面中显示,通常有一些嵌套多个数组的数据,我们称之为‘树形结构’数据,
而我们通常碰到搜索题目id查找对应的数据,又或者我们打开了一个题目,需要点击下一题的时候,我们往往需要通过id去获取题目这个对象;
下面array其实就是多个题目对象组成,我们直接上代码;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
var array = [
{
id: 1,
title:"a",
children:[{
id:2,
children:[]
}]
},

{
id:3,
title:"b",
children:[]
},

{
id:4,
title:"c",
children:[
{
id:5,
title:"c1",
children:[
{
id:6,
title:"c2",
children:[]
},

{
id:7,
title:"c3",
children:[]
}
]
}
]
}
];

方法一:
var returnedItem;

var find = function(arr, id){
    arr.forEach((item) => { 
         if(item.id==id)
         {        
             returnedItem = item;
             return item;
         }
         else if(item.children.length > 0)
         {
             find(item.children, id);                        
         }                   
    })
}

var item = find(array, 7);
console.log(returnedItem);

方法二:

var returnedItem;

    var find = function(arr, id){
        for (var a = 0; a < arr.length; a++) {
            if(arr[a].id == id)
             {
                 returnedItem = arr[a];
                 return item;
             }
             else if(arr[a].children != undefined && arr[a].children.length > 0)
             {
                 find(arr[a].children, id);
             }else {
             }
        }
    }

    var item = find(array, 7);
    console.log(returnedItem);

其中7为你输入的id,得到的是id为7的对象;returnedItem.id和returnedItem.title就是我们想要的数据;

html标签通过代码隐藏和显示

工作中我们常常会碰到这个一个需求:
当用户进行操作之后,通过在页面上提示信息;

首先我们在body中定义一个提示信息的元素:

1
<p id="submitResult"></p>

然后在script里的用户响应中显示结果:

1
2
3
4
5
6
//获取submitResult标签并赋值
var submitResult = document.getElementById('submitResult');
submitResult.innerHTML = '判题结果:' + data.results;
//显示结果五秒后关闭
$('#submitResult').show();
$('#submitResult').delay(5000).hide(0);

至此一个小需求完成了。

当然,我们还可以作很多优化,比如先判断标签是否隐藏
$(“#submitResult”).is(“:hidden”) 返回true,则标签被隐藏了;
如果 $(“#submitResult”).is(“:visible”) 返回true,则标签已经显示了。

通过css实现按钮高亮

本文通过改变css来实现按钮高亮效果
其实高亮只需增加一行代码,如下:
原css:

1
2
3
4
5
6
7
.monaco-workbench > .part.titlebar > .window-controls-container .window-minlogin {
height:100%;
width:45px;
background-color:#1E1E1E;
padding-right: -10px;
margin-right: 20px;
}

可以看到这个颜色是1E1E1E(灰色),然后增加一行代码即可,如下:

1
2
3
.monaco-workbench > .part.titlebar > .window-controls-container .window-minlogin:hover {
background-color:#68217A;
}

效果

JS文件相互调用

我们在写js代码的时候,常常会碰到两个js文件之间相互调用,直接上代码:
messageText.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//定义数组
var msgArray = [
{name: 'In function',value: '在函数'},
{name: 'was not declared in this scope',value: '没有在此范围内声明'},
];

//定义常量
var messageText = {

a_name : '张三',

b_name : '李四',

}
exports.msgArray = msgArray;
exports.messageText = messageText;

在A.js中调用messageText.js

1
2
3
4
5
6
const msg_1 = require("./messageText");
for(var i=0; i < msg_1.msgArray.length; i++)
{
var message = data1.replace(msg_1.msgArray[i].name, msg_1.msgArray[i].value);
data1 = message;
}

上面的例子中,我对data1这个字符串做了一个汉化处理,就是将数组中的name替换成value;
如果想要引用B.js中的常量,那么非常简单:

1
msg_1.messageText.a_name

这样即可得到B.js中a_name中的值了。

ts文件之间调用用法有些差别,如下:
messageText.ts

1
2
3
export class MessageText {
public static name: string = '张三';
}

在A.ts中调用js中调用messageText.ts

1
2
import { MessageText } from 'vs/workbench/api/common/messageText';//注意form ''是你项目中的目录
console.log(MessageText.name);

通过html链接启动电脑软件

我们常常看到通过链接打开电脑上的软件,比如点击迅雷链接打开迅雷软件,这些是怎么实现的呢。
简单来说就是:下载软件时,软件会注册命令到我们计算机的注册表里,命令里面填写的是软件所在计算机的路径,因此我们通过调用命令即可启动我们计算机的软件。
下面以vscode为例:
Ctrl+R打开运行,输入regedit进入注册表,找到vscode的注册命令所在位置,在HKEY_CLASSES_ROOT\vscode

HKEY_CLASSES_ROOT\vscode\shell\open\command里面编辑的就是计算机vscode的所在路径,这些下载软件时计算机都给我们编写好了,我们接下来调用即可。
新建一个html,如下:

1
2
3
4
5
<html>
<body>
<a href="vscode://">打开官方vscode</a>
</body>
</html>

代码中vscode就是注册表中HKEY_CLASSES_ROOT\vscode,这里名称必须保持一样才行。
接下来我们打开html,点击链接就可以打开软件了。
如果电脑软件没有配置注册表,我们也可以手动给软件配置:
在HKEY_CLASSES_ROOT中右击新建项,命名比如test,在test中新建项并命名shell,在shell中新建项命名open,最后在open中新建项命名command,其结构可以参考其他注册表的软件,在command中填入你需要启动的软件应用的路径,如:”C:\Users\user\AppData\Local\Programs\Code.exe”,然后在html里加上<a href="test://">打开</a>即可。

使用session控制web登录退出

今天给大家说一个session的问题,首先是session的使用方法:

使用

<% session().setAttribute(“isLogin”, “true”); %>

获取/逻辑判断

<% session.getAttribute(“isLogin”); %>

移除

<% session.removeAttribute(“isLogin”); %>
我是这样想的,在登录成功之后给session赋值,然后在主页或别的页面获取session做判断,如果session属性的值为空,那么就是未登录,然后跳转到登录页面,下面按照我自己的想法开始写:
首先我在login.jsp中登录之后赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<script type="text/javascript">
loginButton = function() {
var id = $("#id").val(); //jqury val()方法返回元素value属性
var password = $("#password").val();

if (id == '') {
$("#info").text("提示:学号不能为空");
} else if (password == '') {
$("#info").text("提示:密码不能为空");
} else {
$.ajax({
type : "POST",
url : "/books/StudentLoginServlet",
data : {
id : id,
password : password
},
dataType : "json",
success : function(data) {
if (data.code == "000000") {
<% session().setAttribute("isLogin", "true"); %>
window.location.href = "home.jsp?id=" + data.data.id;
} else {
$("#info").text(data.message);
}
}
});
}
}
</script>

然后home.jsp判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<body>
<%
out.print(session.getAttribute("isLogin"));
if (session.getAttribute("isLogin") == null || request.getParameter("id") == null)
{
response.sendRedirect("login.jsp");
}
String id = request.getParameter("id");
%>
<div style="display: flex">
<h3>
欢迎您:<%=id%></h3>
<form style="margin-left: 30px" action="exitLogin.jsp" method="post">
<button type="submit">退出</button>
</form>
</div>
</body>

最后是退出jsp

1
2
3
4
5
6
7
<body>
<%
//session.setAttribute("isLogin",null);
session.removeAttribute("isLogin");
response.sendRedirect("login.jsp");
%>
</body>

理论上这样写是可以的,但最终出现非常奇怪的问题,就是第一次登录是没有问题的,但home.jsp点击退出回到login.jsp之后,我直接进入home.jsp,按理是不能进入home的,因为我退出移除了session的”isLogin”属性值,但结果是可以进入home.jsp。
这很奇怪,我不知道我存在什么问题,这让我烦恼了半天,我在login.jsp中将session的”isLogin”输出,发现这个session的”isLogin”属性值显示是为null,但点击刷新之后这个session的”isLogin”值为true,然后在home.jsp中发现也是true,为什么会出现这种情况呢?刚开始我猜想是不是没有成功移除,我尝试了session.setAttribute(“isLogin”,null);、session.removeAttribute(“isLogin”);和session.invalidate();

最后我的解决方法是:去除login.jsp中的<% session().setAttribute(“isLogin”, “true”); %>代码,进入StudentLoginServlet中里面写为:request.getSession().setAttribute(“isLogin”, “true”);

这样,点击退出之后,session的”isLogin”为null,再刷新也是null,问题终于得到解决。

sql级联更新和级联删除

sql级联更新
执行更新book表失败
后来查找原因是book表被borrow引用了,所以数据库不知道book表更新borrow表要不要更新,所以我们需要进行级联更新,也就是book表更新,borrow表和其它引用了book表也更新外键。
book表

borrow表

级联更新
在创建表时就指定级联更新和级联删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
CREATE TABLE `book` (
  `ISBN` varchar(20NOT NULL,
  `book_name` varchar(50NOT NULL,
  `book_author` varchar(20NOT NULL,
  `book_pub` varchar(50DEFAULT NULL,
  `sort_id` int(11DEFAULT NULL,
  `book_record` varchar(255DEFAULT NULL,
  `book_price` decimal(10,0NOT NULL,
  `book_borrow` int(11DEFAULT '0',
  PRIMARY KEY (`ISBN`),
  KEY `sort_id` (`sort_id`),
  CONSTRAINT `book_ibfk_1` FOREIGN KEY (`sort_id`REFERENCES `book_sort` (`sort_id`)
ENGINE=InnoDB DEFAULT CHARSET=utf8

CREATE TABLE `borrow` (
  `id` int(11NOT NULL AUTO_INCREMENT,
  `ISBN` varchar(20NOT NULL,
  `s_id` varchar(20NOT NULL,
  `price` decimal(10,0NOT NULL,
  `book_name` varchar(50NOT NULL,
  `borrow_date` varchar(255DEFAULT NULL,
  `expect_return_date` varchar(255DEFAULT NULL,
  `return_date` varchar(255DEFAULT NULL,
  `book_borrow` int(11DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `s_id` (`s_id`),
  KEY `ISBN` (`ISBN`),
  CONSTRAINT `borrow_ibfk_1` FOREIGN KEY (`s_id`REFERENCES `student` (`s_id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `borrow_ibfk_2` FOREIGN KEY (`ISBN`REFERENCES `book` (`ISBN`) ON DELETE CASCADE ON UPDATE CASCADE
ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

如果是已经创建了数据表,那么先撤销外键约束

1
2
ALTER TABLE borrow
DROP FOREIGN KEY fk_borrow1 这里为你外键名比如constraint后面的名称

然后再重新增加约束

1
2
3
4
5
6
7
8
9
ALTER TABLE Orders
ADD CONSTRAINT fk_borrow1
FOREIGN KEY (s_id)
REFERENCES student(s_Id) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE Orders
ADD CONSTRAINT fk_borrow2
FOREIGN KEY (ISBN)
REFERENCES book(ISBN) ON DELETE CASCADE ON UPDATE CASCADE;

最后再执行更新

1
UPDATE book SET ISBN = '201905152321007', book_name = 'javascript', book_author = 'javascript作者', book_pub = 'javascript出版社', book_borrow = 1, sort_id = 1, book_record = '2019-05-24', book_price = 250 WHERE ISBN = '201905152321001';

即可成功更新book表,而borrow表中的ISBN也跟着更新。

Tomcat无法启动和访问项目出现404

首先我使用的是eclipse工具开发,Tomcat是9.0,之前项目启动使用Tomcat然后访问一直是可以的,昨天开始写Servlet,然后就想访问一下,结果Tomcat启动不起来了,网上大多说web.xml中配置的路径写的不对,其实如果你是new Servlet,eclipse默认会给你配置,那么配置路径是没有问题的,除非你改了Servlet类名,那么需要手动改一下。下面直接说解决方法:

Tomcat启动不了

如果项目(代码)本身没有问题,那么确认server locations中的server path和deply path是否一致,如图

我们在server locations中选择第二个,也就是Use Tomcat installation,同时Server Path是你下载Tomcat的路径,Deploy path是你Tomcat的webapps目录路径,我的是:C:\dev\tomcat\apache-tomcat-9.0.2\webapps,选择并保存,图片只显示webapps,但我们一定要选择绝对路径。
如果没法选择server locations,那么删除Tomcat重新配置即可选择。

项目访问为404

如果你的Tomcat可以访问,项目访问为404,那么很可能是你的项目结构问题,如http://localhost:8080/books/出现404,那么在web中welcome-file这一项是指定你访问的默认页面,如:login.jsp,那么你访问就是http://localhost:8080/books/login.jsp,请注意是否存在login.jsp文件,路径是否在webapp目录下。如果仍然出现404,那么可以新建一个工作区试试。

Hexo不显示本地图片解决方案

查看主页配置文件_config.yml 里的post_asset_folder:这个选项设置为true还是false,
如果是true,那么会创建文章时会自动生成文章同名文件夹,这个看你具体设置。
但我发现,如果你设置为true,引用本地图片就是:
![](xxxx/图片名.jpg) xxxx为你文件夹名
但如果是false,那么你手动新建的同名文件夹,如果
![](xxxx/图片名.jpg)无法显示图片,
需要改为:
![](a.jpg)
也就是不用前缀xxxx/,这样虽然在本地markdown无法预览,但部署到远程是看得见的。