Weblogic教程

Tomcat 开源项目移植入 WebLogic 问题总结

JDK 和 Servlet 版本问题

WebLogic 8.1 sp4以前(包括 sp4)只支持 JDK1.4,建议使用 JDK1.4进行编译代码, 有时 JDK1.5编译的程序无法运行。由于 WebLogic 8.1不支持 J2EE1.4,不要使用 Servlet2.4和 JSP2.0进行编码。


Include 问题

在 WebLogic 中不允许在一个文件中出现一次以上类似 < %@ page contentType="text/html; charset=GBK"%>的代码,所以使用 include file 时,一般将被 include 的文件中类似代码删除。

在 TOMCAT 时允许上述代码出现多次,并且使用 include file 时,若被 include 的文 件中不包含上述代码,编译后客户端显示为乱码。最早 BEA 对此解释为 TOMCAT 不符合 J2EE 规范。

为了增加代码的通用性和可移植性,建议使用<jsp:include>方式。<jsp:include>将 被 include 的 jsp 代码视为独立存在的文件,所以可以在不同文件内使用多个<%@ page contentType="text/html; charset=GBK"%>。<jsp:include>直接传参由<jsp:param>标签 完成,在被 include 页面可以通过 request 得到传入的值,也可以通过 request.setAttribute()、request.getAttribute()进行内外文件参数传递。


打包后 Log4j 支持问题

有时候应用打包成.war 部署到 WebLogic 后,出现如下问题:

Error: weblogic.management.DeploymentException: Cannot set web app root
system property when WAR file is not expanded - with nested exception:
[java.lang.IllegalStateException: Cannot set web app root system property
when WAR file is not expanded]

问题解决:通常您不需要亲自编写 servlet 或者 listener,比如直接利用 log4j 的 com.apache.jakarta.log4j.Log4jInit 类,Spring 的 org.springframework.web.util.Log4jConfigServlet 和 org.springframework.web.util.ServletContextListener 方式配置,找到 Log4jConfigServlet 和 ServletContextListener 的源码,他们都在适当的地方(callback method)调用了 Log4jWebConfigurer.initLogging(getServletContext());定位到这个方 法,第一句就是:WebUtils.setWebAppRootSystemProperty(servletContext);再定位到该 方法,方法很短:

public static void setWebAppRootSystemProperty(ServletContext
servletContext) throws IllegalStateException {
String param = servletContext.getInitParameter(WEB_APP_ROOT_KEY_PARAM);
String key = (param != null ? param : DEFAULT_WEB_APP_ROOT_KEY);
String oldValue = System.getProperty(key);
if (oldValue != null) {
throw new IllegalStateException(
"WARNING: Web app root system property already set: "
+ key + " = " + oldValue
+ " - Choose unique webAppRootKey values in your web.xml files!");
}
String root = servletContext.getRealPath("/");
if (root == null) {
throw new IllegalStateException
("Cannot set web app root system property when WAR file is not
expanded");
}
System.setProperty(key, root);
servletContext.log("Set web app root system property: "
                   + key + " = " + root);
}

系统需要读取 webAppRootKey 这个参数,所以在部署到 WebLogic 里的时候,在 web.xml 中手动添加如下代码:

 <context-param>
    <param-name>webAppRootKey </param-name>
    <param-value>webapp.root </param-value>
 </context-param>

WebLogic 自身也包含对 Log4j 的支持,在打包部署(.war)的时候,会和 Spring 的 org.springframework.web.util.Log4jConfigListener 有冲突,所以改用 Servlet 加载。

web.xml 中删除下面代码:

<listener id="log4jConfigListener">
   <listener-class>org.springframework.web.util.Log4jConfigListener
   </listener-class>
</listener>

将 Listener 加载改为通过 Servlet 加载,再在 web.xml 增加:

<servlet>
   <servlet-name>log4jConfigListener</servlet-name>
   <servlet-class>org.springframework.web.util.Log4jConfigServlet
   </servlet-class>
   <load-on-startup>0</load-on-startup>
</servlet>

Hibernate3、Axis 部署问题

Hibernate3中 hibernate.query.factory_class 的默认值为 org.hibernate.hql.ast.ASTQueryTranslatorFactory,在 WebLogic 下系统运行时会抛出 org.hibernate.QueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken 异常。

这个问题讨论得很多,解决方法也各式各样,其实很简单,WebLogic 系统默认加载 EJB-QL parser,存在重名类,所以使用时会出现 ClassNotFoundException。一般的简单 修改方式(包括前述)都是修改 startWebLogic 运行的脚本,将 antlr-2.7.5H3.jar 文件优 先加载。但这样的方法会带来一些其他问题,所以不推荐使用。

最好的方法是,在 WEB-INF 目录下建一个 weblogic.xml 文件,文件中加入如下代码:

<weblogic-web-app>
  <container-descriptor>
   <prefer-web-inf-classes>true</prefer-web-inf-classes>
  </container-descriptor>
</weblogic-web-app>

说明:prefer-web-inf-classes=true 是 WebLogic's classloader 在有重名类时,优 先加载 Web 应用中 WEB-INF 内的类。

Axis 部署同理。注意:

1、如果有包在通过修改 startWebLogic 启动脚本优先加载后,web 应用中有重复的 包,并且将 prefer-web-inf-classes=true,BEA WebLogic 编译 JSP 时会报错。(直接设 置 true 就可以,无需再修改脚本;如果已经修改过脚本,需要还原。)

2、可以有两种方式部署 Axis 包:一种为 prefer-web-inf-classes=true,另外一种 将 saaj.jar 一个包在 webservices.jar 之前优先加载。经实际验证,只将 saaj.jar 一个 包优先加载并不能解决全部问题,如果不使用前一种方法,请将 axis 全部的包加载在 webservices.jar 之前。


Axis 远程调用.net Web Service 接口找不到方法

调用时出现如下异常:

    java.lang.NoSuchMethodError:
javax.xml.namespace.QName.getPrefix()Ljava/lang/String

应用系统需要调用远程.net 平台的 Web Service 接口,该程序在 Tomcat 和 Windows 下 BEA WebLogic 8.1 SP5下进行测试,全部正常使用,但移植到 HPUX 上,每次调用接口 时都会找不到 javax.xml.namespace.QName.getPrefix()方法。

查明该方法存在于 jaxrpc.jar 文件中,而 webservices.jar 存在名为 javax.xml.namespace.QName 的重名类。在 startWebLogic.sh 文件中,手动将 jaxpc.jar 排在 webservices.jar 之前加载,即可解决该问题。

关注微信获取最新动态