Spring Boot集成checkstyle快速入门Demo

1.什么是checkstyle?

CheckStyle是一个帮助程序员来遵守一直的编码规范的工具。默认,它支持google 和sun 的java style guide。而且它是高度可配置的,允许自定义编码规范,并可以对各种IDE(eclipse、Intellij)和构建工具(maven,gradle)的支持。

2.配置插件

在maven中一个名为maven-checkstyle-plugin的插件,用于执行CheckStyle task。下面是一个简单的配置。

<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-checkstyle-plugin</artifactId><version>3.1.2</version> <!-- Use the latest version here --><configuration><configLocation>/config/checkstyle.xml</configLocation><encoding>UTF-8</encoding><consoleOutput>true</consoleOutput><failsOnError>true</failsOnError><linkXRef>false</linkXRef></configuration><executions><execution><id>check-style</id><phase>validate</phase><goals><goal>check</goal></goals></execution></executions></plugin><!-- ... other plugins ... --></plugins>
</build>

  我们定义了在maven lifecycle的validate阶段执行check task,并且如果发现有违反标准的情况就会fail当前的build。 maven-checkstyle-plugin内置了4种规范.

  • config/sun_checks.xml
  • config/maven_checks.xml
  • config/turbine_checks.xml
  • config/avalon_checks.xml

其中sun_checks.xml为默认值。如果想要使用其他三种规范,则只需配置configuration。下面是使用maven_checks.xml的示例。

3.个性化配置

我们可以使用默认的规范未见,当然也支持自定义。下面是google的一个checkstyle规范文件。

<?xml version="1.0"?>
<!DOCTYPE module PUBLIC"-//Puppy Crawl//DTD Check Configuration 1.3//EN""http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<module name="Checker"><!-- 检查文件是否以一个空行结束 --><module name="NewlineAtEndOfFile"/><!-- 文件长度不超过1500行 --><module name="FileLength"><property name="max" value="1500"/></module><!-- 修复Checkstyle version版本大于8.23报错:TreeWalker is not allowed as a parent of LineLength 问题,移动LineLength到这里解决 --><!-- 每行不超过140个字符 --><module name="LineLength"><property name="max" value="140" /></module><!-- 每个java文件一个语法树 --><module name="TreeWalker"><!-- import检查--><!-- 检查是否从非法的包中导入了类 --><module name="IllegalImport"/><!-- 检查是否导入了多余的包 --><module name="RedundantImport"/><!-- 没用的import检查,比如:1.没有被用到2.重复的3.import java.lang的4.import 与该类在同一个package的 --><module name="UnusedImports" /><!-- 注释检查 --><!-- 检查构造函数的javadoc --><module name="JavadocType"><property name="allowUnknownTags" value="true"/><message key="javadoc.missing" value="类注释:缺少Javadoc注释。"/></module><!-- 命名检查 --><!-- 局部的final变量,包括catch中的参数的检查 --><module name="LocalFinalVariableName" /><!-- 局部的非final型的变量,包括catch中的参数的检查 --><module name="LocalVariableName" /><!-- 包名的检查(只允许小写字母),默认^[a-z]+(\.[a-zA-Z_][a-zA-Z_0-9_]*)*$ --><module name="PackageName"><property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$" /><message key="name.invalidPattern" value="包名 ''{0}'' 要符合 ''{1}''格式."/></module><!-- 仅仅是static型的变量(不包括static final型)的检查 --><module name="StaticVariableName" /><!-- Class或Interface名检查,默认^[A-Z][a-zA-Z0-9]*$--><module name="TypeName"><property name="severity" value="warning"/><message key="name.invalidPattern" value="名称 ''{0}'' 要符合 ''{1}''格式."/></module><!-- 非static型变量的检查 --><module name="MemberName" /><!-- 方法名的检查 --><module name="MethodName" /><!-- 方法的参数名 --><module name="ParameterName " /><!-- 常量名的检查(只允许大写),默认^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$ --><module name="ConstantName" /><!-- 定义检查 --><!-- 检查数组类型定义的样式 --><module name="ArrayTypeStyle"/><!-- 检查long型定义是否有大写的“L” --><module name="UpperEll"/><!-- 长度检查 --><!-- 方法不超过50行 --><module name="MethodLength"><property name="tokens" value="METHOD_DEF" /><property name="max" value="50" /></module><!-- 方法的参数个数不超过5个。 并且不对构造方法进行检查--><module name="ParameterNumber"><property name="max" value="5" /><property name="ignoreOverriddenMethods" value="true"/><property name="tokens" value="METHOD_DEF" /></module><!-- 空格检查--><!-- 方法名后跟左圆括号"(" --><module name="MethodParamPad" /><!-- 在类型转换时,不允许左圆括号右边有空格,也不允许与右圆括号左边有空格 --><module name="TypecastParenPad" /><!-- 检查在某个特定关键字之后应保留空格 --><module name="NoWhitespaceAfter"/><!-- 检查在某个特定关键字之前应保留空格 --><module name="NoWhitespaceBefore"/><!-- 操作符换行策略检查 --><module name="OperatorWrap"/><!-- 圆括号空白 --><module name="ParenPad"/><!-- 检查分隔符是否在空白之后 --><module name="WhitespaceAfter"/><!-- 检查分隔符周围是否有空白 --><module name="WhitespaceAround"/><!-- 修饰符检查 --><!-- 检查修饰符的顺序是否遵照java语言规范,默认public、protected、private、abstract、static、final、transient、volatile、synchronized、native、strictfp --><module name="ModifierOrder"/><!-- 检查接口和annotation中是否有多余修饰符,如接口方法不必使用public --><module name="RedundantModifier"/><!-- 代码块检查 --><!-- 检查是否有嵌套代码块 --><module name="AvoidNestedBlocks"/><!-- 检查是否有空代码块 --><module name="EmptyBlock"/><!-- 检查左大括号位置 --><module name="LeftCurly"/><!-- 检查代码块是否缺失{} --><module name="NeedBraces"/><!-- 检查右大括号位置 --><module name="RightCurly"/><!-- 代码检查 --><!-- 检查空的代码段 --><module name="EmptyStatement"/><!-- 检查在重写了equals方法后是否重写了hashCode方法 --><module name="EqualsHashCode"/><!-- 检查局部变量或参数是否隐藏了类中的变量 --><module name="HiddenField"><property name="tokens" value="VARIABLE_DEF"/></module><!-- 检查子表达式中是否有赋值操作 --><module name="InnerAssignment"/><!-- 检查switch语句是否有default --><module name="MissingSwitchDefault"/><!-- 检查是否有过度复杂的布尔表达式 --><module name="SimplifyBooleanExpression"/><!-- 检查是否有过于复杂的布尔返回代码段 --><module name="SimplifyBooleanReturn"/><!-- 类设计检查 --><!-- 检查类是否为扩展设计l --><!-- 检查只有private构造函数的类是否声明为final --><module name="FinalClass"/><!-- 检查接口是否仅定义类型 --><module name="InterfaceIsType"/><!-- 检查类成员的可见度 检查类成员的可见性。只有static final 成员是public的除非在本检查的protectedAllowed和packagedAllowed属性中进行了设置--><module name="VisibilityModifier"><property name="packageAllowed" value="true"/><property name="protectedAllowed" value="true"/></module><!-- 语法 --><!-- String的比较不能用!= 和 == --><module name="StringLiteralEquality"/><!-- 限制for循环最多嵌套2层 --><module name="NestedForDepth"><property name="max" value="2"/></module><!-- if最多嵌套3层 --><module name="NestedIfDepth"><property name="max" value="3"/></module><!-- 检查未被注释的main方法,排除以Appllication结尾命名的类 --><module name="UncommentedMain"><property name="excludedClasses" value=".*[Application,Test]$"/></module><!-- 禁止使用System.out.println --><module name="Regexp"><property name="format" value="System\.out\.println"/><property name="illegalPattern" value="true"/></module><!-- return个数 3个--><module name="ReturnCount"><property name="max" value="3"/></module><!--try catch 异常处理数量 3--><module name="NestedTryDepth "><property name="max" value="3"/></module><!-- clone方法必须调用了super.clone() --><module name="SuperClone" /><!-- finalize 必须调用了super.finalize() --><module name="SuperFinalize" /></module>
</module>

4.测试

mvn checkstyle:check

检测结果

<?xml version="1.0" encoding="UTF-8"?>
<checkstyle version="9.3">
<file name="/Users/liuhaihua/IdeaProjects/springboot-demo/checkstyle/src/main/java/com/et/checkstyle/controller/HelloWorldController.java">
<error line="1" severity="error" message="file end without new line。" source="com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck"/>
<error line="10" column="34" severity="error" message="&apos;{&apos; need an blankspace。" source="com.puppycrawl.tools.checkstyle.checks.whitespace.WhitespaceAroundCheck"/>
</file>
</checkstyle>

5.跳过对指定文件的某些检查

如果对于指定文件检查出了一些问题,但是你想忽略它,则可以使用suppression。 例如在上述例子中有一个checkstyle error是说某行超过了100字符。如果我们不想修复这个错误怎么办那?可以将其suppress掉。 方法是建立一个checkstyle-suppressions.xml文件。其中加入下述内容

<?xml version="1.0"?><!DOCTYPE suppressions PUBLIC"-//Puppy Crawl//DTD Suppressions 1.0//EN""http://www.puppycrawl.com/dtds/suppressions_1_0.dtd"><suppressions><suppress checks="NewlineAtEndOfFileCheck"files="HelloWorldController.java"/>
</suppressions>

然后配置maven-checkstyel-plugin设置suppressionsLocation

<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-checkstyle-plugin</artifactId><version>3.1.2</version> <!-- Use the latest version here --><configuration><configLocation>${basedir}/config/maven_checks.xml</configLocation><suppressionsLocation>${basedir}/config/checkstyle-suppressions.xml</suppressionsLocation><encoding>UTF-8</encoding><consoleOutput>true</consoleOutput><failsOnError>true</failsOnError><linkXRef>false</linkXRef></configuration><executions><execution><id>check-style</id><phase>validate</phase><goals><goal>check</goal></goals></execution></executions></plugin><!-- ... other plugins ... --></plugins>
</build>

以上只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

  • GitHub - Harries/springboot-demo: a simple springboot demo with some components for example: redis,solr,rockmq and so on.

6.引用

  • checkstyle – Checkstyle 10.17.0
  • Spring Boot集成checkstyle快速入门Demo | Harries Blog™

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/864545.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

昇思MindSpore学习笔记2-01 LLM原理和实践 --基于 MindSpore 实现 BERT 对话情绪识别

摘要&#xff1a; 通过识别BERT对话情绪状态的实例&#xff0c;展现在昇思MindSpore AI框架中大语言模型的原理和实际使用方法、步骤。 一、环境配置 %%capture captured_output # 实验环境已经预装了mindspore2.2.14&#xff0c;如需更换mindspore版本&#xff0c;可更改下…

前端在for循环中使用Element-plus el-select中的@click.native动态传参

<el-table ref"table" :data"editTableVariables" cell-dblclick"handleRowDblClick" style"width: 100%" > <!-- el-table-column: 表格列组件&#xff0c;定义每列的展示内容和属性 --><el-table-column prop&q…

8种数据迁移工具

前言 最近有些小伙伴问我&#xff0c;ETL数据迁移工具该用哪些。 ETL(是Extract-Transform-Load的缩写&#xff0c;即数据抽取、转换、装载的过程)&#xff0c;对于企业应用来说&#xff0c;我们经常会遇到各种数据的处理、转换、迁移的场景。 今天特地给大家汇总了一些目前…

【云原生】服务网格(Istio)如何简化微服务通信

&#x1f407;明明跟你说过&#xff1a;个人主页 &#x1f3c5;个人专栏&#xff1a;《未来已来&#xff1a;云原生之旅》&#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目录 一、引言 1、微服务架构的兴起 2、Istio&#xff1a;服务网格的佼…

服务器测评

服务器测评 Linux测评口令是否存在空口令账户密码长度和密码定期更换密码复杂度本地登录失败处理功能相关参数超时锁定sshd服务相关端口是否已经打开不允许root账户远程登录查看SELinux状态审计查看Linux中正在运行的服务查看已添加的iptables规则查看文件和目录的权限设置是否…

大文件上传是怎么做的

1. 分片上传 1. 把需要上传的文件按照一定的规则&#xff0c;分割成相同大小的数据块 2. 初始化一个分片上传任务&#xff0c;返回本次分片上传的唯一标识 3. 按照一定的规则把各个数据块上传 4. 发送完成后&#xff0c;服务端会判断数据上传的完整性&#xff0c;如果完整&a…

【Python】Python环境搭建教学#保姆级教学#手把手带你安装——内附Python环境搭建安装包(Python、PyCharm(社区版)安装包)

Python环境搭建 导读一、初识Python1.1 Python的由来1.2 Python的用途1.3 Python的优缺点1.4 Python的前景&#xff08;钱景&#xff09; 二、Python环境搭建2.1 运行环境——Python安装2.2 开发环境——PyCharm安装2.3 项目创建2.4 基本配置2.4.1 主题配置2.4.2 背景图设置2.4…

Vue笔记-vue中使用JS创建的函数

主要是公司对前端要求不高&#xff0c;能解决问题就行了&#xff0c;前端不太熟&#xff0c;用js这种处理起来方便&#xff0c;在此记录下。 在src中创建一个api目录&#xff0c;新建custom.js export const getDivHeightByClass (className) > {let divElements docume…

容器之docker

Docker 是一个开源的平台&#xff0c;旨在使应用程序的开发、部署和运行更加轻松。它利用容器技术&#xff0c;将应用程序及其依赖环境打包在一起&#xff0c;以便于在任何环境中一致运行。 概述 Docker 通过提供轻量级的虚拟化解决方案&#xff0c;使得开发者可以轻松创建、…

.NET 调用API创建系统服务实现权限维持

01阅读须知 此文所节选自小报童《.NET 内网实战攻防》专栏&#xff0c;主要内容有.NET在各个内网渗透阶段与Windows系统交互的方式和技巧&#xff0c;对内网和后渗透感兴趣的朋友们可以订阅该电子报刊&#xff0c;解锁更多的报刊内容。 02基本介绍 本文内容部分节选自小报童…

达梦数据库的DBMS_STATS包

达梦数据库的DBMS_STATS包 基础信息 OS版本&#xff1a; Red Hat Enterprise Linux Server release 7.9 (Maipo) DB版本&#xff1a; DM Database Server 64 V8 DB Version: 0x7000c 03134284132-20240115-215128-20081达梦数据库&#xff08;DM Database&#xff09;提供了 D…

FreeRTOS开发五、任务状态切换以及空闲任务回收结束的任务

1、任务状态切换 任务创建的时候就会处于就绪状态ready&#xff0c;然后他马上就能够运行进入Running状态&#xff0c;运行中可以调用vTaskDelay进入阻塞状态&#xff0c;实际就是延时一小段时间&#xff0c;等待唤醒&#xff0c;当延时时间过去后就回到了就绪状态&#xff0…

【python学习】自定义函数的一些高级用法-1

在 Python 中&#xff0c;自定义函数除了基本的定义和调用外&#xff0c;还有一些高级用法&#xff0c;可以让函数更加灵活和强大。以下是一些自定义函数的高级用法示例&#xff1a; 1. 默认参数 函数定义时可以指定默认参数值&#xff0c;当调用函数时没有提供该参数的值时&…

深入理解Spring Boot与Spring Cloud的整合方式

深入理解Spring Boot与Spring Cloud的整合方式 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们将深入探讨Spring Boot与Spring Cloud的整合方式&#x…

pytorch-ResNet18简单复现

目录 1. ResNet block2. ResNet18网络结构3. 完整代码3.1 网络代码3.2 训练代码 1. ResNet block ResNet block有两个convolution和一个short cut层&#xff0c;如下图&#xff1a; 代码&#xff1a; class ResBlk(nn.Module):def __init__(self, ch_in, ch_out, stride):su…

Java学习 (六) 面向对象--this、继承、方法重写、super

一、this 关键字 1、this 演示 vi Person.java public class Person {String name;int age;//显示声明构造器public Person(String s , int i){name s;age i;}public void setAge(int age){age age;}}vi PersonTest.java public class PersonTest {public static void m…

第二十一章 函数(Python)

文章目录 前言一、定义函数二、函数参数三、参数类型四、函数返回值五、函数类型1、无参数&#xff0c;无返回值2、无参数&#xff0c;有返回值3、有参数&#xff0c;无返回值4、有参数&#xff0c;有返回值 六、函数的嵌套七、全局变量和局部变量1、局部变量2、全局变量 前言 …

了解 .NET 中的会话管理

在 Web 开发领域&#xff0c;跨多个请求维护状态是一个关键方面。HTTP 的无状态特性要求开发人员实现持久保存用户数据的机制。这就是会话发挥作用的地方。在本文中&#xff0c;我们将探讨什么是会话、它们在 .NET 中的工作方式&#xff0c;并提供实际示例来说明它们的用法。 …

set_source_files_properties QT_QML_SINGLETON_TYPE

目录 前言 QT_QML_SINGLETON_TYPE 属性 基本用法 示例 1. 创建一个基本的 CMake 项目 2. 编辑 CMakeLists.txt 3. 创建 main.cpp 4. 创建 MySingleton.qml 5. 创建 qml.qrc 6. 创建 main.qml 构建和运行项目 结论 前言 在使用 Qt 和 CMake 构建项目时&#xff0c;…

weapp.socket.io.js

!function(t,e){if(“object"typeof exports&&"object"typeof module)module.exportse();else if("function"typeof define&&define.amd)define([],e);else{var re();for(var n in r)(“object"typeof exports?exports:t)[n]r[…