0%

Docker基础命令

运行容器:

docker run -i -t ubuntu /bin/bash

docker run -i -t ubuntu:12.04 /bin/bash 运行特定tag标定的容器

-i:开启STDIN
-t:分配一个伪终端

docker run –rm ….

–rm:运行结束后删除容器并清理,等价于容器退出后执行docker rm -v

Read more »

svn迁移到git

为什么要从svn迁移到git?
svn适合项目管理,将项目产出(包括交付代码)在svn上进行管理,有细粒度的权限控制,但不适合代码管理,svn分支和tag太重,使用svn不容易做到开发流程管控,而且极容易出现代码相互覆盖,git配合git flow可以很容易做到代码开发流程管控。

如何从svn迁移到git

  1. git svn命令,git提供了此命令,使使用svn可以使用git命令。
  2. 将svn迁出到本地使用git初始化为git仓库。
  3. 在git服务器新建仓库。
  4. 将本地代码推送到远程git仓库。

安装git-svn

CentOS:

yum install -y git-svn

MacOSX:

brew install git subversion

其他操作系统自理。

Read more »

Spring Security认证授权基本结构

web下大概流程图

Spring Security的Filter

Spring Security通过一系列的Fliter来进行认证授权。
通过SecurityFilterAutoConfiguration注册一系列的SecurityFilter到FilterChainProxy,对请求进行一层层过滤。
Spring Security内置的Fliter,按照顺序如下:

  1. ChannelProcessingFilter,如果你访问的 channel 错了,那首先就会在 channel 之间进行跳转,如 http 变为 https。
  2. SecurityContextPersistenceFilter,一开始进行request的时候在SecurityContextHolder中建立一个SecurityContext,然后在请求结束的时候,任何对SecurityContext的改变都可以被copy到HttpSession。
  3. ConcurrentSessionFilter,因为它需要使用 SecurityContextHolder 的功能,而且更新对应 session 的最后更新时间,以及通过SessionRegistry 获取当前的 SessionInformation 以检查当前的session 是否已经过期,过期则会调用 LogoutHandler。
  4. 认证处理Filter,如 UsernamePasswordAuthenticationFilter,CasAuthenticationFilter,BasicAuthenticationFilter 等,以至于 SecurityContextHolder 可以被更新为包含一个有效的 Authentication 请求。
  5. SecurityContextHolderAwareRequestFilter,它将会把HttpServletRequest 封装成一个继承自 HttpServletRequestWrapper 的 SecurityContextHolderAwareRequestWrapper,同时使用SecurityContext 实现了 HttpServletRequest 中与安全相关的方法。
  6. JaasApiIntegrationFilter,如果 SecurityContextHolder 中拥有的 Authentication 是一个 JaasAuthenticationToken,那么该 Filter 将使用包含在 JaasAuthenticationToken 中的 Subject 继续执行 FilterChain。
  7. RememberMeAuthenticationFilter,如果之前的认证处理机制没有更新 SecurityContextHolder,并且用户请求包含了一个 Remember-Me 对应的 cookie,那么一个对应的 Authentication 将会设给 SecurityContextHolder。
  8. AnonymousAuthenticationFilter,如果之前的认证机制都没有更新 SecurityContextHolder 拥有的 Authentication,那么一个AnonymousAuthenticationToken 将会设给 SecurityContextHolder。
  9. ExceptionTransactionFilter,用于处理在 FilterChain 范围内抛出的 AccessDeniedException 和 AuthenticationException,并把它们转换为对应的Http错误码返回或者对应的页面。
  10. FilterSecurityInterceptor,保护 Web URI,并且在访问被拒绝时抛出异常。

其中,通常需要扩展的地方在4这个位置。可以通过AbstractConfiguredSecurityBuilder的addFilter方法进行添加,addFilter方法可指定添加位置,自定义的Filter要添加到FilterSecurityInterceptor之前ConcurrentSessionFilter之后。

Read more »

求斐波那契数列第N个数

斐波那契数列的数学公式:

  • F(0)=0
  • F(1)=1
  • F(n)=F(n-1)+F(n-2) {n>=2}

后一个数等于它前两个数的和。

前13个为:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233

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
/**
* functional describe:1,1,2,3,5,8...f(n) = f(n-1)+ f(n-2)
*
* @author DR.YangLong [410357434@163.com]
* @version 1.0 2017/6/15
*/
public class Fibonacci {
/***
* 递归实现方式
* @param n 第n位
* @return 第n位的数值
*/
public static int fibonacci(int n) {
if (n <= 2) {
return 1;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}


/**
* 递推实现方式
* @param n 第n位
* @return 第n位的数值
*/
public static int fibonacciLoop(int n) {
if (n <= 2) {
return 1;
}
int n1 = 1, n2 = 1, sn = 0;
for (int i = 0; i < n - 2; i++) {
sn = n1 + n2;
n1 = n2;
n2 = sn;
}
return sn;
}

public static void main(String[] args) {
//1、1、2、3、5、8、13、21、34、55、89、144、233
System.out.println(fibonacci(5));
System.out.println(fibonacciLoop(5));
}

}

基于链表的map结构实现

定义map接口以及key比较器接口

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
public interface Map<K, V> {
/**
* 获取map中元素数量
*
* @return
*/
int size();

/**
* map是否为null
*
* @return
*/
boolean isEmpty();

/**
* 获取key映射的元素
*
* @param key
* @return
*/
V get(K key);

/**
* 向map中放入映射
*
* @param key
* @param val
* @return
*/
V put(K key, V val);

/**
* @param key
* @return
*/
V remove(K key);

/**
* 获取映射集合,使用集合迭代map
* @return
*/
Collection<Entry<K,V>> entries();



interface Entry<K, V> {
/**
* 获取关键码
*
* @return
*/
K getKey();

/**
* 获取entry值
*
* @return
*/
V getValue();

/**
* 更新entry值
*
* @return
*/
V setValue(V val);
}
}


public interface KeyComparator<K> {
default boolean equals(K key1,K key2){
return Objects.equals(key1,key2);
}
}

key比较器及map实现类

1
2
3
//使用接口的默认实现
public class NormalKeyComparator<K> implements KeyComparator<K>{
}
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
public class ListBaseMap<K, V> implements Map<K, V> {
private LinkedList<Entry<K, V>> table;
private KeyComparator<K> keyComparator;

public ListBaseMap(LinkedList<Entry<K, V>> table, KeyComparator<K> keyComparator) {
this.table = table;
this.keyComparator = keyComparator;
}

public ListBaseMap(KeyComparator<K> keyComparator) {
this.table = new LinkedList<>();
this.keyComparator = keyComparator;
}

public ListBaseMap() {
this.table = new LinkedList<>();
this.keyComparator = new NormalKeyComparator<>();
}


static class Node<K, V> implements Entry<K, V> {
private K key;
private V value;

public Node(K key, V value) {
this.key = key;
this.value = value;
}

@Override
public K getKey() {
return this.key;
}

@Override
public V getValue() {
return this.value;
}

@Override
public V setValue(V val) {
V old = this.value;
this.value = val;
return old;
}

@Override
public boolean equals(Object obj) {
if (obj == this) return true;
if (obj instanceof Entry) {
Entry<?, ?> e = (Entry<?, ?>) obj;
return Objects.equals(e.getKey(), this.getKey())
&& Objects.equals(e.getValue(), this.getValue());
}
return false;
}

@Override
public String toString() {
return "ke=["+key+"],value=["+value+"]";
}
}

@Override
public int size() {
return table.size();
}

@Override
public boolean isEmpty() {
return table.isEmpty();
}

@Override
public V get(K key) {
if (size() > 0) {
for (Entry<K, V> entry : table) {
if (Objects.equals(key, entry.getKey())) {
return entry.getValue();
}
}
}
return null;
}

@Override
public V put(K key, V val) {
Node<K, V> node = new Node<>(key, val);
if (size() == 0) {
table.add(node);
} else {
for (Entry<K, V> entry : table) {
if (Objects.equals(key, entry.getKey())) {
V old = entry.getValue();
entry.setValue(val);
return old;
}
}
table.add(node);
}
return null;
}

@Override
public V remove(K key) {
if (size() > 0) {
int count = 0;
for (Entry<K, V> entry : table) {
if (Objects.equals(key, entry.getKey())) {
V oldVal = entry.getValue();
table.remove(count);
return oldVal;
}
count++;
}
}
return null;
}

@Override
public Collection<Entry<K, V>> entries() {
return table;
}
}

合并排序

将数列不停的拆分,直到只剩下一个元素,此时必然有序,然后将拆分的部分两两合并,最后成为一个有序数列。

实现

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
import java.util.Comparator;
import java.util.LinkedList;

import static java.lang.System.out;

/**
* functional describe:基于队列结构的归并排序算法(队列可换成数组,一般示例为数组)
*
* @author DR.YangLong [410357434@163.com]
* @version 1.0 2017/8/8
*/
public class MergeSort<T> {
private Comparator<T> comparator;

//拆分,将s不断的拆分,直至拆分成一个元素的queue,则此时是有序的,然后合并
public void sort(LinkedList<T> s) {
int size = s.size();
if (1 >= size) return;//递归基
LinkedList<T> s1 = new LinkedList<>();
LinkedList<T> s2 = new LinkedList<>();
while (!s.isEmpty()) {//将s拆分到s1和s2
s1.addLast(s.removeFirst());
if (!s.isEmpty()) s2.addLast(s.removeFirst());
}
//递归拆分
sort(s1);
sort(s2);
//合并单个元素的queue
merge(s, s1, s2);
}

//合并,将2个有序queue合并成一个有序queue,使用2个待合并的queue长度为条件进行循环。
private void merge(LinkedList<T> container, LinkedList<T> s1, LinkedList<T> s2) {
while (!s1.isEmpty() || !s2.isEmpty()) {//只要其中一个不为空
T e;//s1和s2中取出的较小元素
if (s1.isEmpty()) {//s1已经取光,从s2中取
e = s2.removeFirst();
} else if (s2.isEmpty()) {//s2已经取光,从s1中取
e = s1.removeFirst();
} else if (comparator.compare(s1.getFirst(), s2.getFirst()) > 0) {//如果s1中第一个大于s2中第一个,则e取s2中第一个
e = s2.removeFirst();
} else {//s1中第一个小于s2中第一个,e取s1第一个
e = s1.removeFirst();
}
//将e放入目标容器队尾
container.addLast(e);
}
}

public MergeSort(Comparator<T> comparator) {
this.comparator = comparator;
}

public static void main(String[] args) {
MergeSort<Integer> sort = new MergeSort<>((o1, o2) -> {
if (o1 < o2) return -1;
if (o1 > o2) return 1;
return 0;
});
LinkedList<Integer> list=new LinkedList<>();
list.add(0);
list.add(8);
list.add(6);
list.add(9);
list.add(7);
list.add(2);
list.add(4);
list.add(3);
list.add(5);
list.add(1);
sort.sort(list);
list.forEach(out::print);
}
}

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
import java.util.Arrays;

import static java.lang.System.out;

/**
* functional describe:快速排序算法
*
* @author DR.YangLong [410357434@163.com]
* @version 1.0 2017/5/16 14:15
*/
public class QuickSort {

//找中轴线
public static int midIndex(int[] a, int i, int j) {
int l = i, r = j;//获取排序的区间
int x = a[i];//第一个数作为基数
while (l < r) {
while (l < r && a[r] >= x) r--;//从后向前找到第一个比基准数小的数
if (l < r) {
a[l] = a[r];//将小的数填到基准数左边
l++;//向后移动一个位置
}
while (l < r && a[l] <= x) l++;//从前向后找到比基准数大的数
if (l < r) {
a[r] = a[l];
r--;//向前移动一个位置
}
}
a[l] = x;//循环退出时i=j位中间位置
return l;
}

//排序
static void sort(int[] a, int l, int r) {
if (l < r) {
int midIndex = midIndex(a, l, r);
sort(a, l, midIndex - 1);
sort(a, midIndex + 1, r);
}
}

/**
* 合并版本
* @param a 待排序数组
* @param left 排序数组起始位置
* @param right 排序数组结束位置
*/
public static void quickSort(int[] a, final int left, final int right) {
if (null != a && a.length > 0 && left >= 0 && right > left && right < a.length) {
int i = left, j = right;
int x = a[left];//中间数,空出i的位置
while (i < j) {
while (i < j && a[j] >= x) j--;//从后向前找,直到找到第一个比基数小的数,停止
if (i < j) {
a[i++] = a[j];//填到i的位置,并且下轮填到i的下一个位置,此时j的位置空出
}
while (i < j && a[i] <= x) i++;//从前向后找,直到找到第一个比基数大的数,停止
if (i < j) {
a[j--] = a[i];//将大的数放到j的位置,并且下轮填到j的前一个位置,此时i的位置空出
}
}
a[i] = x;//循环结束,找到中间位置i,将中间数填入
quickSort(a, left, i-1);//对左边部分排序
quickSort(a, i+1, right);//对右边部分排序
}
}

public static void main(String[] args) {
int[] a = {1, 2, 3, 7, 1, 6, 7, 8, 4, 3, 3, 9};
sort(a, 0, a.length - 1);
Arrays.stream(a).forEach(out::print);
System.out.println("\n==================");
int []b = {1, 2, 3, 7, 1, 6, 7, 8, 4, 3, 3, 9};
quickSort(b,0,b.length-1);
Arrays.stream(b).forEach(out::print);
}
}

基于数组的stack结构实现

接口定义

1
2
3
4
5
6
7
8
9
10
11
12
public interface Stack {
//栈大小
int getSize();
//入栈
void push(Object o);
//出栈
Object pop();
//是否为空
boolean isEmpty();
//查看栈顶端元素,不删除
Object top();
}
Read more »

Kryo序列化

新版kryo提供了工厂类和序列化池,不用自己实现序列化池了。

工场类:

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
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.Serializer;
import com.esotericsoftware.kryo.pool.KryoFactory;

import java.util.HashMap;

/**
* functional describe:Kryo工厂类,<code>registerMap</code>为需要自定义注册的类及其序列化器
*
* @author DR.YangLong [410357434@163.com]
* @version 1.0 2018/2/6
*/
public class CustomKryoFactory implements KryoFactory {
//有并发需求的话改为线程安全的map
private HashMap<Class, Serializer> registerMap;

@Override
public Kryo create() {
Kryo kryo = new Kryo();
if (null != registerMap && registerMap.size() > 0) {
registerMap.forEach((k, v) ->
{
if (v != null) {
kryo.register(k, v);
} else {
kryo.register(k);
}
});
}
return kryo;
}

public HashMap<Class, Serializer> getRegisterMap() {
return registerMap;
}

public void setRegisterMap(HashMap<Class, Serializer> registerMap) {
this.registerMap = registerMap;
}
}
Read more »

Eureka客户端和服务端的通讯

使用Eureka的第一步是进行Eureka client的初始化。如果你是在AWS中使用,可以使用以下方式进行初始化:
使用1.1.153版本时,客户端可以和governator/guice一其使用,详细请看示例
在1.1.153版本之前,你可以使用以下方式进行客户端初始化:

1
2
3
DiscoveryManager.getInstance().initComponent(
new CloudInstanceConfig(),
new DefaultEurekaClientConfig());

如果你是在其他数据中心使用,则使用以下方式:

1
2
3
DiscoveryManager.getInstance().initComponent(
new MyDataCenterInstanceConfig(),
new DefaultEurekaClientConfig());

Eureka Client查找并使用eureka-client.properties,相关信息看第二章客户端配置。

Read more »