Ktor是一個為 Kotlin 編寫和設計的異步 Web 框架,它利用協程并允許您編寫異步代碼,而無需自己管理任何線程。
這是有關 Ktor 的更多背景信息。它得到了Jetbrains的支持,Jetbrains也是 Kotlin 本身的創造者。有誰比開發 Kotlin 的人更適合制作 Kotlin Web 框架?
buildscript {
ext.kotlin_version='1.7.10'
ext.ktor_version='2.0.3'
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'java'
apply plugin: 'kotlin'
group 'ktor-and-kodein-di'
version '1.0.0'
repositories {
mavenLocal()
mavenCentral()
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
testImplementation "junit:junit:4.12"
implementation "io.ktor:ktor-server-netty:$ktor_version"
// each plugin is its own dependency which matches the name in code (default-headers=DefaultHeaders)
implementation "io.ktor:ktor-serialization-jackson:$ktor_version"
implementation "io.ktor:ktor-server-default-headers:$ktor_version"
implementation "io.ktor:ktor-server-call-logging:$ktor_version"
implementation "io.ktor:ktor-server-content-negotiation:$ktor_version"
implementation group: 'org.kodein.di', name: 'kodein-di-generic-jvm', version: '6.5.1'
implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.2.3'
implementation group: 'com.datastax.oss', name: 'java-driver-core', version: '4.14.1'
}
這里正在發生一些事情。
擺脫了無聊的東西,我現在可以讓你完成一個 Web 服務器的實現。下面的代碼就是你所需要的:
kotlin
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
fun main() {
embeddedServer(Netty, port=8080, module=Application::module).start()
}
fun Application.module() {
// code that does stuff which is covered later
}
巴姆。你有它。使用 Ktor 和 Netty 運行的 Web 服務器。好的,是的,它并沒有真正做任何事情,但我們將在以下部分中對此進行擴展。
該代碼非常不言自明。唯一值得強調的是Application.module功能。該module參數embeddedServer需要Application.() -> Unit提供一個函數來配置服務器,并將成為服務器代碼的主要入口點。
在接下來的部分中,我們將擴展內容Application.module,以便您的 Web 服務器真正做一些有價值的事情。
所有傳入的請求都將被拒絕,因為沒有端點來處理它們。通過設置路由,您可以指定請求可以通過的有效路徑以及在請求到達目的地時將處理請求的函數。
這是在一個Routing塊(或多個Routing塊)內完成的。在塊內部,設置了到不同端點的路由:
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.call
import io.ktor.server.request.receive
import io.ktor.server.response.respond
import io.ktor.server.response.respondText
import io.ktor.server.routing.Routing
import io.ktor.server.routing.get
import io.ktor.server.routing.post
import io.ktor.server.routing.route
routing {
// All routes defined inside are prefixed with "/people"
route("/people") {
// Get a person
get("/{id}") {
val id=UUID.fromString(call.parameters["id"]!!)
personRepository.find(id)?.let {
call.respond(HttpStatusCode.OK, it)
} ?: call.respondText(status=HttpStatusCode.NotFound) { "There is no record with id: $id" }
}
// Create a person
post {
val person=call.receive<Person>()
val result=personRepository.save(person.copy(id=UUID.randomUUID()))
call.respond(result)
}
}
}
由于依賴于擴展函數,導入已包含在內,這使得在沒有 IDE 的情況下發現函數變得困難。
routing是一個方便的函數,可以讓代碼流暢。里面的上下文(又名this)routing是類型Routing。此外,函數route、get和post都是 的擴展函數Routing。
route設置其所有后續端點的基本路徑。在這種情況下,/people. get并且post不要自己指定路徑,因為基本路徑足以滿足他們的需求。如果需要,可以為每個路徑添加一個路徑,例如:
routing {
// Get a person
get("/people/{id}") {
val id=UUID.fromString(call.parameters["id"]!!)
personRepository.find(id)?.let {
call.respond(HttpStatusCode.OK, it)
} ?: call.respondText(status=HttpStatusCode.NotFound) { "There is no record with id: $id" }
}
// Create a person
post("/people) {
val person=call.receive<Person>()
val result=personRepository.save(person.copy(id=UUID.randomUUID()))
call.respond(result)
}
}
在繼續下一節之前,我想向您展示我是如何實際實現路由的:
fun Application.module() {
val personRepository by kodein.instance<PersonRepository>()
// Route requests to handler functions
routing { people(personRepository) }
}
// Extracted to a separate extension function to tidy up the code
fun Routing.people(personRepository: PersonRepository) {
route("/people") {
// Get a person
get("/{id}") {
val id=UUID.fromString(call.parameters["id"]!!)
personRepository.find(id)?.let {
call.respond(HttpStatusCode.OK, it)
} ?: call.respondText(status=HttpStatusCode.NotFound) { "There is no record with id: $id" }
}
// Create a person
post {
val person=call.receive<Person>()
val result=personRepository.save(person.copy(id=UUID.randomUUID()))
call.respond(result)
}
}
}
我將代碼提取到一個單獨的函數中以減少Application.module. 在嘗試編寫更重要的應用程序時,這將是一個好主意。我的方式是否是Ktor方式是另一個問題。快速瀏覽一下 Ktor 文檔,看起來這是一個不錯的解決方案。我相信我看到了另一種方法來做到這一點,但我需要花更多的時間來處理它。
將請求路由到請求處理程序時執行的代碼顯然非常重要。該功能畢竟需要做一些事情......
每個處理函數都在協程的上下文中執行。我并沒有真正使用這個事實,因為我展示的每個功能都是完全同步的。
在本文的其余部分,我將盡量不過多提及協程,因為它們對于這個簡單的 REST API 并不是特別重要。
在本節中,get將更仔細地檢查該函數:
get("/{id}") {
val id=UUID.fromString(call.parameters["id"]!!)
personRepository.find(id)?.let {
call.respond(HttpStatusCode.OK, it)
} ?: call.respondText(status=HttpStatusCode.NotFound) { "There is no record with id: $id" }
}
{id}表示請求中需要路徑變量,其值將存儲為id. 可以包含多個路徑變量,但本示例只需要一個。該值id是從 中檢索的call.parameters,它采用您要訪問的變量的名稱。
id數據庫使用路徑變量搜索相應的記錄 。在這種情況下,如果存在,則記錄與相應的200 OK. 如果不是,則返回錯誤響應。兩者都respond改變respondText?了response當前的基礎call。您可以手動執行此操作,例如,使用:
call.response.status(HttpStatusCode.OK)
call.response.pipeline.execute(call, it)
你可以這樣做,但沒有任何必要,因為這實際上只是respond. respondText有一些額外的邏輯,但委托response給最終確定一切。此函數中的最終調用 execute表示函數的返回值。
在 Ktor 中,可以在需要時安裝插件。例如,可以添加Jackson JSON 解析以從應用程序處理和返回 JSON。
以下是安裝到示例應用程序的插件:
import io.ktor.http.HttpHeaders
import io.ktor.serialization.jackson.jackson
import io.ktor.server.application.install
import io.ktor.server.plugins.callloging.CallLogging
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
import io.ktor.server.plugins.defaultheaders.DefaultHeaders
import org.slf4j.event.Level
fun Application.module() {
// Adds header to every response
install(DefaultHeaders) { header(HttpHeaders.Server, "My ktor server") }
// Controls what level the call logging is logged to
install(CallLogging) { level=Level.INFO }
// Setup jackson json serialisation
install(ContentNegotiation) { jackson() }
}
INFO ktor.application.log - 200 OK: GET - /people/302a1a73-173b-491c-b306-4d95387a8e36
對于 Ktor 包含的其他插件的列表,您可以轉到start.ktor.io,您可以在其中查看現有插件(通過假裝創建新應用程序)。
安裝插件一直與之前完成的路由聯系在一起。routing委托到install其實現內部。所以你可以寫:
install(Routing) {
route("/people") {
get {
// Implementation
}
}
}
無論你的船漂浮什么,但我會堅持使用routing. 希望這可以幫助您了解幕后發生的事情,即使只是一點點。
我想簡要介紹一下Kodein,因為我在這篇文章中使用了它。Kodein 是一個用 Kotlin 編寫的依賴注入框架,適用于 Kotlin。下面是我用于示例應用程序的超少量 DI:
科特林
val kodein=Kodein {
bind<CqlSession>() with singleton { cassandraSession() }
bind<PersonRepository>() with singleton { PersonRepository(instance()) }
}
val personRepository by kodein.instance<PersonRepository>()
在Kodein塊內,創建了應用程序類的實例。在這種情況下,每個類只需要一個實例。呼召singleton表明了這一點。instance是 Kodein 提供的用于傳遞給構造函數而不是實際對象的占位符嗎?
在塊之外,檢索Kodein一個實例。PersonRespository
是的,我知道; 在這里使用 Kodein 沒有多大意義,因為我可以用一行代碼替換它……
val personRepository=PersonRepository ( cassandraSession ())
相反,讓我們認為這是一個非常簡潔的例子來理解。
在這篇文章中,我們研究了使用 Ktor 初始化 Web 服務器,將請求路由到生成響應的 lambdas/handlers,以及將插件安裝到服務器。在這篇文章中,我們主要停留在表面,專注于基礎知識,讓您開始使用 Ktor。有關更多信息,值得前往ktor.io并查看 Ktor 的文檔和示例。
約風公寓|鄧林林
家和居住者之間,確實存在著一種難以言喻卻又緊密相連的紐帶,這種關系微妙而深刻,仿佛每一寸空間、每一件家具都在訴說著居住者的故事,蘊藏著他們生活的點點滴滴與獨特印記。
大家好,我是《意大利室內設計中文版+》的主理人意公子,專為設計師分享室內設計創新案例。我們致力于為設計師提供多元的設計美學,也讓世界看到我們的設計實力。
讓我們攜手踏入這座簡約風格的私宅,這是一處不僅融合了現代設計美學,更滿載著居住者深情故事與溫馨回憶的避風港。
設計師選擇以“安靜”為核心設計理念,旨在打造一個能讓居住者徹底放松、享受寧靜時光的居家環境。這種設計不僅是對外界喧囂的隔絕,更是對內心平靜的追求。
The designer chose "quiet" as the core design concept to create a home environment where residents can completely relax and enjoy a quiet time. This design is not only an isolation from the hustle and bustle of the outside world, but also a pursuit of inner peace.
“一家一人”的哲學理念,在設計中體現為對居住者個人情感的尊重與呵護。設計師通過精細的布局與選材,讓家成為居住者精神世界的延伸,賦予生活以全新的意義和價值。
The philosophy of "one family, one person" is reflected in the design as respect and care for the personal feelings of the occupants. Through the fine layout and material selection, the designer makes the home an extension of the spiritual world of the occupants, giving life a new meaning and value.
在確保結構安全的前提下,設計師大膽拆除了室內的隔斷墻,使原本分隔的空間得以自由流通,形成了一體化的開闊視野。這種布局不僅增強了空間的通透性和連貫性,還促進了家庭成員之間的交流與互動。
On the premise of ensuring the safety of the structure, the designer boldly removed the partition wall in the interior, so that the originally separated space could flow freely and form an integrated open vision. This layout not only enhances the transparency and coherence of the space, but also promotes communication and interaction between family members.
深木色的地板,經過特殊處理呈現出自然的做舊效果,每一道痕跡都仿佛在訴說著歲月的故事。這種材質的選擇不僅增加了空間的質感與層次感,還讓人感受到一種沉穩與寧靜的氣息。
The dark wood-colored flooring has been specially treated to give a natural aged effect, and every trace seems to tell the story of the years. This choice of material not only adds texture and layering to the space, but also makes people feel a sense of calm and tranquility.
客廳作為家庭活動的核心區域,設計師在保持簡約風格的同時,也注重了家具的實用性與美觀性。每一件家具都經過精心挑選與搭配,既符合人體工程學原理又兼具藝術美感。
As the core area of family activities, the living room is the designer's focus on the practicality and aesthetics of the furniture while maintaining a simple style. Each piece of furniture has been carefully selected and matched to be both ergonomic and artistic.
客廳區域還巧妙地利用了墻面壁龕和矮柜等收納空間來減少雜物堆積保持空間整潔有序。
The living room area also makes clever use of storage spaces such as wall alcoves and low cabinets to reduce clutter accumulation and keep the space tidy and organized.
餐廚廳位于客廳的另一側通過巧妙的夾角設計實現了空間的有效分隔。這種布局既保證了餐廚區域的獨立性又避免了視線上的直接沖突保持了整體的和諧質感。
The dining and kitchen room is located on the other side of the living room, and the space is effectively divided through a clever angle design. This layout not only ensures the independence of the kitchen area, but also avoids direct conflict in sight, and maintains the overall harmonious texture.
在臥室的設計上設計師更加注重居住者的私密性和舒適度。臥室空間減少了不必要的裝飾元素轉而更專注于設計感的營造和實用功能的實現。
In the design of the bedroom, the designer pays more attention to the privacy and comfort of the occupants. The bedroom space reduces unnecessary decorative elements and focuses more on the creation of a sense of design and the realization of practical functions.
簡約的設計哲學不僅體現在空間的布局和家具的選擇上更滲透在居住者的生活方式和心態中。
The minimalist design philosophy is not only reflected in the layout of the space and the choice of furniture, but also permeates the lifestyle and mentality of the occupants.
設計師通過留白的手法為生活留下了足夠的喘息空間讓居住者能夠在繁忙的生活中找到一片寧靜的避風港。同時這種簡約而不簡單的設計風格也體現了居住者對生活的熱愛和追求在平淡中詮釋著幸福的真諦。
The designer leaves enough breathing space for life through the use of white space, so that residents can find a peaceful haven in their busy lives. At the same time, this simple but not simple design style also reflects the love and pursuit of life of the residents, and interprets the true meaning of happiness in the ordinary.
這套私宅以其簡約而不失格調的設計風格贏得了居住者的喜愛和贊譽。整個空間充滿了溫馨和諧的氛圍讓人感受到家的溫暖和幸福。
This private home has won the love and praise of its occupants for its simple yet stylish design. The whole space is filled with a warm and harmonious atmosphere, making people feel the warmth and happiness of home.
、PHP環境搭建的前提是 Apache HTTP Server (Apache 服務器)已經安裝部署成功,并可以正常訪問到服務器的主頁面。Apache HTTP Server 的安裝部署已經在上一篇講解的很詳細了,不清楚的可以點擊“ Apache HTTP Servcer-Apache服務器下載與Windows系統下安裝”查看具體操作。
2、PHP下載:
2.1、下載地址:http://php.net/downloads.php
2.1、版本選擇:如果是與 Apache 搭配,建議選擇 Thread Safe 版本;如果是與 CGI 或者 FAST-CGI 搭配,建議選擇 Non Thread Safe 版本。
3、PHP環境搭建:
3.1、將下載的 .zip 壓縮包解壓到指定的安裝目錄,此處安裝路徑為:D:\solt\php_5.6.33。
3.2、將 PHP 的根目錄下的 php.ini-development 或者 php.ini-production復制一份并改名為 php.ini,作為PHP的配置文件;
3.3、打開php.ini,修改配置信息:
說明:a、ini文件的注釋是分號(英文分號),所以取消注釋就刪除分號;
b、${phphome}是PHP的根目錄,即:D:\solt\php_5.6.33,配置文件中寫成絕對路徑。
3.3.1、修改擴展文件的路徑:
; extension_dir="ext"
取消注釋,或者改為:
extension_dir="${phphome}\ext";
注意:如果是與 Apache 搭配,建議將擴展文件路徑改為絕對路徑,因為有可能加載不了。
3.3.2、修改需要加載的擴展文件,下面代碼是取消部分擴展程序的注釋之后的代碼:
extension=php_bz2.dll
extension=php_curl.dll
extension=php_fileinfo.dll
extension=php_gd2.dll
extension=php_gettext.dll
;extension=php_gmp.dll
;extension=php_intl.dll
;extension=php_imap.dll
;extension=php_interbase.dll
;extension=php_ldap.dll
extension=php_mbstring.dll
extension=php_exif.dll ; Must be after mbstring as it depends on it
extension=php_mysql.dll
extension=php_mysqli.dll
;extension=php_oci8_12c.dll ; Use with Oracle Database 12c Instant Client
extension=php_openssl.dll
;extension=php_pdo_firebird.dll
extension=php_pdo_mysql.dll
;extension=php_pdo_oci.dll
extension=php_pdo_odbc.dll
extension=php_pdo_pgsql.dll
extension=php_pdo_sqlite.dll
extension=php_pgsql.dll
;extension=php_shmop.dll
; The MIBS data available in the PHP distribution must be installed.
; See http://www.php.net/manual/en/snmp.installation.php
;extension=php_snmp.dll
extension=php_soap.dll
extension=php_sockets.dll
extension=php_sqlite3.dll
;extension=php_sybase_ct.dll
extension=php_tidy.dll
extension=php_xmlrpc.dll
extension=php_xsl.dll
3.3.3、設置默認的時區:
[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone 選擇時區列表網址
date.timezone=Asia/Shanghai
3.3.4、設置 ssl :
[openssl]
; The location of a Certificate Authority (CA) file on the local filesystem
; to use when verifying the identity of SSL/TLS peers. Most users should
; not specify a value for this directive as PHP will attempt to use the
; OS-managed cert stores in its absence. If specified, this value may still
; be overridden on a per-stream basis via the "cafile" SSL stream context
; option.
openssl.cafile=cacert.pem
根據需求可以自己添加擴展。
3.4、修改 Apache24\conf\ 目錄下的 httpd.conf 配置 Apache ,讓 Apache 和 PHP 協同工作;
3.4.1、DocumentRoot 設置:
修改前:默認的是 Apache24 下的 htdocs 目錄:
修改后:指定到自定義的路徑,但是要記住這個路徑。
3.4.2、修改默認的索引,以支持 PHP :
修改前:
# DirectoryIndex: sets the file that Apache will serve if a directory
# is requested.
#
<IfModule dir_module>
DirectoryIndex index.html
</IfModule>
修改后:
# DirectoryIndex: sets the file that Apache will serve if a directory
# is requested.
#
<IfModule dir_module>
DirectoryIndex index.html index.php index.htm
</IfModule>
3.4.3、開啟 rewrite 功能:將下面這行代碼前面的 # 去掉:
LoadModule rewrite_module modules/mod_rewrite.so
3.4.4、加載 PHP 模塊,注意絕對路徑:
如果是 PHP 5,在 httpd.conf 文件最后添加如下代碼:
#php5.6
LoadModule php5_module D:/soft/php-5.6.33/php5apache2_4.dll
<IfModule php5_module>
PHPIniDir "D:/soft/php-5.6.33/"
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps
</IfModule>
如果是 PHP 7,則相應的更改,示例如下:
#php7
LoadModule php7_module D:/soft/php-7.x.x/php7apache2_4.dll
<IfModule php7_module>
PHPIniDir "D:/soft/php-7.x.x/"
AddType application/x-httpd-php .php
AddType application/x-httpd-php-source .phps
</IfModule>
3.5、如果安裝的PHP x64位版本,Apache也需要是x64位版本的。然后還要將php目錄下的libeay32.dll、ssleay32.dll、libssh2.dll以及ext目錄下的php_curl.dll等四個文件,都復制放到System32目錄下。否則curl擴展無法使用。參考鏈接:http://my.oschina.net/lsfop/blog/496181 。未做驗證,只是照做,正常顯示。
4、Apache + PHP 啟動運行測試:
4.1、在 D:\soft\php_5.6.33\www 目錄下,創建 index.php 文件,文本內容如下:
<?php
echo phpinfo();
?>
4.2、重啟 Apache 服務,打開瀏覽地址欄輸入: localhost:8081/index.php 或者 127.0.0.1:8081/index.php ,就可以打開 PHP 頁面。
最后說明一點兒,PHP 環境搭建可以借助于 PHP 開發環境搭建工具,下載地址:http://www.php.cn/xiazai/gongju或者http://www.wampserver.com/,在此處就不介紹工具安裝方法了。
原文:https://blog.csdn.net/weixin_39082031/article/details/79110311
相關內容:https://study.163.com/course/courseMain.htm?courseId=1210406206&share=2&shareId=480000002227524
*請認真填寫需求信息,我們會在24小時內與您取得聯系。