过滤器
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-388L9dWe-1607249381740)(C:\Users\hello\AppData\Roaming\Typora\typora-user-images\image-20201107204647321.png)]](https://i-blog.csdnimg.cn/blog_migrate/5d0d418a647f2576bdbf5192ad948cb8.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mK8Bvo34-1607249381744)(C:\Users\hello\AppData\Roaming\Typora\typora-user-images\image-20201107222543846.png)]](https://i-blog.csdnimg.cn/blog_migrate/752fa08e8742c14c745811effb36b1e6.png)
过滤器其实很简单就是实现Filter接口的java类,接口中有init(),doFilte(),destroy()方法。
init()和destory()方法就不用多说了,他俩跟Servlet是一样的。只有在Web服务器加载和销毁的时候被执行,只会被执行一次!
值得注意的是doFilter()方法,**它有三个参数(ServletRequest,ServletResponse,FilterChain),**从前两个参数我们可以发现:过滤器可以完成任何协议的过滤操作
FilterChain是一个接口
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5hBektje-1607249381749)(C:\Users\hello\AppData\Roaming\Typora\typora-user-images\image-20201107222933471.png)]](https://i-blog.csdnimg.cn/blog_migrate/961204ad052fde13447b0463a1d3b13e.png)
FilterChain.doFilter()就是放行给下一个过滤器,或者目标资源
例子:通过过滤器解决编码问题
jsp:
html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="/fliter" method="post">
姓名: <input type="text" name="name">
<input value="提交" type="submit">
</form>
</body>
</html>
过滤器:
过滤器注册:
<filter>
<filter-name>filterencode</filter-name>
<filter-class>FilterDemo</filter-class>
</filter>
<filter-mapping>
<filter-name>filterencode</filter-name>
<url-pattern>/fliter</url-pattern>
</filter-mapping>
过滤器编写:
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//将request和response强转成http协议的
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
httpServletRequest.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("text/html;charset=UTF-8");
System.out.println("第一经过过滤器");
System.out.println("设置request的utf-8");
System.out.println(httpServletRequest);
//放行
filterChain.doFilter(httpServletRequest,servletResponse);
System.out.println("第二次经过过滤器");
System.out.println("设置response的utf-8");
System.out.println(httpServletResponse);
}
servlet:
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter pw=resp.getWriter();
System.out.println("servlet-->"+req);
String name=req.getParameter("name");
System.out.println("获得前端的name"+name);
pw.write("收到前端的name-->"+name);
System.out.println("servlet-->"+resp);
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jaV7lNVW-1607249381754)(C:\Users\hello\AppData\Roaming\Typora\typora-user-images\image-20201107223328593.png)]](https://i-blog.csdnimg.cn/blog_migrate/7ec51f742d5f2b4527cbc3b0631f473e.png)
监听器
-
监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行
-
监听器涉及三个组件:事件源,事件对象,事件监听器
-
事件源发生动作时,调用监听器的方法,同时传递事件对象给事件监听器(从而监听器可以通过事件对象对时间源进行操作)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ltG71z2h-1607249381757)(C:\Users\hello\AppData\Roaming\Typora\typora-user-images\image-20201107172019394.png)]](https://i-blog.csdnimg.cn/blog_migrate/0212b9a07d79176ff44e5c5a91622cd5.png)
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mQZceBHA-1607249381761)(C:\Users\hello\AppData\Roaming\Typora\typora-user-images\image-20201107174718883.png)]](https://i-blog.csdnimg.cn/blog_migrate/b38d11511d67a0390b37666bb75b3fdc.png)
解释
事件源中的这句代码是核心personListener.doEat(new Event(this))
# 由上图知
# 1. main方法中 产生事件源对象this(调用eat方法的对象) ,调用事件源方法,也就是事件发生
# 2. 事件发生 触发事件对象生成(new event(this))
# 3. 因为在main中通过 匿名对象 在事件源上注册了监听器(person.registerLister(匿名对象的listener))
# 4. 所以第2步事件对象的产生,使得监听器(匿名对象就是监听器)执行[personListener.doEat(new Event(this))]
注:在监听器的方法的执行过程中,因为封装了event,且event封装了事件源(此处为this) 故可在监听器中操作事件源
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VyyYF5tS-1607249381764)(C:\Users\hello\AppData\Roaming\Typora\typora-user-images\image-20201107195949110.png)]](https://i-blog.csdnimg.cn/blog_migrate/fe3ef158568f418afa3d802343e20305.png)
监听器接口:
/**
* 事件监听器
*
* 监听Person事件源的eat和sleep方法
*/
interface PersonListener{
void doEat(Event event);
void doSleep(Event event);
}
事件对象:
* 事件对象Even
*
* 事件对象封装了事件源
*
* 在监听器上能够通过事件对象获取得到事件源
*
*
*/
class Event{
private Person person;
public Event() {
}
public Event(Person person) {
this.person = person;
}
public Person getResource() {
return person;
}
}
测试:
ublic static void main(String[] args) {
Person person = new Person();
//注册监听器,将监听器器赋给person中的监听器
person.registerLister(new PersonListener() {
@Override
public void doEat(Event event) {
Person person1 = event.getResource();
System.out.println(person1 + "正在吃饭呢!");
}
@Override
public void doSleep(Event event) {
Person person1 = event.getResource();
System.out.println(person1 + "正在睡觉呢!");
}
});
//当调用eat方法时,触发事件,将事件对象传递给监听器,(事件对象event封装了事件源)最后监听器获得事件源,对事件源进行操作
person.Eat();
}
监听的实质,要监听的事件源方法中调用监听器的方法对事件源进行操作
servlet监听器
和其它事件监听器略有不同的是,servlet监听器的注册不是直接注册在事件源上,而是由WEB容器负责注册,开发人员只需在web.xml文件中使用<listener>标签配置好监听器
1.监听对象的创建和销毁
- HttpSessionListener
- ServletContextListener
- ServletRequstListener
使用:
<listener>
<listener-class>Listener1</listener-class>
</listener>
ublic class Listener1 implements ServletContextListener,
HttpSessionListener, ServletRequestListener {
// Public constructor is required by servlet spec
public Listener1() {
}
public void contextInitialized(ServletContextEvent sce) {
System.out.println("容器创建了");
}
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("容器销毁了");
}
public void sessionCreated(HttpSessionEvent se) {
System.out.println("Session创建了");
}
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("Session销毁了");
}
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
}
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
}
}
2.监听context,Session,Request属性的变化
- ServletContextAttributeListener
- HttpSessionAttributeListener
- ServletContextAttributeListener
三个接口中的方法名都一致,只不过接受的参数不同,都为
- attributeAdded()
- attributeRemoved()
- attributeReplaced()
public class Listener1 implements ServletContextAttributeListener {
@Override
public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("Context对象增加了属性");
}
@Override
public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("Context对象删除了属性");
}
@Override
public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("Context对象替换了属性");
}
}
3.监听session内的对象
即监听添加进session的对象
实现HttpSessionBindingListener接口,JavaBean 对象可以感知自己被绑定到 Session 中和从 Session 中删除的事件【和HttpSessionAttributeListener的作用是差不多的】
实现HttpSessionActivationListener接口,JavaBean 对象可以感知自己被活化和钝化的事件(当服务器关闭时,会将Session的内容保存在硬盘上【钝化】,当服务器开启时,会将Session的内容在硬盘式重新加载【活化】)
测试:监听session的钝化和活化
- 修改tomcat的配置,META-INF下的context.xml
<Context>
<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
<Store className="org.apache.catalina.session.FileStore" directory="zhongfucheng"/>
</Manager>
</Context>
- User既是监听器又是事件源
/*
* 由于涉及到了将内存的Session钝化到硬盘和用硬盘活化到内存中,所以需要实现Serializable接口
*
* 该监听器是不需要在web.xml文件中配置的。但监听器要在事件源上实现接口
* 也就是说,直接用一个类实现HttpSessionBindingListener和HttpSessionActivationListener接口是监听不到Session内对象的变化的。
* 因为它们是感知自己在Session中的变化!
* */
public class User implements HttpSessionBindingListener,HttpSessionActivationListener,Serializable {
private String username ;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public void sessionWillPassivate(HttpSessionEvent httpSessionEvent) {
HttpSession httpSession = httpSessionEvent.getSession();
System.out.println("钝化了");
}
@Override
public void sessionDidActivate(HttpSessionEvent httpSessionEvent) {
HttpSession httpSession = httpSessionEvent.getSession();
System.out.println("活化了");
}
@Override
public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("绑定了对象");
}
@Override
public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("解除了对象");
}
}
- 测试代码
User user = new User();
request.getSession().setAttribute("aaa", user);
request.getSession().removeAttribute("aaa");
vent) {
System.out.println("绑定了对象");
}
@Override
public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("解除了对象");
}
}
- 测试代码
User user = new User();
request.getSession().setAttribute("aaa", user);
request.getSession().removeAttribute("aaa");
Java Web过滤器与监听器详解
本文详细介绍了Java Web中的过滤器与监听器的工作原理及应用实例。过滤器通过实现Filter接口完成对请求和响应的拦截处理,解决如编码问题等需求;监听器则用于监听应用程序中的各种事件,如对象的创建、销毁或属性变化。
1488

被折叠的 条评论
为什么被折叠?



