KotlinでのSpringを使用したRESTのエラー処理
1. 概要
例外処理は、RESTAPIを構築するときにカバーする最も重要なトピックの1つです。 Springは、APIの応答をカスタマイズするのに役立つネイティブ機能を使用して、例外を処理するための優れたサポートを提供します。
このチュートリアルでは、Kotlinを使用してSpring BootRESTAPIで例外処理を実装するためのいくつかのアプローチについて説明します。
2. RESTコントローラーとテンプレートメッセージ
2.1. RESTコントローラーの例
まず、サンプルAPIを作成する必要があります。 ケーススタディでは、記事を作成、更新、取得するためのサービスを公開する小さなRESTコントローラーを定義します。
@RestController
@RequestMapping("/articles")
class ArticleController(val articleService: ArticleService) {
@PostMapping()
fun createArticle(@RequestBody title: String): ArticleModel {
return articleService.createArticle(title);
}
@GetMapping()
fun getArticle(@RequestParam id: String): ArticleModel {
return articleService.getArticle(id);
}
@PutMapping()
fun updateArticle(@RequestParam id: String, @RequestParam title: String): ArticleModel {
return articleService.updateArticle(id, title);
}
}
2.2. カスタムテンプレートメッセージ
次に、APIのエラーメッセージのテンプレートを定義します。
class ErrorMessageModel(
var status: Int? = null,
var message: String? = null
)
statusプロパティは、HTTPステータスコードの番号を格納し、messageプロパティは、スローされた例外を説明するために定義されたカスタムメッセージを表します。
3. 例外コントローラーのアドバイス
アノテーション@ControllerAdviceを使用して、複数のコントローラーのグローバルハンドラーを定義できます。 たとえば、IllegalStateExceptionタイプのエラーに対してカスタムメッセージを返したい場合があります。
@ControllerAdvice
class ExceptionControllerAdvice {
@ExceptionHandler
fun handleIllegalStateException(ex: IllegalStateException): ResponseEntity<ErrorMessageModel> {
val errorMessage = ErrorMessageModel(
HttpStatus.NOT_FOUND.value(),
ex.message
)
return ResponseEntity(errorMessage, HttpStatus.BAD_REQUEST)
}
}
さらに、特定のシナリオのカスタム例外を定義できます。 たとえば、APIで記事が見つからない場合に例外を作成できます。
class ArticleNotFoundException(message: String) : RuntimeException(message) {
}
したがって、この例外はグローバルハンドラーによってキャッチされます。
@ExceptionHandler
fun handleArticleNotFoundException(ex: ArticleNotFoundException): ResponseEntity<ErrorMessageModel> {
val errorMessage = ErrorMessageModel(
HttpStatus.NOT_FOUND.value(),
ex.message
)
return ResponseEntity(errorMessage, HttpStatus.NOT_FOUND)
}
最後に、APIのビジネスロジックを実行するArticleServiceクラスを定義するために必要なすべてのコンポーネントがあります。
@Service
class ArticleService {
lateinit var articles: List<ArticleModel>
@PostConstruct
fun buildArticles() {
articles = listOf(
ArticleModel("1", "Exception Handling in Kotlin"),
ArticleModel("2", "Decorator Patter in Kotlin"),
ArticleModel("3", "Abstract Pattern in Kotlin")
)
}
fun createArticle(title: String): ArticleModel {
val article = (articles.find { articleModel -> articleModel.title == title })
if (article != null) {
throw IllegalStateException("Article with the same title already exists")
}
return ArticleModel("4", title)
}
fun getArticle(id: String): ArticleModel {
return articles.find { articleModel -> articleModel.id == id }
?: throw ArticleNotFoundException("Article not found")
}
fun updateArticle(id: String, title: String): ArticleModel {
val article = (articles.find { articleModel -> articleModel.id == id }
?: throw ArticleNotFoundException("Article not found"))
if (title.length > 50) {
throw IllegalArgumentException("Article title too long")
}
article.title = title
return article
}
}
4. ResponseStatusExceptionクラス
ResponseStatusExceptionクラスは、例外を動的に処理するための優れたサポートを提供します。 したがって、コントローラークラスのメソッド定義内でエラーを処理できます。
@PutMapping()
fun updateArticle(@RequestParam id: String, @RequestParam title: String): ArticleModel {
try {
return articleService.updateArticle(id, title);
} catch (ex: IllegalArgumentException) {
throw ResponseStatusException(HttpStatus.BAD_REQUEST, ex.localizedMessage, ex)
}
}
その結果、グローバルコントローラーは必要ありませんが、特定の例外を処理する場所を定義する必要があります。
5. 結論
このチュートリアルでは、Kotlinを使用してRESTAPIで例外処理を実装するためのいくつかの効率的なアプローチについて説明しました。 @ControllerAdvice アノテーションを使用してグローバルハンドラーを定義でき、ResponseStatusExceptionクラスを使用して動的ハンドラーを作成することもできます。
いつものように、この記事の完全なコードは、GitHubでから入手できます。