Servlet进阶API
每个Servlet都必须由web容器读取Servlet设置信息(标注或者web.xml)、初始化。
对于每个Servlet的设置信息,web容器会为其生成一个ServletConfig作为代表对象,从中可以取得Servlet初始化参数,以及代表整个web应用
程序的ServletContext对象。
Web容器启动后,会读取Servlet设置信息,将Servlet类加载并实例化,并为每个Servlet设置信息产生一个ServletConfig对象,而后调用Servlet接口的
init()方法,并将产生的ServletConfig对象当做参数传入。
这个过程只会在创建Servlet实例后发生一次。
GenericServlet:
@Override public void init(ServletConfig config) throws ServletException { this.config = config; this.init(); }
public void init() throws ServletException { // NOOP by default }ServletConfig相当于Servlet的设置信息代表对象。
可以使用标注设置Servlet初始参数
*/ @WebServlet(name = "FiveServlet", urlPatterns = {"/five.do"}, initParams = { @WebInitParam(name = "name", value = "xiya"), @WebInitParam(name = "age", value = "24") })
private String name; private String age; @Override public void init() throws ServletException { name = getInitParameter("name"); age = getInitParameter("age"); }或者web.xml
<servlet> <servlet-name>FiveServlet</servlet-name> <servlet-class>FiveServlet</servlet-class> <init-param> <param-name>name</param-name> <param-value>xiya</param-value> </init-param> <init-param> <param-name>age</param-name> <param-value>25</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>FiveServlet</servlet-name> <url-pattern>/five.do</url-pattern> </servlet-mapping>web.xml中的设置会覆盖标注的设置。(标注的name属性需要和web.xml的<servlet-name>匹配)。
ServletContext:作为整个Web应用程序的代表。
应用程序事件、监听器
Web容器管理Servlet/JSP相关的对象生命周期,我们可以使用监听器处理对HttpServletRequest对象、HttpSession对象,ServletContext对象的生成、销毁事件,实际上就是我们编写回调函数,然后由Web容器来调用。
HttpServletRequest事件、监听器
ServletRequestListener:是生命周期监听器。
ServletRequestAttributeListener是属性改变监听器。
public interface ServletRequestListener extends EventListener { /** * The request is about to go out of scope of the web application. * The default implementation is a NO-OP. * @param sre Information about the request */ public default void requestDestroyed (ServletRequestEvent sre) { } /** * The request is about to come into scope of the web application. * The default implementation is a NO-OP. * @param sre Information about the request */ public default void requestInitialized (ServletRequestEvent sre) { } }测试代码:
import javax.servlet.*; import javax.servlet.annotation.WebListener; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Created by N3verL4nd on 2017/3/1. */ @WebListener @WebServlet(name = "ListenerServlet", urlPatterns = {"/listener.do"}) public class ListenerServlet extends HttpServlet implements ServletRequestListener, ServletRequestAttributeListener{ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("doPost"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("doGet"); request.setAttribute("name", "xiya"); request.setAttribute("name", "xiya1"); } @Override public void requestDestroyed(ServletRequestEvent sre) { System.out.println("requestDestroyed"); } @Override public void requestInitialized(ServletRequestEvent sre) { System.out.println("requestInitialized"); } @Override public void attributeAdded(ServletRequestAttributeEvent srae) { System.out.println("attributeAdded"); System.out.println("attributeAdded: " + srae.getName() + " " + srae.getValue()); } @Override public void attributeRemoved(ServletRequestAttributeEvent srae) { System.out.println("attributeRemoved"); System.out.println("attributeRemoved: " + srae.getName() + " " + srae.getValue()); } @Override public void attributeReplaced(ServletRequestAttributeEvent srae) { System.out.println("attributeReplaced"); System.out.println("attributeReplaced:" + srae.getName() + " " + srae.getValue()); } }访问:http://localhost:8080/jspRun/listener.do
输出:
requestInitialized
attributeReplaced
attributeReplaced:org.apache.catalina.ASYNC_SUPPORTED true
doGet
attributeAdded
attributeAdded: name xiya
attributeReplaced
attributeReplaced:name xiya
requestDestroyed
attributeReplaced
attributeReplaced:org.apache.catalina.ASYNC_SUPPORTED true
doGet
attributeAdded
attributeAdded: name xiya
attributeReplaced
attributeReplaced:name xiya
requestDestroyed
HttpSession事件、监听器
public interface HttpSessionListener extends EventListener { /** * Notification that a session was created. * The default implementation is a NO-OP. * * @param se * the notification event */ public default void sessionCreated(HttpSessionEvent se) { } /** * Notification that a session is about to be invalidated. * The default implementation is a NO-OP. * * @param se * the notification event */ public default void sessionDestroyed(HttpSessionEvent se) { } }
在HttpSession对象初始化或结束前,分别调用sessionCreated()与sessionDestroyd()方法。
ServletContext事件、监听器
import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.ServletException; import javax.servlet.annotation.WebListener; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * Created by N3verL4nd on 2017/3/1. */ @WebListener @WebServlet(name = "ContextListenerServlet", urlPatterns = {"/contextListener.do"}) public class ContextListenerServlet extends HttpServlet implements ServletContextListener{ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("doGet"); } @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("contextInitialized"); } @Override public void contextDestroyed(ServletContextEvent sce) { System.out.println("contextDestroyed"); } }[2017-03-01 04:02:31,096] Artifact jspRun:war exploded: Artifact is being deployed, please wait...
[2017-03-01 04:02:31,097] Artifact WeiBo:war exploded: Artifact is being deployed, please wait...
contextInitialized
[2017-03-01 04:02:31,448] Artifact jspRun:war exploded: Artifact is deployed successfully
[2017-03-01 04:02:31,450] Artifact jspRun:war exploded: Deploy took 354 milliseconds
由此可见,当整个Web应用程序加载Web容器之后,容器会生成一个ServletContext对象。
重新部署后的日子信息:
[2017-03-01 04:03:53,921] Artifact jspRun:war exploded: Artifact is being deployed, please wait...
[2017-03-01 04:03:53,922] Artifact WeiBo:war exploded: Artifact is being deployed, please wait...
contextDestroyed
contextInitialized
[2017-03-01 04:03:54,580] Artifact jspRun:war exploded: Artifact is deployed successfully
[2017-03-01 04:03:54,580] Artifact jspRun:war exploded: Deploy took 659 milliseconds
[2017-03-01 04:03:55,270] Artifact WeiBo:war exploded: Artifact is deployed successfully
[2017-03-01 04:03:55,270] Artifact WeiBo:war exploded: Deploy took 1,348 milliseconds
[2017-03-01 04:03:53,922] Artifact WeiBo:war exploded: Artifact is being deployed, please wait...
contextDestroyed
contextInitialized
[2017-03-01 04:03:54,580] Artifact jspRun:war exploded: Artifact is deployed successfully
[2017-03-01 04:03:54,580] Artifact jspRun:war exploded: Deploy took 659 milliseconds
[2017-03-01 04:03:55,270] Artifact WeiBo:war exploded: Artifact is deployed successfully
[2017-03-01 04:03:55,270] Artifact WeiBo:war exploded: Deploy took 1,348 milliseconds
注:
生命周期监听器与属性改变监听器都必须使用@WebListener或在web.xml中设置,容器才会知道要加载、读取监听器的相关设置。
过滤器
它是介于Servlet与浏览器之间,可以拦截过滤浏览器对Servlet的请求,也可以改变Servlet对浏览器的响应。
在Servlet/JSP中要实现过滤器,必须实现Filter接口。并且需要使用@WebFilter标注或在web.xml中定义过滤器。
public interface Filter { public default void init(FilterConfig filterConfig) throws ServletException {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException; public default void destroy() {} }Filter接口的doFilter()方法类似于Servlet接口的service()方法。当请求来到容器,而容器发现调用Servlet的service()方法前,可以应用某过滤器,就会
调用该过滤器的doFilter()方法。
如果调用FilterChain的doFilter()方法,就会运行下一个过滤器,如果没有下一个过滤器,就会调用Servlet的service()方法。
如果没有调用FilterChain的doFilter(),则请求就不会继续交给接下来的过滤器或目标Servlet,这就是所谓的拦截请求。