返回文章列表文章索引阅读全文
STARBLOG / 阅读手记
Kotlin

Developing RESTful APIs with Kotlin and Spring Boot (Part 2): Custom Configuration, CORS, Pagination, and ViewModel

Preface Please see the previous article here: https://zhuanlan.zhihu.com/p/146733027 The previous article covered the development process of using Kotlin with Spring Boot, from project setup, ORM, and Controller to Swagger integration and Docker deployment. However, a master said that article had too much code and too little rambling, so I decided to ramble out another one, introducing several common operations in web development. After finishing this simple system, Kotlin with Spr

曦远 (DealiAxy)约 18 分钟
目录7 个章节

Preface

Please see the previous article here: https://zhuanlan.zhihu.com/p/146733027

The previous article covered the development process of using Kotlin with Spring Boot, from project setup, ORM, and Controller to Swagger integration and Docker deployment. However, a master said that article had too much code and too little rambling, so I decided to ramble out another one, introducing several common operations in web development.

After finishing this simple system, my feeling about Kotlin with Spring Boot is that it's pretty great. Spring Boot itself is a foolproof solution: whatever feature you need, just gradle it down and register it, feeling awesome, and that's that. The only downside is that all of this can only be realized under Java, that garbage language. Every time I use Java I get this feeling of eating *, especially disgusting.

Writing a simple data class requires me to pair every field with those damn get and set methods. I don't know which brilliant big shot invented this. Seeing this, some folks might say you can use Lombok to auto-generate get and set methods. I laughed. Anyone who's been burned knows.

As for null, generics, value types vs reference types, and all that messy stinky ** crap, I won't say much more.

PS: Java fans, don't flame me. The above is just my personal feeling. Languages are just tools for making money. As long as the pay is enough, I'd even use Easy Language, no problem (flees~

Alright, time to get to the main topic.

Custom Configuration

There are two kinds of custom configuration: put it in application.yml, or in a custom file. I don't have much configuration here, so putting it in application.yml is fine.

My configuration:

onecat:
  pageSize: 10

Then define a class in the configuration package:

import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.stereotype.Component

@Component
@ConfigurationProperties("onecat")
object OneCatConfig {
    @Value("\${onecat.pageSize}")
    var pageSize: Int = 10
}

A class defined with the object keyword is a static class, so it can be called directly elsewhere:

OneCatConfig.pageSize

That's all there is to it.

CORS

CORS is a well-worn topic in web development. There are many solutions; I just pick the simplest one: run it through a filter, add a header to each response, easy peasy.

Create a new filter in the filter package:

@WebFilter(filterName = "CorsFilter")
@Configuration
class CorsFilter : Filter {
    override fun doFilter(req: ServletRequest?, res: ServletResponse?, chain: FilterChain?) {
        val response = res as HttpServletResponse
        response.setHeader("Access-Control-Allow-Origin", "*")
        response.setHeader("Access-Control-Allow-Credentials", "true")
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT")
        response.setHeader("Access-Control-Max-Age", "3600")
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
        chain!!.doFilter(req, res)
    }
}

That's all there is to it as well. Spring Boot auto-configuration is really convenient.

Pagination

Next I'll introduce pagination. I believe there must be many pagination components in the Spring Boot ecosystem, but I didn't use them. If you can implement it yourself, don't use a third-party component~

First I defined a Page class in ViewModels, with the following code:

data class Page<T>(
        val page: Int,
        val pageSize: Int,
        val count: Int,
        val totalPages: Int = if (count % pageSize == 0) count / pageSize else count / pageSize + 1,
        val currentList: List<T>
)

Then I used Ktorm's sequence operations, which have the drop and take methods; mapped to a SQL statement, that's a limit operation.

The code is as follows:

@ApiOperation("获取用户列表")
@GetMapping("/")
fun list(@RequestParam("page") page: Int): Response<Page<User>> {
    val users = database.sequenceOf(UserDao)
            .drop((page - 1) * OneCatConfig.pageSize).take(OneCatConfig.pageSize)
    return Response(true, "获取用户列表",
            Page(page, OneCatConfig.pageSize, users.totalRecords, currentList = users.toList()))
}

That's it. Also very simple to implement.

Let me roast Ktorm's author here—too much of a trap. The pagination operations in the example code he provided on GitHub are wrong. I was misled at first, then later changed the code myself and filled in the holes in the original author's code = = Really tough.

ViewModel

Actually, I already used a ViewModel when introducing pagination just now, but Page is just a plain data class. Here with the ViewModel I need to perform further operations on the incoming data.

For example, the following code counts the number of equipment items and available equipment under each type.

class EquipmentGroupViewModel(
        private val database: Database,
        val group: EquipmentGroup
) {
    var total: Int
    var available: Int

    init {
        val queryset = database.sequenceOf(EquipmentDao).filter { it.equipmentGroup eq group.id }
        total = queryset.totalRecords
        available = 0
        for (equipment in queryset) {
            if (equipment.rentStatus == 1 && equipment.damageStatus == 1)
                available++
        }
    }
}

That's OK. Passed on the first test. Kotlin being easy to use, that's that.

Summary

Spring Boot is pretty nice, and Kotlin as a language is quite usable too. It just still feels a bit short compared to C#. The JVM limits what it can do, but it's also thanks to the JVM ecosystem that Kotlin could rise—after all, it can interop with Java seamlessly. You all know that experience. Maybe future Java projects can all gradually switch to Kotlin (not really).

It's just that Ktorm gave me a somewhat not-so-great experience—little pitfalls. When it comes to ORMs, Django ORM is first, EF Core is second. Being able to auto-migrate is really convenient. You like the flexibility of writing SQL yourself; I like the convenience of direct mapping. To each their own.

Language wars are meaningless. Programming for the paycheck is what's real. Some people think Java web development pays well, so they eagerly bounce off to learn Java—nothing wrong with that. Some people like .NET Core's 965 and a full head of hair; that's also a pursuit. As for using scripting languages like Python and Rails on Ruby for web development, that's even more excellent: finish the project, get the money, and bounce (I'm talking nonsense hahaha, guess why I like Python so much?)

Welcome to Discuss

I've compiled a series of technical articles and materials. Reply with linux, flutter, c#, netcore, android, java, python, etc. in the backend of the WeChat official account "Programming Lab" to get related technical articles and materials. You can also leave a message in the official account backend if you have any questions~

_EOF_

Developing RESTful APIs with Kotlin and Spring Boot (Part 2): Custom Configuration, CORS, Pagination, and ViewModel

本文作者:
程序设计实验室
版权声明:
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…