1. Filter 过滤器
1 过滤器简介
-
Filter过滤器是JavaWeb的三大组件(Servlet程序、Listener监听器、Filter过滤器)之一
-
Filter作用:拦截请求、过滤响应
-
是javaee的规范也是接口
-
拦截请求常见的应用有
- 权限检查
- 日记操作
- 事务管理
2 Filter 生命周期
Filter的生命周期包含几个方法
- 构造器方法
- init初始化方法
- doFilter过滤方法,每次拦截到请求,就会执行
- destory销毁
构造器方法和初始化方法都在web工程启动时执行,停止web工程的时候,只执行销毁方法,销毁Filter过滤器
从Java Servlet 3.0 规范开始,为了简化开发,Filter
接口引入了默认方法(default methods),其中包括了默认的init
和destroy
方法的实现。这意味着,你可以只实现doFilter
方法来编写自定义的过滤逻辑,而不需要显式地实现init
和destroy
方法。
3 拦截路径
在web.xml中配置
<filter>
<filter-name>connectionFilter</filter-name>
<filter-class>filter.ConnectionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>connectionFilter</filter-name>
<url-pattern>/user/*</url-pattern>
</filter-mapping>
- 精确匹配
<url-pattern>/target.jsp</url-pattern>
以上配置的路径,表示请求地址必须为 http://ip:port/工程路径/target.jsp
- 目录匹配
<url-pattern>/admin/*</url-pattern>
以上配置的路径, 表示请求地址必须为: http://ip:port/工程路径/admin/*
- 后缀匹配
<url-pattern>*.html</url-pattern>
以上配置的路径, 表示请求地址必须以.html 结尾才会拦截到
<url-pattern>*.do</url-pattern>
以上配置的路径, 表示请求地址必须以.do 结尾才会拦截到
<url-pattern>*.action</url-pattern>
以上配置的路径, 表示请求地址必须以.action 结尾才会拦截到
Filter过滤器只会关心请求的地址是否匹配,不关心资源是否存在
4 FilterConfig类
是Filter的配置文件类
Tomcat 每次创建 Filter 的时候, 也会同时创建一个 FilterConfig 类, 这里包含了 Filter 配置文件的配置信息。FilterConfig 类的作用是获取 filter 过滤器的配置内容
-
获取 Filter 的名称 filter-name 的内容
-
获取在 Filter 中配置的 init-param 初始化参数
-
获取 ServletContext 对象
web.xml
<!--filter 标签用于配置一个 Filter 过滤器-->
<filter>
<!--给 filter 起一个别名-->
<filter-name>AdminFilter</filter-name>
<!--配置 filter 的全类名--> <filterclass>com.lxs.filter.AdminFilter</filter-class>
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost3306/test</param-value>
</init-param>
</filter>
java
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("2.Filter 的 init(FilterConfig filterConfig)初始化");
// 1、 获取 Filter 的名称 filter-name 的内容
System.out.println("filter-name 的值是: " +
filterConfig.getFilterName());
// 2、 获取在 web.xml 中配置的 init-param 初始化参数
System.out.println("初始化参数 username 的值是: " +
filterConfig.getInitParameter("username"));
System.out.println("初始化参数 url 的值是: " +
filterConfig.getInitParameter("url"));
// 3、 获取 ServletContext 对象
System.out.println(filterConfig.getServletContext());
}
5 Filter Chain过滤器链
工作流程图
过滤器链
-
多个过滤器执行的特点:
- 所有filter和目标资源默认都执行在同一个线程中
- 多个filter共同执行时,都使用同一个request对象
-
FilterChain.doFilter()方法的作用:
- 执行下一个Filter(有Filter)
- 执行目标资源(没有Filter)
在多个Filter过滤器执行的时候,执行的优先顺序是由在web.xml中从上到下的顺序决定的
Filter1
public class Filter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
System.out.println("filter1 初始化方法");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException,ServletException {
System.out.println("filter1 前置 过滤方法 ");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("filter1 后置 过滤方法 ");
}
@Override
public void destroy() {
Filter.super.destroy();
System.out.println("销毁方法1");
}
}
Filter2
public class Filter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
System.out.println("filter2 初始化方法");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException,ServletException {
System.out.println("filter2 前置 过滤方法 ");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("filter2 后置 过滤方法 ");
}
@Override
public void destroy() {
Filter.super.destroy();
System.out.println("销毁方法2");
}
}
web.xml
<filter>
<filter-name>filter1</filter-name>
<filter-class>com.lxs.demo.filter.Filter1</filter-class>
</filter>
<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>filter2</filter-name>
<filter-class>com.lxs.demo.filter.Filter2</filter-class>
</filter>
<filter-mapping>
<filter-name>filter2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
6 Filter登录校验
要求:让在web工程下的所有资源在登录后才能被访问
注:WEB-INF目录下的文件不能被直接访问,只能通过转发访问
Filter过滤器使用步骤
- 编写一个类去实现啊Filter接口
- 实现过滤方法doFilter()
- 到web.xml中去配置filter的拦截路径
Filter
public class AdminFilter implements Filter {
/**
* doFilter 方法, 专门用于拦截请求。 可以做权限检查
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
HttpSession session = httpServletRequest.getSession();
Object user = session.getAttribute("user");
// 如果等于 null, 说明还没有登录
if (user == null) {
servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
return;
} else {
// 让程序继续往下访问用户的目标资源
filterChain.doFilter(servletRequest,servletResponse);
}
}
}
web.xml
<!--filter 标签用于配置一个 Filter 过滤器-->
<filter>
<!--给 filter 起一个别名-->
<filter-name>AdminFilter</filter-name>
<!--配置 filter 的全类名-->
<filter-class>com.lxs.filter.AdminFilter</filter-class>
</filter><!--filter-mapping 配置 Filter 过滤器的拦截路径-->
<filter-mapping>
<!--filter-name 表示当前的拦截路径给哪个 filter 使用-->
<filter-name>AdminFilter</filter-name>
<!--url-pattern 配置拦截路径
/ 表示请求地址为: http://ip:port/工程路径/ 映射到 IDEA 的 web 目录
/admin/* 表示请求地址为: http://ip:port/工程路径/admin/*
-->
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
login.jsp 登录表单
这是登录页面。 login.jsp 页面 <br>
<form action="http://localhost:8080/15_filter/loginServlet" method="get">
用户名: <input type="text" name="username"/> <br>
密 码: <input type="password" name="password"/> <br>
<input type="submit" />
</form>
LoginServlet
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=UTF-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
if ("wzg168".equals(username) && "123456".equals(password)) {
req.getSession().setAttribute("user", username);
resp.getWriter().write("登录 成功! ! ! ");
} else {
req.getRequestDispatcher("/login.jsp").forward(req, resp);
}
}
}
7 HttpServletRequestWrapper
HttpServletRequestWrapper是Servlet中的一个包装器类,用于对原始的HttpServletRequest对象进行包装和增强。它继承自ServletRequestWrapper类,并实现了HttpServletRequest接口。
通过使用HttpServletRequestWrapper,可以在HttpServletRequest对象的基础上添加自定义的功能或修改请求的参数、头部信息等内容,同时也能保持对原始HttpServletRequest方法的支持。
HttpServletRequestWrapper的使用通常包括以下几个步骤:
-
创建一个自定义的HttpServletRequestWrapper类,该类需要继承HttpServletRequestWrapper,并实现HttpServletRequest接口的所有抽象方法。
-
在自定义HttpServletRequestWrapper类中重写需要增强或修改的方法。例如,可以重写getParameter()方法来修改请求参数的值,或重写getHeader()方法来添加额外的头部信息。
-
在自定义HttpServletRequestWrapper类的构造函数中调用父类的构造函数,将原始的HttpServletRequest对象传递进去。
-
在Servlet中使用自定义的HttpServletRequestWrapper类来处理请求。可以通过在Servlet中获取到的HttpServletRequest对象创建自定义的HttpServletRequestWrapper对象,然后将其传递给其他的方法进行处理。
通过HttpServletRequestWrapper,我们可以在不修改原始ServletRequest对象的情况下,对请求进行定制化的处理,实现自定义需求。例如,可以用于实现请求参数的过滤、修改请求头、添加额外的请求验证等操作。
实现敏感词过滤
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class SensitiveWordFilterWrapper extends HttpServletRequestWrapper {
public SensitiveWordFilterWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
if (value != null) {
// 进行敏感词过滤处理
value = sensitiveWordFilter(value);
}
return value;
}
private String sensitiveWordFilter(String value) {
// 在这里编写敏感词过滤的逻辑,可以使用正则表达式或其他算法进行匹配和替换操作
// 示例代码只是简单替换了一些敏感词为*
value = value.replaceAll("敏感词1", "*");
value = value.replaceAll("敏感词2", "*");
/* // 对获取到的参数进行处理或修改
if (name.equals("key")) {
if ("敏感词".equals(value)) {
return "XXX(和谐)";
}
}*/
// ...
return value;
}
}
在上面的示例中,我们创建了一个名为SensitiveWordFilterWrapper的类,继承自HttpServletRequestWrapper,并重写了其中的getParameter()方法。在重写的方法中,首先调用父类的getParameter()方法获取原始的请求参数值,然后对该值进行敏感词过滤处理,最后返回处理后的值。
敏感词过滤的具体实现逻辑可以根据需求来定制,可以使用正则表达式、Trie树等算法来匹配和替换敏感词。上述示例代码只是一个简单的示例,将敏感词替换为了*,实际情况中可能需要更复杂的处理逻辑。
在使用该包装器类时,需要在Servlet中将原始的HttpServletRequest对象替换为自定义的SensitiveWordFilterWrapper对象,示例如下:
public class MyServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpServletRequest wrappedRequest = new SensitiveWordFilterWrapper(req);
// 使用包装后的请求对象进行处理
// ...
}
}
2. Listener 监听器
1 什么是监听器
监听器就是监听某个域对象的的状态变化的组件
监听器的相关概念:
-
事件源:被监听的对象(三个域对象 request、session、servletContext)
-
监听器:监听事件源对象事件源对象的状态的变化都会触发监听器
-
注册监听器:将监听器与事件源进行绑定
-
响应行为:监听器监听到事件源的状态变化时所涉及的功能代码(程序员编写代码)
2 监听器分类
第一维度是按被监听的对象划分:ServletRequest域,HttpSession域,ServletContext域
第二维度按照监听的内容分:监听域对象的创建与销毁的,监听域对象的属性变化的
public class MyListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent){
System.out.println("contextInitialized");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("contextDestroyed");
}
}
web.xml
<listener>
<listener-class>com.filter.MyListener</listener-class>
</listener>