技术栈
程序员之禅
关于设计/架构
开源之路(藤原会)
Canal
Apache SkyWalking
Spring Cloud Tencent
APIJSON
Apache pulsar
公益表单管理系统
云教室在线支教
程序设计小case
实现一个基于maven的依赖检查工具
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-dependency-tree</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.5.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.6.0</version>
</plugin>
</plugins>
</build>
@Mojo(name = "collect", requiresDependencyCollection = ResolutionScope.TEST, threadSafe = true)
public class CollectDependencyPlugin extends AbstractMojo {
@Parameter(defaultValue = "${project}", readonly = true, required = true)
private MavenProject project;
@Parameter(defaultValue = "${session}", readonly = true, required = true)
private MavenSession session;
@Component(hint = "default")
private DependencyCollectorBuilder dependencyCollectorBuilder;
@Component(hint = "default")
private DependencyGraphBuilder dependencyGraphBuilder;
@Parameter(property = "verbose", defaultValue = "false")
private boolean verbose;
@Parameter(property = "skip", defaultValue = "false")
private boolean skip;
@Parameter(property = "outputType", defaultValue = "text")
private String outputType;
@Parameter(property = "tokens", defaultValue = "standard")
private String tokens;
@Parameter(property = "scope")
private String scope;
@Parameter(property = "includes")
private String includes;
@Parameter(property = "excludes")
private String excludes;
private DependencyNode rootNode;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
if (isSkip()) {
getLog().info("Skipping plugin execution");
return;
}
try {
String dependencyTreeString;
//String dependencyTreeStringOrigin;
ArtifactFilter artifactFilter = createResolvingArtifactFilter();
ProjectBuildingRequest buildingRequest =
new DefaultProjectBuildingRequest(session.getProjectBuildingRequest());
buildingRequest.setProject(project);
if (verbose) {
rootNode = dependencyCollectorBuilder.collectDependencyGraph(buildingRequest, artifactFilter);
dependencyTreeString = serializeDependencyTree(rootNode);
} else {
rootNode = dependencyGraphBuilder.buildDependencyGraph(buildingRequest, artifactFilter);
dependencyTreeString = serializeDependencyTree(rootNode);
}
String[] dependenciesStr = dependencyTreeString.split("\r\n");
if (dependenciesStr == null || dependenciesStr.length == 0) {
throw new MojoFailureException("当前项目不存在第三方依赖");
}
List<Artifact> artifactList = parseToArtifact(dependenciesStr);
getLog().info(project.getGroupId());
getLog().info(project.getArtifactId());
getLog().info(project.getVersion());
getLog().info(project.getPackaging());
getLog().info(artifactList.toString());
} catch (Exception ex) {
ex.printStackTrace();
}
}
private String serializeDependencyTree(DependencyNode theRootNode) {
StringWriter writer = new StringWriter();
DependencyNodeVisitor visitor = getSerializingDependencyNodeVisitor(writer);
visitor = new BuildingDependencyNodeVisitor(visitor);
DependencyNodeFilter filter = createDependencyNodeFilter();
if (filter != null) {
CollectingDependencyNodeVisitor collectingVisitor = new CollectingDependencyNodeVisitor();
DependencyNodeVisitor firstPassVisitor = new FilteringDependencyNodeVisitor(collectingVisitor, filter);
theRootNode.accept(firstPassVisitor);
DependencyNodeFilter secondPassFilter =
new AncestorOrSelfDependencyNodeFilter(collectingVisitor.getNodes());
visitor = new FilteringDependencyNodeVisitor(visitor, secondPassFilter);
}
theRootNode.accept(visitor);
return writer.toString();
}
public DependencyNodeVisitor getSerializingDependencyNodeVisitor(Writer writer) {
if ("graphml".equals(outputType)) {
return new GraphmlDependencyNodeVisitor(writer);
} else if ("tgf".equals(outputType)) {
return new TGFDependencyNodeVisitor(writer);
} else if ("dot".equals(outputType)) {
return new DOTDependencyNodeVisitor(writer);
} else {
return new SerializingDependencyNodeVisitor(writer, toGraphTokens(tokens));
}
}
private DependencyNodeFilter createDependencyNodeFilter() {
List<DependencyNodeFilter> filters = new ArrayList<>();
if (includes != null) {
List<String> patterns = Arrays.asList(includes.split(","));
getLog().debug("+ Filtering dependency tree by artifact include patterns: " + patterns);
ArtifactFilter artifactFilter = new StrictPatternIncludesArtifactFilter(patterns);
filters.add(new ArtifactDependencyNodeFilter(artifactFilter));
}
if (excludes != null) {
List<String> patterns = Arrays.asList(excludes.split(","));
getLog().debug("+ Filtering dependency tree by artifact exclude patterns: " + patterns);
ArtifactFilter artifactFilter = new StrictPatternExcludesArtifactFilter(patterns);
filters.add(new ArtifactDependencyNodeFilter(artifactFilter));
}
return filters.isEmpty() ? null : new AndDependencyNodeFilter(filters);
}
private ArtifactFilter createResolvingArtifactFilter() {
ArtifactFilter filter;
if (scope != null) {
getLog().debug("+ Resolving dependency tree for scope '" + scope + "'");
filter = new ScopeArtifactFilter(scope);
} else {
filter = null;
}
return filter;
}
private SerializingDependencyNodeVisitor.GraphTokens toGraphTokens(String theTokens) {
return new SerializingDependencyNodeVisitor.GraphTokens("", "","", "");
}
private List<Artifact> parseToArtifact(String[] dependencyGavStrs) {
List<Artifact> artifactList = new ArrayList<>(dependencyGavStrs.length);
for (String dependencyGavStr : dependencyGavStrs) {
String[] gavInfo = dependencyGavStr.split(":");
if (gavInfo == null) {
continue;
}
if (gavInfo.length < 4) {
getLog().error("不合法的依赖:" + dependencyGavStr);
}
//String groupId, String artifactId, String classifier, String extension, String version
Artifact artifact = new DefaultArtifact(gavInfo[0], gavInfo[1], "", gavInfo[2], gavInfo[3]);
artifactList.add(artifact);
}
return artifactList;
}
public boolean isSkip() {
return skip;
}
}
动态控制日志输出级别
@Plugin(
name = "Log4j2DynamicLoggingFilter",
category = "Core",
elementType = "filter",
printObject = true
)
public class Log4j2DynamicLoggingFilter extends AbstractFilter {
private DynamicLoggingHelper helper;
public Log4j2DynamicLoggingFilter() {
helper = DynamicLoggingHelper.getInstance();
}
@Override
public Result filter(LogEvent event) {
return filter(event.getLoggerName(),event.getLevel());
}
@Override
public Result filter(Logger logger, Level level, Marker marker, Message msg, Throwable t) {
return filter(logger.getName(), level);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, Object msg, Throwable t) {
return filter(logger.getName(), level);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String msg, Object... params) {
return filter(logger.getName(), level);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8) {
return filter(logger.getName(), level);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7) {
return filter(logger.getName(), level);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6) {
return filter(logger.getName(), level);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5) {
return filter(logger.getName(), level);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1, Object p2, Object p3, Object p4) {
return filter(logger.getName(), level);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1, Object p2, Object p3) {
return filter(logger.getName(), level);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1, Object p2) {
return filter(logger.getName(), level);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1) {
return filter(logger.getName(), level);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0) {
return filter(logger.getName(), level);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String msg, Object p0, Object p1, Object p2, Object p3, Object p4, Object p5, Object p6, Object p7, Object p8, Object p9) {
return filter(logger.getName(), level);
}
/**
* 核心拦截逻辑
* */
private Result filter(String loggerName, Level level) {
...
}
}
@Slf4j
@Configuration
@ConditionalOnClass(value = {LoggerContext.class, EmbeddedServletContainerInitializedEvent.class})
@ConditionalOnMissingBean(LogbackDynamicAutoConfiguration.class)
public class Log4j2DynamicAutoConfiguration implements ApplicationListener<EmbeddedServletContainerInitializedEvent> {
private DynamicLoggingHelper helper ;
public Log4j2DynamicAutoConfiguration() {
this.helper = DynamicLoggingHelper.getInstance();
}
@Override
public void onApplicationEvent(EmbeddedServletContainerInitializedEvent contextRefreshedEvent) {
if (!this.helper.isDynamicLoggingLevelFilterOff()) {
LoggerContext context = (LoggerContext) LogManager.getContext(false);
org.apache.logging.log4j.core.config.Configuration configuration = context.getConfiguration();
configuration.addFilter(new Log4j2DynamicLoggingFilter());
context.updateLoggers(configuration);
}
}
}
public class LogbackDynamicLoggingFilter extends TurboFilter {
private DynamicLoggingHelper helper ;
public LogbackDynamicLoggingFilter() {
helper = DynamicLoggingHelper.getInstance();
}
@Override
public FilterReply decide(Marker marker, Logger logger, Level level, String s, Object[] objects, Throwable throwable) {
...
}
}
@Slf4j
@Configuration
@ConditionalOnClass(value = {LoggerContext.class, EmbeddedServletContainerInitializedEvent.class})
public class LogbackDynamicAutoConfiguration implements ApplicationListener<EmbeddedServletContainerInitializedEvent> {
private DynamicLoggingHelper helper ;
public LogbackDynamicAutoConfiguration() {
this.helper = DynamicLoggingHelper.getInstance();
}
@Override
public void onApplicationEvent(EmbeddedServletContainerInitializedEvent contextRefreshedEvent) {
if (!helper.isDynamicLoggingLevelFilterOff()) {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
loggerContext.addTurboFilter(new LogbackDynamicLoggingFilter());
}
}
}
Redis双写
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。