简介
SonarQube是什么
SonarQube 是一个用于代码质量管理的开源平台,用于管理源代码的质量。 通过插件形式,可以支持包括 java, C#, C/C , PL/SQL, Cobol, JavaScrip, Groovy 等等二十几种编程语言的代码质量管理与检测。
Sonar可以从以下七个维度检测代码质量,而作为开发人员至少需要处理前5种代码质量问题。
1. 不遵循代码标准
sonar可以通过PMD,CheckStyle,Findbugs等等代码规则检测工具规范代码编写。
2. 潜在的缺陷
sonar可以通过PMD,CheckStyle,Findbugs等等代码规则检测工具检 测出潜在的缺陷。
3. 糟糕的复杂度分布
文件、类、方法等,如果复杂度过高将难以改变,这会使得开发人员 难以理解它们, 且如果没有自动化的单元测试,对于程序中的任何组件的改变都将可能导致需要全面的回归测试。
4. 重复
显然程序中包含大量复制粘贴的代码是质量低下的,sonar可以展示 源码中重复严重的地方。
5. 注释不足或者过多
没有注释将使代码可读性变差,特别是当不可避免地出现人员变动 时,程序的可读性将大幅下降 而过多的注释又会使得开发人员将精力过多地花费在阅读注释上,亦违背初衷。
6. 缺乏单元测试
sonar可以很方便地统计并展示单元测试覆盖率。
7. 糟糕的设计
通过sonar可以找出循环,展示包与包、类与类之间的相互依赖关系,可以检测自定义的架构规则 通过sonar可以管理第三方的jar包,可以利用LCOM4检测单个任务规则的应用情况, 检测耦合。
为神马要分析我的代码
为什么要在项目中使用SonarQube,从上面的描述已经可以略知一二了,最主要的原因就是提高代码质量,了解自己在编码过程中犯过的错误,让自己的代码更具有可读性和维护性。
声明
就算你天天分析自己的代码,如果不去思考发现的问题,其实意义也是不大的。我们应该借鉴持续改进的流程,在这个过程中有所收获。
实验环境
IP | 备注 |
---|---|
192.168.1.10 | JAVA、MySQL、sonarqube |
前置条件
1.mysql数据库 2.jdk
安装JDK
代码语言:javascript复制tar -zxf jdk-8u201-linux-x64.tar.gz
mv jdk1.8.0_201/ /usr/local/java
vim /etc/profile
#添加
export JAVA_HOME=/usr/local/java
export JRE_HOME=/usr/local/java/jre
export CLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
source /etc/profile #文件生效
java -version #查看版本
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)
安装mysql
代码语言:javascript复制wget http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
yum -y install mysql57-community-release-el7-11.noarch.rpm
yum repolist enabled | grep mysql.*
yum install mysql-community-server
grep 'temporary password' /var/log/mysqld.log #获取随机密码
vim /etc/my.cnf
添加【mysqld】下,设置修改密码强度策略
validate_password_policy=0
validate_password_length=1
systemctl start mysqld.service
mysql -uroot -p
Enter password:随机密码
mysql> set password = password('123.com'); #修改一个密码自定义
下载sonarqube
代码语言:javascript复制wget https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-7.7.zip
unzip sonarqube-7.7.zip
配置数据库
代码语言:javascript复制mysql> CREATE DATABASE sonar CHARACTER SET utf8 COLLATE utf8_general_ci; //设置编码格式
mysql> GRANT ALL ON sonar.* TO 'sonar'@'localhost' IDENTIFIED BY 'sonar'; //创建账号以及密码
mysql> GRANT ALL ON sonar.* TO 'sonar'@'%' IDENTIFIED BY 'sonar'; //赋予账号权限
mysql> FLUSH PRIVILEGES; //刷新权限
配置sonar
代码语言:javascript复制[root@localhost fxm]# cd /opt/sonar/sonarqube-7.7/conf //进入配置文件
[root@localhost conf]# ls
sonar.properties wrapper.conf
[root@localhost conf]# vim sonar.properties //配置文件
修改下面的参数
代码语言:javascript复制sonar.jdbc.username=sonar //创建的账号
sonar.jdbc.password=sonar // 创建的密码
sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance&useSSL=false
启动sonarqube
代码语言:javascript复制[root@localhost fxm]# cd /opt/sonar/sonarqube-7.7/bin/linux-x86-64
[root@localhost linux-x86-64]# ./sonar.sh start
结果报错。
代码语言:javascript复制Running SonarQube...
wrapper | --> Wrapper Started as Console
wrapper | Launching a JVM...
jvm 1 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
jvm 1 | Copyright 1999-2006 Tanuki Software, Inc. All Rights Reserved.
jvm 1 |
jvm 1 | 2018.06.23 23:41:55 INFO app[][o.s.a.AppFileSystem] Cleaning or creating temp directory /root/sonarqube/sonarqube-7.2/temp
jvm 1 | 2018.06.23 23:41:55 INFO app[][o.s.a.es.EsSettings] Elasticsearch listening on /127.0.0.1:9001
jvm 1 | 2018.06.23 23:41:55 INFO app[][o.s.a.p.ProcessLauncherImpl] Launch process[[key='es', ipcIndex=1, logFilenamePrefix=es]] from [/root/sonarqube/sonarqube-7.2/elasticsearch]: /root/sonarqube/sonarqube-7.2/elasticsearch/bin/elasticsearch -Epath.conf=/root/sonarqube/sonarqube-7.2/temp/conf/es
jvm 1 | 2018.06.23 23:41:55 INFO app[][o.s.a.SchedulerImpl] Waiting for Elasticsearch to be up and running
jvm 1 | 2018.06.23 23:41:55 INFO app[][o.e.p.PluginsService] no modules loaded
jvm 1 | 2018.06.23 23:41:55 INFO app[][o.e.p.PluginsService] loaded plugin [org.elasticsearch.transport.Netty4Plugin]
jvm 1 | 2018.06.23 23:41:56 WARN app[][o.s.a.p.AbstractProcessMonitor] Process exited with exit value [es]: 1
jvm 1 | 2018.06.23 23:41:56 INFO app[][o.s.a.SchedulerImpl] Process [es] is stopped
查资料发现原因,root用户无法启动es, 现在创建sonarUser用户并赋权
代码语言:javascript复制 [root@localhost fxm]#adduser sonarUser
[root@localhost fxm]#passwd sonarUser
Changing password for user sonarUser.
New password:
BAD PASSWORD: The password is shorter than 8 characters
Retype new password:
passwd: all authentication tokens updated successfully.
[root@localhost fxm]# chown -R sonarUser:sonarUser sonarqube-7.7
把sonarqube-7.7目录放在/home/新用户的目录下/ 到切换用户的时候可以看到
再次启动sonarqube
代码语言:javascript复制切换用户:su sonarUser
[sonarUser@localhost root]$ cd /home/sonarUser/
[sonarUser@localhost ~]$ ls
sonarqube-7.7
[sonarUser@localhost ~]$ cd sonarqube-7.7/bin/linux-x86-64/
[sonarUser@localhost linux-x86-64]$ ./sonar.sh start
启动成功后效果
所涉及的端口
启动成功,访问 ip 9000端口 默认账号密码是 admin 9000端口是默认端口。如果有需要,可以在conf 目录中的sonar.properties里进行修改
测试访问
启动报错,无法启动
报错现象
查看日志
代码语言:javascript复制这个是日志的路径sonarUser/sonarqube-7.7/logs
[sonarUser@k8s-n4 logs]$ ls
access.log es.log README.txt sonar.log web.log
如果无法启动多个日志都看一看
代码语言:javascript复制2021.01.07 16:09:27 ERROR web[][o.s.s.p.Platform] Background initialization failed. Stopping SonarQube
org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (2224 > 2048). You can change this value on the server by setting the max_allowed_packet' variable.
### The error may involve org.sonar.db.rule.RuleMapper.insertDefinition-Inline
### The error occurred while setting parameters
### Cause: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (2224 > 2048). You can change this value on the server by setting the max_allowed_packet' variable.
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:200)
at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:58)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
at com.sun.proxy.$Proxy41.insertDefinition(Unknown Source)
at org.sonar.db.rule.RuleDao.insert(RuleDao.java:165)
at org.sonar.server.rule.RegisterRules.createRuleDto(RegisterRules.java:419)
at org.sonar.server.rule.RegisterRules.lambda$registerRule$2(RegisterRules.java:348)
at org.sonar.server.rule.RegisterRules$$Lambda$1600/415652919.get(Unknown Source)
at java.util.Optional.orElseGet(Optional.java:267)
at org.sonar.server.rule.RegisterRules.registerRule(RegisterRules.java:347)
at org.sonar.server.rule.RegisterRules.start(RegisterRules.java:132)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.picocontainer.lifecycle.ReflectionLifecycleStrategy.invokeMethod(ReflectionLifecycleStrategy.java:110)
at org.picocontainer.lifecycle.ReflectionLifecycleStrategy.start(ReflectionLifecycleStrategy.java:89)
at org.picocontainer.injectors.AbstractInjectionFactory$LifecycleAdapter.start(AbstractInjectionFactory.java:84)
at org.picocontainer.behaviors.AbstractBehavior.start(AbstractBehavior.java:169)
at org.picocontainer.behaviors.Stored$RealComponentLifecycle.start(Stored.java:132)
at org.picocontainer.behaviors.Stored.start(Stored.java:110)
at org.picocontainer.DefaultPicoContainer.potentiallyStartAdapter(DefaultPicoContainer.java:1016)
at org.picocontainer.DefaultPicoContainer.startAdapters(DefaultPicoContainer.java:1009)
at org.picocontainer.DefaultPicoContainer.start(DefaultPicoContainer.java:767)
at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:135)
at org.sonar.server.platform.platformlevel.PlatformLevel.start(PlatformLevel.java:90)
at org.sonar.server.platform.platformlevel.PlatformLevelStartup.access$001(PlatformLevelStartup.java:46)
at org.sonar.server.platform.platformlevel.PlatformLevelStartup$1.doPrivileged(PlatformLevelStartup.java:82)
at org.sonar.server.user.DoPrivileged.execute(DoPrivileged.java:46)
at org.sonar.server.platform.platformlevel.PlatformLevelStartup.start(PlatformLevelStartup.java:79)
at org.sonar.server.platform.Platform.executeStartupTasks(Platform.java:196)
at org.sonar.server.platform.Platform.access$400(Platform.java:46)
at org.sonar.server.platform.Platform$1.lambda$doRun$1(Platform.java:121)
at org.sonar.server.platform.Platform$1$$Lambda$1535/1649202382.run(Unknown Source)
at org.sonar.server.platform.Platform$AutoStarterRunnable.runIfNotAborted(Platform.java:371)
at org.sonar.server.platform.Platform$1.doRun(Platform.java:121)
at org.sonar.server.platform.Platform$AutoStarterRunnable.run(Platform.java:355)
at java.lang.Thread.run(Thread.java:745)
Caused by: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (2224 > 2048). You can change this value on the server by setting the max_allowed_packet' variable.
at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3681)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2512)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2683)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2486)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1858)
at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1197)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:94)
at org.apache.commons.dbcp2.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:94)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:46)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74)
at org.apache.ibatis.executor.ReuseExecutor.doUpdate(ReuseExecutor.java:52)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
... 38 common frames omitted
2021.01.07 16:09:28 INFO web[][o.s.p.StopWatcher] Stopping process
原因:
查询报文太大(2224 > 2048),你可以在服务器上通过设置max_allowed_packet变量来改变这个值。
解决
代码语言:javascript复制检查mysql
mysql> show variables like '%max_allowed_packet%';
-------------------------- -------
| Variable_name | Value |
-------------------------- -------
| max_allowed_packet | 2048 |
| slave_max_allowed_packet | 2048 |
-------------------------- -------
2 rows in set (0.00 sec)
进行设置,索性一次调大一些
mysql> set global max_allowed_packet=1000000;
然后exit退出mysql界面,重新进入查看是否生效;
mysql> show variables like '%max_allowed_packet%';
-------------------------- -------
| Variable_name | Value |
-------------------------- -------
| max_allowed_packet | 999424|
| slave_max_allowed_packet | 2048 |
-------------------------- -------
2 rows in set (0.00 sec)
进行启动测试
代码语言:javascript复制./sonar.sh start
[sonarUser@k8s-n4 linux-x86-64]$ netstat -anput | grep 9000
tcp6 0 0 :::9000 :::* LISTEN 22939/java