springboot servlet、filter、listener
阅读数:101 评论数:0
跳转到新版页面分类
python/Java
正文
一、servlet
(1)静态页面
早期的web应用主要用于浏览静态页面,比如Apache、Nginx向浏览器返回静态HTML,浏览器负责解析HTML,将结果呈现给用户。
为了达到一些交互操作,并动态获取结果,需要扩展,因些Sun推出了servlet技术。
(2)servlet容器
servlet没有main方法,不能独立运行,因此需要由窗口来实例化和调用。
(3)servlet接口
http服务怎么知道调用哪个servlet呢?为了避免与业务逻辑耦合,所以采用了面向接口编辑,这些接口就是servlet接口,有时我们也把实现servlet接口的业务类叫作servlet。
(1)直接实现servlet接口
(2)继承GenericServlet,这是一个抽象类
(3)继承HttpServlet,这个类是GenericServlet的子类
二、Filter
过滤器的执行由Servlet容器回调完成,是AOP思想的一个实践,用于过滤浏览器发出的请求,并且决定放行请求还是对中断请求做特殊处理。
(1)@WebFilter
同时需要在启动类使用@ServletComponentScan,这会扫描带@WebFilter、@WebServlet、@WebListener。
@Slf4j
@Order(1)
@WebFilter(filterName = "myFilter", urlPatterns = {"/user/*"})
public class MyFilter implements Filter {
@Autowired
private SysUserService sysUserService;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("过滤器初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
log.info("请求处理");
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest) servletRequest;
log.info("MyFilter, URL:{}", request.getRequestURI());
if (request.getRequestURI().contains("login")) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
log.info("非法URL:{}", request.getRequestURI());
response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
PrintWriter writer = response.getWriter();
writer.print("no access");
}
}
@Override
public void destroy() {
log.info("过滤器销毁");
}
}
三、Listener
事件监听机制可以理解为一种观察者模式,它是Servlet容器为Servlet提供的扩展点,用于对特定对象的生命周期和特定事件进行响应处理。
在Java中,事件对象都是继承java.util.EventObject对象,事件监听器都是java.util.EventListener实例。EventObject没有默认构造函数,需要外部传递source参数,用于记录并跟踪事件的来源。
(1)面向接口编程,实现ApplicationListener接口
(2)基于注解,@EventListener(Spring自定义的注解)
(1)监听Servlet上下文
监听类需要实现ApplicationListener接口,并实现onApplicationEvent方法(在容器初始化完成之后执行),参数是ContextRefreshEvent(上下文刷新事件)。
package com.ieslab.powergrid.demosvr.utils;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
@Component
public class MyServletContextListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
System.out.println("Spring容器加载完成触发,可用于初始化环境,准备测试数据、加载一些数据到内存");
//此处可以开启一个线程,用于查询首页数据,并缓存在内容中,供所有的首页进行查询
//代码省略
}
}
(2)监听HTTP会话Session对象
监听类需要实现HttpSessionListener接口,然后重写sessionCreated方法和sessionDestroyed销毁方法。
package com.ieslab.powergrid.demosvr.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@Component
@Slf4j
public class MyHttpSessionListener implements HttpSessionListener {
public static Integer count = 0; //记录在线的用户数量
@Override
public synchronized void sessionCreated(HttpSessionEvent httpSessionEvent) {
log.info("新用户上线了");
count++;
httpSessionEvent.getSession().getServletContext().setAttribute("count", count);
}
@Override
public synchronized void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
log.info("用户下线了");
count--;
httpSessionEvent.getSession().getServletContext().setAttribute("count", count);
}
}
(3)监听Servlet Request对象
package com.ieslab.powergrid.demosvr.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
@Component
@Slf4j
public class MyServletRequestListener implements ServletRequestListener {
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
log.info("session id为:{}", request.getRequestedSessionId());
log.info("request url为:{}", request.getRequestURL());
request.setAttribute("name", "斌哥");
}
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
log.info("request end");
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
log.info("request域中保存的name值为:{}", request.getAttribute("name"));
}
}
(1)自定义事件
package com.ieslab.powergrid.demosvr.entity;
import org.springframework.context.ApplicationEvent;
public class TestEvent extends ApplicationEvent {
private Person person;
public TestEvent(Object source, Person person) {
super(source);
this.person = person;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
(2)自定义监听器
package com.ieslab.powergrid.demosvr.utils;
import com.ieslab.powergrid.demosvr.entity.Person;
import com.ieslab.powergrid.demosvr.entity.TestEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class TestEventListener implements ApplicationListener<TestEvent> {
@Override
public void onApplicationEvent(TestEvent testEvent) {
// 把事件中的信息获取到
Person person = testEvent.getPerson();
// 处理事件,实际项目中可以通知别的微服务或者处理其他逻辑等
log.info("用户名:" + person.getFirstName());
log.info("城市:" + person.getCity());
}
}
(3)测试
package com.ieslab.powergrid.demosvr.service;
import com.ieslab.powergrid.demosvr.entity.Person;
import com.ieslab.powergrid.demosvr.entity.TestEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
//发布事件触发器
@Service
@Slf4j
public class TestService {
@Resource
private ApplicationContext applicationContext;
/**
* 发布事件
* @return
*/
public Person getPerson() {
Person person = new Person("", "斌哥","","济南");
// 发布事件
TestEvent event = new TestEvent(this, person);
applicationContext.publishEvent(event);
log.info("触发器被触发");
return person;
}
}