說明
環境
linux:Red Hat 4.8.3-9
weblogic:weblogic 12.1.3
JDK:JDK1.8
程序環境
構建構建:Apache Maven 3.6.1
框架:ijcf 3.2.0(啊,使我們公司的一個內部框架,你可以理解爲Spring、Spring-boot、Spring-web、Spring-MVC等對Spring開源框架的二次封裝)
應用程序本身是一個後臺java應用程序,用戶要求必須運行在weblogic中。故將應用改造成web應用程序。
應用發佈到weblogic的步驟
第一步:在應用的src/main新建webapp,新建web.xml和weblogic.xml。
- web.xml代碼如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.sitech.crmmci.lsms2.app.SpringBootWebLogicApplication</param-value>
</context-param>
<listener>
<!--
<listener-class>org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener</listener-class>
-->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<filter>
<filter-name>metricFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>metricFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.context.WebApplicationContext.ROOT</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- weblogic代碼如下:
<?xml version='1.0' encoding='UTF-8'?>
<weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.3/weblogic-web-app.xsd">
<context-root>/spring-boot-weblogic-app</context-root>
<container-descriptor>
<optimistic-serialization>true</optimistic-serialization>
<prefer-web-inf-classes>false</prefer-web-inf-classes>
<show-archived-real-path-enabled>true</show-archived-real-path-enabled>
<prefer-application-packages>
<package-name>org.slf4j</package-name>
<package-name>javax.validation.*</package-name>
<package-name>org.hibernate.*</package-name>
<package-name>javax.el.*</package-name>
<package-name>org.springframework.*</package-name>
<package-name>org.springframework.web.*</package-name>
<package-name>org.springframework.boot.*</package-name>
<package-name>org.springframework.boot.legacy*</package-name>
<package-name>com.google.*</package-name>
</prefer-application-packages>
</container-descriptor>
</weblogic-web-app>
第二步:配置pom文
- packaing元素的修改爲war
<packaging>war</packaging>
- 在pom中添加maven-war-plugin和spring-boot-maven-plugin插件,用於在執行mvn package默認執行者兩個插件的目標。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<attachClasses>true</attachClasses>
<archive>
<manifestEntries>
<Weblogic-Application-Version>${project.version}</Weblogic-Application-Version>
</manifestEntries>
<manifest>
<addClasspath>true</addClasspath>
<addClasspath>lib/</addClasspath>
</manifest>
</archive>
<webResources>
<resource>
<directory>${project.basedir}/src/main/webapp</directory>
</resource>
</webResources>
<warName>${project.artifactId}</warName>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>BOOT</classifier>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
第三步: 添加啓動類
package com.sitech.crmmci.lsms2.app;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.WebApplicationInitializer;
/**
* @author zhangxy
* @credte 2019-06-26 9:00
*/
@SpringBootApplication
@EnableAutoConfiguration
@Configuration
@ComponentScan
public class SpringBootWebLogicApplication extends SpringBootServletInitializer implements WebApplicationInitializer {
public static void main(String[] args) {
SpringApplication.run(SpringBootWebLogicApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SpringBootWebLogicApplication.class).bannerMode(Banner.Mode.OFF);//.showBanner(false);
}
}
第四步:執行mvn clean package
命令打成war上傳服務器,使用weblogic控制檯部署此war。
部署遇到的問題
本來通過在啓動類上添加@SpringBootApplication,運行在使用Maven的tomcat插件中是一點問題都沒有,但是將程序改造成web應用,達成war部署到weblogic中出現了各種問題。
不要問我這些問題的底層原理?我TM也很惆悵,事情搞完了後不知其然,也不知其所然,好TM自閉。
第一個錯誤:
<Jun 27, 2019 2:33:18 PM CST> <Error> <Munger> <BEA-2156200> <Unable to load descriptor weblogic.utils.classloaders.GenericClassLoader@5f0a0470 finder: weblogic.utils.classloaders.CodeGenClassFinder@24fe96fa annotation: /WEB-INF/lib/tomcat-embed-websocket-9.0.14.jar!/META-INF/web-fragment.xml of module lsms2-app-0.0.1-SNAPSHOT-BOOT. The error is weblogic.descriptor.DescriptorException: Unmarshaller failed
**原因:**沒有導入tomcat-embed-websocket-9.0.14.jar
解決方案:
在pom中添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
Maven會根據傳遞性依賴間接導入tomcat-embed-websocket jar。依賴關係如圖:
——————————————————————————————————
第二個問題:
java.lang.NoSuchMethodError: javax.validation.Configuration.getDefaultParameterNameProvider()Ljavax/validation/ParameterNameProvider;
原因: javax/validation/ParameterNameProvider是validation-api-2.0.0.Final.jar中的類。weblogic應該也自帶validation-api包,所有衝突了。
解決方案: 在weblogic.xml添加如下配置表示優先使用應用中的jar。
<package-name>javax.validation.*</package-name>
validation-api-2.0.0.Final.jar也通過Maven傳遞性依賴引出的。如果你沒有用ijcf框架,可以顯示在pom中制定對此java的依賴。
——————————————————————————————————
第三個問題:
java.lang.IllegalAccessError: tried to access class javax.el.ELUtil from class javax.el.ELManager tried to access class javax.el.ELUtil from class javax.el.ELManager
原因: javax.el.ELManager在javax.el-api-3.0.0.jar中,應用依賴的javax.el-api-3.0.0.ja與web中自帶的javax.el-api衝突。
解決方案: 在weblogic.xml添加如下配置表示優先使用應用中的jar。
<package-name>javax.el.*</package-name>
——————————————————————————————————
第四個問題:
[J2EE:160144]Failed to register library Extension-Name: lsms2-app, Implementation-Version: 0.0.1: Library cannot have Implementation-Version set, without also specifying its Specification-Version
**原因:**部署的時候選擇錯誤。
**解決方案:**在weblogic控制檯部署時選擇如圖中的選項即可解決。
——————————————————————————————————
第五個問題:
<Jun 27, 2019 5:09:35 PM CST> <Warning> <HTTP> <BEA-101162> <User defined listener org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener failed: java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApplicationBuilder.<init>([Ljava/lang/Object;)V. java.lang.NoSuchMethodError: org.springframework.boot.builder.SpringApplicationBuilder.<init>([Ljava/lang/Object;)V
原因: org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener在spring-boot-legacy-2.0.0.RELEASE.jar中,缺少此包。
解決方案: 在pom只添加對此包的依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-legacy</artifactId> <version>2.0.0.RELEASE</version> </dependency>
——————————————————————————————————
第六個問題:
java.lang.IllegalStateException: No WebApplicationContext found: initializer not registered? No WebApplicationContext found: initializer not registered?
原因::web.xml中的listener.listener-class沒有配置或配置不正確。
解決方案: 在web.xml中添加正確的監聽。我的項目一開始使用了SpringBootContextLoaderListener監聽類,後來改成ContextLoaderListener就不報這個錯誤了。
<listener>
<!--
<listener-class>org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener</listener-class>
-->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
——————————————————————————————————
總結一下無非是兩類錯誤:一類是缺少jar,另一類是jar衝突。前者看缺少的那個類在那個jar中(可能在高版本的jar中,不在低版本的jar中),導入對應的jar即可。後者在weblogic.xml中添加相關的配置,來表明優先使用應用中jar即可。