一、Filter过滤器
1 概念
可以实现拦截功能,对于指定资源的限定进行拦截,替换,同时还可以提高程序的性能。在Web开发时,不同的Web资源中的过滤操作可以放在同一个Filter中完成,这样可以不用多次编写重复代码,从而提高了程序的性能。
Filter有三个接口,Filter接口、FilterConfig接口和FilterChain接口,都位于javax.servlet中。
FilterChain接口的doFilter()方法用于调用过滤器链中的下一个过滤器,如果这个过滤器是链上的最后一个过滤器,则将请求提交给处理程序或将响应发给客户端。
2 Filter生命周期
Filter的生命周期可分为创建、执行、销毁三个阶段。
- Web服务器启动的时候会创建Filter实例对象,并调用init()方法,完成对象初始化。Filter对象只会创建一次,init()方法也只执行一次。
- 客户端发送请求资源,如有有符合条件的Filter映射路径,就会按照类名顺序执行doFilter()方法,doFilter()可以执行多次。
- 服务器关闭,Web服务器调用destroy()方法摧毁Filter对象。
3 Filter的实现
@WebFilter注解
@WebFilter注解的属性filterName用于设置Filter的名称,urlPattern属性用于匹配用户请求的URL,例如"/MyServlet",表示过滤器MyFilter会拦截发送到/MyServlet资源的请求。这个URL还可以使用通配符"*"表示,例如,"*.do"匹配所有以".do"结尾的Servlet路径。
创建Servlet类
java
@WebServlet(name = "MyServlet",urlPatterns = "/MyServlet")
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("Hello Servlet");
}
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
创建Filter类
java
@WebFilter(filterName = "MyFilter",urlPatterns = "/MyServlet")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
PrintWriter writer = servletResponse.getWriter();
writer.write("Hello Filter");
}
@Override
public void destroy() {
}
}
没有拦截器运行结果
使用Filter运行结果
4 Filter映射和过滤器链的使用
4.1Filter映射
拦截不同访问方式的请求
注解中的dispatcherTypes属性可以指定过滤器的转发模式,dispatcherTypes属性有4个常用值:Request,INCLUDE、FORWARD、ERROR。
- REUQUEST :当对include()和forwa()方法进行访问目标资源时,过滤器不会被调用,除外过滤器都会被调用。
- INCLUDE:当对include()方法进行访问目标资源时,过滤器会被调用,除外过滤器不会被调用。
- FORWARD:除了forward()外,过滤器不会被调用。
- ERROR:除异常处理机制调用目标外,过滤器不被调用。
创建Forward类
java
@WebServlet(name = "forwardServlet",urlPatterns = "/Forward")
public class Forward extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/helloworld.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
创建跳转界面,在web目录下创建
html
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>成功</h1>
<%int a = 2;%>
<%=a%>
<%! public int print(){
int a = 1;
int b = 2;
return a+b;
}%>
<%= print() %>
</body>
</html>
创建Filter类
java
@WebFilter(filterName = "ForwardFilter",urlPatterns = "/helloworld.jsp",dispatcherTypes = DispatcherType.FORWARD)
public class forwardFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
PrintWriter writer = servletResponse.getWriter();
writer.write("Hello ForwardFilter");
}
@Override
public void destroy() {
}
}
启动服务器,访问/forwar页面时,会请求转发到helloworld.jsp页面,但我们启用了过滤器,因此helloworld.jsp页面被拦截,输出doFilter()中的内容。我们在Filter类中的注解设置了dispatcherTypes = DispatcherType.FORWARD,因此在请求转发的时候会被拦截。
4.2 Filter链
Fliter链是指可以对同一个范文目标设置多个过滤器Filter,那么这些过滤器就形成了一个过滤链。
Filter链使用FilterChain对象,FilterChain对象提供了一个doFilter()方法,该方法的作用是让Filter链上的当前过滤器放行,使请求进入下一个Filter。
在整个链的过程中,如果有两个过滤器,Filter1和Filter2,首先对Filter1进行处理,然后执行doFilter()将方法交给Filter2,Filter2处理完执行doFilter()方法,发送最后的请求,浏览器接收后做出响应,同样也会被拦截器所拦截,但拦截的顺序与前面相反。
创建Filter1
java
@WebFilter(filterName = "MyFilter01",urlPatterns = "/MyServlet")
public class MyFilter01 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
PrintWriter writer = servletResponse.getWriter();
writer.write("Hello 01 ");
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
创建Filter2
java
@WebFilter(filterName = "MyFilter02",urlPatterns = "/MyServlet")
public class MyFilter02 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
PrintWriter writer = servletResponse.getWriter();
writer.write("Hello 02 ");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
拦截目标资源
java
@WebServlet(name = "MyServlet",urlPatterns = "/MyServlet")
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("Hello Servlet");
}
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
}
拦截器的执行顺序是通过命名来执行的。
二、Listener监听器
2.1 概念
Servlet提供了监听器(Listener),专门用于监听Servlet事件。比如监听鼠标单击事件、监听键盘按下事件等。
Listener在监听过程中会涉及几个重要组成部分。
- (1)事件:用户的一个操作,如单击一个按钮、调用一个方法、创建一个对象等。
- (2)事件源:产生事件的对象。比如按钮
- (3)事件监听器:负责监听发生在事件源上的事件。
- (4)事件处理器:监听器的成员方法,当事件发生的时候会触发对应的处理器(成员方法)。
注意:当用户执行一个操作触发事件源上的事件时,该事件会被事件监听器监听到,当监听器监听到事件发生时,相应的事件处理器就会对发生的事件进行处理。
2.2 监听接口
创建ServletContextlistener监听
java
@WebListener
public class MyListener implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("对象被创建");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("对象被摧毁");
}
}
重启服务器并关闭,控制台打印信息。
三、Servlet 3.0新特性
常见注解:
- @WebServlet :修饰Servlet类,用于部署Servlet类。
- @WebFilter:修饰Filter类,用于部署Filter类
- @WebListener:修饰Listener类,用于部署Listener类。
- @WebInitParam:与@WebServlet或@WebFilter注解连用,为@WebServlet或@WebFilter注解配置参数。
- @MultipartConfig:修饰Servlet类,指定Servlet类负责处理multipart/form-data类型的请求(主要用于处理上传文件)
- @ServletSecurity:修饰Servlet类,与JAAS(Java验证和授权API)有关的注解。