文章目录
Filter:过滤器
1. 创建Filter
创建一个Java类去实现Filter接口
Filter是Java中预先定义好了的接口,可以过滤不同的内容,具体怎么过滤,需要使用者定义一个实现类,然后实现接口中的过滤方法,在方法中书写过滤的条件。filter是对客户端访问资源的过滤,符合条件放行,不符合条件不放行。
@WebFilter("/demo1") 过滤的路径
public class Demo1Filter implements Filter{
//重写init 、doFilter、destroy方法
@Override
//初始化方法
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Demo1Filter的init方法执行了");
}
@Override
//doFilter相当于Servlet中的service
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("Demo1Filter的doFilter方法执行了");
}
@Override
//销毁方法
public void destroy() {
System.out.println("Demo1Filter的destroy方法执行了");
}
}
Servlet:一个java类去实现Servlet接口,(不推荐这种方式。可以继承抽象类HTTPServlet)
Servlet笔记:(发展历程,生命周期,tomcat匹配url)
2. 过滤器的用途
- 登录的判断 当你访问网站时,判断你是否进行登录了
- 权限的判断:判断用户的权限
- 解决全局post中文乱码问题
3. 生命周期:
1. Servlet
创建:第一次访问该Servlet(单例),执行init
执行:每次访问都会执行service
销毁:服务器关闭时执行destroy
2. Request/Response
创建:请求过来时创建request、response
销毁:对该请求产生响应结束后销毁
3. Session
创建:会话开启,第一次调用request.getSession()
销毁:
1、手动调用invalidate()
2、服务器非正常关闭时
3、不操作默认30分钟
4. ServletContext
创建:服务器启动时
销毁:服务器关闭时
5. Filter
创建: 服务器启动时创建,执行的是init方法
执行:访问的路径能匹配上@WebFilter(url)
,执行doFilter
销毁:服务器关闭时销毁,执行的是destroy方法
注意:修改Servlet代码或Filter代码后,会重新加载环境。同时会销毁Filter并重新初始化。
4. Filter的执行流程(单个过滤器)
1.根据映射路径匹配到相应的过滤器。
2.执行过滤器的doFilter,进行处理。
3.放行后去匹配请求的资源,没有放行就会被拦截,不请求相应的资源。
4.请求资源结束后,返回过滤器的doFIlter方法,继续执行过滤器内容。
5. Filter的执行流程(过滤器链,即多个过滤器)
过滤器链:多个过滤器组成的一个整体我们称为过滤器链
我们java代码中,有时需要对同一个请求,进行多次不同业务的过滤,所以我们java代码中需要多个过滤器。只有所有的过滤器都对请求进行了放行,请求才能访问到目标资源,只要多个过滤器中有一个过滤器不放行,那么这个请求都不能够访问到目标资源。 而且,过滤器链中的过滤器是一个一个的执行的,一个过滤器执行完毕之后,会执行下一个过滤器,后面没有过滤器了,才会访问到目标资源。只要其中一个过滤器没有放行,那么这个过滤器后面的过滤器也都不会执行了。
写三个过滤器,只有名字,和输出内容不同。和一个Servlet
Filter
@WebFilter("/target/*")
public class Demo1Filter implements Filter{
init destroy 省略
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("demo1Filter 执行:放行前");
chain.doFilter(request, response);
System.out.println("demo1Filter 执行:放行后");
}
}
Servlet
@WebServlet("/target/demo1")
public class Target1Servlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("目标资源执行了。。。");
resp.getWriter().append("<h1>Target1Servlet.java</h1>");
}
}
请求该Servlet,结果如下
6.过滤器执行细节:
6.1 映射路径
Filter匹配:@WebFilter("url")
或 web.xml中的配置文件
-
精确匹配模式:全路径精确匹配
-
模糊匹配模式:
目录匹配:/admin/*
比如:访问后台管理页面
扩展名匹配:*.action
或者*.do
springmvc时
匹配所有:/*
解决请求响应乱码
Servlet匹配:@WebServlet("url")
或 web.xml中的配置文件
精确匹配 > 目录匹配 > 匹配所有/*
> 扩展名匹配 > 匹配所有/
servlet 笔记里有详细的,
https://blog.youkuaiyun.com/BigDevil_/article/details/103927442
6.2 Filter拦截方式
默认 只拦截客户端路径(从浏览器直接访问或者重定向)
重定向也相当于从浏览器直接访问,是响应一个304状态码跟url地址,浏览器重新访问给定url
设置拦截方式
- 设置为只拦截客户端路径(浏览器直接请求)request
@WebFilter(“url” ,dispatcherTypes = DispatcherType.REQUEST)
(只拦截客户端路径 (默认)) - 设置为只拦截请求转发,forward
@WebFilter(“url” ,dispatcherTypes = DispatcherType.FORWARD)
(只拦截请求转发) - 拦截 请求转发+客户端路径
@WebFilter(“url” ,dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD})
@WebFilter(value="/admin/*",dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD})
public class Demo1Filter implements Filter{
...
}
6.3 过滤器链的执行顺序
-
web module_version 3.0: 用注解方式匹配URL
和类名的字符大小有关系(越小的越先执行,从第一个字母开始比较,如果第一个字母相同,再比较第二个字母的大小,以此类推)。(理解:根据字母排序,自然排序。) -
web module_version 2.5:用web.xml配置filter,匹配url-pattern
和web.xml中的配置顺序有关(和类名无关),越靠前的越小执行
案例1:过滤非法字符
form.jsp
<form action="/day18/target" method="get">
请发表你的言论:<input type="text" name="word"><br>
<input type="submit" value = "发表">
</form>
IllegalFilter:
@WebFilter("/target")
public class IllegalFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//获取发表的内容
String word = request.getParameter("word");
//判断里面是否含有非法字符
for(String str :list) {
if(word.contains(str)) {
//含有非法字符
response.getWriter().write("您发表的言论含有非法字符,请检查后重新发表");
return;
}
}
//不含有 放行
chain.doFilter(request, response);
}
/**
* @see Filter#init(FilterConfig)
*/
List<String> list = new ArrayList();
public void init(FilterConfig fConfig) throws ServletException {
try {
//读取illegal.txt中的非法字符
String path = fConfig.getServletContext().getRealPath("");
path = path + "/illegal.txt";
BufferedReader br = new BufferedReader(new FileReader(path));
String str = null;
while((str = br.readLine()) != null) {
list.add(str);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
TargetServlet:
@WebServlet("/target")
public class TargetServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取发表的言论
String word = request.getParameter("word");
response.getWriter().write("发表成功啦!!内容是::"+word);
}
案例2:解决全站乱码
@WebFilter("/*")
public class EncodingFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//解决请求乱码
request.setCharacterEncoding("utf-8");
//解决响应乱码
response.setContentType("text/html;charset=utf-8");
chain.doFilter(request, response);
}