Filter
Servlet用于处理用户请求,Filter(过滤器)用于拦截request、response,对request、response对象进行修改,在Servlet处理请求前后实现某些功能。
Filter接口
Filter是一个实现了javax.servlet.Filter接口的类。
Filter接口中的方法:
- init(FilterConfig filterFonfig) //初始化Filter
- doFilter(ServletRequest request, ServletResponse response, FilterChain chain) //拦截、过滤。chain对象表示Filter链。此方法是Filter的关键方法。
- destroy() //在web服务器移除Filter对象之前调用,释放Filter对象占用的资源
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { //...... //去的时候拦截,做一些处理 chain.doFilter(req, resp); //放行 //...... //回来的时候拦截,做一些处理 }
Filter示例 统一全站编码
1 @WebFilter("/*") 2 public class HandlerFilter implements Filter { 3 public void init(FilterConfig config){ 4 } 5 6 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { 7 req.setCharacterEncoding("utf-8"); 8 resp.setContentType("text/html;charset=utf-8"); 9 chain.doFilter(req, resp); 10 } 11 12 public void destroy() { 13 } 14 15 }
Filter的配置
Filter的配置方式和Servlet的配置方式差不多。
(1)xml配置
<filter> <filter-name>handlerFilter</filter-name> <filter-class>filter.HandlerFilter</filter-class> </filter> <filter-mapping> <filter-name>handlerFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
(2)注解配置
@WebFilter("/*")
@WebFilter(filterName = "handlerFilter",urlPatterns = "/*")
Filter初始参数
在xml中配置Filter的初始参数:
<filter> <filter-name>handlerFilter</filter-name> <filter-class>filter.HandlerFilter</filter-class> <init-param> <param-name>name</param-name> <param-value>张三</param-value> </init-param> <init-param> <param-name>age</param-name> <param-value>20</param-value> </init-param> </filter>
或者在注解中配置:
@WebFilter( filterName = "handlerFilter", urlPatterns = "/*", initParams = {@WebInitParam(name = "name", value = "张三"),@WebInitParam(name="age",value = "12")} )
我们注意到Filter的init(FilterConfig config)有参数FilterConfig,Web服务器创建此Filter的实例时,会自动把xml或注解中这个Filter的初始参数以FilterConfig对象的形式注入。
在Filter中获取初始参数:
1 public class HandlerFilter implements Filter { 2 private FilterConfig filterConfig; //需要创建一个成员变量 3 public void init(FilterConfig config){ 4 this.filterConfig = config; //需要我们手动初始化 5 } 6 7 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { 8 //获取单个初始参数的值 9 String name = filterConfig.getInitParameter("name"); //返回值是String,不存在该参数时返回null 10 String age = filterConfig.getInitParameter("age"); 11 System.out.println(name); 12 System.out.println(age); 13 14 //遍历 15 Enumeration<String> initParameterNames = filterConfig.getInitParameterNames(); 16 while (initParameterNames.hasMoreElements()){ 17 String paramName = initParameterNames.nextElement(); 18 String paramValue = filterConfig.getInitParameter(paramName); 19 System.out.println(paramValue); 20 } 21 22 chain.doFilter(req, resp); 23 } 24 25 public void destroy() { 26 } 27 28 }
Filter示例 自动登录
思路:
使用cookie存储账号、密码,使用Filter拦截,从cookie中取出账号、密码。若用户要注销|登出、不再想使用自动登录,将cookie的有效期设置为0即可。
浏览器可以查看Cookie,不能直接存储账号、密码的明文,使用Cookie存储账号、密码时需要加密,从Cookie中取出来时需要解密。
每次HTTP请求都使用Filter拦截,从Cookie中解密出账号、密码,每次都要解密,浪费时间。第一次从Cookie中解密出账号、密码后,可以将账号、密码放到session域中,会话期间直接从session中取,不必再解密。
Servelt处理登录表单:
1 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 2 //从登录表单中获取user、pwd 3 String user=request.getParameter("user"); 4 String pwd=request.getParameter("pwd"); 5 6 //将user、pwd放到session域中 7 HttpSession session = request.getSession(); 8 session.setAttribute("user",user); 9 session.setAttribute("pwd",pwd); 10 11 //对user、pwd进行加密 12 //...... 13 14 //将加密后的user、pwd存储到Cookie中,以后仍可使用 15 Cookie userCookie = new Cookie("user", user); 16 Cookie pwdCookie = new Cookie("pwd", pwd); 17 userCookie.setMaxAge(60*60*24*365); 18 pwdCookie.setMaxAge(60*60*24*365); 19 response.addCookie(userCookie); 20 response.addCookie(pwdCookie); 21 22 //...... 23 }
Filter拦截请求:
1 public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { 2 HttpServletRequest httpReq = (HttpServletRequest) req; //ServletRequest不行,需要强转为HttpServletRequest 3 HttpServletResponse httpResp = (HttpServletResponse) resp; 4 5 HttpSession session = httpReq.getSession(); 6 String user = null; 7 String pwd = null; 8 9 if (session.getAttribute("user")==null){ //如果session中没有 10 //从Cookie中找 11 Cookie[] cookies = httpReq.getCookies(); 12 for (Cookie cookie:cookies){ 13 //找到就添加到session域中,需要先解密,此处略过 14 if (cookie.getName().equals("user")){ 15 user=cookie.getValue(); 16 session.setAttribute("user",cookie.getValue()); 17 } 18 else if (cookie.getName().equals("pwd")){ 19 pwd=cookie.getValue(); 20 session.setAttribute("pwd",cookie.getValue()); 21 } 22 } 23 24 //判断从Cookie中找到没 25 if (user==null){ //如果Cookie中也没有 26 httpResp.getWriter().write("请先登录!3秒后自动跳转到登录页面"); 27 httpResp.setHeader("refresh","3;url=/login.jsp"); 28 } 29 else{ //如果从Cookie中找到了,根据需要使用user、pwd 30 //....... 31 } 32 } 33 else{ //如果session有,根据需要取出来使用 34 user= (String) session.getAttribute("user"); 35 pwd = (String) session.getAttribute("pwd"); 36 //...... 37 } 38 39 chain.doFilter(req, resp); 40 }
注销、登出、不再使用自动登录:
1 //使用一个单独的Servlet来处理 2 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 3 //从session域中移出user、pwd 4 HttpSession session = request.getSession(); 5 session.removeAttribute("user"); 6 session.removeAttribute("pwd"); 7 8 //删除保存user、pwd的Cookie。这里使用同名覆盖,也可以遍历cookies获取。 9 Cookie userCookie=new Cookie("user",""); 10 Cookie pwdCookie=new Cookie("pwd",""); 11 userCookie.setMaxAge(0); 12 pwdCookie.setMaxAge(0); 13 response.addCookie(userCookie); 14 response.addCookie(pwdCookie); 15 }
Listener
Listener是Servlet的事件监听器,一共有8个:
- ServletContextListener 监听ServletContext对象的创建、销毁
- HttpSessionListener 监听HTTPSession对象的创建、销毁
- ServletRequestListener 监听ServletRequest对象的创建、销毁
- ServletContextAttributeListener 监听ServletContext中属性的变化(添加属性、移除属性、修改属性)
- HttpSessionAttributeListener
- ServletRequestAttributeListener
- HttpSessionBindListener 监听把JavaBean对象绑定到HttpSession对象上、把JavaBean对象从HttpSession对象上解绑
- HttpSessionActivationListener 监听HttpSession中对象的活化、钝化
钝化:HttpSession对象从内存中转移至硬盘
活化:HttpSession对象从持久化状态转变为运行状态
以上监听器均为接口,自己新建Listener实现即可。
xml注册Listener:
<listener> <listener-class>listener.MyListener</listener-class> </listener>
监听的是整个web应用,不是某个Servlet。
注解注册Listener:
@WebListener()