приложение Spring в kotlin ведет себя странно - PullRequest
1 голос
/ 05 мая 2020

Я совершенно новичок в Spring + Kotlin и пытаюсь написать простой сервер. Я пытаюсь написать исполняемый пример кода одного сервера приложений, получающего запрос от клиента и отправляющего запрос другому серверу, который вернет результат, а сервер приложений вернет этот результат клиенту.

Я привязал сервер к localhost: 9000, и когда я отправляю запрос на localhost:9000/music?user=whatever, я сначала получил результат, который ожидал, как показано ниже.

[
    "Music(Genre=Rock, Mood=[Joyful, Depressed])"
]

Однако, отправив тот же запрос снова (используя почтальон) , Я получил [] в качестве возврата. Я не могу понять этого поведения, так как ожидаю, что каждый раз, когда я отправляю запрос, будет возвращаться один и тот же результат. Примеры входных данных жестко запрограммированы в коде контроллера в виде переменной с именем sampleList. Я стремлюсь изменить эту часть, получив эту переменную как тело запроса от клиента после того, как я решу эту проблему.

Может ли кто-нибудь объяснить, почему проявляется это неожиданное поведение? Заранее большое спасибо. Коды показаны ниже.

package org.whatever

import org.springframework.web.bind.annotation.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response

@RestController
class MusicController {

    @GetMapping("/music")
    fun retrieveMusicInfo(@RequestParam(value = "user") user: String): MutableList<String> {
        val valList = mutableListOf<String>()

        val sampleList: List<Int> = listOf(1, 2, 3, 4)
        val sampleAmplitudes = Amplitudes(sampleList)
        MusicService.create()?.genreMoodRequest(sampleAmplitudes).enqueue(object : Callback<Music> {
            override fun onFailure(call: Call<Music>, t: Throwable) { // Whatever }
            override fun onResponse(call: Call<Music>, response: Response<Music>?) {
                val data = response?.body()?.toString()
                data?.let { valList.add(it) }
            }
        })
        return valList
    }
}

Сервисный журнал c, как показано ниже.

package org.whatever

import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.Body
import retrofit2.http.Headers
import retrofit2.http.POST

interface MusicService {
    @Headers("accept: application/json",
            "content-type: application/json")
    @POST("/")
    fun genreMoodRequest(@Body params: Amplitudes)
        : Call<Music>

    companion object {
        fun create(): MusicService {
            val retrofit = Retrofit.Builder()
                    .baseUrl("http://localhost:5000")
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()

            return retrofit.create(MusicService::class.java)
        }
    }
}

1 Ответ

2 голосов
/ 05 мая 2020

Проблема

Retrofit enqueue() работает асинхронно. поэтому он не блокирует поток Spring, обрабатывающий запрос.

В результате поток для запроса может быть выполнен до того, как он получит ответ от модифицированного клиента.

решения

1) используйте пружину RestTemplate вместо Retrofit

2) используйте Retrofit с API блокировки (не enqueue())

...