前言
过滤器Filter是JavaWeb三大组件之一,它与Servlet很相似,过滤器是用来拦截请求的,而不是处理请求的。当用户请求某个Servlet时,会先执行部署在这个请求上的Filter,如果Filter“放行”,那么会继承执行用户请求的Servlet;如果Filter“不放行”,那么就不会执行用户请求的Servlet。可以这样理解,当用户请求某个Servlet时,Tomcat会去执行注册在这个请求上的Filter,然后是否“放行”由Filter来决定。可以理解为,Filter来决定是否调用Servlet!当执行完成Servlet的代码后,还会执行Filter后面的代码。
设计模式不是技术,也不是什么框架,只是前人的一个工作的总结,在实现某一个功能的时候,怎样来减少代码之间的耦合性,以及如何实现高内聚低耦合,设计模式说白了就是按照一定的步骤来完成相应的一个功能,这个就称为设计模式。代理Proxy是指给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。通俗来讲,代理设计模式就是我们生活中常见的中介。主要用来解决的问题第一个:监控目录一个类里面的方法的执行,第二个:在类里面某一个方法执行的前后动态的植入代码。
本文将带大家详细介绍Filter以及Proxy的具体原理以及使用。
1、什么是过滤器
「定义:」
- 过滤器按照我们的理解就是过滤东西的,那么到底这个过滤器能够来过滤啥呢?过滤的是请求
- 请求:动态资源的请求(Servlet)就是程序在运行的过程中,代码会发生改变,那么这一类的资源请求,就称为动态的网络资源请求
- 请求:静态资源的请求(css、html、js、img、png...)程序在运行的过程中,代码不会发生改变的那一类请求,就称为静态的网络资源请求
- 总结:过滤器能够拦截所有的资源请求
2、过滤器的作用
「主要用途:」
- 用户的身份认证
- 字符串的和谐
- 请求的Servlet的乱码问题处理
3、过滤器的使用
「使用案例:」
编写一个类,这个类实现于Filter接口,并实现里面的方法
- public class HelloFilter implements Filter{
-
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- System.out.println("init初始化执行了");
- }
-
- @Override
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
- System.out.println("doFilter执行了....");
- //执行了这个方法那么就表示允许通过 没有执行那么就不允许通过
- chain.doFilter(request, response);
-
- }
-
-
- @Override
- public void destroy() {
-
- System.out.println("destory执行了....");
- }
- }
在web.xml中配置Filter
-
name >HelloFiltername> -
com.qy.filter.HelloFilter -
-
-
name >HelloFiltername> -
- @Override
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- System.out.println("执行前添加的功能....");
- Object result=method.invoke(new UserDAO(), args);
- System.out.println("执行后添加的功能....");
- return result;
- }
- });
测试
- userDAO.save();
「cglib代理:」
- 需求:假设一个类没实现接口?假设我们也需要监听这个类里面的方法的执行呢?
- cglib的使用场景:就是一个类如果没有实现接口 而且我们想在这个类的方法里面动态植入代码 那么这种情况下就可以使用cglib代理
- 首先导入cglib的包
- 编写代理类
- public class UserDAOProxy {
- private UserDAO userDAO=null;
- public UserDAOProxy(UserDAO userDAO) {
- this.userDAO=userDAO;
- }
-
-
- public Object getObjProxy(){
- //这个对象就是用来返回代理类对象的方法
- Enhancer enhancer=new Enhancer();
- //给代理了设置父亲
- enhancer.setSuperclass(userDAO.getClass());
- //设置调用的回调
- enhancer.setCallback(new MethodInterceptor() {
- @Override
- public Object intercept(Object proxy, Method method, Object[] arg2,
- MethodProxy arg3) throws Throwable {
- System.out.println("植入了功能....");
- Object objResult=method.invoke(userDAO, arg2);
- System.out.println("植入了功能....1111");
- return objResult;
- }
- });
- //生成代理类
- return enhancer.create();
- }
- }
编写测试类
- @Test
- public void testCglibProxy() throws Exception {
-
- //获取代理类的对象
- UserDAOProxy2 userDAOProxy=new UserDAOProxy2(new UserDAO());
- //第二步:调用
- UserDAO userDAO=(UserDAO) userDAOProxy.getObjProxy();
- //第三步
- userDAO.save();
- }
6、基于代理和Filter的综合案例
「编码处理的问题:」
原理
- 原理:过滤器技术拦截所有的controll的请求、在controll请求中使用了动态代理的设计模式监听了HttpServletRequest这个接口中getParameter方法的执行、在getParameter执行的时候、我们首先去获取这个数据、再通过判断当前的请求是GET还是POST、如果是GET那么先使用IOS-8859-1进行转码 然后使用UTF-8从新进行编码、如果是POST那么直接使用request.setCharacterEncoding(“UTF-8”)来进行处理
字符编码处理的实现
- public class CharacterFilter implements Filter{
- @Override
- public void init(FilterConfig arg0) throws ServletException {
-
- }
-
- @Override
- public void doFilter(ServletRequest request, ServletResponse response,
- final FilterChain chain) throws IOException, ServletException {
-
- final HttpServletRequest req=(HttpServletRequest) request;
- final HttpServletResponse resp=(HttpServletResponse) response;
-
- //第一步:将返回数据的编码问题给处理了
- resp.setContentType("text/html;charset=utf-8");
- //POST的解决方案
- req.setCharacterEncoding("UTF-8");
- //第二步:监听httpServletRequest中 getParameter方法的执行
- HttpServletRequest req1= (HttpServletRequest) Proxy.newProxyInstance(HttpServletRequest.class.getClassLoader(),
- new Class[]{HttpServletRequest.class},
- new InvocationHandler() {
- @Override
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- //监听当前执行的方法是不是 getParameter
- String methodName=method.getName();
- if("getParameter".equals(methodName)){ //说明执行的是getParameter
- //判断当前执行的是POST呢?还是GET呢?
- String reqName=req.getMethod();
-
- //通过key获取这个值
- String val= (String) method.invoke(req, args);
- if("GET".equalsIgnoreCase(reqName)){ //说明是GET方法
- //执行这个方法获取这个值
- val=new String(val.getBytes("ISO-8859-1"),"UTF-8");
-
- }else if("POST".equalsIgnoreCase(reqName)){ //说明是POST方法
-
- }
- //返回这个方法执行的结果
- return val;
- }else{
- return method.invoke(req, args);
- }
- }
- });
-
- //最终要进行放行
- chain.doFilter(req1, resp);
- }
- @Override
- public void destroy() {
-
- }
- }
「字符和谐的问题:」
- 明白一个问题:什么是字符和谐:类似于博客网站上,比如你发表不文明语句不会直接显示出来,而是显示成***等这种现象就称为字符的和谐
- 要实现字符和谐首先要解决编码问题(上面已经解决了)
- 在过滤器中设置脏数据
- //需要和谐的脏数据
- private String[] dirtyData={"MMD","NND","GD","CTM"};
在处理完字符编码问题的时候进行和谐(在处理完编码之后进行调用)
- protected String handleDirtyData(String val) {
- for (int i = 0; i < dirtyData.length; i++) {
- if(val.contains(dirtyData[i])){
- val=val.replaceAll(dirtyData[i],"***");
- }
- }
- return val;
- }
测试
结语
本篇关于过滤器Filter及代理Proxy的介绍就先到这里结束了,后续会出更多关于Filter和代理Proxy系列更多文章,谢谢大家支持!