??xml version="1.0" encoding="utf-8" standalone="yes"?>
此类错误错误信息,上网上查了一?大概了解了下,原来是JAR文g版本问题,
原来目中用了ehcache-1.1.jar文g,
把它换成ehcache-1.2.3.jar文g?
重新启动JBOSS服务?问题解决~~~~
]]>
在用的W一步你要明白你所发布的web目所使用的服务器Q因Z同的服务器对于用log4j是有些不同的Q我在实际用中主要是用tomcat和jboss两类Q对于tomcat,它本w是没有配置log4j的,所以用v来和常规的一P而在jboss中它是本w配|了log4j的,所以有时候我们在看项目代码时Q其整个目q没有log4j的配|文Ӟ而在一些类中仍然定义了Logger,例如static Logger log = org.apache.log4j.Logger.getLogger(UserDaoImple.class);Q这p明开发者打用jboss默认的log4j的配|,我们可以在jboss下的对应的log目录下的server.log中看到日志,jboss本n的log4j的配|是debug,infoU的日志写在server.log中,而像error{别比较高的日志打印到控制CQ而写到server.log中的日志比较多,q不方便查看。于是我们想C用自qlog4j配置写到某个具体的文件中Q注意文件要先徏立,才能忘里面写东西Qlog4j自己不能建立文gQ,但这里因为jboss有它自己的log4j配置Q所以如果我们配|的log4j包含Console的AppenderӞ׃出错Q错误类g
ERROR: invalid console appender config detected, console stream is looping.
解决Ҏ一是不用Console的Appender,或者改jboss的配|文Ӟ在jboss-service.xml文g??br />
<mbean code="org.jboss.logging.Log4jService" name="jboss.system:type=Log4jService,service=Logging">
<attribute name="ConfigurationURL">resource:log4j.xml</attribute>
<attribute name="CatchSystemOut">false</attribute>
<attribute name="Log4jQuietMode">true</attribute>
</mbean>?/font>
我徏议不用Console的AppenderQ当然这是对jboss3.2.x是这P对于jboss4.0.x如果我们要用自己的log4j配置照上q改q是会有问题Q会有类glog4j:ERROR A "org.jboss.logging.util.OnlyOnceErrorHandler" object is not assignable to a "org.apache.log4j.spi.ErrorHandler" variable的异常,解决Ҏ是把/server/default/jbossweb-tomcat55.sar/META-INF/jboss-service.xml 中的以下两个熟悉Ҏtrue
<attribute name="Java2ClassLoadingCompliance">true</attribute>
<attribute name="UseJBossWebLoader">true</attribute>
以上是使用jboss服务器可能出现的问题Q解决了q些再来使用log4j比较简单了?/strong>
下面说说对于采用了spring框架的项目如何用log4j,在spring中用log4jQ有些方便的地方Q?/font>
1. 动态的改变记录U别和策略,即修改log4j.properties,不需要重启Web应用Q这需要在web.xml中设|一下?br />
2. 把log文g定在 /WEB-INF/logs/ 而不需要写l对路径?
3. 可以把log4j.properties和其他properties一h?WEB-INF/ Q而不是Class-Path?/font>
首先我们在web.xml中需要设定一?/font>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>WEB-INF/log4j.properties</param-value>
</context-param>
<context-param>
<param-name>log4jRefreshInterval</param-name>
<param-value>60000</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
其中W二部分是能够动态修改log4j.properties的关键,容器会每60U扫描log4j的配|文?nbsp;?/font>对于log4j的配|文件如何写Q这׃多说了,大家可以去googleQ有一点就是我们如果用RollingFileAppender或者FileAppenderӞ可以通过${webapp.root}来定位到服务器的发布的该目下,q是spring把web目录的\径压入到了webapp.root的系l变量。然后,在log4j.properties 里就可以q样定义logfile位置
log4j.appender.logfile.File=${webapp.root}/WEB-INF/logs/myfuse.log
如果有多个web应用Q怕webapp.root变量重复Q可以在context-param里定义webAppRootKey?/font>
当我们定义完log4j.properties后,剩下的就是在需要记录的class中new 出Logger?img alt="" src="http://blog.csdn.net/fckeditor/editor/images/smiley/msn/teeth_smile.gif" />
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1067141
Spring框架则简化了使用JEElg(包括JMS)的Q务。它提供的模板机刉藏了典型的JMS实现的细节,q样开发h员可以集中精力放在处理消息的实际工作中,而不用担心如何去创徏Q访问或清除JMS资源?/p>
本文对Spring JMS API作一个概qͼq过一个运行在JBoss MQ服务器上的web例程来介l如何用Spring JMS API来异步处理(发送和接收Q消息。我通过传统JMS实现和Spring JMS实现两者间的比较,来展CZ用Spring JMS处理消息是如何的单和灉|?/p>
在现实中Q大多数webh都是同步处理的。例如,当用戯d一个网站,首先输入用户名和密码Q然后服务器验证d合法性。如果验证成功,E序允许该用户q入|站。这里,dh在从客户端接收以后被x处理了。信用卡验证是另一个同步处理的例子Q只有服务器证实输入的信用卡h有效的,同时客户在帐户上有够的存款Q客h被允许l操作。但是让我们思考一下在序处理pȝ上的支付l算步骤。一旦系l证实该用户信用卡的信息是准的Qƈ且在帐户上有_的资金,׃必等到所有的支付l节落实、{账完成。支付结可以异步方式进行,q样客户可以l箋q行核查操作?/p>
需要比典型同步h耗费更长旉的请求,可以使用异步处理。另一个异步处理的例子是,在本地贷Ƒ֤理程序中Q提交至自动扉KpȝQAUSQ的信用h处理q程。当借方提交h甌后,抉|公司会向AUS发送请求,以获取信用历史记录。由于这个请求要求得到全面而又详细的信用报告,包括借方C和过ȝ帐户Q最q的付款和其他胦务资料,服务器需要耗费较长的时_几小时或着有时甚至是几天)来对q些h作出响应。客LE序Q应用)要与服务器连接ƈ耗费如此长的旉来等待结果,q是毫无意义的。因此通信应该是异步发生的Q也是Q一旦请求被提交Q它p攄在队列中Q同时客L与服务器断开q接。然后AUS服务从指定的队列中选出hq行处理Qƈ处理得到的消息攄在另一个消息队列里。最后,客户端程序从q个队列中选出处理l果Q紧接着处理q个信用历史数据?/p>
如果您用过JMS代码Q您会发现它与JDBC或JCA很像。它所包含的样本代码创建或JMS资源对象回溯Q得每一ơ您需要写一个新cL发送和接收消息Ӟ都具有更好的代码密集性和重复性。以下序列显CZ传统JMS实现所包括的步骤:
您可以看刎ͼ步骤6是处理消息的唯一地方。其他步骤都只是理与实际业务要求无关的JMS资源Q但是开发h员必ȝ写ƈl护q些额外步骤的代码?/p>
Spring框架提供了一个模板机制来隐藏Java APIs的细节。JEE开发h员可以用JDBCTemplate和JNDITemplatecL分别讉K后台数据库和JEE资源Q数据源Q连接池Q。JMS也不例外。Spring提供JMSTemplatec,因此开发h员不用ؓ一个JMS实现ȝ写样本代码。接下来是在开发JMS应用E序时Spring所h一些的优势?/p>
说明Q因为只是ؓ了演C如何用spring~写jms的应用,所以本例没有什么实际用途?/p>
E序功能QMessageProducer.javaҎ一用户信息产生一个消息发送到 JMS ProviderQ由MessageConsumer.java接收?/p>
1.在Jboss里配|XML文g创徏一个新的JMS provider?br />
打开位于%JBOSS_HOME%server\default\deploy\jms文g夹下的jbossmq-destinations-service.xml文gQ加入以下代码片断:
<!-- Register User Send/Receive Queue -->
<mbean code="org.jboss.mq.server.jmx.Queue"
name="jboss.mq.destination:service=Queue,name=registerUserQueue">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
<!-- Register User Send/Receive Topic -->
<mbean code="org.jboss.mq.server.jmx.Topic"
name="jboss.mq.destination:service=Topic,name=registerUserTopic">
<depends optional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>
2.在spring的配|文件中配置JMSlg的具体细节?br />
Q?QJNDI上下文是取得JMS资源的v始位|,因此首先我们要配|JNDI模板Q?br />
<!-- JNDI上下?它是取得JMS资源的v始位|? -->
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">
org.jnp.interfaces.NamingContextFactory
</prop>
<prop key="java.naming.provider.url">localhost</prop>
<prop key="java.naming.factory.url.pkgs">
org.jnp.interfaces:org.jboss.naming
</prop>
</props>
</property>
</bean>
注意Q此JNDI模板用到了org.jnp.interfaces.NamingContextFactory所以要?JBOSS_HOME%\client下的jbossall-client.jar加到你的目的classpath中?br />
Q?Q配|连接工厂:
<!-- JMSq接工厂 -->
<bean id="jmsConnectionFactory"class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>XAConnectionFactory</value>
</property>
</bean>
注意QXAConnectionFactoryq个JNDI名字是在%JBOSS_HOME%server\default\deploy\jms文g夹下的jms-ds.xml中定义的(它是由JBoss指定??br />
Q?Q配|JmsTemplatelg。在例程中我们用JmsTemplate102。同时用defaultDestination属性来指定JMS目标?br />
<!-- JMS模板配置 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate102">
<property name="connectionFactory" ref="jmsConnectionFactory" />
<property name="defaultDestination" ref="destination" />
<property name="pubSubDomain">
<value>true</value>
</property>
<!-- {待消息的时?ms) -->
<property name="receiveTimeout">
<value>30000</value>
</property>
</bean>
注意Q如果用topic-subscribe(主题订阅)模式Q该模板的pubSubDomain属性gؓtrue;若用PToP(点对?模式QpubSubDomain属性gؓfalse或不配置该属性?br />
(4)定义一个JMS目标来发送和接收消息:
<bean id="destination" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>topic/registerUserTopic</value>
</property>
</bean>
(5)配置发送者和接收者组?
<!-- 消息发布?-->
<bean id="msgProducer" class="com.boco.jms.MessageProducer">
<property name="jmsTemplate" ref="jmsTemplate" />
</bean>
<!-- 消息接收?-->
<bean id="msgConsumer" class="com.boco.jms.MessageConsumer">
<property name="jmsTemplate" ref="jmsTemplate" />
</bean>
3.相应的类:
(1). User对象?br />
/**
* User.java
* created on Jul 2, 2006
* Copyrights 2006 BOCO,Inc. All rights reserved.
*/
package com.boco.dto;
import java.io.Serializable;
/**
* desc: 用户信息 Bean
* @author qiujy
*/
public class User {
private int id;
private String username;
private String password;
private String email;
public User(){}
//以下为Getter,setterҎ?br />
......
}
(2).消息生者:
/**
* MessageProducer.java
* created on Jul 22, 2006
* Copyrights 2006 BOCO,Inc. All rights reserved.
*/
package com.boco.jms;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.Session;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import com.boco.dto.User;
/**
* desc:消息生?br />
* @author qiujy
*
*/
public class MessageProducer {
/** JMS模板 */
private JmsTemplate jmsTemplate;
public void setJmsTemplate(JmsTemplate jmsTemplate){
this.jmsTemplate = jmsTemplate;
}
public void sendMessage(final User user){
//调用模板的send来发送消?br />
jmsTemplate.send(new MessageCreator(){
public Message createMessage(Session session) throws JMSException {
//构造一个要发送的消息
MapMessage message = session.createMapMessage();
message.setInt("id", user.getId());
message.setString("username", user.getUsername());
message.setString("password", user.getPassword());
message.setString("email", user.getEmail());
System.out.println("send success!!");
return message;
}
});
}
}
(3).消息消费者:
/**
* MessageConsumer.java
* created on Jul 22, 2006
* Copyrights 2006 BOCO,Inc. All rights reserved.
*/
package com.boco.jms;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import org.springframework.jms.core.JmsTemplate;
import com.boco.dto.User;
/**
* desc:消息消费?br />
* @author qiujy
*
*/
public class MessageConsumer {
/** JMS模板 */
private JmsTemplate jmsTemplate;
public void setJmsTemplate(JmsTemplate jmsTemplate){
this.jmsTemplate = jmsTemplate;
}
public User receiveMessage(){
//参数为Destination的JNDI名字L前面的模式类型标?br />
//MapMessage msg = (MapMessage)jmsTemplate.receive("registerUserQueue");
MapMessage msg = (MapMessage)jmsTemplate.receive("registerUserTopic");
User user = new User();
try {
user.setId(msg.getInt("id"));
user.setUsername(msg.getString("username"));
user.setPassword(msg.getString("password"));
user.setEmail(msg.getString("email"));
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return user;
}
}
(4).试用例Q?br />
//======== 生者测试用?===============
/**
* TestMsgProducer.java
* created on Jul 22, 2006
* Copyrights 2006 BOCO,Inc. All rights reserved.
*/
package com.boco.jms;
import junit.framework.TestCase;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.boco.dto.User;
/**
* desc:
* @author qiujy
*
*/
public class TestMsgProducer extends TestCase {
private ApplicationContext context;
/**
* @param arg0
*/
public TestMsgProducer(String arg0) {
super(arg0);
context = new ClassPathXmlApplicationContext("applicationContext_jms.xml");
}
/* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
}
/* (non-Javadoc)
* @see junit.framework.TestCase#tearDown()
*/
protected void tearDown() throws Exception {
super.tearDown();
}
/**
* Test method for {@link com.boco.jms.MessageProducer#sendMessage(com.boco.dto.User)}.
*/
public void testSendMessage() {
User user = new User();
user.setId(132);
user.setUsername("JMSTest");
user.setPassword("password");
user.setEmail("support@boco.com.cn");
MessageProducer producer = (MessageProducer)context.getBean("msgProducer");
producer.sendMessage(user);
}
}
//============ 消费者测试用?===============
/**
* TestMsgConsumer.java
* created on Jul 22, 2006
* Copyrights 2006 BOCO,Inc. All rights reserved.
*/
package com.boco.jms;
import junit.framework.TestCase;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.boco.dto.User;
/**
* desc:
* @author qiujy
*
*/
public class TestMsgConsumer extends TestCase {
private ApplicationContext context;
/**
* @param arg0
*/
public TestMsgConsumer(String arg0) {
super(arg0);
context = new ClassPathXmlApplicationContext("applicationContext_jms.xml");
}
/* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
}
/* (non-Javadoc)
* @see junit.framework.TestCase#tearDown()
*/
protected void tearDown() throws Exception {
super.tearDown();
}
/**
* Test method for {@link com.boco.jms.MessageConsumer#receiveMessage()}.
*/
public void testReceiveMessage() {
MessageConsumer consumer = (MessageConsumer)context.getBean("msgConsumer");
User user = consumer.receiveMessage();
assertNotNull(user);
System.out.println( "id========" + user.getId()
+ "\nname======" + user.getUsername()
+ "\npassword==" + user.getPassword()
+ "\nemail=====" + user.getEmail());
}
}
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1418938
启动JBOSS服务?先运行TestMsgConsumer.java;再运行TestMsgProducer.java,卛_看到控制台的输出?d~~~~~