用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/InugamiDev/ultrathink-oss --skill spring-boot命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
Unified design foundations — design system architecture, tokens, component specs, visual principles, creative vision, figma integration, plus brand design system loader (66 real brands via DESIGN.md). Absorbs design, design-system, design-systems, design-principles, design-router, creative-vision, figma, design-md.
Render, summarize, and present markdown documents and structured content in multiple output modes
Ultra UI skill - combines Google's DESIGN.md spec (machine-readable design tokens) with the ui-ux-pro-max knowledge base (91 styles, 161 palettes, 73 font pairings, 161 products, 104 UX guidelines, 25 chart types). Generates lint-clean DESIGN.md files, validates token references and WCAG contrast, exports Tailwind/DTCG tokens, and diffs design systems version-over-version.
基于 SOC 职业分类
正在显示 SKILL.md
| name | spring-boot |
| description | Spring Boot patterns — auto-configuration, dependency injection, REST controllers, JPA, and actuator. |
| layer | domain |
| category | backend |
| triggers | ["spring boot","spring framework","spring jpa","spring security","spring actuator"] |
| inputs | ["API endpoint requirements or domain model specifications","Performance or configuration issues with Spring Boot apps","JPA entity relationship design questions","Security configuration needs"] |
| outputs | ["Spring Boot REST controllers with proper patterns","JPA entity mappings and repository queries","Security configuration with Spring Security","Production-ready application.yml configuration"] |
| linksTo | ["postgresql","redis","docker","kubernetes"] |
| linkedFrom | [] |
| riskLevel | low |
| memoryReadPolicy | selective |
| memoryWritePolicy | none |
| sideEffects | [] |
Provide expert guidance on Spring Boot application architecture, auto-configuration, REST API development, JPA/Hibernate patterns, and production-grade configuration. Covers Spring Boot 3.x with Jakarta EE, virtual threads, and GraalVM native image support.
Follow the standard layered architecture:
src/main/java/com/example/app/
├── config/ # @Configuration classes
├── controller/ # @RestController endpoints
├── service/ # @Service business logic
├── repository/ # Spring Data JPA repositories
├── entity/ # JPA @Entity classes
├── dto/ # Request/response DTOs
├── exception/ # Custom exceptions + @ControllerAdvice
├── mapper/ # Entity ↔ DTO mappers (MapStruct)
└── Application.java # @SpringBootApplication entry point
Proper controller structure with validation and response entities:
@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@GetMapping
public ResponseEntity<Page<UserResponse>> list(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "20") int size) {
Pageable pageable = PageRequest.of(page, size, Sort.by("createdAt").descending());
return ResponseEntity.ok(userService.findAll(pageable));
}
@GetMapping("/{id}")
public ResponseEntity<UserResponse> getById(@PathVariable UUID id) {
return ResponseEntity.ok(userService.findById(id));
}
@PostMapping
ResponseEntity<UserResponse> {
userService.create(request);
ServletUriComponentsBuilder.fromCurrentRequest()
.path()
.buildAndExpand(created.id())
.toUri();
ResponseEntity.created(location).body(created);
}
ResponseEntity<UserResponse> {
ResponseEntity.ok(userService.update(id, request));
}
{
userService.delete(id);
}
}
Base entity with auditing:
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@Getter
public abstract class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.UUID)
private UUID id;
@CreatedDate
@Column(updatable = false)
private Instant createdAt;
@LastModifiedDate
private Instant updatedAt;
@Version
private Long version; // Optimistic locking
}
Entity with proper relationships:
@Entity
@Table(name = "orders", indexes = {
@Index(name = "idx_orders_user_id", columnList = "user_id"),
@Index(name = "idx_orders_status", columnList = "status")
})
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Order extends BaseEntity {
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "user_id", nullable = false)
private User user;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
@OrderBy("position ASC")
private List<OrderItem> items = new ArrayList<>();
@Enumerated(EnumType.STRING)
@Column(nullable = false, length = 20)
private OrderStatus status = OrderStatus.DRAFT;
// Domain method — encapsulate logic in the entity
public void addItem(Product product, int quantity) {
OrderItem item = new OrderItem(this, product, quantity, items.size());
items.add(item);
}
public BigDecimal getTotal() {
return items.stream()
.map(OrderItem::getSubtotal)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
}
Spring Data JPA repository with custom queries:
public interface OrderRepository extends JpaRepository<Order, UUID> {
// Derived query
List<Order> findByUserIdAndStatus(UUID userId, OrderStatus status);
// JPQL with fetch join to avoid N+1
@Query("SELECT o FROM Order o JOIN FETCH o.items WHERE o.id = :id")
Optional<Order> findByIdWithItems(@Param("id") UUID id);
// Native query for complex reporting
@Query(value = """
SELECT DATE_TRUNC('month', o.created_at) AS month,
COUNT(*) AS order_count,
SUM(oi.price * oi.quantity) AS revenue
FROM orders o
JOIN order_items oi ON oi.order_id = o.id
WHERE o.status = 'COMPLETED'
GROUP BY month
ORDER BY month DESC
""", nativeQuery = true)
List<MonthlyRevenueProjection> getMonthlyRevenue();
// Specification for dynamic filtering
Page<Order> findAll(Specification<Order> spec, Pageable pageable);
}
Transactional service with proper error handling:
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class OrderService {
private final OrderRepository orderRepository;
private final UserRepository userRepository;
private final OrderMapper orderMapper;
private final ApplicationEventPublisher eventPublisher;
public OrderResponse findById(UUID id) {
Order order = orderRepository.findByIdWithItems(id)
.orElseThrow(() -> new ResourceNotFoundException("Order", id));
return orderMapper.toResponse(order);
}
@Transactional
public OrderResponse create(UUID userId, CreateOrderRequest request) {
User user = userRepository.getReferenceById(userId);
Order order = orderMapper.toEntity(request);
order.setUser(user);
Order saved = orderRepository.save(order);
eventPublisher.publishEvent(new OrderCreatedEvent(saved.getId()));
return orderMapper.toResponse(saved);
}
@Transactional
@Retryable(retryFor = OptimisticLockingFailureException.class, maxAttempts = 3)
public OrderResponse updateStatus(UUID id, OrderStatus newStatus) {
Order order = orderRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("Order", id));
order.setStatus(newStatus);
return orderMapper.toResponse(orderRepository.save(order));
}
}
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ProblemDetail> handleNotFound(ResourceNotFoundException ex) {
ProblemDetail detail = ProblemDetail.forStatusAndDetail(
HttpStatus.NOT_FOUND, ex.getMessage());
detail.setTitle("Resource Not Found");
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(detail);
}
@ExceptionHandler(OptimisticLockingFailureException.class)
public ResponseEntity<ProblemDetail> handleConflict(OptimisticLockingFailureException ex) {
ProblemDetail detail = ProblemDetail.forStatusAndDetail(
HttpStatus.CONFLICT, "Resource was modified by another request");
detail.setTitle("Conflict");
return ResponseEntity.status(HttpStatus.CONFLICT).body(detail);
}
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex, HttpHeaders headers,
HttpStatusCode status, WebRequest request) {
ProblemDetail detail = ProblemDetail.forStatusAndDetail(
HttpStatus.BAD_REQUEST, "Validation failed");
detail.setProperty("errors", ex.getFieldErrors().stream()
.map(fe -> Map.of("field", fe.getField(), "message", fe.getDefaultMessage()))
.toList());
return ResponseEntity.badRequest().body(detail);
}
}
application.yml with profiles:
spring:
application:
name: my-service
datasource:
url: jdbc:postgresql://${DB_HOST:localhost}:${DB_PORT:5432}/${DB_NAME:mydb}
username: ${DB_USER:postgres}
password: ${DB_PASS:postgres}
hikari:
maximum-pool-size: ${DB_POOL_SIZE:10}
minimum-idle: 2
connection-timeout: 5000
jpa:
open-in-view: false # Always disable — prevents lazy loading in controllers
hibernate:
ddl-auto: validate # Use Flyway/Liquibase for migrations
properties:
hibernate:
default_batch_fetch_size: 16
order_inserts: true
order_updates: true
jdbc.batch_size: 50
threads:
virtual:
enabled: true # Spring Boot 3.2+ virtual threads
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
endpoint:
health:
show-details: when-authorized
server:
shutdown: graceful
lifecycle:
timeout-per-shutdown-phase: 30s
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf(csrf -> csrf.ignoringRequestMatchers("/api/**"))
.sessionManagement(sm -> sm.sessionCreationPolicy(STATELESS))
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/v1/auth/**").permitAll()
.requestMatchers("/actuator/health").permitAll()
.requestMatchers(HttpMethod.GET, "/api/v1/products/**").permitAll()
.anyRequest().authenticated()
)
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))
.build();
}
@Bean
public JwtDecoder jwtDecoder(@Value("${jwt.issuer-uri}") String issuerUri) {
return JwtDecoders.fromIssuerLocation(issuerUri);
}
}
open-in-view — Prevents lazy-loading queries from firing inside controllers, which causes performance issues and breaks transactional boundaries.@RequiredArgsConstructor (Lombok) over @Autowired field injection for testability.@Transactional(readOnly = true) at class level — Override with @Transactional only on write methods. This enables read-replica routing and Hibernate flush-mode optimization.JOIN FETCH in JPQL or @EntityGraph annotations to eagerly load associations when needed.ddl-auto in production. Set it to validate.ProblemDetail for errors — Spring 6 supports RFC 9457 Problem Details natively.maximum-pool-size should be (2 * CPU cores) + disk_spindles for most workloads.hibernate.jdbc.batch_size and order_inserts/updates for bulk operations.| Pitfall | Problem | Fix |
|---|---|---|
open-in-view: true (default) | Lazy loading in controller causes extra queries | Set spring.jpa.open-in-view: false |
| N+1 queries | Loading collections triggers per-entity queries | Use JOIN FETCH or @EntityGraph |
| Exposing entities in API | Tight coupling, circular refs, security leaks | Use DTO records + MapStruct |
ddl-auto: update in prod | Schema drift, data loss risk | Use validate + Flyway migrations |
Missing @Version | Lost updates under concurrency | Add optimistic locking with @Version |
| Blocking calls with WebFlux | Mixing blocking JPA with reactive stack | Use virtual threads instead of WebFlux for JPA apps |
| Large Hikari pool | Connection starvation at DB level | Size pool to (2 * cores) + spindles |
| No graceful shutdown | In-flight requests dropped on deploy | Configure server.shutdown: graceful |