Optimize annotation in controller

This commit is contained in:
2023-12-18 13:25:34 +08:00
parent e1970c8a03
commit 66146cb3b4
17 changed files with 113 additions and 109 deletions

View File

@@ -0,0 +1,23 @@
package top.fatweb.api.annotation
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.core.annotation.AliasFor
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@Tag(name = "")
@RequestMapping
@RestController
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class ApiController(
val version: Int = 1,
@get:AliasFor(annotation = RestController::class, attribute = "value") val value: String = "",
@get:AliasFor(annotation = RequestMapping::class, attribute = "path") val path: Array<String> = [""],
@get:AliasFor(annotation = Tag::class, attribute = "name") val name: String,
@get:AliasFor(annotation = Tag::class, attribute = "description") val description: String
)

View File

@@ -1,17 +0,0 @@
package top.fatweb.api.annotation
import org.springframework.core.annotation.AliasFor
/**
* Api controller version annotation
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class ApiVersion(
@get:AliasFor("version") val value: Int = 1,
@get:AliasFor("value") val version: Int = 1
)

View File

@@ -0,0 +1,19 @@
package top.fatweb.api.annotation
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.core.annotation.AliasFor
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@Tag(name = "")
@RequestMapping
@RestController
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class BaseController(
@get:AliasFor(annotation = RequestMapping::class, attribute = "path") val path: Array<String> = [""],
@get:AliasFor(annotation = Tag::class, attribute = "name") val name: String,
@get:AliasFor(annotation = Tag::class, attribute = "description") val description: String
)

View File

@@ -0,0 +1,15 @@
package top.fatweb.api.annotation
import io.swagger.v3.oas.annotations.Hidden
import org.springframework.core.annotation.AliasFor
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@Hidden
@RequestMapping
@RestController
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class HiddenController(
@get:AliasFor(annotation = RequestMapping::class, attribute = "path") val path: Array<String> = [""]
)

View File

@@ -0,0 +1,13 @@
package top.fatweb.api.config
import org.springframework.context.annotation.Configuration
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
import top.fatweb.api.annotation.ApiController
@Configuration
class WebMvcConfigurerConfig : WebMvcConfigurer {
override fun configurePathMatch(configurer: PathMatchConfigurer) {
configurer.addPathPrefix("/api/{API_VERSION}") {it.isAnnotationPresent(ApiController::class.java)}
}
}

View File

@@ -1,9 +1,8 @@
package top.fatweb.api.controller
import io.swagger.v3.oas.annotations.Hidden
import jakarta.servlet.http.HttpServletRequest
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import top.fatweb.api.annotation.HiddenController
/**
* Exception controller
@@ -11,9 +10,7 @@ import org.springframework.web.bind.annotation.RestController
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Hidden
@RestController
@RequestMapping("/error")
@HiddenController(["/error"])
class ExceptionController {
@RequestMapping("/thrown")
fun thrown(request: HttpServletRequest) {

View File

@@ -1,13 +1,10 @@
package top.fatweb.api.controller.api.v1
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import jakarta.validation.Valid
import org.springframework.http.MediaType
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import top.fatweb.api.annotation.ApiController
import top.fatweb.api.entity.common.ResponseCode
import top.fatweb.api.entity.common.ResponseResult
import top.fatweb.api.param.api.v1.avatar.AvatarBaseParam
@@ -22,16 +19,13 @@ import top.fatweb.api.vo.api.v1.avatar.AvatarBase64Vo
* @since 1.0.0
* @see IAvatarService
*/
@Tag(name = "随机头像", description = "随机头像相关接口")
@RequestMapping("/api/{apiVersion}/avatar")
@RestController
@ApiController(value = "avatarControllerV1", path = ["/avatar"], name = "随机头像 V1", description = "随机头像相关接口")
class AvatarController(
private val avatarService: IAvatarService
) {
/**
* Get random avatar
*
* @param apiVersion Api version
* @param avatarBaseParam Avatar base parameters
* @return Avatar byte array
* @author FatttSnake, fatttsnake@gmail.com
@@ -41,7 +35,7 @@ class AvatarController(
*/
@Operation(summary = "获取随机头像")
@GetMapping(produces = [MediaType.IMAGE_PNG_VALUE])
fun getRandom(@PathVariable apiVersion: String, @Valid avatarBaseParam: AvatarBaseParam?): ByteArray =
fun getRandom(@Valid avatarBaseParam: AvatarBaseParam?): ByteArray =
when ((1..4).random()) {
1 -> avatarService.triangle(avatarBaseParam)
2 -> avatarService.square(avatarBaseParam)
@@ -59,7 +53,6 @@ class AvatarController(
/**
* Get random avatar as base64
*
* @param apiVersion Api version
* @param avatarBaseParam Avatar base parameters
* @return Response object includes avatar base64 string
* @author FatttSnake, fatttsnake@gmail.com
@@ -71,7 +64,6 @@ class AvatarController(
@Operation(summary = "获取随机头像 Base64")
@GetMapping("base64")
fun getRandomBase64(
@PathVariable apiVersion: String,
@Valid avatarBaseParam: AvatarBaseParam?
): ResponseResult<AvatarBase64Vo> =
ResponseResult.success(
@@ -93,7 +85,6 @@ class AvatarController(
/**
* Get triangle avatar
*
* @param apiVersion Api version
* @param avatarBaseParam Avatar base parameters
* @return Avatar byte array
* @author FatttSnake, fatttsnake@gmail.com
@@ -103,13 +94,12 @@ class AvatarController(
*/
@Operation(summary = "三角形头像")
@GetMapping("/triangle", produces = [MediaType.IMAGE_PNG_VALUE])
fun triangle(@PathVariable apiVersion: String, @Valid avatarBaseParam: AvatarBaseParam?): ByteArray =
fun triangle(@Valid avatarBaseParam: AvatarBaseParam?): ByteArray =
avatarService.triangle(avatarBaseParam)
/**
* Get triangle avatar as base64
*
* @param apiVersion Api version
* @param avatarBaseParam Avatar base parameters
* @return Response object includes avatar base64 string
* @author FatttSnake, fatttsnake@gmail.com
@@ -121,7 +111,6 @@ class AvatarController(
@Operation(summary = "三角形头像 Base64")
@GetMapping("/triangle/base64")
fun triangleBase64(
@PathVariable apiVersion: String,
@Valid avatarBaseParam: AvatarBaseParam?
): ResponseResult<AvatarBase64Vo> =
ResponseResult.success(
@@ -132,7 +121,6 @@ class AvatarController(
/**
* Get square avatar
*
* @param apiVersion Api version
* @param avatarBaseParam Avatar base parameters
* @return Avatar byte array
* @author FatttSnake, fatttsnake@gmail.com
@@ -142,13 +130,12 @@ class AvatarController(
*/
@Operation(summary = "正方形头像")
@GetMapping("/square", produces = [MediaType.IMAGE_PNG_VALUE])
fun square(@PathVariable apiVersion: String, @Valid avatarBaseParam: AvatarBaseParam?): ByteArray =
fun square(@Valid avatarBaseParam: AvatarBaseParam?): ByteArray =
avatarService.square(avatarBaseParam)
/**
* Get square avatar as base64
*
* @param apiVersion Api version
* @param avatarBaseParam Avatar base parameters
* @return Response object includes avatar base64 string
* @author FatttSnake, fatttsnake@gmail.com
@@ -160,7 +147,6 @@ class AvatarController(
@Operation(summary = "正方形头像 Base64")
@GetMapping("/square/base64")
fun squareBase64(
@PathVariable apiVersion: String,
@Valid avatarBaseParam: AvatarBaseParam?
): ResponseResult<AvatarBase64Vo> =
ResponseResult.success(
@@ -171,7 +157,6 @@ class AvatarController(
/**
* Get identicon avatar
*
* @param apiVersion Api version
* @param avatarBaseParam Avatar base parameters
* @return Avatar byte array
* @author FatttSnake, fatttsnake@gmail.com
@@ -181,13 +166,12 @@ class AvatarController(
*/
@Operation(summary = "Identicon 头像")
@GetMapping("/identicon", produces = [MediaType.IMAGE_PNG_VALUE])
fun identicon(@PathVariable apiVersion: String, @Valid avatarBaseParam: AvatarBaseParam?): ByteArray =
fun identicon(@Valid avatarBaseParam: AvatarBaseParam?): ByteArray =
avatarService.identicon(avatarBaseParam)
/**
* Get identicon avatar as base64
*
* @param apiVersion Api version
* @param avatarBaseParam Avatar base parameters
* @return Response object includes avatar base64 string
* @author FatttSnake, fatttsnake@gmail.com
@@ -199,7 +183,6 @@ class AvatarController(
@Operation(summary = "Identicon 头像 Base64")
@GetMapping("/identicon/base64")
fun identiconBase64(
@PathVariable apiVersion: String,
@Valid avatarBaseParam: AvatarBaseParam?
): ResponseResult<AvatarBase64Vo> =
ResponseResult.success(
@@ -210,7 +193,6 @@ class AvatarController(
/**
* Get GitHub avatar
*
* @param apiVersion Api version
* @param avatarGitHubParam Avatar base parameters
* @return Avatar byte array
* @author FatttSnake, fatttsnake@gmail.com
@@ -220,13 +202,12 @@ class AvatarController(
*/
@Operation(summary = "GitHub 头像")
@GetMapping("/github", produces = [MediaType.IMAGE_PNG_VALUE])
fun github(@PathVariable apiVersion: String, @Valid avatarGitHubParam: AvatarGitHubParam?): ByteArray =
fun github(@Valid avatarGitHubParam: AvatarGitHubParam?): ByteArray =
avatarService.github(avatarGitHubParam)
/**
* Get GitHub avatar as base64
*
* @param apiVersion Api version
* @param avatarGitHubParam Avatar base parameters
* @return Response object includes avatar base64 string
* @author FatttSnake, fatttsnake@gmail.com
@@ -238,7 +219,6 @@ class AvatarController(
@Operation(summary = "GitHub 头像 Base64")
@GetMapping("/github/base64")
fun githubBase64(
@PathVariable apiVersion: String,
@Valid avatarGitHubParam: AvatarGitHubParam?
): ResponseResult<AvatarBase64Vo> =
ResponseResult.success(

View File

@@ -1,13 +1,12 @@
package top.fatweb.api.controller.permission
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import jakarta.servlet.http.HttpServletRequest
import jakarta.validation.Valid
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RestController
import top.fatweb.api.annotation.BaseController
import top.fatweb.api.converter.permission.UserConverter
import top.fatweb.api.entity.common.ResponseCode
import top.fatweb.api.entity.common.ResponseResult
@@ -24,8 +23,7 @@ import top.fatweb.api.vo.permission.TokenVo
* @since 1.0.0
* @see IAuthenticationService
*/
@Tag(name = "身份认证", description = "身份认证相关接口")
@RestController
@BaseController(name = "身份认证", description = "身份认证相关接口")
class AuthenticationController(
private val authenticationService: IAuthenticationService
) {
@@ -63,10 +61,11 @@ class AuthenticationController(
*/
@Operation(summary = "登出")
@PostMapping("/logout")
fun logout(request: HttpServletRequest): ResponseResult<Nothing> = when (authenticationService.logout(WebUtil.getToken(request))) {
true -> ResponseResult.success(ResponseCode.PERMISSION_LOGOUT_SUCCESS, "Logout success", null)
false -> ResponseResult.fail(ResponseCode.PERMISSION_LOGOUT_FAILED, "Logout failed", null)
}
fun logout(request: HttpServletRequest): ResponseResult<Nothing> =
when (authenticationService.logout(WebUtil.getToken(request))) {
true -> ResponseResult.success(ResponseCode.PERMISSION_LOGOUT_SUCCESS, "Logout success", null)
false -> ResponseResult.fail(ResponseCode.PERMISSION_LOGOUT_FAILED, "Logout failed", null)
}
/**
* Renew token

View File

@@ -1,10 +1,10 @@
package top.fatweb.api.controller.permission
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import jakarta.validation.Valid
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.*
import top.fatweb.api.annotation.BaseController
import top.fatweb.api.entity.common.ResponseCode
import top.fatweb.api.entity.common.ResponseResult
import top.fatweb.api.param.permission.group.*
@@ -20,9 +20,7 @@ import top.fatweb.api.vo.permission.base.GroupVo
* @since 1.0.0
* @see IGroupService
*/
@Tag(name = "用户组管理", description = "用户组管理相关接口")
@RequestMapping("/system/group")
@RestController
@BaseController(path = ["/system/group"], name = "用户组管理", description = "用户组管理相关接口")
class GroupController(
val groupService: IGroupService
) {

View File

@@ -1,11 +1,9 @@
package top.fatweb.api.controller.permission
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import top.fatweb.api.annotation.BaseController
import top.fatweb.api.entity.common.ResponseResult
import top.fatweb.api.service.permission.IPowerService
import top.fatweb.api.vo.permission.PowerSetVo
@@ -17,9 +15,7 @@ import top.fatweb.api.vo.permission.PowerSetVo
* @since 1.0.0
* @see IPowerService
*/
@Tag(name = "权限管理", description = "权限管理相关接口")
@RequestMapping("/system/power")
@RestController
@BaseController(path = ["/system/power"], name = "权限管理", description = "权限管理相关接口")
class PowerController(
private val powerService: IPowerService
) {

View File

@@ -1,10 +1,10 @@
package top.fatweb.api.controller.permission
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import jakarta.validation.Valid
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.*
import top.fatweb.api.annotation.BaseController
import top.fatweb.api.entity.common.ResponseCode
import top.fatweb.api.entity.common.ResponseResult
import top.fatweb.api.param.permission.role.*
@@ -20,9 +20,7 @@ import top.fatweb.api.vo.permission.base.RoleVo
* @since 1.0.0
* @see IRoleService
*/
@Tag(name = "角色管理", description = "角色管理相关接口")
@RequestMapping("/system/role")
@RestController
@BaseController(path = ["/system/role"], name = "角色管理", description = "角色管理相关接口")
class RoleController(
private val roleService: IRoleService
) {

View File

@@ -1,10 +1,10 @@
package top.fatweb.api.controller.permission
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import jakarta.validation.Valid
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.*
import top.fatweb.api.annotation.BaseController
import top.fatweb.api.entity.common.ResponseCode
import top.fatweb.api.entity.common.ResponseResult
import top.fatweb.api.exception.NoRecordFoundException
@@ -22,9 +22,7 @@ import top.fatweb.api.vo.permission.UserWithRoleInfoVo
* @since 1.0.0
* @see IUserService
*/
@Tag(name = "用户管理", description = "用户管理相关接口")
@RequestMapping("/system/user")
@RestController
@BaseController(path = ["/system/user"], name = "用户管理", description = "用户管理相关接口")
class UserController(
private val userService: IUserService
) {

View File

@@ -1,10 +1,13 @@
package top.fatweb.api.controller.system
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import jakarta.validation.Valid
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.*
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import top.fatweb.api.annotation.BaseController
import top.fatweb.api.entity.common.ResponseResult
import top.fatweb.api.param.system.MailSendParam
import top.fatweb.api.param.system.MailSettingsParam
@@ -18,9 +21,7 @@ import top.fatweb.api.vo.system.MailSettingsVo
* @since 1.0.0
* @see ISettingsService
*/
@Tag(name = "系统设置", description = "系统设置相关接口")
@RequestMapping("/system/settings")
@RestController
@BaseController(path = ["/system/settings"], name = "系统设置", description = "系统设置相关接口")
class SettingsController(
private val settingsService: ISettingsService
) {

View File

@@ -1,13 +1,14 @@
package top.fatweb.api.controller.system
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import top.fatweb.api.annotation.BaseController
import top.fatweb.api.entity.common.ResponseResult
import top.fatweb.api.service.system.IStatisticService
import top.fatweb.api.vo.system.*
import top.fatweb.api.vo.system.CpuInfoVo
import top.fatweb.api.vo.system.HardwareInfoVo
import top.fatweb.api.vo.system.SoftwareInfoVo
import top.fatweb.api.vo.system.StorageInfoVo
/**
* Statistic controller
@@ -16,9 +17,7 @@ import top.fatweb.api.vo.system.*
* @since 1.0.0
* @see IStatisticService
*/
@Tag(name = "统计接口", description = "系统信息统计相关接口")
@RequestMapping("/system/statistic")
@RestController
@BaseController(path = ["/system/statistic"], name = "统计接口", description = "系统信息统计相关接口")
class StatisticController(
private val statisticService: IStatisticService
) {

View File

@@ -1,12 +1,10 @@
package top.fatweb.api.controller.system
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import jakarta.validation.Valid
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import top.fatweb.api.annotation.BaseController
import top.fatweb.api.entity.common.ResponseCode
import top.fatweb.api.entity.common.ResponseResult
import top.fatweb.api.param.system.SysLogGetParam
@@ -21,9 +19,7 @@ import top.fatweb.api.vo.system.SysLogVo
* @since 1.0.0
* @see ISysLogService
*/
@Tag(name = "系统日志", description = "系统日志相关接口")
@RequestMapping("/system/log")
@RestController
@BaseController(path = ["/system/log"], name = "系统日志", description = "系统日志相关接口")
class SysLogController(
private val sysLogService: ISysLogService
) {

View File

@@ -1,9 +1,8 @@
package top.fatweb.api.util
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.servlet.mvc.condition.RequestCondition
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
import top.fatweb.api.annotation.ApiVersion
import top.fatweb.api.annotation.ApiController
import java.lang.reflect.Method
/**
@@ -13,22 +12,12 @@ import java.lang.reflect.Method
* @since 1.0.0
*/
class ApiResponseMappingHandlerMapping : RequestMappingHandlerMapping() {
private val versionFlag = "{apiVersion}"
private fun createCondition(clazz: Class<*>): RequestCondition<ApiVersionCondition>? {
val classRequestMapping = clazz.getAnnotation(RequestMapping::class.java)
classRequestMapping ?: let { return null }
val mappingUrlBuilder = StringBuilder()
if (classRequestMapping.value.isNotEmpty()) {
mappingUrlBuilder.append(classRequestMapping.value[0])
}
val mappingUrl = mappingUrlBuilder.toString()
if (!mappingUrl.contains(versionFlag)) {
return null
}
val apiVersion = clazz.getAnnotation(ApiVersion::class.java)
val apiController = clazz.getAnnotation(ApiController::class.java)
apiController ?: let { return null }
return if (apiVersion == null) ApiVersionCondition(1) else ApiVersionCondition(apiVersion.version)
return ApiVersionCondition(apiController.version)
}
override fun getCustomMethodCondition(method: Method): RequestCondition<*>? = createCondition(method.javaClass)

View File

@@ -10,7 +10,7 @@ import org.springframework.web.servlet.mvc.condition.RequestCondition
* @since 1.0.0
*/
class ApiVersionCondition(private val apiVersion: Int) : RequestCondition<ApiVersionCondition> {
private val versionPrefixRegex = Regex(".*v(\\d+).*")
private val versionPrefixRegex = Regex("/api/v(\\d+)/.*")
override fun combine(other: ApiVersionCondition): ApiVersionCondition = ApiVersionCondition(other.apiVersion)