本文目录导读:

我来提供一个完整的Java Sonar集成案例,涵盖本地环境和CI/CD流水线两种场景。
环境准备
安装SonarQube服务器
# 使用Docker快速启动SonarQube docker run -d --name sonarqube \ -p 9000:9000 \ -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true \ sonarqube:latest # 默认访问地址:http://localhost:9000 # 默认账号:admin 密码:admin
安装SonarScanner
# macOS brew install sonar-scanner # Linux wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.8.0.2856-linux.zip unzip sonar-scanner-cli-4.8.0.2856-linux.zip export PATH=$PATH:$(pwd)/sonar-scanner-4.8.0.2856-linux/bin
Maven项目集成
Maven配置(pom.xml)
<project>
<!-- ... 其他配置 ... -->
<properties>
<sonar.java.source>1.8</sonar.java.source>
<sonar.java.target>1.8</sonar.java.target>
<sonar.projectName>${project.artifactId}</sonar.projectName>
<sonar.projectKey>${project.groupId}:${project.artifactId}</sonar.projectKey>
<sonar.host.url>http://localhost:9000</sonar.host.url>
<sonar.login>${env.SONAR_TOKEN}</sonar.login>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.9.1.2184</version>
</plugin>
<!-- JaCoCo插件用于测试覆盖率 -->
<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>
</executions>
</plugin>
</plugins>
</build>
</project>
执行Sonar扫描
# 设置token(在SonarQube后台生成) export SONAR_TOKEN=your_generated_token # 执行扫描(自动运行测试并收集覆盖率) mvn clean verify sonar:sonar # 或者只运行Sonar分析 mvn sonar:sonar
Gradle项目集成
build.gradle配置
plugins {
id 'java'
id 'org.sonarqube' version '3.5.0.2730'
id 'jacoco'
}
group = 'com.example'
version = '1.0.0'
repositories {
mavenCentral()
}
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2'
testImplementation 'org.mockito:mockito-core:4.0.0'
}
// Sonar配置
sonarqube {
properties {
property "sonar.projectKey", "com.example:my-project"
property "sonar.projectName", "My Project"
property "sonar.projectVersion", version
property "sonar.host.url", "http://localhost:9000"
property "sonar.login", System.getenv("SONAR_TOKEN")
property "sonar.sourceEncoding", "UTF-8"
property "sonar.java.coveragePlugin", "jacoco"
}
}
// JaCoCo配置
jacocoTestReport {
reports {
xml.enabled true
html.enabled true
}
}
test {
useJUnitPlatform()
finalizedBy jacocoTestReport
}
执行扫描
# 运行测试并生成覆盖率报告 ./gradlew test jacocoTestReport # 执行Sonar扫描 ./gradlew sonarqube
CI/CD集成(Jenkins)
Jenkinsfile配置
pipeline {
agent any
environment {
SONAR_HOST_URL = 'http://sonarqube:9000'
SONAR_TOKEN = credentials('sonar-token')
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Build & Test') {
steps {
sh 'mvn clean verify'
}
post {
always {
junit 'target/surefire-reports/*.xml'
}
}
}
stage('SonarQube Analysis') {
steps {
withSonarQubeEnv('SonarQube') {
sh 'mvn sonar:sonar'
}
}
}
stage('Quality Gate') {
steps {
timeout(time: 1, unit: 'HOURS') {
waitForQualityGate abortPipeline: true
}
}
}
}
post {
success {
echo 'Pipeline succeeded!'
// 发送通知等
}
failure {
echo 'Pipeline failed!'
}
}
}
GitLab CI配置(.gitlab-ci.yml)
stages:
- build
- test
- sonar
variables:
SONAR_HOST_URL: "http://sonarqube:9000"
SONAR_TOKEN: $SONAR_TOKEN # 在GitLab中配置
cache:
paths:
- .m2/repository/
build:
stage: build
script:
- mvn clean compile
artifacts:
paths:
- target/
test:
stage: test
script:
- mvn test
- mvn jacoco:report
artifacts:
paths:
- target/surefire-reports/
- target/site/jacoco/
sonar:
stage: sonar
script:
- mvn sonar:sonar -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_TOKEN
only:
- master
- develop
- merge_requests
代码质量门禁配置
sonar-project.properties
# 项目基本信息 sonar.projectKey=com.example:my-project sonar.projectName=My Enterprise Project sonar.projectVersion=1.0.0 # 源码目录 sonar.sources=src/main/java sonar.tests=src/test/java # Java版本 sonar.java.source=11 sonar.java.target=11 # 测试覆盖率 sonar.jacoco.reportPath=target/jacoco.exec sonar.junit.reportsPath=target/surefire-reports # 编码规则 sonar.exclusions=**/dto/**,**/config/** sonar.test.exclusions=**/test/** # 质量配置文件 sonar.profile=Sonar way
自定义质量规则(示例)
// 自定义规则示例 - 禁止使用System.out.println
public class CustomRules {
@Rule(
key = "no-system-out",
name = "Avoid System.out.println",
description = "Should use logging framework instead of System.out",
severity = "MAJOR",
tags = {"bad-practice"}
)
public class NoSystemOut extends BaseTreeVisitor implements JavaFileScanner {
private JavaFileScannerContext context;
@Override
public void scanFile(JavaFileScannerContext context) {
this.context = context;
scan(context.getTree());
}
@Override
public void visitMethodInvocation(MethodInvocationTree tree) {
if (isSystemOutPrintln(tree)) {
context.reportIssue(this, tree, "Use logger instead of System.out.println");
}
super.visitMethodInvocation(tree);
}
private boolean isSystemOutPrintln(MethodInvocationTree tree) {
// 检查是否是System.out.println调用
IdentifierTree identifier = (IdentifierTree) tree.methodSelect();
return identifier != null &&
"println".equals(identifier.name()) &&
tree.arguments().size() == 1;
}
}
}
最佳实践案例
多模块项目配置
<!-- 根pom.xml -->
<project>
<modules>
<module>core</module>
<module>service</module>
<module>web</module>
<module>common</module>
</modules>
<properties>
<sonar.coverage.jacoco.xmlReportPaths>
${project.basedir}/../target/site/jacoco/jacoco.xml
</sonar.coverage.jacoco.xmlReportPaths>
</properties>
</project>
Docker集成
FROM maven:3.8.4-jdk-11 AS build WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline COPY src ./src RUN mvn clean verify FROM sonarsource/sonar-scanner-cli:4.8 AS sonar COPY --from=build /app /app WORKDIR /app CMD ["sonar-scanner", "-Dsonar.projectKey=my-project"]
完整的CI/CD流程示例
# docker-compose.yml
version: '3'
services:
sonarqube:
image: sonarqube:latest
ports:
- "9000:9000"
environment:
- SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true
volumes:
- sonarqube_data:/opt/sonarqube/data
- sonarqube_extensions:/opt/sonarqube/extensions
jenkins:
image: jenkins/jenkins:lts
ports:
- "8080:8080"
volumes:
- jenkins_home:/var/jenkins_home
environment:
- SONAR_HOST_URL=http://sonarqube:9000
volumes:
sonarqube_data:
sonarqube_extensions:
jenkins_home:
优化与故障排查
性能优化
// 使用增量分析
<properties>
<sonar.scm.disabled>true</sonar.scm.disabled>
<sonar.analysis.mode>incremental</sonar.analysis.mode>
</properties>
常见问题解决
# 问题1: 数据库连接失败 docker logs sonarqube # 问题2: 内存不足 export SONAR_SCANNER_OPTS="-Xmx1g" # 问题3: 扫描超时 sonar-scanner -Dsonar.analysis.timeout=600 # 问题4: 排除特定文件 -Dsonar.exclusions=**/generated/**,**/test/**
监控与告警配置
// 在pom.xml中配置质量门禁
<profile>
<id>sonar-quality-gate</id>
<build>
<plugins>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>sonar</goal>
</goals>
<configuration>
<sonarqualitygate>true</sonarqualitygate>
<sonarqualitygateTimeout>300</sonarqualitygateTimeout>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
验证与报告
# 查看分析结果 curl -u admin:admin http://localhost:9000/api/projects/search?key=my-project # 获取质量门禁状态 curl -u admin:admin http://localhost:9000/api/qualitygates/project_status?projectKey=my-project # 导出分析报告 sonar-scanner -Dsonar.report.export.path=sonar-report.json
这个案例涵盖了Java项目Sonar集成的完整流程,从环境搭建到CI/CD集成,再到质量门禁配置,根据实际需求,可以调整相应配置。