Статьи

Как визуализировать графики модулей Java

Эта статья демонстрирует, как мы можем визуализировать граф модуля Jigsaw в приложении Java. API модуля может перечислять модули Jigsaw и их зависимые элементы, как показано ниже.

Set<Module> modules = ModuleLayer.boot().modules();
Set<Requires> requires = module.getDescriptor().requires();

С помощью этих двух простых команд мы можем получить доступ к графу связей модулей в запущенном приложении.

Для визуализации отношений модуля можно использовать vis.js. С помощью vis.js. легко создавать сетевые графики. Взгляните на следующий фрагмент кода!

// create an array with nodes
  var nodes = new vis.DataSet([
    {id: 'java.base', label: 'java.base'},
    {id: 'java.logging', label: 'java.logging'},
    {id: 'java.sql', label: 'java.sql'}
  ]);

  // create an array with edges
  var edges = new vis.DataSet([
    {from: 'java.sql', to: 'java.base'},
    {from: 'java.sql', to: 'java.logging'},
    {from: 'java.logging', to: 'java.base'}
  ]);

  // create a network
  var container = document.getElementById('mynetwork');
  var data = {
    nodes: nodes,
    edges: edges
  };
  var options = {};
  var network = new vis.Network(container, data, options);

Вид должен быть похож на изображение ниже:

Давайте создадим целый живой визуализатор графов модулей. Сначала введите следующее:

public class Node {
    private String id;
    private String label;

    // getters, setters, constructors
}

Node.java представляет данные узла. У каждого имени модуля будет один узел:

public class Edge {
    private String from;
    private String to;

    // getters, setters, constructors
}

Edge.java представляет ребро между двумя узлами:

@RestController
public class ModuleGraphController {

    @GetMapping("/modules")
    public Map<String, HashSet<?>> moduleInfo() {
        var nodes = new HashSet<Node>(); // <1>
        var edges = new HashSet<Edge>(); // <2>
        fillNodeAndEdges(nodes, edges); // <3>
        return Map.of("nodes", nodes, "edges", edges); // <4>
    }

    private void fillNodeAndEdges(HashSet<Node> nodes, HashSet<Edge> edges) {
        Set<Module> modules = ModuleLayer.boot().modules(); // <5>
        for (Module module : modules) {
            String moduleName = module.getName();

            if (moduleNotContain(moduleName, "jdk")) { // <6>
                nodes.add(new Node(moduleName));
            }

            Set<Requires> requires = module.getDescriptor().requires(); <7>
            for (Requires require : requires) {
                edges.add(new Edge(moduleName, require.name())); <8>
            }
        }
    }

    private boolean moduleNotContain(String moduleName, String text) {
        return !moduleName.startsWith(text);
    }
}
1

Создать набор узлов

2

Создать набор ребер

3

Заполнить наборы узлов и ребер

4

Возвращает набор ребер и узлов на карте

5

Список модулей доступа

6

Пропустите внутренние модули jdk для ясности

7

Доступ к модулям

8

Заполнить грань между модулем и зависимым

ModuleController — это REST-контроллер, который возвращает отношения модулей в формате JSON. Чтобы получить доступ к этим данным на стороне JS, мы можем использовать fetch api. Давайте посмотрим на это.

function showGraph(json) {
        var container = document.getElementById('placeholder');
        var data = {
            nodes: json.nodes,
            edges: json.edges
        };
        var options = {};
        network = new vis.Network(container, data, options);
    }

fetch("/modules") // <1>
  .then(function (res) {
            return res.json()
        })
  .then(showGraph); // <2>
1

Запрос / модули json

2

Показать все модульные отношения

Это все!

Вот окончательный результат:

Чтобы запустить демо, выполните следующие действия:

mvn clean install
java -jar target/module-graph.jar
//  Then open http://localhost:8080

или

mvn clean install
docker build -t rahmanusta/module-graph .
docker run -it -p 8080:8080 rahmanusta/module-graph
//  Then open http://localhost:8080

Вы можете получить полный исходный код здесь:  https://github.com/rahmanusta/module-graph .