spring-boot-4
17
总安装量
15
周安装量
#19903
全站排名
安装命令
npx skills add https://github.com/m19803261706/springboot-vben-admin --skill spring-boot-4
Agent 安装分布
claude-code
12
opencode
11
trae
10
cursor
10
codex
9
Skill 文档
Spring Boot 4 å¼åè§è
æ¬é¡¹ç®ä½¿ç¨ Spring Boot 4.0.1 + JPA + MySQL 8 ææ¯æ ã
ææ¯æ
| ææ¯ | çæ¬ | ç¨é |
|---|---|---|
| Spring Boot | 4.0.1 | Web æ¡æ¶ |
| Spring Data JPA | 3.4.x | æ°æ®è®¿é® |
| Hibernate | 7.x | ORM |
| MySQL | 8.0 | æ°æ®åº |
| JSpecify | 1.0.0 | Null å®å ¨ |
| SpringDoc | 2.8.x | API ææ¡£ |
| Lombok | – | ç®å代ç |
ç®å½ç»æ
backend/src/main/java/com/taichu/yingjiguanli/
âââ YingjiGuanliApplication.java # å¯å¨ç±»
âââ common/ # éç¨ç±»
â âââ ApiResponse.java # ç»ä¸ååº
â âââ BusinessException.java # ä¸å¡å¼å¸¸
â âââ PageResult.java # åé¡µç»æ
âââ config/ # é
置类
â âââ CorsConfig.java
â âââ GlobalExceptionHandler.java
â âââ JpaConfig.java
âââ modules/ # ä¸å¡æ¨¡å
â âââ {module}/ # 模åå
â âââ entity/ # å®ä½ç±»
â âââ repository/ # æ°æ®è®¿é®
â âââ service/ # æå¡å±
â â âââ impl/
â âââ controller/ # æ§å¶å¨
â âââ dto/ # æ°æ®ä¼ è¾å¯¹è±¡
â âââ vo/ # è§å¾å¯¹è±¡
âââ resources/
âââ application.yml
âââ db/migration/ # Flyway è¿ç§»
ä»£ç æ¨¡æ¿
Entity å®ä½ç±»
package com.taichu.yingjiguanli.modules.{module}.entity;
import jakarta.persistence.*;
import lombok.Data;
import org.hibernate.annotations.Comment;
import org.jspecify.annotations.Nullable;
import java.time.LocalDateTime;
/**
* {å®ä½æè¿°}
*
* @author CX
* @since {date}
*/
@Data
@Entity
@Table(name = "{table_name}")
@Comment("{表æè¿°}")
public class {EntityName} {
/**
* 主é®ID
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Comment("主é®ID")
private Long id;
/**
* {åæ®µæè¿°}
*/
@Column(nullable = false, length = 100)
@Comment("{åæ®µæè¿°}")
private String name;
/**
* å建æ¶é´
*/
@Column(nullable = false, updatable = false)
@Comment("å建æ¶é´")
private LocalDateTime createdAt;
/**
* æ´æ°æ¶é´
*/
@Column(nullable = false)
@Comment("æ´æ°æ¶é´")
private LocalDateTime updatedAt;
@PrePersist
protected void onCreate() {
createdAt = LocalDateTime.now();
updatedAt = LocalDateTime.now();
}
@PreUpdate
protected void onUpdate() {
updatedAt = LocalDateTime.now();
}
}
Repository æ°æ®è®¿é®
package com.taichu.yingjiguanli.modules.{module}.repository;
import com.taichu.yingjiguanli.modules.{module}.entity.{EntityName};
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
import java.util.Optional;
/**
* {å®ä½}æ°æ®è®¿é®æ¥å£
*
* @author CX
* @since {date}
*/
@Repository
public interface {EntityName}Repository extends JpaRepository<{EntityName}, Long>, JpaSpecificationExecutor<{EntityName}> {
/**
* æ ¹æ®åç§°æ¥è¯¢
*/
Optional<{EntityName}> findByName(String name);
}
Service æå¡å±
package com.taichu.yingjiguanli.modules.{module}.service;
import com.taichu.yingjiguanli.modules.{module}.dto.{EntityName}DTO;
import com.taichu.yingjiguanli.modules.{module}.entity.{EntityName};
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import java.util.Optional;
/**
* {å®ä½}æå¡æ¥å£
*
* @author CX
* @since {date}
*/
public interface {EntityName}Service {
/**
* å建
*/
{EntityName} create({EntityName}DTO dto);
/**
* æ´æ°
*/
{EntityName} update(Long id, {EntityName}DTO dto);
/**
* å é¤
*/
void delete(Long id);
/**
* æ ¹æ®IDæ¥è¯¢
*/
Optional<{EntityName}> findById(Long id);
/**
* å页æ¥è¯¢
*/
Page<{EntityName}> findAll(Pageable pageable);
}
ServiceImpl æå¡å®ç°
package com.taichu.yingjiguanli.modules.{module}.service.impl;
import com.taichu.yingjiguanli.common.BusinessException;
import com.taichu.yingjiguanli.modules.{module}.dto.{EntityName}DTO;
import com.taichu.yingjiguanli.modules.{module}.entity.{EntityName};
import com.taichu.yingjiguanli.modules.{module}.repository.{EntityName}Repository;
import com.taichu.yingjiguanli.modules.{module}.service.{EntityName}Service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
/**
* {å®ä½}æå¡å®ç°
*
* @author CX
* @since {date}
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class {EntityName}ServiceImpl implements {EntityName}Service {
private final {EntityName}Repository repository;
@Override
@Transactional
public {EntityName} create({EntityName}DTO dto) {
log.info("å建{å®ä½}: {}", dto);
{EntityName} entity = new {EntityName}();
// è®¾ç½®å±æ§...
return repository.save(entity);
}
@Override
@Transactional
public {EntityName} update(Long id, {EntityName}DTO dto) {
log.info("æ´æ°{å®ä½} ID={}: {}", id, dto);
{EntityName} entity = repository.findById(id)
.orElseThrow(() -> new BusinessException(404, "{å®ä½}ä¸åå¨"));
// æ´æ°å±æ§...
return repository.save(entity);
}
@Override
@Transactional
public void delete(Long id) {
log.info("å é¤{å®ä½} ID={}", id);
if (!repository.existsById(id)) {
throw new BusinessException(404, "{å®ä½}ä¸åå¨");
}
repository.deleteById(id);
}
@Override
public Optional<{EntityName}> findById(Long id) {
return repository.findById(id);
}
@Override
public Page<{EntityName}> findAll(Pageable pageable) {
return repository.findAll(pageable);
}
}
Controller æ§å¶å¨
package com.taichu.yingjiguanli.modules.{module}.controller;
import com.taichu.yingjiguanli.common.ApiResponse;
import com.taichu.yingjiguanli.common.BusinessException;
import com.taichu.yingjiguanli.modules.{module}.dto.{EntityName}DTO;
import com.taichu.yingjiguanli.modules.{module}.entity.{EntityName};
import com.taichu.yingjiguanli.modules.{module}.service.{EntityName}Service;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.*;
/**
* {å®ä½}æ§å¶å¨
*
* @author CX
* @since {date}
*/
@RestController
@RequestMapping("/api/{module}")
@RequiredArgsConstructor
@Tag(name = "{模ååç§°}", description = "{模åæè¿°}")
public class {EntityName}Controller {
private final {EntityName}Service service;
/**
* å建
*/
@PostMapping
@Operation(summary = "å建{å®ä½}")
public ApiResponse<{EntityName}> create(@Valid @RequestBody {EntityName}DTO dto) {
return ApiResponse.success(service.create(dto));
}
/**
* æ´æ°
*/
@PutMapping("/{id}")
@Operation(summary = "æ´æ°{å®ä½}")
public ApiResponse<{EntityName}> update(@PathVariable Long id, @Valid @RequestBody {EntityName}DTO dto) {
return ApiResponse.success(service.update(id, dto));
}
/**
* å é¤
*/
@DeleteMapping("/{id}")
@Operation(summary = "å é¤{å®ä½}")
public ApiResponse<Void> delete(@PathVariable Long id) {
service.delete(id);
return ApiResponse.success();
}
/**
* æ¥è¯¢è¯¦æ
*/
@GetMapping("/{id}")
@Operation(summary = "æ¥è¯¢{å®ä½}详æ
")
public ApiResponse<{EntityName}> getById(@PathVariable Long id) {
return ApiResponse.success(service.findById(id)
.orElseThrow(() -> new BusinessException(404, "{å®ä½}ä¸åå¨")));
}
/**
* å页æ¥è¯¢
*/
@GetMapping
@Operation(summary = "å页æ¥è¯¢{å®ä½}")
public ApiResponse<Page<{EntityName}>> list(Pageable pageable) {
return ApiResponse.success(service.findAll(pageable));
}
}
DTO æ°æ®ä¼ è¾å¯¹è±¡
package com.taichu.yingjiguanli.modules.{module}.dto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
/**
* {å®ä½}æ°æ®ä¼ è¾å¯¹è±¡
*
* @author CX
* @since {date}
*/
@Data
public class {EntityName}DTO {
/**
* åç§°
*/
@NotBlank(message = "åç§°ä¸è½ä¸ºç©º")
@Size(max = 100, message = "åç§°é¿åº¦ä¸è½è¶
è¿100")
private String name;
// å
¶ä»å段...
}
Flyway è¿ç§»èæ¬
-- V{n}__{description}.sql
-- ä½è
: CX
-- æ¥æ: {date}
-- æè¿°: {description}
CREATE TABLE {table_name} (
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主é®ID',
name VARCHAR(100) NOT NULL COMMENT 'åç§°',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´',
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'æ´æ°æ¶é´'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='{表æè¿°}';
å½åè§è
| ä½ç½® | è§è | ç¤ºä¾ |
|---|---|---|
| å å | å°å | com.taichu.yingjiguanli.modules.user |
| ç±»å | PascalCase | UserController, UserService |
| æ¹æ³å | camelCase | findById, createUser |
| åéå | camelCase | userName, createdAt |
| 常éå | UPPER_SNAKE | MAX_PAGE_SIZE |
| 表å | snake_case | sys_user, t_order |
| åæ®µå | snake_case | user_name, created_at |
æä½³å®è·µ
- ç»ä¸ååº: æææ¥å£è¿å
ApiResponse<T> - ä¸å¡å¼å¸¸: 使ç¨
BusinessExceptionæåºä¸å¡é误 - åæ°æ ¡éª: 使ç¨
@Valid+jakarta.validation - æ¥å¿è®°å½: å
³é®æä½ä½¿ç¨
@Slf4jè®°å½æ¥å¿ - äºå¡ç®¡ç: Service å±ä½¿ç¨
@Transactional - ä¸ææ³¨é: ææç±»ãæ¹æ³ãåæ®µå¿ é¡»æä¸ææ³¨é
项ç®: åºæ¥ç®¡çç³»ç» (yingjiguanli) ææ¯æ : Spring Boot 4.0.1 + JPA + MySQL 8