管弦丝竹,余音袅袅


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

  • 搜索

java内部类学习

发表于 2017-05-29 | 分类于 java | 0 comments

java内部类学习:

  • 内部类的作用:
    • 1.内部类可以很好的实现隐藏
    • 一般的非内部类,是不允许有 private 与protected权限的,但内部类可以
    • 2.内部类拥有外围类的所有元素的访问权限
    • 3.可是实现多重继承(使用内部类去继承其他类实现 外部类的间接多继承)
    • 4.可以避免修改接口而实现同一个类中两种同名方法的调用。
    • (继承的父类和实现的接口类中的方法名相同时,可以用内部类来实现接口,外部类继承其他类,这样就不会与外围类的方法冲突了)

注意:
1.内部类可以随意的访问外部类的成员。包括private等修饰符修饰的变量和方法。但是外部类不能轻松的访问内部类的成员,必须常见一个内部类的实例再去访问。
2.内部类可以拥有private访问权限、protected访问权限、public访问权限及包访问权限。比如上面的例子,如果成员内部类Inner用private修饰,则只能在外部类的内部访问,如果用public修饰,则任何地方都能访问;如果用protected修饰,则只能在同一个包下或者继承外部类的情况下访问;如果是默认访问权限,则只能在同一个包下访问。这一点和外部类有一点不一样,外部类只能被public和包访问两种权限修饰。我个人是这么理解的,由于成员内部类看起来像是外部类的一个成员,所以可以像类的成员一样拥有多种权限修饰。

  • 内部类的类型:
    成员内部类:成员内部类是最普通的内部类,定义在主类体内部的类,类似该类的成员。成员内部类是依附外部类而存在的.
    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
    public class Test {
    public static void main(String[] args) {
    //第一种方式:
    Outter outter = new Outter();
    Outter.Inner inner = outter.new Inner(); //必须通过Outter对象来创建
    //第二种方式:
    Outter.Inner inner1 = outter.getInnerInstance();
    }
    }
    class Outter {
    private Inner inner = null;
    public Outter() {}
    //获取内部类实例对象的方法(单例模式)
    public Inner getInnerInstance() {
    if(inner == null)
    inner = new Inner();
    return inner;
    }
    class Inner {
    public Inner() { }
    }
    }

局部内部类:局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。

1
2
3
4
5
6
7
8
9
10
11
12
13
class People {
}
class Man {
//局部内部类
public People getWoman() {
class Woman extends People { //局部内部类
int age = 23;
}
return new Woman();
}
}

匿名内部类:
1、 匿名内部类是没有访问修饰符的。
2、 new 匿名内部类,这个类首先是要存在的。如果我们将那个InnerClass接口注释掉,就会出现编译出错。
3、 注意getInnerClass()方法的形参,第一个形参是用final修饰的,而第二个却没有。同时我们也发现第二个形参在匿名内部类中没有使用过,所以当所在方法的形参需要被匿名内部类使用,那么这个形参就必须为final。
4、 匿名内部类是没有构造方法的。因为它连名字都没有何来构造方法。

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
public class OuterClass {
public InnerClass getInnerClass(final int num,String str2){
return new InnerClass(){
int number = num + 3;
public int getNumber(){
return number;
}
}; /* 注意:分号不能省 */
}
public static void main(String[] args) {
OuterClass out = new OuterClass();
InnerClass inner = out.getInnerClass(2, "chenssy");
System.out.println(inner.getNumber());
//inner.method4();
}
}
interface InnerClass {
int getNumber();
}
//class InnerClass{
// int getNumber(){};
//
// public void method4() {
// System.out.println("匿名内部类 method4");
// }
//}

静态内部类:static声明的内部类。静态内部类也是定义在另一个类里面的类,只不过在类的前面多了一个关键字static。静态内部类是不需要依赖于外部类的,这点和类的静态成员属性有点类似,并且它不能使用外部类的非static成员变量或者方法,这点很好理解,因为在没有外部类的对象的情况下,可以创建静态内部类的对象,如果允许访问外部类的非static成员就会产生矛盾,因为外部类的非static成员必须依附于具体的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Test {
public static void main(String[] args) {
//不依赖外部类的实例去创建静态内部类的实例对象
Outter.Inner inner = new Outter.Inner();
}
}
class Outter {
public Outter() {
}
static class Inner {
public Inner() {
}
}
}

  • 参考:
    http://blog.csdn.net/a1259109679/article/details/48156407
    http://andy136566.iteye.com/blog/1061951/
    http://www.cnblogs.com/chenssy/p/3388487.html

java反射机制之获取类信息的Util

发表于 2017-05-28 | 分类于 java | 0 comments

#java反射机制之获取类信息的Util

学习反射期间编写的一个能获取类的信息(包括成员变量,成员方法以及构造函数信息)的Util类。对于java反射操作的关键,获取类类型(Class):

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
/**
* Created by g-Linlf on 2017/5/28.
**/
public class ClassUtil {
//获取对象的所有信息 成员方法
public static void getMethodsMessage(Object obj) {
// 获取类类型
//String name = obj.getClass().getName();
//System.out.println(name);
//System.out.println(obj.getClass().getSimpleName());
Class tClass = obj.getClass();
//tClass = Class.forName(name);
System.out.println("类名为:" + tClass.getName());
//获取成员方法 ,万事万物接对象 Method类为方法的对象
//Object[] methods = tClass.getMethods();
Method[] methods = tClass.getMethods();//获取到所有public的函数,包括父类继承过来的
//Method[] methods = tClass.getDeclaredMethods();//获取到该类所有自己声明的方法,不论访问权限。
for (Method method : methods) {
//System.out.println(method);
//获得返回值类类型
Class returnType = method.getReturnType();
System.out.print(returnType.getSimpleName() + " ");
//获得方法名
System.out.print(method.getName() + "(");
//获取参数
//获取参数类型
Class[] paramsType = method.getParameterTypes();
//for (Class class1 : paramsType) {
// System.out.print(class1.getName() + ",");
//}
for (int i = 0; i < paramsType.length; i++) {
if (i == paramsType.length - 1) {
System.out.print(paramsType[i].getName());
} else {
System.out.print(paramsType[i].getName() + ",");
}
}
System.out.println(")");
}
}
//获取对象的成员变量
public static void getFieldMessage(Object obj) {
Class tClass = obj.getClass();
/**
* 成员变量也是对象
* Field封装了关于成员变量的操作
*
*/
System.out.println("--------成员变量---------");
//getFields()获取到所有public的成员变量 getDeclaredFields()获取到该类自己声明的成员变量
//Field[] fields = tClass.getFields();
Field[] fields = tClass.getDeclaredFields();
for (Field field : fields) {
//System.out.println(field);
//变量类型
System.out.print(field.getType() + " ");
// 变量名
System.out.println(field.getName());
}
}
//获取对象的构造函数信息(构造函数 也是对象)
public static void getConMessage(Object obj) {
Class tClass = obj.getClass();
/**
* java.lang.Constructor封装了构造函数的信息
* getConstructors() 获取所有public的构造函数
* getDeclaredConstructors() 获取对象定义的构造函数
*/
//Constructor[] cons = tClass.getConstructors();
Constructor[] cons = tClass.getDeclaredConstructors();
for (Constructor con : cons) {
//获取构造函数的名
System.out.print(con.getName() + "(");
//获取构造函数的参数列表
Class[] paramsType = con.getParameterTypes();
for (int i = 0; i < paramsType.length; i++) {
if (i != paramsType.length - 1) {
System.out.print(paramsType[i].getSimpleName() + ",");
} else {
System.out.print(paramsType[i].getSimpleName());
}
System.out.println(")");
}
}
}
public static void main(String args[]) {
//ClassUtil.getMethodsMessage("123");
Integer num = 1;
//ClassUtil.getFieldMessage(num);
ClassUtil.getConMessage(num);
}
}

数据结构 队列 之java实现

发表于 2017-05-27 | 分类于 数据结构 | 0 comments

数据结构 队列 之java实现

  • 队列:
    队列是一种先进先出的线性表(FIFO),它只允许在表的一端进行插入,而在另一端删除元素。在队列中,允许插入数据一端成为队尾(rear),允许删除的那一端称为队头(front)。
  • 队列的基本操作:
    isEmpty() 判断空队列
    isFull() 判断满队列
    put() 入队列
    get() 出队列
    取队首元素(返回队首元素,不修改队首指针)
    清空队列

-顺序队列:
顺序队列利用一组地址连续的存储单元依次存放自队首到队尾的数据元素,同时由于队的操作的特殊性,还必须附两个位置指针front和rear来动态地指示队首元素和队尾元素在顺序队列中的位置。通常front=rear表示空队列。(rear+1)%maxSize = front表示队满。

-链式队列:
采用链表作为存储结构实现的队列。为便于操作,采用带头结点的单链表实现队列。因为队列的插入和删除操作位置不同,所以链表需要设置表头指针和表尾指针分别指队首和队尾。

-循环队列:
假设向量的空间是m,只要在入出队列时,将队首和队尾的指针对m做求模运算即可实现队首和队尾指针的循环,即队首和队尾指针的取值范围是0到m-1之间。

  • java值demo实现:
    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
    125
    /**
    * Created by g-Linlf on 2017/5/26.
    * 顺序队列
    * 链式队列
    * 循环队列
    **/
    public class TestQueue {
    public static void main(String args[]) throws Exception {
    LinkedListQueue queue1 = new LinkedListQueue();
    queue1.put(1);
    //queue1.put(1);
    queue1.clear();
    System.out.println(queue1.size());
    queue1.put(1);
    System.out.println(queue1.get());
    System.out.println(queue1.isEmpty());
    System.out.println("====================");
    ArrayQueue arrayQueue = new ArrayQueue(2);
    arrayQueue.put(2);
    arrayQueue.put(7);
    System.out.println(arrayQueue.isFull());
    System.out.println(arrayQueue.size());
    System.out.println(arrayQueue.get());
    System.out.println(arrayQueue.isEmpty());
    arrayQueue.clear();
    arrayQueue.put(3);
    System.out.println("====================");
    Queue queue3 = new LinkedBlockingQueue();//
    Queue queue4 = new ArrayBlockingQueue(2);//
    Object[] objects = new Object[2];
    System.out.println(objects[1] == null);
    }
    }
    //使用LinkedList实现
    class LinkedListQueue {
    private LinkedList ll = new LinkedList();
    //入队操作
    public void put(Object o) {
    ll.addLast(o);
    }
    //使用removeFirst()方法,返回队列中第一个数据,然后将它从队列 中删除
    //出队操作
    public Object get() {
    return ll.removeFirst();
    }
    public boolean isEmpty() {
    return ll.isEmpty();
    }
    //队列大小
    public int size() {
    return ll.size();
    }
    //清空队列
    public void clear() {
    ll = null;
    ll = new LinkedList();
    }
    }
    //使用数组实现
    class ArrayQueue {
    private int maxSize;
    private Object[] queue;
    private int front; //头指针 允许删除
    private int rear; //尾指针 允许插入数据
    public ArrayQueue(int size) {
    maxSize = size + 1; //尾指针指向下一个位置(该位置为空)
    queue = new Object[maxSize];
    front = 0;
    rear = 0;
    }
    public void put(Object value) {
    if (isFull()) {
    System.out.println("Full!");
    //throw new RuntimeException("queue is full!");
    return;
    }
    queue[rear] = value;
    rear = (rear + 1) % queue.length;
    }
    public Object get() throws Exception {
    Object value;
    if (isEmpty()) {
    throw new RuntimeException("Empty!");
    }
    value = queue[front];
    queue[front] = null; //释放对象
    front = (front + 1) % queue.length;
    return value;
    }
    //获取实际存储数据大小
    public int size() {
    return (rear - front);
    }
    //清空队列
    public void clear() {
    queue = null;
    queue = new Object[maxSize];
    }
    public boolean isEmpty() {
    return rear == front;
    }
    public boolean isFull() {
    return rear + 1 - front == queue.length;
    //return (rear + 1) % maxSize == front;
    }
    }

数据结构 栈 之java实现

发表于 2017-05-27 | 分类于 数据结构 | 0 comments

数据结构 栈 之java实现

  • 栈:是限制在表的一端进行插入和删除运算的线性表,通常称插入、删除的这一端为栈顶,另一端为栈底。当表中没有元素时成为空栈。(LIFO)后进先出
  • 栈的基本操作:

initStack() //初始化
clearStack() //清空栈
stackEmpty() //判断栈是否为空
stackFull() //判断栈是否满栈
getTop() //获取栈顶元素
push() //从栈顶压入一个元素
pop() //从栈顶删除(取出)一个元素
stackLength() //计算堆栈中元素的个数

  • 顺序栈:顺序栈利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时由于栈的操作的特殊性,还必须附设一个位置指针top来动态地指示栈顶元素的顺序栈中的位置。通常以top=0表示空栈。(java中使可用数组实现栈的基本操作)
  • 链栈:采用链表作为存储结构实现的栈。为便于操作,采用带头结点的单链表实现栈。(java中使用LinkedArray 可以实现栈的基本操作,java也已经有相应的Stack类及其方法)
  • 顺序栈和链栈的比较:
    实现链式栈和顺序栈的操作都是需要常数时间,即时间复杂度为O(1),主要从空间和时间两个方面考虑。初始时,顺序堆栈必须说明一个固定的长度,当堆栈不够满时,造成一些空间的浪费;而链式堆栈的长度可变则使长度不需要预先设定,动态增减,相对比较节省空间,但是在每个节点中设置了一个指针域,从而产生了结构开销。

  • 具体demo实现:

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
/**
* Created by g-Linlf on 2017/5/26.
* <p>
* 方法一使用LinkedList实现栈(链栈)
* (类似链表的栈实现,因为链表不用担心容量的问题)
* 方法二使用数组实现(顺序栈)
* 有容量限制。
**/
public class TestStack {
public static void main(String args[]) {
LinkedListStack stack = new LinkedListStack();
stack.push(1);
System.out.println(stack.size());
System.out.println(stack.peek());
System.out.println(stack.pop());
System.out.println(stack.size());
System.out.println(stack.empty());
//java 已经实现了Stack类extends Vector
Stack stack1 = new Stack();
stack1.push(2);
System.out.println(stack1.size());
System.out.println(stack1.peek());
System.out.println(stack1.pop());
System.out.println(stack1.size());
System.out.println(stack1.empty());
System.out.println("---------------------");
// 测试数组实现 栈大小固定
ArrayStack myStack = new ArrayStack(3);
//myStack.push(3);
//myStack.push(3);
//myStack.push(3);
//myStack.push(3);
System.out.println(myStack.size());
System.out.println(myStack.peek());
System.out.println(myStack.pop());
System.out.println(myStack.empty());
}
}
//使用数组实现
class ArrayStack {
private int top;
private int[] data;
private int maxSize;
public ArrayStack(int cap) {
data = new int[cap];
maxSize = cap - 1;
top = -1;
}
public int size() {
return top+1;
}
public boolean push(int value) {
if (top == maxSize) {
return false;
} else {
data[++top] = value;
return true;
}
}
public int pop() {
if (top == -1) {
return -1;
} else {
return data[top--];
}
}
//获得栈顶元素
public int peek() {
if (top == -1) {
return -1;
} else {
return data[top];
}
}
public boolean empty() {
if (top == -1) {
return true;
} else {
return false;
}
}
}
//使用LinkedList实现
class LinkedListStack {
private LinkedList linkedList = new LinkedList();
//进栈
public void push(Object obj) {
linkedList.addFirst(obj);
}
//出站 移除第一个元素并返回
public Object pop() {
return linkedList.removeFirst();
}
//获得第一个元素(栈顶元素)
public Object peek() {
return linkedList.getFirst();
}
public boolean empty() {
return linkedList.isEmpty();
}
public int size() {
return linkedList.size();
}
}

Java 多态小记

发表于 2017-05-26 | 分类于 java | 0 comments

Java 多态小记

  • 什么是多态

1.面向对象的三大特性:封装、继承、多态。从一定角度来看,封装和继承几乎都是为多态而准备的。
2.多态的定义:指允许不同类的对象对同一消息(方法函数调用)做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用),
3.实现多态的技术称为:动态绑定(dynamic binding),是指在执行期间判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。(父类对象应用指向子类的实例对象)
4.多态的作用:消除类型之间的耦合关系。
5.运行时多态存在的三个必要条件:
一、要有继承(包括接口的实现);
二、要有重写;
三、父类引用指向子类对象。

对静态方法的调用不存在任何动态的分派机制(不存在多态性)。当一个程序调用了一个静态方法,要被调用的方法都是在编译时就被选定的,即调用哪个方法是根据该引用被声明的类型决定的。

注意:静态方法不能被重写为非静态的方法(会编译出错)

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
public class G0526 {
public static void main(String args[]) {
A a = new A();
A b = new B();
a.method1(); //class A method1
b.method1();//class B method1
a.method2(); //class A method2
b.method2();//class A method2
}
}
class A {
public void method1() {
System.out.println("class A method1");
}
public static void method2() {
System.out.println("class A method2");
}
}
class B extends A {
public void method1() {
System.out.println("class B method1");
}
public static void method2() {
System.out.println("class B method2");
}
}

springboot启动器

发表于 2017-05-22 | 分类于 springboot | 0 comments

#springboot启动器

Spring Boot应用启动器基本的一共有(现知道的是44)种:具体如下:

1)spring-boot-starter
这是Spring Boot的核心启动器,包含了自动配置、日志和YAML。
2)spring-boot-starter-actuator
帮助监控和管理应用。
3)spring-boot-starter-amqp
通过spring-rabbit来支持AMQP协议(Advanced Message Queuing Protocol)。
4)spring-boot-starter-aop
支持面向方面的编程即AOP,包括spring-aop和AspectJ。
5)spring-boot-starter-artemis
通过Apache Artemis支持JMS的API(Java Message Service API)。
6)spring-boot-starter-batch
支持Spring Batch,包括HSQLDB数据库。
7)spring-boot-starter-cache
支持Spring的Cache抽象。
8)spring-boot-starter-cloud-connectors
支持Spring Cloud Connectors,简化了在像Cloud Foundry或Heroku这样的云平台上连接服务。
9)spring-boot-starter-data-elasticsearch
支持ElasticSearch搜索和分析引擎,包括spring-data-elasticsearch。
10)spring-boot-starter-data-gemfire
支持GemFire分布式数据存储,包括spring-data-gemfire。
11)spring-boot-starter-data-jpa
支持JPA(Java Persistence API),包括spring-data-jpa、spring-orm、Hibernate。
12)spring-boot-starter-data-mongodb
支持MongoDB数据,包括spring-data-mongodb。
13)spring-boot-starter-data-rest
通过spring-data-rest-webmvc,支持通过REST暴露Spring Data数据仓库。
14)spring-boot-starter-data-solr
支持Apache Solr搜索平台,包括spring-data-solr。
15)spring-boot-starter-freemarker
支持FreeMarker模板引擎。
16)spring-boot-starter-groovy-templates
支持Groovy模板引擎。
17)spring-boot-starter-hateoas
通过spring-hateoas支持基于HATEOAS的RESTful Web服务。
18)spring-boot-starter-hornetq
通过HornetQ支持JMS。
19)spring-boot-starter-integration
支持通用的spring-integration模块。
20)spring-boot-starter-jdbc
支持JDBC数据库。
21)spring-boot-starter-jersey
支持Jersey RESTful Web服务框架。
22)spring-boot-starter-jta-atomikos
通过Atomikos支持JTA分布式事务处理。
23)spring-boot-starter-jta-bitronix
通过Bitronix支持JTA分布式事务处理。
24)spring-boot-starter-mail
支持javax.mail模块。
25)spring-boot-starter-mobile
支持spring-mobile。
26)spring-boot-starter-mustache
支持Mustache模板引擎。
27)spring-boot-starter-redis
支持Redis键值存储数据库,包括spring-redis。
28)spring-boot-starter-security
支持spring-security。
29)spring-boot-starter-social-facebook
支持spring-social-facebook
30)spring-boot-starter-social-linkedin
支持pring-social-linkedin
31)spring-boot-starter-social-twitter
支持pring-social-twitter
32)spring-boot-starter-test
支持常规的测试依赖,包括JUnit、Hamcrest、Mockito以及spring-test模块。
33)spring-boot-starter-thymeleaf
支持Thymeleaf模板引擎,包括与Spring的集成。
34)spring-boot-starter-velocity
支持Velocity模板引擎。
35)spring-boot-starter-web
S支持全栈式Web开发,包括Tomcat和spring-webmvc。
36)spring-boot-starter-websocket
支持WebSocket开发。
37)spring-boot-starter-ws
支持Spring Web Services。

Spring Boot应用启动器面向生产环境的还有2种,具体如下:
1)spring-boot-starter-actuator
增加了面向产品上线相关的功能,比如测量和监控。
2)spring-boot-starter-remote-shell
增加了远程ssh shell的支持。

最后,Spring Boot应用启动器还有一些替换技术的启动器,具体如下:
1)spring-boot-starter-jetty
引入了Jetty HTTP引擎(用于替换Tomcat)。
2)spring-boot-starter-log4j
支持Log4J日志框架。
3)spring-boot-starter-logging
引入了Spring Boot默认的日志框架Logback。
4)spring-boot-starter-tomcat
引入了Spring Boot默认的HTTP引擎Tomcat。
5)spring-boot-starter-undertow
引入了Undertow HTTP引擎(用于替换Tomcat)。

spring boot 之Controller简单单元测试(RESTful API)

发表于 2017-05-22 | 分类于 springboot | 0 comments

#spring boot 之Controller简单单元测试(RESTful API)

MocMvc做为服务端测试类,功能十分强大;在spring全家桶中,在springMVC和springboot中都可以使用,用法十分相似。

  • 首先需要在pom.xml中加入依赖配置。
1
2
3
4
5
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

###第一种使用注解方法注入MocMvc
//@RunWith(SpringJUnit4ClassRunner.class) SpringRunner extends SpringJUnit4ClassRunner
@RunWith(SpringRunner.class)
@WebAppConfiguration //支持web项目注解
@SpringBootTest////(classes = DemoApplication.class, webEnvironment = SpringBootTest.WebEnvironment.MOCK)指定SpringBoot工程的Application启动类
@AutoConfigureMockMvc
public class TestController {
@Autowired
private MockMvc mockMvc;
@Autowired
private UserService userService;

@Test
public void testUser() throws Exception {
    //提交请求 构建RequestBuilder对象,模拟request请求
    RequestBuilder request = null;
    request = MockMvcRequestBuilders.get("/");
    mockMvc.perform(request).andExpect(status().isOk()).andReturn();
    mockMvc.perform((post("/hello"))).andExpect(status().isOk())
            .andDo(print()).andReturn();
}

###第二种手动注入MocMvc(分为集成web环境和独立测试方式)

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
@RunWith(SpringRunner.class)
@WebAppConfiguration //支持web项目注解
@SpringBootTest////(classes = DemoApplication.class, webEnvironment = SpringBootTest.WebEnvironment.MOCK)指定SpringBoot工程的Application启动类
public class TestController {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext wac;
//集成Web环境方式 ()
@Before
public void setUp() {
this.mockMvc = webAppContextSetup(this.wac).build();
}
//独立测试
//@Before
//public void setUp() {
// IndexController indexController =new IndexController();
// this.mockMvc = MockMvcBuilders.standaloneSetup(indexController).build();
//}
@Test
public void testUser() throws Exception {
//提交请求 构建RequestBuilder对象,模拟request请求
RequestBuilder request = null;
request = MockMvcRequestBuilders.get("/");
mockMvc.perform(request).andExpect(status().isOk()).andReturn();
mockMvc.perform((post("/hello"))).andExpect(status().isOk())
.andDo(print()).andReturn();
}

1、@WebAppConfiguration:测试环境使用,用来表示测试环境使用的ApplicationContext将是WebApplicationContext类型的;value指定web应用的根;
2、通过@Autowired WebApplicationContext wac:注入web环境的ApplicationContext容器;
3、然后通过MockMvcBuilders.webAppContextSetup(wac).build()创建一个MockMvc进行测试;

  • 几个常用的方法:

perform:执行一个RequestBuilder请求,会自动执行SpringMVC的流程并映射到相应的控制器执行处理;
andExpect:添加ResultMatcher验证规则,验证控制器执行完成后结果是否正确;
andDo:添加ResultHandler结果处理器,比如调试时打印结果到控制台;
andReturn:最后返回相应的MvcResult;然后进行自定义验证/进行下一步的异步处理;

  • 参考

spring boot 基于Controller自动化测试demo
Junit学习笔记之五:MockMVC

springboot 将默认web容器tomcat 换成 jetty

发表于 2017-05-21 | 分类于 springboot | 0 comments

springboot 将默认web容器tomcat 换成 jetty

springboot框架默认集成(tomcat或jetty)web容器,web容器也使用默认配置,不过也可在配置文件(application.properties)中进行重写覆盖;springboot项目的启动方式和java程序类似,使用main()方法启动非常方便快捷(也可以使用maven命令启动 mvn spring- boot:run)。框架默认使用tomcat容器,下面介绍如何将默认容器tomcat换成jetty容器。

###第一步修改pom.xml的配置,将原来的默认的tomcat依赖配置去掉;新增jetty依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!--把pom中的tomcat依赖排除-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--增加jetty依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
</dependencies>

###第二步(方法一)在(DemoApplication.java命名可能不同)启动类中继承SpringBootServletInitializer类重写configure()方法;

1
2
3
4
5
6
7
8
9
10
11
@SpringBootApplication
public class DemoApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(this.getClass());
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

###第二步(方法二)注入Jetty容器的管理Bean,在(DemoApplication.java命名可能不同)启动类中:

1
2
3
4
5
6
7
8
9
10
11
12
13
@SpringBootApplication
public class DemoApplication {
@Bean
public EmbeddedServletContainerFactory servletContainer() {
JettyEmbeddedServletContainerFactory factory =
new JettyEmbeddedServletContainerFactory();
return factory;
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}

内置服务器配置覆盖说明使用可参见其他blog;项目亦可打包成war包手动放置web容器(tomcat,weblogic等)中进行项目部署。

how to use idea create a springboot web project

发表于 2017-05-21 | 分类于 springboot | 0 comments

#how to use idea create a springboot web project

第一步:打开idea,点检File–>New–>project

第二步:

images

第三步:

images

第四步:

images

第五步:

images

第六步:生成的项目结构

images

JVM概况了解

发表于 2017-05-14 | 分类于 JVM | 0 comments

JVM了解学习

Java程序的跨平台特性主要是指字节码文件可以在任何具有Java虚拟机的计算机或者电子设备上运行,Java虚拟机中的Java解释器负责将字节码文件解释成为特定的机器码进行运行。因此在运行时,Java源程序需要通过编译器编译成为.class文件。众所周知java.exe是Java class文件的执行程序,但实际上java.exe程序只是一个执行的外壳,它会装载jvm.dll(windows下,下皆以windows平台为例,Linux下和solaris下其实类似,为:libjvm.so),这个动态连接库才是java虚拟机的实际操作处理所在。
JVM是JRE的一部分。它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java语言最重要的特点就是跨平台运行。使用JVM就是为了支持与操作系统无关,实现跨平台。所以,JAVA虚拟机JVM是属于JRE的,而现在我们安装JDK时也附带安装了JRE(当然也可以单独安装JRE)。

JVM = 类加载器 classloader + 执行引擎 execution engine + 运行时数据区域 runtime data areaclassloader 把硬盘上的class 文件加载到JVM中的运行时数据区域, 但是它不负责这个类文件能否执行,而这个是 执行引擎 负责的。

##类加载器:
作用:装载.class文件classloader 有两种装载class的方式 (时机):
隐式:运行过程中,碰到new方式生成对象时,隐式调用classLoader到JVM
显式:通过class.forname()动态加载
类加载器 classloader 是具有层次结构的,也就是父子关系。其中,Bootstrap 是所有类加载器的父亲。这个类加载器不是用 java 语言写的,而是用 C/C++ 写的。

##执行引擎:
作用: 执行字节码,或者执行本地方法

##运行时数据区:主要包括:
Java虚拟机栈:java 虚拟机栈也是线程私有的。每一个 JVM 线程都有自己的 java 虚拟机栈,这个栈与线程同时创建,它的生命周期与线程相同。虚拟机栈描述的是Java 方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程
本地方法栈:与虚拟机栈的作用相似,虚拟机栈为虚拟机执行执行java方法服务,而本地方法栈则为虚拟机使用到的本地方法服务。
java堆:被所有线程共享的一块存储区域,在虚拟机启动时创建,它是JVM用来存储对象实例以及数组值的区域,可以认为Java中所有通过new创建的对象的内存都在此分配。(JVM将Heap分为两块:新生代New Generation和旧生代Old Generation),
PC程序计数器:一块较小的内存空间,可以看做是当前线程所执行的字节码的行号指示器, NAMELY存储每个线程下一步将执行的JVM指令,如该方法为native的,则PC寄存器中不存储任何信息。Java 的多线程机制离不开程序计数器,每个线程都有一个自己的PC,以便完成不同线程上下文环境的切换。
方法区:方法区和堆区域一样,是各个线程共享的内存区域,它用于存储每一个类的结构信息,例如运行时常量池,成员变量和方法数据,构造函数和普通函数的字节码内容,还包括一些在类、实例、接口初始化时用到的特殊方法。当开发人员在程序中通过Class对象中的getName、isInstance等方法获取信息时,这些数据都来自方法区。
运行时常量池:(其空间从方法区中分配,存放的为类中固定的常量信息、方法和域的引用信息)
参见个人学习整理的JVM运行时数据区域总结

##垃圾回收机制GC。
垃圾回收机制是由垃圾收集器Garbage Collection GC来实现的,GC是后台的守护进程。垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,按照特定的垃圾收集算法来实现资源自动回收的功能。当一个对象不再被引用的时候,内存回收它占领的空间,以便空间被后来的新对象使用,以免造成内存泄露。
参考个人GC学习总结

JVM 的 工作原理,层次结构 以及 GC工作原理
Java内存管理:深入Java内存区域

123
glinlf

glinlf

心之所向 步履维艰

24 日志
11 分类
34 标签
© 2017 glinlf
由 Hexo 强力驱动
主题 - NexT.Pisces