mcpField
S
spring-boot-engineer

spring-boot-engineer

github.com/jeffallan開発12.1k8.5k 回インストール今日更新
リポジトリ

spring-boot-engineer について

本番運用を意識した Java サービスを構築する開発者向けの Spring Boot エンジニアリングスキルです。設計から実装、セキュリティ、テスト、デプロイまでを、分野別ガイドと基本構成例で支援します。

主な機能

  1. 01要件とアーキテクチャの計画
  2. 02レイヤー化した Spring Boot 実装ガイド
  3. 03セキュリティと入力検証の実践
  4. 04単体・統合・スライステスト
  5. 05Actuator のヘルスチェックガイド

活用シーン

  1. 01REST サービスの境界と API の設計
  2. 02検証付き Spring Boot エンドポイントの実装
  3. 03テストやセキュリティルールの失敗調査
  4. 04デプロイ前のサービス状態確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jeffallan/claude-skills --skill spring-boot-engineer

インストール後、Claude Code で/spring-boot-engineerを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
cloud.md
data.md
security.md
testing.md
web.md

詳細

Spring Boot エンジニア

コアワークフロー

  1. 要件を分析する — サービスの境界、API、データモデル、セキュリティ要件を特定します
  2. アーキテクチャを設計する — マイクロサービス、データアクセス、クラウド統合、セキュリティを計画し、コーディング前に設計を確認します
  3. 実装する — コンストラクターインジェクションとレイヤードアーキテクチャを使用してサービスを作成します(以下のクイックスタートを参照)
  4. セキュリティを確保する — Spring Security、OAuth2、メソッドセキュリティ、CORS 設定を追加し、セキュリティルールがコンパイルされ、テストに合格することを確認します。コンパイルまたはテストに失敗した場合は、エラー出力を確認し、失敗したルールまたは設定を修正してから、次に進む前に再実行します
  5. テストする — 単体テスト、統合テスト、スライステストを作成し、./mvnw test(または ./gradlew test)を実行して、次に進む前にすべて合格することを確認します。テストに失敗した場合は、スタックトレースを確認し、失敗したアサーションまたはコンポーネントを特定して修正し、テストスイート全体を再実行します
  6. デプロイする — Actuator を使用してヘルスチェックとオブザーバビリティを設定し、/actuator/health が UP を返すことを確認します。ヘルス状態が DOWN の場合は、レスポンス内の components の詳細を確認し、失敗したコンポーネント(例:データソース、ブローカー)を解決して、再度確認します

リファレンスガイド

状況に応じて詳細なガイダンスを読み込みます。

トピックリファレンス読み込むタイミング
Web レイヤーreferences/web.mdコントローラー、REST API、バリデーション、例外処理
データアクセスreferences/data.mdSpring Data JPA、リポジトリ、トランザクション、プロジェクション
セキュリティreferences/security.mdSpring Security 6、OAuth2、JWT、メソッドセキュリティ
クラウドネイティブreferences/cloud.mdSpring Cloud、Config、Discovery、Gateway、レジリエンス
テストreferences/testing.md@SpringBootTest、MockMvc、Testcontainers、テストスライス

クイックスタート — 最小限の動作構成

標準的な Spring Boot の機能は、次のレイヤーで構成されます。コピーして利用する際の出発点として使用してください。

エンティティ
@Entity
@Table(name = "products")
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank
    private String name;

    @DecimalMin("0.0")
    private BigDecimal price;

    // getters / setters or use @Data (Lombok)
}
リポジトリ
public interface ProductRepository extends JpaRepository<Product, Long> {
    List<Product> findByNameContainingIgnoreCase(String name);
}
サービス(コンストラクターインジェクション)
@Service
public class ProductService {
    private final ProductRepository repo;

    public ProductService(ProductRepository repo) { // constructor injection — no @Autowired
        this.repo = repo;
    }

    @Transactional(readOnly = true)
    public List<Product> search(String name) {
        return repo.findByNameContainingIgnoreCase(name);
    }

    @Transactional
    public Product create(ProductRequest request) {
        var product = new Product();
        product.setName(request.name());
        product.setPrice(request.price());
        return repo.save(product);
    }
}
REST コントローラー
@RestController
@RequestMapping("/api/v1/products")
@Validated
public class ProductController {
    private final ProductService service;

    public ProductController(ProductService service) {
        this.service = service;
    }

    @GetMapping
    public List<Product> search(@RequestParam(defaultValue = "") String name) {
        return service.search(name);
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public Product create(@Valid @RequestBody ProductRequest request) {
        return service.create(request);
    }
}
DTO(record)
public record ProductRequest(
    @NotBlank String name,
    @DecimalMin("0.0") BigDecimal price
) {}
グローバル例外ハンドラー
@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Map<String, String> handleValidation(MethodArgumentNotValidException ex) {
        return ex.getBindingResult().getFieldErrors().stream()
            .collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
    }

    @ExceptionHandler(EntityNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public Map<String, String> handleNotFound(EntityNotFoundException ex) {
        return Map.of("error", ex.getMessage());
    }
}
テストスライス
@WebMvcTest(ProductController.class)
class ProductControllerTest {
    @Autowired MockMvc mockMvc;
    @MockBean ProductService service;

    @Test
    void createProduct_validRequest_returns201() throws Exception {
        var product = new Product(); product.setName("Widget"); product.setPrice(BigDecimal.TEN);
        when(service.create(any())).thenReturn(product);

        mockMvc.perform(post("/api/v1/products")
                .contentType(MediaType.APPLICATION_JSON)
                .content("""{"name":"Widget","price":10.0}"""))
            .andExpect(status().isCreated())
            .andExpect(jsonPath("$.name").value("Widget"));
    }
}

制約

必ず行うこと
ルール正しいパターン
コンストラクターインジェクションpublic MyService(Dep dep) { this.dep = dep; }
API 入力を検証するすべての変更エンドポイントで @Valid @RequestBody MyRequest req を使用
型安全な設定レコードまたはクラスにバインドされた @ConfigurationProperties(prefix = "app")
適切なステレオタイプビジネスロジックには @Service、データには @Repository、HTTP には @RestController
トランザクションの範囲複数ステップの書き込みには @Transactional、読み取りには @Transactional(readOnly = true)
内部情報を隠す@RestControllerAdvice でドメイン例外をキャッチし、スタックトレースではなく問題の詳細を返す
シークレットを外部化する環境変数または Spring Cloud Config を使用し、application.properties には決して記述しない
絶対に行わないこと
  • フィールドインジェクションを使用する(フィールドに @Autowired を付ける)
  • API エンドポイントの入力検証を省略する
  • @Service/@Repository/@Controller が適切な場面で @Component を使用する
  • ブロッキングコードとリアクティブコードを混在させる(例:WebFlux チェーン内で .block() を呼び出す)
  • シークレットや認証情報を application.properties/application.yml に保存する
  • URL、認証情報、環境固有の値をハードコードする
  • 非推奨の Spring Boot 2.x パターンを使用する(例:WebSecurityConfigurerAdapter)

@jeffallan(Synergetic Solutions のプリンシパルコンサルタント)がメンテナンスしています

ドキュメント

コメント