当前位置: 首页 > news >正文

公益平台网站怎么做经典重庆论坛新闻论坛发展论坛

公益平台网站怎么做,经典重庆论坛新闻论坛发展论坛,ftp网站后台,看网站的浏览器首发于Enaium的个人博客 前言 本文将介绍如何使用 Kotlin 全栈技术栈KtorKotlin/JS来构建一个简单的全栈应用。 准备工作 创建项目 首先我们需要创建一个Kotlin项目#xff0c;之后继续在其中新建两个子项目#xff0c;一个是Kotlin/JS项目#xff0c;另一个是Ktor项目。…首发于Enaium的个人博客 前言 本文将介绍如何使用 Kotlin 全栈技术栈KtorKotlin/JS来构建一个简单的全栈应用。 准备工作 创建项目 首先我们需要创建一个Kotlin项目之后继续在其中新建两个子项目一个是Kotlin/JS项目另一个是Ktor项目。 添加依赖和插件 这里我使用了Gradle的catalog在项目中的gradle目录下创建一个libs.versions.toml文件用于管理项目中的依赖版本。 [versions] jimmer 0.0.9 kotlin 1.9.23 ktor 2.3.9 ksp 1.9.23-1.0.20 coroutines 1.8.0 serialization 1.6.3 wrappers 1.0.0-pre.729 logback 1.5.3 postgresql 42.7.3 hikari 5.1.0 koin 3.5.6[libraries] ktor-server-core { module io.ktor:ktor-server-core-jvm, version.ref ktor } ktor-server-netty { module io.ktor:ktor-server-netty-jvm, version.ref ktor } ktor-server-cors { module io.ktor:ktor-server-cors, version.ref ktor } ktor-server-content-negotiation { module io.ktor:ktor-server-content-negotiation, version.ref ktor } ktor-serialization-jsackson { module io.ktor:ktor-serialization-jackson, version.ref ktor } ktor-server-config-yaml { module io.ktor:ktor-server-config-yaml, version.ref ktor } logback { module ch.qos.logback:logback-classic, version.ref logback } kotlinx-coroutines-core { module org.jetbrains.kotlinx:kotlinx-coroutines-core, version.ref coroutines } kotlinx-serialization-json { module org.jetbrains.kotlinx:kotlinx-serialization-json, version.ref serialization } kotlin-wrappers { module org.jetbrains.kotlin-wrappers:kotlin-wrappers-bom, version.ref wrappers } kotlin-wrappers-react { module org.jetbrains.kotlin-wrappers:kotlin-react } kotlin-wrappers-react-dom { module org.jetbrains.kotlin-wrappers:kotlin-react-dom } kotlin-wrappers-emotion { module org.jetbrains.kotlin-wrappers:kotlin-emotion } postgresql { module org.postgresql:postgresql, version.ref postgresql } hikari { module com.zaxxer:HikariCP, version.ref hikari } koin { module io.insert-koin:koin-ktor, version.ref koin }[bundles] api [ktor-server-core, ktor-server-netty, ktor-server-cors, ktor-server-content-negotiation, ktor-serialization-jsackson, ktor-server-config-yaml, logback, postgresql, hikari, koin] app [kotlinx-coroutines-core, kotlinx-serialization-json, kotlin-wrappers-react, kotlin-wrappers-react-dom, kotlin-wrappers-emotion][plugins] jimmer { id cn.enaium.jimmer.gradle, version.ref jimmer } kotlin-jvm { id org.jetbrains.kotlin.jvm, version.ref kotlin } kotlin-multiplatform { id org.jetbrains.kotlin.multiplatform, version.ref kotlin } ktor { id io.ktor.plugin, version.ref ktor } ksp { id com.google.devtools.ksp, version.ref ksp } kotlin-plugin-serialization { id org.jetbrains.kotlin.plugin.serialization, version.ref kotlin }之后我们分别在前端和后端项目中的build.gradle.kts文件中引入这些依赖和插件。 后端 plugins {alias(libs.plugins.kotlin.jvm)alias(libs.plugins.ktor)alias(libs.plugins.ksp)alias(libs.plugins.jimmer)application }group cn.enaium version 1.0.0application {mainClass cn.enaium.TodoKtapplicationDefaultJvmArgs listOf(-Dio.ktor.development${extra[development] ?: false}) }dependencies {implementation(libs.bundles.api) }这里有一个配置添加到gradle.properties文件中。 developmenttrue前端 plugins {alias(libs.plugins.kotlin.multiplatform)alias(libs.plugins.kotlin.plugin.serialization) }kotlin {js {browser {commonWebpackConfig {cssSupport {enabled.set(true)}}}binaries.executable()}sourceSets {val jsMain by getting {dependencies {implementation(project.dependencies.enforcedPlatform(libs.kotlin.wrappers))implementation(libs.bundles.app)}}} }这里需要将前端项目的src/main改为src/jsMain。 最后进入到根项目的settings.gradle.kts文件中添加以下代码。 pluginManagement {repositories {maven(https://maven.pkg.jetbrains.space/public/p/compose/dev)google()gradlePluginPortal()mavenCentral()} }dependencyResolutionManagement {repositories {google()mavenCentral()maven(https://maven.pkg.jetbrains.space/public/p/compose/dev)} }还有gradle.build.kts文件中只保留以下代码。 plugins {alias(libs.plugins.kotlin.jvm) apply falsealias(libs.plugins.kotlin.multiplatform) apply false }好了现在我们的项目已经准备好了。 编写代码 后端 首先创建配置文件src/main/resources/application.yml。 ktor:deployment:port: 8080application:modules:- cn.enaium.TodoKt.module jdbc:driver: org.postgresql.Driverurl: jdbc:postgresql://localhost:5432/postgres?currentSchematodousername: postgrespassword: postgres之后创建logback配置文件src/main/resources/logback.xml。 configurationappender nameSTDOUT classch.qos.logback.core.ConsoleAppenderencoderpattern%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n/pattern/encoder/appenderroot leveltraceappender-ref refSTDOUT//rootlogger nameorg.eclipse.jetty levelINFO/logger nameio.netty levelINFO/ /configuration还有创建数据库。 drop schema if exists todo cascade; create schema todo;drop table if exists todo.task; create table todo.task (id uuid primary key,name text not null,start_time timestamp default now(),end_time timestamp )之后创建一个主类cn.enaium.Todo。 fun main(args: ArrayString) EngineMain.main(args)之后编写一个扩展函数cn.enaium.Todo.module。 fun Application.module() {}安装一些插件 Koin install(Koin) {modules(module {singleApplicationEnvironment { environment }}) }CORS install(CORS) {allowMethod(HttpMethod.Options)allowMethod(HttpMethod.Post)allowMethod(HttpMethod.Get)allowHeader(HttpHeaders.AccessControlAllowOrigin)allowHeader(HttpHeaders.ContentType)anyHost() }Jackson install(ContentNegotiation) {jackson {registerModules(ImmutableModule())} }Jimmer 接下来配置一下Jimmer。 fun sql(environment: ApplicationEnvironment): KSqlClient {return newKSqlClient {setConnectionManager {HikariPool(HikariConfig().apply {driverClassName environment.config.property(jdbc.driver).getString()jdbcUrl environment.config.property(jdbc.url).getString()username environment.config.property(jdbc.username).getString()password environment.config.property(jdbc.password).getString()maximumPoolSize 10connectionTimeout 30000}).connection.use {proceed(it)}}setDialect(PostgresDialect())} }之后添加到Koin中。 singleKSqlClient { sql(get()) }编写一个Task实体类。 package cn.enaium.entityimport org.babyfish.jimmer.sql.Entity import org.babyfish.jimmer.sql.GeneratedValue import org.babyfish.jimmer.sql.Id import org.babyfish.jimmer.sql.Table import org.babyfish.jimmer.sql.meta.UUIDIdGenerator import java.util.*/*** author Enaium*/ Entity Table(name task) interface Task {IdGeneratedValue(generatorType UUIDIdGenerator::class)val id: UUIDval name: Stringval startTime: Dateval endTime: Date? }接下来就可以编写Service了。 package cn.enaium.serviceimport cn.enaium.entity.Task import cn.enaium.entity.endTime import cn.enaium.entity.startTime import org.babyfish.jimmer.sql.kt.KSqlClient import org.babyfish.jimmer.sql.kt.ast.expression.isNotNull/*** author Enaium*/ class TodoServe(private val sql: KSqlClient) {fun getTasks(): ListTask {return sql.createQuery(Task::class) {orderBy(table.endTime.isNotNull(), table.startTime)select(table)}.execute()}fun saveTask(task: Task) {sql.save(task)} }这里我们添加两个方法getTasks和saveTaskgetTasks用于获取所有任务并按照创建时间和是否完成排序saveTask用于保存任务之后还是添加到Koin中。 singleTodoServe { TodoServe(get()) }之后我们在module添加路由。 val todoServe by injectTodoServe()routing {get(/task) {call.respond(todoServe.getTasks())}post(/task) {todoServe.saveTask(call.receive())call.response.status(HttpStatusCode.OK)} }前端 首先在src/jsMain/resources/index.html中添加以下代码这里需要注意的是app.js这个文件名称需要和前端的项目名称一致。 !doctype html html langen headmeta charsetUTF-8titleHello, Kotlin/JS!/title /head body div idroot/div script srcapp.js/script /body /html之后写一个main函数。 import react.dom.client.createRoot import web.dom.document/*** author Enaium*/ fun main() {val container document.getElementById(root) ?: error(Couldnt find root container!)createRoot(container).render(App.create()) }val App FC {}然后就可以编写组件了。 首先需要创建两个data类一个是Task另一个是TaskInputTask用于展示任务TaskInput用于请求。 Serializable data class Task(val id: String, var name: String, val startTime: Long, val endTime: Long?) {fun copy(name: String this.name, startTime: Long this.startTime, endTime: Long? this.endTime) Task(id, name, startTime, endTime)fun toInput() TaskInput(id, name, startTime, endTime) }Serializable data class TaskInput(val id: String? null,val name: String? null,val startTime: Long? null,val endTime: Long? null )之后编写请求函数使用fetch发送请求。 val coroutine CoroutineScope(window.asCoroutineDispatcher())suspend fun fetchTasks(): ListTask {window.fetch(http://localhost:8080/task).await().let {if (it.status ! 200.toShort()) {throw Exception(Failed to fetch)}return Json.decodeFromDynamicListTask(it.json().await())} }suspend fun saveTask(task: TaskInput) {window.fetch(http://localhost:8080/task,RequestInit(method POST,body Json.encodeToString(TaskInput.serializer(), task),headers json(Content-Type to application/json))).await().let {if (it.status ! 200.toShort()) {throw Exception(Failed to save)}} }TaskItem 编写一个TaskItem组件用于展示任务编辑任务完成任务逻辑就是点击Edit按钮可以编辑任务按Enter保存按Escape取消点击Finish按钮完成任务。 external interface TaskItemProps : Props {var task: Task }val TaskItem FCTaskItemProps { props -var editState by useState(false)var taskState by useStateTaskInput()useEffect(listOf(taskState)) {taskState?.let {coroutine.launch {saveTask(it)window.location.reload()}}}div {if (editState) {input {defaultValue props.task.nameonKeyUp {if (it.asDynamic().key Enter) {taskState props.task.copy(name it.target.asDynamic().value as String).toInput()editState false}if (it.asDynamic().key Escape) {editState false}}}} else {div {css {color if (props.task.endTime null) Color(red) else Color(green)}div {props.task.id}div {props.task.name}div {kotlin.js.Date(props.task.startTime).toLocaleString()props.task.endTime?.let { - kotlin.js.Date(it).toLocaleString()}}}button {EditonClick {editState !editState}}button {FinishonClick {taskState props.task.copy(endTime Date().getTime().toLong()).toInput()}}}} }App 最后编写App组件获取任务列表添加任务。 val App FC {var tasksState by useState(emptyListTask())var taskState by useStateTaskInput()useEffectOnce {coroutine.launch {tasksState fetchTasks()}}useEffect(listOf(taskState)) {taskState?.let {coroutine.launch {saveTask(it)window.location.reload()}}}div {input {css {fontSize 24.px}onKeyUp {if (it.asDynamic().key Enter) {taskState TaskInput(name it.target.asDynamic().value as String)}}}div {css {marginTop 10.pxdisplay Display.flexflexDirection FlexDirection.columngap 10.px}tasksState.forEach {TaskItem {key it.idtask it}}}} }运行 前端和后端默认端口都是8080所以先运行后端之后运行前端。 后端使用application插件的run任务前端使用jsBrowserDevelopmentRun任务。
http://www.hkea.cn/news/14459812/

相关文章:

  • 用别人的电影网站做公众号wordpress字菜单
  • 陇南做网站企业门户管理系统
  • 做系统之前的网站徐州网络建站模板
  • 北京网站优化外包个人简历wps模板免费
  • 成都交易网站建设企业网站建设 阿里云
  • 百度服务器建设自己的网站建设行政主管部门相关网站
  • 重庆网站建设的培训机构深圳建筑网站建设
  • 广州中医药资源门户网站虚拟搭建wordpress
  • 品牌网站建设价格实惠网页设计与网站建设课程
  • 网站建设与管理 教材网站推广的好处
  • 谷歌推广网站教育网站如何做seo
  • 自己做网站前期困难吗网页版微信传文件
  • 公司网站SEO优化哪个做得好在百度上做网站找谁
  • 汕头制作网站腾讯邮箱注册入口官网
  • 昌乐建设局网站中国知名品牌
  • 怎么注册企业网站域名青岛鑫隆建设集团网站
  • 建筑类企业网站模板天津室内设计培训
  • 一个网站开发流程图建设网站用模版
  • 网站颜色编号盐城网站建设咨询
  • 猫眼网站建设饿了么网站怎么做的
  • 重庆论坛网站建设如何申请一个网站 新网
  • 怎么使用织梦做下载网站学生做网站的软件
  • 石家庄网站开发与优化艺术网站欣赏
  • 网站管理维护怎么做wordpress 4.9.9
  • 网站设计收费明细表个人网站 备案备注
  • 网站接入查询工业设计效果图
  • 菜鸟式网站建设图书重庆智能建站模板
  • 东莞企业网站推广运营wordpress装饰模板排名
  • 前端转网站建设字体设计素材网
  • 如何查询网站点击量公司文化墙设计模板