filter过滤器
用的功能很简单,但是很重要(做框架的时候可能才会用得很深)
平时用就是实现一下Filter接口(重写它得doFliter(),init(),destroy()方法,放行chain.doFilter(request,response);),并在web.xml里边进行配置就完事了
另外一个是它的最佳实践:
公共代码得提取(如request,response指定编码解码方式,公共代码提到一块(处理post))
对request,response的方法进行增强(装饰者模式(包装,同样是乱码处理,使处理参数的能力更强大,支持中文(处理get))/动态代理(反射))(自动登陆)
进行权限控制
//装饰者模式(这个模式也很好记,就是你想用request对象的时候,你又希望它的getParameter()方法更加强大,可以处理中文,那么你可以建一个新类,对它的方法进行增强) //(应用场景:不想增加很多子类/只想增强类的一些方法,例如在EncodingFilter过滤器中对request的getParameter方法进行增强,处理其中文参数乱码问题) public class EncodingFilter implements Filter{ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //在传递request之前对request的getParameter方法进行增强 /* * 装饰者模式(包装) * * 1、增强类与被增强的类要实现统一接口(继承同一个父类) * 2、在增强类中传入被增强的类(构造) * 3、需要增强的方法重写 不需要增强的方法调用被增强对象的 * */ //被增强的对象req HttpServletRequest req = (HttpServletRequest) request; //增强对象enhanceRequest EnhanceRequest enhanceRequest = new EnhanceRequest(req); chain.doFilter(enhanceRequest, response); } @Override public void destroy() { } @Override public void init(FilterConfig filterConfig) throws ServletException { } } class EnhanceRequest extends HttpServletRequestWrapper{ //HttpServletRequestWrapper这个包装类就是专门用来你继承,进而写增强方法的 private HttpServletRequest request; public EnhanceRequest(HttpServletRequest request) {//核心:传入被增强的类 super(request); this.request = request; } //对getParaameter增强,增强的是原来类的方法 @Override public String getParameter(String name) { String parameter = request.getParameter(name);//乱码 try { parameter = new String(parameter.getBytes("iso8859-1"),"UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return parameter; } }
Listener监听器
监听三个域对象:request,session,servletContext
ServletContext代表整个web应用,只有一个
步骤:实现接口,覆盖方法,xml中进行配置
ServletContextListener
方法中可以获取到被监听的对象(两方法,一个是通用的)
应用:
web应用一创建,加载数据库驱动,连接池的初始话
加载spring初始配置文件(applicationContext.xml)
任务调度(定时器:Timer/TimeTask)
HttpSession(多个)
服务端没有某浏览器对应的session时创建
3种销毁:应用正常关闭,手动销毁,过期(默认30min)
应用:统计访问量
ServletRequest(瞬间的事)
ServletContext,HttpSession,ServletRequest三个域对象的属性变化(getAttribute,setAttribute,removeAttribute)
对象感知监听器((绑定,解绑)(钝化,活化)),(对象需要实现接口,不需要配置xml)
绑定状态:就一个对象被放到session域中
解绑状态:就是这个对象从session域中移除了
钝化状态:是将session内存中的对象持久化(序列化)到磁盘
活化状态:就是将磁盘上的对象再次恢复到session内存中
package com.itheima.domian; import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionBindingListener; public class Person implements HttpSessionBindingListener{ private String id; private String name; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override //绑定的方法 public void valueBound(HttpSessionBindingEvent event) { System.out.println("person被绑定了"); } @Override //解绑方法 public void valueUnbound(HttpSessionBindingEvent event) { System.out.println("person被解绑了"); } }
Person p = new Person(); p.setId("100"); p.setName("zhangsanfeng"); //将person对象绑到session中 session.setAttribute("person", p); //将person对象从session中解绑 session.removeAttribute("person");
一个对象必须要实现了Serializable接口,才能被存储到磁盘上
钝化:服务器正常关闭时,session中的对象会被钝化到磁盘
活化:服务器正常启动时,session会活化这个对象(外界又可以正常的访问这个session了)
另外,钝化和活化你可以进行主动控制(context.xml,默认配置1分钟不用被销毁)
package com.itheima.domian; import java.io.Serializable; import javax.servlet.http.HttpSessionActivationListener; import javax.servlet.http.HttpSessionEvent; public class Customer implements HttpSessionActivationListener,Serializable{ private String id; private String name; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override //钝化 public void sessionWillPassivate(HttpSessionEvent se) { System.out.println("customer被钝化了"); } @Override //活化 public void sessionDidActivate(HttpSessionEvent se) { System.out.println("customer被活化了"); } }
<?xml version="1.0" encoding="UTF-8"?> <Context> <!-- maxIdleSwap:session中的对象多长时间不使用就钝化 --> <!-- directory:钝化后的对象的文件写到磁盘的哪个目录下 配置钝化的对象文件在 work/catalina/localhost/钝化文件 --> <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1"> <Store className="org.apache.catalina.session.FileStore" directory="itheima32" /> </Manager> </Context>
Listener 监听器结合Timer定时任务实现每天定时给过生日的员工发邮件
<listener> <listener-class>com.itheima.birthday.BirthdayListener</listener-class> </listener>
package com.itheima.birthday; import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import java.util.Timer; import java.util.TimerTask; import javax.mail.MessagingException; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanListHandler; import com.itheima.mail.MailUtils; public class BirthdayListener implements ServletContextListener{ @Override public void contextInitialized(ServletContextEvent sce) { //当web应用启动 开启任务调动---功能在用户的生日当前发送邮件 //开启一个定时器 Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { // 为当前的生日的用户发邮件 //1、获得今天过生日的人 //获得今天的日期 SimpleDateFormat format = new SimpleDateFormat("MM-dd"); String currentDate = format.format(new Date()); //根据当前时间从数据查询今天过生日的人 QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource()); String sql = "select * from customer where birthday like ?"; List<Customer> customerList = null; try { customerList = runner.query(sql, new BeanListHandler<Customer>(Customer.class) ,"%"+currentDate+"%"); } catch (SQLException e) { e.printStackTrace(); } //08-18 //2、发邮件 if(customerList!=null&&customerList.size()>0){ for(Customer c : customerList){ String emailMsg = "亲爱的:"+c.getRealname()+",生日快乐!"; try { MailUtils.sendMail(c.getEmail(), "生日祝福", emailMsg); System.out.println(c.getRealname()+"邮件发送完毕"); } catch (MessagingException e) { e.printStackTrace(); } } } } }, new Date(), 1000*10); //实际开发中起始时间是一个固定的时间 //实际开发中间隔时间是1天 } @Override public void contextDestroyed(ServletContextEvent sce) { } }
Interceptor拦截器
Java三大器:过滤器,监听器,拦截器Interceptor
拦截器是依赖Java反射机制来实现的。拦截器的实现,用到的是JDK实现的动态代理,我们都知道,JDK实现的动态代理,需要依赖接口。拦截器
是在面向切面编程中应用的,就是在你的service或者一个方法前调用一个方法,或者在方法后调用一个方法。拦截器不是在web.xml,比如struts在
struts.xml中配置。
过滤器可以简单的理解为“取你所想取”,过滤器关注的是web请求;拦截器可以简单的理解为“拒你所想拒”,拦截器关注的是方法调用