目录
Filter:过滤器
生活中:净水器、空气净化器、核酸检测
来回都得拦截————————来回都得拦截
web中:当客户端访问服务器时,拦截下来请求完成特殊功能
作用:
拦截请求,增强请求、完成通用的操作,当需要获取的资源都需要检测时 (如登录验证、特殊字符敏感字符的操作、统一编码处理)
入门学习:
import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; //访问所有资源执行过滤器 @WebFilter("/*") public class Filter01 implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //放行资源 没设置不放行 filterChain.doFilter(servletRequest,servletResponse); } public void destroy() { } }
没有注解
没有Filter接口时
AIL+Enter 查找依赖 自动添加依赖。刷新maven
细节:
xml配置和注解配置的区别
过滤器的执行流程
过滤器的生命周期方法
过滤器配置详解
过滤器链——一个过滤器接一个过滤器。
XML配置路径————
去掉注解、设置过滤器名字、映射引用到什么路径
过滤器的执行流程————
::执行过滤器,执行放行后的资源(既 doFilter方法),再回来执行放行后面的方法
过滤器的生命周期:————
import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; //访问所有资源执行过滤器 @WebFilter("/*") public class Filter01 implements Filter { /** * 服务器启动时,会创建Filter对象,自动执行一次,也只执行一次 * 作用:执行加载资源 * @param filterConfig * @throws ServletException */ public void init(FilterConfig filterConfig) throws ServletException { } /** * 每次请求被拦截时 执行多次 * @param servletRequest * @param servletResponse * @param filterChain * @throws IOException * @throws ServletException */ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //一般在这里对请求做增强 System.out.println("请求进来了"); //放行资源 没设置不放行 filterChain.doFilter(servletRequest,servletResponse); //到这里会输出页面的内容 //在这里做响应的增强 System.out.println("请求出去了...."); } /** * 服务器正常关闭时 执行一次 * 作用:释放资源 */ public void destroy() { } }
过滤器配置————
路径配置:
1、具体路径:/index.html
2、目录拦截:/user/* 要在servlet配置路径(controller同理)下面图
3、后缀名拦截:.jpg
4、所有资源:*
方式配置:方式指的是 资源被访问的方式。
String[] urlPatterns() default {};//配置路径
//配置请求方式
//属性
//REQUEST:默认值
//FORWARD:转发访问资源
//INCLUDE:包含访问资源
//ERROR:错误跳转资源
//ASYNC:异步访问这个属性是个数组:相当于可以配置多种配置方式。
注解的源码:
package javax.servlet.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.servlet.DispatcherType; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface WebFilter { String description() default ""; String displayName() default ""; WebInitParam[] initParams() default {}; String filterName() default ""; String smallIcon() default ""; String largeIcon() default ""; String[] servletNames() default {}; String[] value() default {};//配置路径 String[] urlPatterns() default {};//配置路径 //配置请求方式 //属性 //REQUEST:默认值 //FORWARD:转发访问资源 //INCLUDE:包含访问资源 //ERROR:错误跳转资源 //ASYNC:异步访问 DispatcherType[] dispatcherTypes() default {DispatcherType.REQUEST}; boolean asyncSupported() default false; }
一个设置转发的类...
过滤器......
xml的配置
过滤器链:
执行顺序
domain方法....
先后顺序:
注解配置的过滤器:根据人过滤器的类名字母数字顺序比较
xml配置:谁在前面谁先执行。
案例:
登录验证(权限控制——后期有权限控制框架)
过滤铭感词汇
分析步骤:
代码实现:、
import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import java.io.IOException; @WebFilter("/*") public class Filter01 implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //1、强转ServletRequest为HttpRequest 只有HttpRequest对象由得到请求路径的方法 HttpServletRequest request= (HttpServletRequest) servletRequest; //2、得到路径判断路径包不包含是不是登录页面的请求 String requestURI = request.getRequestURI(); //要判断请求的所有资源 做放行css js 验证码动态资源 图片等 if (requestURI.contains("/login.html") ||requestURI.contains("/login.servlet") ||requestURI.contains("/css/") ||requestURI.contains("/js/") ||requestURI.contains("/loginServlet") ||requestURI.contains("/.jpg")){ //想登录、放行去登录页面 filterChain.doFilter(servletRequest,servletResponse); }else { //不是登录页面、判断是否登录 String user = (String) request.getSession().getAttribute("user"); if (user!=null){ //用户名要去数据库找,这里写死 filterChain.doFilter(servletRequest,servletResponse); }else { //没有登录、跳转页面 request.setAttribute("login_msg","没有登录!!!请登录"); request.getRequestDispatcher("/login.html").forward(servletRequest,servletResponse); } } //放行资源 没设置不放行 filterChain.doFilter(servletRequest,servletResponse); //到这里会输出页面的内容 //在这里做响应的增强 System.out.println("请求出去了...."); } public void destroy() { } }
案例二————————————————————————————————————
这里为什么用动态代理,当出现更多的敏感词汇,直接更改配置文件即可。
动态代理增强
增强对象的功能。。 SpringAOP
设计模式:23中设计模式
代理模式和装饰着模式可以实现。
代理模式参考 我的Spring AOP
接口(代理和真实对象的公共行为) public interface shop { public String sale(double dollar); }
真实对象 public class Lenovo implements shop { public String sale(double dollar) { System.out.println("联想电脑卖"+dollar+"元"); return "我是真实对象那个的返回值"; } }
使用者 使用代理对象 import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /* 用户对象使用动态代理是生成代理类 */ public class user { public static void main(String[] args) { final Lenovo lenovo=new Lenovo(); /** * 三个参数 * 代理的真实对象、代理对象实现的接口、真实对象要执行方法时要经过的接口(固定写法,只需要处理invoke方法的逻辑) * 生成的是object,需要强转为 接口类型 * invoke方法(被代理对象:真实对象、方法、方法的参数) */ shop shopComputer = (shop) Proxy.newProxyInstance(Lenovo.class.getClassLoader(), Lenovo.class.getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("代理对象的方法被调用了"); //判断是不是规定需要增强的方法 if (method.getName().equals("sale")) { //1、增强参数 double money = Double.parseDouble(args[0].toString()); money = money + 100; //真实对象调用方法,利用的是反射中的方法对象那个的invoke 和上面的invoke区别开来 System.out.println("开始增强方法体"); String invoke = (String) method.invoke(lenovo, money); System.out.println(invoke); System.out.println("已经增强方法体"); //2、增强返回值 //invoke变量是真实返回值 return invoke + "成功增强方法返回值"; //3、增强方法体在method.invoke方法执行前后 加入方法体。 }else { return "不是增强的方法执行了"; } } }); //这里调用的代理对象的sale方法,但是在实际执行在invoke里面。 String ni=shopComputer.sale(123); System.out.println(ni); } } —————————————————————————————————————————————————————————————————————————— 输出 代理对象的方法被调用了 开始增强方法体 联想电脑卖223.0元 我是真实对象那个的返回值 已经增强方法体 我是真实对象那个的返回值成功增强方法返回值
分析,
增强request的获取参数的方法
放行,传递代理对象
过滤器:::::::: import javax.jws.Oneway; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import java.io.*; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.List; @WebFilter("/*") public class Filter01 implements Filter { //加载文件 开启时执行一次 private List<String> list=new ArrayList<String>(); public void init(FilterConfig filterConfig) throws ServletException { try { //加载文件的上下文 ServletContext servletContext = filterConfig.getServletContext(); //获取文件的路径 String nihao=servletContext.getRealPath("/nihao.text"); //读取 BufferedReader bf=new BufferedReader(new FileReader(nihao)); String n=null; if (n.equals(bf.readLine())){ list.add(n); } bf.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //1、创建代理对象 Object getParameter = Proxy.newProxyInstance( servletRequest.getClass().getClassLoader(), servletRequest.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //2、判断是否是需要增强的方法 if (method.getName().equals("getParameter")) { //反射控制 执行方法的返回值 String value= (String) method.invoke(servletRequest, args); if (value!=null){ for (String ss:list) { if (value.contains(ss)){ value=value.replaceAll(ss,"***"); } } } //再执行getParameter者个方法时,得到的就是这个返回值 return value; } return method.invoke(servletRequest, args); } }); } public void destroy() { } }
servlet接口
![]()
![]()
注意点,这个项目需要部署在tomcat上
文件位置要写好
判断时逻辑要清楚
servletContext 去了解好。
判断getParameterMap
判断getParameterValue
listener:监听器:
伴随某个事件的创建而存在
事件的监听机制:
事件:创建了servletContext对象
事件源:tomcat
监听器:我们自己创建的类
注册监听:xml /注解
XML配置:
下面配置时将某个类作为监听器
监听器时伴随servletContext对象的创建二创建............重要
初始化执行方法一般用来加载文件
自己定义的监听器 import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import java.io.FileInputStream; import java.io.FileNotFoundException; public class ContextLoadListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent servletContextEvent) { //获取ServletContext对象 代表整个项目负责和服务器交互通信 ServletContext servletContext = servletContextEvent.getServletContext(); //配置加载的映射xml, String str=servletContext.getInitParameter("contextConfigLocation"); //3. 获取资源文件在服务器的地址 String s=servletContext.getRealPath(str); //加载资源文件 try { FileInputStream fis=new FileInputStream(s); System.out.println(fis); fis.close(); } catch (Exception e) { e.printStackTrace(); } } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { System.out.println("监听器被销毁了"); } }