最近需要用spring boot + mybatis整合hadoop,其中也有碰到一些坑,記錄下來方便後面的人少走些彎路。
背景呢是因為需要在 web 中上傳檔案到 hdfs ,所以需要在spring boot中加入hadoop相關的jar包。在加入的過程中容易出一些錯誤,主要是包衝突這一類的問題,解決了之後就好了,在這裡順便記錄一下此次解決問題的思路,有需要的朋友可以看看。
一. Spring boot整合Hadoop依賴
先給出答案吧,要整合hadoop,比如在 web 中對Hdfs 進行一些處理什麼的,直接在pom.xml 中加入以下依賴就行。對了,記得要改成你對應的版本。
<!-- hadoop 依賴 -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.7.4</version>
<exclusions>
<exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId></exclusion>
<exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion>
<exclusion> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> </exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.4</version>
<exclusions>
<exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId></exclusion>
<exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion>
<exclusion> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> </exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.4</version>
<exclusions>
<exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId></exclusion>
<exclusion> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </exclusion>
<exclusion> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> </exclusion>
</exclusions>
</dependency>
把這段程式碼放到pom.xml 裡面應該就沒問題了,這裡主要是需要用
二. 發現問題的思路
剛開始加入hadoop包的時候,出現了這樣的錯誤
Caused by: java.lang.IllegalStateException: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError. See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details.
我就明白是因為日誌包log4j這些衝突了,於是就新增
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]
at java.util.concurrent.FutureTask.report(FutureTask.java:122) [na:1.8.0_151]
at java.util.concurrent.FutureTask.get(FutureTask.java:192) [na:1.8.0_151]
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:941) ~[tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1421) [tomcat-embed-core-8.5.31.jar:8.5.31]
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1411) [tomcat-embed-core-8.5.31.jar:8.5.31]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_151]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_151]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_151]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_151]
這個問題在網上搜了會都沒法解決,於是去 stackoverflod 找了找,直接給出解決方案的倒是沒有,不過看到了這個資訊:
Don't know if your problem is resolved. I had similar issues and found out that one of the dependencies is built with an older version of servlet-api. Springboot doesn't want you to include the servlet-api, but if the dependency is built with an older version, then you will see this error.
意思就是說這個錯誤是因為依賴中有其他版本的 servlet-api ,於是就會出現上面那個錯誤。看到這我再去 maven 裡面看了看 hadoop-common 的依賴,果然發現了個寶貝!
然後就很簡單啦,把這玩意也給排除了,萬事大吉!!