Merge pull request #13 from TouchInstinct/version-spring-web
add version-spring-web
This commit is contained in:
commit
8a4c5158ff
|
|
@ -79,3 +79,7 @@ Interceptor для логирования запросов/ответов.
|
|||
## exception-handler-logger-spring-web
|
||||
|
||||
Добавляет логирование в обработку ошибок
|
||||
|
||||
## version-spring-web
|
||||
|
||||
Добавляет возможность задавать версию апи через `properties` без необходимости явно указывать в каждом маппинге
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ subprojects {
|
|||
|
||||
dependency("com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0")
|
||||
dependency("org.mockito:mockito-inline:2.13.0")
|
||||
|
||||
dependency("com.github.zafarkhaja:java-semver:0.9.0")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,3 +30,4 @@ include("logger-spring")
|
|||
include("logger-spring-web")
|
||||
include("exception-handler-spring-web")
|
||||
include("exception-handler-logger-spring-web")
|
||||
include("version-spring-web")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
plugins {
|
||||
id("kotlin")
|
||||
id("kotlin-spring")
|
||||
id("maven-publish")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||
|
||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||
|
||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
@file:Suppress("unused")
|
||||
package ru.touchin.version
|
||||
|
||||
import org.springframework.context.annotation.Import
|
||||
import ru.touchin.version.configurations.SpringVersionConfiguration
|
||||
|
||||
@Import(value = [SpringVersionConfiguration::class])
|
||||
annotation class EnableSpringVersion
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package ru.touchin.version.annotations
|
||||
|
||||
@Target(allowedTargets = [AnnotationTarget.CLASS])
|
||||
internal annotation class Versioned(
|
||||
val value: String = ""
|
||||
)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package ru.touchin.version.annotations
|
||||
|
||||
@Versioned("/api/v\${api.version}")
|
||||
@Target(allowedTargets = [AnnotationTarget.CLASS])
|
||||
annotation class VersionedApi
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package ru.touchin.version.configurations
|
||||
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import ru.touchin.version.mapping.WebMvcVersionRegistrations
|
||||
|
||||
@Suppress("SpringFacetCodeInspection")
|
||||
@Configuration
|
||||
class SpringVersionConfiguration {
|
||||
|
||||
@Bean
|
||||
fun webMvcRegistrations(): WebMvcRegistrations {
|
||||
return WebMvcVersionRegistrations()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package ru.touchin.version.mapping
|
||||
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
|
||||
import ru.touchin.version.annotations.Versioned
|
||||
import java.lang.reflect.Method
|
||||
|
||||
class VersionedRequestMappingHandlerMapping : RequestMappingHandlerMapping() {
|
||||
|
||||
override fun getMappingForMethod(method: Method, handlerType: Class<*>): RequestMappingInfo? {
|
||||
val mappingResult = super.getMappingForMethod(method, handlerType)
|
||||
?: return null
|
||||
|
||||
val versionedAnnotation = AnnotatedElementUtils.findMergedAnnotation(handlerType, Versioned::class.java)
|
||||
?: return mappingResult
|
||||
|
||||
val versionPath = resolveEmbeddedValuesInPatterns(
|
||||
arrayOf(versionedAnnotation.value)
|
||||
)
|
||||
|
||||
return RequestMappingInfo.paths(*versionPath).build().combine(mappingResult)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package ru.touchin.version.mapping
|
||||
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
|
||||
|
||||
class WebMvcVersionRegistrations : WebMvcRegistrations {
|
||||
|
||||
override fun getRequestMappingHandlerMapping(): RequestMappingHandlerMapping {
|
||||
return VersionedRequestMappingHandlerMapping()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package ru.touchin.version
|
||||
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
|
||||
@SpringBootApplication
|
||||
class TestApplication
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package ru.touchin.version
|
||||
|
||||
import org.hamcrest.Matchers.`is`
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.test.context.ActiveProfiles
|
||||
import org.springframework.test.web.servlet.MockMvc
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
|
||||
import org.springframework.test.web.servlet.result.MockMvcResultHandlers.print
|
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content
|
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath
|
||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
import ru.touchin.version.annotations.VersionedApi
|
||||
|
||||
@VersionedApi
|
||||
@RestController
|
||||
@RequestMapping("/app")
|
||||
class VersionController {
|
||||
|
||||
@GetMapping("/version")
|
||||
fun version(): Map<String, String> {
|
||||
return mapOf("version" to "yes")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/app")
|
||||
class NoVersionController {
|
||||
|
||||
@GetMapping("/no-version")
|
||||
fun noVersion(): Map<String, String> {
|
||||
return mapOf("version" to "no")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ActiveProfiles("test")
|
||||
@SpringBootTest
|
||||
@AutoConfigureMockMvc
|
||||
internal class VersionedRequestMappingHandlerMappingMvcTest {
|
||||
|
||||
@Autowired
|
||||
private lateinit var mockMvc: MockMvc
|
||||
|
||||
@Test
|
||||
@DisplayName("К пути должна добавляться версия")
|
||||
fun shouldBePathWithVersion() {
|
||||
mockMvc
|
||||
.perform(get("/api/v6/app/version"))
|
||||
.andDo(print())
|
||||
.andExpect(status().isOk)
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.version", `is`("yes")))
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("К пути не должна добавляться версия")
|
||||
fun shouldBePathWithoutVersion() {
|
||||
mockMvc
|
||||
.perform(get("/app/no-version"))
|
||||
.andDo(print())
|
||||
.andExpect(status().isOk)
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.version", `is`("no")))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
# suppress inspection "SpringBootApplicationProperties"
|
||||
api.version=6
|
||||
Loading…
Reference in New Issue