Kotlin开发springboot项目(二)

中文学习网站:

https://www.kotlincn.net/

研究一下kotlin的demo:

https://github.com/JetBrains/kotlin-examples

Kotlin 文件以 .kt 为后缀。

包声明

kotlin源文件不需要相匹配的目录和包,源文件可以放在任何文件目录。

如果没有指定包,默认为 default 包。

package basic.kotlin.manager.beijing

/**
* 定义类
*/
class 总经理(var 姓: String) {
override fun toString(): String {
return "${姓}经理"
}
}
package basic.kotlin.manager.beijing

import basic.kotlin.manager.beijing.总经理 as 茶水大王   // 起一个别名
/**
* 包必须声明在非注释的第一行
*/
fun main(args: Array<String>) {
val manager: 茶水大王 = 茶水大王("张")
println(manager)
}

默认导入

有多个包会默认导入到每个 Kotlin 文件中:
kotlin.*
kotlin.annotation.*
kotlin.collections.*
kotlin.comparisons.*
kotlin.io.*
kotlin.ranges.*
kotlin.sequences.*
kotlin.text.*

基本数据类型:

定义常量与变量

可变变量定义:var 关键字

var <标识符> : <类型> = <初始化值>

不可变变量定义:val 关键字,只能赋值一次的变量(类似Java中final修饰的变量)

val <标识符> : <类型> = <初始化值>
package basic.kotlin

/**
* 基本数据类型
* 变量名称:变量类型=变量值
*/
val aBoolean: Boolean = true
val anotherBoolean: Boolean = false val anInt: Int = 8
val anotherInt: Int = 0xFF
val moreInt: Int = 0b00000011
val maxInt: Int = Int.MAX_VALUE
val minInt: Int = Int.MIN_VALUE val aLong: Long = 12368172397127391
val another: Long = 123
val maxLong: Long = Long.MAX_VALUE
val minLong: Long = Long.MIN_VALUE val aFloat: Float = 2.0F
val anotherFloat: Float = 1E3f
val maxFloat: Float = Float.MAX_VALUE
val minFloat: Float = -Float.MAX_VALUE val aDouble: Double = 3.0
val anotherDouble: Double = 3.1415926
val maxDouble: Double= Double.MAX_VALUE
val minDouble: Double= -Double.MAX_VALUE val aShort: Short = 127
val maxShort: Short = Short.MAX_VALUE
val minShort: Short = Short.MIN_VALUE val aByte:Byte=127
val maxByte: Byte = Byte.MAX_VALUE
val minByte: Byte = Byte.MIN_VALUE
val aChar: Char = '0'
val bChar: Char = '中'
val cChar: Char = '\u56fd'
val dChar: Char = '\u000f'


fun main(args: Array<String>) {
println(anotherInt)
println(moreInt) println(maxInt)
println(Math.pow(2.0, 31.0) - 1)
println(minInt)
println( - Math.pow(2.0, 31.0)) println(maxLong)
println(Math.pow(2.0, 63.0) - 1)
println(minLong)
println(- Math.pow(2.0, 63.0)) println(aFloat)
println(anotherFloat)
println(maxFloat)
println(minFloat) println(maxDouble)
println(minDouble) println(maxShort)
println(minShort) println(aByte)
println(maxByte)
println(minByte) println(aChar)
println(bChar)
   println("Unicode:"+cChar) // 需要转义才能打印
println("Unicode:"+dChar) // 需要转义才能打印
}

 Range区间

package basic.kotlin

/**
* Range 区间
*/
val range: IntRange = 0..1024 // [0, 1024] 闭区间
val range_exclusive: IntRange = 0 until 1024 // [0, 1024) = [0, 1023] 开区间
val emptyRange: IntRange = 0..-1 fun main(args: Array<String>) {
println(emptyRange.isEmpty()) // 是否为空
println(range.contains(50)) // 是否包含
println(50 in range) // 是否在这个区间 for(i in range_exclusive){ // 循环遍历
print("$i, ")
}
}

 kotlin不支持隐式转换

package basic.kotlin
/**
* 隐式转换 与 字符串类型
*/ val aInt:Int= 6
val bLong:Long= aInt.toLong() // int整形转换为long类型需要显示转换,在kotlin中不支持隐式转换 val string: String = "HelloWorld"
val fromChars: String = String(charArrayOf('H','e','l','l','o','W','o','r','l','d')) fun main(args: Array<String>) {
println(bLong)
println(string == fromChars) // 双等号 比较内容 相当于java中的equals
println(string === fromChars) // 三等号 比较引用 相当于java 中比较的引用的地址 println("接下来我们要输出:" + string) val arg1: Int = 0
val arg2: Int = 1
println("" + arg1 + " + " + arg2 + " = " + (arg1 + arg2)) // java传统方式进行字符串拼接
println("$arg1 + $arg2 = ${arg1 + arg2}") // 字符串模板进行字符拼接 //Hello "Trump"
val sayHello : String = "Hello \"Trump\"" // 双引号转义
println(sayHello)
//salary
val salary: Int = 1000
//$salary
println("$$salary")
println("\$salary") // 三个双引号的字符串原样输出,在这种字符串模板拼接时,\ 进行转义时不起作用
val rawString: String = """
\t
\n
$salary
\$salary
$ salary
"""
println(rawString)
println(rawString.length)
}

kotlin中Any是所有类的父类

package com.basic.kotlin

/**
* 对象继承关系
*/
// 类的定义方式一:
class 妹子(性格: String, 长相: String, 声音: String): person(性格, 长相, 声音) // 类的定义方式二:
class 帅哥(性格: String, 长相: String, 声音: String): person(性格, 长相, 声音){ fun say(){
println("我最帅")
}
} class 大叔(性格: String, 长相: String, 声音: String): person(性格, 长相, 声音){
init{
println("我有房、有车、有存款,我在父类的init方法后运行,在自己的实例每次创建被new时先运行")
}
}
open class person(var 性格: String, var 长相: String, var 声音: String){
init {
println("new 了一个${this.javaClass.simpleName}, ta性格:$性格, 长相:$长相, 声音:$声音")
}
} fun main(args: Array<String>) {
val girl: 妹子 = 妹子("温柔", "甜美", "动人")
println(girl is person) val boy: 帅哥 = 帅哥("彪悍", "帅气", "浑厚")
boy.say() val uncle: 大叔 = 大叔("稳重", "成熟", "洪亮") }

 空类型安全

package basic.kotlin

/**
* 空值安全
* 安全的kotlin写法
*/
fun getName(): String?{ // ? 表示返回值的String类型允许为null
return null
} fun main(args: Array<String>) {
val str: String? = null //值允许为空
println(str?.length) //值为空直接返回null val value: String? = "HelloWorld"
println(value!!.length) // 已经明确知道不为空,!! 告诉编译器,我知道是不为空了,你编译吧 val name: String = getName() ?: return // ? 表示允许为null 为空直接返回,下边的打印语句不会执行了
println(name.length)
}

智能类型转换

定义一个父类

/**
* 父类
*/
public class Parent {
}

定义一个子类

/**
* 子类继承父类
*/
public class Child extends Parent {
public String getName(){
return "Child";
}
}

类型转换

package basic.kotlin
/**
* 智能识别类型转换
* 安全的kotlin写法
*/
fun main(args: Array<String>) {
val p: Parent = Parent()
val c: Parent = Child() if (c is Child) // 类型相等,就可以执行方法体的内容
println(c.name) val child: Child? = p as? Child // 转换失败不让其抛出异常,返回个null ,不带?就会和java原生语法一样抛出异常
println(child) val string: String? = "Hello"
if(string != null)
println(string.length) // 智能甄别 ,前边判断了,后边不用判断了
}

 数组

package basic.kotlin

import basic.kotlin.manager.beijing.总经理 as m1

/**
* 数组
*/
val arrayOfInt: IntArray = intArrayOf(1,3,5,7)
val arrayOfChar: CharArray = charArrayOf('H', 'e','l','l','o','W','o','r','l','d')
val arrayOfString: Array<String> = arrayOf("我", "是", "码农")
val arrayOf经理: Array<m1> = arrayOf(m1("张"),m1("李")) fun main(args: Array<String>) {
println(arrayOfInt.size)
for(int in arrayOfInt){
print("$int \t")
}
println() println(arrayOfString.joinToString(""))
println(arrayOf经理[1])
arrayOf经理[1] = m1("王")
println(arrayOf经理[1]) // 取出第二个元素 println(arrayOfChar.joinToString()) // 字符串连接 默认逗号
println(arrayOfChar.joinToString("")) // 空字符串连接 ,就是一个完整的字符串
println(arrayOfInt.slice(1..2)) // 字符串区间截取子串
println(arrayOfInt.slice(0..1)) // 字符串区间截取子串
}

idea 查看字节码 bytecode插件 (jclasslib Bytecode Viewer、ASM Bytecode Viewer )

jclasslib Bytecode Viewer


然后重启idea===>重新编译(构建项目)

然后能够直接看java文件的字节码



ASM Bytecode Viewer


安装完了之后同样需要重新编译,然后可以直接查看java文件的asm 字节码


在使用 intellij idea 编写 kotlin 的时候,我们可以查看当前 kotlin 文件的字节码。
Tools → Kotlin → Show Kotlin Bytecode

当然字节码是很难看懂的。没关系,我们可以把字节码再反编译成 java 代码。

Windows下安装和配置Kotlin

参考文档:https://www.kotlincn.net/docs/tutorials/command-line.html

在JDK安装完成后,就可以安装Kotlin了。Kotlin是跨平台的,目前支持3种IDE:IntelliJ IDEA、Android Studio和Eclipse。不过在这一节,我们先不考虑IDE的事情。

与Java一样,安装Kotlin后,首先看看是否可以通过命令行方式运行Kotlin程序,这是入门Kotlin要进行的第一步。本节只考虑如何在Windows下安装和配置Kotlin环境,首先进入下面列出的Kotlin官网。

https://kotlinlang.org

将页面滚动到下半部分,会看到如图所示的4个下载区域。最右侧的Compiler是Kotlin编译器的下载页面。

将压缩包解压放在自己喜欢的位置,然后仿照“配置JDK环境变量”的方式配置Kotlin的环境变量。

如果在命令行下输入kotlinc显示类似如下界面,说明配置成功。

编写一个hello.kt,如下

fun main(args: Array<String>) {
println("Hello, World!")
}

使用kotlinc hello.kt编译上面的文件,这时会在同一目录下生成一个HelloKt.class,尝试用java命令来运行HelloKt,结果会是NoClassDefFoundError!

那么,应该如何运行这段代码呢?根据官网的介绍大概是以下两种方式。

方式一:使用Kotlin运行这段代码

D:\IdeaProjects\Helloworld-kotlin\src\basic\kotlin>kotlinc hello.kt
D:\IdeaProjects\Helloworld-kotlin\src\basic\kotlin>kotlin HelloKt
Hello, World!

方式二:使用本地JVM运行这个JAR包

官方的命令为:kotlinc hello.kt -include-runtime -d hello.jar

应该很好理解,运行上述命令之后将得到一个hello.jar,运行这个JAR包:java -jar -hello.jar

D:\labs>java -jar hello.jar
Hello, World!

证明Kotlin是完全兼容JVM的


package basic.kotlin.test

/**
* var 与 val 定义变量:
* 1、var内容可变,可以重新赋值
* 2、val内容不可变,不可以重新赋值
* 3、类型推导
* val修饰的变量相当于java中被final修饰的类型变量--------运行时常量
* 当被const修饰时,编译器会在编译期间编译为具体的值,否则就是还是对象的引用 ----------编译期常量
*
**/
const val FINAL_HELLO_WORLD: String = "HelloWorld" // 不可以重新赋值 var helloWorld: String = FINAL_HELLO_WORLD // 可以重新赋值 val FINAL_HELLO_CHINA = "HelloChina" // 类型推导,由编译器判断。 // 默认返回值 Unit 相当于java中的void,就是什么都不返回,也可省略
fun main(args: Array<String>) { // (Array<String>) -> Unit // FINAL_HELLO_WORLD="qqqq"
helloWorld="123456" // 对var 修饰的常量进行重新赋值
println(helloWorld)
println(FINAL_HELLO_CHINA) println("hello ${args[0]}") var arrayOfstr: Array<String> = arrayOf("1","3")
checkArgs(arrayOfstr)
val arg1 = arrayOfstr[0].toInt()
val arg2 = arrayOfstr[1].toInt()
println("$arg1 + $arg2 = ${sum(arg1, arg2)}") println(int2Long(3)) println(sum(1,3))
println(sum.invoke(1,3)) // invoke是 运算符重载 arrayOfstr.forEach(::println) // reference 写法 // 不加ForEach@ 是退出forEach所在的函数,后面的代码不会被执行
// 加ForEach@ 是退出整个for循环,后面的代码依然会被执行
arrayOfstr.forEach ForEach@{
if(it == "3") return@ForEach
println(it)
} println("The End") println(sum)
println(int2Long)
println(::printUsage is ()-> Unit)
} fun checkArgs(args: Array<String>) {
if (args.size != 2) {
printUsage()
System.exit(-1)
}
} // 函数定义 --- 无返回值
fun printUsage() {
println("请传入两个整型参数,例如 1 2") // (Any?) -> Unit
} // ()->Unit // lambda 表达式 (Int, Int) -> Int
val sum = { arg1: Int, arg2: Int ->
println("$arg1 + $arg2 = ${arg1 + arg2}")
arg1 + arg2
} // ()-> Unit
val printlnHello = {
println("Hello")
} // 匿名函数定义 有返回值
val int2Long = fun(x: Int): Long {
return x.toLong()
}
}

IDEA按键失效:常用快捷键:Ctrl+C  Ctrl+V  选中删除都不起效,原因是IDEA勾选了Vim模式,

Tools,Vim Emulator,前面会有一个√,可,如图:

把那个√取消即可解决问题。

kotlin属性和函数

package basic.kotlin.function

/**
* 测试 属性和方法 属性的getter 和setter是默认实现,也可以手动重写
*
* 默认访问修饰符 public
* 私有的:protected、private
*
* lateinit 是属性延迟初始化修饰符
*/ class Score class Stu{
var age = 0 // getter 和 setter 只能放在当前属性的正下方
get() {
println("测试getter方法")
return field
}
set(value) {
println("测试setter方法")
field=value
} lateinit var name: String // 字符串引用类型懒加载赋值 在使用是必须初始化 lateinit var score: Score // 自定义对象类型懒加载赋值 在使用是必须初始化 val e: Score by lazy { // val 修饰的懒加载赋值,通过 by lazy ,在使用是必须初始化
println("初始化 Score")
Score()
} var cc: String? = null
} fun main(args: Array<String>) {
val stu = Stu()
println(stu.age) // 等价于 stu.getAge()
stu.age=30
println(stu.age) // 使用之前需要初始化 stu.name="张三" // 使用之前需要初始化
println(stu.name) // lateinit property name has not been initialized println(stu.e) // 在定义时初始化 stu.score = Score() // 初始化赋值
println(stu.score) // 打印的对象名,使用之前初始化
println(stu.cc?.length) // 空值的条件判断
}

kotlin的运算符

package basic.kotlin.function
/**
* 运算符:本质上就是一个函数
* + 实际上对应的是kotlin的默认plus 方法
* 我们可以自己定义plus的重载方法 写自己的运算符实现
*
*/
//c1.plus(c2) 返回值 Complex
class Complex(var real: Double, var imaginary: Double){
// 重载方法:1 参数Complex, 返回值 Complex
operator fun plus(other: Complex): Complex{
return Complex(real + other.real, imaginary + other.imaginary)
}
// 重载方法:2 参数Complex,返回值 Complex
operator fun plus(other: Int): Complex{
return Complex(real + other, imaginary)
} // 重载方法:3 参数Any,返回值 Int
operator fun plus(other: Any): Int {
return (real + imaginary).toInt()
} // 重载方法:4
operator fun invoke(): Double{
return Math.hypot(real, imaginary) // q取模运算
} override fun toString(): String {
return "结果:$real + ${imaginary}"
}
} //中缀符号表达式,用于两个对象间的运算
class Book{
infix fun on(any: Any): Boolean{
return false
}
} class Desk fun main(args: Array<String>) {
// + 实际上对应的是kotlin的默认plus 方法
println(1 + 2)
val c1 = Complex(3.0, 4.0)
val c2 = Complex(2.0, 5.0) println(c1 + c2) // 结果:5.0 + 9.0 第一个重载方法 等价于 println(c1.plus(c2))
println(c1 + 5) // 结果:8.0 + 4.0第二个重载方法 等价于 println(c1.plus(5))
println(c1 + "haha") // 7 第三个重载方法 等价于 println(c1.plus("haha"))
println(c1()) // 5.0 第四个重载方法 等价于 println(c1.invoke()) //字符串包含
val arrayOfStr: Array<String> = arrayOf("my","name","is黑客")
if("name" in arrayOfStr){ // 等价于 arrayOfStr.contains("name")
println(arrayOfStr[arrayOfStr.indexOf("name") + 1])
} if(Book() on Desk()){ // dsl
} }

分支表达式 if、when

package basic.kotlin.function
/**
* 分支表达式 if 、when
*/
private const val USERNAME = "kotlin"
private const val PASSWORD = "123" private const val ADMIN_USER = "admin"
private const val ADMIN_PASSWD = "admin" private const val DEBUG = 1
private const val USER = 0 fun main(args: Array<String>) { val x = 5
when(x){ // 只会执行其中的一个
is Int -> println("Hello $x") // 判断 是否是int类型
in 1..100 -> println("$x is in 1..100") // 判断是否是在区间中
!in 1..100 -> println("$x is not in 1..100") // 判断是否是不在区间中
args[0].toInt() -> println("x == args[0]") // x 和当前表达式是否一样
} // 相当于if else
val wh = when{
args.isNotEmpty() && args[0] == "1"
-> 1
else -> 0
} println(wh) // if表达式 带返回值
val mode = if(args.isNotEmpty() && args[0] == "1"){
DEBUG
}else{
USER
} println("请输入用户名:")
val username = readLine()
println("请输入密码:")
val passwd = readLine() if(mode == DEBUG && username == ADMIN_USER && passwd == ADMIN_PASSWD) {
println("管理员登录成功")
}else if(username == USERNAME && passwd == PASSWORD){
println("登录成功")
}else{
println("登录失败")
}
}

package basic.kotlin.function

/**
* 跳过continue 和 跳出break 循环
*/
class Student{
fun isNotClothedProperly(): Boolean{
return false
}
} fun main(args: Array<String>) {
val students = ArrayList<Student>()
val you = Student()
for (student in students){
if(student == you) continue
if(student.isNotClothedProperly()){
break
}
}
}
package basic.kotlin.function

/**
* for 循环 和 while 循环 语句
*/
fun main(args: Array<String>) { val arrayOfStr: Array<String> = arrayOf("my","name","is黑客") var x = 5
while(x > 0){
println(x)
x--
} do{
println(x)
x--
}while (x > 0) for (arg in arrayOfStr){
println(arg)
} for((index, value) in arrayOfStr.withIndex()){
println("$index -> $value")
} for(indexedValue in arrayOfStr.withIndex()){
println("${indexedValue.index} -> ${indexedValue.value}")
} val list = MyIntList()
list.add(1)
list.add(2)
list.add(3) for(i in list){
println(i)
}
} class MyIterator(val iterator: Iterator<Int>){
operator fun next(): Int{
return iterator.next()
} operator fun hasNext(): Boolean{
return iterator.hasNext()
}
} class MyIntList{
private val list = ArrayList<Int>() fun add(int : Int){
list.add(int)
} fun remove(int: Int){
list.remove(int)
} operator fun iterator(): MyIterator{
return MyIterator(list.iterator())
}
}

异常捕获

package basic.kotlin.function

/**
* 异常捕获
*/
fun main(args: Array<String>) {
val res = try {
val result = 1/0
}catch (e: Exception){
println("程序出现了未知异常,可能是您的人品太差了。${e.message}")
0
}finally {
println("谢谢您使用我们的加法计算器")
}
println(res)
}

具名参数:参数赋值到具体名称,没有顺序

变长参数:在java里是最后一个参数,在kotlin没有这种限制

默认参数:调用时不传入参数,可以采用设置默认值

package basic.kotlin.function

/**
* 具名参数:参数赋值到具体名称,没有顺序
* 变长参数:在java里是最后一个参数,在kotlin没有这种限制
* 默认参数:调用时不传入参数,可以采用设置默认值
*/
fun main(vararg args: String) {
// for (arg in args){
// println(arg)
// } val list = arrayListOf(1,3,4,5)
val array = intArrayOf(1,3,4,5)
hello(3.0, *array)
} fun hello(double: Double, vararg ints: Int, string: String = "Hello"){
println(double)
ints.forEach(::println)
println(string)
}

先以 Http Servlet 创建 Web 应用 为例

在导入工程后,通过gradle的工具创建生成war,war包的名称和settings.gradle的 rootProject.name = 'servlet-web-applications' 一致

方式一:打成war包运行

手动放到tomcat容器,双击运行tomcat。

方式二:

IDEA 中添加tomcat容器的方式运行工程

Kotlin开发springboot项目(二)的更多相关文章

  1. Kotlin开发springboot项目(一)

    Kotlin开发springboot项目(一) Kotlin语言与Xtend语言有很多相似之处 为什么会存在这么多JVM语言? 现存的语言提供了太过受限制的功能,要不就是功能太过繁杂,导致语言的臃肿和 ...

  2. Kotlin开发springboot项目(三)

    Kotlin开发springboot项目(三) 在线工具 https://www.sojson.com IDEA中Kotlin生成可执行文件1,项目使用Gradle构建2,在model的build.g ...

  3. docker 运行jenkins及vue项目与springboot项目(二.docker运行jenkins为自动打包运行做准备)

    docker 运行jenkins及vue项目与springboot项目: 一.安装docker 二.docker运行jenkins为自动打包运行做准备 三.jenkins的使用及自动打包vue项目 四 ...

  4. 使用Spring Boot开发Web项目(二)之添加HTTPS支持

    上篇博客使用Spring Boot开发Web项目我们简单介绍了使用如何使用Spring Boot创建一个使用了Thymeleaf模板引擎的Web项目,当然这还远远不够.今天我们再来看看如何给我们的We ...

  5. 从零开始的SpringBoot项目 ( 二 ) 使用IDEA创建一个SpringBoot项目

    工欲善其事 , 必先利其器 . IntelliJ IDEA 2019.3.3 x64的安装与破解 下面详细说明下如何使用idea创建我们的第一个springboot项目: 首先打开idea主界面选择 ...

  6. 利用maven开发springMVC项目(二)——框架配置

    申明:主要内容来源于大神博客(使用IntelliJ IDEA开发SpringMVC网站(二)框架配置),我只是用eclipse自己练习使用,记录下来也只是为了学习使用,没有任何的商业用途,侵权必删. ...

  7. [Android]使用Kotlin开发Android(二)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4829007.html [TOC] 使用Kotlin+OkHtt ...

  8. Maven多模块开发SpringBoot项目自定义第三方依赖版本

    参考:官方文档 - Build System of Maven https://blog.didispace.com/books/spring-boot-reference/IX. 'How-to' ...

  9. 10.17正式开发stark项目(二)

    2018-10-17 11:09:48 orm补充参考连接: https://www.cnblogs.com/yuanchenqi/articles/8963244.html model 进阶 参考连 ...

随机推荐

  1. Linux SSH建立连接过程分析

    https://blog.csdn.net/qwertyupoiuytr/article/details/71213463 SSH建立连接的过程主要分为下面几个阶段: SSH协议版本协商阶段.SSH目 ...

  2. django之分页器、多对多关系、form校验组件

    批量插入数据 bulk_create # 1.往书籍表中插入数据 1000 # for i in range(1000): # 这种插入方式 效率极低 # models.Book.objects.cr ...

  3. django之视图层和部分模板层

    视图层 小白必会三板斧(三个返回的都是HttpResponse对象,通过看源码,可以知道是内部实现) 1.HttpResponse # 返回字符串 2.render # 返回一个html页面 还可以给 ...

  4. Ubuntu使用snap安装常用软件

    1,snap简介 什么是snap,snap是一种全新的软件包管理方式,它类似一个容器拥有一个应用程序所有的文件和库,各个应用程序之间完全独立.所以使用snap包的好处就是它解决了应用程序之间的依赖问题 ...

  5. ibatis<iterate>标签

    <iterate  property="" 从传入的参数集合中使用属性名去获取值,   这个必须是一个List类型,   否则会出现OutofRangeException, ...

  6. 了解html

    什么是html? html:Hyper Text Markup Language(超文本标记语言) 纯文本:只能存储一些简单的字符(不能插入图片.视频...) 注意:html不是一种编程语言(它没有任 ...

  7. 谈谈IntersectionObserver懒加载

    概念 IntersectionObserver接口(从属于Intersection Observer API)为开发者提供了一种可以异步监听目标元素与其祖先或视窗(viewport)交叉状态的手段.祖 ...

  8. K8s 集群安装(一)

    01,集群环境 三个节点   master node1 node2 IP 192.168.0.81 192.168.0.82 192.168.0.83 环境 centos 7 centos 7 cen ...

  9. Deep Learning专栏--强化学习之MDP、Bellman方程(1)

    本文主要介绍强化学习的一些基本概念:包括MDP.Bellman方程等, 并且讲述了如何从 MDP 过渡到 Reinforcement Learning. 1. 强化学习基本概念 这里还是放上David ...

  10. apache poi操作office文档----java在线预览txt、word、ppt、execel,pdf代码

    在页面上显示各种文档中的内容.在servlet中的逻辑 word: BufferedInputStream bis = null;  URL url = null;  HttpURLConnectio ...