Java反射之方法

原文地址Java Reflection Methods

Obtaining Method Objects

获取类的方法,Method[]数组里面只包含类中public修饰的方法

1
Method[] methods = orderClass.getMethods();

也可以使用具体的方法名及参数类型直接获取,以Order类中的getState(),setState()方法为例:

1
2
3
4
5
6
7
8
9
10
try {
Method methodHaveNoParameter = orderClass.getMethod("getState",null);//该方法没有参数,null省略也可以
System.out.println(methodHaveNoParameter.getName());//getState

Method methodHaveParameter = orderClass.getMethod("setState",new Class[]{String.class});//该方有String类型参数
System.out.println(methodHaveParameter.getName());//setState

} catch (NoSuchMethodException e) {
e.printStackTrace();
}

Method Parameters and Return Types

获取方法的参数类型及返回类型

1
2
3
4
5
Class[] parameters = methodHaveParameter.getParameterTypes();
System.out.println(parameters[0].getName());//class java.lang.String

Class returnType = methodHaveParameter.getReturnType();
System.out.println(returnType);//void

Invoking Methods using Method Object

使用invoke调用方法,以Order类中的pay()方法为例,该方法直接返回一个字符串

1
2
3
4
5
6
7
8
9
10
11
12
try {
Method methodPay = orderClass.getMethod("pay",new Class[]{String.class});
Order order = new Order();
Object returnValue = methodPay.invoke(order,"2016050902");
System.out.println(returnValue);//2016050902 pay success
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}

如果方法是static的,那么在调用invoke时,第一个参数(类的实例)可以传null(传入类的实例也是可以的)。

获取getter/setter方法

使用反射时,如果需要获取类的getter和setter方法,需要获取所有methods,并根据getter/setter的特点找到他们。

  • Getter
    getter方法以「get」开头,没有参数,有返回值
  • Setter
    setter方法以「set」开头,有一个参数,返回值可能有可能没有

下面是从类中找到get/set方法的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void printGettersSetters(Class aClass){
Method[] methods = aClass.getMethods();

for(Method method : methods){
if(isGetter(method)) System.out.println("getter: " + method);
if(isSetter(method)) System.out.println("setter: " + method);
}
}

public static boolean isGetter(Method method){
if(!method.getName().startsWith("get")) return false;
if(method.getParameterTypes().length != 0) return false;
if(void.class.equals(method.getReturnType()) return false;
return true;
}

public static boolean isSetter(Method method){
if(!method.getName().startsWith("set")) return false;
if(method.getParameterTypes().length != 1) return false;
return true;
}

Java反射之变量

Java Reflection Fields

原文地址Java Reflection Fields

Obtaining Field Objects

1
Field[] fields = orderClass.getFields();

Field[]数组里面只包含类中public修饰的成员变量

如果知道类的成员变量名称,可以直接通过getField()方法获取到,成员变量的访问权限同样需要是public的

Field Name and Type

1
2
3
4
5
6
7
try {
Field field = orderClass.getField("description");
System.out.println(field.getName());//成员变量名称description
System.out.println(field.getType());//成员变量类型class java.lang.String
} catch (NoSuchFieldException e) {//如果不存在description的变量,会抛出NoSuchFieldException
e.printStackTrace();
}

Getting and Setting Field Values

获得了field的引用,就可以通过get(),set()方法,获取和设置成员变量的值

1
2
3
4
5
6
7
8
9
10
try {
Field field = orderClass.getField("description");
Order order = new Order();
Object value = field.get(order);
field.set(order, value);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}

传入Field.get()/Field.set()方法的参数order是Order类的实例。
如果变量是静态变量的话(public static)那么在调用Field.get()/Field.set()方法的时候传入null做为参数而不用传递拥有该变量的类的实例(传入类的实例也是可以的)。

Java反射之构造函数

原文地址Java Reflection Constructors

获取构造函数的对象

1
Constructor[] constructors = orderClass.getConstructors();

可以通过构造函数的具体参数类型直接获取单独的构造函数,而不用获取全部的Constructors

1
2
3
4
5
6
try {
Constructor constructor = orderClass.getConstructor(new Class[]{String.class});
System.out.println(constructor.getName());//com.larry.bean.Order
} catch (NoSuchMethodException e) {//没有找到匹配的构造函数会抛出NoSuchMethodException
e.printStackTrace();
}

构造函数的参数类型

可以像下面这样获取构造函数的参数

1
2
Class[] parameterTypes = constructor.getParameterTypes();
parameterTypes[0].getName();//java.lang.String

用构造函数对象实例化一个类

constructor.newInstance()方法的方法参数是一个可变参数列表,但是当你调用构造方法的时候你必须提供精确的参数,即形参与实参必须一一对应。在这个例子中构造方法需要一个String类型的参数,那我们在调用newInstance方法的时候就必须传入一个String类型的参数

1
2
3
4
5
6
7
8
9
10
11
12
try {
Constructor constructor = Order.class.getConstructor(String.class);
Order order = (Order) constructor.newInstance("2016050901");
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}

Java反射之对象

原文地址Java Reflection Classes

获取class对象

Java中的所有类型包括基本类型(int, long, float等等),即使是数组都有与之关联的Class类的对象。
如果你在编译期知道一个类的名字的话,那么你可以使用如下的方式获取一个类的Class对象

1
Class orderClass = Order.class;

如果你在编译期不知道类的名字,但是你可以在运行期获得到类名的字符串,那么你则可以这么做来获取Class对象

1
2
String className = ... ;//在运行期获取的类名字符串
Class class = Class.forName(className);

在使用Class.forName()方法时,你必须提供一个类的全名,这个全名包括类所在的包的名字

Class Name 类名

通过getName() 方法返回类的全限定类名,不包含包名使用getSimpleName()

1
2
orderClass.getName();//com.larry.bean.Order
orderClass.getSimpleName();
Modifiers 修饰符

通过Class对象来访问一个类的修饰符,即public,private,static等的关键字;

修饰符都被包装成一个int类型的数字,这样每个修饰符都是一个位标识(flag bit),这个位标识可以设置和清除修饰符的类型;

使用java.lang.reflect.Modifier类中的方法来检查修饰符的类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int modifiers = orderClass.getModifiers();

Modifier.isAbstract(modifiers);
Modifier.isFinal(modifiers);
Modifier.isInterface(modifiers);
Modifier.isNative(modifiers);
Modifier.isPrivate(modifiers);
Modifier.isProtected(modifiers);
Modifier.isPublic(modifiers);//true
Modifier.isStatic(modifiers);
Modifier.isStrict(modifiers);
Modifier.isSynchronized(modifiers);
Modifier.isTransient(modifiers);
Modifier.isVolatile(modifiers);
Package Info 包

Package对象你可以获取包的相关信息,比如包名

1
2
Package packages = orderClass.getPackage();
packages.getName();//com.larry.bean
Superclass 父类

superclass对象其实就是一个Class类的实例,所以你可以继续在这个对象上进行反射操作

1
2
Class superClass = orderClass.getSuperclass();
superClass.getName();//java.lang.Object
Implemented Interfaces 实现的接口

获取指定类所实现的接口集合

1
Class[] interfaces = orderClass.getInterfaces();

getInterfaces()方法仅仅只返回当前类所实现的接口。当前类的父类如果实现了接口,这些接口是不会在返回的Class集合中的,尽管实际上当前类其实已经实现了父类接口

Constructors 构造函数
获取构造函数的对象
1
Constructor[] constructors = orderClass.getConstructors();
Method 方法

获取类的方法,Method[]数组里面只包含类中public修饰的方法

1
Method[] methods = orderClass.getMethods();
Field 变量

获取成员变量

1
Field[] fields = orderClass.getFields();
Annotations 注解

获取类的注解

1
Annotation[] annotations = orderClass.getAnnotations();

使用Spring Boot Jquery Datatables实现管理平台的表格

最近在公司做一个运营平台,增删改查的那种,需要一个多功能的表格,网上看到Jquery的DataTables功能很丰富,查询,排序,翻页等等功能完善,
但是DataTables官网上的例子,表格数据都没有从服务端获取,生产上使用还得自己摸索下.另外,公司使用
Spring boot这个框架,配置简单,下面我们一起做一个整合的例子

新建Spring boot的应用

新建个项目springboot-datatables-demo,我使用的是intellij idea,创建个maven项目,在pom里面引用包后,创建main方法即可主要代码如下:
(详细讲解可以参考我的上一篇日志第一个Spring Boot应用)

####pom.xml

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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.larry</groupId>
<artifactId>springboot-datatables-demo</artifactId>
<version>1.0-SNAPSHOT</version>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.5.RELEASE</version>
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<version>1.9.21</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.4</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.8</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

<repositories>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release</url>
</pluginRepository>
</pluginRepositories>
</project>

SddApplication.java

1
2
3
4
5
6
7
8
9
10
11
package com.larry;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SddApplication {
public static void main(String[] args) {
SpringApplication.run(SddApplication.class, args);
}
}

ok,添加完上面两个主要的内容maven引入相关包以后,就可以运行啦,在SDDApplication上右击run一下…..额,是不是报错了,貌似把数据库给忘啦.
我们使用mysql数据库,需要添加数据库配置类config.java,添加配置文件application.properties

建表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `app`;
CREATE TABLE `app` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`create_time` datetime DEFAULT NULL,
`description` text,
`hot` int(8) DEFAULT '0',
`keywords` text,
`url` varchar(255) NOT NULL,
`disabled` int(2) NOT NULL DEFAULT '0',
`name` varchar(50) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`is_delete` bit(1) DEFAULT NULL COMMENT '是否删除,0:删除',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

####application.properties添加数据库配置信息

1
2
3
4
5
6
7
8
9
10
11
12
spring.thymeleaf.mode=LEGACYHTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.cache=false

spring.datasource.c3p0.driver-class-name=com.mchange.v2.c3p0.ComboPooledDataSource
spring.datasource.c3p0.jdbc-url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=yes&characterEncoding=UTF-8
spring.datasource.c3p0.username=root
spring.datasource.c3p0.password=
spring.datasource.c3p0.min-evictable-idle-time-millis=30000
spring.jpa.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

由于我使用的是thymeleaf模板引擎,需要在resource下面添加文件夹templates,再添加个html, 随便建个html叫index.html,在body里面写个 hello world! 好了。

然后,我们run一下试试

1
2
2016-04-03 15:29:27.850  INFO 1847 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
2016-04-03 15:29:27.852 INFO 1847 --- [ main] com.larry.SddApplication : Started SddApplication in 4.522 seconds ...

当我们发现这两句话时,说明我们项目已经启动成功了.不过输入http://localhost:8080/浏览器仍然会报错,我们配置下路由让/路径默认跳转到index模板上.

###MvcConfig

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.larry.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("").setViewName("index");
}
}

重启后,浏览器中输入http://localhost:8080 哈哈,是不是看到熟悉的 hello world! 啦。

datatables

啰嗦了半天终于进入主题了。。。。我在github上发现有个哥们已经封装了一套spring data jpa + jquery datatables的项目,直接pom里面引用下,就ok拉,下面看看具体怎么是用

Maven 依赖

1
2
3
4
5
<dependency>
<groupId>com.github.darrachequesne</groupId>
<artifactId>spring-data-jpa-datatables</artifactId>
<version>2.0</version>
</dependency>

注意这哥们使用的hibernate包是4.3.10.Final,这个和spring-boot用的hibernate要一致,否则启动的时候就会报错,所以我选择了1.2.5.RELEASE的版本的spring boot。

启用DataTablesRepository工厂

1
2
3
4
5
6
7
@SpringBootApplication
@EnableJpaRepositories(repositoryFactoryBeanClass = DataTablesRepositoryFactoryBean.class)
public class SddApplication {
public static void main(String[] args) {
SpringApplication.run(SddApplication.class, args);
}
}

扩展DataTablesRepository接口

1
2
public interface AppRepository extends DataTablesRepository<App, Long> {
}

设置model属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class App {
@Id
@GeneratedValue
private long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
@URL
private String url;
private String description;
private String keywords;
private boolean disabled;
private int hot;

@CreationTimestamp
private Date createTime;
@UpdateTimestamp
private Date updateTime;
private boolean isDelete;
}

包含jquery.spring-friendly.js

It overrides jQuery data serialization to allow Spring MVC to correctly map input parameters (by changing column[0][data] to column[0].data in request payload)

index.html

index.html

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--<link rel="stylesheet" href="//cdn.datatables.net/1.10.11/css/jquery.dataTables.min.css">-->
<link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.css">
<link rel="stylesheet" href="/dataTables.bootstrap.css">
</head>
<body>
<div class="box">
<div class="box-header with-border">
<button type="button" class="btn btn-info" >增加12条数据</button>
</div><!-- /.box-header -->
<div class="box-body">
<table id="appTable" class="table table-bordered table-striped">
<thead>
<tr>
<th></th>
<th>操作</th>
<th>名称</th>
<th>地址</th>
<th>关键字</th>
<th>描述</th>
<th>热度</th>
<th>添加日期</th>
<th>更新时间</th> <!--日期格式在application.properties添加:spring.jackson.date-format=yyyy-MM-dd HH:mm:ss-->
<th>状态</th>
</tr>
</thead>
</table>
</div><!-- /.box-body -->
</div>
<script src="/jQuery-2.1.4.min.js"></script>
<script src="/jquery.dataTables.js"></script>
<script src="/dataTables.bootstrap.min.js"></script>
<script src="/jquery.spring-friendly.js"></script>
<script>
$().ready(function () {
$('#appTable').DataTable({
ajax: '/all',
serverSide: true,
order: [
[8, 'desc']//更新时间倒序
],
columns: [{
data: null,
orderable: false,
searchable: false,
render: function (data, type, row) {
return "<td><input type='checkbox' name='allocated' value='" + row.id + "'></td>";
}
}, {
data: '',
orderable: false,
searchable: false,
render: function (data, type, row) {
return "<td><button type='button' class='btn btn-primary btn-sm' onclick='editApp(" + row.id + ")'>编辑</button> &nbsp;" +
// "<button type='button' class='btn btn-info btn-sm' onclick='detail("+row.id+")'>详情</button>" +
"&nbsp;<button type='button' class='btn btn-warning btn-sm' onclick='deleteSingle("+row.id+")'>删除</button>" +
"</td>";
}
}, {
data: 'name'
}, {
data: 'url',
render: function (data, type, row) {
var shortUrl;
if(data.length<30){
shortUrl = data ;
} else {
shortUrl = data.substring(0,30)+"...";
}
return "<a href='" + data + "' target='_blank'>"+shortUrl+"</a>";
}
}, {
data: 'keywords'
}, {
data: 'description'
}, {
data: 'hot'
}, {
data: 'createTime'
}, {
data: 'updateTime'
}, {
data: 'disabled',
render: function (data, type, row) {
if (row.disabled) {
return "<input type='checkbox' name='state-checkbox' value='" + row.id + "'>";
} else {
return "<input type='checkbox' name='state-checkbox' value='" + row.id + "' checked>";
}
}
}]
// initComplete: function () {
// $("input[name='state-checkbox']").bootstrapSwitch();
// },
// drawCallback: function() {//Function that is called every time DataTables performs a draw.
// $("input[name='state-checkbox']").bootstrapSwitch();
// }


});
});

$("button").on("click", function () {
$.get("init")
.success(function (data) {
window.location="/";
});
});
</script>

</body>
</html>

AppController

1
2
3
4
5
@ResponseBody
@RequestMapping(value = "all", method = RequestMethod.GET)
public DataTablesOutput<App> messages(@Valid DataTablesInput input) {
return appRepository.findAll(input);
}

启动后,添加数据后,显示效果如下,已经可以分页搜索排序了。
表格
到这里就可以看到,我们的基本目标已经完成了。不过仍然有个问题,现在的这个查询用的是findAll(input),如果我们要添加过滤条件进行查询呢。其实darrachequesne这个哥们已经封装了。’DataTablesOutput findAll(DataTablesInput var1, Specification var2);’调用这个就可以,下面我们来看看具体怎么用

使用过滤条件查询

过滤查询使用到了Spring Data JPA - Specifications,自己要去熟悉了解下这个。

我们创建个Specification条件,然后调用’DataTablesOutput findAll(DataTablesInput var1, Specification var2);’
假设我们要查询所有删除状态为false的记录

AppSpec

1
2
3
4
5
public class AppSpec {
public static Specification<App> isNotDelete() throws Exception {
return (root, criteriaQuery, criteriaBuilder) -> criteriaBuilder.isFalse(root.get("isDelete"));
}
}

注意:使用了lambda表达式,其实就是创建了内部类

修改AppController

1
2
3
4
5
6
7
8
@RequestMapping(value = "all", method = RequestMethod.GET)
public DataTablesOutput<App> messages(@Valid DataTablesInput input) {
try {
return appRepository.findAll(input, AppSpec.isNotDelete());
} catch (Exception e) {
return null;
}
}

重启,添加12条数据,设置6条记录删除状态为true,看看效果
过滤删除记录
表格下面显示:
Showing 1 to 6 of 6 entries (filtered from 12 total entries)
说明我们过滤成功了!

打完收工!
详细代码,欢迎从我的github上获取:spring-data-jpa-jquery-datatables

第一个Spring Boot应用

原文地址:天码营-SpringBoot参考指南 本文只是学习笔记

准备

让我们使用Java开发一个简单的”Hello World!” web应用,来强调下Spring Boot的一些关键特性。我们将使用Maven构建该项目,因为大多数IDEs都支持它。

注:spring.io网站包含很多使用Spring Boot的”入门”指南。如果你正在找特定问题的解决方案,可以先去那瞅瞅。

在开始前,你需要打开一个终端,检查是否安装可用的Java版本和Maven:

1
2
3
4
5
6
7
8
9
10
11
➜  ~ java -version
java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)
➜ ~ mvn -v
Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-11T00:41:47+08:00)
Maven home: /usr/local/Cellar/maven/3.3.9/libexec
Java version: 1.8.0_65, vendor: Oracle Corporation
Java home: /Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home/jre
Default locale: zh_CN, platform encoding: UTF-8
OS name: "mac os x", version: "10.11", arch: "x86_64", family: "mac"

Read More

Spring Boot安装

JDK

Spring Boot可以跟典型的Java开发工具一块使用或安装为一个命令行工具。不管怎样,你将需要安装Java SDK v1.6 或更高版本。在开始之前,你需要检查下当前安装的Java版本:

1
java -version

注:尽管Spring Boot兼容Java 1.6,如果可能的话,你应该考虑使用Java最新版本。

maven

Spring Boot兼容Apache Maven 3.2或更高版本,OSX系统下使用brew安装

1
brew install maven

Read More

Shell编程之正则表达式

正则表达式与通配符

Linux中的正则表达式和通配符有些区别,正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配。grep,awk,sed等命令可以支持正则表达式。通配符用来匹配符合条件的文件名,通配符是完全匹配。ls,find,cp这些命令不支持正则所有只能用shell自己的通配符进行匹配。

Read More

shell编程之运算符

声明变量类型declare

declare语法:

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
declare [-afiprx] 变量名
参数说明:
- :设置属性
+ :取消属性
-a :定义为数组 array
-f :定义为函数 function
-i :定义为整数 integer
-p :显示变量被声明的类型
-r :定义为『只读』
-x :定义为环境变量

bash-3.2$ declare -i a=47
bash-3.2$ declare -i b=53
bash-3.2$ declare -i c=$a+$b
bash-3.2$ echo $c
100
bash-3.2$ declare -p c
declare -i c="100"

bash-3.2$ declare -a arr[0]=11 <==定义数组
bash-3.2$ declare -p arr
declare -a arr='([0]="11")'
bash-3.2$ declare -a arr[1]=22
bash-3.2$ declare -p arr
declare -a arr='([0]="11" [1]="22")'
bash-3.2$

bash-3.2$ echo ${arr} <==查看数组方法
11
bash-3.2$ echo ${arr[1]}
22
bash-3.2$ echo ${arr[*]}
11 22
bash-3.2$

Read More

Shell编程之变量

变量

变量的配置守则

  1. 变量与变量内容以一个等号『=』来连结,如下所示:
    『myname=VBird』
  2. 等号两边不能直接接空格符,如下所示为错误:
    『myname = VBird』或『myname=VBird Tsai』
  3. 变量名称只能是英文字母与数字,但是开头字符不能是数字,如下为错误:
    『2myname=VBird』
  4. 变量内容若有空格符可使用双引号『\”』或单引号『\’』将变量内容结合起来,但
    • 双引号内的特殊字符如 $ 等,可以保有原本的特性,如下所示:
      『var=”lang is $LANG”』则『echo $var』可得『lang is en_US』
    • 单引号内的特殊字符则仅为一般字符 (纯文本),如下所示:
      『var=’lang is $LANG’』则『echo $var』可得『lang is $LANG』
  5. 可用转义字符『 \ 』将特殊符号(如 [Enter], $, \, 空格符, `等)变成一般字符;
  6. 在一串命令中,还需要藉由其他的命令提供的信息,可以使用反单引号『命令』或 『$(命令)』。特别注意,那个 ` 是键盘上方的数字键 1 左边那个按键,而不是单引号! 例如想要取得核心版本的配置:
    『version=$(uname -r)』再『echo $version』可得『2.6.18-128.el5』
  7. 若该变量为扩增变量内容时,则可用 “$变量名称” 或 ${变量} 累加内容,如下所示:
    『PATH=”$PATH”:/home/bin』
  8. 若该变量需要在其他子程序运行,则需要以 export 来使变量变成环境变量
    『export PATH』
  9. 通常大写字符为系统默认变量,自行配置变量可以使用小写字符,方便判断 (纯粹依照使用者兴趣与嗜好) ;
  10. 取消变量的方法为使用 unset :『unset 变量名称』例如取消 myname 的配置:
    『unset myname』
  11. 在Bash中,变量的默认类型是字符串型

Read More

Shell基础

Shell 概述

imooc shell课程

Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用可以用Shell来启动,挂起,停止甚至是编写一些程序。

Shell还是一个功能强大的编程语言,易编写易调试,灵活性较强。Shell是解释执行的脚本语言,在Shell中可以直接调用Linux系统命令。

Read More

What is Docker?

What is Docker

Docker allows you to package an applications with all of its dependencies into a standardized unit for development.

对于软件开发,Docker允许你用其所有相关的依赖打包应用程序到一个标准化单元中.

layered_filesystems_sm

Docker containers wrap up a piece of software in a complete filesystem that contains everything it needs to run : code,runtime,system tools,system libraries - anything you can install on a sever. This guarantees that it will always run the same,regardless of the environment it is running in.

Docker容器在一个完整的文件系统中包裹一个软件,这个文件系统包含软件运行所需要的code,runtime,系统工具,系统库等任何你所能在服务器上安装的.这保证了软件总是运行在相同的环境.(这句翻译的烂,欢迎指正)

Read More

2015

2015还有一会就结束了.这一年我身上发生了好多大事,一点点想起来,有些苦涩,也有些甜蜜.

2015年年初就开始筹划买房的事情,2月份开始从苏州到上海,新房,二手房,看了不下100套,跑了3个月,看着房价一直涨涨涨,总感觉再不买就真的买不起了.一咬牙,5月底同双方父母朋友借钱加上自己和女友的积蓄勉强凑齐首付,在松江买下.买房的同时也和女友领证,正式结为夫妇,结束了7年多得恋爱之路.

房子有了,证领了,就开始筹划10月份的婚礼.拍婚纱照,买婚戒,买衣服,一点点的直到把老婆娶回家.

Read More

Why Docker?

一直听说Docker怎么怎么厉害,不明所以,网上查了下,也只是简单了解.学技术还得去官网,尽管Docker官网都是英文,看的比较辛苦,不过一方面学技术,一方面学英语也是妙事.这一系列的Docker笔记,就边抄英文边翻译,边学技术吧.

Why Docker?

Docker provides an integrated technology suite that enables development and IT operations teams to build,ship,and run distributed applications anywhere.

Docker 提供了一个集成的技术组件,它使得开发或IT运营团队可以在任何地方构建,ship,以及运行分布式应用.(ship到底该怎么翻译呢?)

Docker Containers as a Service(CaaS)

Achieve agility and control for Development and IT operations teams to build,ship,and run any app,anywhere

开发或者IT运营部门在任何地方对应用进行构建,ship都实现了灵活性和控制性

Agility 灵活性

Docker gives developers the freedom to define environments, and create and deploy apps faster and easier,and flexibility for IT ops to quickly response to change.

Docker使开发人员能够自由的定义环境,以及简单快速的创建和部署应用,同时提供了灵活性,IT运维也可以快速应对变化.

Control 控制性

Docker enables developers to own all the code from infrastructure to app , and the manageability for IT ops to standardize ,secure and scale the operating environment.

Docker能够让开发人员从基础设施到应用程序上获取所有的代码 , 能让IT运维对于操作环境的规范,安全,规模都易于管理.

Portability 可移植性

Docker gives you choice without complexity , from a laptop to team , to private infrastructure and public cloud provides.

Docker给你简单的选择,从个人电脑到团队,从私有基础设施到公有云服务提供商.

zookeeper客户端命令

zkCli.sh

连接zookeeper:./zkCli.sh -server ip:port

bin目录下输入命令`./zkCli.sh -server 192.168.1.101:2181`

客户端命令

help

ZooKeeper -server host:port cmd args
stat path [watch]
set path data [version]
ls path [watch]
delquota [-n|-b] path
ls2 path [watch]
setAcl path acl
setquota -n|-b val path
history 
redo cmdno
printwatches on|off
delete path [version]
sync path
listquota path
rmr path
get path [watch]
create [-s] [-e] path data acl
addauth scheme auth
quit 
getAcl path
close 
connect host:port

Read More

zookeeper概述

zookeeper是什么

zookeeper是源代码开放的分布式协调服务 ,由雅虎创建,是Google
Chubby的开源实现。zookeeper是一个高性能的分布式数据一致性解决方案 ,它将那些复杂的、容易出错的分布式一致性服务封装起来,构成一个高效可靠的原语集,并提供一系列简单易用的接口给用户使用

zookeeper 从设计模式角度来看,是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,zookeeper 就将负责通知已经在 zookeeper 上注册的那些观察者做出相应的反应,从而实现集群中类似 Master/Slave 管理模式

Read More