01学习目标
- 能够说出过滤器的作用
- 能够编写过滤器
- 能够说出过滤器生命周期相关方法
- 能够根据过滤路径判断指定的过滤器是否起作用
- 能够说出什么是过滤器链
- 能够编写过滤器解决全局乱码
02.过滤器介绍与应用场景【理解】
目标
掌握过滤器的作用与应用场景
为什么学习过滤器
浏览器提交post传递中文数据给不同的Servlet去处理,那所有接收post中文数据的Servlet都要处理乱码,非常麻烦。可以使用一种拦截请求的方式,拦截所有Servlet的请求,进行集中对中文乱码处理,处理完成以后再去各自的目标Servlet, 这样每个Servlet就不用处理乱码。那么这个拦截所有Servlet的请求就是过滤器。
过滤器介绍
过滤器是javaEE体系提供的一个Filter接口,我们只需要实现Filter接口就可以拦截任意的请求与响应。
过滤器的作用
拦截请求与响应
应用场景介绍
-
解决post提交中文乱码应用场景
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UtcfDueO-1606226675658)(assets/image-20200508093708142.png)]
-
登录权限控制
需求:服务器某一类资源(很多资源)需要登录后才可以访问,就是登录权限控制
传统解决方案:访问这一类中每个资源都要判断是否登录,登录了允许访问,否则return结束
过滤器:使用过滤器拦截这一类资源的请求,进行统一判断是否登录,登录了允许继续访问,否则return结束。节省了每个资源都不需要判断了。
小结
-
过滤器的作用?
拦截请求与响应
-
过滤器是解决什么问题的?
解决如果每一个操作是每个资源都要操作的,那么可以将这个操作放入过滤器中集中处理
-
过滤器的应用场景
统一解决post中文乱码
统一解决登录权限控制
03.开发方式1-手动XML配置【理解】
目标
理解手动xml配置实现过滤器
实现步骤
1、创建Demo1Servlet资源,输出“执行了Demo1Servlet”
2、创建过滤器类实现Filter接口,重写拦截请求与响应的doFilter方法
3、在web.xml中配置过滤器类要拦截的资源路径
Servlet代码
package _01_创建web资源;
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;
/**
* @author 黑马程序员
*/
@WebServlet(name = "Demo1Servlet", urlPatterns = "/Demo1Servlet")
public class Demo1Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("执行了Demo1Servlet");
}
}
过滤器代码
package _02_手动xml创建过滤器;
import javax.servlet.*;
import java.io.IOException;
/**
* @author 黑马程序员
*/
public class Demo1Filter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
//拦截请求与响应的方法
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
//1、拦截请求
System.out.println("==执行了Demo1Filter的拦截请求的任务代码==");
//2.放行(放行就是允许去访问目标资源,如果不放行就不会去目标资源)
filterChain.doFilter(request,response);//本质:调用目标资源去执行
//注意:有这句代码就是放行,否则不放行
//3.拦截响应
System.out.println("==执行了Demo1Filter的拦截响应的任务代码==");
}
@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_4_0.xsd"
version="4.0">
<!--在web.xml中配置过滤器类要拦截的资源路径
1、定义过滤器,配置过滤器类全名
2、配置过滤器拦截的资源路径
-->
<!--定义过滤器,配置过滤器类全名-->
<filter>
<filter-name>Demo1Filter</filter-name>
<filter-class>_02_手动xml创建过滤器.Demo1Filter</filter-class>
</filter>
<!--配置过滤器拦截的资源路径-->
<filter-mapping>
<filter-name>Demo1Filter</filter-name>
<url-pattern>/Demo1Servlet</url-pattern>
</filter-mapping>
</web-app>
访问地址
http://localhost:8080/day15_01_filter_war_exploded/Demo1Servlet
效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tOdBA51D-1606226675662)(assets/image-20200508100412266.png)]
小结
-
实现过滤器的接口是什么?
javax.servlet.Filter
-
过滤器拦截请求与响应的方法是什么?
doFilter
04.开发方式2-注解实现【应用】
目标
使用模板向导和注解配置路径实现过滤器
实现步骤
1、创建Demo2Servlet资源,输出“执行了Demo2Servlet”
2、使用过滤器模板向导创建过滤器类,重写拦截请求与响应的doFilter方法
3、配置过滤器类的注解实现拦截路径配置
Servlet资源代码
package _01_创建web资源;
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;
/**
* @author 黑马程序员
*/
@WebServlet(name = "Demo2Servlet", urlPatterns = "/Demo2Servlet")
public class Demo2Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("执行了Demo2Servlet");
}
}
过滤器代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jVDpSVS5-1606226675666)(assets/image-20200508102127549.png)]
package _03_注解方式创建过滤器;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @author 黑马程序员
*
* @WebFilter 过滤器注解类
* filterName = "Demo2Filter",设置过滤器别名,功能与xml<filter-name>一样, 可有可无的属性
* urlPatterns = "/Demo2Servlet", 设置拦截的资源路径,如果拦截多个路径使用数组, 这个属性必须有
*
* 注解简写方式:@WebFilter("/Demo2Servlet") 只需要配置拦截路径即可
*/
@WebFilter(filterName = "Demo2Filter",urlPatterns = "/Demo2Servlet")
public class Demo2Filter implements Filter {
public void destroy() {
}
//拦截请求与响应的方法
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//1、拦截请求
System.out.println("==执行了Demo2Filter的拦截请求的任务代码==");
//2.放行
chain.doFilter(request,response);
//3.拦截响应
System.out.println("==执行了Demo2Filter的拦截响应的任务代码==");
}
public void init(FilterConfig config) throws ServletException {
}
}
运行效果
方法地址
http://localhost:8080/day15_01_filter_war_exploded/Demo2Servlet
效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C2ltZPk2-1606226675667)(assets/image-20200508102712129.png)]
小结
-
注解实现代码是什么?
@WebFilter(filename="过滤器",urlPatterns={"/资源路径",“/xxx”})
注意:这里配置的资源路径与Servlet资源路径保存一致,必须以“/”开头
-
注解配置与xml配置出现冲突的时候,谁的优先级高?
xml的优先级高
05.过滤器执行流程【理解】
执行流程(时序图)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QIspu0Ty-1606226675669)(assets/1566385548791.png)]
注意:1、先走过滤器拦截请求
2、只有放行才可以去目标资源
3、拦截响应什么都不做就会响应给浏览器数
06.过滤器生命周期【理解】
目标
1.过滤器对象什么时候被创建?
2.服务创建过滤器对象创建了几次?
3.什么时候销毁过滤器?
实现步骤
1. 创建Demo3Servlet资源
2. 创建LifeCycleFilter拦截请求与响应,重写3个方法(init方法, doFilter方法, destroy方法)
3. 观察运行
Demo3Servlet资源代码
package _01_创建web资源;
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;
/**
* @author 黑马程序员
*/
@WebServlet(name = "Demo3Servlet", urlPatterns = "/Demo3Servlet")
public class Demo3Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("执行了Demo3Servlet");
}
}
过滤器代码
package _04_过滤器的生命周期;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @author 黑马程序员
*
* 1.过滤器对象什么时候被创建?
* 答:关注init的运行时间,服务器启动的时候就运行了init方法
* 说明过滤器是在服务器启动的时候服务器创建的
* 2.服务创建过滤器对象创建了几次?
* 答:关注init方法执行了几次,发现init方法只运行一次
* 说明服务器值创建了一次过滤器对象,全局唯一,节省内存
* 3.什么时候销毁过滤器?
* 答:服务器关闭就销毁了
*/
@WebFilter(filterName = "LifeCycleFilter",urlPatterns = "/Demo3Servlet")
public class LifeCycleFilter implements Filter {
//init初始化方法,当前过滤器创建时候调用
public void init(FilterConfig config) throws ServletException {
System.out.println("==调用了LifeCycleFilter的init方法==");
}
//doFilter拦截请求与响应的方法,每次浏览器访问符合拦截路径的资源都会触发
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("==调用了LifeCycleFilter的doFilter方法==");
//注意:没有放行,所以目标资源Demo3Servlet不会运行
}
//destroy销毁方法,服务器关闭之前的时候调用
public void destroy() {
System.out.println("==调用了LifeCycleFilter的destroy方法==");
}
}
运行效果
访问地址
http://localhost:8080/day15_01_filter_war_exploded/Demo3Servlet
效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8F4lDkdt-1606226675670)(assets/image-20200508105015183.png)]
小结
-
过滤器对象什么时候创建?对象全局唯一吗?
服务器启动时创建,全局唯一
-
过滤器对象什么时候销毁?
服务器关闭前
07.过滤器拦截路径的配置【理解】
思考
-
一个过滤器只能拦截一个资源吗?如何做到一个过滤器拦截多个资源?
需要学习拦截路径的配置
目标
过滤器通过拦截路径配置可以拦截一个或多个资源
过滤路径映射配置介绍
拦截路径配置方式有2种:
第一种:精确匹配,配置的路径与资源访问的路径要一模一样就可以拦截
任何资源路径都是可以的
urlPatterns = "/img/3.jpg",
urlPatterns = "/index.jsp"
第二种:模糊匹配,只能使用一个“*”号通配符操作,代表0~多个字符
1.前缀匹配,匹配开头一致的
要求:以“/”开头,以"/*"结尾
例子:
/abc/*,拦截资源访问路径以/abc开头的所有资源
/*,拦截所有资源
2.后缀匹配,匹配结尾一致的
要求:以“*”开头,以“.扩展名”方式结尾
例子:
*.action,拦截资源访问路径以.action为结尾的所有资源
*.do,拦截资源访问路径以.do为结尾的所有资源
注意
1.urlPatterns = "/abc/*/abc",这是精确匹配(完全匹配)
2.在过滤器里面可以使用“/*”,(但是在Servlet里面不可以,否则静态资源无法访问), 在过滤器里面有放行,所以不影响静态资源的执行。
过滤器代码
package _05_过滤器拦截路径的配置;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @author 黑马程序员
*
* 拦截路径配置方式有2种(与servlet路径配置一致):
* 第一种:完全匹配(精确匹配),配置的拦截路径与资源访问的路径要一模一样就可以拦截
* 任何资源路径都是可以的
* urlPatterns = "/img/3.jpg",
* urlPatterns = "/index.jsp"
* 第二种:模糊匹配,只能使用一个“*”号通配符操作,代表0~多个任意字符
* 1.目录匹配(前缀匹配),匹配目录开头一致的
* 要求:以“/”开头,以"/*"结尾
* 例子:
* /abc/*,拦截资源访问路径以/abc目录开头的所有资源
* /*,拦截所有资源
* 2.扩展名匹配(后缀匹配),匹配结尾一致的
* 要求:以“*”开头,以“.扩展名”方式结尾
* 例子:
* *.action,拦截资源访问路径以.action为结尾的所有资源
* *.do,拦截资源访问路径以.do为结尾的所有资源
*/
@WebFilter(filterName = "UrlPatternsFilter",
urlPatterns ={
//完全匹配
"/img/3.jpg","/index.jsp", //3.jpg资源没有也可以拦截
"/abc/*/abc", //注意:这个是完全匹配
//模糊目录匹配
"/abc/*",
//扩展名匹配
"*.do"
} )
public class UrlPatternsFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//1、拦截请求
System.out.println("==执行了UrlPatternsFilter的拦截请求的任务代码==");
//2.放行
chain.doFilter(request,response);
//3.拦截响应
System.out.println("==执行了UrlPatternsFilter的拦截响应的任务代码==");
}
public void init(FilterConfig config) throws ServletException {
}
}
小结
-
过滤器的映射路径配置方式有几种?
3种 1、完全匹配: 拦截的路径与访问的路径一模一样 2、模糊匹配-目录匹配:以“/”开头,“/*”结尾, 例如:/abc/* 3、模糊匹配-扩展名匹配:以“*”开头,“.扩展名”结尾, 例如: *.do
-
常用的路径配置如下,分别代表什么意思?
路径 含义 /admin/* 拦截所有以admin目录开头访问的所有资源 /* 拦截所有资源
08.默认不拦截转发跳转目标资源【应用】
疑问
-
是不是所有资源配置了拦截路径默认都会拦截?
默认不会拦截转发的目标资源
目标
测试过滤器默认不拦截请求转发跳转的目标资源
过滤器默认不拦截请求转发访问的资源演示,实现步骤
1、创建2个资源 ,分别是OneServlet和TwoServlet
2、实现OneServlet转发跳转到TwoServlet
3、创建过滤器类Demo3Filter,拦截TwoServlet
4、运行观察,访问OneServlet转发跳转到TwoServlet,过滤器默认没有拦截TwoServlet
OneServlet代码
package _01_创建web资源;
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;
/**
* @author 黑马程序员
*/
@WebServlet(name = "OneServlet", urlPatterns = "/OneServlet")
public class OneServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//转发跳转到TwoServlet
request.getRequestDispatcher("/TwoServlet").forward(request,response);
}
}
TwoServlet代码
package _01_创建web资源;
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;
/**
* @author 黑马程序员
*/
@WebServlet(name = "TwoServlet", urlPatterns = "/TwoServlet")
public class TwoServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("执行了TwoServlet");
}
}
过滤器代码
package _06_过滤器默认不拦截转发跳转的目标资源TwoServlet;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @author 黑马程序员
*/
@WebFilter(filterName = "Demo3Filter",urlPatterns = "/TwoServlet")
public class Demo3Filter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//1、拦截请求
System.out.println("==执行了Demo3Filter的拦截请求的任务代码==");
//2.放行
chain.doFilter(request,response);
//3.拦截响应
System.out.println("==执行了Demo3Filter的拦截响应的任务代码==");
}
public void init(FilterConfig config) throws ServletException {
}
}
效果
访问地址
http://localhost:8080/day15_01_filter_war_exploded/OneServlet
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H38FvOKk-1606226675671)(assets/image-20200508114120701.png)]
小结
-
过滤器默认可以拦截请求转发访问的目标资源请求与响应吗?
不可以
09.修改拦截方式拦截转发资源【应用】
目标
1、理解过滤器拦截方式
2、掌握拦截方式的修改
拦截方式介绍
拦截方式是浏览器访问资源的方式,可以分为:直接访问和间接访问资源
直接访问资源:浏览器直接的资源路径,包含2个方式
第一个方式:在浏览器地址栏上直接输入资源访问路径
第二个方式:重定向跳转访问的资源,因为2次请求都是浏览器地址栏发出的请求
注意:直接访问资源方式,过滤器默认都可以拦截
间接访问资源:请求转发跳转访问的资源, 比如访问OneServlet转发跳转到TwoServlet
直接访问的是OneServlet, 间接访问的TwoServlet
注意:间接访问资源方式,过滤器默认不拦截
拦截方式类型
类型 | 介绍 |
---|---|
REQUEST | 直接访问资源方式,默认方式 |
FORWARD | 间接访问资源方式,如果设置成这个方式,转发跳转的目标资源也可以拦截了 |
注解方式修改拦截方式的语法
注解属性 | 说明 |
---|---|
dispatcherTypes = {DispatcherType.REQUEST} | 设置采用默认拦截方式,拦截浏览器直接url访问的资源请求与响应 |
dispatcherTypes = {DispatcherType.FORWARD} | 设置采用请求转发拦截方式(间接资源访问方式),注意,如果只配置这种方式,默认方式直接url访问资源将无效不能拦截 |
dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD} | 设置采用直接url与请求转发2种拦截方式 |
扩展web.xml配置过滤器修改拦截方式设置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dWkxEA0c-1606226675672)(assets/1551581167805.png)]
过滤器实现拦截请求转发访问和直接url访问的资源演示,实现步骤
- 创建2个Servlet,OneServlet2与TwoServlet2
- 在OneServlet2实现转发跳转到TwoServlet2
- 创建过滤器拦截TwoServlet2资源请求与响应, 配置拦截方式支持2种(直接和间接)
- 观察运行,可以拦截
OneServlet2
package _07_修改过滤器拦截方式支持拦截2种类型直接与间接;
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;
/**
* @author 黑马程序员
*/
@WebServlet(name = "OneServlet2", urlPatterns = "/OneServlet2")
public class OneServlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//转发跳转到TwoServlet2
request.getRequestDispatcher("/TwoServlet2").forward(request,response);
}
}
TwoServlet2
package _07_修改过滤器拦截方式支持拦截2种类型直接与间接;
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;
/**
* @author 黑马程序员
*/
@WebServlet(name = "TwoServlet2", urlPatterns = "/TwoServlet2")
public class TwoServlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("执行了TwoServlet2");
}
}
过滤器代码
package _07_修改过滤器拦截方式支持拦截2种类型直接与间接;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @author 黑马程序员
*/
@WebFilter(filterName = "Demo4Filter",urlPatterns = "/TwoServlet2",
//配置拦截方式支持直接访问资源方式REQUEST和间接访问资源方式FORWARD
dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST}
)
public class Demo4Filter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//1、拦截请求
System.out.println("==执行了Demo4Filter的拦截请求的任务代码==");
//2.放行
chain.doFilter(request,response);
//3.拦截响应
System.out.println("==执行了Demo4Filter的拦截响应的任务代码==");
}
public void init(FilterConfig config) throws ServletException {
}
}
效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VyYikwSs-1606226675673)(assets/image-20200508120309721.png)]
小结
1、过滤器拦截方式是什么
拦截方式就是浏览器访问资源的方式:
1、直接访问资源REQUEST
2、间接访问资源FORWARD
2、拦截方式如何修改
注解方式修改: dispatcherTypes={DispatcherType.REQUEST,DispatcherType.FORWARD}
xml方式forwardrequest
10.过滤器链介绍与实现【应用】
目标
掌握什么是过滤器链与实现
过滤器链介绍
一个资源被多个过滤器进行拦截请求与响应,多个过滤器是串型执行形成过滤器链条,叫过滤器链
实现过滤器链的步骤
1、创建一个资源Demo4Servlet并输出数据
2、创建Chain1Filter过滤器拦截Demo4Servlet的请求与响应
3、创建Chain2Filter过滤器拦截Demo4Servlet的请求与响应
4、观察运行效果
Demo4Servlet资源代码
package _08_实现过滤器链;
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;
/**
* @author 黑马程序员
*/
@WebServlet(name = "Demo4Servlet", urlPatterns = "/Demo4Servlet")
public class Demo4Servlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("执行了Demo4Servlet");
}
}
Chain1Filter代码
package _08_实现过滤器链;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @author 黑马程序员
*/
@WebFilter(filterName = "Chain1Filter",urlPatterns = "/Demo4Servlet")
public class Chain1Filter implements Filter {
public void destroy() {
}
//拦截请求与响应的方法
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//1、拦截请求
System.out.println("==执行了Chain1Filter的拦截请求的任务代码==");
//2.放行
chain.doFilter(request,response);
//3.拦截响应
System.out.println("==执行了Chain1Filter的拦截响应的任务代码==");
}
public void init(FilterConfig config) throws ServletException {
}
}
Chain2Filter代码
package _08_实现过滤器链;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @author 黑马程序员
*/
@WebFilter(filterName = "Chain2Filter",urlPatterns = "/Demo4Servlet")
public class Chain2Filter implements Filter {
public void destroy() {
}
//拦截请求与响应的方法
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//1、拦截请求
System.out.println("==执行了Chain2Filter的拦截请求的任务代码==");
//2.放行
chain.doFilter(request,response);
//3.拦截响应
System.out.println("==执行了Chain2Filter的拦截响应的任务代码==");
}
public void init(FilterConfig config) throws ServletException {
}
}
运行效果
访问地址
http://localhost:8080/day15_01_filter_war_exploded/Demo4Servlet
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OLO46K5j-1606226675674)(assets/image-20200508141638954.png)]
小结
-
什么是过滤器链?
一个资源被多个过滤器拦截请求与响应,串行执行的过程就是过滤器链
11.过滤器链执行顺序分析与修改【理解】
目标
理解过滤器执行的顺序
理解过滤器执行顺序的修改
执行顺序分析
注解方式通过过滤器类的名字:class chain1Filter 升序继续排序, 不是注解上属性的名字
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BJ2bHYCL-1606226675675)(assets/image-20200229112333031.png)]
案例需求
使用web.xml修改过滤器运行顺序,先运行Chain2Filter,再运行Chain1Filter
Demo4Servlet2
package _09_通过xml配置过滤器链执行顺序;
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;
/**
* @author 黑马程序员
*/
@WebServlet(name = "Demo4Servlet2", urlPatterns = "/Demo4Servlet2")
public class Demo4Servlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("执行了Demo4Servlet2");
}
}
Chain1Filter2
package _09_通过xml配置过滤器链执行顺序;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @author 黑马程序员
*/
@WebFilter(filterName = "Chain1Filter2",urlPatterns = "/Demo4Servlet2")
public class Chain1Filter2 implements Filter {
public void destroy() {
}
//拦截请求与响应的方法
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//1、拦截请求
System.out.println("==执行了Chain1Filter2的拦截请求的任务代码==");
//2.放行
chain.doFilter(request,response);
//3.拦截响应
System.out.println("==执行了Chain1Filter2的拦截响应的任务代码==");
}
public void init(FilterConfig config) throws ServletException {
}
}
Chain2Filter2
package _09_通过xml配置过滤器链执行顺序;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* @author 黑马程序员
*/
@WebFilter(filterName = "Chain2Filter2",urlPatterns = "/Demo4Servlet2")
public class Chain2Filter2 implements Filter {
public void destroy() {
}
//拦截请求与响应的方法
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//1、拦截请求
System.out.println("==执行了Chain2Filter2的拦截请求的任务代码==");
//2.放行
chain.doFilter(request,response);
//3.拦截响应
System.out.println("==执行了Chain2Filter2的拦截响应的任务代码==");
}
public void init(FilterConfig config) throws ServletException {
}
}
web.xml配置
<!--
目标:先执行Chain2Filter2,之后再执行Chain1Filter2
-->
<!--定义过滤器,配置过滤器类全名-->
<filter>
<filter-name>Chain2Filter2</filter-name>
<filter-class>_09_通过xml配置过滤器链执行顺序.Chain2Filter2</filter-class>
</filter>
<!--配置过滤器拦截的资源路径-->
<filter-mapping>
<filter-name>Chain2Filter2</filter-name>
<url-pattern>/Demo4Servlet2</url-pattern>
</filter-mapping>
<!--定义过滤器,配置过滤器类全名-->
<filter>
<filter-name>Chain1Filter2</filter-name>
<filter-class>_09_通过xml配置过滤器链执行顺序.Chain1Filter2</filter-class>
</filter>
<!--配置过滤器拦截的资源路径-->
<filter-mapping>
<filter-name>Chain1Filter2</filter-name>
<url-pattern>/Demo4Servlet2</url-pattern>
</filter-mapping>
运行效果
访问地址
http://localhost:8080/day15_01_filter_war_exploded/Demo4Servlet2
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cIP1OJMu-1606226675677)(assets/image-20200508143337527.png)]
12.案例1-解决全站post中文乱码【应用】
需求
解决访问项目任何资源请求post传输中文乱码问题
实现步骤
- 准备一个表单数据提交post中文请求
- 新建一个EncodingServlet处理请求接收中文数据并控制台打印输出
- 创建一个过滤器EncodingFilter拦截所有资源解决全站post中文乱码
Form.jsp页面(素材代码)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="encoding" method="post">
<input type="text" name="name"/>
<input type="submit" value="提交"/>
</form>
</body>
</html>
EncodingServlet代码
package _10_案例_解决全站Post中文乱码;
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;
/**
* @author 黑马程序员
*/
@WebServlet(name = "EncodingServlet", urlPatterns = "/encoding")
public class EncodingServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1、获取post提交传递的中文数据
String name = request.getParameter("name");
//2、控制台打印输出
System.out.println(name);
}
}
运行form.jsp提交中文的乱码效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BQ6H2Hd2-1606226675678)(assets/image-20200508144053132.png)]
EncodingFilter代码
package _10_案例_解决全站Post中文乱码;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @author 黑马程序员
*
* 目标:拦截所有资源的请求,处理post提交中文乱码
*/
@WebFilter(filterName = "EncodingFilter",urlPatterns = "/*")
public class EncodingFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//ServletRequest 父接口,没有提供getMethod()方法
//HttpServletRequest 子接口,提供getMethod()方法
//将父接口转换为子接口
HttpServletRequest request = (HttpServletRequest) req;
//1、判断请求的类型是否是post
//获取请求方法类型
String method = request.getMethod();
//判断
if("post".equalsIgnoreCase(method)) {
//2、如果请求类型是post ,解决乱码
request.setCharacterEncoding("utf-8");
}
chain.doFilter(request, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
过滤器处理乱码后效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t1VXpkUE-1606226675679)(assets/image-20200508144844213.png)]
小结
-
过滤器如何可以拦截所有资源?
urlPatterns="/*"
13.案例2-登录权限控制1-登录功能【理解】
需求
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J2MXuhhk-1606226675681)(assets/1566384570819.png)]
如何知道是否登录?
答:登录成功后要将登录数据写入session会话对象中,session有数据就代表登录,否则代表没有登录
环境搭建
-
创建一个项目
-
导入页面素材(“资料\原型”)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RPazAqhE-1606226675682)(assets/image-20200229114512777.png)]
-
实现登录
搭建环境结构(导入选中的资源)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gFboQf5L-1606226675683)(assets/image-20200508150714245.png)]
实现分析
1、创建LoginServleet处理login.jsp进行登录请求
2、LoginServlet校验登录,登录成功将登录数据写入session,登录失败提示消息
LoginServlet代码
package com.itheima.web.servlet;
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;
/**
* @author 黑马程序员
*/
@WebServlet(name = "LoginServlet", urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* 目标:LoginServlet校验登录,登录成功将登录数据写入session,登录失败提示消息
* */
//1、获取用户名与密码
String user = request.getParameter("user");
String password = request.getParameter("password");
//2、校验登录(用户名必须为admin,密码必须为123)
if("admin".equals(user) && "123".equals(password)) {
//3、校验通过
//将登录数据写入session
request.getSession().setAttribute("loginUser",user);
//跳转到list.jsp页面
response.sendRedirect(request.getContextPath()+"/list.jsp");
}else {
//4、校验失败
//请求域存储错误消息
request.setAttribute("errorMsg","用户名或密码错误");
//跳转到login.jsp页面显示错误消息
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}
}
修改login.jsp页面显示的错误消息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-onvpRjaH-1606226675684)(assets/1566446428446.png)]
运行效果
访问地址
http://localhost:8080/day15_02_login_control_war_exploded/login.jsp
登录失败效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VIn1vjug-1606226675685)(assets/image-20191227112807525.png)]
登录成功效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LpsYraSh-1606226675686)(assets/image-20191227112825565.png)]
14.案例2-登录权限控制2-权限控制【应用】
目标
使用过滤器实现登录权限控制
-
我们的目标是admin目录下的资源必须登录以后才可以访问,那就需要在admin目录的每个资源里面都要判断是否用户登录了,如果没有登录不能访问,这样操作是否麻烦?有没有更好的操作?
使用过滤器
过滤器代码
package com.itheima.web.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author 黑马程序员
*
* 目标:拦截admin目录下所有资源,判断是否登录,登录了放行,没有登录跳转到登录页面
*/
@WebFilter(filterName = "LoginConrolFilter",urlPatterns = "/admin/*")
public class LoginConrolFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//1、将请求与响应的父接口转换为子接口(因为子接口功能强大)
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//2、判断用户是否登录
//从session中获取登录数据
String user = (String) request.getSession().getAttribute("loginUser");
//判断登录是否有效
if(user!=null) {
//3、登录了,放行
chain.doFilter(request,response);
}else {
//4、没有登录,跳转到登录页面
response.sendRedirect(request.getContextPath()+"/login.jsp");
}
}
public void init(FilterConfig config) throws ServletException {
}
}
小结
-
过滤器如何拦截浏览器访问admin目录下的所有资源?
urlPatterns="/admin/*"
-
如何知道用户是否登录了?
判断sesson中是否含有登录数据,有代表登录,没有代表没有登录
15.总结
1.能够说出过滤器的作用
拦截请求与响应
适合解决问题类型:如果某一个操作是你多资源都要进行的,可以将这个操作放入到过滤器中集中处理
2.能够编写过滤器
xml方式:
1、创建一个类实现Filter接口,重写doFilter方法
2、配置web.xml的过滤器拦截路径
注解方式:
1、使用idea提供模板创建过滤器类,重写doFilter方法
2、在注解上@WebFilter里面配置拦截路径
3.能够说出过滤器生命周期相关方法
init方法
doFilter方法
destroy方法
过滤器对象是服务器启动时创建的一个唯一对象
过滤器对象是服务器关闭前效果
4.能够根据过滤路径判断指定的过滤器是否起作用
1、完全匹配:拦截路径与访问的资源路径一模一样
2、目录匹配:拦截指定目录开头的所有资源,格式要求,以“/”开头,以“/*”结尾
3、扩展名匹配:拦截指定扩展名结尾的所有资源,格式要求:以“*”开头,以“.扩展名”结尾
5.能够说出什么是过滤器链
一个资源被多个过滤器拦截请求与响应,并进行串行执行
可以掌握过滤器执行顺序的修改:
注解方式:修改过滤器的类名,控制类名字符串比较升序
xml方式:配置顺序就是执行顺序
6.能够编写过滤器解决全局乱码
单词 | ||
---|---|---|
Filter | 过滤器 | /ˈfɪltər/ |
chain | 链 | /tʃeɪn/ |
encoding | 编码 | /ɪn’kodɪŋ/ |
dispatcher | 分配器 | /dɪˈspætʃər/ |
uest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//2、判断用户是否登录
//从session中获取登录数据
String user = (String) request.getSession().getAttribute("loginUser");
//判断登录是否有效
if(user!=null) {
//3、登录了,放行
chain.doFilter(request,response);
}else {
//4、没有登录,跳转到登录页面
response.sendRedirect(request.getContextPath()+"/login.jsp");
}
}
public void init(FilterConfig config) throws ServletException {
}
}
### 小结
* 过滤器如何拦截浏览器访问admin目录下的所有资源?
```java
urlPatterns="/admin/*"
-
如何知道用户是否登录了?
判断sesson中是否含有登录数据,有代表登录,没有代表没有登录
15.总结
1.能够说出过滤器的作用
拦截请求与响应
适合解决问题类型:如果某一个操作是你多资源都要进行的,可以将这个操作放入到过滤器中集中处理
2.能够编写过滤器
xml方式:
1、创建一个类实现Filter接口,重写doFilter方法
2、配置web.xml的过滤器拦截路径
注解方式:
1、使用idea提供模板创建过滤器类,重写doFilter方法
2、在注解上@WebFilter里面配置拦截路径
3.能够说出过滤器生命周期相关方法
init方法
doFilter方法
destroy方法
过滤器对象是服务器启动时创建的一个唯一对象
过滤器对象是服务器关闭前效果
4.能够根据过滤路径判断指定的过滤器是否起作用
1、完全匹配:拦截路径与访问的资源路径一模一样
2、目录匹配:拦截指定目录开头的所有资源,格式要求,以“/”开头,以“/*”结尾
3、扩展名匹配:拦截指定扩展名结尾的所有资源,格式要求:以“*”开头,以“.扩展名”结尾
5.能够说出什么是过滤器链
一个资源被多个过滤器拦截请求与响应,并进行串行执行
可以掌握过滤器执行顺序的修改:
注解方式:修改过滤器的类名,控制类名字符串比较升序
xml方式:配置顺序就是执行顺序
6.能够编写过滤器解决全局乱码
单词 | ||
---|---|---|
Filter | 过滤器 | /ˈfɪltər/ |
chain | 链 | /tʃeɪn/ |
encoding | 编码 | /ɪn’kodɪŋ/ |
dispatcher | 分配器 | /dɪˈspætʃər/ |