maven是java开发常用的工具,可以很快地对项目进行构建,包含了clean、compile、package和install等功能。在平时使用中,如果在maven引入依赖不对时,就很容易造成打包不成功,有时解决打包的问题就可能要很久。所以,在平时一定要多总结项目常见的问题,避免因maven打包问题影响了开发进度。

下面就总结一下目前maven常见的问题。

Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.1:test (default-test)

报错的原因就是test类打包的问题,直接去除掉test即可,下面两种方式都可以。

  • 在用到的测试类test中都添加上@Ignore
  • 直接在pom文件中去除test打包的内容即可。
<plugin>
		<groupId>org.apache.maven.plugins</groupId>
		<artifactId>maven-surefire-plugin</artifactId>
		<configuration>
			<skipTests>true</skipTests>
		</configuration>
</plugin>

项目的包中有某个类,却一直引入不了

有时将某块代码复制到某个类中,一个类名明明就存在,却始终引入不了。那么解决办法有如下几种:

  • 重新写一下需要用的类名:有时是因为直接复制粘贴无法正常引入,需要重新写一下。
  • 清除缓存:由于缓存的原因,不能正常加载。那么在idea左上角File-Setting-Invalidate Caches / Restart -Invalidate

引入的依赖冲突导致没有引入高版本jar,而是引入到低版本的jar

分两种情况:

- 在引入依赖时时用到了两个不同版本的jar

生产发布时报错:

java.lang.NoClassDefFoundError: org/apache/httpclients

在pom文件中要引入的是:

<dependency>
	<groupId>org.apache.httpcomponents</groupId>
	<artifactId>httpclient</artifactId>
	<version>4.5.6</version>
</dependency>

但是查看打的jar包,引入的httpclient依赖版本竟然是4.0.1的版本。
但是在pom文件中已经指定了4.5.6的版本了,为什么会引入4.0.1的版本呢?
经过排查,发现在工具类用httpclient时使用的架构提供的框架的jar包,而其中引入的jar就是4.0.1。
所以,将使用到4.0.1的pom和代码中的依赖直接调整为高版本的版本就可以了。

- 低版本的依赖直接继承了parent的标签的内容,而parent中依赖低版本的jar

在启动时,一直报找不到nacos为2.1.3的

经排查发现,项目中有多个module,
在最终打包的pom文件中,架构提供的framework-common中引用的nacos为2.1.3,
但是在依赖其他模板时:用到的nacos并没有指定版本号。

如果在pom中需要的jar没有引用指定版本号时,就会用parent的版本。

而这个parent使用的架构提供的框架使用的nacos版本号是2.1.2。所以启动时就直接只加载了2.1.2,而没有加载到2.1.3。

解决办法:
在依赖的模块直接指定nacos的版本,而不要用默认的parent。或者升级框架版本。

no main manifest attribute, in xxx-xxx-xxx.jar

在linux打包时报这个错误。需要在pom文件设置打包:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>2.1.3.RELEASE</version>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile

报错信息:

Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile (default-compile) on project springbootdemo: Fatal error compiling: 无效的标记: -parameters

错误的原因:
由于项目中所需jdk版本和你当前使用的jdk版本不一致导致的,因为我项目的pom.xml中定义了java版本为1.8,但是我实际idea中run这个项目却是1.7
<java.version>1.8</java.version>
解决办法:
更换当前jdk版本为项目所需jdk版本即可
要是你在intellij idea里面的maven窗口点击的打包编译的话,就在intellij idea设置项目jdk版本,直接Ctrl+Alt+s进入设置界面进行设置

指定/调整打的jar包名称:

在pom.xml文件中标签中添加finalName即可:

<build>
	 <plugins>
	      <plugin>
	          <groupId>org.springframework.boot</groupId>
	          <artifactId>spring-boot-maven-plugin</artifactId>
	          <version>2.1.3.RELEASE</version>
	      </plugin>
	  </plugins>
	  <finalName>springboot-station-demo</finalName>
</build>

打包时找不到符合的符号

这种原因也是有缓存jar包的缘故。解决的办法:maven-clean-install
如果还不行,右键整个项目-Maven-Reimport

如果还不行,就在File-Project Structure-Project Settings-Modules中选择清除掉当前报错的包。然后整个项目-Maven-Reimport

maven一直在打包中 maven打包失败的原因_maven

在idea中配置好了maven仓库,却一直下载jar到系统默认的路径

需要在maven的jar包的setting.xml中设置指定的路径才行

<localRepository>/usr/local/java/repository</localRepository>

pom文件中project显示setting.xml有error错误

pom文件一直有error报错,就花了很多精力去调整,但是最后还是找不到原因。
最终发现还是直接找一个别人正确的setting.xml文件直接替换最快。
还是不要把太多的时间用在配置这个上面。

idea中下载了maven中的jar包依赖,但仍然还是有红色波浪线

idea中下载了maven中的jar包依赖,但是在libraries或者在右上角的Maven Project的Dependencies/Plugins仍然还是有红色波浪线。
可能是上一步中修改了仓库地址,没有将有些依赖下载完整,那么可以点击Maven中的下载按钮即可。

SLF4J: Class path contains multiple SLF4J bindings.

启动时显示日志相关的jar有重复:

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/D:/Software/Repository-Station/org/apache/logging/log4j/log4j-slf4j-impl/2.11.2/log4j-slf4j-impl-2.11.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/D:/Software/Repository-Station/org/slf4j/slf4j-log4j12/1.7.25/slf4j-log4j12-1.7.25.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory]

排查发现有多个依赖都有日志的依赖,那么把不需要的日志依赖排除掉即可。

<exclusion>
	<artifactId>spring-boot-starter-log4j2</artifactId>
	<groupId>org.springframework.boot</groupId>
</exclusion>
<exclusion>
	<groupId>org.slf4j</groupId>
	<artifactId>slf4j-log4j12</artifactId>
</exclusion>

项目中兼容同一名称的不同版本的jar内容

redis单点和哨兵并行

在做项目更新优化时,老项目要将redis单点改为redis哨兵和单点并行的模式。
redis单点用的版本是2.1.0。

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.1.0</version>
</dependency>

但2.1.0的redis没有哨兵模式,无法正常引用,而2.9.0的有哨兵模式。而这个2.1.0版本引用的地方特别多,不可能为了改哨兵强制升级jar版本,这样太费时间又风险太大了。

那么可以用jarjar.jar来兼容版本。jarjar可以将redis-client 2.9.0修改成你想要的名字,比如myredis-client,那么调整后整个包名都是修改后的名称,这样就能正常使用2.9.0了。

<dependency>
	<groupId>myredis.clients</groupId>
	<artifactId>myjedis</artifactId>
	<version>1.0</version>
</dependency>

jarjar具体的依赖:

<!-- https://mvnrepository.com/artifact/com.googlecode.jarjar/jarjar -->
<dependency>
    <groupId>com.googlecode.jarjar</groupId>
    <artifactId>jarjar</artifactId>
    <version>1.3</version>
</dependency>

具体操作如下:

  1. 将如下内容放到任意一个盘下的同一个文件夹中:
    jarjar.jar
    redis-client-2.9.0.jar
    新建rule.txt
  2. 在rule.txt文章中输入以下内容:
## 内容格式  rule   要改变的包名称     改变的名称
rule redis.clients.jedis.**  redis.clients.myjedis.@1
  1. 在cmd中输入:
#java -jar   你的jarjar.jar的名称    process rule.txt    要改变的jar包名称   最终的jar名称
java -jar jarjar-1.3.jar  process rule.txt  redis-client-2.9.0.jar   myredis.clients.jar

看到jar名称改变成功,大功告成!

那么在代码中需要引用2.9.0的,就需要将redis的完整包名地址写上,比如:

redis.clients.myjedis.c.Jedis jedis=null;

另外为了方便别人正常查看和打包,需要将这个jar上传到私服上。

redis哨兵和cacheCloud并行

项目中需要用到redis的分布式锁,而不同的地方redis有用到哨兵和集群模式。那么哨兵和cacheCloud引用的依赖:

redis哨兵用的依赖是:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>

cacheCloud引用的依赖是:

<dependency>
    <groupId>com.sohu.tv</groupId>
    <artifactId>cachecloud-open-client-redis</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

在代码中写了JedisCluster调用set方法时却一直报错:
具体代码:

@Autowired
private JedisCluster jedisCluster;

public void tryLock(String key,int seconds){
	String isExists=jedisCluster.set(key,value,"NX","EX",seconds);
}

报错信息:

Cannot resolver method set() ...

查看JedisCluster时发现,引用的cacheCloud的方法,cacheCloud的依赖并没有这个set方法,而redis-2.9.0的依赖有这个方法。但是在引用时一直引用到cacheCloud的依赖,即使在引用处加上redis.client.jedis.JedisCluster的前缀也引用不了redis.client-2.9.0。

查看源码发现,redis.client-2.9.0还是cacheCloud,引用的都是redis.client.jedis.JedisCluster,名字竟然还一模一样。

原来cacheCloud的依赖底层并没有修改redis的依赖名称,而是重写了里面的方法,就导致引用时出错。真是坑啊!

那么如何解决呢?

将pom文件中redis-2.9.0的依赖放在cacheCloud的前面,那么在加载时就可以优先加载redis-2.9.0了。

Failed to configure a DataSource: ‘url’ attribute is not specified and no embedded datasource could be configured.

项目启动时报错:

Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
 
Reason: Failed to determine a suitable driver class

Action:

Consider the following:
  If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
  If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).

启动类需要禁止springboot自动注入数据源配置:

@SpringBootApplication(exclude = {DruidDataSourceAutoConfigure.class})

java.lang.NoClassDefFoundError: org/springframework/boot/bind/RelaxedPropertyResolver‘

引入alibaba druid时报错:

java.lang.NoClassDefFoundError: org/springframework/boot/bind/RelaxedPropertyResolver
  at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getExcludeAutoConfigurationsProperty(AutoConfigurationImportSelector.java:215) ~[spring-boot-autoconfigure-1.5.12.RELEASE.jar:1.5.12.RELEASE]
  at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getExclusions(AutoConfigurationImportSelector.java:209) ~[spring-boot-autoconfigure-1.5.12.RELEASE.jar:1.5.12.RELEASE]
  at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.selectImports(AutoConfigurationImportSelector.java:99) ~[spring-boot-autoconfigure-1.5.12.RELEASE.jar:1.5.12.RELEASE]
  at org.springframework.context.annotation.ConfigurationClassParser$DefaultDeferredImportSelectorGroup.process(ConfigurationClassParser.java:892) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
  at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGrouping.getImports(ConfigurationClassParser.java:878) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
  at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:804) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
  at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:774) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
  at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:185) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
  at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:315) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
  at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:232) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
  at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:275) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
  at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:95) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
  at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:705) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:531) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
  at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142) ~[spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
  at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]

根据报错的信息可以得知:

org.springframework.boot.autoconfigure出现了两个版本,分别是1.5.12和2.1.3。那么在pom文件中搜索到autoconfigure依赖发现两个地方的依赖不一致:

maven一直在打包中 maven打包失败的原因_maven_02


那么就需要将druid-spring-boot-starter的spring-boot-autoconfigure排除掉。

<dependency>
       <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.2.1</version>
        <exclusions>
            <exclusion>
                <artifactId>spring-boot-autoconfigure</artifactId>
                <groupId>org.springframework.boot</groupId>
            </exclusion>
        </exclusions>
</dependency>

Class path contains multiple SLF4J bindings.

项目启动后,报错日志依赖重复:

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/D:/Software/Repository-JobsTribe/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/D:/Software/Repository-JobsTribe/org/apache/logging/log4j/log4j-slf4j-impl/2.11.2/log4j-slf4j-impl-2.11.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [ch.qos.logback.classic.util.ContextSelectorStaticBinder]

那么需要排除多余的日志依赖:

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
     <version>2.1.3.RELEASE</version>
     <exclusions>
         <exclusion>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-logging</artifactId>
         </exclusion>
     </exclusions>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
    <version>2.1.3.RELEASE</version>
</dependency>