zoukankan      html  css  js  c++  java
  • 转载-Archunit的使用

    Archunit的使用

    注:开发的编辑器: Intellij Idea,JDK版本是JDK8

        Archunit是什么,官网的英文介绍很好,建议阅读原文,"ArchUnit is a free, simple and extensible library for checking the architecture of your Java code using any plain Java unit test framework. That is, ArchUnit can check dependencies between packages and classes, layers and slices, check for cyclic dependencies and more"。
    简单来说,它是代码格式、类之间的依赖关系检查工具。

    使用介绍

    进入官网
    点击右上角的"User Gruide"
    之后就可以看到它的英文教程文档。

    1.pom.xml中加入依赖

    List-1 最重要的是archunit-junit4依赖
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.tngtech.archunit</groupId>
        <artifactId>archunit-junit4</artifactId>
        <version>0.9.1</version>
        <scope>test</scope>
    </dependency>

    2.添加规则

    直接上代码了,如下List-2所示,按项目情况,修改自己的"@AnalyzeClassespackages值"
    import javax.persistence.Entity;

    import com.tngtech.archunit.junit.AnalyzeClasses;
    import com.tngtech.archunit.junit.ArchTest;
    import com.tngtech.archunit.junit.ArchUnitRunner;
    import com.tngtech.archunit.lang.ArchRule;

    import org.junit.runner.RunWith;

    import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
    import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
    import static com.tngtech.archunit.library.GeneralCodingRules.NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS;
    import static com.tngtech.archunit.library.GeneralCodingRules.NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS;
    import static com.tngtech.archunit.library.GeneralCodingRules.NO_CLASSES_SHOULD_USE_JAVA_UTIL_LOGGING;

    /**
     * @author dmj1161859184@126.com 2018-09-14 23:03
     * @version 1.0
     * @since 1.0
     */

    @RunWith(ArchUnitRunner.class) // Remove this line for JUnit 5!!
    @AnalyzeClasses(packages = "com.mjduan.project") //要扫描的package
    public class ArchunitTest {

        /** dao下的类应该以Dao结尾 */
        @ArchTest
        public static final ArchRule DAOs_must_reside_in_a_dao_package = classes()
                .that()
                .haveNameMatching(".*Dao")
                .should()
                .resideInAPackage("..dao..")
                .as("DAOs should reside in a package '..dao..'");

        /** controller下的类应该以Controller结尾 */
        @ArchTest
        public static final ArchRule CONTROLLERs_must_reside_in_a_dao_package = classes()
                .that()
                .haveNameMatching(".*Controller")
                .should()
                .resideInAPackage("..controller..")
                .as("DAOs should reside in a package '..dao..'");

        /** util下的类应该以Util结尾 */
        @ArchTest
        public static final ArchRule UTILs_must_reside_in_a_dao_package = classes()
                .that()
                .haveNameMatching(".*Util")
                .should()
                .resideInAPackage("..util..")
                .as("DAOs should reside in a package '..dao..'");

        /** 有Entity注解的类,应该在domain或者entity包下 */
        @ArchTest
        public static final ArchRule entities_must_reside_in_a_domain_package = classes()
                .that()
                .areAnnotatedWith(Entity.class)
                .should()
                .resideInAnyPackage("..domain..""..entity..");

        /** 接口类,应该以I开头 */
        @ArchTest
        public static final ArchRule interface_className_must_start_with_I = classes()
                .that()
                .areInterfaces()
                .should()
                .haveSimpleNameStartingWith("I")
                .as("Interface should start with I");

        /** service下的类,只能被controller下或者时service下的类访问 */
        @ArchTest
        public static final ArchRule services_should_only_be_accessed_by_controllers_or_other_services = classes()
                .that()
                .resideInAPackage("..service..")
                .should()
                .onlyBeAccessed()
                .byAnyPackage("..controller..""..service..");
        /** impl下的类,不能是interface */
        @ArchTest
        public static final ArchRule interfaces_must_not_be_placed_in_implementation_packages = noClasses()
                .that()
                .resideInAPackage("..impl..")
                .should()
                .beInterfaces();
        /** 接口类,类名不能以Interface结尾 */
        @ArchTest
        public static final ArchRule interfaces_should_not_have_names_ending_with_the_word_interface = noClasses()
                .that()
                .areInterfaces()
                .should()
                .haveNameMatching(".*Interface");
        /** service下的类,不能调用controller下的类 */
        @ArchTest
        public static final ArchRule services_should_not_access_controllers = noClasses()
                .that()
                .resideInAPackage("..service..")
                .should()
                .accessClassesThat()
                .resideInAPackage("..controller..");
        /** dao下的类,不能调用controller下的类 */
        @ArchTest
        public static final ArchRule controllers_should_not_access_dao = noClasses()
                .that()
                .resideInAPackage("..dao..")
                .should()
                .accessClassesThat()
                .resideInAnyPackage("..controller..");
        /** 不应该使用System.* */
        @ArchTest
        private final ArchRule NO_ACCESS_TO_STANDARD_STREAMS = NO_CLASSES_SHOULD_ACCESS_STANDARD_STREAMS;
        /** 不应该抛出Exception */
        @ArchTest
        private final ArchRule NO_GENERIC_EXCEPTIONS = NO_CLASSES_SHOULD_THROW_GENERIC_EXCEPTIONS;
        /** 不应该使用java.util.logging来记录日志 */
        @ArchTest
        private final ArchRule NO_JAVA_UTIL_LOGGING = NO_CLASSES_SHOULD_USE_JAVA_UTIL_LOGGING;
    }
        List-2中的代码中已经给出注释,自己可以在项目中运行看下结果。不过发现有个不好的地方是,archunit会扫描test下的类。

        注:如果要忽略某个规则,那么加上@ArchIgnore就可以了,参考这里。

    2.1 忽略某个规则

    public class ArchitectureTest {

        // will run
        @ArchTest
        public static final ArchRule rule1 = classes().should()...

        // won't run
        @ArchIgnore
        @ArchTest
        public static final ArchRule rule2 = classes().should()...
    }

    2.2 忽略多个类,即不让Archunit扫描多个类

    一般出现在遗留系统中。

    如图 图2.1

    ![图2.1](https://oscimg.oschina.net/oscnet/af8ed5e83e516a1da4caefbe86c7c6b09ac.jpg)

        比如我们想在Archunit扫描时,忽略DemoInterface和AnnotationDemo,那么在resources下建个"archunit_ignore_patterns.txt"的文件(这个文件名称是固定的,不能修改),在将要忽略的类路径放入其中,注意格式,如下图2.2所示,参考其官网。
    图2.2图2.2

    3.Demo

        新建一个interface,名为DemoInterface,之后运行List-2,结果如下图1所示,由于DemoInterface是interface,类名以Interface结尾(List-2中定义不能以Interface结尾),未以I开头(List-2中定义要以I开头):

    3.1  运行List-2后报错信息
     图3.1  运行List-2后报错信息 图3.1 运行List-2后报错信息

    4.官方的Archunit example

    可以在Github上看Archunit的例子,Github地址: https://github.com/TNG/ArchUnit-Examples    

    实际项目中,代码量较多,规范要做好,特别是人员流动是公司中很常见的。

    ```

  • 相关阅读:
    ASP.NET MVC5+EF6+EasyUI 后台管理系统(28)-系统小结
    用谷歌浏览器来当手机模拟器
    解决PHP使用CVS导出Excel乱码问题
    Linux系统中关于Sqlite3中文乱码问题及解决办法
    解决excel日期变成数字的问题
    基于IE的多标签的浏览器-世界之窗2.4
    Thinkphp 获取所有子分类或父分类ID
    PhpExcel 删除默认的Sheet
    Mysql 创建表时错误:Tablespace for table `tablexx` exists. Please DISCARD the tablespace before IMPORT.
    关于ThinkPhp中getField方法存在的问题
  • 原文地址:https://www.cnblogs.com/xiaoshahai/p/12071278.html
Copyright © 2011-2022 走看看