本章包含:

  • 设置开发环境
  • 一个Echo服务和客户端
  • 构建和测试应用

2.1 设置开发环境

下载安装JDK和MAVEN,设置JAVA_HOME,并且设置M2_HOME

2.2 Netty的客户端和服务器概览

下图是我们的Echo服务器和客户端一览。虽然我们大部分是在写web应用,但实现服务器和客户端有助于更好的理解Netty API.
Alt text

2.3 编写Echo服务器

所有的Netty Server都需要:

  • 至少一个ChannelHandler:这个组建实现了服务端用于处理客户端提交的数据,它是业务逻辑。
  • Bootstrapping:用来配置服务的启动代码。最少的启动代码是绑定端口。

2.3.1 ChannelHandler和业务逻辑

Read more »

Netty(http://netty.io )是一个用来快速开发可维护高性能服务器和客户端应用的异步事件驱动网络应用框架。

高性能系统不仅需要我们有优秀的编码技巧,还需要对网络、多线程与并发有相关的经验。

1.1 Java网络

早期版本Java的java.net支持本地系统的socket库提供的阻塞函数。

Alt text

  • accept()一直阻塞直到ServerSocket简历了链接,它返回一个Socket对象用来在客户端和服务器之间进行通信。
  • BufferedRead用来从Socket中读取文本;PrintWriter用来写入。
  • readLine阻塞直到发送了回车换行

上面的代码每次只能处理一个链接。要管理多个并发的客户端,需要为每一个新的Socket来分配一个Thread,如图:
Alt text

我们来思考一下这个方法:

  • 首先,很多时间线程处于等待状态,这是一种资源的浪费;
  • 每个线程需要在内存上分配64k到1M的空间;
  • 即使JVM支持大量的线程,但上下文之间的切换耗时。

1.1.1 Java NIO

Read more »

此笔记是我在阅读《Java8实战》中的一些记录。

Java8中增加了流(stream)的概念,为数据的处理带来了很大的方便。

并行流将数据分割成不同的块,并且用不同的线程处理不同的块。

现在要根据输入n,求从1到n的和,这里我们不使用n*(1+n)/2的方式,而是使用累加。我们分别写出迭代、顺序流、并行流的写法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ParallelStreams {
public static long sequentialSum(long n) {
return Stream.iterate(1L, i->i+1)
.limit(n)
.reduce(0L, Long::sum);
}

public static long iterativeSum(long n) {
long result = 0;
for (long i = 1L; i <= n; i++) {
result += i;
}
return result;
}

public static long parallelSum(long n) {
return Stream.iterate(1L, i->i+1)
.limit(n)
.parallel()
.reduce(0L, Long::sum);
}
}

我们可以看到,将顺序流转换为并行流只需要parallel()方法即可。

现在我们来测量这几个方法的性能:

1
2
3
4
5
6
7
8
9
10
11
public static long measureSumPerf(Function<Long, Long> adder, long n) {
long fastest = Long.MAX_VALUE;
for (int i = 0; i < 10; i++) {
long start = System.nanoTime();
long sum = adder.apply(n);
long duration = (System.nanoTime() - start) / 1_000_000; //毫秒
System.out.println("Result: "+sum);
if(duration < fastest) fastest = duration;
}
return fastest;
}

然后分别测试这三个方法:

1
2
3
4
5
public static void main(String[] args) {
System.out.println("顺序流:" + measureSumPerf(ParallelStreams::sequentialSum, 10_000_000)+" 毫秒");
System.out.println("循环:" + measureSumPerf(ParallelStreams::iterativeSum, 10_000_000)+" 毫秒");
System.out.println("并行流:" + measureSumPerf(ParallelStreams::parallelSum, 10_000_000)+" 毫秒");
}
Read more »

maven快速入门

Maven是基于项目对象模型(POM),可以通过一小段描述信息来管理项目的构建、报告和文档的软件项目管理工具。

maven安装配置

下载好maven后,需要配置环境变量。

  1. 设置JAVA_HOMED:\program files\Java\jdk1.8.0_91, path添加%JAVA_HOME%\bin
  2. 新建M2_HOME,指向maven安装目录:D:\app\apache-maven-3.3.9
  3. 修改path,添加%M2_HOME%\bin
  4. 在命令行中输入mvn -v看看是否输出正确。

maven helloworld案例

maven目录结构结构

1
2
3
4
5
6
7
8
src
-main
-java
-package
-test
-java
-package
-resources

按照上面的目录结构创建目录,package目录先不要创建package。

分别新建

Read more »

1.搭建Spark项目

使用Idea创建Gradle项目,包名是:io.github.liulixiang.course,Artifactid是course-ideas
在builder.gradle里添加spark依赖。

1
2
compile "com.sparkjava:spark-core:2.5"
compile "org.slf4j:slf4j-simple:1.7.21"

然后创建io.github.liulixiang.course.Main类。

1
2
3
4
5
6
7
import static spark.Spark.get;
public class Main {
public static void main(String[] args) {
get("/hello", (req, res) -> "Hello World");
get("/", (req, res) -> "欢迎");
}
}

此时,访问http://localhost:4567 就能看到返回的页面了。

2.返回响应

Spark支持多种模板引擎,我们使用Handlebars。

添加依赖:

1
compile "com.sparkjava:spark-template-handlebars:2.3"
Read more »

1. 添加依赖

指定仓库是maven central

1
2
3
repositories {
mavenCentral()
}

加入我们要使用apache commons中的csv包,首先在网页https://commons.apache.org/proper/commons-csv/ 中找到对应的maven:

1
2
3
4
5
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.3</version>
</dependency>

上面的是xml格式,我们把它转换成gradle格式:

1
2
3
4
5
dependencies {
compile group: 'org.apache.commons', name: 'commons-csv', version: '1.3'
//等价于
//compile 'org.apache.commons:commons-csv:1.3'
}

然后我们在gradle面板刷新项目。

也可以在Gradle面板右键选择auto import.

也可以在命令行运行./gradlew用来在电脑上安装gradle。以及./gradlew dependencies是用来安装依赖的。

Read more »

1. 老的方法

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
//Book.java
public class Book {
private String mTitle;
private String mAuthor;
private int mPublicationDate;

public Book(String title, String author, int publicationDate) {
mTitle = title;
mAuthor = author;
mPublicationDate = publicationDate;
}

public String getTitle() {
return mTitle;
}

public String getAuthor() {
return mAuthor;
}

public int getPublicationDate() {
return mPublicationDate;
}

@Override
public String toString() {
return "Book{" +
"mTitle='" + mTitle + '\'' +
", mAuthor='" + mAuthor + '\'' +
", mPublicationDate=" + mPublicationDate +
'}';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//Books.java
import java.util.ArrayList;
import java.util.List;

public class Books {
public static List<Book> all() {
List<Book> books = new ArrayList<Book>();
books.add(new Book("Functional Programming in Java", "Venkat Subramaniam", 2014));
books.add(new Book("Clean Code", "Robert C. Martin", 2008));
books.add(new Book("Java Generics and Collections", "Maurice Naftalin and Philip Wadler", 2008));
books.add(new Book("Effective Java", "Joshua Bloch", 2008));
books.add(new Book("Pragmatic Unit Testing in Java 8 with JUnit", "Jeff Langr", 2015));
books.add(new Book("JavaFX Essentials", "Mohamed Taman", 2015));
return books;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Main {

public static void usingAnonymousInlineClass(){
List<Book> books = Books.all();
Collections.sort(books, new Comparator<Book>() {
@Override
public int compare(Book b1, Book b2) {
return b1.getTitle().compareTo(b2.getTitle());
}
});
for(Book book : books) {
System.out.println(book);
}
}

public static void main(String[] args) {
// write your code here
usingAnonymousInlineClass();
}
}

2. Java Lambdas

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//Lambda长形式
public static void usingLambdaInLongForm(){
List<Book> books = Books.all();
Collections.sort(books, (Book b1, Book b2) -> {
return b1.getTitle().compareTo(b2.getTitle());
});
for(Book book : books) {
System.out.println(book);
}
}

//Lambda短形式
public static void usingLambdaInShortForm(){
List<Book> books = Books.all();
Collections.sort(books, (b1, b2) -> b1.getTitle().compareTo(b2.getTitle()));
//forEach调用
books.forEach((book)->System.out.println(book));
}

3. 方法引用

1
2
3
4
5
public static void usingMethodReference(){
List<Book> books = Books.all();
Collections.sort(books, Comparator.comparing(Book::getTitle));
books.forEach(System.out::println);
}

1. Java链接数据库

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
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import java.util.List;
import java.util.ArrayList;

public class JdbcMain {
public static void main(String[] args) throws ClassNotFoundException {
// TODO: Load the SQLite JDBC driver (JDBC class implements java.sql.Driver)
Class.forName("org.sqlite.JDBC");
// TODO: Create a DB connection
try(Connection connection = DriverManager.getConnection("jdbc:sqlite:contactmgr.db")) {

// TODO: Create a SQL statement
Statement statement = connection.createStatement();

// TODO: Create a DB table
statement.executeUpdate("DROP TABLE IF EXISTS contacts");
statement.executeUpdate("CREATE TABLE contacts (id INTEGER PRIMARY KEY, firstname STRING, lastname STRING, email STRING, phone INT(10))");

// TODO: Insert a couple contacts
statement.executeUpdate("INSERT INTO contacts (firstname, lastname, email, phone) VALUES('Liu', 'Lixiang', 'liulixiang1988@gmail.com', 1234567890)");
statement.executeUpdate("INSERT INTO contacts (firstname, lastname, email, phone) VALUES('Long', 'Long', 'abc@gmail.com', 0987654321)");

// TODO: Fetch all the records from the contacts table
ResultSet rs = statement.executeQuery("SELECT * FROM contacts");

// TODO: Iterate over the ResultSet & display contact info
while(rs.next()){
int id = rs.getInt("id");
String firstName = rs.getString("firstname");
String lastName = rs.getString("lastname");

System.out.printf("%s %s (%d)", firstName, lastName, id);
}

} catch (SQLException ex) {
// Display connection or query errors
System.err.printf("There was a database error: %s%n",ex.getMessage());
}
}
}

编译:javac JdbcMain.java

运行:java -cp sqlite-jdbc.3.8.6.jar:. JdbcMain

2 Hibernate入门

2.1 创建一个使用Hibernate的项目

创建gradle项目contactmgr-hibernate项目,并修改build.gradle:

1
2
3
4
dependencies {
compile 'org.hibernate:hibernate-core:5.1.0.Final'
compile 'com.h2database:h2:1.4.191'
}

在根目录创建data文件夹,用来存放h2文件数据库。

resources目录下创建hibernate.cfg.xml,这个文件用来保存SessionFactory的配置:

Read more »

##1. 环境配置

1.1 创建应用

打开idea,新建应用:

img

然后输入包名、应用名:

img

其他默认。

1.2 修改build.gradle

打开build.gradle,修改dependencies:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
group 'io.github.liulixiang1988'
version '1.0-SNAPSHOT'

buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.3.3.RELEASE'
}
}

apply plugin: 'java'
apply plugin: 'spring-boot'

sourceCompatibility = 1.5

repositories {
mavenCentral()
}

dependencies {
compile 'org.springframework.boot:spring-boot-starter-web:1.3.3.RELEASE'
}
Read more »

0. Kotlin简介

0.1 简介

0.2 Kotlin安装

0.3 Hello, Kotlin

1
2
3
4
fun main(args:Array<String>)
{
println("Hello, Kotlin!")
}

1. 类型和变量

1.1 变量声明(Variable Declarations)

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
fun main(args: Array<String>) {
val_declarations()
}

fun val_declarations(){
//val声明的变量不能更改
val a:Int = 64
val b:Long = 123

//这种事不行的,必须每个占一行:
//val c = 3, d = 4

val c:Float = 3.4f //后面跟'F'或者'f'
val d:Double = 3.4
val e:Double = 12.3e5
//不赋值的val声明
val f: Int
f = 13

val g:StringBuffer = StringBuffer("test")
g.replace(0, 1, "T")
//打印
println("$a $b $c $d $e $f")
println("$g")

//可更改的变量
var h:Int = 123
h = 45
println("$h")
}

1.2 类型推导(Type Deduction)

类型能够根据赋值进行推到

Read more »
0%