跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

IntelliJ IDEA 项目配置与 Web 部署完全指南

综述由AI生成IntelliJ IDEA 项目配置与 Web 部署指南涵盖了从环境搭建到生产部署的全流程。内容包括 IDE 基础设置、Maven 与 Gradle 项目管理、Web 模块创建、Tomcat 集成、Spring Boot 框架配置、数据库连接池优化、Docker 容器化部署及 CI/CD 流水线构建。此外还涉及多环境管理、应用监控、性能调优及安全最佳实践,旨在帮助开发者构建高效稳定的企业级 Java Web 应用。

极客零度发布于 2026/2/8更新于 2026/5/319K 浏览

第一部分:IntelliJ IDEA 基础与环境配置

1.1 IntelliJ IDEA 概述与版本选择

IntelliJ IDEA 是 JetBrains 公司开发的 Java 集成开发环境,被公认为当前最智能、最高效的 Java IDE 之一。它提供强大的代码分析、智能提示、重构工具和丰富的插件生态系统。

版本选择策略:
  • Community Edition(社区版):免费开源,支持 Java、Kotlin、Android 开发
  • Ultimate Edition(旗舰版):商业许可,支持 Web 开发、企业框架、数据库工具等

对于 Web 开发,必须选择 Ultimate Edition,因为它包含:

  • 对 JavaScript、TypeScript、HTML、CSS 的深度支持
  • 框架支持(Spring、Spring Boot、Jakarta EE 等)
  • 服务器集成(Tomcat、Jetty、GlassFish 等)
  • 数据库工具和 SQL 支持
1.2 安装与初始配置
安装步骤:
  1. 从 JetBrains 官网下载对应操作系统的安装包
  2. 运行安装程序,选择安装路径
  3. 配置安装选项:
    • 创建桌面快捷方式
    • 关联文件类型(.java、.js 等)
    • 添加到 PATH 环境变量
初始配置优化:
// 配置示例:idea.properties 关键参数
-Xms2048m // 初始堆内存
-Xmx4096m // 最大堆内存
-XX:ReservedCodeCacheSize=512m // 代码缓存大小
-Dsun.io.useCanonCaches=false // 禁用规范缓存
-Djava.net.preferIPv4Stack=true // 优先使用 IPv4
1.3 界面布局与核心概念
项目结构层级:
text
Project (项目) └── Module (模块)
                └── Package (包)
                    └── Class (类)
关键界面区域:
  1. 项目工具窗口(Project Tool Window):显示项目文件结构
  2. 编辑器(Editor):代码编写和查看区域
  3. 导航栏(Navigation Bar):快速定位文件路径
  4. 状态栏(Status Bar):显示项目状态和 IDE 信息
  5. 工具窗口栏(Tool Window Bars):侧面和底部的工具窗口
重要快捷键:
  • :查找操作
Ctrl+Shift+A
  • Ctrl+N:查找类
  • Ctrl+Shift+N:查找文件
  • Ctrl+Alt+L:格式化代码
  • Ctrl+Alt+O:优化导入
  • Shift+F10:运行当前配置
  • Shift+F9:调试当前配置
  • 第二部分:项目创建与配置管理

    2.1 新项目创建流程
    基于 Maven 的项目创建:
    1. 文件 → 新建 → 项目
    2. 选择左侧的 Maven 选项
    3. 配置项目 SDK(Java Development Kit)
    4. 设置 GroupId、ArtifactId、Version
    5. 选择项目存储位置
    <!-- 生成的 pom.xml 示例 -->
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.example</groupId>
      <artifactId>my-web-app</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>war</packaging>
      <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      </properties>
    </project>
    
    基于 Gradle 的项目创建:
    1. 文件 → 新建 → 项目
    2. 选择 Gradle 选项
    3. 配置 DSL(Groovy 或 Kotlin)
    4. 设置 GroupId、ArtifactId、Version
    // build.gradle 示例
    plugins {
      id 'java'
      id 'war'
    }
    group = 'com.example'
    version = '1.0-SNAPSHOT'
    sourceCompatibility = '11'
    repositories {
      mavenCentral()
    }
    dependencies {
      // 依赖配置
    }
    
    2.2 模块化项目结构
    多模块项目配置:
    text
    my-project/
    ├── pom.xml (父 pom)
    ├── my-web-module/
    │   ├── pom.xml
    │   └── src/
    ├── my-service-module/
    │   ├── pom.xml
    │   └── src/
    └── my-dao-module/
        ├── pom.xml
        └── src/
    
    父 pom.xml 配置示例:
    <project>
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.example</groupId>
      <artifactId>my-parent-project</artifactId>
      <version>1.0.0</version>
      <packaging>pom</packaging>
      <modules>
        <module>my-web-module</module>
        <module>my-service-module</module>
        <module>my-dao-module</module>
      </modules>
      <dependencyManagement>
        <dependencies>
          <!-- 统一管理依赖版本 -->
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.23</version>
          </dependency>
        </dependencies>
      </dependencyManagement>
      <build>
        <pluginManagement>
          <!-- 统一管理插件 -->
        </pluginManagement>
      </build>
    </project>
    
    2.3 项目配置详解
    项目结构配置(Project Structure):

    访问方式:文件 → 项目结构 或 Ctrl+Shift+Alt+S

    1. 项目设置:

    • 项目 SDK:指定 Java 版本
    • 语言级别:设置语言特性兼容性
    • 编译器输出路径

    2. 模块设置:

    • 源代码目录标记:
      • Sources:源代码目录(蓝色)
      • Tests:测试代码目录(绿色)
      • Resources:资源文件目录
      • Test Resources:测试资源目录
      • Excluded:排除目录(橙色)

    3. 库管理:

    • 全局库:所有项目可用
    • 项目库:当前项目可用
    • 模块库:特定模块可用

    4. 构面(Facets):

    • 为模块添加特定框架支持
    • 配置框架特定参数
    • 示例:Spring、Web、JPA 等

    5. 工件(Artifacts):

    • 定义项目输出格式
    • 配置打包方式和内容
    • 设置依赖包含策略
    编译器配置:

    访问方式:文件 → 设置 → 构建、执行、部署 → 编译器

    // 推荐的编译器配置:
    {
      "自动构建项目": true,
      "编译独立模块": false,
      "使用外部构建": false,
      "构建进程堆大小": 700,
      "共享构建进程 VM 选项": "-Xmx512m",
      "添加异常断言": true,
      "生成无符号字节码": false,
      "预编译检测注解": true
    }
    
    运行/调试配置:

    访问方式:运行 → 编辑配置 或 Shift+Alt+F10 → 0

    配置模板类型:

    • Application:Java 应用程序
    • Maven:Maven 目标
    • Gradle:Gradle 任务
    • Spring Boot:Spring Boot 应用
    • Tomcat Server:本地 Tomcat 服务器
    • JavaScript Debug:JavaScript 调试

    第三部分:Web 项目配置详解

    3.1 Web 模块创建与配置
    创建 Web 模块:
    1. 文件 → 新建 → 模块
    2. 选择 Java Enterprise
    3. 勾选 Web 应用程序
    4. 选择版本(Jakarta EE 9+ 或 Java EE 8)
    5. 勾选 创建 web.xml
    目录结构:
    text
    web-module/
    ├── src/
    │   └── main/
    │       ├── java/ # Java 源代码
    │       ├── resources/ # 资源文件
    │       └── webapp/ # Web 资源
    │           ├── WEB-INF/
    │           │   ├── web.xml # 部署描述符
    │           │   └── classes/
    │           └── index.jsp # 首页
    └── pom.xml
    
    web.xml 配置示例:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd" version="5.0">
      <display-name>My Web Application</display-name>
      <!-- 上下文参数 -->
      <context-param>
        <param-name>appName</param-name>
        <param-value>MyApplication</param-value>
      </context-param>
      <!-- Servlet 配置 -->
      <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/spring-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <!-- Servlet 映射 -->
      <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
      <!-- 欢迎文件列表 -->
      <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
    </web-app>
    
    3.2 Servlet 容器配置
    内嵌 Servlet 容器配置(Spring Boot):
    // Spring Boot 配置类示例
    @Configuration
    public class ServletConfig {
        @Bean
        public ServletWebServerFactory servletContainer() {
            TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
            tomcat.addAdditionalTomcatConnectors(createSslConnector());
            tomcat.setPort(8443);
            tomcat.setContextPath("/api");
            return tomcat;
        }
        private Connector createSslConnector() {
            Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
            connector.setScheme("https");
            connector.setSecure(true);
            connector.setPort(8443);
            return connector;
        }
    }
    
    3.3 静态资源处理
    Spring MVC 资源映射:
    @Configuration
    @EnableWebMvc
    public class WebConfig implements WebMvcConfigurer {
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/resources/**")
                .addResourceLocations("classpath:/static/", "classpath:/public/")
                .setCachePeriod(3600)
                .resourceChain(true)
                .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
            registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
        }
        @Override
        public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
        }
    }
    
    资源文件组织结构:
    text
    src/main/resources/
    ├── static/ # 静态资源
    │   ├── css/
    │   ├── js/
    │   ├── images/
    │   └── fonts/
    ├── templates/ # 模板文件
    │   ├── thymeleaf/
    │   ├── freemarker/
    │   └── jsp/
    └── application.properties # 配置文件
    

    第四部分:服务器集成与部署配置

    4.1 本地服务器配置
    Tomcat 服务器配置步骤:

    1. 下载和配置 Tomcat:

    • 从 Apache 官网下载 Tomcat
    • 解压到合适目录
    • 配置环境变量(可选)

    2. 在 IDEA 中集成 Tomcat:

    1. 运行 → 编辑配置
    2. 点击 + → Tomcat 服务器 → 本地
    3. 配置服务器:
      • 名称:Local Tomcat
      • 应用程序服务器:选择 Tomcat 安装目录
      • HTTP 端口:8080
      • JMX 端口:1099

    3. 部署配置:

    // Tomcat 部署配置示例
    {
      "服务器配置": {
        "名称": "Local Tomcat",
        "类型": "Tomcat 9.0.x",
        "HTTP 端口": 8080,
        "JMX 端口": 1099,
        "启动前": "构建工件",
        "更新操作": "重新部署",
        "帧延迟": 3000
      },
      "部署": {
        "工件": "my-web-app:war exploded",
        "上下文路径": "/myapp",
        "JRE": "11",
        "VM 选项": "-Xms512m -Xmx1024m -Dspring.profiles.active=dev"
      }
    }
    
    Tomcat 配置详情:

    server.xml 配置示例片段:

    <Server port="8005" shutdown="SHUTDOWN">
      <Service name="Catalina">
        <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" maxThreads="200" minSpareThreads="10" enableLookups="false" acceptCount="100" disableUploadTimeout="true" compression="on" compressionMinSize="1024" compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/json"/>
        <Engine name="Catalina" defaultHost="localhost">
          <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
            <Context path="/myapp" docBase="C:\projects\myapp" reloadable="true" crossContext="true"/>
          </Host>
        </Engine>
      </Service>
    </Server>
    
    4.2 热部署与热交换配置
    配置热部署:

    1. IDEA 设置:

    • 文件 → 设置 → 构建、执行、部署 → 部署
    • 启用 自动上传更改的文件
    • 设置上传间隔:默认 500 毫秒

    2. Spring Boot DevTools 配置:

    <!-- pom.xml 依赖 -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
      <scope>runtime</scope>
      <optional>true</optional>
    </dependency>
    
    # application-dev.properties
    spring.devtools.restart.enabled=true
    spring.devtools.livereload.enabled=true
    spring.devtools.restart.poll-interval=1000
    spring.devtools.restart.quiet-period=400
    spring.devtools.restart.exclude=static/**,public/**
    

    3. JRebel 配置(商业工具):

    • 安装 JRebel 插件
    • 激活许可证
    • 配置自动重新加载
    4.3 多环境部署配置
    配置文件结构:
    text
    src/main/resources/
    ├── application.properties # 主配置
    ├── application-dev.properties # 开发环境
    ├── application-test.properties # 测试环境
    ├── application-prod.properties # 生产环境
    └── config/
        ├── logback-dev.xml # 开发日志配置
        └── logback-prod.xml # 生产日志配置
    
    多环境配置示例:
    // Spring Boot 多环境配置
    @Configuration
    @PropertySource({
      "classpath:application.properties",
      "classpath:application-${spring.profiles.active}.properties"
    })
    public class EnvironmentConfig {
        @Bean
        @Profile("dev")
        public DataSource devDataSource() {
            // 开发环境数据源
        }
        @Bean
        @Profile("prod")
        public DataSource prodDataSource() {
            // 生产环境数据源
        }
    }
    
    运行配置示例:
    // 开发环境运行配置
    {
      "类型": "Spring Boot",
      "名称": "MyApp Dev",
      "主类": "com.example.MyApplication",
      "VM 选项": "-Dspring.profiles.active=dev -Xms512m -Xmx1024m",
      "程序实参": "--server.port=8081",
      "环境变量": "SPRING_PROFILES_ACTIVE=dev;DB_HOST=localhost"
    }
    

    第五部分:框架集成配置

    5.1 Spring/Spring Boot 配置
    Spring Boot 项目创建:
    1. 文件 → 新建 → 项目
    2. 选择 Spring Initializr
    3. 配置项目元数据
    4. 选择依赖:
      • Spring Web
      • Spring Data JPA
      • Spring Security
      • Thymeleaf
      • 等
    application.properties 配置:
    # 服务器配置
    server.port=8080
    server.servlet.context-path=/api
    server.servlet.session.timeout=30m
    server.compression.enabled=true
    server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javascript,application/json
    # 数据库配置
    spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC
    spring.datasource.username=root
    spring.datasource.password=secret
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.hikari.connection-timeout=30000
    spring.datasource.hikari.maximum-pool-size=20
    # JPA 配置
    spring.jpa.hibernate.ddl-auto=update
    spring.jpa.show-sql=true
    spring.jpa.properties.hibernate.format_sql=true
    spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
    # 日志配置
    logging.level.root=INFO
    logging.level.com.example=DEBUG
    logging.file.name=logs/myapp.log
    logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} - %msg%n
    logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
    # 静态资源
    spring.resources.static-locations=classpath:/static/,classpath:/public/,file:./uploads/
    spring.resources.cache.period=3600
    spring.mvc.static-path-pattern=/static/**
    # 上传文件配置
    spring.servlet.multipart.max-file-size=10MB
    spring.servlet.multipart.max-request-size=10MB
    spring.servlet.multipart.enabled=true
    
    Spring 配置类示例:
    @Configuration
    @EnableWebMvc
    @ComponentScan("com.example")
    @EnableTransactionManagement
    @EnableJpaRepositories("com.example.repository")
    @EntityScan("com.example.entity")
    @EnableCaching
    @EnableScheduling
    public class AppConfig implements WebMvcConfigurer {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LogInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/**/static/**", "/error");
        }
        @Bean
        public LocaleResolver localeResolver() {
            SessionLocaleResolver slr = new SessionLocaleResolver();
            slr.setDefaultLocale(Locale.US);
            return slr;
        }
        @Bean
        public MessageSource messageSource() {
            ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
            messageSource.setBasename("messages");
            messageSource.setDefaultEncoding("UTF-8");
            messageSource.setCacheSeconds(3600);
            return messageSource;
        }
        @Bean
        public CacheManager cacheManager() {
            return new ConcurrentMapCacheManager("products", "users");
        }
    }
    
    5.2 数据库配置与连接
    数据源配置:
    @Configuration
    public class DatabaseConfig {
        @Bean
        @Primary
        @ConfigurationProperties(prefix = "spring.datasource")
        public DataSource dataSource() {
            return DataSourceBuilder.create().build();
        }
        @Bean
        public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            EntityManagerFactoryBuilder builder,
            DataSource dataSource) {
            return builder
                .dataSource(dataSource)
                .packages("com.example.entity")
                .persistenceUnit("main")
                .properties(jpaProperties())
                .build();
        }
        @Bean
        public PlatformTransactionManager transactionManager(
            EntityManagerFactory entityManagerFactory) {
            return new JpaTransactionManager(entityManagerFactory);
        }
        private Map<String, Object> jpaProperties() {
            Map<String, Object> props = new HashMap<>();
            props.put("hibernate.hbm2ddl.auto", "validate");
            props.put("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect");
            props.put("hibernate.show_sql", true);
            props.put("hibernate.format_sql", true);
            props.put("hibernate.use_sql_comments", true);
            return props;
        }
        @Bean
        public Flyway flyway(DataSource dataSource) {
            Flyway flyway = Flyway.configure()
                .dataSource(dataSource)
                .locations("classpath:db/migration")
                .baselineOnMigrate(true)
                .outOfOrder(true)
                .validateOnMigrate(true)
                .load();
            flyway.migrate();
            return flyway;
        }
    }
    
    在 IDEA 中配置数据库工具:
    1. 视图 → 工具窗口 → 数据库
    2. 点击 + → 数据源
    3. 选择数据库类型(MySQL、PostgreSQL 等)
    4. 配置连接参数:
      • 主机:localhost
      • 端口:3306
      • 数据库:mydb
      • 用户名/密码
    5. 测试连接
    5.3 安全配置(Spring Security)
    Security 配置类:
    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private UserDetailsService userDetailsService;
        @Autowired
        private JwtAuthenticationEntryPoint unauthorizedHandler;
        @Bean
        public JwtAuthenticationFilter jwtAuthenticationFilter() {
            return new JwtAuthenticationFilter();
        }
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder());
        }
        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .cors()
                .and()
                .csrf()
                .disable()
                .exceptionHandling()
                .authenticationEntryPoint(unauthorizedHandler)
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/", "/favicon.ico", /**/*.png", /**/*.gif", /**/*.svg", /**/*.jpg", /**/*.html", /**/*.css", /**/*.js")
                .permitAll()
                .antMatchers("/api/auth/**")
                .permitAll()
                .antMatchers("/api/user/checkUsernameAvailability", "/api/user/checkEmailAvailability")
                .permitAll()
                .antMatchers(HttpMethod.GET, "/api/polls/**", "/api/users/**")
                .permitAll()
                .anyRequest()
                .authenticated();
            // 添加 JWT 过滤器
            http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
            // 添加 CORS 过滤器
            http.addFilterBefore(corsFilter(), JwtAuthenticationFilter.class);
        }
        @Bean
        public CorsFilter corsFilter() {
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            CorsConfiguration config = new CorsConfiguration();
            config.setAllowCredentials(true);
            config.addAllowedOrigin("http://localhost:3000");
            config.addAllowedHeader("*");
            config.addAllowedMethod("*");
            source.registerCorsConfiguration("/**", config);
            return new CorsFilter(source);
        }
    }
    

    第六部分:构建工具配置

    6.1 Maven 深度配置
    完整 pom.xml 示例:
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.example</groupId>
      <artifactId>my-enterprise-app</artifactId>
      <version>1.0.0-RELEASE</version>
      <packaging>war</packaging>
      <name>My Enterprise Application</name>
      <description>A comprehensive enterprise web application</description>
      <url>http://www.example.com</url>
      <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.4</version>
        <relativePath/>
      </parent>
      <organization>
        <name>Example Inc.</name>
        <url>http://www.example.com</url>
      </organization>
      <licenses>
        <license>
          <name>Apache License, Version 2.0</name>
          <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
          <distribution>repo</distribution>
        </license>
      </licenses>
      <developers>
        <developer>
          <id>dev1</id>
          <name>John Doe</name>
          <email>[email protected]</email>
          <roles>
            <role>architect</role>
            <role>developer</role>
          </roles>
        </developer>
      </developers>
      <properties>
        <java.version>11</java.version>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>${project.reporting.outputEncoding}</project.reporting.outputEncoding>
        <!-- 依赖版本 -->
        <spring.version>5.3.23</spring.version>
        <hibernate.version>5.6.11.Final</hibernate.version>
        <jackson.version>2.13.4</jackson.version>
        <logback.version>1.2.11</logback.version>
        <junit.version>5.9.1</junit.version>
        <!-- 插件版本 -->
        <maven-compiler-plugin.version>3.10.1</maven-compiler-plugin.version>
        <maven-war-plugin.version>3.3.2</maven-war-plugin.version>
        <maven-surefire-plugin.version>3.0.0-M7</maven-surefire-plugin.version>
      </properties>
      <dependencyManagement>
        <dependencies>
          <!-- Spring BOM -->
          <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-framework-bom</artifactId>
            <version>${spring.version}</version>
            <type>pom</type>
            <scope>import</scope>
          </dependency>
          <!-- Jackson BOM -->
          <dependency>
            <groupId>com.fasterxml.jackson</groupId>
            <artifactId>jackson-bom</artifactId>
            <version>${jackson.version}</version>
            <type>pom</type>
            <scope>import</scope>
          </dependency>
        </dependencies>
      </dependencyManagement>
      <dependencies>
        <!-- Spring Boot Starters -->
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <!-- Database -->
        <dependency>
          <groupId>com.mysql</groupId>
          <artifactId>mysql-connector-j</artifactId>
          <scope>runtime</scope>
        </dependency>
        <dependency>
          <groupId>com.h2database</groupId>
          <artifactId>h2</artifactId>
          <scope>test</scope>
        </dependency>
        <!-- Utilities -->
        <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <scope>provided</scope>
        </dependency>
        <dependency>
          <groupId>org.apache.commons</groupId>
          <artifactId>commons-lang3</artifactId>
          <version>3.12.0</version>
        </dependency>
        <dependency>
          <groupId>com.google.guava</groupId>
          <artifactId>guava</artifactId>
          <version>31.1-jre</version>
        </dependency>
        <!-- Testing -->
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
          <exclusions>
            <exclusion>
              <groupId>org.junit.vintage</groupId>
              <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
          </exclusions>
        </dependency>
        <dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-test</artifactId>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>com.tngtech.archunit</groupId>
          <artifactId>archunit-junit5</artifactId>
          <version>1.0.0</version>
          <scope>test</scope>
        </dependency>
        <!-- Dev Tools -->
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-devtools</artifactId>
          <scope>runtime</scope>
          <optional>true</optional>
        </dependency>
      </dependencies>
      <build>
        <finalName>${project.artifactId}-${project.version}</finalName>
        <resources>
          <resource>
            <directory>src/main/resources</directory>
            <filtering>true</filtering>
            <includes>
              <include>**/*.properties</include>
              <include>**/*.xml</include>
              <include>**/*.yml</include>
            </includes>
          </resource>
          <resource>
            <directory>src/main/resources</directory>
            <filtering>false</filtering>
            <excludes>
              <exclude>**/*.properties</exclude>
              <exclude>**/*.xml</exclude>
              <exclude>**/*.yml</exclude>
            </excludes>
          </resource>
        </resources>
        <plugins>
          <!-- Spring Boot Maven Plugin -->
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
              <executable>true</executable>
              <mainClass>com.example.Application</mainClass>
              <layout>WAR</layout>
              <classifier>exec</classifier>
              <excludes>
                <exclude>
                  <groupId>org.projectlombok</groupId>
                  <artifactId>lombok</artifactId>
                </exclude>
              </excludes>
            </configuration>
            <executions>
              <execution>
                <goals>
                  <goal>repackage</goal>
                </goals>
              </execution>
            </executions>
          </plugin>
          <!-- Compiler Plugin -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven-compiler-plugin.version}</version>
            <configuration>
              <source>${java.version}</source>
              <target>${java.version}</target>
              <encoding>${project.build.sourceEncoding}</encoding>
              <annotationProcessorPaths>
                <path>
                  <groupId>org.projectlombok</groupId>
                  <artifactId>lombok</artifactId>
                  <version>${lombok.version}</version>
                </path>
              </annotationProcessorPaths>
              <compilerArgs>
                <arg>-parameters</arg>
              </compilerArgs>
            </configuration>
          </plugin>
          <!-- War Plugin -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <version>${maven-war-plugin.version}</version>
            <configuration>
              <failOnMissingWebXml>false</failOnMissingWebXml>
              <warSourceDirectory>src/main/webapp</warSourceDirectory>
              <warName>${project.artifactId}</warName>
              <outputDirectory>${project.build.directory}</outputDirectory>
              <webResources>
                <resource>
                  <directory>src/main/webapp</directory>
                </resource>
              </webResources>
            </configuration>
          </plugin>
          <!-- Surefire Plugin for Testing -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>${maven-surefire-plugin.version}</version>
            <configuration>
              <skipTests>false</skipTests>
              <includes>
                <include>**/*Test.java</include>
                <include>**/*Tests.java</include>
              </includes>
              <excludes>
                <exclude>**/*IntegrationTest.java</exclude>
                <exclude>**/*IT.java</exclude>
              </excludes>
              <systemPropertyVariables>
                <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
              </systemPropertyVariables>
            </configuration>
          </plugin>
          <!-- JaCoCo for Code Coverage -->
          <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>0.8.8</version>
            <executions>
              <execution>
                <goals>
                  <goal>prepare-agent</goal>
                </goals>
              </execution>
              <execution>
                <id>report</id>
                <phase>test</phase>
                <goals>
                  <goal>report</goal>
                </goals>
              </execution>
              <execution>
                <id>check</id>
                <goals>
                  <goal>check</goal>
                </goals>
                <configuration>
                  <rules>
                    <rule>
                      <element>BUNDLE</element>
                      <limits>
                        <limit>
                          <counter>LINE</counter>
                          <value>COVEREDRATIO</value>
                          <minimum>0.80</minimum>
                        </limit>
                      </limits>
                    </rule>
                  </rules>
                </configuration>
              </execution>
            </executions>
          </plugin>
          <!-- Dependency Plugin for Analysis -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>3.3.0</version>
            <executions>
              <execution>
                <id>analyze</id>
                <goals>
                  <goal>analyze</goal>
                </goals>
                <configuration>
                  <failOnWarning>true</failOnWarning>
                </configuration>
              </execution>
              <execution>
                <id>copy-dependencies</id>
                <phase>package</phase>
                <goals>
                  <goal>copy-dependencies</goal>
                </goals>
                <configuration>
                  <outputDirectory>${project.build.directory}/lib</outputDirectory>
                  <overWriteReleases>false</overWriteReleases>
                  <overWriteSnapshots>false</overWriteSnapshots>
                  <overWriteIfNewer>true</overWriteIfNewer>
                </configuration>
              </execution>
            </executions>
          </plugin>
          <!-- Clean Plugin -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-clean-plugin</artifactId>
            <version>3.2.0</version>
            <configuration>
              <filesets>
                <fileset>
                  <directory>${project.build.directory}</directory>
                  <includes>
                    <include>**/*</include>
                  </includes>
                  <followSymlinks>false</followSymlinks>
                </fileset>
                <fileset>
                  <directory>${basedir}/logs</directory>
                </fileset>
                <fileset>
                  <directory>${basedir}/temp</directory>
                </fileset>
              </filesets>
            </configuration>
          </plugin>
          <!-- Resources Plugin -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>3.3.0</version>
            <configuration>
              <encoding>${project.build.sourceEncoding}</encoding>
              <nonFilteredFileExtensions>
                <nonFilteredFileExtension>pdf</nonFilteredFileExtension>
                <nonFilteredFileExtension>jar</nonFilteredFileExtension>
                <nonFilteredFileExtension>zip</nonFilteredFileExtension>
              </nonFilteredFileExtensions>
            </configuration>
          </plugin>
          <!-- Enforcer Plugin for Rules -->
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-enforcer-plugin</artifactId>
            <version>3.1.0</version>
            <executions>
              <execution>
                <id>enforce-versions</id>
                <goals>
                  <goal>enforce</goal>
                </goals>
                <configuration>
                  <rules>
                    <requireJavaVersion>
                      <version>[11,17)</version>
                    </requireJavaVersion>
                    <requireMavenVersion>
                      <version>[3.6,)</version>
                    </requireMavenVersion>
                    <banDuplicatePomDependencyVersions/>
                    <dependencyConvergence/>
                    <requireReleaseDeps>
                      <message>No Snapshots Allowed!</message>
                    </requireReleaseDeps>
                  </rules>
                </configuration>
              </execution>
            </executions>
          </plugin>
          <!-- Versions Plugin -->
          <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>versions-maven-plugin</artifactId>
            <version>2.13.0</version>
            <configuration>
              <generateBackupPoms>false</generateBackupPoms>
            </configuration>
          </plugin>
        </plugins>
      </build>
      <profiles>
        <profile>
          <id>development</id>
          <activation>
            <activeByDefault>true</activeByDefault>
          </activation>
          <properties>
            <spring.profiles.active>dev</spring.profiles.active>
            <build.profile.id>dev</build.profile.id>
          </properties>
          <build>
            <resources>
              <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
              </resource>
            </resources>
          </build>
        </profile>
        <profile>
          <id>testing</id>
          <properties>
            <spring.profiles.active>test</spring.profiles.active>
            <build.profile.id>test</build.profile.id>
          </properties>
          <build>
            <plugins>
              <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                  <skipTests>false</skipTests>
                  <includes>
                    <include>**/*Test.java</include>
                    <include>**/*Tests.java</include>
                    <include>**/*IT.java</include>
                  </includes>
                </configuration>
              </plugin>
            </plugins>
          </build>
        </profile>
        <profile>
          <id>production</id>
          <properties>
            <spring.profiles.active>prod</spring.profiles.active>
            <build.profile.id>prod</build.profile.id>
          </properties>
          <build>
            <plugins>
              <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                  <executable>true</executable>
                  <jvmArguments>
                    -Xms512m -Xmx2048m -XX:MaxMetaspaceSize=512m -XX:+UseG1GC -XX:+UseStringDeduplication
                  </jvmArguments>
                </configuration>
              </plugin>
            </plugins>
          </build>
        </profile>
        <profile>
          <id>docker</id>
          <build>
            <plugins>
              <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>dockerfile-maven-plugin</artifactId>
                <version>1.4.13</version>
                <configuration>
                  <repository>${project.artifactId}</repository>
                  <tag>${project.version}</tag>
                  <buildArgs>
                    <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                  </buildArgs>
                </configuration>
                <executions>
                  <execution>
                    <id>default</id>
                    <phase>install</phase>
                    <goals>
                      <goal>build</goal>
                    </goals>
                  </execution>
                </executions>
              </plugin>
            </plugins>
          </build>
        </profile>
      </profiles>
      <reporting>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-project-info-reports-plugin</artifactId>
            <version>3.4.1</version>
          </plugin>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-javadoc-plugin</artifactId>
            <version>3.4.1</version>
            <configuration>
              <show>private</show>
              <nohelp>true</nohelp>
              <additionalOptions>
                <additionalOption>-Xdoclint:none</additionalOption>
              </additionalOptions>
            </configuration>
          </plugin>
          <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>0.8.8</version>
            <reportSets>
              <reportSet>
                <reports>
                  <report>report</report>
                </reports>
              </reportSet>
            </reportSets>
          </plugin>
        </plugins>
      </reporting>
      <repositories>
        <repository>
          <id>central</id>
          <name>Central Repository</name>
          <url>https://repo.maven.apache.org/maven2</url>
          <layout>default</layout>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </repository>
        <repository>
          <id>spring-milestones</id>
          <name>Spring Milestones</name>
          <url>https://repo.spring.io/milestone</url>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </repository>
        <repository>
          <id>spring-snapshots</id>
          <name>Spring Snapshots</name>
          <url>https://repo.spring.io/snapshot</url>
          <snapshots>
            <enabled>true</enabled>
          </snapshots>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <id>central</id>
          <name>Central Plugin Repository</name>
          <url>https://repo.maven.apache.org/maven2</url>
          <layout>default</layout>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </pluginRepository>
      </pluginRepositories>
    </project>
    
    6.2 Gradle 配置
    build.gradle 示例:
    plugins {
      id 'java'
      id 'war'
      id 'org.springframework.boot' version '2.7.4'
      id 'io.spring.dependency-management' version '1.0.14.RELEASE'
      id 'jacoco'
      id 'com.palantir.docker' version '0.34.0'
    }
    group = 'com.example'
    version = '1.0.0-RELEASE'
    sourceCompatibility = '11'
    configurations {
      compileOnly {
        extendsFrom annotationProcessor
      }
      developmentOnly runtimeClasspath {
        extendsFrom developmentOnly
      }
    }
    repositories {
      mavenCentral()
      maven { url 'https://repo.spring.io/milestone' }
      maven { url 'https://repo.spring.io/snapshot' }
    }
    ext {
      set('springCloudVersion', "2021.0.4")
      set('testcontainersVersion', "1.17.4")
    }
    dependencyManagement {
      imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
        mavenBom "org.testcontainers:testcontainers-bom:${testcontainersVersion}"
      }
    }
    dependencies {
      // Spring Boot Starters
      implementation 'org.springframework.boot:spring-boot-starter-web'
      implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
      implementation 'org.springframework.boot:spring-boot-starter-security'
      implementation 'org.springframework.boot:spring-boot-starter-validation'
      implementation 'org.springframework.boot:spring-boot-starter-actuator'
      implementation 'org.springframework.boot:spring-boot-starter-cache'
      implementation 'org.springframework.boot:spring-boot-starter-websocket'
      // Spring Cloud
      implementation 'org.springframework.cloud:spring-cloud-starter-config'
      implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
      implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
      implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j'
      // Database
      runtimeOnly 'com.mysql:mysql-connector-j'
      runtimeOnly 'com.h2database:h2'
      // Security
      implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
      runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
      runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
      // Utilities
      compileOnly 'org.projectlombok:lombok'
      annotationProcessor 'org.projectlombok:lombok'
      implementation 'org.apache.commons:commons-lang3:3.12.0'
      implementation 'com.google.guava:guava:31.1-jre'
      implementation 'org.modelmapper:modelmapper:3.1.0'
      // Cache
      implementation 'com.github.ben-manes.caffeine:caffeine:3.1.2'
      // Monitoring
      implementation 'io.micrometer:micrometer-registry-prometheus'
      // Documentation
      implementation 'org.springdoc:springdoc-openapi-ui:1.6.12'
      // Development
      developmentOnly 'org.springframework.boot:spring-boot-devtools'
      // Testing
      testImplementation 'org.springframework.boot:spring-boot-starter-test'
      testImplementation 'org.springframework.security:spring-security-test'
      testImplementation 'org.testcontainers:mysql'
      testImplementation 'org.testcontainers:junit-jupiter'
      testImplementation 'com.tngtech.archunit:archunit-junit5:1.0.0'
      testImplementation 'org.awaitility:awaitility:4.2.0'
    }
    tasks.named('test') {
      useJUnitPlatform()
      testLogging {
        events "passed", "skipped", "failed"
        exceptionFormat "full"
      }
      systemProperty 'spring.profiles.active', 'test'
      finalizedBy jacocoTestReport
    }
    jacoco {
      toolVersion = "0.8.8"
    }
    jacocoTestReport {
      dependsOn test
      reports {
        xml.required = true
        html.required = true
        csv.required = false
      }
      afterEvaluate {
        classDirectories.setFrom(files(classDirectories.files.collect {
          fileTree(dir: it, exclude: [
            '**/config/**',
            '**/entity/**',
            '**/dto/**',
            '**/*Application*',
            '**/exception/**'
          ])
        }))
      }
    }
    jacocoTestCoverageVerification {
      violationRules {
        rule {
          limit {
            minimum = 0.80
          }
        }
        rule {
          element = 'CLASS'
          includes = ['com.example.service.*']
          limit {
            counter = 'BRANCH'
            value = 'COVEREDRATIO'
            minimum = 0.80
          }
        }
      }
    }
    check.dependsOn jacocoTestCoverageVerification
    bootJar {
      archiveClassifier = 'boot'
      launchScript()
    }
    war {
      archiveClassifier = 'war'
      enabled = true
    }
    springBoot {
      buildInfo()
    }
    docker {
      name "${project.name}:${project.version}"
      files bootJar.archiveFile
      buildArgs(['JAR_FILE': bootJar.archiveFileName.get()])
    }
    task copyDependencies(type: Copy) {
      from configurations.runtimeClasspath into "${buildDir}/libs/dependencies"
    }
    build.dependsOn copyDependencies
    // 自定义任务
    task generateVersionProperties {
      doLast {
        def propertiesFile = file("$buildDir/resources/main/version.properties")
        propertiesFile.parentFile.mkdirs()
        def properties = new Properties()
        properties.setProperty('version', project.version.toString())
        properties.setProperty('build.time', new Date().format("yyyy-MM-dd HH:mm:ss"))
        properties.setProperty('java.version', System.getProperty('java.version'))
        properties.store(propertiesFile.newWriter(), null)
      }
    }
    processResources.dependsOn generateVersionProperties
    // 多环境配置
    bootRun {
      systemProperties = System.properties
    }
    // 性能优化
    tasks.withType(JavaCompile) {
      options.compilerArgs += ['-parameters', '-Xlint:unchecked', '-Xlint:deprecation']
      options.encoding = 'UTF-8'
      options.incremental = true
    }
    // 资源过滤
    processResources {
      filesMatching('**/application*.yml') {
        filter org.apache.tools.ant.filters.ReplaceTokens, tokens: [
          'app.version': project.version
        ]
      }
    }
    

    第七部分:部署与持续集成

    7.1 Docker 容器化部署
    Dockerfile 配置:
    # 多阶段构建 Dockerfile
    # 第一阶段:构建阶段
    FROM maven:3.8.6-eclipse-temurin-11 AS build
    WORKDIR /app
    # 复制 pom.xml 和下载依赖
    COPY pom.xml .
    RUN mvn dependency:go-offline -B
    # 复制源代码并构建
    COPY src ./src
    RUN mvn clean package -DskipTests
    # 第二阶段:运行阶段
    FROM eclipse-temurin:11-jre-alpine
    # 添加非 root 用户
    RUN addgroup -S spring && adduser -S spring -G spring
    USER spring:spring
    WORKDIR /app
    # 复制构建产物
    COPY --from=build /app/target/*.war app.war
    # 配置 JVM 参数
    ENV JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+ParallelRefProcEnabled -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp -XX:+ExitOnOutOfMemoryError"
    # 健康检查
    HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
      CMD wget --no-verbose --tries=1 --spider http://localhost:8080/actuator/health || exit 1
    # 暴露端口
    EXPOSE 8080
    # 启动应用
    ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app/app.war"]
    
    Docker Compose 配置:
    version: '3.8'
    services:
      mysql:
        image: mysql:8.0
        container_name: mysql_db
        environment:
          MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
          MYSQL_DATABASE: ${DB_NAME}
          MYSQL_USER: ${DB_USER}
          MYSQL_PASSWORD: ${DB_PASSWORD}
        ports:
          - "3306:3306"
        volumes:
          - mysql_data:/var/lib/mysql
          - ./config/mysql/init.sql:/docker-entrypoint-initdb.d/init.sql
        networks:
          - app-network
        healthcheck:
          test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
          timeout: 20s
          retries: 10
      redis:
        image: redis:7-alpine
        container_name: redis_cache
        ports:
          - "6379:6379"
        volumes:
          - redis_data:/data
        command: redis-server --appendonly yes
        networks:
          - app-network
        healthcheck:
          test: ["CMD", "redis-cli", "ping"]
          interval: 10s
          timeout: 5s
          retries: 5
      app:
        build:
          context: .
          dockerfile: Dockerfile
        container_name: web_app
        environment:
          SPRING_PROFILES_ACTIVE: docker
          DB_HOST: mysql
          DB_PORT: 3306
          REDIS_HOST: redis
          REDIS_PORT: 6379
        ports:
          - "8080:8080"
          - "5005:5005" # 远程调试端口
        volumes:
          - ./logs:/app/logs
          - ./uploads:/app/uploads
        depends_on:
          mysql:
            condition: service_healthy
          redis:
            condition: service_healthy
        networks:
          - app-network
        restart: unless-stopped
        deploy:
          resources:
            limits:
              cpus: '1'
              memory: 1024M
            reservations:
              cpus: '0.5'
              memory: 512M
      nginx:
        image: nginx:1.23-alpine
        container_name: web_nginx
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
          - ./nginx/conf.d:/etc/nginx/conf.d:ro
          - ./ssl:/etc/nginx/ssl:ro
          - ./static:/usr/share/nginx/static:ro
        depends_on:
          - app
        networks:
          - app-network
      prometheus:
        image: prom/prometheus:latest
        container_name: prometheus_monitor
        ports:
          - "9090:9090"
        volumes:
          - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
          - prometheus_data:/prometheus
        command:
          - '--config.file=/etc/prometheus/prometheus.yml'
          - '--storage.tsdb.path=/prometheus'
          - '--web.console.libraries=/etc/prometheus/console_libraries'
          - '--web.console.templates=/etc/prometheus/consoles'
          - '--storage.tsdb.retention.time=200h'
          - '--web.enable-lifecycle'
        networks:
          - app-network
      grafana:
        image: grafana/grafana:latest
        container_name: grafana_dashboard
        ports:
          - "3000:3000"
        volumes:
          - grafana_data:/var/lib/grafana
          - ./grafana/provisioning:/etc/grafana/provisioning
        environment:
          - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
        depends_on:
          - prometheus
        networks:
          - app-network
    networks:
      app-network:
        driver: bridge
        ipam:
          config:
            - subnet: 172.20.0.0/16
    volumes:
      mysql_data:
      redis_data:
      prometheus_data:
      grafana_data:
    
    7.2 持续集成/持续部署(CI/CD)
    GitHub Actions 配置:
    name: Java CI/CD Pipeline
    on:
      push:
        branches: [ main, develop ]
      pull_request:
        branches: [ main ]
      release:
        types: [ published ]
    env:
      REGISTRY: ghcr.io
      IMAGE_NAME: ${{ github.repository }}
    jobs:
      test:
        runs-on: ubuntu-latest
        services:
          mysql:
            image: mysql:8.0
            env:
              MYSQL_ROOT_PASSWORD: root
              MYSQL_DATABASE: testdb
            ports:
              - 3306:3306
            options: >-
              --health-cmd="mysqladmin ping"
              --health-interval=10s
              --health-timeout=5s
              --health-retries=3
          redis:
            image: redis:7-alpine
            ports:
              - 6379:6379
            options: >-
              --health-cmd="redis-cli ping"
              --health-interval=10s
              --health-timeout=5s
              --health-retries=3
        steps:
          - uses: actions/checkout@v3
          - name: Set up JDK 11
            uses: actions/setup-java@v3
            with:
              java-version: '11'
              distribution: 'temurin'
              cache: maven
          - name: Build and Test
            run: mvn -B clean test
            env:
              SPRING_PROFILES_ACTIVE: test
              DB_HOST: localhost
              DB_PORT: 3306
              REDIS_HOST: localhost
              REDIS_PORT: 6379
          - name: Upload Test Results
            uses: actions/upload-artifact@v3
            if: always()
            with:
              name: test-results
              path: target/surefire-reports/
          - name: Upload Coverage Report
            uses: codecov/codecov-action@v3
            with:
              file: ./target/site/jacoco/jacoco.xml
              fail_ci_if_error: true
      build:
        runs-on: ubuntu-latest
        needs: test
        if: github.event_name == 'push' && github.ref == 'refs/heads/main'
        steps:
          - uses: actions/checkout@v3
          - name: Set up JDK 11
            uses: actions/setup-java@v3
            with:
              java-version: '11'
              distribution: 'temurin'
              cache: maven
          - name: Build with Maven
            run: mvn -B clean package -DskipTests
          - name: Log in to Container Registry
            uses: docker/login-action@v2
            with:
              registry: ${{ env.REGISTRY }}
              username: ${{ github.actor }}
              password: ${{ secrets.GITHUB_TOKEN }}
          - name: Extract metadata
            id: meta
            uses: docker/metadata-action@v4
            with:
              images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
              tags: |
                type=ref,event=branch
                type=ref,event=pr
                type=semver,pattern={{version}}
                type=semver,pattern={{major}}.{{minor}}
                type=sha,prefix={{branch}}-
          - name: Build and push Docker image
            uses: docker/build-push-action@v4
            with:
              context: .
              push: true
              tags: ${{ steps.meta.outputs.tags }}
              labels: ${{ steps.meta.outputs.labels }}
              cache-from: type=gha
              cache-to: type=gha,mode=max
          - name: Generate Deployment Package
            run: |
              mkdir -p deployment
              cp target/*.war deployment/
              cp Dockerfile deployment/
              cp docker-compose.yml deployment/
              cp -r config deployment/
              tar -czf deployment-package.tar.gz deployment/
          - name: Upload Deployment Package
            uses: actions/upload-artifact@v3
            with:
              name: deployment-package
              path: deployment-package.tar.gz
      deploy:
        runs-on: ubuntu-latest
        needs: build
        if: github.event_name == 'push' && github.ref == 'refs/heads/main'
        environment:
          name: production
          url: https://your-domain.com
        steps:
          - name: Download Deployment Package
            uses: actions/download-artifact@v3
            with:
              name: deployment-package
          - name: Setup SSH
            uses: webfactory/[email protected]
            with:
              ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
          - name: Deploy to Server
            env:
              DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
              DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
              DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }}
            run: |
              tar -xzf deployment-package.tar.gz
              scp -o StrictHostKeyChecking=no -r deployment/* ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/
              ssh -o StrictHostKeyChecking=no ${DEPLOY_USER}@${DEPLOY_HOST} "
                cd ${DEPLOY_PATH} && docker-compose down && docker-compose pull && docker-compose up -d --build && docker system prune -af
              "
          - name: Verify Deployment
            run: |
              sleep 30
              curl --retry 5 --retry-delay 10 --max-time 30 \n          https://your-domain.com/actuator/health
          - name: Notify Success
            uses: 8398a7/action-slack@v3
            with:
              channel: '#deployments'
              status: ${{ job.status }}
              author_name: GitHub Actions
            env:
              SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
            if: always()
    
    7.3 云平台部署
    AWS 部署配置(使用 AWS CDK):
    import * as cdk from '@aws-cdk/core';
    import * as ec2 from '@aws-cdk/aws-ec2';
    import * as ecs from '@aws-cdk/aws-ecs';
    import * as ecs_patterns from '@aws-cdk/aws-ecs-patterns';
    import * as rds from '@aws-cdk/aws-rds';
    import * as elasticache from '@aws-cdk/aws-elasticache';
    import * as secretsmanager from '@aws-cdk/aws-secretsmanager';
    
    export class WebAppStack extends cdk.Stack {
      constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
        super(scope, id, props);
        // 创建 VPC
        const vpc = new ec2.Vpc(this, 'WebAppVPC', {
          maxAzs: 2,
          natGateways: 1,
          subnetConfiguration: [
            { cidrMask: 24, name: 'Public', subnetType: ec2.SubnetType.PUBLIC },
            { cidrMask: 24, name: 'Private', subnetType: ec2.SubnetType.PRIVATE_WITH_NAT },
            { cidrMask: 28, name: 'Isolated', subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
          ]
        });
        // 创建 RDS MySQL 实例
        const databaseSecret = new secretsmanager.Secret(this, 'DatabaseSecret', {
          secretName: 'webapp-db-secret',
          generateSecretString: {
            secretStringTemplate: JSON.stringify({ username: 'admin' }),
            generateStringKey: 'password',
            excludePunctuation: true,
            passwordLength: 16,
          },
        });
        const database = new rds.DatabaseInstance(this, 'Database', {
          engine: rds.DatabaseInstanceEngine.mysql({ version: rds.MysqlEngineVersion.VER_8_0_28 }),
          instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MICRO),
          vpc,
          vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_ISOLATED },
          credentials: rds.Credentials.fromSecret(databaseSecret),
          storageEncrypted: true,
          backupRetention: cdk.Duration.days(7),
          deletionProtection: false,
          databaseName: 'webappdb',
        });
        // 创建 ElastiCache Redis 集群
        const redisSubnetGroup = new elasticache.CfnSubnetGroup(this, 'RedisSubnetGroup', {
          description: 'Subnet group for Redis',
          subnetIds: vpc.selectSubnets({ subnetType: ec2.SubnetType.PRIVATE_ISOLATED }).subnetIds,
        });
        const redis = new elasticache.CfnCacheCluster(this, 'RedisCache', {
          cacheNodeType: 'cache.t3.micro',
          engine: 'redis',
          numCacheNodes: 1,
          clusterName: 'webapp-redis',
          vpcSecurityGroupIds: [/* security group IDs */],
          cacheSubnetGroupName: redisSubnetGroup.ref,
        });
        // 创建 ECS 集群
        const cluster = new ecs.Cluster(this, 'WebAppCluster', {
          vpc,
          containerInsights: true,
        });
        // 创建 Fargate 服务
        const fargateService = new ecs_patterns.ApplicationLoadBalancedFargateService(this, 'WebAppService', {
          cluster,
          memoryLimitMiB: 1024,
          cpu: 512,
          desiredCount: 2,
          taskImageOptions: {
            image: ecs.ContainerImage.fromRegistry('ghcr.io/your-org/your-app:latest'),
            containerPort: 8080,
            environment: {
              SPRING_PROFILES_ACTIVE: 'prod',
              DB_HOST: database.dbInstanceEndpointAddress,
              DB_PORT: database.dbInstanceEndpointPort,
              REDIS_HOST: redis.attrRedisEndpointAddress,
              REDIS_PORT: redis.attrRedisEndpointPort,
            },
            secrets: {
              DB_USERNAME: ecs.Secret.fromSecretsManager(databaseSecret, 'username'),
              DB_PASSWORD: ecs.Secret.fromSecretsManager(databaseSecret, 'password'),
            },
          },
          publicLoadBalancer: true,
        });
        // 配置自动伸缩
        const scaling = fargateService.service.autoScaleTaskCount({
          minCapacity: 2,
          maxCapacity: 10,
        });
        scaling.scaleOnCpuUtilization('CpuScaling', {
          targetUtilizationPercent: 70,
          scaleInCooldown: cdk.Duration.seconds(60),
          scaleOutCooldown: cdk.Duration.seconds(60),
        });
        scaling.scaleOnMemoryUtilization('MemoryScaling', {
          targetUtilizationPercent: 70,
          scaleInCooldown: cdk.Duration.seconds(60),
          scaleOutCooldown: cdk.Duration.seconds(60),
        });
        // 允许 ECS 访问数据库
        database.connections.allowFrom(fargateService.service, ec2.Port.tcp(3306));
        // 输出负载均衡器 URL
        new cdk.CfnOutput(this, 'LoadBalancerDNS', {
          value: fargateService.loadBalancer.loadBalancerDnsName,
        });
      }
    }
    

    第八部分:监控与优化

    8.1 应用监控配置
    Spring Boot Actuator 配置:
    # Actuator 配置
    management.endpoints.web.exposure.include=health,info,metrics,env,beans,loggers,prometheus
    management.endpoints.web.exposure.exclude=threaddump,heapdump
    management.endpoint.health.show-details=always
    management.endpoint.health.probes.enabled=true
    management.health.db.enabled=true
    management.health.redis.enabled=true
    management.health.diskspace.enabled=true
    management.metrics.export.prometheus.enabled=true
    management.metrics.distribution.percentiles-histogram.http.server.requests=true
    management.metrics.enable.jvm=true
    management.metrics.enable.logback=true
    management.metrics.enable.process=true
    management.metrics.enable.system=true
    # 自定义健康指示器
    management.health.custom.enabled=true
    # 日志级别管理
    management.endpoint.loggers.enabled=true
    
    自定义健康检查:
    @Component
    public class CustomHealthIndicator implements HealthIndicator {
        private final DatabaseService databaseService;
        private final CacheService cacheService;
        private final ExternalService externalService;
    
        public CustomHealthIndicator(DatabaseService databaseService, CacheService cacheService, ExternalService externalService) {
            this.databaseService = databaseService;
            this.cacheService = cacheService;
            this.externalService = externalService;
        }
    
        @Override
        public Health health() {
            Health.Builder builder = Health.up();
            // 检查数据库连接
            try {
                databaseService.checkConnection();
                builder.withDetail("database", "connected");
            } catch (Exception e) {
                builder.down()
                    .withDetail("database", "disconnected")
                    .withDetail("databaseError", e.getMessage());
            }
            // 检查缓存连接
            try {
                cacheService.ping();
                builder.withDetail("cache", "connected");
            } catch (Exception e) {
                builder.down()
                    .withDetail("cache", "disconnected")
                    .withDetail("cacheError", e.getMessage());
            }
            // 检查外部服务
            try {
                externalService.checkStatus();
                builder.withDetail("externalService", "available");
            } catch (Exception e) {
                builder.withDetail("externalService", "unavailable")
                    .withDetail("externalServiceError", e.getMessage());
            }
            // 检查磁盘空间
            File file = new File(".");
            long freeSpace = file.getFreeSpace();
            long totalSpace = file.getTotalSpace();
            double freePercentage = (double) freeSpace / totalSpace * 100;
            builder.withDetail("disk.free", formatBytes(freeSpace))
                .withDetail("disk.total", formatBytes(totalSpace))
                .withDetail("disk.freePercentage", String.format("%.2f%%", freePercentage));
            if (freePercentage < 10) {
                builder.status(Status.DOWN).withDetail("disk", "critical");
            } else if (freePercentage < 20) {
                builder.status(Status.DOWN).withDetail("disk", "warning");
            }
            return builder.build();
        }
    
        private String formatBytes(long bytes) {
            if (bytes < 1024) return bytes + " B";
            int exp = (int) (Math.log(bytes) / Math.log(1024));
            String pre = "KMGTPE".charAt(exp - 1) + "i";
            return String.format("%.1f %sB", bytes / Math.pow(1024, exp), pre);
        }
    }
    
    指标监控配置:
    @Configuration
    @EnableMetrics
    public class MetricsConfig {
        @Bean
        public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
            return registry -> registry.config()
                .commonTags("application", "webapp", "environment", "production");
        }
        @Bean
        public TimedAspect timedAspect(MeterRegistry registry) {
            return new TimedAspect(registry);
        }
        @Bean
        public CountedAspect countedAspect(MeterRegistry registry) {
            return new CountedAspect(registry);
        }
        @Bean
        public MeterBinder cacheMetrics() {
            return new MeterBinder() {
                @Override
                public void bindTo(MeterRegistry registry) {
                    Gauge.builder("cache.size", CacheManager.getCache("users")::getSize)
                        .description("The number of entries in the cache")
                        .tags("cache", "users")
                        .register(registry);
                }
            };
        }
    }
    
    8.2 性能优化配置
    JVM 优化参数:
    # 生产环境 JVM 参数
    -Xms512m # 初始堆大小
    -Xmx2048m # 最大堆大小
    -XX:MaxMetaspaceSize=512m # 最大元空间大小
    -XX:+UseG1GC # 使用 G1 垃圾回收器
    -XX:MaxGCPauseMillis=200 # 目标最大 GC 暂停时间
    -XX:ParallelGCThreads=4 # 并行 GC 线程数
    -XX:ConcGCThreads=2 # 并发 GC 线程数
    -XX:+UseStringDeduplication # 字符串去重
    -XX:+HeapDumpOnOutOfMemoryError # OOM 时生成堆转储
    -XX:HeapDumpPath=/tmp/heapdump.hprof # 堆转储路径
    -XX:+PrintGCDetails # 打印 GC 详情
    -XX:+PrintGCDateStamps
    -Xloggc:/tmp/gc.log # GC 日志文件
    -XX:+UseCompressedOops # 使用压缩普通对象指针
    -XX:+UseCompressedClassPointers # 使用压缩类指针
    -XX:+AlwaysPreTouch # 启动时预接触内存页
    -Djava.security.egd=file:/dev/./urandom # 随机数生成优化
    -Dsun.net.inetaddr.ttl=60 # DNS 缓存 TTL
    
    Web 服务器优化:
    @Configuration
    public class WebServerConfig {
        @Bean
        public TomcatServletWebServerFactory servletContainer() {
            TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
            factory.addConnectorCustomizers(connector -> {
                // 优化连接器配置
                connector.setProperty("maxThreads", "200");
                connector.setProperty("minSpareThreads", "20");
                connector.setProperty("maxConnections", "10000");
                connector.setProperty("acceptCount", "100");
                connector.setProperty("connectionTimeout", "20000");
                connector.setProperty("maxKeepAliveRequests", "100");
                connector.setProperty("keepAliveTimeout", "30000");
                connector.setProperty("compression", "on");
                connector.setProperty("compressionMinSize", "2048");
                connector.setProperty("compressableMimeType", "text/html,text/xml,text/plain,text/css,text/javascript,application/json");
                connector.setProperty("useBodyEncodingForURI", "true");
                connector.setProperty("URIEncoding", "UTF-8");
            });
            return factory;
        }
        @Bean
        public FilterRegistrationBean<CorsFilter> corsFilter() {
            FilterRegistrationBean<CorsFilter> registrationBean = new FilterRegistrationBean<>();
            registrationBean.setFilter(new CorsFilter());
            registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
            return registrationBean;
        }
        @Bean
        public FilterRegistrationBean<GzipFilter> gzipFilter() {
            FilterRegistrationBean<GzipFilter> registrationBean = new FilterRegistrationBean<>();
            registrationBean.setFilter(new GzipFilter());
            registrationBean.addUrlPatterns("/*");
            registrationBean.setOrder(Ordered.LOWEST_PRECEDENCE);
            return registrationBean;
        }
    }
    
    数据库连接池优化:
    # HikariCP 连接池配置
    spring.datasource.hikari.connection-timeout=30000
    spring.datasource.hikari.maximum-pool-size=20
    spring.datasource.hikari.minimum-idle=10
    spring.datasource.hikari.idle-timeout=600000
    spring.datasource.hikari.max-lifetime=1800000
    spring.datasource.hikari.connection-test-query=SELECT 1
    spring.datasource.hikari.pool-name=WebAppPool
    spring.datasource.hikari.auto-commit=false
    spring.datasource.hikari.leak-detection-threshold=60000
    spring.datasource.hikari.initialization-fail-timeout=1
    
    8.3 日志配置优化
    Logback 配置:
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration scan="true" scanPeriod="30 seconds">
      <property name="LOG_PATH" value="./logs"/>
      <property name="LOG_ARCHIVE" value="${LOG_PATH}/archive"/>
      <property name="APP_NAME" value="webapp"/>
      <!-- 控制台输出 -->
      <appender name="CONSOLE">
        <encoder>
          <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
          <charset>UTF-8</charset>
        </encoder>
        <filter>
          <level>INFO</level>
        </filter>
      </appender>
      <!-- 文件输出 -->
      <appender name="FILE">
        <file>${LOG_PATH}/${APP_NAME}.log</file>
        <encoder>
          <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
          <charset>UTF-8</charset>
        </encoder>
        <rollingPolicy>
          <fileNamePattern>${LOG_ARCHIVE}/${APP_NAME}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
          <timeBasedFileNamingAndTriggeringPolicy>
            <maxFileSize>100MB</maxFileSize>
          </timeBasedFileNamingAndTriggeringPolicy>
          <maxHistory>30</maxHistory>
          <totalSizeCap>3GB</totalSizeCap>
        </rollingPolicy>
      </appender>
      <!-- 错误日志单独输出 -->
      <appender name="ERROR_FILE">
        <file>${LOG_PATH}/${APP_NAME}-error.log</file>
        <encoder>
          <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
          <charset>UTF-8</charset>
        </encoder>
        <filter>
          <level>ERROR</level>
        </filter>
        <rollingPolicy>
          <fileNamePattern>${LOG_ARCHIVE}/${APP_NAME}-error.%d{yyyy-MM-dd}.log</fileNamePattern>
          <maxHistory>90</maxHistory>
        </rollingPolicy>
      </appender>
      <!-- 访问日志 -->
      <appender name="ACCESS_FILE">
        <file>${LOG_PATH}/access.log</file>
        <encoder>
          <pattern>%msg%n</pattern>
          <charset>UTF-8</charset>
        </encoder>
        <rollingPolicy>
          <fileNamePattern>${LOG_ARCHIVE}/access.%d{yyyy-MM-dd}.log</fileNamePattern>
          <maxHistory>30</maxHistory>
        </rollingPolicy>
      </appender>
      <!-- 异步日志 -->
      <appender name="ASYNC_FILE">
        <appender-ref ref="FILE"/>
        <queueSize>512</queueSize>
        <discardingThreshold>0</discardingThreshold>
        <includeCallerData>true</includeCallerData>
        <neverBlock>true</neverBlock>
      </appender>
      <!-- 日志级别配置 -->
      <logger name="com.example" level="DEBUG" additivity="false">
        <appender-ref ref="ASYNC_FILE"/>
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="ERROR_FILE"/>
      </logger>
      <logger name="org.springframework" level="INFO"/>
      <logger name="org.hibernate" level="WARN"/>
      <logger name="org.hibernate.SQL" level="DEBUG"/>
      <logger name="org.hibernate.type.descriptor.sql" level="TRACE"/>
      <logger name="com.zaxxer.hikari" level="INFO"/>
      <logger name="org.apache.http" level="INFO"/>
      <!-- 访问日志 -->
      <logger name="ACCESS_LOG" level="INFO" additivity="false">
        <appender-ref ref="ACCESS_FILE"/>
      </logger>
      <!-- 根日志 -->
      <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="ASYNC_FILE"/>
        <appender-ref ref="ERROR_FILE"/>
      </root>
    </configuration>
    

    第九部分:调试与故障排除

    9.1 远程调试配置
    IDEA 远程调试配置:
    1. 运行 → 编辑配置
    2. 点击 + → 远程 JVM 调试
    3. 配置参数:
      名称:Remote Debug
      主机:localhost
      端口:5005
      命令行实参:-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
      
    生产环境远程调试:
    # 启动应用时添加 JVM 参数
    java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 \n -jar your-application.jar
    
    Docker 容器远程调试:
    # Dockerfile 中添加调试支持
    ENV JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005"
    EXPOSE 5005
    
    9.2 性能分析工具
    VisualVM 集成:
    1. 安装 VisualVM 插件
    2. 配置 JMX 连接:
      -Dcom.sun.management.jmxremote
      -Dcom.sun.management.jmxremote.port=9010
      -Dcom.sun.management.jmxremote.ssl=false
      -Dcom.sun.management.jmxremote.authenticate=false
      
    3. 连接并监控应用性能
    IDEA 内置分析工具:
    • CPU Profiler:分析 CPU 使用情况
    • Memory Profiler:分析内存使用情况
    • Async Profiler:异步性能分析
    9.3 常见问题与解决方案
    问题 1:应用启动缓慢

    可能原因:

    1. 类路径扫描过多
    2. 数据库连接初始化慢
    3. 缓存预热时间长

    解决方案:

    @Configuration
    @EnableJpaRepositories(
      basePackages = "com.example.repository",
      considerNestedRepositories = true
    )
    @EntityScan(basePackages = "com.example.entity")
    @ComponentScan(
      basePackages = "com.example",
      excludeFilters = @ComponentScan.Filter(
        type = FilterType.REGEX,
        pattern = "com.example.config.*Test.*"
      )
    )
    public class FastStartupConfig {
        @Bean
        public CommandLineRunner cacheWarmup(CacheService cacheService) {
            return args -> {
                // 异步预热缓存
                CompletableFuture.runAsync(cacheService::warmupCache);
            };
        }
    }
    
    问题 2:内存泄漏

    检测工具:

    • Eclipse Memory Analyzer (MAT)
    • YourKit Java Profiler
    • JProfiler

    常见内存泄漏场景:

    1. 静态集合持有对象引用
    2. 未关闭的资源(连接、流等)
    3. 线程局部变量未清理

    预防措施:

    @Component
    public class MemoryLeakPrevention {
        @PreDestroy
        public void cleanup() {
            // 清理静态资源
            CacheManager.clearAll();
            ThreadLocal.remove();
        }
        @Bean
        public ServletListenerRegistrationBean<HttpSessionListener> sessionListener() {
            return new ServletListenerRegistrationBean<>(new HttpSessionListener() {
                @Override
                public void sessionDestroyed(HttpSessionEvent se) {
                    // 清理会话相关资源
                    HttpSession session = se.getSession();
                    session.removeAttribute("largeObject");
                }
            });
        }
    }
    
    问题 3:数据库连接泄漏

    检测方法:

    -- 监控数据库连接
    SHOW PROCESSLIST;
    SHOW STATUS LIKE 'Threads_connected';
    

    预防措施:

    @Configuration
    public class ConnectionLeakDetection {
        @Bean
        public DataSource dataSource() {
            HikariDataSource dataSource = new HikariDataSource();
            // 启用泄漏检测
            dataSource.setLeakDetectionThreshold(60000);
            return dataSource;
        }
        @Bean
        public JdbcTemplate jdbcTemplate(DataSource dataSource) {
            return new JdbcTemplate(dataSource);
        }
        @Bean
        public ConnectionValidator connectionValidator() {
            return new ConnectionValidator();
        }
    }
    
    @Component
    class ConnectionValidator {
        @Scheduled(fixedDelay = 300000) // 每 5 分钟执行一次
        public void validateConnections() {
            // 验证和清理无效连接
        }
    }
    

    第十部分:最佳实践与总结

    10.1 项目结构最佳实践
    推荐的包结构:
    text
    com.example.application
    ├── Application.java # 主启动类
    ├── config/ # 配置类
    │   ├── WebConfig.java
    │   ├── SecurityConfig.java
    │   ├── DatabaseConfig.java
    │   └── CacheConfig.java
    ├── controller/ # 控制器层
    │   ├── api/ # REST API
    │   │   ├── v1/ # API 版本 v1
    │   │   └── v2/ # API 版本 v2
    │   └── web/ # Web 控制器
    ├── service/ # 服务层
    │   ├── impl/ # 服务实现
    │   ├── dto/ # 数据传输对象
    │   └── mapper/ # 对象映射器
    ├── repository/ # 数据访问层
    │   ├── entity/ # 实体类
    │   ├── dao/ # 数据访问对象
    │   └── jpa/ # JPA 仓库
    ├── domain/ # 领域层
    │   ├── model/ # 领域模型
    │   ├── event/ # 领域事件
    │   └── service/ # 领域服务
    ├── infrastructure/ # 基础设施层
    │   ├── cache/ # 缓存
    │   ├── message/ # 消息队列
    │   └── external/ # 外部服务集成
    ├── common/ # 公共模块
    │   ├── exception/ # 异常处理
    │   ├── constant/ # 常量定义
    │   ├── util/ # 工具类
    │   └── annotation/ # 自定义注解
    └── aspect/ # 切面
        ├── log/ # 日志切面
        ├── metrics/ # 指标切面
        └── transaction/ # 事务切面
    
    10.2 代码质量保障
    代码检查工具集成:
    <!-- checkstyle 配置 -->
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-checkstyle-plugin</artifactId>
      <version>3.2.0</version>
      <configuration>
        <configLocation>checkstyle.xml</configLocation>
        <encoding>UTF-8</encoding>
        <consoleOutput>true</consoleOutput>
        <failsOnError>true</failsOnError>
        <linkXRef>false</linkXRef>
      </configuration>
      <executions>
        <execution>
          <id>validate</id>
          <phase>validate</phase>
          <goals>
            <goal>check</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    <!-- spotbugs 配置 -->
    <plugin>
      <groupId>com.github.spotbugs</groupId>
      <artifactId>spotbugs-maven-plugin</artifactId>
      <version>4.7.2.1</version>
      <configuration>
        <effort>Max</effort>
        <threshold>Low</threshold>
        <failOnError>true</failOnError>
      </configuration>
      <executions>
        <execution>
          <goals>
            <goal>check</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    <!-- PMD 配置 -->
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-pmd-plugin</artifactId>
      <version>3.19.0</version>
      <configuration>
        <rulesets>
          <ruleset>rulesets/java/quickstart.xml</ruleset>
        </rulesets>
        <failOnViolation>true</failOnViolation>
      </configuration>
      <executions>
        <execution>
          <goals>
            <goal>check</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    
    测试策略:
    // 分层测试策略
    @SpringBootTest
    @AutoConfigureMockMvc
    @ActiveProfiles("test")
    @Tag("integration")
    class ApplicationIntegrationTests {
        @Test
        @DisplayName("完整的应用启动测试")
        void contextLoads() {
            // 验证 Spring 上下文加载
        }
        @Test
        @DisplayName("REST API 集成测试")
        void testRestApi() {
            // 完整的 API 测试
        }
    }
    
    @WebMvcTest
    @AutoConfigureMockMvc
    class ControllerTests {
        @Test
        @DisplayName("控制器单元测试")
        void testController() {
            // 控制器层测试
        }
    }
    
    @DataJpaTest
    @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
    class RepositoryTests {
        @Test
        @DisplayName("仓库层测试")
        void testRepository() {
            // 数据访问层测试
        }
    }
    
    @ExtendWith(MockitoExtension.class)
    class ServiceTests {
        @Test
        @DisplayName("服务层单元测试")
        void testService() {
            // 服务层测试
        }
    }
    
    10.3 安全最佳实践
    安全配置检查清单:
    1. 依赖安全扫描:
      mvn org.owasp:dependency-check-maven:check
      
    2. 密码安全:
      @Bean
      public PasswordEncoder passwordEncoder() {
          return new BCryptPasswordEncoder(12); // 使用高强度加密
      }
      
    3. HTTPS 强制:
      @Configuration
      public class HttpsConfig {
          @Bean
          public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
              http.requiresChannel()
                  .requestMatchers(r -> r.getHeader("X-Forwarded-Proto") != null)
                  .requiresSecure();
              return http.build();
          }
      }
      
    4. 安全头部配置:
      @Bean
      public SecurityFilterChain securityHeaders(HttpSecurity http) throws Exception {
          http.headers()
              .contentSecurityPolicy("default-src 'self'")
              .and()
              .xssProtection()
              .and()
              .frameOptions().deny()
              .and()
              .httpStrictTransportSecurity()
              .includeSubDomains(true)
              .maxAgeInSeconds(31536000);
          return http.build();
      }
      
    10.4 总结

    IntelliJ IDEA 作为一款强大的 Java 开发工具,配合合理的项目配置和部署策略,可以显著提高 Web 应用的开发效率和运行稳定性。本指南涵盖了从项目创建到生产部署的全过程,包括:

    1. 环境配置:优化 IDE 设置,提高开发效率
    2. 项目结构:合理的模块化和包组织
    3. 框架集成:Spring Boot、数据库、安全等配置
    4. 构建工具:Maven 和 Gradle 的深度配置
    5. 部署策略:本地部署、容器化、云平台部署
    6. 监控优化:性能监控、日志管理、故障排除
    7. 最佳实践:代码质量、安全、测试策略

    通过遵循这些最佳实践,您可以构建出高性能、高可用、易维护的企业级 Web 应用。记住,配置管理是一个持续优化的过程,需要根据具体业务需求和运行环境不断调整和完善。

    目录

    1. 第一部分:IntelliJ IDEA 基础与环境配置
    2. 1.1 IntelliJ IDEA 概述与版本选择
    3. 版本选择策略:
    4. 1.2 安装与初始配置
    5. 安装步骤:
    6. 初始配置优化:
    7. 1.3 界面布局与核心概念
    8. 项目结构层级:
    9. 关键界面区域:
    10. 重要快捷键:
    11. 第二部分:项目创建与配置管理
    12. 2.1 新项目创建流程
    13. 基于 Maven 的项目创建:
    14. 基于 Gradle 的项目创建:
    15. 2.2 模块化项目结构
    16. 多模块项目配置:
    17. 父 pom.xml 配置示例:
    18. 2.3 项目配置详解
    19. 项目结构配置(Project Structure):
    20. 编译器配置:
    21. 运行/调试配置:
    22. 第三部分:Web 项目配置详解
    23. 3.1 Web 模块创建与配置
    24. 创建 Web 模块:
    25. 目录结构:
    26. web.xml 配置示例:
    27. 3.2 Servlet 容器配置
    28. 内嵌 Servlet 容器配置(Spring Boot):
    29. 3.3 静态资源处理
    30. Spring MVC 资源映射:
    31. 资源文件组织结构:
    32. 第四部分:服务器集成与部署配置
    33. 4.1 本地服务器配置
    34. Tomcat 服务器配置步骤:
    35. Tomcat 配置详情:
    36. 4.2 热部署与热交换配置
    37. 配置热部署:
    38. application-dev.properties
    39. 4.3 多环境部署配置
    40. 配置文件结构:
    41. 多环境配置示例:
    42. 运行配置示例:
    43. 第五部分:框架集成配置
    44. 5.1 Spring/Spring Boot 配置
    45. Spring Boot 项目创建:
    46. application.properties 配置:
    47. 服务器配置
    48. 数据库配置
    49. JPA 配置
    50. 日志配置
    51. 静态资源
    52. 上传文件配置
    53. Spring 配置类示例:
    54. 5.2 数据库配置与连接
    55. 数据源配置:
    56. 在 IDEA 中配置数据库工具:
    57. 5.3 安全配置(Spring Security)
    58. Security 配置类:
    59. 第六部分:构建工具配置
    60. 6.1 Maven 深度配置
    61. 完整 pom.xml 示例:
    62. 6.2 Gradle 配置
    63. build.gradle 示例:
    64. 第七部分:部署与持续集成
    65. 7.1 Docker 容器化部署
    66. Dockerfile 配置:
    67. 多阶段构建 Dockerfile
    68. 第一阶段:构建阶段
    69. 复制 pom.xml 和下载依赖
    70. 复制源代码并构建
    71. 第二阶段:运行阶段
    72. 添加非 root 用户
    73. 复制构建产物
    74. 配置 JVM 参数
    75. 健康检查
    76. 暴露端口
    77. 启动应用
    78. Docker Compose 配置:
    79. 7.2 持续集成/持续部署(CI/CD)
    80. GitHub Actions 配置:
    81. 7.3 云平台部署
    82. AWS 部署配置(使用 AWS CDK):
    83. 第八部分:监控与优化
    84. 8.1 应用监控配置
    85. Spring Boot Actuator 配置:
    86. Actuator 配置
    87. 自定义健康指示器
    88. 日志级别管理
    89. 自定义健康检查:
    90. 指标监控配置:
    91. 8.2 性能优化配置
    92. JVM 优化参数:
    93. 生产环境 JVM 参数
    94. Web 服务器优化:
    95. 数据库连接池优化:
    96. HikariCP 连接池配置
    97. 8.3 日志配置优化
    98. Logback 配置:
    99. 第九部分:调试与故障排除
    100. 9.1 远程调试配置
    101. IDEA 远程调试配置:
    102. 生产环境远程调试:
    103. 启动应用时添加 JVM 参数
    104. Docker 容器远程调试:
    105. Dockerfile 中添加调试支持
    106. 9.2 性能分析工具
    107. VisualVM 集成:
    108. IDEA 内置分析工具:
    109. 9.3 常见问题与解决方案
    110. 问题 1:应用启动缓慢
    111. 问题 2:内存泄漏
    112. 问题 3:数据库连接泄漏
    113. 第十部分:最佳实践与总结
    114. 10.1 项目结构最佳实践
    115. 推荐的包结构:
    116. 10.2 代码质量保障
    117. 代码检查工具集成:
    118. 测试策略:
    119. 10.3 安全最佳实践
    120. 安全配置检查清单:
    121. 10.4 总结
    • 💰 8折买阿里云服务器限时8折了解详情
    • Magick API 一键接入全球大模型注册送1000万token查看
    • 🤖 一键搭建Deepseek满血版了解详情
    • 一键打造专属AI 智能体了解详情
    极客日志微信公众号二维码

    微信扫一扫,关注极客日志

    微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

    更多推荐文章

    查看全部
    • 基于 Coze 抓取小红书视频并同步至飞书多维表实战
    • 从零搭建 SpringBoot 项目详解
    • 医疗人工智能大模型的关键能力:中期训练 (Mid-training)
    • 分布式文件系统 HDFS 存储原理
    • Git 连接 GitHub 端口 443 失败解决方案
    • 前端国际化实现指南:i18next 与 vue-i18n 实践
    • 使用 Continue 插件本地部署 AI 代码助手替代 Cursor 与 Copilot
    • 大模型领域热门岗位解析:算法、研发与管理方向
    • Windows 11 配置 CUDA 版 llama.cpp 实现 GGUF 模型本地聊天
    • Spring Boot 基础工程构建与热部署实战
    • OpenTiny NEXT 前端智能化征文:系统学习 AI 前端与 WebAgent
    • Python 11 种常用编译器与解释器介绍
    • 最新 ACM Fellow 名单发布,4 名中国大陆学者当选,中国机构入选人数第二
    • 大模型微调实战:ChatGLM-6B 微调经验与开源项目汇总
    • 垂直领域大模型微调实践经验总结
    • MySQL 表操作实战:创建、修改与删除全解析
    • 轻量化网络设计:MobileNet V2 倒残差结构全解析与部署实战
    • 【教程】CLAUDE.md 与 AGENTS.md 完全指南:让 AI 编程助手更懂你的项目
    • 边缘计算设备部署轻量 TensorFlow 模型全流程
    • PyCharm 集成 GitHub Copilot:从安装到配置实战指南

    相关免费在线工具

    • Keycode 信息

      查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

    • Escape 与 Native 编解码

      JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

    • JavaScript / HTML 格式化

      使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

    • JavaScript 压缩与混淆

      Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

    • Base64 字符串编码/解码

      将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

    • Base64 文件转换器

      将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online