EricZeng

  • 首页

  • 分类

  • 标签

  • 归档

  • 站点地图

  • 关于

  • 搜索

使用IDE远程调试

发表于 2019-08-21 分类于 开发工具

以被调试jar包项目为例,使用IDEA/Eclipse对jar包进行远程调试。

IDEA

版本:IntelliJ IDEA 2019.1.2 (Ultimate Edition)

启动被调试jar包时使用如下命令:

1
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 -jar XXX.jar

其中XXX.jar是被调试项目的jar包。
打开IDEA,依次点击Run->Debug Configurations,点击Run/Debug Configurations对话框左上角的“+”号,选择Remote。根据需要修改Host和module如下图所示:


保存配置之后,点击Debug即可。

Eclipse

版本:Eclipse Oxygen 2.2.100.v20170612-0950

启动时使用如下命令:

1
java -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000 -jar XXX.jar

打开Eclipse,依次点击Run->Debug Configurations,鼠标右击Remote Java Application->New。如下图所示,表单必填项有Connect中的Project和Host,其余的Name、Port根据需要进行修改,端口号与被调试项目一致即可。

img

启动Debug运行刚刚创建的“Remote Debug”即可。

fastjson自带JsonPath与json-path比较

发表于 2019-08-07 分类于 java

场景

fastjson从1.2版本开始支持JsonPath语法,但是在部分情境下还是无法很好的支持。例如下面的json结构:

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
{
"store": {
"book": [{
"title": "Java虚拟机",
"price": 20
}, {
"title": "Head First 设计模式",
"price": 72
}, {
"title": "重构:改善既有代码的设计",
"isbn": "123",
"price": 38
}, {
"title": "Spring实践4",
"isbn": "321",
"price": 32
}, {
"title": "图解HTTP",
"isbn": "543",
"price": 25
}],
"bicycle": {
"color": "red",
"price": 219
}
}
}

需要取出book中的title和price字段,理想情况是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[{
"title": "Java虚拟机",
"price": 20
}, {
"title": "Head First 设计模式",
"price": 72
}, {
"title": "重构:改善既有代码的设计",
"price": 38
}, {
"title": "Spring实践4",
"price": 32
}, {
"title": "图解HTTP",
"price": 25
}]

测试

引入fastjson/json-path版本如下:

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.4.0</version>
</dependency>

java代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import com.alibaba.fastjson.JSONPath;
import com.jayway.jsonpath.JsonPath;

public class JsonPathTest {

public static void main(String[] args) {
String json = "{\"store\": {\"book\": [{\"title\": \"Java虚拟机\",\"price\": 20}, {\"title\": \"Head First 设计模式\",\"price\": 72}, {\"title\": \"重构:改善既有代码的设计\",\"isbn\": \"123\",\"price\": 38}, {\"title\": \"Spring实践4\",\"isbn\": \"321\",\"price\": 32}, {\"title\": \"图解HTTP\",\"isbn\": \"543\",\"price\": 25}],\"bicycle\": {\"color\": \"red\",\"price\": 219}}}";

String jsonPath = "$['store']['book'][:-1]['price','title']";
Object obj = JSONPath.read(json, jsonPath);
System.out.println(obj);

jsonPath = "$.store.book.[*].['title', 'price']";
obj = JsonPath.parse(json).read(jsonPath);
String str = JSONObject.toJSONString(obj);
System.out.println(str);
}
}

测试结果:

[[20,72,38,32,25], ["Java虚拟机","Head First 设计模式","重构:改善既有代码的设计","Spring实践4","图解HTTP"]]
[{"title":"Java虚拟机","price":20},{"title":"Head First 设计模式","price":72},{"title":"重构:改善既有代码的设计","price":38},{"title":"Spring实践4","price":32},{"title":"图解HTTP","price":25}]

从结果上看json-path可以实现json带list结构的结果筛选,而fastjson只提取了两个列表(也可能我的语法不对,但是以目前的版本,我查了很多资料都没有找到一个更好的语法实现,如果有请联系我)。

参考资料

  1. fastjson对JSONPath的官方教程
  2. Jayway JsonPath
  3. GitRepo

J-IM启动

发表于 2019-08-05 更新于 2019-08-07 分类于 即时通讯

开源社区:Gitee

下载J-IM源码,目前(2019.8.1)最新版本(v2.6.0)的J-IM没有上传到Maven仓库中,需要自己打包。作为一个Java开发人员,我相信你本地安装了Maven而且配置了环境变量。下载源码后进入jim-parent文件夹执行如下命令:

1
2
mvn clean package -U -Dmaven.test.skip=true
# Maven命令解释: 打包并跳过测试类的编译

或者直接双击jim-parent/install.bat,该脚本实际执行如下命令:

1
2
call mvn clean install
# 该命令会将打好的包存放到本地Maven仓库里,请悉知

J-IM提供了简单的client/server端演示Demo,当然本文主要关心的是服务端如何启动。该Demo项目名为jim-server-demo,进入该项目的target目录找到刚刚打好的jar包,如:jim-server-demo-2.6.0v20190114-RELEASE.jar。

启动

jar包启动的通常做法是执行如下命令:

1
java -jar jim-server-demo-2.6.0v20190114-RELEASE.jar

但是执行后会报如下异常:

1
jim-server-demo-2.6.0.v20190114-RELEASE.jar中没有主清单属性

打开jar包里的META-INF/MANIFEST.MF文件会发现缺失启动类。解决办法是在pom里添加插件:

jar/dependency插件

配置如下:

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
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>org.jim.server.demo.ImServerDemoStart</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>

再次启动就可以啦:

1
java -jar jim-server-demo-2.6.0.v20190114-RELEASE.jar

这样使用有个限制,拷贝jar包时需要带lib文件夹。

assembly插件

配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>org.jim.server.demo.ImServerDemoStart</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<!--下面是为了使用 mvn package命令,如果不加则使用mvn assembly-->
<executions>
<execution>
<id>make-assemble</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>

mvn打包后生成jim-server-demo-2.6.0.v20190114-RELEASE.jar和jim-server-demo-2.6.0.v20190114-RELEASE-jar-with-dependencies.jar两个jar包,后面那个包将依赖的jar一起打包,任何位置直接使用java -jar即可。

IDE启动

直接启动main方法。

SpringBoot集成

J-IM启动类继承org.springframework.boot.CommandLineRunner接口,实现run()方法:

1
2
3
4
5
6
7
public class JimStarter implements CommandLineRunner {

@Override
public void run(String... args) {
// J-IM启动代码
}
}

参考资料

  1. jar包中META-INF文件作用
  2. java -cp & java jar的区别

Eclipse查看jar包源码

发表于 2019-07-31 分类于 开发工具

还在使用Eclipse的同学真是伤不起,点开一个未知类报一个Source not fournd。两步完全解决查看jar源码的问题。

Maven配置

如图,打开Window->Preferences->Maven,勾选“Download Artifact Sources”,所有Maven公共仓库提供Source的jar包都可以下到源码,而且带注释。
img

Java Decomplier配置

  1. 下载反编译插件jd-eclipse-2.0.0(其他版本看这里)
  2. Eclipse安装(Help->Install New Software->Add,Archive选择“jd-eclipse-2.0.0.zip”)
  3. 安装完后重启Eclipse
  4. 如下图所示,打开Window->Preferences->Gneral->Editors->File Associations,选中“*.class without source”,在下方的Associated editors中选中“JD Class File Viewer”点击“Default->Apply and Close”。

img

点评

*.class不用配置成JD,用原来的Class File Viewer就可以。反编译出来的毕竟不是源码,有可能行不对齐,所以会看到JD用注释标注的行号。还有反编译出来的并不一定准确,而且没注释。

建议

换IDEA吧,IDEA自带反编译工具。

CentOS添加用户

发表于 2019-07-29 分类于 CentOS

添加用户

1
useradd username

添加用户的同时将该用户指定到了同名的用户组中,如果将新添加的用户放到root组中,执行如下命令即可:

1
useradd -g root username

root是用户组名,username是用户名。

添加完用户要及时修改密码:

1
passwd zengguang

密码输入两次。

切换用户:

1
su username

设计模式-Singleton Pattern

发表于 2019-07-27 更新于 2019-07-31 分类于 设计模式

线程安全

四种线程安全的单例实现方式

饿汉式

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
/**
* 饿汉式单例,在第一次加载类到内存时进行初始化(线程安全)。
* <p>
* <strong>缺点:</strong>非懒加载模式,在实例依赖参数或配置文件时无法使用。
*
* @author zengguang
*
*/
public class StarveSingleton {

/**
* 第一次类加载时创建实例。
*/
private static final StarveSingleton INSTANCE = new StarveSingleton();

/**
* 构造函数私有,不允许外部创建实例。
*/
private StarveSingleton() {
}

/**
* 直接返回类加载时创建的实例。
*
* @return {@link StarveSingleton}的实例。
*/
public static StarveSingleton getSingleton() {
return INSTANCE;
}
}

双检锁

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
41
42
43
44
45
/**
* 双检锁单例模式(懒汉式,线程安全)。
* <p>
* <strong>注意:</strong>JDK1.5之前的版本volatile声明不一定起作用。
*
* @author zengguang
* @since JDK1.5
*/
public class DoubleCheckSingleton {

/**
* 一定要有<strong>volatile</strong>修饰,否则instance受指令重排的影响会返回一个空对象。
*/
private volatile static DoubleCheckSingleton instance;

/**
* 构造函数私有,不允许外部创建实例。
*/
private DoubleCheckSingleton() {
}

/**
* 返回一个单例,当第一次调用时才创建一个实例。
* <p>
* <code>instance = new DoubleCheckSingleton();</code>并非源自操作,JVM中该行代码做了如下操作:
* <ol>
* <li>给instance分配内存</li>
* <li>调用{@link DoubleCheckSingleton}的构造函数来初始化成员变量</li>
* <li>将instance对象指向分配的内存空间</li>
* </ol>
* JVM在做指令重排时,并不能保证2/3步的顺序,顺序可能是1-2-3或者1-3-2,所以其他线程调用时可能{@link DoubleCheckSingleton}还没有初始化,进而出现NPE的问题。所以在instance变量声明需要加{@code volatile}修饰。
*
* @return {@link DoubleCheckSingleton}的单实例。
*/
public static DoubleCheckSingleton getSingleton() {
if (null == instance) {
synchronized (DoubleCheckSingleton.class) {
if (null == instance) {
instance = new DoubleCheckSingleton();
}
}
}
return instance;
}
}

静态内部类

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
/**
* 静态内部类单例(懒汉式,线程安全)。
*
* @author zengguang
*
*/
public class NestedClassSingleton {

/**
* 构造函数私有,不允许外部创建实例。
*/
private NestedClassSingleton() {
}

/**
* 静态内部类只有在第一次引用的时候才会被加载。
*
* @return {@link NestedClassSingleton}的单实例。
*/
public static NestedClassSingleton getSingleton() {
return SingletonHolder.INSTANCE;
}

/**
* 内部类,且为私有的,只有{@link NestedClassSingleton}本身才能访问。
*/
private static class SingletonHolder {
private static final NestedClassSingleton INSTANCE = new NestedClassSingleton();
}
}

枚举类型

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
41
42
43
44
45
46
47
48
49
50
51
/**
* 枚举型单例模式(线程安全)。
*
* @author zengguang
* @since JDK1.5
*/
public class EnumSingleton {

/**
* 构造函数私有,不允许外部创建实例。
*/
private EnumSingleton() {
}

/**
*
* @return {@link EnumSingleton}的单实例
*/
public static EnumSingleton getSingleton() {
return Singleton.INSTANCE.getSingleton();
}

/**
* 这种实现方式有点类似静态内部类,而且枚举类型本质还是一个类。
*/
private enum Singleton {

INSTANCE(new EnumSingleton());

private EnumSingleton isntance;

/**
* 外部类作为构造参数
*
* @param singleton
* 外部类
*/
private Singleton(EnumSingleton singleton) {
this.isntance = singleton;
}

/**
* 枚举类型持有的单实例
*
* @return {@link EnumSingleton}的单实例
*/
private EnumSingleton getSingleton() {
return isntance;
}
}
}

参考资料

  1. Java 利用枚举实现单例模式
  2. Java实现单例模式(懒汉式、饿汉式、双重检验锁、静态内部类方式、枚举方式)
  3. 单例模式有五种写法:懒汉、饿汉、双重检验锁、静态内部类、枚举

GitHub仓库

SINGLETON

设计模式-Builder Pattern

发表于 2019-07-25 更新于 2019-08-03 分类于 设计模式

Builder Pattern:中文译名为“生成器模式”、“建造模式”。

示例

假设一个对象Student:

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
41
42
43
public class Student {

private int id;

private String name;

private int age;

private String gender;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getGender() {
return gender;
}

public void setGender(String gender) {
this.gender = gender;
}

}

初级编码

不使用builder模式,我们创建一个实例并给实例赋值是这样的:

1
2
3
4
5
Student std = new Student();
std.setId(10001);
std.setAge(18);
std.setName("小明");
std.setGender("male");

使用builder模式

重新改造一下Student类:

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
public class Student {

private int id;

private String name;

private int age;

private String gender;

public Student() {
}

public Student(int id, String name, int age, String gender) {
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
}

public static Student.StudentBuilder builder(){
return new StudentBuilder();
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getGender() {
return gender;
}

public void setGender(String gender) {
this.gender = gender;
}

public static class StudentBuilder {

private int id;

private String name;

private int age;

private String gender;

public StudentBuilder id(int id) {
this.id = id;
return this;
}

public StudentBuilder name(String name) {
this.name = name;
return this;
}

public StudentBuilder age(int age) {
this.age = age;
return this;
}

public StudentBuilder gender(String gender) {
this.gender = gender;
return this;
}

public Student build() {
return new Student(this.id, this.name, this.age, this.gender);
}
}
}

使用builder模式后的画风是这个样子的:

1
Student std = Student.builder().id(10001).age(18).name("小明").gender("male").build();

从此再也不用先new一个实例然后挨个赋值啦,尤其对那些属性超级多的对象,或者创建实例时有些属性是可选的,写起来更是简洁。

改造builder模式要点

  • 静态内部类
  • 静态内部类属性设置方法与属性名相同(建议相同)
  • 静态内部类属性设置方法返回内部类实例本身
  • 内部静态类需要一个build()方法且返回类型为外部类
  • 外部类需要实现一个全参数和无参构造函数
  • 外部类需要一个静态builder()方法且返回类型为静态内部类

Lombok

Lombok提供了@Builder声明式注解,直接可以让POJO拥有builder模式。

参考资料:

  • 《Head First 设计模式》
  • org.elasticsearch.common.xcontent.XContentBuilder
  • J-IM消息类org.jim.common.packets.Message及子类设计(v2.6.0)
  • Lombok使用与原理

更新(2019/8/3)

今天看到几篇Builder模式的博客,对之前的设计进行改进:

  • 静态内部类
  • 静态内部类属性设置方法与属性名相同(建议相同)
  • 静态内部类属性设置方法返回内部类实例本身
  • 内部静态类需要一个build()方法且返回类型为外部类
  • 外部类需要实现一个全参数和无参构造函数
  • 外部类需要一个入参为内部类的构造函数
  • 外部类需要一个静态builder()方法且返回类型为静态内部类

改进

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
public class Student {

private int id;

private String name;

private int age;

private String gender;

public Student() {
}

public Student(Builder builder) {
this.id = builder.id;
this.name = builder.name;
this.age = builder.age;
this.gender = builder.gender;
}

@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + ", gender=" + gender + "]";
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

public String getGender() {
return gender;
}

public void setGender(String gender) {
this.gender = gender;
}

public static class Builder {

private int id;

private String name;

private int age;

private String gender;

public Builder id(int id) {
this.id = id;
return this;
}

public Builder name(String name) {
this.name = name;
return this;
}

public Builder age(int age) {
this.age = age;
return this;
}

public Builder gender(String gender) {
this.gender = gender;
return this;
}

public Student build() {
return new Student(this);
}
}
}

使用对比

1
2
3
4
// 改进前
Student std = Student.builder().id(10001).age(18).name("小明").gender("male").build();
// 改进后
Student std = new Student.Builder().id(10001).age(18).name("小明").gender("male").build();

讨论

当初想到用builder模式时,是在项目中有些javabean属性特别多,不想中规中矩的一行一行写setter方法。这里没有使用final修饰属性,说明这不是一个可变类,有一个public的无参构造函数,且所有的getter/setter方法都可访问,所以也可以看做是一个JavaBean。

参考资料

  • 优雅地创建复杂对象 —— Builder 模式
  • 设计模式之Builder模式

Github上fork项目更新

发表于 2019-07-22 更新于 2019-08-15 分类于 git

场景:很早之前fork了github/gitee/gitlab等等的项目,但是项目经过多次迭代提交了更多更新,而自己账号下面被fork过来的项目并没有及时更新。此时,需要把提交过的内容更新到自己账号下的远程分支上。以我自己fork过的一个项目为例,主要分添加上游仓库和同步两个步骤。

添加上游仓库

查看远程分支状态:

1
git remote -v

git remote -v
添加需要同步的上游仓库:

1
git remote add upstream https://github.com/tywo45/t-io

再次查看远程状态:

1
2
3
4
5
$ git remote -v
origin git@github.com:eEricZeng/t-io.git (fetch)
origin git@github.com:eEricZeng/t-io.git (push)
upstream https://github.com/tywo45/t-io (fetch)
upstream https://github.com/tywo45/t-io (push)

同步

将上游仓库内容拉到本地:

1
git fetch upstream

此时,并没有将上游仓库的内容合并到本地中,可以使用status查看,也可以对比更新:

1
git diff master upstream/master --stat

若要同步哪个分支就切换到对应的分支,例如master分支:

1
git checkout master

同步并推送到自己账号下的远程分支,这里的同步本质是把upstream中master分支的内容合并到当前的master分支中:

1
2
git merge upstream/master
git push origin master

PicGo搭建Github图床

发表于 2019-07-20 更新于 2019-07-23 分类于 hexo

版本说明

  • node.js v6.4.1
  • PigGo v2.1.2

安装

安装PicGo需要node.js环境,没有的看这里。下载PicGo最新版本安装包,根据操作系统下载相应的安装包,以Windows为例,在Assets中点击picgo-setup-2.1.2.exe下载。本地双机安装到指定的目录。安装完成如下图所示:
image

GitHub图床

PicGo支持SM.MS图床、腾讯云COS、微博图床、GitHub图床、七牛图床、Imgur图床、阿里云OSS、又拍云等各种图床。各家图床各有利弊,但是最好找一个稳定靠谱点的。虽然不是每一个都研究过,但是也是耳闻一些消息。像微博图床2019/4添加了防盗链,微博图床的老粉几多欢喜几多愁;CDN加速?薅羊毛还是要还的。个人独钟GitHub(主要是免费),当然哪天GitHub不能访问了就告别代码吧。

GitHub图床设置还是蛮简单的,PicGo官网配置说明。Windows点击右下角PicGo小图标打开软件,依次点击 图床设置->GitHub图床,需要配置的有以下三个必须参数:

  • 仓库名
  • 分支名
  • token

仓库名要带github用户名的,如我的配置:eEricZeng/imgbed。分支名无特殊需求使用master即可。token稍微麻烦一点,需要 登录GitHub->Settings->Developer settings->Personal access tokens->Generate new token,之后添加 Note 描述,勾选scopes中的repo(包含repo:status、repo_deployment、public_repo、repo:invite四项),点击 Generate token 生成token,复制到PicGo的token表单中,点击确定即可。返回到上传取即可体验PicGo。
image

更多更新

参考资料

  1. PicGo官网
  2. Markdown 图片粘贴工具 PicGo

hexo添加阅读统计

发表于 2019-07-15 分类于 hexo

版本说明

  • hexo v3.9.0
  • hexo-theme-next v7.1.2

不蒜子

NexT内置了leancloud、firebase、busuanzi三种访客统计插件,前两种需要到官网注册获取网站颁发的appKey,相对麻烦,有兴趣的请访问leancloud、firebase。而不蒜子配置只需要将false改为true即可:

1
2
busuanzi_count:
enable: true

更多用法请参考官网说明不蒜子官网。

百度统计

起初我以为阅读统计是通过百度统计进行计数的,后来发现百度统计、GA等只是分析工具,并不会把统计信息显示在博客页面上,所以是否需要百度统计看个人需求。打开百度统计,登录并进入网站列表,点击新增网站。以我的GitPage为例,填写新增网站表单,添加必要字段网站域名:eericzeng.github.io,网站首页:https://eericzeng.github.io, 网站名称 、行业类别选填。点击“确定”后,会出现包含如下信息的提示:

1
2
3
4
5
6
7
8
9
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?324a1c41343d123482f031976f9";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>

复制”https://hm.baidu.com/hm.js?" 后面的Id字符串,粘贴到主题配置文件中,如themes/next/_config.yml

1
2
# Baidu Analytics ID
baidu_analytics: 324a1c41343d123482f031976f9

发布

重新打包静态文件并发布:

1
2
hexo g
hexo s

点击百度统计控制台,代码管理->代码安装检查进行安装校验。

123
Eric Zeng

Eric Zeng

你的才华撑不起你的野心时,请静下心来学习
25 日志
11 分类
75 标签
RSS
GitHub E-Mail
Creative Commons
© 2019 EricZeng
由 Hexo 强力驱动 v3.9.0
|
主题 – NexT.Mist v7.2.0
|
0%