一、过滤器
当需要限制用户访问某些资源或者在处理请求时提前处理某些资源的时候,就可以使用过滤器Filter完成。
过滤器是以一种组件的形式绑定到WEB应用程序当中的,与其他的WEB应用程序组件不同的是,过滤器是采用了“链”的方式进行处理的。
1、实现过滤器
在Servlet中,如果要定义一个过滤器,则直接让一个类实现javax.servlet.Filter接口即可,此接口定义了三个操作方法:
public void init(FilterConfig filterConfig) throws ServletException
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException,ServletException
public void destroy()
注意:过滤器是在容器启动时自动加载的
2、FilterChain
FilterChain接口的主要作用是将用户的请求向下传递:
public void doFilter(ServletRequest request,ServletResponse response)throws
IOException,ServletException
package org.afanti.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class HelloFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("HelloFilter初始化啦......");
String admin=filterConfig.getInitParameter("admin");
System.out.println("接收到传递给HelloFilter过滤器的初始化参数是:"+admin);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("进入HelloFilter的doFilter()方法了...");
chain.doFilter(request, response); // "放行",将请求传递给下一个过滤器,如果没有下一个过滤器则使之请求资源
System.out.println("准备离开HelloFilter的doFilter()方法...");
}
@Override
public void destroy() {
System.out.println("HelloFilter销毁了...");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>FilterProjectT</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>hello</filter-name>
<filter-class>org.afanti.filter.HelloFilter</filter-class>
<init-param>
<param-name>admin</param-name>
<param-value>obama</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hello</filter-name>
<url-pattern>/images/*</url-pattern>
</filter-mapping>
</web-app>
2、Filter的配置方式
方式一:
注解配置
@WebFilter(filterName="",urlPatterns={"/images/*"},
initParams={
@WebInitParam(name="fruit",value="grape")
})
方式二:
web.xml中配置
3、过滤器的过滤路径配置类型
路径类型一:以目录的方式配置过滤路径:eg: /images/*
路径类型二:以资源类型的方式配置过滤路径: eg: *.jpg
但是,不能将两种路径类型的配置结合起来,否则Web容器启动时发生错误。
4、过滤器的应用
编码过滤
在过滤器中设置编码
package org.afanti.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class EncodingFilter implements Filter{
private String encode;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("EncodingFilter初始化了...");
this.encode=filterConfig.getInitParameter("encode");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("进入EncodingFilter的doFilter...");
request.setCharacterEncoding(encode); // 设置请求编码
chain.doFilter(request, response);// “放行”
System.out.println("将要离开EncodingFilter的doFilter...");
}
@Override
public void destroy() {
System.out.println("EncodingFilter销毁了...");
}
}
web.xml
<filter>
<filter-name>encoding</filter-name>
<filter-class>org.afanti.filter.EncodingFilter</filter-class>
<init-param>
<param-name>encode</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encoding</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
登录验证
在过滤器中判断session属性是否为空,从而进行登录验证
package org.afanti.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("LoginFilter初始化了...");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("进入LoginFilter的doFilter...");
HttpServletRequest req=(HttpServletRequest)request;
HttpSession session=req.getSession();
if(session.getAttribute("user")!=null){ // 如果session范围中user属性不为null,则说明已经登录
chain.doFilter(request, response); // “放行”
}else{
// String contextPath=request.getServletContext().getContextPath();
request.setAttribute("msg","您还未登录,请先登录!");
request.getRequestDispatcher("/login/login.jsp").forward(request, response); // 服务端跳转(转发)
// HttpServletResponse resp=(HttpServletResponse)response;
//resp.sendRedirect("/FilterProject/login/login.jsp");
}
System.out.println("将要离开LoginFilter的doFilter......");
}
@Override
public void destroy() {
}
}
web.xml
<filter>
<filter-name>loginValidate</filter-name>
<filter-class>org.afanti.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginValidate</filter-name>
<url-pattern>/success/*</url-pattern>
</filter-mapping>
二、监听器
在WEB中可以对application、session、request三种操作进行监听。
Servlet监听器分为三种:
1.ServletContext监听器(容器监听器)
2.HttpSession监听器(会话监听器)
3.ServletRequest监听器(请求监听器)
1、Servlet配置监听器的方式
方式一:
注解配置: @WebListener
方式二:
web.xml中配置:
<listener>
<listener-class>监听器路径</listener-class>
</listener>
2、ServletContext监听器
1.对Web容器状态(生命周期)的监听
实现ServletContextListener接口,覆写相关方法
补充:ServletContextEvent代表容器状态的事件类,里面有个getServletContext()方法
package session;
import java.util.*;
import javax.servlet.http.HttpSession;
public class MySessionUtil {
private static Map<String,HttpSession> map=new HashMap<String,HttpSession>(); // 用来装session的
public static void addSession(HttpSession session){
map.put(session.getId(),session);
}
// 通过sessionid查询session
public static HttpSession getSessionById(String sessionId){
return map.get(sessionId);
}
}
package application;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
// 监听Web容器状态的监听器
@WebListener
public class ContextStateListener implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent sce) {
String contextPath=sce.getServletContext().getContextPath();
System.out.println("容器启动啦,上下文路径是:"+contextPath);
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
String contextPath=sce.getServletContext().getContextPath();
System.out.println("容器销毁啦,bye bye~~~,上下文路径是:"+contextPath);
}
}
2.对ServletContext属性范围的监听
实现ServletContextAttributeListener接口,覆写相关方法
package application;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class ContextAttributeListener implements ServletContextAttributeListener{
@Override
public void attributeAdded(ServletContextAttributeEvent event) {
String attrName=event.getName(); // 获取属性名
Object attrValue=event.getValue(); // 获取属性值
System.out.println("属性添加(add)了,属性名为:"+attrName+";属性值为:"+attrValue);
}
@Override
public void attributeRemoved(ServletContextAttributeEvent event) {
String attrName=event.getName(); // 获取属性名
Object attrValue=event.getValue(); // 获取属性值
System.out.println("属性移除(remove)了,属性名为:"+attrName+";属性值为:"+attrValue);
}
@Override
public void attributeReplaced(ServletContextAttributeEvent event) {
String attrName=event.getName(); // 获取属性名
Object attrValue=event.getValue(); // 获取属性值
System.out.println("属性替换(replace)了,属性名为:"+attrName+";属性值为:"+attrValue);
}
}
3、HttpSession监听器(对会话进行监听)
(1)对会话状态(生命周期)进行监听
实现HttpSessionListener接口,覆写相关方法
package session;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class SessionStateListener implements HttpSessionListener{
@Override
public void sessionCreated(HttpSessionEvent se) {
HttpSession session=se.getSession();
// session.setMaxInactiveInterval(30);
MySessionUtil.addSession(session); // 将新创建的session添加到工具类的Map集合中
String sessionid=session.getId();
System.out.println("新的session创建了,sessionID是:"+sessionid);
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
String sessionid=se.getSession().getId();
System.out.println("session销毁了,sessionID是:"+sessionid);
}
}
(2)对会话(HttpSession)属性范围进行监听
实现HttpSessionAttributeListener接口,覆写相关方法
package session;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
@WebListener
public class SessionAttributeListener implements HttpSessionAttributeListener{
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
String name=event.getName(); // 获取属性名
Object value=event.getValue(); // 获取属性值
System.out.println("添加(add)session属性了,属性名是:"+name+";属性值是:"+value);
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
String name=event.getName(); // 获取属性名
Object value=event.getValue(); // 获取属性值
System.out.println("移除session(remove)属性了,属性名是:"+name+";属性值是:"+value);
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
String name=event.getName(); // 获取属性名
Object value=event.getValue(); // 获取属性值
System.out.println("替换session(replace)属性了,属性名是:"+name+";属性值是:"+value);
}
}
(3)对会话(HttpSession)属性范围进行监听———使用HttpSessionBindingListener接口
实现HttpSessionBindingListener接口,覆写相关方法
特别注意:使用HttpSessionBindingListener接口实现会话属性监听时,不用注册!
实现了HttpSessionBindingListener接口的类,将该类的对象在会话属性范围绑定和解绑属性时,会自动调用valueBound(xxx)方法和valueUnbound(xxx)方法。
package session;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
// 实现了HttpSessionBindingListener接口的监听器,用来监听session范围的属性,该监听器不用注册!
public class SessionBindingListener implements HttpSessionBindingListener{
@Override
public void valueBound(HttpSessionBindingEvent event) {
String name=event.getName(); // 获取属性名
Object value=event.getValue(); // 获取属性值
System.out.println("绑定(bound)session属性了,属性名是:"+name+";属性值是:"+value);
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
String name=event.getName(); // 获取属性名
Object value=event.getValue(); // 获取属性值
System.out.println("解绑(unbound)session(remove)属性了,属性名是:"+name+";属性值是:"+value);
}
}
4、ServletRequest监听器(请求监听)
1.对请求状态(生命周期)进行监听
实现ServletRequestListener接口,覆写相关方法
2.对请求范围的属性进行监听
实现ServletRequestAttributeListener接口,覆写相关方法