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
}
}