0%

数据类型

  • String

    1
    2
    3
    4
    redis 127.0.0.1:6379> SET name "runoob"
    OK
    redis 127.0.0.1:6379> GET name
    "runoob"
  • Hash

    1
    2
    3
    4
    5
    6
    redis> HMSET myhash field1 "Hello" field2 "World"
    "OK"
    redis> HGET myhash field1
    "Hello"
    redis> HGET myhash field2
    "World"
  • List

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    redis 127.0.0.1:6379> lpush runoob redis
    (integer) 1
    redis 127.0.0.1:6379> lpush runoob mongodb
    (integer) 2
    redis 127.0.0.1:6379> lpush runoob rabitmq
    (integer) 3
    redis 127.0.0.1:6379> lrange runoob 0 10
    1) "rabitmq"
    2) "mongodb"
    3) "redis"
    redis 127.0.0.1:6379>
  • Set

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    redis 127.0.0.1:6379> sadd runoob redis
    (integer) 1
    redis 127.0.0.1:6379> sadd runoob mongodb
    (integer) 1
    redis 127.0.0.1:6379> sadd runoob rabitmq
    (integer) 1
    redis 127.0.0.1:6379> sadd runoob rabitmq
    (integer) 0
    redis 127.0.0.1:6379> smembers runoob

    1) "redis"
    2) "rabitmq"
    3) "mongodb"
  • zset(sorted set:有序集合)

    • Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。

      不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。

    • 命令

      1
      zadd key score member 
    • 实例

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      redis 127.0.0.1:6379> zadd runoob 0 redis
      (integer) 1
      redis 127.0.0.1:6379> zadd runoob 0 mongodb
      (integer) 1
      redis 127.0.0.1:6379> zadd runoob 0 rabitmq
      (integer) 1
      redis 127.0.0.1:6379> zadd runoob 0 rabitmq
      (integer) 0
      redis 127.0.0.1:6379> > ZRANGEBYSCORE runoob 0 1000
      1) "mongodb"
      2) "rabitmq"
      3) "redis"

操作

  • show all keys

    KEYS *

  • Delete All Keys In Redis

    1
    2
    3
    4
    5
    6
      Delete all keys from all Redis databases:
    `$ redis-cli FLUSHALL`
    Delete all keys of the currently selected Redis database:
    `$ redis-cli FLUSHDB`
    Delete all keys of the specified Redis database:
    `$ redis-cli -n <database_number> FLUSHDB`
  • 删除指定前缀的数据

    1
    2
    # 删除指定CCR866前缀的redis数据
    path/to/redis-cli -p 16379 -a Redis6379 -n 1 keys 'CCR866*' | xargs ./redis-cli -p 16379 -a Redis6379 -n 1 del
  • 在启动命令中添加 –raw,可以查看value的中文信息

问题解决

  • RedisConnectionFailureException

    1
    2
    3
    redis.conf中默认的是bind 127.0.0.1,需要将这段注释
    设置protected-mode no,因为如果是yes的话,只能进行本地访问。如果设置了密码和bind这个可以开启,如果没有设置,这个属性可以设置为no即可。
    daemonize yes表示后台运行
  • 需要安装gcc

  • make时,提示fatal error: jemalloc/jemalloc.h: No such file or directory

    1
    2
    3
    4
    5
    6
    解决:   
    cd src/deps
    make hiredis jemalloc linenoise lua geohash-int
    cd ..
    make
    sudo make install

    自定义配置redis server

    涉及到的目录或文件有

    1
    2
    3
    1.配置文件    /etc/redis/xxxx.conf
    2.日志、数据文件 /data/redis/xxxx
    3.启动脚本 /etc/init.d/redis_xxxx
  • 客户端启动时 redis-cli -p xxxx

高并发处理技术老司机带你玩RabbitMq实现性能倍增
链接:https://pan.baidu.com/s/1tdWyeXgXzbWsltY8NlhdaQ

密码:ripd

缓存那些事,缓存一致性问题爬坑记
链接:https://pan.baidu.com/s/10aX13k6GjIr7XUcrb6j-Pw

密码:f5kl

分布式事务处理你不得不听的踩坑故事-让你的代码经得起考验
链接:https://pan.baidu.com/s/1PeiCr0DYMI7x4LwGJktrOg

密码:phsp

大咖带你玩转分布式锁 Zookeeper篇
链接:https://pan.baidu.com/s/1Nh8mTrLNwtmh4hwU2khksg

密码:fznh

JRE JVM JDK

  • JRE: java run-time

Java is every where in browser, in mobile, in TV or in set-top boxes and if you are into Java programming language than you know that Java code which is bundled in JAR (Java archive) file require Java virtual machine JVM to execute it.

  • JVM: java virtual machine

Java Virtual Machine is get created when you run a java program using java command e.g. java HelloWorld. JVM is responsible for converting byte code into machine specific code

  • JDK: java development kit

JDK is also loosely referred as JRE but its lot more than JRE and it provides all the tools and executable require to compile debug and execute Java Program.

basic architecture of the JVM

Class Loader Sub System

1. Loading

  • loading the class file and store inside method area

  • Created object is not student object or customer object. It is a predefined class “Class” object that is presently in java.lang package.

  • For every loaded .class file, only one class “Class” object will be created by JVM, even though we are using that class multiple times in our program. Example,

2. Linking

  • verification

    This Byte Code Verifier is responsible to verify weather .class file is properly formatted or not, structurally correct or not, generated by valid compiler or not.

  • preparation

    allocate memory for class level static variables and assigned default values.

    E.g. For int —> 0, For double —> 0.0, For boolean —> false

  • Resolution

    It is the process of replacing all symbolic references used in our class with original direct references from method area.

  • Initialization

In Initialization activity, for class level static variables assigns original values and static blocks will be executed from top to bottom.

  • Types of class loaders in class loader subsystem
    • Bootstrap class loader/ Primordial class loader
    • Extension class loader
    • Application class loader/System class loader

3. Class loader sub system follows delegation hierarchy algorithm

  • Customized class loaderSometimes we may not satisfy with default class loader mechanism then we can go for Customized class loader. For example:

Various Memory Areas in JVM

1. Method Area

  • Inside method area class level binary data including static variables will be stored

  • Constant pools of a class will be stored inside method area.

  • Method area can be accessed by multiple threads simultaneously.

    All threads share the same method area, so access to the method area’s data structures must be designed to be thread-safe.

2. Heap Area

Heap space in Java is used for dynamic memory allocation for Java objects and JRE classes at the runtime. New objects are always created in heap space and the references to this objects are stored in stack memory.

These objects have global access and can be accessed from anywhere in the application.

This memory model is further broken into smaller parts called generations, these are:

  1. Young Generation – this is where all new objects are allocated and aged. A minor Garbage collection occurs when this fills up
  2. Old or Tenured Generation – this is where long surviving objects are stored. When objects are stored in the Young Generation, a threshold for the object’s age is set and when that threshold is reached, the object is moved to the old generation
  3. Permanent Generation – this consists of JVM metadata for the runtime classes and application methods
  • It’s accessed via complex memory management techniques that include Young Generation, Old or Tenured Generation, and Permanent Generation
  • If heap space is full, Java throws java.lang.OutOfMemoryError
  • Access to this memory is relatively slower than stack memory
  • This memory, in contrast to stack, isn’t automatically deallocated. It needs Garbage Collector to free up unused objects so as to keep the efficiency of the memory usage
  • Unlike stack, a heap isn’t threadsafe and needs to be guarded by properly synchronizing the code

  • Objects and corresponding instance variables will be stored in the heap area.

  • Every array in java is object only hence arrays also will be stored in the heap area.

  • Heap area can be access by multiple threads and hence the data stored in the heap area is not thread safe.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Set Maximum and Minimum heap size
-Xmx
To set maximum heap size , i.e., maxMemory
java -Xmx512m HeapSpaceDemo
Here mx = maximum size
512m = 512 MB
HeapSpaceDemo = Java class name
-Xms
To set minimum heap size , i.e., total memory
java -Xms65m HeapSpaceDemo
Here ms = minimum size
65m = 65 MB
HeapSpaceDemo = Java class name
or, you can set a minimum maximum heap size at a time
java -Xms256m -Xmx1024m HeapSpaceDemo

3. Stack Memory

Stack Memory in Java is used for static memory allocation and the execution of a thread. It contains primitive values that are specific to a method and references to objects that are in a heap, referred from the method.

1
2
3
Access to this memory is in Last-In-First-Out (LIFO) order. Whenever a new method is called, a new block on top of the stack is created which contains values specific to that method, like primitive variables and references to objects.

When the method finishes execution, it’s corresponding stack frame is flushed, the flow goes back to the calling method and space becomes available for the next method.
  • It grows and shrinks as new methods are called and returned respectively

  • Variables inside stack exist only as long as the method that created them is running

  • It’s automatically allocated and deallocated when method finishes execution

  • If this memory is full, Java throws java.lang.StackOverFlowError

  • Access to this memory is fast when compared to heap memory

  • This memory is threadsafe as each thread operates in its own stack


  • Local Variable Array

    • It contains all parameters and local variables of the method.

    • the occupied slot

  • Operand Stack

    • JVM uses operand stack as work space.

    • last-in first-out (LIFO)

    • how a Java virtual machine would add two local variables that contain ints and store the int result in a third local variable:

  • Frame Data

Stack Memory vs Heap Space

Parameter Stack Memory Heap Space
Application Stack is used in parts, one at a time during execution of a thread The entire application uses Heap space during runtime
Size Stack has size limits depending upon OS and is usually smaller then Heap There is no size limit on Heap
Storage Stores only primitive variables and references to objects that are created in Heap Space All the newly created objects are stored here
Order It is accessed using Last-in First-out (LIFO) memory allocation system This memory is accessed via complex memory management techniques that include Young Generation, Old or Tenured Generation, and Permanent Generation.
Life Stack memory only exists as long as the current method is running Heap space exists as long as the application runs
Efficiency Comparatively much faster to allocate when compared to heap Slower to allocate when compared to stack
Allocation/Deallocation This Memory is automatically allocated and deallocated when a method is called and returned respectively Heap space is allocated when new objects are created and deallocated by Gargabe Collector when they are no longer referenced

4. PC Registers(Program Counter Registers)

For every thread a separate PC register will be created at the time of thread creation. PC register contains address of current executing instruction. Once instruction execution completes automatically PC register will be incremented to hold address of next instruction. An “address” can be a native pointer or an offset from the beginning of a method’s byte codes.

5. Native Method Stacks

Here also for every Thread a separate run time stack will be created. It contains all the native methods used in the application. Native method means methods written in a language other than the Java programming language. In other words, it is a stack used to execute C/C++ codes invoked through JNI (Java Native Interface). According to the language, a C stack or C++ stack is created.

Execution Engine

1. Interpreter

It is responsible to read byte code and interpret into machine code (native code) and execute that machine code line by line.

2. JIT Compiler

The JIT compiler has been introduced to compensate for the disadvantages of the interpreter. The main purpose of JIT compiler is to improve the performance. Internally JIT compiler maintains a separate count for every method. Whenever JVM across any method call, first that method will be interpreted normally by the interpreter and JIT compiler increments the corresponding count variable.

  • Profiler which is the part of JIT compiler is responsible to identify Hotspot(Repeated Used Methods).

Java Native Interface(JNI)

JNI is acts as a bridge (Mediator) for java method calls and corresponding native libraries.

内存大小设置

  • 在命令行下用 java -Xmx1200m -XX:Max Perm Size=60m -version 命令来进行测试,然后逐渐的增大XXXX的值,如果执行正常就表示指定的内存大小可用,否则会打印错误信息。
    最后得到的虚拟机实际分配到的
    总内存大小=堆内存+非堆内存
    1200m:为堆内存大小,如果不指定后者参数则有最大数限制,网上很多文章认为这就是JVM内存, -Xmx为设置最大堆内存
    60m: 为非堆内存大小, -XX: Max PermSize实为 永久域内存,在堆内存之外,属于非堆内存部分,jdk1.5我测了好像默认为62m,即得到非堆部分默认内存)

进程内存

查看进程对象大小

  • jmap -histo 进程id

    1
    jmap -histo 123456 | head -n15

查看内存分布及回收情况

  • jstat -gc 进程id 毫秒

    1
    jstat -gc 1692 5000

    S0C: Young Generation第一个survivor space的内存大小 (kB).
    S1C: Young Generation第二个survivor space的内存大小 (kB).
    S0U: Young Generation第一个Survivor space当前已使用的内存大小 (kB).
    S1U: Young Generation第二个Survivor space当前已经使用的内存大小 (kB).
    EC: Young Generation中eden space的内存大小 (kB).
    EU: Young Generation中Eden space当前已使用的内存大小 (kB).
    OC: Old Generation的内存大小 (kB).
    OU: Old Generation当前已使用的内存大小 (kB).
    MC: Permanent Generation的内存大小 (kB)
    MU: Permanent Generation当前已使用的内存大小 (kB).
    YGC: 从启动到采样时Young Generation GC的次数
    YGCT: 从启动到采样时Young Generation GC所用的时间 (s).
    FGC: 从启动到采样时Old Generation GC的次数.
    FGCT: 从启动到采样时Old Generation GC所用的时间 (s).
    GCT: 从启动到采样时GC所用的总时间 (s).

查看堆栈占用

  • jmap -heap 进程id

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    S0: 新生代中Survivor space 0区已使用空间的百分比
    S1: 新生代中Survivor space 1区已使用空间的百分比
    E :新生代已使用空间的百分比 Eden space
    O: 老年代已使用空间的百分比(P: 永久带已使用空间的百分比)

    M: 元空间使用百分比
    CCS: 压缩类空间利用率为百分比
    YGC: YGC次数
    YGCT: 年轻一代垃圾收集时间
    FGC: FGC次数.
    FGCT: 完全垃圾收集时间
    GCT: 垃圾回收总时间

命令介绍

  1. mvn compile 编译,将Java 源程序编译成 class 字节码文件。
  2. mvn test 测试,并生成测试报告
  3. mvn clean 将以前编译得到的旧的 class 字节码文件删除
  4. mvn pakage 打包,动态 web工程打 war包,Java工程打 jar 包。
  5. mvn install 将项目生成 jar 包放在仓库中,以便别的模块调用
  6. Maven的几个常用plugin

tomcat项目的部署

maven多项目之间相互引用

  • 应该在父目录下进行maven install操作,会自动生成子模块的jar或war包。

  • 解决maven无法加载本地lib/下的jar包问题(程序包XXX不存在)

    • 原因

      若该程序包是第三方的jar,解决方案是让maven既加载maven库中的jar包,又要加载本地WEB-INF/lib下的jar包。

    • 解决

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.6.0</version>
      <configuration>
      <source>1.8</source>
      <target>1.8</target>
      <encoding>UTF-8</encoding>
      <compilerArguments>
      <extdirs>${project.basedir}/src/main/webapp/WEB-INF/lib</extdirs>
      </compilerArguments>
      </configuration>
      </plugin>

创建本地引用包

1.直接引用本地jar

将jar放在项目中,例如web项目就放在 webapp/WEB-INF/lib下面
然后再pom.xml中添加jar的依赖:

1
2
3
4
5
6
7
<dependency>
<groupId>myjar</groupId>
<artifactId>myjar</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/webapp/WEB-INF/lib/myjar-1.0.0.jar</systemPath>
</dependency>

2.安装到本地仓库

1
2
3
4
5
6
7
8
mvn install:install-file -Dfile=xxx.jar -DgroupId=xx.xxx.xx -DartifactId=xx -Dversion=xx -Dpackaging=jar

参数说明:
-DgroupId:对应dependency的groupId
-DartifactId:对应dependency的artifactId
-Dversion:对应dependency中的version
-Dpackaging:安装的类型,jar或者pom
-Dfile:要安装的jar文件的路径

scope

  • compile
    默认就是compile,什么都不配置也就是意味着compile。compile表示被依赖项目需要参与当前项目的编译,当然后续的测试,运行周期也参与其中,是一个比较强的依赖。打包的时候通常需要包含进去。

  • test
    scope为test表示依赖项目仅仅参与测试相关的工作,包括测试代码的编译,执行。比较典型的如junit。

  • runntime
    runntime表示被依赖项目无需参与项目的编译,不过后期的测试和运行周期需要其参与。与compile相比,跳过编译而已,说实话在终端的项目(非开源,企业内部系统)中,和compile区别不是很大。比较常见的如JSR×××的实现,对应的API jar是compile的,具体实现是runtime的,compile只需要知道接口就足够了。oracle jdbc驱动架包就是一个很好的例子,一般scope为runntime。另外runntime的依赖通常和optional搭配使用,optional为true。我可以用A实现,也可以用B实现。

  • provided
    provided意味着打包的时候可以不用包进去,别的设施(Web Container)会提供。事实上该依赖理论上可以参与编译,测试,运行等周期。相当于compile,但是在打包阶段做了exclude的动作。

  • system
    从参与度来说,和provided相同,不过被依赖项不会从maven仓库抓,而是从本地文件系统拿,一定需要配合systemPath属性使用

依赖传递原则

几乎所有的Jar包冲突都和依赖传递原则有关,所以我们先说Maven中的依赖传递原则:

最短路径优先原则

假如引入了2个Jar包A和B,都传递依赖了Z这个Jar包:

A -> X -> Y -> Z(2.5)
B -> X -> Z(2.0)

那其实最终生效的是Z(2.0)这个版本。因为他的路径更加短。如果我本地引用了Z(3.0)的包,那生效的就是3.0的版本。一样的道理。

最先声明优先原则

如果路径长短一样,优先选最先声明的那个。

A -> Z(3.0)
B -> Z(2.5)

这里A最先声明,所以传递过来的Z选择用3.0版本的。

引用本地jar包依赖

  1. jar包放入项目指定位置 ie:${project.basedir}/src/main/resources/lib/xxx.jar

  2. pom文件引入依赖

    1
    2
    3
    4
    5
    6
    7
    <dependency>
    <groupId>com.aliyun</groupId>
    <artifactId>sdk.core</artifactId>
    <version>3.3.1</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/src/main/resources/lib/xxx.jar</systemPath>
    </dependency>

    systemPath这个路径是jar包的路径。${project.basedir}只是一个系统自己的常量。

  3. 在将项目用Maven打包是需要在 标签中加入:

    1
    2
    3
    4
    5
    6
    7
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
    <includeSystemScope>true</includeSystemScope>
    </configuration>
    </plugin>

init project

1
mvn archetype:generate -DgroupId=brook.hbase -DartifactId=hbase-client -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false

命令启动springboot

1
mvn spring-boot:run

add git commit info to jar package

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
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>2.2.4</version>
<executions>
<execution>
<id>get-the-git-infos</id>
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
<configuration>
<dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
<prefix>git</prefix>
<verbose>false</verbose>
<generateGitPropertiesFile>true</generateGitPropertiesFile
<generateGitPropertiesFilename>${project.build.outputDirectory}/git.properties</generateGitPropertiesFilename>
<format>json</format>
<gitDescribe>
<skip>false</skip>
<always>false</always>
<dirty>-dirty</dirty>
</gitDescribe>
</configuration>
</plugin>

生成的git.properties会在jar包位置 BOOT-INF/classes/git.properties

相关问题

Creational Design Patterns

These design patterns provide a way to create objects while hiding the creation logic, rather than instantiating objects directly using new operator. This gives program more flexibility in deciding which objects need to be created for a given use case.

Singleton

In Factory pattern, we create object without exposing the creation logic to the client and refer to newly created object using a common interface.

  • different approaches to implement:

    • Private constructor to restrict instantiation of the class from other classes.
    • Private static variable of the same class that is the only instance of the class.
    • Public static method that returns the instance of the class, this is the global access point for outer world to get the instance of the singleton class.
  • design concerns with the implementation

    • Eager initialization
    • Static block initialization
    • Lazy Initialization
    • Thread Safe Singleton
    • Bill Pugh Singleton Implementation
    • Using Reflection to destroy Singleton Pattern
    • Enum Singleton
    • Serialization and Singleton
    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
    //SingleObject.java
    public class SingleObject {

    //create an object of SingleObject
    private static SingleObject instance = new SingleObject();

    //make the constructor private so that this class cannot be
    //instantiated
    private SingleObject(){}

    //Get the only object available
    public static SingleObject getInstance(){
    return instance;
    }

    public void showMessage(){
    System.out.println("Hello World!");
    }
    }

    //SingletonPatternDemo.java
    public class SingletonPatternDemo {
    public static void main(String[] args) {

    //illegal construct
    //Compile Time Error: The constructor SingleObject() is not visible
    //SingleObject object = new SingleObject();

    //Get the only object available
    SingleObject object = SingleObject.getInstance();

    //show the message
    object.showMessage();
    }
    }

Factory

  • Factory design pattern provides approach to code for interface rather than implementation.
  • Factory pattern removes the instantiation of actual implementation classes from client code. Factory pattern makes our code more robust, less coupled and easy to extend. For example, we can easily change PC class implementation because client program is unaware of this.
  • Factory pattern provides abstraction between implementation and client classes through inheritance.

Abstract Factory

  • Abstract Factory design pattern provides approach to code for interface rather than implementation.
  • Abstract Factory pattern is “factory of factories” and can be easily extended to accommodate more products, for example we can add another sub-class Laptop and a factory LaptopFactory.
  • Abstract Factory pattern is robust and avoid conditional logic of Factory pattern.

Builder

  • Builder pattern solves the issue with large number of optional parameters and inconsistent state by providing a way to build the object step-by-step and provide a method that will actually return the final Object.

Prototype

  • Prototype design pattern is used when the Object creation is a costly affair and requires a lot of time and resources and you have a similar object already existing.Prototype pattern provides a mechanism to copy the original object to a new object and then modify it according to our needs. Prototype design pattern uses java cloning to copy the object.

Structural Design Patterns

These design patterns concern class and object composition. Concept of inheritance is used to compose interfaces and define ways to compose objects to obtain new functionalities.

Adapter

  • Adapter design pattern is one of the structural design pattern and its used so that two unrelated interfaces can work together. The object that joins these unrelated interface is called an Adapter.

Composite

  • Composite design pattern is used when we have to represent a part-whole hierarchy.

Proxy

  • Proxy design pattern common uses are to control access or to provide a wrapper implementation for better performance.

Flyweight

  • Use sharing to support large numbers of fine-grained objects efficiently

Facade

  • Provide a unified interface to a set of interfaces in a subsystem. Facade Pattern defines a higher-level interface that makes the subsystem easier to use.

Bridge

  • Decouple an abstraction from its implementation so that the two can vary independently.

Decorator

  • Decorator design pattern is helpful in providing runtime modification abilities and hence more flexible. Its easy to maintain and extend when the number of choices are more.
  • The disadvantage of decorator design pattern is that it uses a lot of similar kind of objects (decorators).

Behavioral Design Patterns

These design patterns are specifically concerned with communication between objects.

Template Method

  • Template method should consists of certain steps whose order is fixed and for some of the methods, implementation differs from base class to subclass. Template method should be final.
  • Most of the times, subclasses calls methods from super class but in template pattern, superclass template method calls methods from subclasses, this is known as Hollywood Principle – “don’t call us, we’ll call you.”.
  • Methods in base class with default implementation are referred as Hooks and they are intended to be overridden by subclasses, if you want some of the methods to be not overridden, you can make them final, for example in our case we can make buildFoundation() method final because if we don’t want subclasses to override it.

Media

  • Allows loose coupling by encapsulating the way disparate sets of objects interact and communicate with each other. Allows for the actions of each object set to vary independently of one another.

Architectural

Business Object

A business object is a normal class which has a normal business logic.

Aspect

An aspect is a modularization of a concern that cuts across multiple classes.

JoinPoint

A Joinpoint is a point during the execution of a program, such as execution of a method or the handling of an exception.

In Spring AOP, a JoinPoint always represents a method execution.

Pointcut

A Pointcut is a predicate that helps match an Advice to be applied by an Aspect at a particular JoinPoint.

The Advice is often associated with a Pointcut expression and runs at any Joinpoint matched by the Pointcut.

Advice

An advice is an action taken by an aspect at a particular Joinpoint. Different types of advice include “around,” “before” and “after” advice.

In Spring, an Advice is modeled as an interceptor, maintaining a chain of interceptors around the Joinpoint.


Example:Wiring Business Object and Aspect

  • Business Object

    1
    2
    3
    4
    5
    public class SampleAdder {
    public int add(int a, int b) {
    return a + b;
    }
    }
  • a simple Aspect

    Unified logging can be an example of such cross-cutting concern:

    1
    2
    3
    4
    5
    6
    public class AdderAfterReturnAspect {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    public void afterReturn(Object returnValue) throws Throwable {
    logger.info("value return was {}", returnValue);
    }
    }
  • config excerpt

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <bean id="sampleAdder" class="org.xxx.SampleAdder" />
    <bean id="doAfterReturningAspect"
    class="org.xxx.AdderAfterReturnAspect" />
    <aop:config>
    <aop:aspect id="aspects" ref="doAfterReturningAspect">
    <aop:pointcut id="pointCutAfterReturning" expression=
    "execution(* org.xxx.SampleAdder+.*(..))"/>
    <aop:after-returning method="afterReturn"
    returning="returnValue" pointcut-ref="pointCutAfterReturning"/>
    </aop:aspect>
    </aop:config>

依赖注入DI有助于应用对象之间的解耦,而AOP可以实现横切关注点与它们所影响的对象之间的解耦

  • 通知Advice

    切面的工作被称为通知,通知定义了切面是什么以及何时使用。

    • 前置通知(Before):在目标方法被调用之前调用通知功能
    • 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出
    • 返回通知(After-returning):在目标方法成功执行之后调用通知
    • 异常通知(After-throwing):在目标方法抛出异常后调用通知
    • 环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。
  • 连接点Join point

    连接点是应用程序的点,可供插入切面

    我理解的是程序的某处,或者任意一处都可以称作为连接点

  • 切点Pointcut

    切点有助于缩小切面所通知的连接点的范围

    如果Advice定义了切面的what和when,那么pointcut就定义了where

  • 切面Aspect

    Aspect是Advice和Pointcut的结合

RPC
Remote Procedure Call,远程过程调用


服务之间的调用大多采用rpc的方式调用,或者消息队列的方式进行解耦。

RPC与http调用的区别
rpc是基于TCP/IP协议的,而HTTP服务主要是基于HTTP协议的,而http协议是在传输层协议TCP之上的。所以rpc效率更好。

RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,
由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。

由于计算能力需要横向扩展,需要在多台机器组成的集群上部署应用。

  • GET: A safe read-only method that reads a single or a list of resources.
  • POST: Creates a new resource.
  • PUT: Completely replaces the resource(s) at the given location with the new data.
  • PATCH: Merges the resource(s) at the given location with the new data.
  • DELETE: Deletes the resource(s) at a location.
  • HEAD: Same as GET but only returns the header and no data.

用 URL 表示要操作的资源,用不同的 HTTP 请求(GET,POST,PUT,DELETE)描述对资源的操作,通过 HTTP 的状态码来判断此次对资源操作的结果,这就是 Restful风格。

  1. GET 用来获取资源
  2. POST 用来新增资源
  3. PUT 用来更新资源
  4. DELETE 用来删除资源
  • put和delete虽然是http协议的规范 ,但是遗憾的是,所有的无论是html4还是h5都不支持,所以我们在实际开开发过程当中要模拟这两种状态。

Restful有什么意义

  • 网络上的所有的信息体都看作一种资源,对网络资源的某种操作,都是通过 method 来确定的。
  • 对于现在的数据或者资源提供方,对外透露的接口一般是 restful 风格的,有利于不同系统之间的资源共享,而且只需要遵守规范不需要做另外的配置就能达到资源共享。

restful 是用来外提供接口的,主要用于在不同的系统之间进行数据的交互。

ps:其实在做内部系统的时候并不会使用 restful 风格的 url 请求,只用普通的 @RequestMapping 来匹配请求就行了。

返回码

RESTful API 中的标准返回码通常遵循 HTTP 状态码,并根据不同的操作和结果返回不同的状态码。以下是一些常见的 HTTP 状态码及其通常的含义:

  • 200 OK: 表示请求成功。通常用于 GET 请求。
  • 201 Created: 表示成功创建了新的资源。通常用于 POST 请求。
  • 204 No Content: 表示请求成功处理,但没有返回内容。通常用于 DELETE 请求。
  • 400 Bad Request: 表示客户端发送的请求有错误,服务器无法理解。
  • 401 Unauthorized: 表示请求需要用户认证,用户没有提供有效的认证信息。
  • 403 Forbidden: 表示服务器理解请求,但拒绝执行,通常因为权限问题。
  • 404 Not Found: 表示请求的资源不存在。
  • 405 Method Not Allowed: 表示请求方法不被允许。
  • 409 Conflict: 表示请求可能引发冲突,例如更新资源时的版本冲突。
  • 500 Internal Server Error: 表示服务器在处理请求时发生了错误。
  • 502 Bad Gateway - This indicates an invalid response from an upstream server.
  • 503 Service Unavailable - This indicates that something unexpected happened on server side (It can be anything like server overload, some parts of the system failed, etc.).

RESTful API 的返回码可以根据实际情况进行适当扩展和调整,但通常遵循以上基本的 HTTP 状态码标准。

TIPS

  • url中包含传参时,例如delete /auth/user/{参数},那此时其他delete方法 /auth/user/other,会发生冲突,需要在路径侯后面添加“/”,变成/auth/user/other/

  • vue实例初始化过程:

    • 设置数据监听
    • 编译模板
    • 将实例挂载到DOM并在数据变化时更新DOM等
  • 生命周期钩子:提供用户在不同阶段添加自己的代码的机会

    • created,用来实例被创建之后执行代码
    • mounted,
    • updated,
    • destoryed
  • 指令(Directives)是带有v-前缀的特殊特性。指令特性的值预期是单个JavaScript表达式(v-for是例外情况),指令的职责是:当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM。

    • v-bind,可以接受一个参数,用于响应式地更新HTML特性。

      1
      2
      3
      4
      5
      <!-- 完整语法 -->
      <a v-bind:href="url">...</a>

      <!-- 缩写 -->
      <a :href="url">...</a>
    • v-on,用于监听DOM事件

      1
      2
      3
      4
      5
      <!-- 完整语法 -->
      <a v-on:click="doSomething">...</a>

      <!-- 缩写 -->
      <a @click="doSomething">...</a>
    • 修饰符v-on:submit.prevent,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()


  • 计算属性

    1
    2
    3
    4
    <div id="example">
    <p>Original message: "{{ message }}"</p>
    <p>Computed reversed message: "{{ reversedMessage }}"</p>
    </div>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var vm = new Vue({
    el: '#example',
    data: {
    message: 'Hello'
    },
    computed: {
    // 计算属性的 getter
    reversedMessage: function () {
    // `this` 指向 vm 实例
    return this.message.split('').reverse().join('')
    }
    }
    })
    • 计算属性缓存vs方法

      在方法中实现同计算属性同样的效果

      1
      <p>Reversed message: "{{ reversedMessage() }}"</p>
      1
      2
      3
      4
      5
      6
      // 在组件中
      methods: {
      reversedMessage: function () {
      return this.message.split('').reverse().join('')
      }
      }

      计算属性是基于它们的依赖进行缓存的。只在相关依赖发生改变时它们才会重新求值。

    • 计算属性vs侦听属性

      侦听属性的用法:

      1
      <div id="demo">{{ fullName }}</div>
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      var vm = new Vue({
      el: '#demo',
      data: {
      firstName: 'Foo',
      lastName: 'Bar',
      fullName: 'Foo Bar'
      },
      watch: {
      firstName: function (val) {
      this.fullName = val + ' ' + this.lastName
      },
      lastName: function (val) {
      this.fullName = this.firstName + ' ' + val
      }
      }
      })

      与计算属性的版本进行对比:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      var vm = new Vue({
      el: '#demo',
      data: {
      firstName: 'Foo',
      lastName: 'Bar'
      },
      computed: {
      fullName: function () {
      return this.firstName + ' ' + this.lastName
      }
      }
      })
    • 计算属性的setter

      计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter :

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      // ...
      computed: {
      fullName: {
      // getter
      get: function () {
      return this.firstName + ' ' + this.lastName
      },
      // setter
      set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
      }
      }
      }
      // ...

      现在再运行 vm.fullName = 'John Doe' 时,setter 会被调用,vm.firstNamevm.lastName 也会相应地被更新。

  • 侦听器

    使用场景:当需要在数据变化时执行异步或开销较大的操作时


  • 条件渲染

    v-if

  • 展示元素

    v-show,它只是简单地切换元素的css属性display

    **注意v-show 不支持 <template> 元素,也不支持 v-else

    • v-ifvsv-show

      一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

  • 列表渲染

    v-for

    • 实例一

      1
      2
      3
      4
      5
      <ul id="example-1">
      <li v-for="item in items">
      {{ item.message }}
      </li>
      </ul>
      1
      2
      3
      4
      5
      6
      7
      8
      9
      var example1 = new Vue({
      el: '#example-1',
      data: {
      items: [
      { message: 'Foo' },
      { message: 'Bar' }
      ]
      }
      })
    • 实例二

      1
      2
      3
      4
      5
      <ul id="example-2">
      <li v-for="(item, index) in items">
      {{ parentMessage }} - {{ index }} - {{ item.message }}
      </li>
      </ul>
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      var example2 = new Vue({
      el: '#example-2',
      data: {
      parentMessage: 'Parent',
      items: [
      { message: 'Foo' },
      { message: 'Bar' }
      ]
      }
      })
    • 可以用 of 替代 in 作为分隔符

      1
      <div v-for="item of items"></div>
    • 实例三

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      new Vue({
      el: '#v-for-object',
      data: {
      object: {
      firstName: 'John',
      lastName: 'Doe',
      age: 30
      }
      }
      })
      1
      2
      3
      4
      5
      <ul id="v-for-object" class="demo">
      <li v-for="value in object">
      {{ value }}
      </li>
      </ul>
      1
      2
      3
      <div v-for="(value, key) in object">
      {{ key }}: {{ value }}
      </div>
      1
      2
      3
      4
      <div v-for="(value, key, index) in object">
      {{ index }}. {{ key }}: {{ value }}
      </div>

  • 数组更新检测

    • 变异方法,会改变被这些方法调用的原始数组
      • push()
      • pop()
      • shift()
      • unshift()
      • splice()
      • sort()
      • reverse()
    • 也有非变异 (non-mutating method) 方法,例如:filter(), concat()slice() 。这些不会改变原始数组,但总是返回一个新数组

  • vue组件实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 定义一个名为 button-counter 的新组件
    Vue.component('button-counter', {
    data: function () {
    return {
    count: 0
    }
    },
    template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
    })
    • prop可以在组件上注册的一些自定义特性

      1
      2
      3
      4
      Vue.component('blog-post', {
      props: ['title'],
      template: '<h3>{{ title }}</h3>'
      })
      1
      2
      3
      <blog-post title="My journey with Vue"></blog-post>
      <blog-post title="Blogging with Vue"></blog-post>
      <blog-post title="Why Vue is so fun"></blog-post>
    • 调用内建的 $emit 方法并传入事件的名字,来向父级组件触发一个事件:

      1
      2
      3
      <button v-on:click="$emit('enlarge-text')">
      Enlarge text
      </button>

      然后我们可以用 v-on 在博文组件上监听这个事件,就像监听一个原生 DOM 事件一样

      1
      2
      3
      4
      <blog-post
      ...
      v-on:enlarge-text="postFontSize += 0.1"
      ></blog-post>

组件注册

  • 全局注册

    1
    2
    3
    Vue.component('my-component-name', {
    // ... 选项 ...
    })
  • 局部注册

    定义组件

    1
    2
    3
    var ComponentA = { /* ... */ }
    var ComponentB = { /* ... */ }
    var ComponentC = { /* ... */ }

    使用组件

    1
    2
    3
    4
    5
    6
    7
    new Vue({
    el: '#app',
    components: {
    'component-a': ComponentA,
    'component-b': ComponentB
    }
    })

全局注册的行为必须在根 Vue 实例 (通过 new Vue) 创建之前发生


自定义事件

  • cypher语法对大小写敏感,注意属性的大小写
  • 导入csv出现乱码时,需要通过记事本更改编码格式,如果文本过大,需要一段一段的复制粘贴到新文本中,且以UTF-8格式编码
  • MERGE命令是CREATE命令和MATCH命令的组合。MERGE = CREATE + MATCH

问题

1.
现象: 在外部处理csv数据,导入服务器,然后load csv到neo4j中,可能由于文件所属问题,不能成功导入csv,提示Couldn't load the external resource的错误。
解决:复制可以导入的csv文件为副本,把待导入的数据粘贴到副本中,load csv副本即可

2.
现象: 在外部处理csv数据,进行merge操作的时候,提示cannot merge using null property value for uid的错误。
解决:经发现,是由于指令中的属性拼写错误,导致Neo.ClientError.Statement.SemanticError的错误,例如把sfzh拼写成sfhm

3.
现象: 大量数据的导入问题。
解决:需使用https://neo4j.com/docs/operations-manual/current/tools/import/
注意Import tool is only for newly created databases.
You can use LOAD CSV cypher command to load into an existing database.也就是说neo4j-admin import只会在新建数据库的时候会用到