Java中的设计模式之–代理模式
1.代理:与我们平常听说的代理基本上是一个意思,例如:微商现在是许多人实现梦想的一个重要平台,从厂商—-代理—-客户三者之间来进行商品交易。代理就是为厂商提供客户,厂商为代理提供商品,以及佣金报酬。
2.代理模式能够解决什么问题呢?
代理模式在Java中用于对一个类的增强,具体是对方法的增强。那么微商中,有些商品可以在销售中需要做一些过滤,比如某些商品只对学生销售,厂商并不去做这件事情,而是代理人自己去处理,这样通过代理人去处理业务逻辑,而不影响商品销售这件事情,客户在厂商那里能够买到东西,通过代理人也能够买到东西,这种模式被称之为代理模式。
3.Java中的代理模式:
JDK中提供的Proxy代理类,由Java.lang.reflect.Proxy提供动态创建代理的方法`Proxy.newProxyInstance(ClassLoader, Class
静态代理实现对查询结果的判空处理:
实现条件:
①需要存在提供方法的接口,委托类与代理类实现同一个接口
②代理类中需要有委托类的对象的引用。
接口:UserDao层的接口,提供查询等方法。
public interface UserDaoImpl{
public User queryUser();
}
委托类:(相当于厂商,需要代理解决判空的问题)
public class UserDao implements UserDaoImpl{
public User queryUser(){
QueryRunner qr = new QueryRunner(JDBCUtils.getDataSource());
String sql = "select * from user where uname = ? and password = ?";
User exitUser = qr.query(sql, new BeanHandler<User>(User.class),user.getUname(),user.getPassword());
return exitUser;
}
}
代理类:(代理人,处理了判断查询结果是否为空)
public UserDaoProxy implements UserDaoImpl{
private UserDaoImpl obj;//拥有实现这个接口子类对象的引用
public UserDaoProxy (Object obj){
this.obj = obj;
}
public User queryUser(){
User user = obj.queryUser();
//调用这个方法之后,我们可以检查是否有结果
if(null != user){
return user;
}else{
System.out.println("没有查询到结果");
}
}
}
客户(测试):
public class DoMain{
@Test
public void test(){
产生代理对象,传入的为一个userdao的对象,
UserDaoImpl imp = new UserDaoProxy(new UserDao());
User user = imp.queryUser();
System.out.println(user.toString());
}
}
那么,动态代理与静态代理的区别就是:动态代理并没有代理类的.java文件编写,而是通过Proxy提供的newProxyInstance()这个方法来实现的。
具体实现demo如下:
客户:
创建动态代理的核心方法:
Proxy.newProxyInstance(①类加载器对象,②类实现的所有接口,③代理处理器InvocationHandler)
代理处理器InvocationHandler接口,这里通过匿名内部类实现,因为它只提供了一个抽象方法。
这个处理器主要处理增强的方法的业务实现。这里就实现了对查询结果判空的处理
public class DoMain{
@Test
public void test(){
//产生一个动态代理类对象
UserDaoImpl proxy = (UserDaoImpl)Proxy.newProxyInstance(UserDaoImpl.class.getClassLoader(),
UserDaoImpl.class.getInterfaces(),new InvocationHandler(){
@Override
Object表示的是委托类的对象,method表示的是委托类中的方法,args参数表示执行此方法需要的参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
User result = (User) method.invoke(proxy, args);
if(null != result){
return result;
}
return null;
}
});
通过代理对象调用方法。
User user = proxy.queryUser();
}
}
具体实现如图:
关于使用过滤器结合动态代理完成对请求中文乱码的处理现在就变得容易多了。代码如下:
使用动态代理完成输入中文乱码问题
* JDK中的动态代理:Proxy
* Proxy.newProxyInstance(ClassLoader,实现的所有接口,对象.getClass().getInterfaces,InvocationHandler);
* InvocationHandler接口,它是JDK Proxy实现动态代理的核心,可以理解为一个中介,用于执行委托类的方法
* 委托类:被增强的类HttpServletRequest 的request对象
* 代理类:通过newProxyInstance产生的动态代理
* 中介类:InvocationHandler接口的实现类,执行代理类中的getParameter,进而执行委托类中的getParameter
* 使用动态代理的条件:
* 被代理的类需要实现接口,例如:GenericEncodingType 实现Filter接口
@WebFilter("/*")
public class GenericEncodingType implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
//
HttpServletRequest request = (HttpServletRequest)req;
//使用匿名内部类创建一个动态代理对象
HttpServletRequest StrongReq = (HttpServletRequest)Proxy.newProxyInstance(request.getClass().getClassLoader(),
request.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//method为getParameter时
String type = request.getMethod();
if("getParameter".equals(method)){
if("get".equalsIgnoreCase(type)){
String result = (String)method.invoke(request, response);
return new String(result.getBytes("ISO-8859-1"),"UTF-8");
}else if("post".equalsIgnoreCase(type)){
request.setCharacterEncoding("UTF-8");
}
}
return method.invoke(request, response);
}
});
filterChain.doFilter(StrongReq, response);
}