最近写一个http调用第三方接口的时候偶发的会爆这个错,我一直以为是编译的类错了,百度了n久都是说JSONARRAY的问题,总之废了快一天多时间,也没啥精力去看源码找bug,终于让我在这里找到答案了:http://luofei.me/?p=173 ,解决办法其实就是在返回的时候要指定泛型的类,没有返回的也用Result<Void>就可以了,另外贴一点经常用的工具防止原文链接失效:
启动ngrok的命令:
ngrok -config ngrok.yml 端口号
查看端口号占用:
1、使用lsof
lsof -i:端口号查看某个端口是否被占用
lsof -i:80
2、使用netstat
netstat -anp|grep 80
3、netstat常用命令
netstat -ntlp //查看当前所有tcp端口·
netstat -ntulp |grep 80 //查看所有80端口使用情况·
netstat -an | grep 3306 //查看所有3306端口使用情况·
<![CDATA[]]>和转义字符
被<![CDATA[]]>
这个标记所包含的内容将表示为纯文本,比如<![CDATA[<]]>
表示文本内容“<”
。
此标记用于xml文档中,我们先来看看使用转义符的情况。我们知道,在xml中,”<”
、”>”
、”&”
等字符是不能直接存入的,否则xml语法检查时会报错,如果想在xml中使用这些符号,必须将其转义为实体,如”<”
、”>”
、”&”
,这样才能保存进xml文档。
在使用程序读取的时候,解析器会自动将这些实体转换回”<”
、”>”
、”&”
。举个例子:
<age> age < 30 </age>
上面这种写法会报错,应该这样写:
<age> age < 30 </age>
值得注意的是:
(1)转义序列字符之间不能有空格;
(2) 转义序列必须以”;”结束;
(3) 单独出现的”&”不会被认为是转义的开始;
(4) 区分大小写。
在XML中,需要转义的字符有:
(1)& &
(2)< <
(3)> >
(4)" "
(5)' '
但是严格来说,在XML中只有”<”和”&”是非法的,其它三个都是可以合法存在的,但是,把它们都进行转义是一个好的习惯。
不管怎么样,转义前的字符也好,转义后的字符也好,都会被xml解析器解析,为了方便起见,使用<![CDATA[]]>
来包含不被xml解析器解析的内容。但要注意的是:
(1) 此部分不能再包含”]]>”
;
(2) 不允许嵌套使用;
(3)”]]>”
这部分不能包含空格或者换行。
最后,说说<![CDATA[]]>
和xml转移字符的关系,它们两个看起来是不是感觉功能重复了?
是的,它们的功能就是一样的,只是应用场景和需求有些不同:
(1)<![CDATA[]]>
不能适用所有情况,转义字符可以;
(2) 对于短字符串<![CDATA[]]>
写起来啰嗦,对于长字符串转义字符写起来可读性差;
(3) <![CDATA[]]>
表示xml解析器忽略解析,所以更快。
使用 PM2 管理nodejs进程
pm2 是一个带有负载均衡功能的Node应用的进程管理器.当你要把你的独立代码利用全部的服务器上的所有CPU,并保证进程永远都活着,0秒的重载, PM2是完美的。
它非常适合IaaS结构,但不要把它用于PaaS方案(随后将开发Paas的解决方案).和使用node index.js方式比较,优点:
1 一个命令窗口就可管理多个node服务器进程。而node命令多个进程就需要开多个窗口。
2 关闭命令窗口,node进程仍然会运行。而node命令运行的关闭窗口后,进程也就关闭了。
一 安装PM2
npm install -g pm2
二 用pm2 启动index.js
pm2 start index.js --name tank
--name tank是给这个进程取个名字
三 其他pm2命令
安装
npm install -g pm2
用法
npm install pm2 -g # 命令行安装 pm2
pm2 start app.js -i 4 #后台运行pm2,启动4个app.js
# 也可以把'max' 参数传递给 start
# 正确的进程数目依赖于Cpu的核心数目
pm2 start app.js --name my-api # 命名进程
pm2 list # 显示所有进程状态
pm2 monit # 监视所有进程
pm2 logs # 显示所有进程日志
pm2 stop all # 停止所有进程
pm2 restart all # 重启所有进程
pm2 reload all # 0秒停机重载进程 (用于 NETWORKED 进程)
pm2 stop 0 # 停止指定的进程
pm2 restart 0 # 重启指定的进程
pm2 startup # 产生 init 脚本 保持进程活着
pm2 web # 运行健壮的 computer API endpoint (http://localhost:9615)
pm2 delete 0 # 杀死指定的进程
pm2 delete all # 杀死全部进程
运行进程的不同方式:
pm2 start app.js -i max # 根据有效CPU数目启动最大进程数目
pm2 start app.js -i 3 # 启动3个进程
pm2 start app.js -x #用fork模式启动 app.js 而不是使用 cluster
pm2 start app.js -x -- -a 23 # 用fork模式启动 app.js 并且传递参数 (-a 23)
pm2 start app.js --name serverone # 启动一个进程并把它命名为 serverone
pm2 stop serverone # 停止 serverone 进程
pm2 start app.json # 启动进程, 在 app.json里设置选项
pm2 start app.js -i max -- -a 23 #在--之后给 app.js 传递参数
pm2 start app.js -i max -e err.log -o out.log # 启动 并 生成一个配置文件
你也可以执行用其他语言编写的app ( fork 模式):
pm2 start my-bash-script.sh -x --interpreter bash
pm2 start my-python-script.py -x --interpreter python
0秒停机重载:
这项功能允许你重新载入代码而不用失去请求连接。
注意:
仅能用于web应用
运行于Node 0.11.x版本
运行于 cluster 模式(默认模式)
pm2 reload all
CoffeeScript:
pm2 start my_app.coffee #这就是全部
PM2准备好为产品级服务了吗?
只需在你的服务器上测试
git clone https://github.com/Unitech/pm2.git
cd pm2
npm install # 或者 npm install --dev ,如果devDependencies 没有安装
npm test
mongodb:
LINUX环境下,可以通过查看端口27017的状态查看mongodb是否已经启动。
netstat -lanp | grep "27017"
可以看到已经启动了mongodb服务。
然后关闭mongodb服务
sudo service mongod stop
可以看到端口状态发生了变化
再开启服务(如果再次开启失败可以删除.lock文件再试)
sudo service mongod start
端口又变成了listen状态。
非正常关闭会有这个文件,把这个文件删了就行了
sql命令(用于清空某表的数据 且让自增的id重新从0开始):
truncate table 表名
Linux 对mysql远程连接的授权操作
//首先linux连接mysql数据库
mysql -uroot -p
//授权:
grant all on *.* to 'root'@'%' identified by '123456' with grant option; //允许账户root从任何主机连接到所有数据库(*.*)
grant all on test.* to 'user'@'%' identified by '123456' with grant option; //允许账户user从任何主机连接到test数据库(test.*)
//释放远程授权:
revoke all on *.* from 'user'@'%'; //禁止用户user从任何主机访问所有数据库
revoke all on test.* from 'user'@'%'; //禁止用户user从任何主机访问test数据库
flush privileges; //刷新系统授权表
linux连接mysql数据库去数据库的操作的一些基本命令
mysql -uroot -p //连接mysql数据库
//mysql其他命令:
show databases; //显示数据库
create database name; //创建数据库
use databasename; //选择数据库
drop database name //直接删除数据库,不提醒
show tables; //显示表
describe tablename; //显示具体的表结构
//select 中加上distinct去除重复字段
mysqladmin drop databasename //删除数据库前,有提示。
//显示当前mysql版本和当前日期
select version(),current_date;
Java Array、List、Set互相转化
1. Array、List、Set互转实例
1.1 Array、List互转
Array转List
String[] s = new String[]{"A", "B", "C", "D","E"};
List<String> list = Arrays.asList(s);
注意这里list里面的元素直接是s里面的元素( list backed by the specified array),换句话就是说:对s的修改,直接影响list。
s[0] ="AA";
System.out.println("list: " + list);
输出结果
list: [AA, B, C, D, E]
List转Array
String[] dest = list.toArray(new String[0]);//new String[0]是指定返回数组的类型
System.out.println("dest: " + Arrays.toString(dest));
输出结果
dest: [AA, B, C, D, E]
注意这里的dest里面的元素不是list里面的元素,换句话就是说:对list中关于元素的修改,不会影响dest。
list.set(0, "Z");
System.out.println("modified list: " + list);
System.out.println("dest: " + Arrays.toString(dest));
输出结果
modified list: [Z, B, C, D, E]
dest: [AA, B, C, D, E]
可以看到list虽然被修改了,但是dest数组没有没修改。
1.2 List、Set互转
因为List和Set都实现了Collection接口,且addAll(Collection<? extends E> c);方法,因此可以采用addAll()方法将List和Set互相转换;另外,List和Set也提供了Collection<? extends E> c作为参数的构造函数,因此通常采用构造函数的形式完成互相转化。
//List转Set
Set<String> set = new HashSet<>(list);
System.out.println("set: " + set);
//Set转List
List<String> list_1 = new ArrayList<>(set);
System.out.println("list_1: " + list_1);
和toArray()一样,被转换的List(Set)的修改不会对被转化后的Set(List)造成影响。
1.3 Array、Set互转
由1.1 1.2可完成Array和Set的互转
//array转set
s = new String[]{"A", "B", "C", "D","E"};
set = new HashSet<>(Arrays.asList(s));
System.out.println("set: " + set);
//set转array
dest = set.toArray(new String[0]);
System.out.println("dest: " + Arrays.toString(dest));
2.Arrays.asList() 和 Collection.toArray()
上述列出的互相转换离不开Arrays.asList()和Collection.toArray()两个重要的方法;
This method acts as bridge between array-based and collection-based APIs, in combination with Collection.toArray. The returned list is serializable and implements RandomAccess.
Arrays.asList()
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
这里出现的ArrayList<>并不是我们通常使用的java.util.ArrayList,因为java.util.ArrayList没有数组作为参数的构造函数。查看对应的源码发现,其实Arrays类的静态内部类。
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable
{
private static final long serialVersionUID = -2764017481108945198L;
private final E[] a;
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
@Override
public int size() {
return a.length;
}
@Override
public Object[] toArray() {
return a.clone();
}
@Override
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
int size = size();
if (a.length < size)
return Arrays.copyOf(this.a, size,
(Class<? extends T[]>) a.getClass());
System.arraycopy(this.a, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}
@Override
public E get(int index) {
return a[index];
}
@Override
public E set(int index, E element) {
E oldValue = a[index];
a[index] = element;
return oldValue;
}
@Override
public int indexOf(Object o) {
E[] a = this.a;
if (o == null) {
for (int i = 0; i < a.length; i++)
if (a[i] == null)
return i;
} else {
for (int i = 0; i < a.length; i++)
if (o.equals(a[i]))
return i;
}
return -1;
}
@Override
public boolean contains(Object o) {
return indexOf(o) != -1;
}
@Override
public Spliterator<E> spliterator() {
return Spliterators.spliterator(a, Spliterator.ORDERED);
}
@Override
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
for (E e : a) {
action.accept(e);
}
}
@Override
public void replaceAll(UnaryOperator<E> operator) {
Objects.requireNonNull(operator);
E[] a = this.a;
for (int i = 0; i < a.length; i++) {
a[i] = operator.apply(a[i]);
}
}
@Override
public void sort(Comparator<? super E> c) {
Arrays.sort(a, c);
}
}
可以看到,这个由Arrays类实现的另一个Arrays$ArrayList,对于java.util.ArrayList类来讲,是比较简单粗糙的类。
没有扩容机制;
无法在指定位置add(int index, E element),调用该方法会抛异常;
这些不同让这个ArrayList看起来实际上就是一个List-View的数组。
Collection.toArray()
虽然List、Set的具体实现类都对Collection.toArray()方法进行了不同程度的重写,但是大致都差不多。
这里选AbstractCollection.toArray()的实现:
public <T> T[] toArray(T[] a) {
// Estimate size of array; be prepared to see more or fewer elements
int size = size();
T[] r = a.length >= size ? a :
(T[])java.lang.reflect.Array
.newInstance(a.getClass().getComponentType(), size);//如果给定的参数T[] a的长度足够存放当前collection(list or set)的元素,则采用该参数来存放元素;否则则根据参数给定的类型反射生成一个数组;
//因此这里的参数T[] a有俩作用;第一:可能用作存放元素;第二:为返回数组提供类型
Iterator<E> it = iterator();
for (int i = 0; i < r.length; i++) {
if (! it.hasNext()) { // fewer elements than expected 集合的size少于给定的参数数组的长度
if (a == r) {
r[i] = null; // null-terminate 最后一个元素被设置为null,表明collection元素结束;
} else if (a.length < i) {
return Arrays.copyOf(r, i);
} else {
System.arraycopy(r, 0, a, 0, i);
if (a.length > i) {
a[i] = null;
}
}
return a;
}
r[i] = (T)it.next();
}
// more elements than expected
return it.hasNext() ? finishToArray(r, it) : r;
}
win10专业版激活方法
1. 先查看一下Win10正式专业版系统的激活状态:
点击桌面左下角的“Windows”按钮,从打开的扩展面板中依次点击“设置”-“更新和安全”,并切换到“激活”选项卡,在此就可以查看到当前系统的激活状态。如图,Win10正式专业版当前未激活
2. 在桌面左下角的“cortana”搜索框中输入“CMD”,待出现“命令提示符”工具时,右击选择“以管理员身份”运行。
3. 此时将“以管理员身份”打开“MSDOS”窗口,在此界面中,依次输出以下命令:
slmgr.vbs /upk
复制以上命令,并在MSDOW窗口中右击以粘贴此命令,按回车进行确定。
此时弹出窗口显未“已成功卸载了产品密钥”。
4. 接着输入以下命令:
slmgr /ipk W269N-WFGWX-YVC9B-4J6C9-T83GX
弹出窗口提示:“成功的安装了产品密钥”。
5. 继续输入以下命令:
slmgr /skms zh.us.to
弹出窗口提示:“密钥管理服务计算机名成功的设置为zh.us.to”。
6. 接下来输入以下命令:
slmgr /ato
此时将弹出窗口提示:“成功的激活了产品”。