JavaWeb开发 Servlet技术详解(五)

简介: JavaWeb开发 Servlet技术详解(五)

4.34.3 FilterConfig对象的使用

FilterConfig对象是用来读取<filter>中<init-param>初始化参数的对象。该对象通过参数传递到init方法中,用于读取初始化参数。

通过name获取对应的value。

filterConfig.getInitParameter("name")

返回该Filter中所有中的值。

filterConfig.getInitParameterNames()
<filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>cn.it.filter.EncodingFilter</filter-class>
        <init-param>
            <param-name>code</param-name>
            <param-value>gbk</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>  <!--所有请求都能进入过滤器-->
    </filter-mapping>
package cn.it.filter;
import javax.servlet.*;
import java.io.IOException;
public class EncodingFilter implements Filter {
    //设置默认编码
    private String defaultEncoding = "UTF-8";
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String code = filterConfig.getInitParameter("code");
        //如果设置了编码方式就用设置的编码方式,没有设置就用默认的编码方式
        if (code != null && code.length() > 0) {
            defaultEncoding = code;
        }
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding(defaultEncoding);
        filterChain.doFilter(servletRequest, servletResponse);
    }
    @Override
    public void destroy() {
    }
}

4.34.4 FilterChain(过滤器链)

Filter技术的特点是在对请求或响应做预处理时,可实现“插拔式”的程序设计。我们可以根据自己需求添加多个Filter,也可以根据需求去掉某个Filter,通过修改web.xml文件即可实现。那么如果有多个过滤器对某个请求及响应进行过滤,那么这组过滤器就称为过滤器链。

Filter执行顺序

则按照在web.xml文件中配置的上下顺序来决定先后。在上的先执行,在下的后执行。

4.34.5 基于注解式开发Filter

Filter支持注解式开发,通过@WebFilter注解替代web.xml中Filter的配置。

属性名 类型 作用
filterName String 指定过滤器的 name 属性
urlPatterns String[] 拦截请求的URL,支持多个
value String[] 拦截请求的URL,支持多个
description String 过滤器的描述
displayName String 过滤器的显示名称
initParams WebInitParam[] 指定一组过滤器初始化参数,等价于 标签。

使用注解式开发Filter时,执行顺序会根据Filter的名称进行排序的结果决定调用的顺序。web.xml配置的优先级要高于注解。

package cn.it.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
@WebFilter(urlPatterns = "/ann.do",initParams = {
        @WebInitParam(name = "key",value = "web"),
        @WebInitParam(name = "key2",value = "java")
})
public class AnnotationFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        String key1 = filterConfig.getInitParameter("key1");
        String key2 = filterConfig.getInitParameter("key2");
        System.out.println(key1);
        System.out.println(key2);
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("请求处理");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("响应处理");
    }
    @Override
    public void destroy() {
    }
}

4.34.6 Filter的生命周期

Filter的生命周期是由容器管理的。当容器启动时会实例化Filter并调用init方法完成初始化动作。当客户端浏览器发送请求时,容器会启动一个新的线程来处理请求,如果请求的URL能够被过滤器所匹配,那么则先调用过滤器中 的doFilter方法,再根据是否有chain.doFilter的指令,决定是否继续请求目标资源。当容器关闭时会销毁Filter对象,在销毁之前会调用destroy方法。

4.35 Listener监听器

监听器用于监听web应用中某些对象的创建、销毁、增加,修改,删除等动作的发生,然后作出相应的响应处理。当范围对象的状态发生变化的时候,服务器会自动调用监听器对象中的方法。

监听器分类

按监听的对象划分,可以分为:

  • ServletContext对象生命周期监听器与属性操作监听器;
  • HttpSession对象生命周期监听器与属性操作监听器;
  • ServletRequest对象生命周期监听器与属性操作监听器;

4.35.1 ServletContext对象的生命周期监听器

ServletContextListener接口定义了ServletContext对象生命周期的监听行为。

void contextInitialized(ServletContextEvent sce)

ServletContext对象创建之后会触发该监听方法,并将ServletContext对象传递到该方法中。

void contextDestroyed(ServletContextEvent sce)

ServletContext对象在销毁之前会触发该监听方法,并将ServletContext对象传递到该方法中。

<!--配置ServletLifeCircleListener-->
    <listener>
        <listener-class>cn.it.listener.ServletLifeCircleListener</listener-class>
    </listener>
package cn.it.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class ServletLifeCircleListener implements ServletContextListener {
    //监听ServletContext创建的监听方法(容器启动时创建ServletContext对象,而且只会创建一个)
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("servletContextInitialized:"+sce.getServletContext());
    }
    //监听ServletContext销毁的监听方法(容器关闭时销毁ServletContext对象)
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("servletContextDestroyed:"+sce.getServletContext());
    }
}

4.35.2 ServletContext对象的属性操作监听器

ServletContextAttributeListener接口定义了对于ServletContext对象属性操作的监听行为。

void attributeAdded(ServletContextAttributeEvent scae)

向ServletContext对象中添加属性时会触发该监听方法,并将ServletContext对象传递到该方法中。触发事件的方法servletContext.setAttribute("key","value")。

void attributeRemoved(ServletContextAttributeEvent scae)

当从ServletContext对象中删除属性时会触发该监听方法,并将ServletContext对象传递到该方法中。触发事件方法servletContext.removeAttribute("key")。

void attributeReplaced(ServletContextAttributeEvent scae)

当从ServletContext对象中属性的值发生替换时会触发该监听方法,并将ServletContext对象传递到该方法中。触发事件的方法servletContext.setAttribute("key","value")。

<!--配置ServletContextAttrListener-->
    <listener>
        <listener-class>cn.it.listener.ServletContextAttrListener</listener-class>
    </listener>
package cn.it.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(urlPatterns = "/context.do")
public class ServletContextAttrServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
       //获取ServletContext
        ServletContext servletContext = this.getServletContext();
        servletContext.setAttribute("servletContextKey","123");
        servletContext.setAttribute("servletContextKey",111);
        servletContext.removeAttribute("servletContextKey");
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}
package cn.it.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
public class ServletContextAttrListener implements ServletContextAttributeListener {
    @Override
    public void attributeAdded(ServletContextAttributeEvent scae) {
        System.out.println("-------------addStart-------------------");
        System.out.println("监听添加属性:"+scae.getName()+"="+scae.getValue());
        ServletContext servletContext = scae.getServletContext();
        System.out.println("--------------addend------------------");
    }
    @Override
    public void attributeRemoved(ServletContextAttributeEvent scae) {
        System.out.println("-------------removeStart-------------------");
        System.out.println("监听删除属性:"+scae.getName()+"="+scae.getValue());
        ServletContext servletContext = scae.getServletContext();
        System.out.println("--------------removeEnd------------------");
    }
    @Override
    public void attributeReplaced(ServletContextAttributeEvent scae) {
        System.out.println("-------------replaceStart-------------------");
        System.out.println("监听替换属性:"+scae.getName()+"="+scae.getValue());
        ServletContext servletContext = scae.getServletContext();
        System.out.println("--------------replaceEnd------------------");
    }
}

4.35.3 HttpSession对象的生命周期监听器

HttpSessionListener接口定义了HttpSession对象生命周期的监听行为。

void sessionCreated(HttpSessionEvent se)

HttpSession对象创建后会触发该监听方法,并将已创建HttpSession对象传递到该方法中。

void sessionDestroyed(HttpSessionEvent se)

HttpSession对象在销毁之前会触发该监听方法,并将要销毁的HttpSession对象传递到该方法中。

<!--配置HttpSessionLifeCircleListener-->
    <listener>
        <listener-class>cn.it.listener.HttpSessionLifeCircleListener</listener-class>
    </listener>
    <session-config>
        <session-timeout>1</session-timeout>
    </session-config>
package cn.it.listener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class HttpSessionLifeCircleListener implements HttpSessionListener {
    //监听HttpSession对象创建的方法
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("session对象创建:"+se.getSession());
    }
    //监听HttpSession对象销毁的方法
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("session对象销毁:"+se.getSession());
    }
}

4.35.4 HttpSession对象的属性操作监听器

HttpSessionAttributeListener接口定义了对于HttpSession对象属性操作的监听行为。

void attributeAdded(HttpSessionBindingEvent se)

向HttpSession对象中添加属性时会触发该监听方法,并将HttpSession对象传递到该方法中。触发事件的方法HttpSession.setAttribute("key","value")。

void attributeRemoved(HttpSessionBindingEvent se)

当从HttpSession对象中删除属性时会触发该监听方法,并将HttpSession对象传递到该方法中。触发事件方法HttpSession.removeAttribute("key")。

void attributeReplaced(HttpSessionBindingEvent se)

当从HttpSession对象中属性的值发生替换时会触发该监听方法,并将HttpSession对象传递到该方法中。触发事件的方法HttpSession.setAttribute("key","value")。

<!--配置HttpSessionAttrListener-->
    <listener>
        <listener-class>cn.it.listener.HttpSessionAttrListener</listener-class>
    </listener>
package cn.it.listener;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/sessionAttr.do")
public class HttpSessionAttrServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session = req.getSession();
        session.setAttribute("sessionKey","123");
        session.setAttribute("sessionKey",1123);
        session.removeAttribute("sessionKey");
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}
package cn.it.listener;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
public class HttpSessionAttrListener implements HttpSessionAttributeListener {
    @Override
    public void attributeAdded(HttpSessionBindingEvent se) {
        System.out.println("-------------addStart-------------------");
        System.out.println("监听添加属性:"+se.getName()+"="+se.getValue());
        System.out.println(se.getSession());
        System.out.println("--------------addend------------------");
    }
    @Override
    public void attributeReplaced(HttpSessionBindingEvent se) {
        System.out.println("-------------replaceStart-------------------");
        System.out.println("监听替换属性:"+se.getName()+"="+se.getValue());
        System.out.println(se.getSession());
        System.out.println("--------------replaceEnd------------------");
    }
    @Override
    public void attributeRemoved(HttpSessionBindingEvent se) {
        System.out.println("-------------removeStart-------------------");
        System.out.println("监听删除属性:"+se.getName()+"="+se.getValue());
        System.out.println(se.getSession());
        System.out.println("--------------removeEnd------------------");
    }
}

4.35.5 HttpServletRequest对象的生命周期监听器

ServletRequestListener接口定义了ServletRequest(是HttpServletRequest接口的父接口类型)对象生命周期的监听行为。

void requestInitialized(ServletRequestEvent sre)

HttpServletRequest对象创建后会触发该监听方法,并将已创建HttpServletRequest对象传递到该方法中。

void requestDestroyed(ServletRequestEvent sre)

HttpServletRequest对象在销毁之前会触发该监听方法,并将要销毁HttpServletRequest对象传递到该方法中。

<!--配置HttpServletRequestCircleListener-->
    <listener>
        <listener-class>cn.it.listener.HttpServletRequestCircleListener</listener-class>
    </listener>
package cn.it.listener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
public class HttpServletRequestCircleListener implements ServletRequestListener {
    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println((HttpServletRequest)sre.getServletRequest()+"创建-----------");
    }
    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println((HttpServletRequest)sre.getServletRequest()+"销毁-----------");
    }
}

4.35.6 HttpServletRequest对象的属性操作监听器

<!--配置HttpServletRequestAttrListener-->
<listener>
    <listener-class>cn.it.listener.HttpServletRequestAttrListener</listener-class>
</listener>
package cn.it.listener;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/reqAttr.do")
public class HttpServletRequestAttrServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setAttribute("requestKey","123");
        req.setAttribute("requestKey","123123123");
        req.removeAttribute("requestKey");
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}
package cn.it.listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
public class HttpServletRequestAttrListener implements ServletRequestAttributeListener {
    @Override
    public void attributeAdded(ServletRequestAttributeEvent srae) {
        System.out.println("-------------addStart-------------------");
        System.out.println("监听添加属性:"+srae.getName()+"="+srae.getValue());
        System.out.println(srae.getServletRequest());
        System.out.println("--------------addend------------------");
    }
    @Override
    public void attributeReplaced(ServletRequestAttributeEvent srae) {
        System.out.println("-------------replaceStart-------------------");
        System.out.println("监听替换属性:"+srae.getName()+"="+srae.getValue());
        System.out.println(srae.getServletRequest());
        System.out.println("--------------replaceEnd------------------");
    }
    @Override
    public void attributeRemoved(ServletRequestAttributeEvent srae) {
        System.out.println("-------------removeStart-------------------");
        System.out.println("监听删除属性:"+srae.getName()+"="+srae.getValue());
        System.out.println(srae.getServletRequest());
        System.out.println("--------------removeEnd------------------");
    }
}

4.35.7 基于注解式开发监听器

Listener支持注解式开发,通过@WebListener注解替代web.xml中Listener的配置。

@WebListener
public class HttpServletContextAttrListener implements ServletContextAttributeListener {}
@WebListener
public class HttpServletContextLifeCircleListener implements ServletContextListener {}

4.36 Filter与Listener设计模式

“知其然,知其所以然”。面试会问。

4.36.1 Filter的设计模式

在Servlet的Filter中使用的责任链设计模式。

责任链模式特点

责任链(Chain of Responsibility):责任链模式也叫职责链模式,是一种对象行为模式。在责任链模式里,很多对象由每一个对象对其下一个对象的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不需要知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。

责任链的优缺点

优点:

  • 降低了对象之间的耦合度。
  • 增强了系统的可扩展性。
  • 增强了给对象指派职责的灵活性。
  • 责任链简化了对象之间的连接。
  • 责任分担。每个类只需要处理自己该处理的工作。

缺点:

  • 不能保证请求一定被接收。
  • 对比较长的责任链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
  • 可能会由于责任链的错误设置而导致系统出错,如可能会造成循环调用。

4.36.2 Listener的设计模式

在Servlet的Listener中使用的观察者设计模式。

观察者模式的特点

观察者模式(Observer Pattern):观察者模式是一种对象行为模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

观察者模式的优缺点

优点:

  • 观察者和被观察者是抽象耦合的。
  • 建立一套触发机制。

缺点:

  • 如果一个被观察者对象有很多的直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
  • 如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。
  • 观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
相关文章
|
2月前
|
Java 容器
【学习笔记】Jsp与Servlet技术
【学习笔记】Jsp与Servlet技术
83 0
|
3月前
|
Java 应用服务中间件 Maven
JavaWeb基础5——HTTP,Tomcat&Servlet
JavaWeb技术栈、HTTP、get和post区别、响应状态码、请求响应格数据式、IDEA使用Tomcat、报错解决、Servlet的体系结构、IDEA使用模板创建Servlet
JavaWeb基础5——HTTP,Tomcat&Servlet
|
4月前
|
缓存 安全 Java
Java服务器端技术:Servlet与JSP的集成与扩展
Java服务器端技术:Servlet与JSP的集成与扩展
42 3
|
4月前
|
前端开发 Java 开发工具
servlet技术--使用注解模拟用户登录实现页面跳转
该文章介绍了Servlet技术的使用,通过注解方式开发Servlet来模拟用户登录功能,并在登录成功后实现页面跳转,展示用户的用户名和密码。
servlet技术--使用注解模拟用户登录实现页面跳转
|
4月前
|
前端开发 安全 Java
在Java服务器端开发的浩瀚宇宙中,Servlet与JSP犹如两颗璀璨的明星,它们联袂登场,共同编织出动态网站的绚丽篇章。
在Java服务器端开发的浩瀚宇宙中,Servlet与JSP犹如两颗璀璨的明星,它们联袂登场,共同编织出动态网站的绚丽篇章。
31 0
|
6月前
|
缓存 安全 Java
Java服务器端技术:Servlet与JSP的集成与扩展
【6月更文挑战第23天】Java Web开发中,Servlet和JSP是构建动态Web应用的基础。Servlet处理逻辑,JSP专注展示。示例展示了Servlet如何通过`request.setAttribute`传递数据给JSP渲染。JSP自定义标签提升页面功能,如创建`WelcomeTag`显示欢迎消息。Servlet过滤器,如`CacheControlFilter`,用于预处理数据或调整响应头。这些集成和扩展技术增强了应用效率、安全性和可维护性,是Java服务器端开发的关键。
75 7
|
6月前
|
前端开发 安全 Java
Java服务器端开发实战:利用Servlet和JSP构建动态网站
【6月更文挑战第23天】**Servlet和JSP在Java Web开发中扮演关键角色。Servlet处理业务逻辑,管理会话,JSP则结合HTML生成动态页面。两者协同工作,形成动态网站的核心。通过Servlet的doGet()方法响应请求,JSP利用嵌入式Java代码创建动态内容。实战中,Servlet处理数据后转发给JSP展示,共同构建高效、稳定的网站。虽然新技术涌现,Servlet与JSP仍为Java Web开发的基石,提供灵活且成熟的解决方案。**
89 8
|
6月前
|
存储 设计模式 搜索推荐
早期javeweb技术 JSP JDBC JSTJ Servlet BooStrap(下)
早期javeweb技术 JSP JDBC JSTJ Servlet BooStrap(下)
41 1
|
5月前
|
Java 应用服务中间件 API
如何安装与使用Java EE 8、Servlet 3.0及Apache Maven进行高效开发
【7月更文第1天】搭建高效Java EE 8开发环境,包括安装JDK、选择WildFly或Payara Server作为应用服务器,以及安装Apache Maven。使用Maven创建Servlet 3.0 Web项目,编写 HelloWorldServlet,打包部署到服务器,通过访问特定URL测试应用。这一流程助力开发者实现快速原型和大型项目开发。
122 0
序-Servlet和SpringMVC的联系和区别-配置路径先想好使用的使用的方法,然后匹配的需要的技术
序-Servlet和SpringMVC的联系和区别-配置路径先想好使用的使用的方法,然后匹配的需要的技术