概念
- 生活中的过滤器:净水器,空气净化器,土匪、
- web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。
过滤器的作用
- 一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤…
步骤
- 定义一个类,实现接口Filter
- 复写方法
- 配置拦截路径
- web.xml
- 注解
生命周期
-
init
:在服务器启动后,会创建Filter对象,然后调用init
方法。只执行一次。用于加载资源 -
doFilter
:每一次请求被拦截资源时,会执行。执行多次 -
destroy
:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源
代码:
package cn.luis.web.filter;
import javax.servlet.*;
import java.io.IOException;
/*@WebFilter("/*")*/
public class FilterDemo3 implements Filter {
/**
* 每一次请求被拦截资源时,会执行。执行多次
* @param req
* @param resp
* @param chain
* @throws ServletException
* @throws IOException
*/
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("doFilter....");
chain.doFilter(req, resp);
}
/**
* 在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
* @param config
* @throws ServletException
*/
public void init(FilterConfig config) throws ServletException {
System.out.println("init....");
}
/**
* 在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源
*/
public void destroy() {
System.out.println("destroy....");
}
}
拦截路径配置
注解配置
1. 具体资源路径:/index.jsp
【只有访问index.jsp
资源时,过滤器才会被执行】
@WebFilter("/index.jsp")
2. 拦截目录:/user/*
【/user是url
地址】
@WebFilter(" /user/*")
访问/user下的所有资源时,过滤器都会被执行
如:
http://localhost:8080/13_Filter_Listener/user/findAllServlet
3. 后缀名拦截: *.jsp
【访问所有后缀名为jsp
资源时,过滤器都会被执行】
@WebFilter("*.jsp")
4. 拦截所有资源:/*
【访问所有资源时,过滤器都会被执行】
@WebFilter("/*")
web.xml配置
<filter>
<filter-name>demo1</filter-name>
<filter-class>cn.luis.web.filter.FilterDemo1</filter-class>
</filter>
<filter-mapping>
<filter-name>demo1</filter-name>
<!--拦截路径配置-->
<url-pattern>/*</url-pattern>
<!--拦截方式配置-->
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
拦截方式配置
资源被访问的方式
注解配置
设置dispatcherTypes
属性
- REQUEST:默认值。浏览器直接请求资源
- FORWARD:转发访问资源
- INCLUDE:包含访问资源
- ERROR:错误跳转资源
- ASYNC:异步访问资源
代码:
- 浏览器直接请求
index.jsp
资源时,该过滤器会被执行
@WebFilter(value="/index.jsp",dispatcherTypes = DispatcherType.REQUEST)
- 只有转发访问
index.jsp
时,该过滤器才会被执行
@WebFilter(value="/index.jsp",dispatcherTypes = DispatcherType.FORWARD)
- 浏览器直接请求
index.jsp
或者转发访问index.jsp
。该过滤器才会被执行
@WebFilter(value="/*",dispatcherTypes ={DispatcherType.FORWARD,
DispatcherType.REQUEST})
访问
http://localhost:8080/13_Filter_Listener/user/updateServlet
时会执行两次过滤器
web.xml配置
设置<dispatcher></dispatcher>
标签即可
代码见上面!‘
执行流程
- 执行过滤器
- 执行放行后的资源
- 回来执行过滤器放行代码下边的代码
过滤器链
配置多个过滤器
执行顺序:如果有两个过滤器
- 过滤器1
- 过滤器2
- 资源执行
- 过滤器2
- 过滤器1
过滤器先后顺序问题
注解配置
按照类名的字符串比较规则比较,值小的先执行
- 如:
AFilter
和BFilter
,AFilte
r就先执行了。
web.xml配置
<filter-mapping>
谁定义在上边,谁先执行
增强对象的功能
设计模式:一些通用的解决固定问题的方式
- 装饰模式
- 代理模式
代理模式
概念
- 真实对象:被代理的对象
- 代理对象:
- 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的
实现方式
- 静态代理:有一个类文件描述代理模式
- 动态代理:在内存中形成代理类
动态代理实现步骤
- 代理对象和真实对象实现相同的接口
- 代理对象 :
Proxy.newProxyInstance();
- 使用代理对象调用方法。
- 增强方法
方法的增强方式
- 增强参数列表
- 增强返回值类型
- 增强方法体执行逻辑
代码:
真实类
package cn.luis.web.proxy;
/**
* @ClassName Lenovo
* @Description 真实类
* @Author L
* @Date 2020.02.16 11:22
* @Version 1.0
* @Remark TODO
**/
public class Lenovo implements SaleComputer {
@Override
public String sale(double money) {
System.out.println("花了"+ money +"买了台联想电脑...");
return "联想电脑";
}
@Override
public void show() {
System.out.println("展示电脑...");
}
}
接口
package cn.luis.web.proxy;
public interface SaleComputer {
public String sale(double money);
public void show();
}
代理对象
package cn.luis.web.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @ClassName ProxyTest
* @Description TODO
* @Author L
* @Date 2020.02.16 11:25
* @Version 1.0
* @Remark TODO
**/
public class ProxyTest {
public static void main(String[] args) {
// 创建真实对象
Lenovo lenovo = new Lenovo();
/*
三个参数:
1. 类加载器:真实对象.getClass().getClassLoader()
2. 接口数组:真实对象.getClass().getInterfaces()
3. 处理器:new InvocationHandler()
*/
// 动态代理增强Lenovo对象
SaleComputer proxyLenovo = (SaleComputer) Proxy.newProxyInstance(
lenovo.getClass().getClassLoader(),
lenovo.getClass().getInterfaces(),
new InvocationHandler() {
/*
代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法执行
参数:
1. proxy:代理对象
2. method:代理对象调用的方法,被封装为的对象
3. args:代理对象调用的方法时,传递的实际参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/*System.out.println(method.getName());
System.out.println(args[0]);*/
// 判断是否为sale方法
if(method.getName().equals("sale")) {
// 1.增强参数
double money = (double) args[0];
money = money * 0.85;
// 使用真实对象调用该方法
String obj = (String) method.invoke(lenovo,money);
// 2.增强方法体
System.out.println("免费送货...");
// 3.增强返回值
return obj + " + 键鼠套装";
} else {
Object obj = method.invoke(lenovo, args);
return obj;
}
}
});
// 调用方法1
/*String computer = proxyLenovo.sale(8888);
System.out.println(computer);*/
// 调用方法2
proxyLenovo.show();
}
}
结果:
// 调用方法1
花了7554.8买了台联想电脑...
免费送货...
联想电脑 + 键鼠套装
// 调用方法2
展示电脑...