idea里的maven项目的Plugins的红色波浪线错误的原因及解决

maven的pom报plugins错误的原因及解决方法

错误信息

Failure to transfer org.apache.maven.plugins:maven-surefire-plugin:pom:2.7.1 from http://repo1.maven.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced

碰到一个类似以上的错误.以maven-surefire-plugin-2.7.1.jar报红为例子

原因

maven的plugin并未正在下载到本地.

首先查看maven仓库位置

idea里的maven项目的Plugins的红色波浪线错误的原因及解决

 

进入
~\.m2\repository\org\apache\maven\plugins\maven-surefire-plugin\2.7.1

的话,会发现里面只有一个

的文件,而并没有maven-surefire-plugin-2.7.1.jar

解决办法

1.删除所有以lastUpdated结尾的文件

2.重新点击reimport即可

idea里的maven项目的Plugins的红色波浪线错误的原因及解决

如果点击更新后发现

下还是没有maven-surefire-plugin-2.7.1.jar,去http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-surefire-plugin/2.7.1/下载

包再重复步骤2即可解决。

0

多模块Maven项目的 POM 重构

重复的坏味道

程序员应该有狗一般的嗅觉,要能嗅到重复这一最常见的坏味道,不管重复披着怎样的外衣,一旦发现,都应该毫不留情地彻底地将其干掉。不要因为 POM 不是产品代码而纵容重复在这里发酵,例如这样一段代码就有重复:

你会在一个项目中使用不同版本的 SpringFramework 组件么?答案显然是不会。因此这里就没必要重复写三次2.5,使用 Maven 属性将 2.5 提取出来如下:


 

现在 2.5 只出现在一个地方,虽然代码稍微长了点,但重复消失了,日后升级依赖版本的时候,只需要修改一处,而且也能避免漏掉升级某个依赖。

读者可能已经非常熟悉这个例子了,我这里再啰嗦一遍是为了给后面做铺垫,多模块 POM 重构的目的和该例一样,也是为了消除重复,模块越多,潜在的重复就越多,重构就越有必要。

消除多模块依赖配置重复

考虑这样一个不大不小的项目,它有 10 多个 Maven 模块,这些模块分工明确,各司其职,相互之间耦合度比较小,这样大家就能够专注在自己的模块中进行开发而不用过多考虑他人对自己的影响。(好吧,我承认这是比较理想的情况)那我开始对模块 A 进行编码了,首先就需要引入一些常见的依赖如 JUnit、Log4j 等等:


 

我的同事在开发模块 B,他也要用 JUnit 和 Log4j(我们开会讨论过了,统一单元测试框架为 JUnit 而不是 TestNG,统一日志实现为 Log4j 而不是 JUL,为什么做这个决定就不解释了,总之就这么定了)。同事就写了如下依赖配置:

看出什么问题来没有?对的,他漏了 JUnit 依赖的 scope,那是因为他不熟悉 Maven。还有什么问题?对,版本!虽然他和我一样都依赖了 JUnit 及 Log4j,但版本不一致啊。我们开会讨论没有细化到具体用什么版本,但如果一个项目同时依赖某个类库的多个版本,那是十分危险的!OK,现在只是两个模块的两个依赖,手动修复一下没什么问题,但如果是 10 个模块,每个模块 10 个依赖或者更多呢?看来这真是一个泥潭,一旦陷进去就难以收拾了。

好在 Maven 提供了优雅的解决办法,使用继承机制以及 dependencyManagement 元素就能解决这个问题。注意,是 dependencyMananget 而非 dependencies。也许你已经想到在父模块中配置 dependencies,那样所有子模块都自动继承,不仅达到了依赖一致的目的,还省掉了大段代码,但这么做是有问题的,例如你将模块 C 的依赖 spring-aop 提取到了父模块中,但模块 A 和 B 虽然不需要 spring-aop,但也直接继承了。dependencyManagement 就没有这样的问题,dependencyManagement 只会影响现有依赖的配置,但不会引入依赖。例如我们可以在父模块中配置如下:

这段配置不会给任何子模块引入依赖,但如果某个子模块需要使用 JUnit 和 Log4j 的时候,我们就可以简化依赖配置成这样:

现在只需要 groupId 和 artifactId,其它元素如 version 和 scope 都能通过继承父 POM 的 dependencyManagement 得到,如果有依赖配置了 exclusions,那节省的代码就更加可观。但重点不在这,重点在于现在能够保证所有模块使用的 JUnit 和 Log4j 依赖配置是一致的。而且子模块仍然可以按需引入依赖,如果我不配置 dependency,父模块中 dependencyManagement 下的 spring-aop 依赖不会对我产生任何影响。

也许你已经意识到了,在多模块 Maven 项目中,dependencyManagement 几乎是必不可少的,因为只有它是才能够有效地帮我们维护依赖一致性

我们在使用 dependencyManagement 的时候,我们可以不从父模块继承,而是使用特殊的 import scope 依赖。

我们知道 Maven 的继承和 Java 的继承一样,是无法实现多重继承的,如果 10 个、20 个甚至更多模块继承自同一个模块,那么按照我们之前的做法,这个父模块的 dependencyManagement 会包含大量的依赖。如果你想把这些依赖分类以更清晰的管理,那就不可能了,import scope 依赖能解决这个问题。你可以把 dependencyManagement 放到单独的专门用来管理依赖的 POM 中,然后在需要使用依赖的模块中通过 import scope 依赖,就可以引入 dependencyManagement。例如可以写这样一个用于依赖管理的 POM:

然后我就可以通过非继承的方式来引入这段依赖管理配置:


这样,父模块的 POM 就会非常干净,由专门的 packaging 为 pom 的 POM 来管理依赖,也契合的面向对象设计中的单一职责原则。此外,我们还能够创建多个这样的依赖管理 POM,以更细化的方式管理依赖。这种做法与面向对象设计中使用组合而非继承也有点相似的味道。

消除多模块插件配置重复

与 dependencyManagement 类似的,我们也可以使用 pluginManagement 元素管理插件。一个常见的用法就是我们希望项目所有模块的使用 Maven Compiler Plugin 的时候,都使用 Java 1.5,以及指定 Java 源文件编码为 UTF-8,这时可以在父模块的 POM 中如下配置 pluginManagement:


这段配置会被应用到所有子模块的 maven-compiler-plugin 中,由于 Maven 内置了 maven-compiler-plugin 与生命周期的绑定,因此子模块就不再需要任何 maven-compiler-plugin 的配置了。

与依赖配置不同的是,通常所有项目对于任意一个依赖的配置都应该是统一的,但插件却不是这样,例如你可以希望模块 A 运行所有单元测试,模块 B 要跳过一些测试,这时就需要配置 maven-surefire-plugin 来实现,那样两个模块的插件配置就不一致了。这也就是说,简单的把插件配置提取到父 POM 的 pluginManagement 中往往不适合所有情况,那我们在使用的时候就需要注意了,只有那些普适的插件配置才应该使用 pluginManagement 提取到父 POM 中。

关于插件 pluginManagement,Maven 并没有提供与 import scope 依赖类似的方式管理,那我们只能借助继承关系,不过好在一般来说插件配置的数量远没有依赖配置那么多,因此这也不是一个问题。

小结

关于 Maven POM 重构的介绍,在此就告一段落了。基本上如果你掌握了本篇和上一篇 Maven 专栏讲述的重构技巧,并理解了其背后的目的原则,那么你肯定能让项目的 POM 变得更清晰易懂,也能尽早避免一些潜在的风险。虽然 Maven 只是用来帮助你构建项目和管理依赖的工具,POM 也并不是你正式产品代码的一部分。但我们也应该认真对待 POM,这有点像测试代码,以前可能大家都觉得测试代码可有可无,更不会去用心重构优化测试代码,但随着敏捷开发和 TDD 等方式越来越被人接受,测试代码得到了开发人员越来越多的关注。因此这里我希望大家不仅仅满足于一个“能用”的 POM,而是能够积极地去修复 POM 中的坏味道。

0

使用maven-assembly-plugin插件进行自定义打包

介绍

Maven的Assembly Plugin使开发人员能够将项目输出组合到一个可分发的存档中,该存档还包含依赖项,模块,站点文档和其他文件。

您的项目可以使用预制的装配体描述符之一轻松构建分发“装配体”。 这些描述符处理许多常见的操作,例如将项目的文件以及生成的文档打包到单个zip存档中。 或者,您的项目可以提供自己的描述符,并且可以对程序集中的依赖项,模块,文件集和单个文件的打包方式进行更高级别的控制。

当前,它可以创建以下格式的发行版:

  • zip
  • tar
  • tar.gz (or tgz)
  • tar.bz2 (or tbz2)
  • tar.snappy
  • tar.xz (or txz)
  • jar
  • dir
  • war
  • 等等

实战

pom.xml

工程截图

package.xml

pid文件

web-server.bat脚本

web-server.sh脚本

打包命令

打包完的截图

打包完的截图
打包完的截图
解压后的文件
解压后的文件

lib文件下放了所有用到的jar包,要想运行程序,直接运行脚本文件即可。很方便。使用maven-assembly-plugin插件进行自定义打包就介绍完成了。

0

maven下载jar包慢似龟速,如何解决?

问题描述

有时我们在maven项目的pom.xml中添加了依赖后就出现一直building Workspace的情况, 这就是jar包下载速度缓慢甚至卡死的问题。

原因分析

下载源在国外,速度慢就对了

问题解决

设置国内镜像

步骤

1.打开maven 安装目录,打开settings.xml文件

maven下载jar包慢1
maven下载jar包慢1

2.添加阿里云的仓库地址镜像标签

添加阿里云的仓库地址镜像
添加阿里云的仓库地址镜像

0

Idea右边的maven projects窗口找不到,该怎么调出来

有的时候,会发现Idea右边的maven projects窗口找不到,那该如何调出来?

首先idea自带了maven控件,不像Eclipse还需要下载控件,如果你以前有maven在右边,出于某种原因,消失找不到 了,你可以试试下面这些方法。

方法1.点击idea界面最左下角的那个小框,maven应该从里面找到

方法2.点击菜单栏View->Tool Windows->Maven projects

方法3.点击菜单栏Help->Find Action(Ctrl+Shift+A),输入Maven projects

其实有Ctrl+Shift+A的快捷键,但是因为有很多软件都有快捷键,这边可能会出现快捷键冲突。

0

maven项目有两个src怎么办?

maven 配置的项目中其实都有两个src文件夹。那他们有什么不同呢?各有什么用呢?

Java Resource下的src是用来存放java相关的源文件,src可以存放包括web在内的资源。

如果是刚刚导入项目,可能需要:

1、对第二个src文件夹右击,点击Build path ——>Use as source folder

2、项目clean,refresh一下

3、如果还报错,将项目关掉重新打开一下。

+2

maven项目配置log4j

Apache Log4j是一个基于Java的日志记录工具,它的日志级别按下面顺序递减:

级别描述
OFF最高级别,用于关闭日志记录。
FATAL将导致应用程序提前终止的严重错误的信息将立即呈现在日志上。
ERROR将其他运行时错误或意外情况的信息呈现在日志上。
WARN使用已过时的API,API的滥用,潜在错误,其他不良的或意外的运行时的状况(但不一定是错误的)
INFO一些感兴趣的运行时事件(启动/关闭
DEBUG一些详细信息,查看程序的运行状态
TRACE最详细的信息。一般这些信息只记录到日志文件中。

 下面介绍如何在java项目中如何使用Log4j。

1. 配置maven,引入jar包

2. 配置log4j的配置文件

  其配置文件名为log4j.properties,需要手动在java/resources下创建,如果建在其他位置,idea这个工具将无法识别(如果无法识别后面会介绍怎么解决)。下面介绍该配置文件的几个基本配置项。

a. 日志的输出的目的地

形式描述
org.apache.log4j.ConsoleAppender控制台
org.apache.log4j.FileAppender文件
org.apache.log4j.DailyRollingFileAppender每天产生一个日志文件
org.apache.log4j.RollingFileAppender文件大小到达指定尺寸的时候产生一个新的文件
org.apache.log4j.WriterAppender将日志信息以流格式发送到任意指定的地方

b. Layout:日志输出格式

形式描述
org.apache.log4j.HTMLLayout以HTML表格形式布局
org.apache.log4j.PatternLayout可以灵活地指定布局模式
org.apache.log4j.SimpleLayout包含日志信息的级别和信息字符串
org.apache.log4j.TTCCLayout包含日志产生的时间、线程、类别等等信息

c. 格式化日志信息

采用类似C语言中的printf函数的打印格式格式化日志信息

形式描述
%d输出日志时间点的日期或时间,可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss , SSS}
%t输出产生该日志事件的线程名
%p优先级 DEBUG/INFO/ERROR
%c所属类的全名(包括包名)
%l发生的位置,在某个类的某行
%m输出代码中指定的讯息,如log(message)中的message
%n输出一个换行符号

案例

  案例使用如下的配置信息:

12345678910111213141516### set log levels ###log4j.rootLogger = DEBUG,Console,File###  输出到控制台  ###log4j.appender.Console=org.apache.log4j.ConsoleAppenderlog4j.appender.Console.Target=System.outlog4j.appender.Console.layout=org.apache.log4j.PatternLayoutlog4j.appender.Console.layout.ConversionPattern=[%d{yy/MM/dd HH:mm:ss:SSS}]-%l:%m%n### 输出到日志文件 ###log4j.appender.File=org.apache.log4j.RollingFileAppenderlog4j.appender.File.File=${project}src\\main\\resources\\app.loglog4j.appender.File.MaxFileSize=10MBlog4j.appender.File.Threshold=ALLlog4j.appender.File.layout=org.apache.log4j.PatternLayoutlog4j.appender.File.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH\:mm\:ss,SSS}][%c]%m%n

3. 使用Log4j

配置完上面信息后就可以创建一个Java文件去测试日志的文件的使用了。

123456789package com.gqx.test;import org.apache.log4j.Logger;public class Hello {private static Logger log = Logger.getLogger(Hello.class.getClass());public static void main(String[] args) {log.debug("debug...");log.error("error...");}}

结果如图左侧(左上是控制台的log,左下是app.log文件的log),其中整个工程的布局如图右侧:

4 . 问题

过程中可能出现下面的问题:

这个其实是IDE(Idea)找不到log4j的properties文件,有些博客说可以去project_structure去改配置,尝试了一下可惜没有用,但发现了可以在程序中通过代码去指定properties文件的位置,如果出现了 上面的错误,可以改成如下形式:

12345678910111213package com.gqx.test;import org.apache.log4j.Logger;import org.apache.log4j.PropertyConfigurator;public class Hello {private static Logger log = Logger.getLogger(Hello.class.getClass());public static void main(String[] args) {//获取当前项目的根目录String relativelyPath=System.getProperty("user.dir");PropertyConfigurator.configure(relativelyPath+ "\\src\\main\\resources\\log4j.properties");log.debug("debug...");log.error("error...");}}

maven项目配置log4j总结完了。

0

spring profile 与 maven profile 多环境管理

实际开发中一个项目至少对应开发、测试、生成三种环境,如何方便的管理多环境是今天的要讨论的主题

Spring Profile

Spring Profile 是 Spring 提供的多环境管理方案。

如图,每种环境都对应一个 properties 文件,然后在application.properties中配置一下要使用的环境

上面配置匹配的是 application-dev.properties,如果写的是test,则匹配 application-test.properties。也就是说,Spring Profile 对配置文件的命名有要求,必须是 application- 开头

除了配置环境外,一些不随环境而变化的配置也应该放到 application.properties中,application-.properties最好只存放与环境相关的配置项

以上就是 Spring Profile 给出的多环境管理方案。通过改变 spring.profiles.active的值来切换不同的环境。这种方法简单易懂,但有两个问题。

  1. 每次切换环境要手动修改 spring.profiles.active 的值
  2. 打包的时候,要手动删除其它环境的配置文件,不然其它环境的敏感信息就都打包进去了

为了解决这两个问题,我们需要 maven profile 的配合

maven profile

  maven 的 profile 可以让我们定义多套配置信息,并指定其激活条件,然后在不同的环境下使用不同的profile配置。   

profile 的定义位置

在maven中有两个地方可以配置 profile

  1. pom.xml中:这里面定义的 profile 作用范围是当前项目
  2. {user}/.m2/settings.xml中:这里面定义的 profile 作用范围是所有使用了该配置文件的项目

settings.xml中的 profile

不同的地方 profile 中能定义的信息也不相同

  • 由于settings.xml作用范围宽泛, profile 中只能定义一些公共信息,如下
  • id:该 profile 的唯一标识
  • activation:在哪些情况下激活 profile,这里面有多种策略可供选择,只要满足其中一个条件就激活
  • repositories:远程仓库

由于能配置的东西有限,一般都会将 maven profile 配置在pom.xml

pom.xml中 的profile

pom.xml中:profile 能定义的东西就非常多了,如下

当然我们的目的也不是把它配全,而是解决 Spring Profile 遗留下来的两个问题。

首先看第一个问题

问题1

“每次切换环境要手动修改spring.profiles.active的值”

这个问题就可以通过配置 profile 解决,在pom的根节点下添加

如上,定义了三套环境,其中id为dev的是默认环境,三套环境中定义了叫 env的“变量”

如果你用的是idea编辑器,添加好后,maven控件窗口应该会多出一个 Profiles,其中默认值就是上面配置的dev

最小化的 profiles 已经配置好了,通过勾选上图中的Profiles,就可以快速切换 maven的 profile 环境。

现在 maven profile 可以通过 勾选上图中的Profiles 快速切换环境

Spring Profile 还得通过 手动修改spring.profiles.active的值来切环境

现在的问题是怎样让 maven profile的环境与Spring Profile一一对应,达到切换maven profile环境时,Spring Profile环境也被切换了

还记得maven profile 中定义的 env “变量”吗,现在只需要把

改成

就将maven profile 与 Spring Profile 环境关联起来了

当maven profile 将 环境切换成 test 时,在pom中定义的id为test的profile环境将被激活,在该环境下env的值是test,maven插件会将 @env@ 替换为 test,这样Spring Profile的环境也随之发生了改变。从上面可以看出,自定义的”变量”env的值还不能乱写,要与Spring Profile的环境相对应。

总结

  • 第一步,在pom文件中配置 profiles
  • 第二步,在application.properties配置文件中添加 spring.profiles.active=@env@

问题2

打包的时候,要手动删除其它环境的配置文件,不然其它环境的敏感信息就都打包进去了

解决这个问题需要在pom根节点下中配置 build 信息

  • directory:资源文件所在目录
  • includes:需要包含的文件列表
  • excludes:需要排除的文件列表

如上,配置了两个 <resource>,第一个先排除了src/main/resources目录下所有 application 开头是配置文件,第二个在第一个的基础上添加了所需的配置文件。注意 application-${env}.yml,它是一个动态变化的值,随着当前环境的改变而改变,假如当前环境是 id叫 dev的 profile,那么env的值为 dev。

这样配置后,maven在build时,就会根据配置先排除掉指定的配置文件,然后根据当前环境添加所需要的配置文件。

0

Maven配置本地仓库和阿里云的远程中央仓库

一、配置Maven的本地仓库

Maven的本地仓库默认地址位于 C:\Users\用户名.m2 目录下,由于仓库中的jar包会随着项目的不断迭代而变得越来越大,所以建议把仓库的地址切换到其它盘,具体步骤如下:                                                      

1.自己选个位置,创建一个新文件夹用来存放仓库

我这边是在D盘下面新建了一个 maven_repos 文件夹

2.修改maven的settings.xml文件

settings.xml文件就在maven的安装目录下

将本地仓库的地址修改为D:\maven_repos

3.检测配置是否生效

打开命令行输入 mvn help:system

当控制台出现build success时,再查看D盘的maven_repos文件夹,多了很多文件,说明配置生效。

二、配置Maven的远程仓库

Maven默认的远程地址是,http://my.repository.com/repo/path,因为是国外的,所以下载jar包时速度会非常慢,这里我们切换到阿里云的地址。

三、最后

推荐一个搜索jar包的maven依赖时常用地址:http://mvnrepository.com/

Maven 依赖搜索顺序

本地仓库 -> 中央仓库 -> 远程仓库

0