JavaWeb——动态代理

1、什么是代理(中介)
目标对象/被代理对象 —— 房主:真正的租房的方法
代理对象 ——- 黑中介:有租房子的方法(调用房主的租房的方法)
执行代理对象方法的对象 —- 租房的人

流程:我们要租房—–>中介(租房的方法)——>房主(租房的方法)
抽象:调用对象—–>代理对象——>目标对象

2、动态代理
动态代理:不用手动编写一个代理对象,不需要一一编写与目标对象相同的方法,这个过程,在运行时 的内存中动态生成代理对象。——字节码对象级别的代理对象

注意:JDK的Proxy方式实现的动态代理 目标对象必须有接口 没有接口不能实现jdk版动态代理
这里写图片描述
这里写图片描述
Target.java(目标对象)

package cn.ctgu.proxy;

public class Target implements TargetInterface{

    @Override
    public void method1() {
        // TODO Auto-generated method stub
        System.out.println("method1 running...");
    }
    @Override
    public String method2() {
        // TODO Auto-generated method stub
        System.out.println("method2 running...");
        return "method2";
    }
    @Override
    public int method3(int x) {
        // TODO Auto-generated method stub
        return x;
    }

}

TargetInterface.java(目标对象接口)

package cn.ctgu.proxy;

public interface TargetInterface {
    public void method1();
    public String method2();
    public int method3(int x);
}

ProxyTest.java

package cn.ctgu.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.junit.Test;

public class ProxyTest {
    @Test
    public void test1() {
        //获得动态的代理对象----在运行时在内存中动态的为target创建一个虚拟的代理对象
        //ObjectProxy是代理对象   根据参数确定到底是谁的代理对象
        TargetInterface objProxy=(TargetInterface) Proxy.newProxyInstance(
                Target.class.getClassLoader(),//与目标对象相同的类加载器 
                new Class[] {TargetInterface.class}, 
                new InvocationHandler() {
                    //invoke代表的是执行代理对象的方法
                    //method代表目标对象的方法字节码对象
                    //args代表目标对象的响应的方法参数
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // TODO Auto-generated method stub
                        System.out.println("目标方法前的逻辑");
                        //执行目标对象的方法
                        Object invoke=method.invoke(new Target(), args);
                        System.out.println("目标方法后的逻辑");
                        return invoke;//如果return null则method2不能返回,即为空
                    }
                }
            );
        objProxy.method1();
        String method2=objProxy.method2();
        System.out.println(method2);
    }
}

ProxyTest2.java

package cn.ctgu.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyTest2 {
    public static void main(String[] args) {
        final Target target=new Target();
        //动态创建代理对象
        TargetInterface proxy=(TargetInterface) Proxy.newProxyInstance(
                target.getClass().getClassLoader(), 
                target.getClass().getInterfaces(), 
                new InvocationHandler() {
                    //被执行几次?-----看代理对象调用方法几次
                    //代理对象调用接口相应方法都是调用invoke
                    @Override
                    /*
                     * proxy:代理对象
                     * method:代表的是目标方法的字节码对象
                     * args代表是调用目标方法时参数
                     * */
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // TODO Auto-generated method stub
                        Object invoke=method.invoke(target, args);//目标对象相应的方法
                        //return 返回的值给代理对象
                        return invoke;
                    }
                }
            );
        proxy.method1();//调用invoke----method:目标对象的method1方法   args:null 返回值是null
        String method2=proxy.method2();//调用invoke----method:目标对象的method2方法   args:null  返回值是"method2"
        int method3=proxy.method3(100);//调用invoke----method:目标对象的method2方法   args:Object[]{100} 返回值是100

        System.out.println(method2);
        System.out.println(method3);
    }
}

3、案例——动态代理解决全局乱码
encoding.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>解决全局乱码</title>
</head>
<body>
    <form action="${pageContext.request.contextPath }/encodingServlet" method="post">
        <input type="text" name="username"/>
        <input type="submit" value="提交">

    </form>
</body>
</html>

encodingServlet.java

package cn.ctgu.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class encodingServlet
 */
@WebServlet("/encodingServlet")
public class encodingServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String parameter=request.getParameter("username");
        System.out.println(parameter);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

encodingFilter.java

package cn.ctgu.filter;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

@WebFilter(filterName="encodingFilter",urlPatterns="/*")
public class encodingFilter implements Filter{

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        //使用动态代理完成全局编码
        HttpServletRequest req=(HttpServletRequest) request;
        //使用动态代理完成全局编码
        HttpServletRequest enhanceRequest=(HttpServletRequest) Proxy.newProxyInstance(
                req.getClass().getClassLoader(), 
                req.getClass().getInterfaces(), 
                new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //对getParameter方法进行增强
                        String name=method.getName();//获得目标对象的方法名称
                        if("getParameter".equals(name)) {
                            String invoke=(String) method.invoke(req, args);//乱码
                            //转码
                            invoke=new String(invoke.getBytes("iso8859-1"),"utf-8");
                            return invoke;
                        }
                        return method.invoke(req, args);
                    }
                }
            );
        chain.doFilter(enhanceRequest, response);
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub

    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值