0%

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只会在新建数据库的时候会用到

What is

Java Persistence API is a collection of classes and methods to persistently store the vast amounts of data into a database which is provided by the Oracle Corporation.

Where to use

To reduce the burden of writing codes for relational object management, a programmer follows the ‘JPA Provider’ framework, which allows easy interaction with database instance. Here the required framework is taken over by JPA.

  • JPA Pro

    JPA is an open source API, therefore various enterprise vendors such as Oracle, Redhat, Eclipse, etc. provide new products by adding the JPA persistence flavor in them. Some of these products include:Hibernate, Eclipselink, Toplink, Spring Data JPA, etc.

Architecture

  • jpa class relationships

  • ORM Architecture

  • Entity Relationships

    • @ManyToOne Relation
    • @OneToMany Relation
    • @OneToOne Relation
    • @ManyToMany Relation

Creating Java Streams

  1. We can use Stream.of() to create a stream from similar type of data. For example, we can create Java Stream of integers from a group of int or Integer objects.
    1
    Stream<Integer> stream = Stream.of(1,2,3,4);
  2. We can use Stream.of() with an array of Objects to return the stream. Note that it doesn’t support autoboxing, so we can’t pass primitive type array.
    1
    2
    3
    4
    5
    Stream<Integer> stream = Stream.of(new Integer[]{1,2,3,4}); 
    //works fine

    Stream<Integer> stream1 = Stream.of(new int[]{1,2,3,4});
    //Compile time error, Type mismatch: cannot convert from Stream<int[]> to Stream<Integer>
  3. We can use Collection stream() to create sequential stream and parallelStream() to create parallel stream.
    1
    2
    3
    4
    5
    6
    7
    8
    List<Integer> myList = new ArrayList<>();
    for(int i=0; i<100; i++) myList.add(i);

    //sequential stream
    Stream<Integer> sequentialStream = myList.stream();

    //parallel stream
    Stream<Integer> parallelStream = myList.parallelStream();
  4. We can use Stream.generate() and Stream.iterate() methods to create Stream.
    1
    2
    Stream<String> stream1 = Stream.generate(() -> {return "abc";});
    Stream<String> stream2 = Stream.iterate("abc", (i) -> i);
  5. Using Arrays.stream() and String.chars() methods.
    1
    2
    LongStream is = Arrays.stream(new long[]{1,2,3,4});
    IntStream is2 = "abc".chars();

Converting Java Stream to Collection or Array

  1. We can use java Stream collect() method to get List, Map or Set from stream.
    1
    2
    3
    4
    5
    6
    7
    Stream<Integer> intStream = Stream.of(1,2,3,4);
    List<Integer> intList = intStream.collect(Collectors.toList());
    System.out.println(intList); //prints [1, 2, 3, 4]

    intStream = Stream.of(1,2,3,4); //stream is closed, so we need to create it again
    Map<Integer,Integer> intMap = intStream.collect(Collectors.toMap(i -> i, i -> i+10));
    System.out.println(intMap); //prints {1=11, 2=12, 3=13, 4=14}
  2. We can use stream toArray() method to create an array from the stream.
    1
    2
    3
    Stream<Integer> intStream = Stream.of(1,2,3,4);
    Integer[] intArray = intStream.toArray(Integer[]::new);
    System.out.println(Arrays.toString(intArray)); //prints [1, 2, 3, 4]

Java Stream Intermediate Operations

  1. Stream filter() : We can use filter() method to test stream elements for a condition and generate filtered list.
    1
    2
    3
    4
    5
    6
    7
    8
    List<Integer> myList = new ArrayList<>();
    for(int i=0; i<100; i++) myList.add(i);
    Stream<Integer> sequentialStream = myList.stream();

    Stream<Integer> highNums = sequentialStream.filter(p -> p > 90); //filter numbers greater than 90
    System.out.print("High Nums greater than 90=");
    highNums.forEach(p -> System.out.print(p+" "));
    //prints "High Nums greater than 90=91 92 93 94 95 96 97 98 99 "
  2. Stream map() : We can use map() to apply functions to an stream. Let’s see how we can use it to apply upper case function to a list of Strings.
    1
    2
    3
    4
    5
    Stream<String> names = Stream.of("aBc", "d", "ef");
    System.out.println(names.map(s -> {
    return s.toUpperCase();
    }).collect(Collectors.toList()));
    //prints [ABC, D, EF]
  3. Stream sorted() : We can use sorted() to sort the stream elements by passing Comparator argument.
    1
    2
    3
    4
    5
    6
    7
    Stream<String> names2 = Stream.of("aBc", "d", "ef", "123456");
    List<String> reverseSorted = names2.sorted(Comparator.reverseOrder()).collect(Collectors.toList());
    System.out.println(reverseSorted); // [ef, d, aBc, 123456]

    Stream<String> names3 = Stream.of("aBc", "d", "ef", "123456");
    List<String> naturalSorted = names3.sorted().collect(Collectors.toList());
    System.out.println(naturalSorted); //[123456, aBc, d, ef]
  4. Stream flatMap() : We can use flatMap() to create a stream from the stream of list. Let’s see a simple example to clear this doubt.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Stream<List<String>> namesOriginalList = Stream.of(
    Arrays.asList("Pankaj"),
    Arrays.asList("David", "Lisa"),
    Arrays.asList("Amit"));
    //flat the stream from List<String> to String stream
    Stream<String> flatStream = namesOriginalList
    .flatMap(strList -> strList.stream());

    flatStream.forEach(System.out::println);

Java Stream Terminal Operations

  1. Stream reduce() example: We can use reduce() to perform a reduction on the elements of the stream, using an associative accumulation function, and return an Optional. Let’s see how we can use it multiply the integers in a stream.
    1
    2
    3
    4
    Stream<Integer> numbers = Stream.of(1,2,3,4,5);

    Optional<Integer> intOptional = numbers.reduce((i,j) -> {return i*j;});
    if(intOptional.isPresent()) System.out.println("Multiplication = "+intOptional.get()); //120
  2. Stream count() example: We can use this terminal operation to count the number of items in the stream.
    1
    2
    Stream<Integer> numbers1 = Stream.of(1,2,3,4,5);
    System.out.println("Number of elements in stream="+numbers1.count()); //5
  3. Stream forEach() example: This can be used for iterating over the stream. We can use this in place of iterator. Let’s see how to use it for printing all the elements of the stream.
    1
    2
    Stream<Integer> numbers2 = Stream.of(1,2,3,4,5);
    numbers2.forEach(i -> System.out.print(i+",")); //1,2,3,4,5,
  4. Stream match() examples: Let’s see some of the examples for matching methods in Stream API.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Stream<Integer> numbers3 = Stream.of(1,2,3,4,5);
    System.out.println("Stream contains 4? "+numbers3.anyMatch(i -> i==4));
    //Stream contains 4? true

    Stream<Integer> numbers4 = Stream.of(1,2,3,4,5);
    System.out.println("Stream contains all elements less than 10? "+numbers4.allMatch(i -> i<10));
    //Stream contains all elements less than 10? true

    Stream<Integer> numbers5 = Stream.of(1,2,3,4,5);
    System.out.println("Stream doesn't contain 10? "+numbers5.noneMatch(i -> i==10));
    //Stream doesn't contain 10? true
  5. Stream findFirst() :This is a short circuiting terminal operation, let’s see how we can use it to find the first string from a stream starting with D.
    1
    2
    3
    4
    5
    Stream<String> names4 = Stream.of("Pankaj","Amit","David", "Lisa");
    Optional<String> firstNameWithD = names4.filter(i -> i.startsWith("D")).findFirst();
    if(firstNameWithD.isPresent()){
    System.out.println("First Name starting with D="+firstNameWithD.get()); //David
    }

some example

1
2
3
4
5
6
//merge collection
List<String> resultPersonnos = Stream.of(list1, list2)
.flatMap(Collection::stream)
.distinct()
.sorted()
.collect(Collectors.toList());

  • 安装插件

    CTRL + SHIFT + P并且输入Package Control: Install Package

  • html格式化

    输入!,然后按 TAB

  • Pretty JSON插件

    格式化 CTRL + ALT + J

语法

  • 设置标签属性

    $("div").attr("属性名","属性值");

  • 设置标签样式

    $("div").css("color","yellow"); $("div").css("padding-left"))

  • 移除属性

    $("div").removeAttr("id");

  • 遍历数组

    • 原生js有两种方法都可以使用[for(var i;i<arr.length;i++){},for(var i in arr){}]

    • jquery有两个函数共计四种方法都可以使用

      1
      2
      3
      4
      $.each(arr,function(i,item){}),
      $(arr).each(function(i,item){}),
      $.map(arr,function(i,item){}),
      $(arr).map(function(i,item){})
  • 遍历对象

    • 原生js有一种方法可以使用[for(var i in obj){}]

    • jquery有两个函数共计两种方法可以使用

      1
      2
      $.each(obj,function(i,item){})
      $.map(obj,function(i,item){})
  • Jquery中的ajax在默认不写async情况下,请求为异步请求;即:async:true

  • $(function(){ })是定义一个匿名函数,它是$(document).ready(function(){})的简写

关于代码编译的事情

  • 问题

    • 由于一些配置项写在统一的配置文档中,代码从配置文件中读取确定的配置项;此时操作的文本路径是要追加上根目录的路径,然而开发环境和生成环境是不一样的。项目在打包的过程中,就确定了文本路径,这样导致两边环境的配置文档读取结果不一致。
  • 解决办法

    • 把文件路径精确写入
    • 在生成环境下编译代码

关于读取数据量大的excel文件

  • 问题

    • 项目部署到tomcat中,每次读取大于1M的文件时,会停滞在org.apache.poi.ss.usermodel.Workbook workbook = new XSSFWorkbook(is);,直到tomcat出现报错信息java.lang.OutOfMemoryError: Java heap space ,即java虚拟机堆溢出的错误。
  • 现象描述

    • 手动设置Xms,Xmx的大小,在/bin/catalina.bat(windows环境)配置中,添加JAVA_OPTS="-server -Xms10G -Xmx20G",不知道什么原因,重启服务,仍旧报一样的错。(当我在自己电脑上运行程序,操作同样大小的文档时,也没有报错,何况自己电脑才8G内存,远不及服务器,再则就是自身电脑tomcat的配置也是默认的)

    • 内存总体分为年轻代(young),老年代(old),永久代(permanent),如图

      7OCHl.jpg