一、Filter过滤器简介
1、基本概念
-
JavaWeb的三大组件之一,三大组件为:Servlet、Filter、Listener。
-
过滤器相当于浏览器与Web资源之间的一道过滤网,在访问资源之前通过一系列的过滤器对请求 进行修改、判断以及拦截等,也可以对响应进行修改、判断以及拦截等。
2、工作方式
二、原始登录方式的实现 及 缺陷
1、代码实现
(1)编写登录界面
-
创建空工程,在工程中创建javaEE模块
-
配置中设置tomcat的部署
-
使用了jstl,所以需要添加依赖
<dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency>
-
编写login界面
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登录</title> </head> <body> <form action="loginServlet" method="post"> 用户名:<input type="text" name="userName"><br> 密码:<input type="password" name="password"><br> <span style="color:red"><%--错误提示--%> <c:if test="${requestScope.error != null}"> ${requestScope.error} </c:if> </span><br> <input type="submit" value="登录"> </form> </body> </html>
(2)编写Servlet
LoginServlet:
package com.example.login_demo01;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet(name = "LoginServlet", value = "/loginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1、获取页面传递的用户名和密码
String userName = request.getParameter("userName");
System.out.println("接收到的用户名为:" + userName);
String password = request.getParameter("password");
System.out.println("接收到的密码为:" + password);
//2、使用固定的用户名和密码进行登录校验
if ("admin".equals(userName) && "12345".equals(password)){
System.out.println("登录成功,欢迎使用!");
//在session中存储用户名
request.getSession().setAttribute("userName", userName);
response.sendRedirect("main.jsp");
}else {
System.out.println("用户名或者密码错误,请重新输入!");
request.setAttribute("error", "用户名或者密码错误,请重新输入!");
request.getRequestDispatcher("login.jsp").forward(request, response);
}
}
}
(3)编写main界面
main.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>主界面</title>
</head>
<body>
<h1><c:out value="登录成功,欢迎${sessionScope.userName}!"></c:out></h1>
</body>
</html>
(4)测试结果
2、缺陷
上述代码部署完毕后,直接访问登录界面 http://localhost:8080/login_demo01/login.jsp 并没有问题,但若更换浏览器,再直接访问主界面 http://localhost:8080/login_demo01/main.jsp ,则会直接跳转到主界面,这种状态显然不合理。如下图:
由于request中没有值,并不能显示用户名。
三、使用Filter优化登录功能的代码演示
1、自定义类实现Filter接口并重写doFilter方法
-
LoginFilter
package com.example.login_demo01; import javax.servlet.*; import javax.servlet.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.io.IOException; @WebFilter(filterName = "LoginFilter", urlPatterns = "/main.jsp") public class LoginFilter implements Filter { public void init(FilterConfig config) throws ServletException { } public void destroy() { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { /**用户访问主界面过滤,只有登录的才能访问,没登录的都拦截**/ HttpServletRequest httpServletRequest = (HttpServletRequest) request; HttpSession session = httpServletRequest.getSession(); Object userName = session.getAttribute("userName"); //获取servlet请求路径 String servletPath = httpServletRequest.getServletPath(); System.out.println(servletPath); //没登录,返回登录界面,已登录的放行 if (null == userName && !servletPath.contains("login")){ request.getRequestDispatcher("login.jsp").forward(request, response); }else { chain.doFilter(request, response); } } }
2、测试:
使用一个浏览器登录成功后,再更换另一个浏览器,则会直接跳转到登录界面。
四、多过滤器的使用
1、过滤执行图
2、多过滤器的过滤顺序:
- web.xml 注册方式,是按照映射(即filter-mapping)的顺序;
- 注解方式注册,是按照过滤器类的字母顺序执行的。
3、代码演示(只演示注解方式)
-
添加一个模块,并配置tomcat
-
注解添加两个过滤器
-
AFilter
package com.example.filterchain_demo02; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter(filterName = "AFilter", urlPatterns = "/") public class AFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { Filter.super.init(filterConfig); System.out.println(filterConfig.getFilterName() + "初始化了~"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("请求经过了AFilter..."); filterChain.doFilter(servletRequest, servletResponse); System.out.println("响应经过了AFilter..."); } @Override public void destroy() { Filter.super.destroy(); System.out.println("AFilter 销毁了..."); } }
-
BFilter
package com.example.filterchain_demo02; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter(filterName = "BFilter", urlPatterns = "/") public class BFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { Filter.super.init(filterConfig); System.out.println(filterConfig.getFilterName() + "初始化了~"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("请求经过了BFilter..."); filterChain.doFilter(servletRequest, servletResponse); System.out.println("响应经过了BFilter..."); } @Override public void destroy() { Filter.super.destroy(); System.out.println("BFilter 销毁了..."); } }
-