**
JavaWeb的三大组件
Servlet:小应用程序,在JavaWeb中主要做为控制器来使用 可以处理用户的请求并且做出响应。
实现接口:javax.servlet.Servlet
Filter:过滤器,对用户发送的请求或响应进行集中处理,实现请求的拦截。
实现接口:javax.servlet.Filter
Listener:监听器,在某些框架中会使用到监听器(比如spring),在Web执行过程中,引发一些事件,对相应事件进行处理
实现接口:javax.servlet.XxxListener 每个事件有一个接口
应用场景
登录验证、统一编码处理、敏感字符过滤等
配置方式,一共两种
Xml配置如下:
① 编写java类,实现filter接口
import javax.servlet.*;
import java.io.IOException;
/*
Filter编写
1. 创建一个类实现Filter接口 (不要导错包了)
2. 配置web.xml
解释:
1. filter的url-pattern : 是要拦截的路径
2. filterChain.doFilter(servletRequest, servletResponse);
允许请求向后传递
* */
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/*
filterChain : 过滤器链
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
System.out.println("filter拦截请求");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("filter拦截响应");
}
@Override
public void destroy() {
}
}
**
② 配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<filter>
<filter-name>MyFilter01</filter-name>
<filter-class>com.jsj.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter01</filter-name>
<!-- 过滤器要拦截的路径 -->
<url-pattern>/MyServlet</url-pattern>
</filter-mapping>
</web-app>
注解配置如下
① 编写java类,实现filter接口
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/*
Filter编写
1. 创建一个类实现Filter接口 (不要导错包了)
2. 配置注解
解释:
1. filter的url-pattern : 是要拦截的路径
2. filterChain.doFilter(servletRequest, servletResponse);
允许请求向后传递
* */
//注解配置
@WebFilter("/MyServlet")
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/*
filterChain : 过滤器链
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
System.out.println("filter拦截请求");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("filter拦截响应");
}
@Override
public void destroy() {
}
}
Filter模板设置
模板内容:
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
#parse("File Header.java")
@javax.servlet.annotation.WebFilter(urlPatterns = "/")
public class ${Class_Name} implements javax.servlet.Filter {
public void init(javax.servlet.FilterConfig config) throws javax.servlet.ServletException {
}
public void doFilter(javax.servlet.ServletRequest req, javax.servlet.ServletResponse resp, javax.servlet.FilterChain chain) throws javax.servlet.ServletException, java.io.IOException {
chain.doFilter(req, resp);
}
public void destroy() {
}
}
工作原理:
- 用户发送请求,请求Web资源(包括html,jsp,servlet等)
- 如果Web资源的地址,是filter要拦截的地址,请求将先经过filter,并执行doFilter()
- doFilter()方法中如果调用filterChain.doFilter(),则允许请求访问下一个Web资源。
- 访问Web资源,响应回来会再次经过filter,执行过滤器中的代码,到达浏览器端。
生命周期:
// 初始化方法
public void init(FilterConfig config);
// 执行拦截方法
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain);
// 销毁方法
public void destroy();
-
创建
服务器启动项目加载,创建filter对象,执行init方法(只执行一次) -
运行(过滤拦截)
用户访问被拦截目标资源时,执行doFilter方法 -
销毁
服务器关闭项目卸载时,销毁filter对象,执行destroy方法(只执行一次) -
补充:
过滤器一定是优先于servlet创建的,后于Servlet销毁
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/*
Filter三个生命周期方法
1. init
项目一运行就执行一次,而且早于Servlet的init
2. doFilter
每次被访问都会运行一次,先于Servlet的service
chain.doFilter(req, resp); 相当于请求转发, 请求才能传递下去
3. destroy
服务器关闭之前,执行一次,晚于Servlet的destroy
记住: Filter的生命周期比Servlet长
*/
@WebFilter(urlPatterns = "/LifeServlet")
public class LifeFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
System.out.println("filter init");
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("filter doFilter before");
chain.doFilter(req, resp);
System.out.println("filter doFilter after");
}
public void destroy() {
System.out.println("filter destroy");
}
}
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;
/*
Servlet三个生命周期方法
1. init
默认第一次被访问,执行一次
如果设置启动加载,tomcat启动的时候就会运行
2. service
每次被访问都会运行一次
3. destroy
服务器关闭之前,执行一次
*/
@WebServlet(value = "/LifeServlet",loadOnStartup = 5)
public class LifeServlet extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("servlet init");
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servlet service");
}
@Override
public void destroy() {
System.out.println("servlet destroy");
}
}
拦截路径:
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/*
# 虚拟路径匹配模式
* 精准匹配
用户访问指定目标资源(/show.jsp)时,过滤器进行拦截
* 目录匹配
用户访问指定目录下(/user/*)所有资源时,过滤器进行拦截
* 后缀匹配
用户访问指定后缀名(*.html)的资源时,过滤器进行拦截
* 匹配所有
用户访问该网站所有资源(/*)时,过滤器进行拦截
* */
//@WebFilter(urlPatterns = "/user/a.jsp")
//@WebFilter(urlPatterns = {"/user/a.jsp","/user/b.jsp"})
//@WebFilter(urlPatterns = "/user/*")
//@WebFilter(urlPatterns = "*.html")
//@WebFilter(urlPatterns = "*.do")
public class UrlFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("UrlFilter执行了");
chain.doFilter(req, resp);
}
public void destroy() {
}
}
拦截方式:
常见的两种:1. request(默认拦截方式)
浏览器直接发送请求时,拦截
2. forward
请求转发的时候,拦截
比如: 资源A转发到资源B时
① xml版本
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/*
* # 拦截方式
* 1. 默认情况下, 请求直接来源浏览器 -> 过滤器会执行拦截
* 2. 如果请求来源于 请求转发 -> 过滤器不会执行拦截
*
* # web.xml中的设置
* 0. filter-mapping的子标签dispatcher
* 1. REQUEST (默认) 浏览器的直接请求
* 2. FORWARD 转发的请求
* */
public class MethodFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("我专门拦截BServlet");
chain.doFilter(req, resp);
}
public void destroy() {
}
}
<filter>
<filter-name>MethodFilter</filter-name>
<filter-class>com.itheima04.method.MethodFilter</filter-class>
</filter>
<!--
dispatcher : 用来指定拦截方式的
1. REQUEST(默认) : 浏览器直接发送过来的请求
2. FORWARD: 请求转发过来的请求
可以同时设置
-->
<filter-mapping>
<filter-name>MethodFilter</filter-name>
<url-pattern>/BServlet</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
② 注解版本
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/*
拦截方式:
1. request(默认拦截方式)
浏览器直接发送请求时,拦截
2. forward
请求转发的时候,拦截
# 配置
2. 注解
*/
//@WebFilter(urlPatterns = "/BServlet",dispatcherTypes=DispatcherType.FORWARD) //只配置一种
//配置多种
@WebFilter(urlPatterns = "/BServlet",dispatcherTypes={DispatcherType.REQUEST,DispatcherType.FORWARD})
public class DispatcherFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("DispatcherFilter执行了");
chain.doFilter(req, resp);
}
public void destroy() {
}
}
过滤器链:
在一次请求中,若我们请求匹配到了多个filter,通过请求就相当于把这些filter串起来了,形成了过滤器链.
- 过滤器链执行顺序 (先进后出)
- 过滤器链中执行的先后问题…
配置文件
谁先声明,谁先执行
注解【不推荐】
根据过滤器类名进行排序,值小的先执行。
比如: 用户访问目标资源 show.jsp时,经过 FilterA FilterB
1.用户发送请求
2.FilterA拦截,放行
3.FilterB拦截,放行
4.执行目标资源 show.jsp
5.FilterB增强响应
6.FilterA增强响应
7.封装响应消息格式,返回到浏览器
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("/SourceServlet")
public class SourceServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("SourceServlet被访问了");
}
}
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
//@WebFilter(urlPatterns = "/SourceServlet")
public class FilterA implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws ServletException, IOException {
System.out.println("FilterA执行了");
//允许请求向后传递
chain.doFilter(req, resp);
}
public void destroy() {
}
}
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
//@WebFilter(urlPatterns = "/SourceServlet")
public class FilterB implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("FilterB执行了");
chain.doFilter(req, resp);
}
public void destroy() {
}
}
<filter>
<filter-name>FilterB</filter-name>
<filter-class>com.jsj.chain.FilterB</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterB</filter-name>
<url-pattern>/SourceServlet</url-pattern>
</filter-mapping>
<filter>
<filter-name>FilterA</filter-name>
<filter-class>com.jsj.chain.FilterA</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterA</filter-name>
<url-pattern>/SourceServlet</url-pattern>
</filter-mapping>