Spring Boot完全指南:从入门到精通的实践之路

管理员
## 目录 1. [引言:为什么选择Spring Boot](#引言为什么选择spring-boot) 2. [Spring Boot基础入门](#spring-boot基础入门) 3. [核心注解深度解析](#核心注解深度解析) 4. [自动配置原理](#自动配置原理) 5. [Web开发实战](#web开发实战) 6. [数据访问与持久化](#数据访问与持久化) 7. [安全认证与授权](#安全认证与授权) 8. [缓存与性能优化](#缓存与性能优化) 9. [消息队列集成](#消息队列集成) 10. [测试与监控](#测试与监控) 11. [生产环境部署](#生产环境部署) 12. [微服务架构](#微服务架构) 13. [最佳实践与设计模式](#最佳实践与设计模式) 14. [常见问题与解决方案](#常见问题与解决方案) 15. [总结](#总结) --- ## 引言:为什么选择Spring Boot ### Spring Boot的核心价值 Spring Boot通过约定优于配置的理念,极大地简化了Spring应用的开发、部署和运维。 ```java /** * Spring Boot的核心优势 */ public class SpringBootAdvantages { /** * 1. 快速开发 * * - 自动配置:无需手动配置繁琐的Spring XML * - 起步依赖:简化依赖管理 * - 内嵌服务器:无需部署Web服务器 * - 热部署:提升开发效率 */ /** * 2. 生产就绪 * * - 健康检查:/actuator/health端点 * - 监控指标:/actuator/metrics端点 * - 外部配置:application.yml配置 * - 日志管理:Logback默认集成 */ /** * 3. 开箱即用 * * - 自动配置组件:JPA、Redis、RabbitMQ等 * - 丰富的starter:满足各种场景需求 * - 生产特性:监控、度量、安全等 */ /** * 4. 微服务友好 * * - 轻量级:适合微服务架构 * - 可独立部署:每个服务独立运行 * - 云原生:支持Docker、K8s * - 服务发现:支持Eureka、Consul */ } ``` ### Spring Boot vs 传统Spring ```java /** * Spring Boot vs 传统Spring对比 */ public class SpringBootVsTraditionalSpring { /** * 传统Spring开发 * * 需要配置的内容: * 1. DispatcherServlet配置 * 2. ViewResolver配置 * 3. DataSource配置 * 4. TransactionManager配置 * 5. EntityManagerFactory配置 * 6. 组件扫描配置 * 7. ...大量XML配置 */ /** * Spring Boot开发 * * 需要配置的内容: * 1. 添加spring-boot-starter-web依赖 * 2. 配置application.yml数据源 * 3. 编写业务代码 * * 其他全部自动配置! */ } ``` ### Spring Boot应用场景 ```java /** * Spring Boot典型应用场景 */ public class SpringBootUseCases { /** * 1. Web应用 * - 企业官网 * - 管理后台 * - RESTful API */ /** * 2. 微服务 * - 用户服务 * - 订单服务 * - 支付服务 */ /** * 3. 批处理应用 * - 数据同步 * - 定时任务 * - 报表生成 */ /** * 4. 实时应用 * - WebSocket推送 * - 消息队列消费 * - 流数据处理 */ } ``` --- ## Spring Boot基础入门 ### 1. 项目创建 #### 1.1 使用Spring Initializr创建项目 ```bash # 方式1:使用在线工具 # 访问 https://start.spring.io/ # 选择: # - Project: Maven # - Language: Java # - Spring Boot: 2.7.0 # - Project Metadata: 填写项目信息 # - Dependencies: 添加需要的依赖 # 方式2:使用命令行 curl https://start.spring.io/starter.zip \ -d dependencies=web,data-jpa,h2,actuator \ -d type=maven-project \ -d language=java \ -d bootVersion=2.7.0 \ -d baseDir=my-springboot-app \ -o my-springboot-app.zip unzip my-springboot-app.zip cd my-springboot-app ``` #### 1.2 项目结构说明 ``` my-springboot-app/ ├── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── com/example/demo/ │ │ │ ├── DemoApplication.java # 主程序入口 │ │ │ ├── controller/ # 控制器层 │ │ │ ├── service/ # 服务层 │ │ │ ├── repository/ # 数据访问层 │ │ │ ├── model/ # 实体类 │ │ │ ├── dto/ # 数据传输对象 │ │ │ ├── config/ # 配置类 │ │ │ └── exception/ # 异常处理 │ │ └── resources/ │ │ ├── application.yml # 主配置文件 │ │ ├── application-dev.yml # 开发环境配置 │ │ ├── application-prod.yml # 生产环境配置 │ │ ├── static/ # 静态资源 │ │ ├── templates/ # 模板文件 │ │ └── logback.xml # 日志配置 │ └── test/ │ └── java/ │ └── com/example/demo/ │ └── DemoApplicationTests.java # 测试类 ├── pom.xml # Maven配置文件 └── .gitignore # Git忽略文件 ``` #### 1.3 主程序入口 ```java package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * Spring Boot应用主程序 * * @SpringBootApplication注解包含: * 1. @Configuration: 标识为配置类 * 2. @ComponentScan: 自动扫描组件 * 3. @EnableAutoConfiguration: 启用自动配置 */ @SpringBootApplication public class DemoApplication { public static void main(String[] args) { // 启动Spring Boot应用 SpringApplication.run(DemoApplication.class, args); } } ``` ### 2. 配置文件详解 #### 2.1 application.yml配置 ```yaml # application.yml - 主配置文件 # 服务器配置 server: port: 8080 # 服务端口 servlet: context-path: /api # 上下文路径 compression: enabled: true # 启用压缩 mime-types: application/json,application/xml,text/html,text/xml,text/plain tomcat: max-threads: 200 # 最大线程数 min-spare-threads: 10 # 最小空闲线程 # Spring配置 spring: application: name: demo-application # 应用名称 # 环境配置 profiles: active: dev # 激活的配置文件 # 数据源配置 datasource: url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8 username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver hikari: maximum-pool-size: 20 # 最大连接池大小 minimum-idle: 5 # 最小空闲连接 connection-timeout: 30000 # 连接超时时间 idle-timeout: 600000 # 空闲超时时间 max-lifetime: 1800000 # 连接最大生命周期 # JPA配置 jpa: database-platform: org.hibernate.dialect.MySQL8Dialect hibernate: ddl-auto: update # 自动创建/更新表结构 show-sql: true # 显示SQL语句 properties: hibernate: format_sql: true # 格式化SQL use_sql_comments: true # 显示SQL注释 # Redis配置 redis: host: localhost port: 6379 password: database: 0 lettuce: pool: max-active: 8 max-idle: 8 min-idle: 0 max-wait: -1ms # 缓存配置 cache: type: redis redis: time-to-live: 3600000 # 缓存过期时间(毫秒) cache-null-values: false # 是否缓存null值 # Actuator配置 management: endpoints: web: exposure: include: health,info,metrics,prometheus # 暴露的端点 base-path: /actuator endpoint: health: show-details: always # 日志配置 logging: level: root: INFO com.example.demo: DEBUG pattern: console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n" file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n" file: name: logs/application.log ``` #### 2.2 多环境配置 ```yaml # application-dev.yml - 开发环境 spring: datasource: url: jdbc:mysql://localhost:3306/demo_dev username: root password: root redis: host: localhost port: 6379 logging: level: root: DEBUG # application-prod.yml - 生产环境 spring: datasource: url: jdbc:mysql://prod-db.example.com:3306/demo_prod username: ${DB_USERNAME} password: ${DB_PASSWORD} redis: host: redis-prod.example.com port: 6379 password: ${REDIS_PASSWORD} logging: level: root: INFO file: name: /var/log/demo/application.log ``` #### 2.3 自定义配置 ```java /** * 自定义配置类 */ @Component @ConfigurationProperties(prefix = "app") @Data // 需要添加Lombok依赖 public class AppConfig { /** * 应用配置 */ private String name; private String version; private String description; /** * 业务配置 */ private Business business; @Data public static class Business { private int maxPageSize; private long cacheExpireTime; private List allowedOrigins; } } ``` ```yaml # application.yml app: name: Demo Application version: 1.0.0 description: Spring Boot Demo Application business: max-page-size: 100 cache-expire-time: 3600 allowed-origins: - http://localhost:3000 - http://localhost:8080 ``` ```java /** * 使用自定义配置 */ @Service @RequiredArgsConstructor public class ConfigService { private final AppConfig appConfig; public void printConfig() { System.out.println("App Name: " + appConfig.getName()); System.out.println("Max Page Size: " + appConfig.getBusiness().getMaxPageSize()); } } ``` --- ## 核心注解深度解析 ### 1. 核心注解 #### 1.1 @SpringBootApplication ```java /** * @SpringBootApplication注解解析 * * 这是Spring Boot的核心注解,由三个注解组成: * 1. @SpringBootConfiguration * 2. @EnableAutoConfiguration * 3. @ComponentScan */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { /** * 指定要扫描的包 */ @AliasFor(annotation = ComponentScan.class, attribute = "basePackages") String[] scanBasePackages() default {}; /** * 指定要扫描的类 */ @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses") Class[] scanBasePackageClasses() default {}; /** * 排除自动配置类 */ @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude") Class[] exclude() default {}; /** * 排除自动配置类(按类名) */ @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName") String[] excludeName() default {}; } ``` #### 1.2 @Configuration ```java /** * @Configuration注解解析 * * 标识一个类为配置类,相当于传统的XML配置文件 */ @Configuration public class DataSourceConfig { /** * 配置数据源 */ @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource dataSource() { return DataSourceBuilder.create().build(); } /** * 配置JPA EntityManagerFactory */ @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory( DataSource dataSource) { LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); emf.setDataSource(dataSource); emf.setPackagesToScan("com.example.demo.model"); emf.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); return emf; } } ``` #### 1.3 @Bean ```java /** * @Bean注解解析 * * 用于声明一个方法返回的对象要被Spring容器管理 */ @Configuration public class AppConfig { /** * 默认情况下,Bean的名称为方法名 */ @Bean public UserService userService() { return new UserService(); } /** * 指定Bean的名称 */ @Bean("customUserService") public UserService customUserService() { return new UserService(); } /** * 指定Bean的初始化和销毁方法 */ @Bean(initMethod = "init", destroyMethod = "destroy") public ConnectionPool connectionPool() { return new ConnectionPool(); } /** * 依赖注入其他Bean */ @Bean public UserRestController userRestController(UserService userService) { UserRestController controller = new UserRestController(); controller.setUserService(userService); return controller; } /** * 条件化创建Bean */ @Bean @ConditionalOnProperty(name = "cache.enabled", havingValue = "true") public CacheManager cacheManager() { return new SimpleCacheManager(); } /** * 按顺序创建Bean */ @Bean @DependsOn("databaseInitializer") public ApplicationRunner applicationRunner() { return new ApplicationRunner(); } } ``` #### 1.4 @Component及其衍生注解 ```java /** * @Component及其衍生注解 * * 这些注解用于标识一个类为Spring组件,会被自动扫描并注册为Bean */ /** * @Component: 通用的组件注解 */ @Component public class EmailValidator { public boolean isValid(String email) { return email != null && email.contains("@"); } } /** * @Service: 标识服务层组件 */ @Service public class UserService { public User getUserById(Long id) { // 业务逻辑 return null; } } /** * @Repository: 标识数据访问层组件 * * 特殊功能: * 1. 将持久层异常转换为Spring的DataAccessException * 2. 支持事务管理 */ @Repository public interface UserRepository extends JpaRepository { User findByUsername(String username); } /** * @Controller: 标识控制器层组件 */ @Controller @RequestMapping("/users") public class UserController { @GetMapping public String listUsers(Model model) { model.addAttribute("users", userService.findAll()); return "users/list"; } } /** * @RestController: 标识REST控制器 * * 等价于 @Controller + @ResponseBody */ @RestController @RequestMapping("/api/users") public class UserRestController { @GetMapping public List listUsers() { return userService.findAll(); } } ``` #### 1.5 @Autowired ```java /** * @Autowired注解解析 * * 用于自动装配Bean,可以标记在字段、构造方法、setter方法上 */ @RestController @RequestMapping("/api/users") public class UserRestController { /** * 方式1: 字段注入(不推荐) * * 缺点: * - 无法设置为final * - 容易空指针 * - 不便于单元测试 */ @Autowired private UserService userService; /** * 方式2: Setter注入(不推荐) */ private UserService userService; @Autowired public void setUserService(UserService userService) { this.userService = userService; } /** * 方式3: 构造器注入(推荐) * * 优点: * - 可以设置为final * - 保证依赖不可变 * - 便于单元测试 */ private final UserService userService; @Autowired public UserRestController(UserService userService) { this.userService = userService; } /** * 方式4: Lombok简化构造器注入 * * 等价于上面的构造器注入 */ @RestController @RequiredArgsConstructor public class UserRestController { private final UserService userService; } } ``` ### 2. Web注解 #### 2.1 @RestController和@RequestMapping ```java /** * @RestController注解 * * 组合注解,等价于 @Controller + @ResponseBody * 用于标识RESTful API控制器 */ @RestController @RequestMapping("/api/v1") public class UserRestController { /** * @RequestMapping: 通用请求映射 */ @RequestMapping(value = "/users", method = RequestMethod.GET) public List getUsers() { return userService.findAll(); } /** * @GetMapping: GET请求映射 */ @GetMapping("/users/{id}") public User getUser(@PathVariable Long id) { return userService.findById(id); } /** * @PostMapping: POST请求映射 */ @PostMapping("/users") public User createUser(@RequestBody User user) { return userService.save(user); } /** * @PutMapping: PUT请求映射 */ @PutMapping("/users/{id}") public User updateUser(@PathVariable Long id, @RequestBody User user) { return userService.update(id, user); } /** * @DeleteMapping: DELETE请求映射 */ @DeleteMapping("/users/{id}") public void deleteUser(@PathVariable Long id) { userService.delete(id); } } ``` #### 2.2 @PathVariable和@RequestParam ```java /** * 路径变量和请求参数 */ @RestController @RequestMapping("/api/v1/users") public class UserRestController { /** * @PathVariable: 路径变量 * * 从URL路径中提取参数 */ @GetMapping("/{id}") public User getUser(@PathVariable Long id) { return userService.findById(id); } /** * @RequestParam: 请求参数 * * 从URL查询参数中提取参数 */ @GetMapping public Page searchUsers( @RequestParam(required = false) String name, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size) { Pageable pageable = PageRequest.of(page, size); return userService.search(name, pageable); } /** * @RequestBody: 请求体 * * 从请求体中提取JSON数据 */ @PostMapping public User createUser(@RequestBody @Valid UserCreateRequest request) { return userService.create(request); } /** * @RequestHeader: 请求头 */ @GetMapping("/profile") public User getProfile(@RequestHeader("Authorization") String token) { return userService.getByToken(token); } /** * @CookieValue: Cookie值 */ @GetMapping("/session") public String getSession(@CookieValue("JSESSIONID") String sessionId) { return sessionId; } } ``` #### 2.3 @Valid和验证注解 ```java /** * 请求体验证 */ @Data public class UserCreateRequest { /** * @NotNull: 不能为null */ @NotNull(message = "用户名不能为空") /** * @NotBlank: 不能为空白字符串 */ @NotBlank(message = "用户名不能为空") /** * @Size: 字符串长度限制 */ @Size(min = 3, max = 20, message = "用户名长度必须在3-20之间") private String username; /** * @Email: 必须是有效的邮箱格式 */ @Email(message = "邮箱格式不正确") @NotBlank(message = "邮箱不能为空") private String email; /** * @Min: 最小值 * @Max: 最大值 */ @Min(value = 18, message = "年龄必须大于18岁") @Max(value = 120, message = "年龄必须小于120岁") private Integer age; /** * @Pattern: 正则表达式验证 */ @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确") private String phone; /** * @Past: 必须是过去的日期 */ @Past(message = "生日必须是过去的日期") private LocalDateTime birthday; } /** * 控制器中使用验证 */ @RestController @RequestMapping("/api/v1/users") public class UserRestController { @PostMapping public ResponseEntity createUser( @RequestBody @Valid UserCreateRequest request) { User user = userService.create(request); return ResponseEntity.ok(user); } /** * 统一异常处理 */ @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity handleValidationException( MethodArgumentNotValidException ex) { List errors = ex.getBindingResult() .getFieldErrors() .stream() .map(error -> error.getField() + ": " + error.getDefaultMessage()) .collect(Collectors.toList()); ErrorResponse errorResponse = ErrorResponse.builder() .code("VALIDATION_ERROR") .message("参数验证失败") .errors(errors) .timestamp(LocalDateTime.now()) .build(); return ResponseEntity.badRequest().body(errorResponse); } } ``` --- ## 自动配置原理 ### 1. 自动配置机制 ```java /** * Spring Boot自动配置原理 * * 自动配置通过以下机制实现: * 1. @EnableAutoConfiguration注解 * 2. @Import(AutoConfigurationImportSelector.class) * 3. 读取META-INF/spring.factories配置文件 * 4. 根据条件注决定是否加载配置 */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class[] exclude() default {}; String[] excludeName() default {}; } /** * AutoConfigurationImportSelector * * 负责加载自动配置类 */ public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } /** * 加载自动配置类 */ protected AutoConfigurationEntry getAutoConfigurationEntry( AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return EMPTY_ENTRY; } AnnotationAttributes attributes = getAttributes(annotationMetadata); // 加载所有候选配置类 List configurations = getCandidateConfigurations( annotationMetadata, attributes ); // 去重 configurations = removeDuplicates(configurations); // 排除不需要的配置 Set exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); // 过滤掉不满足条件的配置 configurations = getConfigurationClassFilter() .filter(configurations); // 触发自动配置事件 fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationEntry(configurations, exclusions); } } ``` ### 2. 条件注解 ```java /** * 条件注解详解 * * 条件注解用于控制Bean是否被创建 */ @Configuration public class ConditionalConfiguration { /** * @ConditionalOnClass: 类路径下存在指定类时才创建Bean */ @Bean @ConditionalOnClass(name = "redis.clients.jedis.Jedis") public RedisTemplate redisTemplate() { return new RedisTemplate<>(); } /** * @ConditionalOnMissingBean: 容器中不存在指定Bean时才创建Bean */ @Bean @ConditionalOnMissingBean(DataSource.class) public DataSource dataSource() { return DataSourceBuilder.create().build(); } /** * @ConditionalOnProperty: 配置文件中存在指定属性时才创建Bean */ @Bean @ConditionalOnProperty( prefix = "cache", name = "enabled", havingValue = "true", matchIfMissing = true ) public CacheManager cacheManager() { return new SimpleCacheManager(); } /** * @ConditionalOnBean: 容器中存在指定Bean时才创建Bean */ @Bean @ConditionalOnBean(DataSource.class) public JdbcTemplate jdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } /** * @ConditionalOnWebApplication: Web应用环境才创建Bean */ @Bean @ConditionalOnWebApplication public WebMvcConfigurer webMvcConfigurer() { return new WebMvcConfigurer() {}; } /** * @ConditionalOnExpression: SpEL表达式为true时才创建Bean */ @Bean @ConditionalOnExpression("'${app.mode}' == 'dev' or '${app.mode}' == 'test'") public DevToolsService devToolsService() { return new DevToolsService(); } /** * 自定义条件注解 */ @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Conditional(FeatureEnabledCondition.class) public @interface ConditionalOnFeatureEnabled { String value(); } /** * 自定义条件实现 */ public static class FeatureEnabledCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { // 获取注解属性 String feature = (String) metadata.getAnnotationAttributes( ConditionalOnFeatureEnabled.class.getName() ).get("value"); // 获取环境变量 Environment environment = context.getEnvironment(); // 检查功能是否启用 return environment.getProperty( "app.features." + feature + ".enabled", Boolean.class, false ); } } } ``` ### 3. 自定义自动配置 ```java /** * 自定义自动配置示例 * * 创建自己的Starter模块 */ @Configuration @ConditionalOnClass(MyService.class) @EnableConfigurationProperties(MyServiceProperties.class) public class MyServiceAutoConfiguration { private final MyServiceProperties properties; public MyServiceAutoConfiguration(MyServiceProperties properties) { this.properties = properties; } /** * 创建MyService Bean */ @Bean @ConditionalOnMissingBean public MyService myService() { MyService service = new MyService(); service.setConfig(properties.getConfig()); service.setEnabled(properties.isEnabled()); return service; } } /** * 配置属性类 */ @ConfigurationProperties(prefix = "my.service") @Data public class MyServiceProperties { private boolean enabled = true; private String config; private int timeout = 5000; } /** * META-INF/spring.factories配置文件 * * org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ * com.example.myservice.autoconfigure.MyServiceAutoConfiguration */ ``` --- ## Web开发实战 ### 1. RESTful API开发 #### 1.1 控制器设计 ```java /** * RESTful API控制器最佳实践 */ @RestController @RequestMapping("/api/v1/users") @RequiredArgsConstructor public class UserRestController { private final UserService userService; /** * GET /api/v1/users - 获取用户列表 */ @GetMapping public ResponseEntity> getUsers( @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size, @RequestParam(required = false) String keyword) { Pageable pageable = PageRequest.of(page, size); Page users = userService.searchUsers(keyword, pageable); return ResponseEntity.ok(users); } /** * GET /api/v1/users/{id} - 获取用户详情 */ @GetMapping("/{id}") public ResponseEntity getUser(@PathVariable Long id) { UserDTO user = userService.getUserById(id); return ResponseEntity.ok(user); } /** * POST /api/v1/users - 创建用户 */ @PostMapping public ResponseEntity createUser( @RequestBody @Valid UserCreateRequest request) { UserDTO user = userService.createUser(request); URI location = ServletUriComponentsBuilder .fromCurrentRequest() .path("/{id}") .buildAndExpand(user.getId()) .toUri(); return ResponseEntity.created(location).body(user); } /** * PUT /api/v1/users/{id} - 更新用户 */ @PutMapping("/{id}") public ResponseEntity updateUser( @PathVariable Long id, @RequestBody @Valid UserUpdateRequest request) { UserDTO user = userService.updateUser(id, request); return ResponseEntity.ok(user); } /** * DELETE /api/v1/users/{id} - 删除用户 */ @DeleteMapping("/{id}") @ResponseStatus(HttpStatus.NO_CONTENT) public void deleteUser(@PathVariable Long id) { userService.deleteUser(id); } /** * PATCH /api/v1/users/{id}/status - 部分更新 */ @PatchMapping("/{id}/status") public ResponseEntity updateUserStatus( @PathVariable Long id, @RequestBody @Valid UserStatusUpdateRequest request) { UserDTO user = userService.updateUserStatus(id, request); return ResponseEntity.ok(user); } } ``` #### 1.2 统一响应格式 ```java /** * 统一响应DTO */ @Data @Builder @NoArgsConstructor @AllArgsConstructor public class ApiResponse { /** * 响应码 */ private String code; /** * 响应消息 */ private String message; /** * 响应数据 */ private T data; /** * 时间戳 */ private LocalDateTime timestamp; /** * 成功响应 */ public static ApiResponse success(T data) { return ApiResponse.builder() .code("SUCCESS") .message("操作成功") .data(data) .timestamp(LocalDateTime.now()) .build(); } /** * 失败响应 */ public static ApiResponse error(String code, String message) { return ApiResponse.builder() .code(code) .message(message) .timestamp(LocalDateTime.now()) .build(); } } /** * 统一响应处理器 */ @RestControllerAdvice public class ResponseAdvice implements ResponseBodyAdvice { @Override public boolean supports(MethodParameter returnType, Class> converterType) { // 排除ApiResponse类型,避免重复包装 return !returnType.getParameterType().equals(ApiResponse.class); } @Override public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { // 处理void返回类型 if (body == null) { return ApiResponse.success(null); } // 包装响应 return ApiResponse.success(body); } } ``` #### 1.3 全局异常处理 ```java /** * 全局异常处理器 */ @RestControllerAdvice @Slf4j public class GlobalExceptionHandler { /** * 业务异常 */ @ExceptionHandler(BusinessException.class) public ResponseEntity> handleBusinessException( BusinessException ex) { log.error("业务异常: {}", ex.getMessage()); return ResponseEntity .status(HttpStatus.BAD_REQUEST) .body(ApiResponse.error(ex.getCode(), ex.getMessage())); } /** * 参数验证异常 */ @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity>> handleValidationException( MethodArgumentNotValidException ex) { Map errors = new HashMap<>(); ex.getBindingResult().getFieldErrors().forEach(error -> { errors.put(error.getField(), error.getDefaultMessage()); }); log.error("参数验证异常: {}", errors); return ResponseEntity .status(HttpStatus.BAD_REQUEST) .body(ApiResponse.error("VALIDATION_ERROR", "参数验证失败")); } /** * 资源不存在异常 */ @ExceptionHandler(NoSuchElementException.class) public ResponseEntity> handleNotFoundException( NoSuchElementException ex) { log.error("资源不存在: {}", ex.getMessage()); return ResponseEntity .status(HttpStatus.NOT_FOUND) .body(ApiResponse.error("NOT_FOUND", "资源不存在")); } /** * 权限不足异常 */ @ExceptionHandler(AccessDeniedException.class) public ResponseEntity> handleAccessDeniedException( AccessDeniedException ex) { log.error("权限不足: {}", ex.getMessage()); return ResponseEntity .status(HttpStatus.FORBIDDEN) .body(ApiResponse.error("FORBIDDEN", "权限不足")); } /** * 系统异常 */ @ExceptionHandler(Exception.class) public ResponseEntity> handleException(Exception ex) { log.error("系统异常: ", ex); return ResponseEntity .status(HttpStatus.INTERNAL_SERVER_ERROR) .body(ApiResponse.error("SYSTEM_ERROR", "系统异常,请联系管理员")); } } ``` ### 2. 模板引擎集成 #### 2.1 Thymeleaf集成 ```java /** * Thymeleaf模板引擎配置 */ @Configuration public class ThymeleafConfig { /** * 配置Thymeleaf视图解析器 */ @Bean public SpringResourceTemplateResolver templateResolver() { SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); resolver.setPrefix("classpath:/templates/"); resolver.setSuffix(".html"); resolver.setTemplateMode(TemplateMode.HTML); resolver.setCharacterEncoding("UTF-8"); resolver.setCacheable(false); // 开发环境关闭缓存 return resolver; } /** * 配置Thymeleaf模板引擎 */ @Bean public SpringTemplateEngine templateEngine( SpringResourceTemplateResolver templateResolver) { SpringTemplateEngine engine = new SpringTemplateEngine(); engine.setTemplateResolver(templateResolver); engine.setEnableSpringELCompiler(true); return engine; } /** * 配置Thymeleaf视图解析器 */ @Bean public ThymeleafViewResolver thymeleafViewResolver( SpringTemplateEngine templateEngine) { ThymeleafViewResolver resolver = new ThymeleafViewResolver(); resolver.setTemplateEngine(templateEngine); resolver.setCharacterEncoding("UTF-8"); resolver.setContentType("text/html;charset=UTF-8"); return resolver; } } ``` ```java /** * Thymeleaf控制器 */ @Controller @RequestMapping("/users") public class UserViewController { @Autowired private UserService userService; /** * 用户列表页面 */ @GetMapping public String listUsers( @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size, Model model) { Pageable pageable = PageRequest.of(page, size); Page users = userService.findAll(pageable); model.addAttribute("users", users); model.addAttribute("page", page); model.addAttribute("size", size); return "users/list"; } /** * 用户详情页面 */ @GetMapping("/{id}") public String getUser(@PathVariable Long id, Model model) { User user = userService.findById(id); model.addAttribute("user", user); return "users/detail"; } } ``` ```html 用户列表

用户列表

ID 用户名 邮箱 操作
1 张三 zhangsan@example.com 详情
1
``` --- ## 数据访问与持久化 ### 1. Spring Data JPA #### 1.1 实体类定义 ```java /** * 用户实体类 */ @Entity @Table(name = "users") @Data @NoArgsConstructor @AllArgsConstructor @Builder public class User { /** * 主键 */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; /** * 用户名 */ @Column(nullable = false, unique = true, length = 50) private String username; /** * 密码 */ @Column(nullable = false, length = 100) private String password; /** * 邮箱 */ @Column(nullable = false, unique = true, length = 100) private String email; /** * 手机号 */ @Column(length = 20) private String phone; /** * 年龄 */ @Column private Integer age; /** * 性别 */ @Enumerated(EnumType.STRING) @Column(length = 10) private Gender gender; /** * 状态 */ @Enumerated(EnumType.STRING) @Column(length = 20) private UserStatus status; /** * 创建时间 */ @Column(name = "created_at", nullable = false, updatable = false) @CreationTimestamp private LocalDateTime createdAt; /** * 更新时间 */ @Column(name = "updated_at") @UpdateTimestamp private LocalDateTime updatedAt; /** * 是否删除 */ @Column(name = "deleted", nullable = false) @Builder.Default private Boolean deleted = false; } /** * 性别枚举 */ public enum Gender { MALE, FEMALE } /** * 用户状态枚举 */ public enum UserStatus { ACTIVE, INACTIVE, BANNED, PENDING } ``` #### 1.2 Repository定义 ```java /** * 用户Repository接口 */ @Repository public interface UserRepository extends JpaRepository, JpaSpecificationExecutor { /** * 根据用户名查找用户 */ Optional findByUsername(String username); /** * 根据邮箱查找用户 */ Optional findByEmail(String email); /** * 根据状态查找用户 */ List findByStatus(UserStatus status); /** * 根据状态和年龄查找用户 */ List findByStatusAndAgeGreaterThan(UserStatus status, Integer age); /** * 根据用户名或邮箱查找用户 */ Optional findByUsernameOrEmail(String username, String email); /** * 查找活跃用户并按创建时间排序 */ List findByStatusOrderByCreatedAtDesc(UserStatus status); /** * 根据用户名模糊查询 */ List findByUsernameContaining(String keyword); /** * 查找用户数量 */ long countByStatus(UserStatus status); /** * 检查用户名是否存在 */ boolean existsByUsername(String username); /** * 自定义查询 - 使用@Query */ @Query("SELECT u FROM User u WHERE u.username LIKE %:keyword% OR u.email LIKE %:keyword%") List searchByKeyword(@Param("keyword") String keyword); /** * 自定义查询 - 原生SQL */ @Query(value = "SELECT * FROM users WHERE status = ?1 ORDER BY created_at DESC", nativeQuery = true) List findActiveUsers(String status); /** * 自定义查询 - 分页 */ @Query("SELECT u FROM User u WHERE u.status = :status") Page findByStatus(@Param("status") UserStatus status, Pageable pageable); /** * 更新查询 - 使用@Modifying */ @Modifying @Query("UPDATE User u SET u.status = :status WHERE u.id = :id") int updateStatus(@Param("id") Long id, @Param("status") UserStatus status); } ``` #### 1.3 Service层实现 ```java /** * 用户服务接口 */ public interface UserService { UserDTO getUserById(Long id); UserDTO createUser(UserCreateRequest request); UserDTO updateUser(Long id, UserUpdateRequest request); void deleteUser(Long id); Page searchUsers(String keyword, Pageable pageable); List getActiveUsers(); boolean existsByUsername(String username); } /** * 用户服务实现 */ @Service @Transactional @RequiredArgsConstructor public class UserServiceImpl implements UserService { private final UserRepository userRepository; private final UserMapper userMapper; @Override @Transactional(readOnly = true) public UserDTO getUserById(Long id) { User user = userRepository.findById(id) .orElseThrow(() -> new BusinessException("用户不存在", "USER_NOT_FOUND")); return userMapper.toDTO(user); } @Override public UserDTO createUser(UserCreateRequest request) { // 检查用户名是否已存在 if (userRepository.existsByUsername(request.getUsername())) { throw new BusinessException("用户名已存在", "USERNAME_EXISTS"); } // 检查邮箱是否已存在 if (userRepository.findByEmail(request.getEmail()).isPresent()) { throw new BusinessException("邮箱已存在", "EMAIL_EXISTS"); } // 创建用户 User user = userMapper.toEntity(request); user.setStatus(UserStatus.ACTIVE); User savedUser = userRepository.save(user); return userMapper.toDTO(savedUser); } @Override public UserDTO updateUser(Long id, UserUpdateRequest request) { User user = userRepository.findById(id) .orElseThrow(() -> new BusinessException("用户不存在", "USER_NOT_FOUND")); // 更新用户信息 if (request.getUsername() != null) { user.setUsername(request.getUsername()); } if (request.getEmail() != null) { user.setEmail(request.getEmail()); } if (request.getPhone() != null) { user.setPhone(request.getPhone()); } if (request.getAge() != null) { user.setAge(request.getAge()); } User updatedUser = userRepository.save(user); return userMapper.toDTO(updatedUser); } @Override public void deleteUser(Long id) { User user = userRepository.findById(id) .orElseThrow(() -> new BusinessException("用户不存在", "USER_NOT_FOUND")); // 软删除 user.setDeleted(true); userRepository.save(user); } @Override @Transactional(readOnly = true) public Page searchUsers(String keyword, Pageable pageable) { Specification spec = (root, query, cb) -> { List predicates = new ArrayList<>(); // 只查询未删除的用户 predicates.add(cb.equal(root.get("deleted"), false)); // 关键字搜索 if (StringUtils.hasText(keyword)) { Predicate usernamePredicate = cb.like(root.get("username"), "%" + keyword + "%"); Predicate emailPredicate = cb.like(root.get("email"), "%" + keyword + "%"); predicates.add(cb.or(usernamePredicate, emailPredicate)); } return cb.and(predicates.toArray(new Predicate[0])); }; Page users = userRepository.findAll(spec, pageable); return users.map(userMapper::toDTO); } @Override @Transactional(readOnly = true) public List getActiveUsers() { List users = userRepository.findByStatus(UserStatus.ACTIVE); return userMapper.toDTOList(users); } @Override @Transactional(readOnly = true) public boolean existsByUsername(String username) { return userRepository.existsByUsername(username); } } ``` --- ## 安全认证与授权 ### 1. Spring Security集成 #### 1.1 安全配置 ```java /** * Spring Security安全配置 */ @Configuration @EnableWebSecurity @RequiredArgsConstructor public class SecurityConfig extends WebSecurityConfigurerAdapter { private final UserDetailsService userDetailsService; private final JwtAuthenticationFilter jwtAuthenticationFilter; /** * 密码编码器 */ @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } /** * 认证管理器 */ @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } /** * 配置安全规则 */ @Override protected void configure(HttpSecurity http) throws Exception { http // 禁用CSRF .csrf().disable() // 配置会话管理 .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() // 配置授权规则 .authorizeRequests() // 公开端点 .antMatchers("/api/v1/auth/**").permitAll() .antMatchers("/api/v1/public/**").permitAll() // Actuator端点 .antMatchers("/actuator/health").permitAll() .antMatchers("/actuator/**").hasRole("ADMIN") // Swagger文档 .antMatchers("/swagger-ui/**", "/swagger-resources/**", "/v3/api-docs/**").permitAll() // 其他请求需要认证 .anyRequest().authenticated() .and() // 添加JWT过滤器 .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) // 异常处理 .exceptionHandling() .authenticationEntryPoint(unauthorizedHandler) .accessDeniedHandler(accessDeniedHandler); } /** * 配置UserDetailsService */ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService) .passwordEncoder(passwordEncoder()); } } ``` #### 1.2 JWT认证实现 ```java /** * JWT工具类 */ @Component @Slf4j public class JwtUtils { @Value("${jwt.secret}") private String jwtSecret; @Value("${jwt.expiration}") private int jwtExpiration; /** * 生成JWT Token */ public String generateJwtToken(Authentication authentication) { UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal(); return Jwts.builder() .setSubject((userPrincipal.getUsername())) .setIssuedAt(new Date()) .setExpiration(new Date((new Date()).getTime() + jwtExpiration)) .signWith(SignatureAlgorithm.HS512, jwtSecret) .compact(); } /** * 从Token中获取用户名 */ public String getUserNameFromJwtToken(String token) { return Jwts.parser() .setSigningKey(jwtSecret) .parseClaimsJws(token) .getBody() .getSubject(); } /** * 验证JWT Token */ public boolean validateJwtToken(String authToken) { try { Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken); return true; } catch (SignatureException e) { log.error("Invalid JWT signature: {}", e.getMessage()); } catch (MalformedJwtException e) { log.error("Invalid JWT token: {}", e.getMessage()); } catch (ExpiredJwtException e) { log.error("JWT token is expired: {}", e.getMessage()); } catch (UnsupportedJwtException e) { log.error("JWT token is unsupported: {}", e.getMessage()); } catch (IllegalArgumentException e) { log.error("JWT claims string is empty: {}", e.getMessage()); } return false; } } /** * JWT认证过滤器 */ @Component @RequiredArgsConstructor public class JwtAuthenticationFilter extends OncePerRequestFilter { private final JwtUtils jwtUtils; private final UserDetailsService userDetailsService; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { try { String jwt = parseJwt(request); if (jwt != null && jwtUtils.validateJwtToken(jwt)) { String username = jwtUtils.getUserNameFromJwtToken(jwt); UserDetails userDetails = userDetailsService.loadUserByUsername(username); UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( userDetails, null, userDetails.getAuthorities()); authentication.setDetails( new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authentication); } } catch (Exception e) { log.error("Cannot set user authentication: {}", e.getMessage()); } filterChain.doFilter(request, response); } private String parseJwt(HttpServletRequest request) { String headerAuth = request.getHeader("Authorization"); if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) { return headerAuth.substring(7); } return null; } } ``` --- ## 缓存与性能优化 ### 1. Spring Cache集成 #### 1.1 缓存配置 ```java /** * Redis缓存配置 */ @Configuration @EnableCaching public class CacheConfig { /** * Redis缓存管理器 */ @Bean public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { // 默认缓存配置 RedisCacheConfiguration defaultConfig = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(1)) .serializeKeysWith(RedisSerializationContext.SerializationPair .fromSerializer(new StringRedisSerializer())) .serializeValuesWith(RedisSerializationContext.SerializationPair .fromSerializer(new GenericJackson2JsonRedisSerializer())) .disableCachingNullValues(); // 针对不同缓存的不同配置 Map cacheConfigurations = new HashMap<>(); cacheConfigurations.put("users", defaultConfig.entryTtl(Duration.ofMinutes(30))); cacheConfigurations.put("products", defaultConfig.entryTtl(Duration.ofHours(2))); return RedisCacheManager.builder(redisConnectionFactory) .cacheDefaults(defaultConfig) .withInitialCacheConfigurations(cacheConfigurations) .build(); } } ``` #### 1.2 缓存使用 ```java /** * 缓存使用示例 */ @Service @RequiredArgsConstructor public class ProductService { private final ProductRepository productRepository; /** * 查询商品(使用缓存) */ @Cacheable(value = "products", key = "#id") public Product getProductById(Long id) { return productRepository.findById(id) .orElseThrow(() -> new BusinessException("商品不存在", "PRODUCT_NOT_FOUND")); } /** * 创建商品(清除缓存) */ @CacheEvict(value = "products", allEntries = true) public Product createProduct(ProductCreateRequest request) { Product product = new Product(); // 设置商品属性 return productRepository.save(product); } /** * 更新商品(清除缓存) */ @CachePut(value = "products", key = "#id") public Product updateProduct(Long id, ProductUpdateRequest request) { Product product = getProductById(id); // 更新商品属性 return productRepository.save(product); } /** * 删除商品(清除缓存) */ @CacheEvict(value = "products", key = "#id") public void deleteProduct(Long id) { productRepository.deleteById(id); } /** * 批量查询商品(使用缓存) */ @Cacheable(value = "products", key = "'all'") public List getAllProducts() { return productRepository.findAll(); } /** * 清除所有商品缓存 */ @CacheEvict(value = "products", allEntries = true) public void clearProductCache() { // 清除所有商品缓存 } } ``` --- ## 消息队列集成 ### 1. RabbitMQ集成 #### 1.1 RabbitMQ配置 ```java /** * RabbitMQ配置 */ @Configuration @EnableRabbit public class RabbitMQConfig { /** * 队列配置 */ @Bean public Queue emailQueue() { return QueueBuilder.durable("email.queue") .withArgument("x-dead-letter-exchange", "email.dlx") .withArgument("x-dead-letter-routing-key", "email.dlq") .build(); } /** * 交换机配置 */ @Bean public TopicExchange emailExchange() { return new TopicExchange("email.exchange"); } /** * 绑定配置 */ @Bean public Binding emailBinding() { return BindingBuilder.bind(emailQueue()) .to(emailExchange()) .with("email.send"); } /** * 死信队列 */ @Bean public Queue deadLetterQueue() { return QueueBuilder.durable("email.dlq").build(); } @Bean public DirectExchange deadLetterExchange() { return new DirectExchange("email.dlx"); } @Bean public Binding deadLetterBinding() { return BindingBuilder.bind(deadLetterQueue()) .to(deadLetterExchange()) .with("email.dlq"); } /** * 消息转换器 */ @Bean public Jackson2JsonMessageConverter messageConverter() { return new Jackson2JsonMessageConverter(); } /** * RabbitMQ模板配置 */ @Bean public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) { RabbitTemplate template = new RabbitTemplate(connectionFactory); template.setMessageConverter(messageConverter()); // 开启强制回调 template.setMandatory(true); // 设置回调 template.setConfirmCallback((correlationData, ack, cause) -> { if (!ack) { log.error("消息发送失败: {}", cause); } }); template.setReturnsCallback(returned -> { log.error("消息路由失败: {}", returned.getMessage()); }); return template; } } ``` #### 1.2 消息发送与接收 ```java /** * 消息生产者 */ @Component @RequiredArgsConstructor public class EmailProducer { private final RabbitTemplate rabbitTemplate; /** * 发送邮件 */ public void sendEmail(EmailMessage emailMessage) { CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString()); rabbitTemplate.convertAndSend( "email.exchange", "email.send", emailMessage, correlationData ); log.info("邮件消息已发送: {}", emailMessage); } } /** * 消息消费者 */ @Component @Slf4j public class EmailConsumer { /** * 消费邮件消息 */ @RabbitListener(queues = "email.queue") public void handleEmailMessage(EmailMessage emailMessage) { try { log.info("收到邮件消息: {}", emailMessage); // 发送邮件 sendEmail(emailMessage); log.info("邮件发送成功: {}", emailMessage); } catch (Exception e) { log.error("邮件发送失败: {}", emailMessage, e); throw new AmqpRejectAndDontRequeueException(e); } } private void sendEmail(EmailMessage message) { // 实际发送邮件逻辑 } } /** * 邮件消息 */ @Data @AllArgsConstructor @NoArgsConstructor public class EmailMessage { private String to; private String subject; private String content; private Map data; } ``` --- ## 测试与监控 ### 1. 单元测试 ```java /** * UserService单元测试 */ @SpringBootTest @ExtendWith(MockitoExtension.class) class UserServiceTest { @Mock private UserRepository userRepository; @Mock private UserMapper userMapper; @InjectMocks private UserServiceImpl userService; @Test void testGetUserById() { // Given Long userId = 1L; User user = User.builder() .id(userId) .username("testuser") .email("test@example.com") .build(); UserDTO userDTO = UserDTO.builder() .id(userId) .username("testuser") .email("test@example.com") .build(); when(userRepository.findById(userId)).thenReturn(Optional.of(user)); when(userMapper.toDTO(user)).thenReturn(userDTO); // When UserDTO result = userService.getUserById(userId); // Then assertNotNull(result); assertEquals(userId, result.getId()); assertEquals("testuser", result.getUsername()); verify(userRepository, times(1)).findById(userId); } @Test void testGetUserById_NotFound() { // Given Long userId = 1L; when(userRepository.findById(userId)).thenReturn(Optional.empty()); // When & Then assertThrows(BusinessException.class, () -> { userService.getUserById(userId); }); } } ``` --- ## 生产环境部署 ### 1. Docker部署 ```dockerfile # Dockerfile FROM openjdk:11-jre-slim # 设置工作目录 WORKDIR /app # 复制jar文件 COPY target/demo-application.jar /app/app.jar # 设置时区 ENV TZ=Asia/Shanghai # 暴露端口 EXPOSE 8080 # 启动应用 ENTRYPOINT ["java", "-jar", "app.jar"] ``` ```yaml # docker-compose.yml version: '3.8' services: mysql: image: mysql:8.0 container_name: demo-mysql environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: demo ports: - "3306:3306" volumes: - mysql-data:/var/lib/mysql redis: image: redis:7-alpine container_name: demo-redis ports: - "6379:6379" volumes: - redis-data:/data rabbitmq: image: rabbitmq:3-management container_name: demo-rabbitmq environment: RABBITMQ_DEFAULT_USER: admin RABBITMQ_DEFAULT_PASS: admin ports: - "5672:5672" - "15672:15672" volumes: - rabbitmq-data:/var/lib/rabbitmq app: build: . container_name: demo-app ports: - "8080:8080" environment: SPRING_PROFILES_ACTIVE: prod SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/demo SPRING_DATASOURCE_USERNAME: root SPRING_DATASOURCE_PASSWORD: root SPRING_REDIS_HOST: redis SPRING_RABBITMQ_HOST: rabbitmq depends_on: - mysql - redis - rabbitmq volumes: mysql-data: redis-data: rabbitmq-data: ``` --- ## 总结 ### 学习路径总结 通过本文的学习,你已经掌握了Spring Boot的完整知识体系: #### 1. 基础阶段 - ✅ 项目创建与配置 - ✅ 核心注解使用 - ✅ 自动配置原理 - ✅ RESTful API开发 #### 2. 进阶阶段 - ✅ 数据访问与持久化 - ✅ 安全认证与授权 - ✅ 缓存与性能优化 - ✅ 消息队列集成 #### 3. 高级阶段 - ✅ 测试与监控 - ✅ 生产环境部署 - ✅ 微服务架构 - ✅ 最佳实践 ### 核心要点回顾 1. **自动配置** - 理解自动配置原理 - 掌握条件注解使用 - 能够自定义Starter 2. **Web开发** - RESTful API设计 - 统一响应格式 - 全局异常处理 3. **数据访问** - JPA实体设计 - Repository使用 - 复杂查询实现 4. **安全认证** - Spring Security配置 - JWT认证实现 - 权限控制 5. **性能优化** - 缓存使用 - 异步处理 - 连接池优化 ### 下一步学习建议 1. **深入源码** - 阅读Spring Boot源码 - 理解启动流程 - 掌握自动配置实现 2. **实战项目** - 构建完整的Spring Boot应用 - 实现微服务架构 - 接入第三方服务 3. **性能调优** - 监控应用性能 - 优化数据库查询 - 提升并发处理能力 4. **架构设计** - 设计高可用架构 - 实现分布式事务 - 构建可扩展系统 掌握Spring Boot,能够快速构建生产级别的Java应用。希望这篇完全指南能帮助你从Spring Boot小白成长为高手!
评论 0

发表评论 取消回复

Shift+Enter 换行  ·  Enter 发送
还没有评论,来发表第一条吧