|
1 |
| -# reakt |
| 1 | +# React.js 集成 Kotlin Spring Boot 开发 Web 应用实例详解 |
| 2 | + |
| 3 | +> Reakt , an example of using React.js 集成 Kotlin Spring Boot 开发 Web 应用实例 |
| 4 | +
|
| 5 | + |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | + |
| 10 | + |
| 11 | + |
| 12 | +项目工程目录 |
| 13 | +``` |
| 14 | +~/easykotlin/reakt$ tree |
| 15 | +. |
| 16 | +├── build |
| 17 | +│ ├── kotlin |
| 18 | +│ │ ├── compileKotlin |
| 19 | +│ │ └── compileTestKotlin |
| 20 | +│ └── kotlin-build |
| 21 | +│ └── version.txt |
| 22 | +├── build.gradle |
| 23 | +├── gradle |
| 24 | +│ └── wrapper |
| 25 | +│ ├── gradle-wrapper.jar |
| 26 | +│ └── gradle-wrapper.properties |
| 27 | +├── gradlew |
| 28 | +├── gradlew.bat |
| 29 | +├── reakt.iml |
| 30 | +├── reakt.ipr |
| 31 | +├── reakt.iws |
| 32 | +├── reakt_main.iml |
| 33 | +├── reakt_test.iml |
| 34 | +└── src |
| 35 | + ├── main |
| 36 | + │ ├── java |
| 37 | + │ ├── kotlin |
| 38 | + │ │ └── com |
| 39 | + │ │ └── easykotlin |
| 40 | + │ │ └── reakt |
| 41 | + │ │ └── ReaktApplication.kt |
| 42 | + │ └── resources |
| 43 | + │ ├── application.properties |
| 44 | + │ ├── static |
| 45 | + │ └── templates |
| 46 | + └── test |
| 47 | + ├── java |
| 48 | + ├── kotlin |
| 49 | + │ └── com |
| 50 | + │ └── easykotlin |
| 51 | + │ └── reakt |
| 52 | + │ └── ReaktApplicationTests.kt |
| 53 | + └── resources |
| 54 | +
|
| 55 | +24 directories, 14 files |
| 56 | +
|
| 57 | +``` |
| 58 | + |
| 59 | + |
| 60 | + |
| 61 | + |
| 62 | + |
| 63 | + |
| 64 | + |
| 65 | + |
| 66 | + |
| 67 | + |
| 68 | +build.gradle |
| 69 | + |
| 70 | +```groovy |
| 71 | +buildscript { |
| 72 | + ext { |
| 73 | + kotlinVersion = '1.2.0' |
| 74 | + springBootVersion = '2.0.0.M7' |
| 75 | + } |
| 76 | + repositories { |
| 77 | + mavenCentral() |
| 78 | + maven { url "https://repo.spring.io/snapshot" } |
| 79 | + maven { url "https://repo.spring.io/milestone" } |
| 80 | + } |
| 81 | + dependencies { |
| 82 | + classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") |
| 83 | + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}") |
| 84 | + classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}") |
| 85 | + } |
| 86 | +} |
| 87 | +
|
| 88 | +apply plugin: 'kotlin' |
| 89 | +apply plugin: 'kotlin-spring' |
| 90 | +apply plugin: 'eclipse' |
| 91 | +apply plugin: 'org.springframework.boot' |
| 92 | +apply plugin: 'io.spring.dependency-management' |
| 93 | +
|
| 94 | +group = 'com.easykotlin' |
| 95 | +version = '0.0.1-SNAPSHOT' |
| 96 | +sourceCompatibility = 1.8 |
| 97 | +compileKotlin { |
| 98 | + kotlinOptions.jvmTarget = "1.8" |
| 99 | +} |
| 100 | +compileTestKotlin { |
| 101 | + kotlinOptions.jvmTarget = "1.8" |
| 102 | +} |
| 103 | +
|
| 104 | +repositories { |
| 105 | + mavenCentral() |
| 106 | + maven { url "https://repo.spring.io/snapshot" } |
| 107 | + maven { url "https://repo.spring.io/milestone" } |
| 108 | +} |
| 109 | +
|
| 110 | +
|
| 111 | +dependencies { |
| 112 | + compile('org.springframework.boot:spring-boot-starter-actuator') |
| 113 | + compile('org.springframework.boot:spring-boot-starter-data-jpa') |
| 114 | + compile('org.springframework.boot:spring-boot-starter-freemarker') |
| 115 | + compile('org.springframework.boot:spring-boot-starter-security') |
| 116 | + compile('org.springframework.boot:spring-boot-starter-web') |
| 117 | + compile("org.jetbrains.kotlin:kotlin-stdlib-jre8:${kotlinVersion}") |
| 118 | + compile("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}") |
| 119 | + runtime('mysql:mysql-connector-java') |
| 120 | + testCompile('org.springframework.boot:spring-boot-starter-test') |
| 121 | + testCompile('org.springframework.security:spring-security-test') |
| 122 | +} |
| 123 | +
|
| 124 | +``` |
| 125 | + |
| 126 | +ReaktApplication.kt |
| 127 | + |
| 128 | +```kotlin |
| 129 | +package com.easykotlin.reakt |
| 130 | + |
| 131 | +import org.springframework.boot.autoconfigure.SpringBootApplication |
| 132 | +import org.springframework.boot.runApplication |
| 133 | + |
| 134 | +@SpringBootApplication |
| 135 | +class ReaktApplication |
| 136 | + |
| 137 | +fun main(args: Array<String>) { |
| 138 | + runApplication<ReaktApplication>(*args) |
| 139 | +} |
| 140 | + |
| 141 | +``` |
| 142 | + |
| 143 | + |
| 144 | +后端工程目录 |
| 145 | + |
| 146 | +``` |
| 147 | +~/easykotlin/reakt$ tree |
| 148 | +. |
| 149 | +├── LICENSE |
| 150 | +├── README.md |
| 151 | +├── build |
| 152 | +│ ├── kotlin |
| 153 | +│ │ ├── compileKotlin |
| 154 | +│ │ └── compileTestKotlin |
| 155 | +│ └── kotlin-build |
| 156 | +│ └── version.txt |
| 157 | +├── build.gradle |
| 158 | +├── gradle |
| 159 | +│ └── wrapper |
| 160 | +│ ├── gradle-wrapper.jar |
| 161 | +│ └── gradle-wrapper.properties |
| 162 | +├── gradlew |
| 163 | +├── gradlew.bat |
| 164 | +├── out |
| 165 | +│ └── production |
| 166 | +│ ├── classes |
| 167 | +│ │ ├── META-INF |
| 168 | +│ │ │ └── reakt_main.kotlin_module |
| 169 | +│ │ └── com |
| 170 | +│ │ └── easykotlin |
| 171 | +│ │ └── reakt |
| 172 | +│ │ ├── ReaktApplication.class |
| 173 | +│ │ ├── ReaktApplicationKt$main$1$$special$$inlined$bean$1.class |
| 174 | +│ │ ├── ReaktApplicationKt$main$1$$special$$inlined$bean$2$1$lambda$1.class |
| 175 | +│ │ ├── ReaktApplicationKt$main$1$$special$$inlined$bean$2$1.class |
| 176 | +│ │ ├── ReaktApplicationKt$main$1$$special$$inlined$bean$2$2$lambda$1.class |
| 177 | +│ │ ├── ReaktApplicationKt$main$1$$special$$inlined$bean$2$2.class |
| 178 | +│ │ ├── ReaktApplicationKt$main$1$$special$$inlined$bean$2.class |
| 179 | +│ │ ├── ReaktApplicationKt$main$1.class |
| 180 | +│ │ ├── ReaktApplicationKt.class |
| 181 | +│ │ ├── WebSecurityConfig.class |
| 182 | +│ │ ├── advice |
| 183 | +│ │ │ └── GlobalExceptionHandlerAdvice.class |
| 184 | +│ │ ├── controller |
| 185 | +│ │ │ ├── ApiController.class |
| 186 | +│ │ │ ├── LoginController.class |
| 187 | +│ │ │ └── RouterController.class |
| 188 | +│ │ ├── dao |
| 189 | +│ │ │ ├── RoleDao.class |
| 190 | +│ │ │ └── UserDao.class |
| 191 | +│ │ ├── entity |
| 192 | +│ │ │ ├── Role.class |
| 193 | +│ │ │ └── User.class |
| 194 | +│ │ ├── handler |
| 195 | +│ │ │ ├── ControllerTools.class |
| 196 | +│ │ │ └── MyAccessDeniedHandler.class |
| 197 | +│ │ └── service |
| 198 | +│ │ └── MyUserDetailService.class |
| 199 | +│ └── resources |
| 200 | +│ ├── application-daily.properties |
| 201 | +│ ├── application-dev.properties |
| 202 | +│ ├── application-prod.properties |
| 203 | +│ ├── application.properties |
| 204 | +│ └── logback-spring.xml |
| 205 | +├── reakt.iml |
| 206 | +├── reakt.ipr |
| 207 | +├── reakt.iws |
| 208 | +├── reakt_main.iml |
| 209 | +├── reakt_test.iml |
| 210 | +└── src |
| 211 | + ├── main |
| 212 | + │ ├── java |
| 213 | + │ ├── kotlin |
| 214 | + │ │ └── com |
| 215 | + │ │ └── easykotlin |
| 216 | + │ │ └── reakt |
| 217 | + │ │ ├── ReaktApplication.kt |
| 218 | + │ │ ├── advice |
| 219 | + │ │ │ └── GlobalExceptionHandlerAdvice.kt |
| 220 | + │ │ ├── controller |
| 221 | + │ │ │ ├── ApiController.kt |
| 222 | + │ │ │ ├── LoginController.kt |
| 223 | + │ │ │ └── RouterController.kt |
| 224 | + │ │ ├── dao |
| 225 | + │ │ │ ├── RoleDao.kt |
| 226 | + │ │ │ └── UserDao.kt |
| 227 | + │ │ ├── entity |
| 228 | + │ │ │ ├── Role.kt |
| 229 | + │ │ │ └── User.kt |
| 230 | + │ │ ├── handler |
| 231 | + │ │ │ └── MyAccessDeniedHandler.kt |
| 232 | + │ │ ├── security |
| 233 | + │ │ │ └── WebSecurityConfig.kt |
| 234 | + │ │ └── service |
| 235 | + │ │ └── MyUserDetailService.kt |
| 236 | + │ └── resources |
| 237 | + │ ├── application-daily.properties |
| 238 | + │ ├── application-dev.properties |
| 239 | + │ ├── application-prod.properties |
| 240 | + │ ├── application.properties |
| 241 | + │ ├── logback-spring.xml |
| 242 | + │ ├── static |
| 243 | + │ └── templates |
| 244 | + └── test |
| 245 | + ├── java |
| 246 | + ├── kotlin |
| 247 | + │ └── com |
| 248 | + │ └── easykotlin |
| 249 | + │ └── reakt |
| 250 | + │ └── ReaktApplicationTests.kt |
| 251 | + └── resources |
| 252 | +
|
| 253 | +45 directories, 58 files |
| 254 | +
|
| 255 | +``` |
| 256 | + |
| 257 | +前端Node React 工程部分: |
| 258 | + |
| 259 | +使用 $ nowa init web 命令创建前端 web 工程: |
| 260 | + |
| 261 | + |
| 262 | + |
| 263 | + |
| 264 | +``` |
| 265 | +~/easykotlin/reakt/front$ nowa init web |
| 266 | +
|
| 267 | +Welcome to nowa project generator! |
| 268 | +I will use this template to generate your project: |
| 269 | +https://github.com/nowa-webpack/template-uxcore/archive/v5.zip |
| 270 | +May I ask you some questions? |
| 271 | +
|
| 272 | +? Project name reakt |
| 273 | +? Project description An awesome project |
| 274 | +? Author name jack |
| 275 | +? Project version 1.0.0 |
| 276 | +? Project homepage |
| 277 | +? Project repository |
| 278 | +? Npm registry https://registry.npm.taobao.org |
| 279 | +? Do you want SPA feature? Yes |
| 280 | +? Do you want i18n feature? (Y/n) Y |
| 281 | +
|
| 282 | +
|
| 283 | +
|
| 284 | +Start to copy files ... |
| 285 | +
|
| 286 | +Generate file .editorconfig |
| 287 | +Generate file .eslintignore |
| 288 | +Generate file .eslintrc.json |
| 289 | +Generate file .gitignore |
| 290 | +Generate file abc.json |
| 291 | +Generate file html/index.html |
| 292 | +Generate file mock/user/query.js |
| 293 | +Generate file package.json |
| 294 | +Generate file src/app/app.js |
| 295 | +Generate file src/app/app.less |
| 296 | +Generate file src/app/db.js |
| 297 | +Generate file src/app/routes.jsx |
| 298 | +Generate file src/app/util.js |
| 299 | +Generate file src/app/variables.js |
| 300 | +Generate file src/components/search-data/index.js |
| 301 | +Generate file src/components/search-data/SearchData.jsx |
| 302 | +Generate file src/components/search-word/index.js |
| 303 | +Generate file src/components/search-word/SearchWord.jsx |
| 304 | +Generate file src/i18n/en.js |
| 305 | +Generate file src/i18n/index.js |
| 306 | +Generate file src/i18n/zh-cn.js |
| 307 | +Generate file src/images/README.md |
| 308 | +Generate file src/pages/demo/index.js |
| 309 | +Generate file src/pages/demo/logic.js |
| 310 | +Generate file src/pages/demo/PageDemo.jsx |
| 311 | +Generate file src/pages/demo/PageDemo.less |
| 312 | +Generate file src/pages/error/index.js |
| 313 | +Generate file src/pages/error/PageError.jsx |
| 314 | +Generate file src/pages/error/PageError.less |
| 315 | +Generate file src/pages/home/index.js |
| 316 | +Generate file src/pages/home/logic.js |
| 317 | +Generate file src/pages/home/PageHome.jsx |
| 318 | +Generate file src/pages/home/PageHome.less |
| 319 | +Generate file webpack.config.js |
| 320 | +npm notice created a lockfile as package-lock.json. You should commit this file. |
| 321 | +npm WARN uxcore-layout@1.0.5 requires a peer of react@>=0.13.0 but none is installed. You must install peer dependencies yourself. |
| 322 | +npm WARN uxcore-button@0.3.12 requires a peer of react@>=0.13.0 but none is installed. You must install peer dependencies yourself. |
| 323 | +npm WARN uxcore-button@0.3.12 requires a peer of react@>=0.13.0 but none is installed. You must install peer dependencies yourself. |
| 324 | +npm WARN uxcore-button@0.3.12 requires a peer of react@>=0.13.0 but none is installed. You must install peer dependencies yourself. |
| 325 | +npm WARN uxcore-transfer@0.3.10 requires a peer of react@>=0.13.0 but none is installed. You must install peer dependencies yourself. |
| 326 | +npm WARN react-slick@0.14.8 requires a peer of react@^0.14.0 || ^15.0.1 but none is installed. You must install peer dependencies yourself. |
| 327 | +npm WARN react-slick@0.14.8 requires a peer of react-dom@^0.14.0 || ^15.0.1 but none is installed. You must install peer dependencies yourself. |
| 328 | +npm WARN enzyme@2.9.1 requires a peer of react@0.13.x || 0.14.x || ^15.0.0-0 || 15.x but none is installed. You must install peer dependencies yourself. |
| 329 | +npm WARN react-test-renderer@15.6.2 requires a peer of react@^15.6.2 but none is installed. You must install peer dependencies yourself. |
| 330 | +npm WARN react-hammerjs@0.5.0 requires a peer of react@^0.14.3 || ^15.0.0 but none is installed. You must install peer dependencies yourself. |
| 331 | +
|
| 332 | +added 249 packages in 15.628s |
| 333 | +``` |
| 334 | + |
| 335 | + |
| 336 | +设置 JavaScript 的版本是 ES6 |
| 337 | + |
| 338 | + |
| 339 | + |
| 340 | + |
| 341 | + |
| 342 | +前端工程 |
| 343 | + |
| 344 | + |
| 345 | + |
| 346 | +``` |
| 347 | +~/easykotlin/reakt/front$ nowa server |
| 348 | +Listening at http://192.168.0.104:3000 |
| 349 | +``` |
| 350 | + |
| 351 | + |
| 352 | + |
| 353 | + |
| 354 | +``` |
| 355 | +~/easykotlin/reakt/front$ nowa server |
| 356 | +Listening at http://192.168.0.104:3000 |
| 357 | +webpack built 77b5a8beed9790822bea in 12869ms |
| 358 | +Hash: 77b5a8beed9790822bea |
| 359 | +Version: webpack 1.13.3 |
| 360 | +Time: 12869ms |
| 361 | + Asset Size Chunks Chunk Names |
| 362 | + app-zh-cn.js 1.98 MB 0 [emitted] app |
| 363 | + 1.home-zh-cn.js 641 kB 1 [emitted] home |
| 364 | + 2.demo-zh-cn.js 641 kB 2 [emitted] demo |
| 365 | +3.error-zh-cn.js 540 kB 3 [emitted] error |
| 366 | +webpack: bundle is now VALID. |
| 367 | +
|
| 368 | +``` |
| 369 | + |
| 370 | + |
| 371 | +nowa build 之后的默认输出目录在 dist 下面. 我们下面写一个构建脚本,分别拷贝这些 js,css,html 到 Spring Boot 工程的 resource 目录下面: |
| 372 | + |
| 373 | + |
| 374 | + |
| 375 | + |
| 376 | + |
| 377 | +reakt.sh |
| 378 | + |
| 379 | +```shell |
| 380 | +#!/usr/bin/env bash |
| 381 | +#build front js,css,html |
| 382 | +cd ./front |
| 383 | +nowa build |
| 384 | +cd ../ |
| 385 | +#cp js,css,html to /templates, /static |
| 386 | +kotlinc -script reakt.kts |
| 387 | +#gradle bootRun |
| 388 | +gradle bootRun |
| 389 | + |
| 390 | +``` |
| 391 | + |
| 392 | + |
| 393 | +reakt.kts |
| 394 | + |
| 395 | +```kotlin |
| 396 | +import java.io.File |
| 397 | +import java.io.FileFilter |
| 398 | + |
| 399 | +val srcPath = File("./front/dist/") |
| 400 | + |
| 401 | +val templatesPath = "src/main/resources/templates/" |
| 402 | +val jsFile = "src/main/resources/static/js/" |
| 403 | +val cssPath = "src/main/resources/static/css/" |
| 404 | + |
| 405 | +val templatesDir = File("src/main/resources/templates/") |
| 406 | +val cssDir = File("src/main/resources/static/css/") |
| 407 | +val jsDir = File("src/main/resources/static/js/") |
| 408 | + |
| 409 | +if (!templatesDir.exists()) templatesDir.mkdirs() |
| 410 | +if (!cssDir.exists()) cssDir.mkdirs() |
| 411 | +if (!jsDir.exists()) jsDir.mkdirs() |
| 412 | + |
| 413 | +srcPath.listFiles().forEach { |
| 414 | + val fileName = it.name |
| 415 | + when { |
| 416 | + fileName.endsWith(".html") -> { |
| 417 | + println("Copy file: $fileName") |
| 418 | + |
| 419 | + val htmlFile = File("$templatesPath$fileName") |
| 420 | + it.copyTo(target = htmlFile, overwrite = true) |
| 421 | + replaceJsCssSrc(htmlFile) |
| 422 | + } |
| 423 | + fileName.endsWith(".js") -> { |
| 424 | + println("Copy file: $fileName") |
| 425 | + it.copyTo(target = File("$jsFile$fileName"), overwrite = true) |
| 426 | + } |
| 427 | + fileName.endsWith(".css") -> { |
| 428 | + println("Copy file: $fileName") |
| 429 | + it.copyTo(target = File("$cssPath$fileName"), overwrite = true) |
| 430 | + } |
| 431 | + } |
| 432 | +} |
| 433 | + |
| 434 | + |
| 435 | + |
| 436 | + |
| 437 | +fun replaceJsCssSrc(htmlFile: File) { |
| 438 | + val oldJsSrc = """<script src="/""" |
| 439 | + val oldJsSrcParticular = """<script src="//""" |
| 440 | + val newJsSrc = """<script src="/js/""" |
| 441 | + |
| 442 | + val oldCssSrc = """<link rel="stylesheet" href="/""" |
| 443 | + val newCssSrc = """<link rel="stylesheet" href="/css/""" |
| 444 | + |
| 445 | + var lines = StringBuilder() |
| 446 | + htmlFile.readLines().forEach { |
| 447 | + var line = it |
| 448 | + if (line.contains(oldJsSrc) && !line.contains(oldJsSrcParticular)) { |
| 449 | + line = line.replace(oldJsSrc, newJsSrc) |
| 450 | + } else if (line.contains(oldCssSrc)) { |
| 451 | + line = line.replace(oldCssSrc, newCssSrc) |
| 452 | + } |
| 453 | + |
| 454 | + lines.append(line + "\n") |
| 455 | + } |
| 456 | + |
| 457 | + htmlFile.writeText(lines.toString()) |
| 458 | +} |
| 459 | + |
| 460 | +``` |
| 461 | + |
| 462 | + |
| 463 | + |
| 464 | + |
| 465 | + |
| 466 | + |
| 467 | + |
| 468 | + |
| 469 | +logback-spring.xml |
| 470 | + |
| 471 | +```xml |
| 472 | +<?xml version="1.0" encoding="UTF-8"?> |
| 473 | +<configuration> |
| 474 | + <springProperty scope="context" |
| 475 | + name="logging.file" |
| 476 | + source="logging.file"/> |
| 477 | + |
| 478 | + <springProperty scope="context" |
| 479 | + name="logging.path" |
| 480 | + source="logging.path"/> |
| 481 | + |
| 482 | + <springProperty scope="context" |
| 483 | + name="logging.level.root" |
| 484 | + source="logging.level.root"/> |
| 485 | + |
| 486 | + <springProperty scope="context" |
| 487 | + name="spring.application.name" |
| 488 | + source="spring.application.name"/> |
| 489 | + |
| 490 | + <springProperty scope="context" |
| 491 | + name="logging.file.max-size" |
| 492 | + source="logging.file.max-size"/> |
| 493 | + |
| 494 | + <springProperty scope="context" |
| 495 | + name="logging.file.max-history" |
| 496 | + source="logging.file.max-history"/> |
| 497 | + |
| 498 | + <property name="LOG_FILE" |
| 499 | + value="${logging.path:-.}/${logging.file:-${spring.application.name:-spring}.log}"/> |
| 500 | + |
| 501 | + |
| 502 | + <property name="MAX_SIZE" |
| 503 | + value="${logging.file.max-size:-10MB}"/> |
| 504 | + |
| 505 | + |
| 506 | + <property name="MAX_HISTORY" |
| 507 | + value="${logging.file.max-history:-0}"/> |
| 508 | + |
| 509 | + |
| 510 | + <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter"/> |
| 511 | + <conversionRule conversionWord="wex" |
| 512 | + converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter"/> |
| 513 | + <conversionRule conversionWord="wEx" |
| 514 | + converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter"/> |
| 515 | + |
| 516 | + <property name="CONSOLE_LOG_PATTERN" |
| 517 | + value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> |
| 518 | + <property name="FILE_LOG_PATTERN" |
| 519 | + value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> |
| 520 | + |
| 521 | + <logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR"/> |
| 522 | + <logger name="org.apache.catalina.util.LifecycleBase" level="ERROR"/> |
| 523 | + <logger name="org.apache.coyote.http11.Http11NioProtocol" level="WARN"/> |
| 524 | + <logger name="org.apache.sshd.common.util.SecurityUtils" level="WARN"/> |
| 525 | + <logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN"/> |
| 526 | + <logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="ERROR"/> |
| 527 | + <logger name="org.hibernate.validator.internal.util.Version" level="WARN"/> |
| 528 | + |
| 529 | + <!-- show parameters for hibernate sql 专为 Hibernate 定制 --> |
| 530 | + <logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/> |
| 531 | + <logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="DEBUG"/> |
| 532 | + <logger name="org.hibernate.SQL" level="DEBUG"/> |
| 533 | + <logger name="org.hibernate.engine.QueryParameters" level="DEBUG"/> |
| 534 | + <logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG"/> |
| 535 | + |
| 536 | + <!--myibatis log configure--> |
| 537 | + <logger name="com.apache.ibatis" level="TRACE"/> |
| 538 | + <logger name="java.sql.Connection" level="DEBUG"/> |
| 539 | + <logger name="java.sql.Statement" level="DEBUG"/> |
| 540 | + <logger name="java.sql.PreparedStatement" level="DEBUG"/> |
| 541 | + |
| 542 | + <!--<include resource="org/springframework/boot/logging/logback/base.xml"/>--> |
| 543 | + |
| 544 | + <appender name="FILE" |
| 545 | + class="ch.qos.logback.core.rolling.RollingFileAppender"> |
| 546 | + <encoder> |
| 547 | + <pattern>${FILE_LOG_PATTERN}</pattern> |
| 548 | + </encoder> |
| 549 | + <file>${LOG_FILE}</file> |
| 550 | + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> |
| 551 | + <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz</fileNamePattern> |
| 552 | + <maxFileSize>${MAX_SIZE}</maxFileSize> |
| 553 | + <maxHistory>${MAX_HISTORY}</maxHistory> |
| 554 | + </rollingPolicy> |
| 555 | + </appender> |
| 556 | + |
| 557 | + <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> |
| 558 | + <encoder> |
| 559 | + <pattern>${CONSOLE_LOG_PATTERN}</pattern> |
| 560 | + <charset>utf8</charset> |
| 561 | + </encoder> |
| 562 | + </appender> |
| 563 | + |
| 564 | + <root level="${logging.level.root}"> |
| 565 | + <appender-ref ref="CONSOLE"/> |
| 566 | + <appender-ref ref="FILE"/> |
| 567 | + </root> |
| 568 | +</configuration> |
| 569 | + |
| 570 | +``` |
| 571 | + |
| 572 | +application-dev.properties |
| 573 | + |
| 574 | +``` |
| 575 | +spring.application.name=reakt |
| 576 | +server.port=8004 |
| 577 | +#mysql |
| 578 | +spring.datasource.url=jdbc:mysql://localhost:3306/reakt?useUnicode=true&characterEncoding=UTF8&useSSL=false |
| 579 | +spring.datasource.username=root |
| 580 | +spring.datasource.password=root |
| 581 | +spring.datasource.driverClassName=com.mysql.jdbc.Driver |
| 582 | +# Specify the DBMS |
| 583 | +spring.jpa.database=MYSQL |
| 584 | +# Show or not log for each sql query |
| 585 | +spring.jpa.show-sql=true |
| 586 | +# Hibernate ddl auto (create, create-drop, update) |
| 587 | +spring.jpa.hibernate.ddl-auto=create-drop |
| 588 | +#spring.jpa.hibernate.ddl-auto=update |
| 589 | +# stripped before adding them to the entity manager) |
| 590 | +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect |
| 591 | +#logging |
| 592 | +logging.level.root=info |
| 593 | +logging.level.org.springframework.web=info |
| 594 | +logging.path=${user.home}/logs |
| 595 | +#logging.file=${spring.application.name}.log |
| 596 | +#logging.exception-conversion-word= |
| 597 | +#logging.pattern.console= |
| 598 | +#logging.pattern.file= |
| 599 | +logging.file.max-history=30 |
| 600 | +logging.file.max-size=2MB |
| 601 | +#logging.pattern.level= |
| 602 | +#logging.pattern.dateformat= |
| 603 | +#Freemarker |
| 604 | +# template-loader-path, comma-separated list |
| 605 | +#spring.freemarker.template-loader-path=classpath:/reakt/dist/ |
| 606 | +spring.freemarker.template-loader-path=classpath:/templates/ |
| 607 | +# suffix |
| 608 | +spring.freemarker.suffix=.html |
| 609 | +# static resources path pattern, default is root path: /** , 浏览器请求路径,会映射到spring.resources.static-locations |
| 610 | +#spring.mvc.static-path-pattern=/reakt/dist/** |
| 611 | +# if config this key, will overwrite the default Spring Boot Config |
| 612 | +#spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,classpath:/reakt/dist/ |
| 613 | +#management |
| 614 | +management.endpoints.web.enabled=true |
| 615 | +management.endpoints.enabled-by-default=true |
| 616 | +management.endpoints.web.base-path=/actuator |
| 617 | +management.health.db.enabled=true |
| 618 | +management.endpoint.health.enabled=true |
| 619 | +management.endpoint.metrics.enabled=true |
| 620 | +management.endpoint.mappings.enabled=true |
| 621 | +management.endpoint.info.enabled=true |
| 622 | +management.endpoint.beans.enabled=true |
| 623 | +management.endpoint.env.enabled=true |
| 624 | +management.endpoint.health.show-details=true |
| 625 | +management.endpoint.logfile.enabled=true |
| 626 | +management.endpoint.scheduledtasks.enabled=true |
| 627 | +management.endpoint.sessions.enabled=true |
| 628 | +management.health.diskspace.enabled=true |
| 629 | +management.info.git.enabled=true |
| 630 | +
|
| 631 | +``` |
| 632 | + |
| 633 | + |
| 634 | +# 工程源代码 |
| 635 | + |
| 636 | +完整的工程源代码(感觉有所帮助的, 顺手点个 Star 哦 !): |
| 637 | + |
| 638 | +https://github.com/EasyKotlin/reakt |
| 639 | + |
| 640 | + |
| 641 | + |
| 642 | +# 参考文章 |
| 643 | + |
| 644 | +React.js and Spring Data REST: |
| 645 | + |
| 646 | +https://spring.io/guides/tutorials/react-and-spring-data-rest/ |
| 647 | + |
| 648 | +Kotlin 使用命令行执行 kts 脚本: http://www.jianshu.com/p/5848fbb73227 |
| 649 | + |
| 650 | +http://start.spring.io/ |
| 651 | + |
| 652 | + |
| 653 | + |
| 654 | + |
0 commit comments