JHipster-进阶操作手册


企业级项目开发流程

1. 项目初始化策略

# 创建项目工作区
mkdir enterprise-app && cd enterprise-app

# 初始化JHipster项目
jhipster

# 关键配置选择
Application type: Monolithic application
Base name: enterpriseApp  
Package name: com.enterprise.app
Build tool: Maven
Authentication: JWT
Database: PostgreSQL
Cache: Redis

2. 团队协作配置

// .yo-rc.json - 标准化团队配置
{
  "generator-jhipster": {
    "applicationType": "monolith",
    "baseName": "enterpriseApp",
    "packageName": "com.enterprise.app",
    "buildTool": "maven",
    "authenticationType": "jwt",
    "databaseType": "sql",
    "devDatabaseType": "postgresql",
    "prodDatabaseType": "postgresql",
    "cacheProvider": "redis",
    "enableHibernateCache": true,
    "websocket": true,
    "searchEngine": "elasticsearch"
  }
}

3. 代码质量配置

# 配置代码检查
npm run lint
npm run test:ci  

# SonarQube集成
./mvnw sonar:sonar \
  -Dsonar.projectKey=enterprise-app \
  -Dsonar.host.url=http://localhost:9000

微服务架构实战

1. 架构设计

API网关:8080
用户服务:8081
订单服务:8082
库存服务:8083
用户数据库
订单数据库
库存数据库
服务注册中心:8761

2. JDL微服务定义

// microservices.jdl
application {
  config {
    baseName gateway
    applicationType gateway
    packageName com.enterprise.gateway
    serverPort 8080
    serviceDiscoveryType consul
    authenticationType jwt
    databaseType sql
    prodDatabaseType postgresql
    clientFramework angular
  }
}

application {
  config {
    baseName userservice  
    applicationType microservice
    packageName com.enterprise.user
    serverPort 8081
    serviceDiscoveryType consul
    authenticationType jwt
    databaseType sql
    prodDatabaseType postgresql
    skipClient true
  }
  entities User, Role
}

application {
  config {
    baseName orderservice
    applicationType microservice 
    packageName com.enterprise.order
    serverPort 8082
    serviceDiscoveryType consul
    authenticationType jwt
    databaseType sql
    prodDatabaseType postgresql
    skipClient true
  }
  entities Order, OrderItem
}

// 实体定义
entity User {
  login String required unique
  email String required unique
  firstName String
  lastName String
  activated Boolean
}

entity Role {
  name String required unique
}

entity Order {
  orderDate Instant required
  status OrderStatus required
  totalAmount BigDecimal required min(0)
}

entity OrderItem {
  quantity Integer required min(1)
  unitPrice BigDecimal required min(0)
  totalPrice BigDecimal required min(0)
}

enum OrderStatus {
  PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED
}

// 关系定义
relationship ManyToMany {
  User{roles} to Role{users}
}

relationship OneToMany {
  User{orders} to Order{customer}
  Order{items} to OrderItem{order}
}

// 服务分配
microservice User, Role with userservice
microservice Order, OrderItem with orderservice

3. 微服务生成与配置

# 生成微服务架构
jhipster jdl microservices.jdl

# 启动服务注册中心
cd gateway && ./mvnw spring-boot:run

# 启动微服务
cd ../userservice && ./mvnw spring-boot:run
cd ../orderservice && ./mvnw spring-boot:run

JDL高级建模

1. 复杂业务建模

// 电商系统完整建模
application {
  config {
    baseName ecommerce
    applicationType monolith
    packageName com.ecommerce.app
    databaseType sql
    prodDatabaseType postgresql
    clientFramework angular
    enableSwaggerCodegen true
  }
}

// 核心业务实体
entity Customer {
  customerCode String required unique pattern(/^[A-Z]{2}\d{6}$/)
  firstName String required minlength(2) maxlength(50)
  lastName String required minlength(2) maxlength(50)  
  email String required unique pattern(/^[^@\s]+@[^@\s]+\.[^@\s]+$/)
  phoneNumber String pattern(/^\+?[1-9]\d{1,14}$/)
  dateOfBirth LocalDate
  gender Gender
  registrationDate Instant required
  isActive Boolean
}

entity Product {
  sku String required unique minlength(3) maxlength(20)
  name String required minlength(2) maxlength(100)
  description TextBlob
  price BigDecimal required min(0)
  discountPrice BigDecimal min(0)
  stockQuantity Integer required min(0)
  isActive Boolean
  weight Double min(0)
  dimensions String
  createdDate Instant required
  lastModifiedDate Instant
}

entity Category {
  name String required unique minlength(2) maxlength(50)
  description String maxlength(500)
  categoryCode String required unique
  isActive Boolean
  sortOrder Integer
}

entity Order {
  orderNumber String required unique pattern(/^ORD-\d{8}-\d{4}$/)
  orderDate Instant required
  deliveryDate Instant
  status OrderStatus required
  totalAmount BigDecimal required min(0)
  discountAmount BigDecimal min(0)
  taxAmount BigDecimal min(0)
  shippingAmount BigDecimal min(0)
  paymentMethod PaymentMethod required
  notes TextBlob
}

entity OrderItem {
  quantity Integer required min(1)
  unitPrice BigDecimal required min(0) 
  totalPrice BigDecimal required min(0)
  discountAmount BigDecimal min(0)
}

entity Address {
  type AddressType required
  street String required maxlength(200)
  city String required maxlength(50)
  state String maxlength(50)
  postalCode String required pattern(/^\d{5}(-\d{4})?$/)
  country String required maxlength(50)
  isDefault Boolean
}

entity Payment {
  paymentDate Instant required
  amount BigDecimal required min(0)
  paymentMethod PaymentMethod required
  transactionId String unique
  status PaymentStatus required
  notes String maxlength(500)
}

// 枚举定义
enum Gender {
  MALE, FEMALE, OTHER
}

enum OrderStatus {
  DRAFT, PENDING, CONFIRMED, PROCESSING, SHIPPED, DELIVERED, CANCELLED, RETURNED
}

enum PaymentMethod {
  CREDIT_CARD, DEBIT_CARD, PAYPAL, BANK_TRANSFER, CASH_ON_DELIVERY
}

enum PaymentStatus {
  PENDING, COMPLETED, FAILED, REFUNDED, CANCELLED
}

enum AddressType {
  HOME, WORK, SHIPPING, BILLING
}

// 复杂关系定义
relationship OneToMany {
  Customer{orders} to Order{customer required}
  Customer{addresses} to Address{customer required}
  Order{items} to OrderItem{order required}
  Order{payments} to Payment{order required}
  Category{products} to Product{category}
  Product{orderItems} to OrderItem{product required}
}

relationship ManyToOne {
  Order{shippingAddress} to Address
  Order{billingAddress} to Address
}

// 分页配置
paginate Customer, Product, Order with pagination
paginate Category with infinite-scroll

// 服务层生成
service Customer, Product, Order with serviceImpl
service Category, Address with serviceClass

// DTO配置
dto Customer, Product, Order, OrderItem with mapstruct

// 搜索配置
search Customer, Product with elasticsearch

// 微服务部署选项
deployment {
  deploymentType docker-compose
  monitoring prometheus
  serviceDiscoveryType consul
  dockerRepositoryName "mycompany"
  enableRancherLoadBalancing true
}

2. JDL验证与最佳实践

// JDL验证脚本
const validateJDL = async (jdlContent: string) => {
  const validator = {
    // 实体命名验证
    validateEntityNames: (entities: Entity[]) => {
      entities.forEach(entity => {
        if (!/^[A-Z][a-zA-Z0-9]*$/.test(entity.name)) {
          throw new Error(`实体名称格式错误: ${entity.name}`);
        }
      });
    },
    
    // 关系验证
    validateRelationships: (relationships: Relationship[]) => {
      relationships.forEach(rel => {
        if (rel.type === 'OneToMany' && !rel.otherEntityField) {
          console.warn(`建议为 ${rel.from} -> ${rel.to} 关系设置外键字段`);
        }
      });
    },
    
    // 数据库约束验证
    validateConstraints: (entities: Entity[]) => {
      entities.forEach(entity => {
        entity.fields.forEach(field => {
          if (field.type === 'String' && !field.validation?.maxlength) {
            console.warn(`建议为 ${entity.name}.${field.name} 设置最大长度`);
          }
        });
      });
    }
  };
  
  return validator;
};

实体关系设计

1. 高级关系映射

// 复杂关系设计示例
entity BlogPost {
  title String required maxlength(100)
  content TextBlob required
  publishDate Instant
  isPublished Boolean
  viewCount Long
  slug String required unique
}

entity Tag {
  name String required unique maxlength(30)
  color String pattern(/^#[0-9A-Fa-f]{6}$/)
}

entity Comment {
  content TextBlob required
  commentDate Instant required
  isApproved Boolean
  authorName String required maxlength(50)
  authorEmail String required
}

entity User {
  username String required unique minlength(3) maxlength(50)
  email String required unique
  firstName String maxlength(50)
  lastName String maxlength(50)
}

// 多对多关系(文章-标签)
relationship ManyToMany {
  BlogPost{tags} to Tag{posts}
}

// 层级关系(评论回复)
relationship OneToMany {
  Comment{replies} to Comment{parent}
  BlogPost{comments} to Comment{post required}
  User{posts} to BlogPost{author required}
  User{comments} to Comment{commenter required}
}

// 自引用关系示例
entity Category {
  name String required
  description String
  level Integer
  sortOrder Integer
}

relationship OneToMany {
  Category{children} to Category{parent}
}

2. 数据库索引优化

// 生成的实体类中添加索引
@Entity
@Table(name = "blog_post", indexes = {
    @Index(name = "idx_blog_post_slug", columnList = "slug"),
    @Index(name = "idx_blog_post_published", columnList = "is_published"),
    @Index(name = "idx_blog_post_publish_date", columnList = "publish_date"),
    @Index(name = "idx_blog_post_author", columnList = "author_id")
})
public class BlogPost {
    // 实体字段...
    
    @Column(name = "slug", unique = true, nullable = false)
    private String slug;
    
    @Column(name = "is_published")
    private Boolean isPublished;
    
    @Column(name = "publish_date")
    private Instant publishDate;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "author_id")
    private User author;
}

蓝图定制开发

1. 创建自定义蓝图

# 生成蓝图项目
jhipster generate-blueprint

# 蓝图配置
Blueprint name: enterprise
Description: Enterprise features blueprint
Local blueprint: Yes
CLI: Yes

2. 蓝图生成器实现

// generators/app/generator.js
import BaseApplicationGenerator from 'generator-jhipster/generators/base-application';

export default class extends BaseApplicationGenerator {
  constructor(args, opts, features) {
    super(args, opts, features);
  }

  get [BaseApplicationGenerator.INITIALIZING]() {
    return this.asInitializingTaskGroup({
      async parseBlueprint() {
        await this.parseCurrentJHipsterCommand();
      }
    });
  }

  get [BaseApplicationGenerator.PROMPTING]() {
    return this.asPromptingTaskGroup({
      async askForEnterpriseFeatures() {
        const answers = await this.prompt([
          {
            type: 'confirm',
            name: 'enableAudit',
            message: '启用审计功能?',
            default: true
          },
          {
            type: 'confirm', 
            name: 'enableMultiTenant',
            message: '启用多租户?',
            default: false
          },
          {
            type: 'list',
            name: 'loggingFramework',
            message: '选择日志框架',
            choices: ['logback', 'log4j2'],
            default: 'logback'
          }
        ]);

        this.blueprintStorage.set(answers);
      }
    });
  }

  get [BaseApplicationGenerator.WRITING]() {
    return this.asWritingTaskGroup({
      async writeEnterpriseFiles() {
        if (this.blueprintStorage.get('enableAudit')) {
          await this.writeFiles({
            sections: {
              auditFiles: [
                {
                  templates: [
                    'src/main/java/_package_/config/audit/AuditConfiguration.java.ejs',
                    'src/main/java/_package_/config/audit/AuditEventConverter.java.ejs'
                  ]
                }
              ]
            }
          });
        }

        if (this.blueprintStorage.get('enableMultiTenant')) {
          await this.writeFiles({
            sections: {
              multiTenantFiles: [
                {
                  templates: [
                    'src/main/java/_package_/config/tenant/TenantContext.java.ejs',
                    'src/main/java/_package_/config/tenant/TenantInterceptor.java.ejs'
                  ]
                }
              ]
            }
          });
        }
      }
    });
  }
}

3. 蓝图模板定制

// templates/src/main/java/_package_/config/audit/AuditConfiguration.java.ejs
package <%= packageName %>.config.audit;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;

import java.util.Optional;

@Configuration
@EnableJpaAuditing(auditorAwareRef = "auditorProvider")
public class AuditConfiguration {

    @Bean
    public AuditorAware<String> auditorProvider() {
        return () -> Optional.ofNullable(SecurityContextHolder.getContext())
            .map(SecurityContext::getAuthentication)
            .filter(Authentication::isAuthenticated)
            .map(Authentication::getName);
    }
}

CI/CD集成配置

1. GitHub Actions配置

# .github/workflows/ci.yml
name: CI/CD Pipeline

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    
    services:
      postgres:
        image: postgres:13
        env:
          POSTGRES_PASSWORD: postgres
          POSTGRES_DB: testdb
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
          
    steps:
    - uses: actions/checkout@v3
    
    - name: Setup Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
        cache: 'npm'
        
    - name: Setup Java
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'temurin'
        
    - name: Cache Maven dependencies
      uses: actions/cache@v3
      with:
        path: ~/.m2
        key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
        
    - name: Install dependencies
      run: npm ci
      
    - name: Run backend tests
      run: ./mvnw clean verify
      
    - name: Run frontend tests
      run: npm test
      
    - name: Build application
      run: ./mvnw clean package -Pprod
      
    - name: Build Docker image
      run: |
        docker build -t ${{ github.repository }}:${{ github.sha }} .
        
    - name: Run security scan
      uses: securecodewarrior/github-action-add-sarif@v1
      with:
        sarif-file: 'security-scan-results.sarif'

  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Deploy to staging
      run: |
        # Kubernetes deployment
        kubectl apply -f k8s/

2. Jenkins Pipeline配置

// Jenkinsfile
pipeline {
    agent any
    
    environment {
        DOCKER_REGISTRY = 'your-registry.com'
        IMAGE_NAME = 'enterprise-app'
        KUBECONFIG = credentials('kubeconfig')
    }
    
    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
        
        stage('Test') {
            parallel {
                stage('Backend Tests') {
                    steps {
                        sh './mvnw clean test'
                    }
                    post {
                        always {
                            publishTestResults testsPattern: 'target/surefire-reports/*.xml'
                        }
                    }
                }
                
                stage('Frontend Tests') {
                    steps {
                        sh 'npm test -- --watchAll=false --coverage'
                    }
                    post {
                        always {
                            publishCoverage adapters: [
                                coberturaAdapter('coverage/cobertura-coverage.xml')
                            ]
                        }
                    }
                }
            }
        }
        
        stage('Quality Gate') {
            steps {
                withSonarQubeEnv('SonarQube') {
                    sh './mvnw sonar:sonar'
                }
                
                timeout(time: 10, unit: 'MINUTES') {
                    waitForQualityGate abortPipeline: true
                }
            }
        }
        
        stage('Build') {
            steps {
                sh './mvnw clean package -Pprod'
                
                script {
                    def image = docker.build("${DOCKER_REGISTRY}/${IMAGE_NAME}:${BUILD_NUMBER}")
                    docker.withRegistry("https://${DOCKER_REGISTRY}", 'docker-registry-credentials') {
                        image.push()
                        image.push('latest')
                    }
                }
            }
        }
        
        stage('Deploy') {
            when {
                branch 'main'
            }
            steps {
                sh """
                    helm upgrade --install enterprise-app ./helm-chart \
                        --set image.tag=${BUILD_NUMBER} \
                        --set database.password=${env.DB_PASSWORD} \
                        --namespace production
                """
            }
        }
    }
    
    post {
        failure {
            emailext (
                subject: "Build Failed: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
                body: "Build failed. Check console output at ${env.BUILD_URL}",
                to: "${env.CHANGE_AUTHOR_EMAIL}"
            )
        }
    }
}

3. GitLab CI/CD配置

# .gitlab-ci.yml
stages:
  - test
  - build
  - security
  - deploy

variables:
  DOCKER_DRIVER: overlay2
  MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
  
cache:
  paths:
    - .m2/repository/
    - node_modules/

test:backend:
  stage: test
  image: openjdk:17-jdk
  services:
    - postgres:13
  variables:
    POSTGRES_DB: testdb
    POSTGRES_USER: postgres
    POSTGRES_PASSWORD: postgres
  script:
    - ./mvnw clean test
  artifacts:
    reports:
      junit:
        - target/surefire-reports/*.xml
    paths:
      - target/
      
test:frontend:
  stage: test
  image: node:18
  script:
    - npm ci
    - npm run test:ci
  coverage: '/Lines\s*:\s*(\d+\.?\d*)%/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage/cobertura-coverage.xml

security:scan:
  stage: security
  image: owasp/dependency-check-cli:latest
  script:
    - dependency-check --project "Enterprise App" --scan . --format JSON --out dependency-check-report.json
  artifacts:
    reports:
      dependency_scanning: dependency-check-report.json
      
build:image:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  only:
    - main
    - develop

deploy:staging:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl config use-context $STAGING_CONTEXT
    - kubectl set image deployment/enterprise-app app=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  environment:
    name: staging
    url: https://staging.enterprise-app.com
  only:
    - develop

deploy:production:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl config use-context $PRODUCTION_CONTEXT 
    - kubectl set image deployment/enterprise-app app=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  environment:
    name: production
    url: https://enterprise-app.com
  when: manual
  only:
    - main

生产环境部署

1. Docker化部署

# 多阶段构建Dockerfile
FROM node:18-alpine AS frontend-build
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build:prod

FROM maven:3.8.6-openjdk-17 AS backend-build
WORKDIR /app
COPY pom.xml .
COPY src ./src
COPY --from=frontend-build /app/target/classes/static ./src/main/resources/static
RUN mvn clean package -Pprod -DskipTests

FROM openjdk:17-jre-slim
VOLUME /tmp
EXPOSE 8080

# 安全用户
RUN groupadd -r appuser && useradd --no-log-init -r -g appuser appuser
USER appuser

COPY --from=backend-build /app/target/*.jar app.jar

# JVM优化参数
ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0 -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap"

ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /app.jar"]

2. Kubernetes部署配置

# k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: enterprise-app
  namespace: production
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  selector:
    matchLabels:
      app: enterprise-app
  template:
    metadata:
      labels:
        app: enterprise-app
        version: "v1.0"
    spec:
      containers:
      - name: app
        image: your-registry.com/enterprise-app:latest
        ports:
        - containerPort: 8080
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "prod"
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: url
        - name: DATABASE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: password
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /management/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /management/health/readiness
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
        volumeMounts:
        - name: app-config
          mountPath: /config
          readOnly: true
      volumes:
      - name: app-config
        configMap:
          name: enterprise-app-config
---
apiVersion: v1
kind: Service
metadata:
  name: enterprise-app-service
  namespace: production
spec:
  selector:
    app: enterprise-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: enterprise-app-ingress
  namespace: production
  annotations:
    kubernetes.io/ingress.class: "nginx"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/rate-limit: "100"
spec:
  tls:
  - hosts:
    - enterprise-app.com
    secretName: enterprise-app-tls
  rules:
  - host: enterprise-app.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: enterprise-app-service
            port:
              number: 80

3. Helm Chart配置

# helm-chart/values.yaml
replicaCount: 3

image:
  repository: your-registry.com/enterprise-app
  tag: "latest"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80
  targetPort: 8080

ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: nginx
    cert-manager.io/cluster-issuer: letsencrypt-prod
  hosts:
    - host: enterprise-app.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: enterprise-app-tls
      hosts:
        - enterprise-app.com

resources:
  limits:
    cpu: 500m
    memory: 1Gi
  requests:
    cpu: 250m
    memory: 512Mi

autoscaling:
  enabled: true
  minReplicas: 3
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80
  targetMemoryUtilizationPercentage: 80

database:
  host: postgres-service
  port: 5432
  name: enterprise_db
  username: enterprise_user

redis:
  enabled: true
  host: redis-service
  port: 6379

monitoring:
  enabled: true
  serviceMonitor:
    enabled: true
    interval: 30s

性能优化策略

1. 数据库优化

// 数据库连接池优化 - application-prod.yml
spring:
  datasource:
    hikari:
      connection-timeout: 20000
      minimum-idle: 10
      maximum-pool-size: 20
      idle-timeout: 300000
      max-lifetime: 1200000
      auto-commit: false
  jpa:
    properties:
      hibernate:
        jdbc:
          batch_size: 25
        order_inserts: true
        order_updates: true
        batch_versioned_data: true
        connection:
          provider_disables_autocommit: true
        cache:
          use_second_level_cache: true
          use_query_cache: true
          region:
            factory_class: org.hibernate.cache.jcache.JCacheRegionFactory
// 实体查询优化
@Entity
@Table(name = "product")
@NamedEntityGraph(
    name = "Product.withCategoryAndReviews",
    attributeNodes = {
        @NamedAttributeNode("category"),
        @NamedAttributeNode(value = "reviews", subgraph = "reviews-subgraph")
    },
    subgraphs = {
        @NamedSubgraph(
            name = "reviews-subgraph",
            attributeNodes = {@NamedAttributeNode("author")}
        )
    }
)
public class Product {
    // 实体字段...
}

@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    
    @Query("SELECT p FROM Product p WHERE p.category.id = :categoryId AND p.isActive = true")
    @EntityGraph(value = "Product.withCategoryAndReviews")
    List<Product> findActiveByCategoryId(@Param("categoryId") Long categoryId);
    
    @Query(value = "SELECT * FROM product p WHERE MATCH(p.name, p.description) AGAINST (?1 IN NATURAL LANGUAGE MODE)", 
           nativeQuery = true)
    List<Product> findByFullTextSearch(String searchTerm);
}

2. 缓存策略

// Redis缓存配置
@Configuration
@EnableCaching
public class CacheConfiguration {
    
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(30))
            .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
            .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));
        
        return RedisCacheManager.builder(connectionFactory)
            .cacheDefaults(config)
            .transactionAware()
            .build();
    }
}

// 服务层缓存应用
@Service
@Transactional
public class ProductService {
    
    @Cacheable(value = "products", key = "#categoryId + '_' + #pageable.pageNumber")
    public Page<ProductDTO> findByCategory(Long categoryId, Pageable pageable) {
        return productRepository.findActiveByCategoryId(categoryId, pageable)
            .map(productMapper::toDto);
    }
    
    @CacheEvict(value = "products", allEntries = true)
    public ProductDTO save(ProductDTO productDTO) {
        Product product = productMapper.toEntity(productDTO);
        product = productRepository.save(product);
        return productMapper.toDto(product);
    }
}

3. 前端性能优化

// Angular组件优化
@Component({
  selector: 'app-product-list',
  templateUrl: './product-list.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush,  // 性能优化
  standalone: true,
  imports: [CommonModule, RouterModule]
})
export class ProductListComponent implements OnInit {
  products$ = new BehaviorSubject<Product[]>([]);
  loading$ = new BehaviorSubject<boolean>(false);
  
  // 虚拟滚动支持
  @ViewChild(CdkVirtualScrollViewport) viewport!: CdkVirtualScrollViewport;
  
  constructor(
    private productService: ProductService,
    private cdr: ChangeDetectorRef
  ) {}
  
  // 延迟加载
  @debounce(300)
  onSearch(term: string): void {
    this.loading$.next(true);
    this.productService.search(term)
      .pipe(
        finalize(() => this.loading$.next(false))
      )
      .subscribe(products => {
        this.products$.next(products);
        this.cdr.markForCheck();
      });
  }
  
  // 追踪函数优化
  trackByProductId(index: number, product: Product): number {
    return product.id;
  }
}
// 服务层优化
@Injectable({
  providedIn: 'root'
})
export class ProductService {
  private readonly cache = new Map<string, Observable<any>>();
  
  constructor(private http: HttpClient) {}
  
  // 请求缓存
  getProducts(categoryId?: number): Observable<Product[]> {
    const cacheKey = `products_${categoryId || 'all'}`;
    
    if (!this.cache.has(cacheKey)) {
      const request$ = this.http.get<Product[]>(`/api/products`, {
        params: categoryId ? { categoryId: categoryId.toString() } : {}
      }).pipe(
        shareReplay(1),
        // 5分钟后清除缓存
        delay(300000),
        tap(() => this.cache.delete(cacheKey))
      );
      
      this.cache.set(cacheKey, request$);
    }
    
    return this.cache.get(cacheKey)!;
  }
  
  // 分页加载
  getProductsPaged(page: number, size: number = 20): Observable<PageResponse<Product>> {
    return this.http.get<PageResponse<Product>>('/api/products', {
      params: { page: page.toString(), size: size.toString() }
    });
  }
}

监控与运维

1. 应用监控配置

# Prometheus配置
management:
  endpoints:
    web:
      exposure:
        include: "*"
  endpoint:
    health:
      show-details: always
    metrics:
      enabled: true
  metrics:
    export:
      prometheus:
        enabled: true
    distribution:
      percentiles-histogram:
        http.server.requests: true
      percentiles:
        http.server.requests: 0.5, 0.9, 0.95, 0.99
      slo:
        http.server.requests: 10ms,50ms,100ms,200ms,500ms

2. 自定义监控指标

// 业务指标监控
@Component
public class BusinessMetrics {
    
    private final Counter orderCounter;
    private final Timer orderProcessingTimer;
    private final Gauge activeUsersGauge;
    
    public BusinessMetrics(MeterRegistry meterRegistry) {
        this.orderCounter = Counter.builder("orders.created")
            .description("Total orders created")
            .register(meterRegistry);
            
        this.orderProcessingTimer = Timer.builder("order.processing.time")
            .description("Order processing time")
            .register(meterRegistry);
            
        this.activeUsersGauge = Gauge.builder("users.active")
            .description("Currently active users")
            .register(meterRegistry, this, BusinessMetrics::getActiveUserCount);
    }
    
    public void recordOrderCreated() {
        orderCounter.increment();
    }
    
    public void recordOrderProcessingTime(Duration duration) {
        orderProcessingTimer.record(duration);
    }
    
    private double getActiveUserCount() {
        // 实际的活跃用户统计逻辑
        return sessionService.getActiveUserCount();
    }
}

3. 日志聚合配置

<!-- logback-spring.xml -->
<configuration>
    <springProfile name="prod">
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                <providers>
                    <timestamp/>
                    <logLevel/>
                    <loggerName/>
                    <mdc/>
                    <message/>
                    <stackTrace/>
                </providers>
            </encoder>
        </appender>
        
        <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>/var/log/app/application.log</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
                <fileNamePattern>/var/log/app/application.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
                <maxFileSize>100MB</maxFileSize>
                <maxHistory>30</maxHistory>
                <totalSizeCap>3GB</totalSizeCap>
            </rollingPolicy>
            <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                <providers>
                    <timestamp/>
                    <logLevel/>
                    <loggerName/>
                    <mdc/>
                    <message/>
                    <stackTrace/>
                </providers>
            </encoder>
        </appender>
        
        <root level="INFO">
            <appender-ref ref="STDOUT"/>
            <appender-ref ref="FILE"/>
        </root>
    </springProfile>
</configuration>

故障排除与调优

1. 常见问题诊断

# 性能分析脚本
#!/bin/bash

# JVM性能分析
echo "=== JVM 内存使用情况 ==="
jcmd <PID> GC.class_histogram | head -20

echo "=== 线程转储 ==="
jcmd <PID> Thread.print > thread_dump.txt

echo "=== 堆转储 ==="
jcmd <PID> GC.run_finalization
jcmd <PID> VM.gc
jmap -dump:format=b,file=heap_dump.hprof <PID>

# 数据库连接分析
echo "=== 数据库连接池状态 ==="
curl -s http://localhost:8080/management/metrics/hikaricp.connections | jq

# 缓存命中率
echo "=== 缓存统计 ==="
curl -s http://localhost:8080/management/metrics/cache.gets | jq

2. 生产环境调优清单

# 生产环境配置检查清单
production_checklist:
  jvm_settings:
    - name: "堆内存设置"
      check: "-Xmx4g -Xms4g"
      status: "✓"
    - name: "GC算法选择" 
      check: "-XX:+UseG1GC"
      status: "✓"
    - name: "GC日志"
      check: "-Xloggc:gc.log -XX:+PrintGCDetails"
      status: "✓"
      
  database_settings:
    - name: "连接池大小"
      check: "maximum-pool-size: 20"
      status: "✓"
    - name: "索引优化"
      check: "主要查询字段已建立索引"
      status: "✓"
    - name: "慢查询监控"
      check: "slow_query_log = 1"
      status: "✓"
      
  security_settings:
    - name: "HTTPS配置"
      check: "SSL证书有效"
      status: "✓"
    - name: "安全头设置"
      check: "CSP, HSTS等已配置"
      status: "✓"
    - name: "敏感信息保护"
      check: "密码等已加密存储"
      status: "✓"
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值