#SpringMVC之ApplicationListener简单使用
个人感觉,最好的理解就是把虚拟的思维用现实中的模型实体化,如果找不到实体化的模型怎么办?那就自己创造模型。
我们用现实中的模型来实体化监听这个概念。
《疯狂的石头》里面的那个厕所的感应器就是监听器,手传过感应器就是一个事件,而手所属的人就是触发者。响铃就是监听器触发后做的事情。
废话多了,现在开始定义
- 手去摸传感器(event)
- 手(业务contrlller or sevice)
- 传感器(listener)
首先从厕所把那个感应器拆下来 TraderEvent ###手去摸传感器(event)
package com.excelib.publisher;
import org.springframework.context.ApplicationEvent;
public class TraderEvent extends ApplicationEvent {
/**
*
*/
private static final long serialVersionUID = 1L;
public TraderEvent(Object source) {
super(source);
// TODO Auto-generated constructor stub
System.out.println("--------响铃---------");
}
}
TraderEvent extends ApplicationEvent(spring) extends EventObject。(J2SE)
###手(业务contrlller or sevice)
package com.excelib.publisher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.web.context.support.ServletRequestHandledEvent;
public class HelloWorld implements ApplicationEventPublisherAware {
@Autowired
private String word;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
public void say() {
System.out.println("say:" + word);
TraderEvent event = new TraderEvent(word);
this.applicationEventPublisher.publishEvent(event);
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
// TODO Auto-generated method stub
this.applicationEventPublisher = applicationEventPublisher;
}
public String getWord() {
return word;
}
public void setWord(String word) {
this.word = word;
}
}
xxx-Aware不在介绍了。
###传感器(listener)
package com.excelib.publisher;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
public class ApplicationContetxtListener implements ApplicationListener<ApplicationEvent> {
@Override
public void onApplicationEvent(ApplicationEvent event) {
// TODO Auto-generated method stub
System.out.println("ApplicationContetxtListener===" + event.getClass().toString());
if(event instanceof TraderEvent){
System.out.println("===ApplicationContetxtListener======TraderEvent");
System.out.println(event.toString());
}
else{
System.out.println("===ApplicationContetxtListener======OtherEvent");
System.out.println(event.toString());
}
}
}
###注入spring bean
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean name="helloWorld" class="com.excelib.publisher.HelloWorld">
<property name="word" value="hello world" />
</bean>
<bean id="applicationContetxtListener" class="com.excelib.publisher.ApplicationContetxtListener" />
</beans>
###Test类
package com.excelib.publisher;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestHelloWorld {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
ApplicationContext ac = new ClassPathXmlApplicationContext("spring/spring-event.xml");
HelloWorld hw = (HelloWorld)ac.getBean("helloWorld");
hw.say();
}
}
一起就绪,run吧
ApplicationContetxtListener===class org.springframework.context.event.ContextRefreshedEvent
===ApplicationContetxtListener======OtherEvent
org.springframework.context.event.ContextRefreshedEvent[source=org.springframework.context.support.ClassPathXmlApplicationContext@443ad545: startup date [Fri Jun 16 18:21:18 CST 2017]; root of context hierarchy]
say:hello world
--------响铃---------
TraderContextListener:class com.excelib.publisher.TraderEvent
ApplicationContetxtListener===class com.excelib.publisher.TraderEvent
===ApplicationContetxtListener======TraderEvent
com.excelib.publisher.TraderEvent[source=hello world]
demo到此结束了。
##springmvc中的ServletRequestHandledEvent 其实springmvc在启动的过程中,在很多地方都设置了感应器。ServletRequestHandledEvent就是其中一个, 在http请求的时候,FrameworkServlet的doGet\doPost...里面会出发这个感应器。
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
protected final void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
...
publishRequestHandledEvent(request, startTime, failureCause);
}
private void publishRequestHandledEvent(HttpServletRequest request, long startTime, Throwable failureCause) {
if (this.publishEvents) {
// Whether or not we succeeded, publish an event.
long processingTime = System.currentTimeMillis() - startTime;
this.webApplicationContext.publishEvent(
new ServletRequestHandledEvent(this,
request.getRequestURI(), request.getRemoteAddr(),
request.getMethod(), getServletConfig().getServletName(),
WebUtils.getSessionId(request), getUsernameForRequest(request),
processingTime, failureCause));
}
}
自定义 ApplicationContetxtListener 并注入到spring中
package com.xxx.listener;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.web.context.support.ServletRequestHandledEvent;
public class ApplicationContetxtListener implements ApplicationListener<ApplicationEvent> {
@Override
public void onApplicationEvent(ApplicationEvent event) {
// TODO Auto-generated method stub
System.out.println("ApplicationContetxtListener===" + event.getClass().toString());
if(event instanceof ServletRequestHandledEvent){
System.out.println("===ApplicationContetxtListener======ServletRequestHandledEvent");
System.out.println(event.toString());
}
else{
System.out.println("===ApplicationContetxtListener======OtherEvent");
System.out.println(event.toString());
}
}
}
<bean id="applicationContetxtListener" class="com.xxx.listener.ApplicationContetxtListener">
</bean>
看下输出
ApplicationContetxtListener===class org.springframework.web.context.support.ServletRequestHandledEvent
===ApplicationContetxtListener======ServletRequestHandledEvent
ServletRequestHandledEvent: url=[/productType/list.html]; client=[127.0.0.1]; method=[GET]; servlet=[mvc]; session=[null]; user=[null]; time=[6ms]; status=[OK]
如果需要统计用户请求接口信息,可以在这个地方做点文章。