Welcome

Dec 3 2015
python mysqldb insert时数据带有转义字符处理

今天在使用python编写数据处理的时候,碰到数据中带有转义字符的时候,插入数据错误(数据是通过format拼接的,因此从数据库读取的字符串中的转移字符不能处理)

后来查阅资料,MysqlDB中的execute 可以将数据参数绑定到sql参数列表中(其实之前封装好的mysqlor.py中有该接口实现,只是从来没用过。。。今天才发现该接口的用处)

具体方法如下

1
2
3
params = [1, 2, 3]
insert_sql = 'INSERT INTO {tb} VALUES(%s, %s, %s)'.format(tb=table_name)
mysql_execute(cur, insert_sql, params) # params为user对应的字段

其中 mysql_execute 函数实现如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def mysql_execute(cursor, sql, param=None, debug=False):
u'''
执行 SQL 语句
'''

if cursor:
try:
if param in [None, "", '']:
return cursor.execute(sql)
else:
if isinstance(param, (list, tuple)): param = param
if debug: print "cursor.execute(sql, param) parameter, sql: {s}, param: {p}".format(s=sql, p=param)
return cursor.execute(sql, param)
except IndexError:
#except:
if debug: print "cursor.execute(sql, param) error, sql: {s}, param: {p}".format(s=sql, p=param)
return None
else:
if debug: print "mysql_execute parameter cursor is error."
return None
阅读此文

Oct 21 2015
maven_use_summary

1. 指定环境进行编译

  • 在pom.xml 中定义各种 profile
  • 在编译的时候指定 -Pprofile_id 即可

    1
    2
    3
    4
    5
    6
    <profiles>
    <profile>
    <id>dd</id>
    ...
    </profile>
    </profiles>
  • 可用于编译开发,测试,发布不同的版本

2. 去除测试

  • -Dmaven.test.skip = true 即可

3. 指定特定的测试模块进行测试

  • -Dtest=test_unit_name 即可
阅读此文

Sep 13 2015
菜鸟学习系列--netty服务器启动流程分析

最近在学习netty网络编程,下面以netty 中 DiscardServer 例子分析其流程

先贴下DiscardServer.java 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class DiscardServer {
private int port;

public DiscardServer(int port) {
this.port = port;
}

public void run() throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap(); // 1
b.group(bossGroup, workerGroup) // 2
.channel(NioServerSocketChannel.class) // 3
.childHandler(new ChannelInitializer<SocketChannel>() { // 4
public void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new DiscardServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128) // 5
.childOption(ChannelOption.SO_KEEPALIVE, true); // 6
ChannelFuture f = b.bind(port).sync(); // 7 bind 8 sync

f.channel().closeFuture().sync(); // 9
} finally {
workerGroup.shutdownGracefully(); // 10
bossGroup.shutdownGracefully();
}
}
}

消息处理类 DiscardServerHandler.java 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class DiscardServerHandler extends ChannelHandlerAdapter {

private Logger logger = Logger.getLogger(DiscardServerHandler.class);

public void channelRead(ChannelHandlerContext ctx, Object msg) {
logger.info("enter");
ByteBuf in = (ByteBuf)msg;
try {
logger.info("recv msg " + in.toString(CharsetUtil.US_ASCII));
} finally {
((ByteBuf)msg).release();
}
}

public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}

好,现在现从 DiscardServer 的第1步开始分析

  1. 调用ServerBootstrap 的无参构造函数,实例化对象
    1
    2
    3
    ServerBootstrap b = new ServerBootstrap(); 
    // 对应源码
    public ServerBootstrap() { } // 什么也没干

其中ServerBootstrap 的继承关系

1
2
3
public class ServerBootstrap 
public class AbstractBootstrap
public interface Cloneable

  1. 将父子事件管理器添加至ServerBootstrap中
    1
    b.group(bossGroup, workerGroup)

ServerBootstrap group 方法代码

1
2
3
4
5
6
7
8
9
10
11
public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
super.group(parentGroup); // 2.1 调用 父类AbstractBootstrap group 方法, 初始化父类事件管理器
if (childGroup == null) {
throw new NullPointerException("childGroup");
}
if (this.childGroup != null) { // 如果已经存在则抛异常
throw new IllegalStateException("childGroup set already");
}
this.childGroup = childGroup; // 初始化子类时间管理器
return this; // 返回对象本身
}

2.1. super.group(parentGroup);

1
2
3
4
5
6
7
8
9
10
public B group(EventLoopGroup group) {
if (group == null) {
throw new NullPointerException("group");
}
if (this.group != null) {
throw new IllegalStateException("group set already");
}
this.group = group;
return (B) this;
}

流程和ServerBootstrap.group 类似

  1. b.channel(NioServerSocketChannel.class)

利用反射机制生成 SocketChannel 实例, 调用的是 AbstractBootstrap.channel

1
2
3
4
5
6
public B channel(Class<? extends C> channelClass) { 
if (channelClass == null) {
throw new NullPointerException("channelClass");
}
return channelFactory(new ReflectiveChannelFactory<C>(channelClass)); // 3.1
}

其中 NioServerSocketChannel 类的继承关系如下

1
2
3
4
5
6
7
8
9
10
public class NioServerSocketChannel                                                                             
public class AbstractNioMessageChannel
public class AbstractNioChannel
public class AbstractChannel
public interface Channel
public interface Comparable
public interface ServerSocketChannel
public interface ServerChannel
public interface Channel
public interface Comparable

3.1. 调用AbstractBootstrap.channelFactory方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public B channelFactory(io.netty.channel.ChannelFactory<? extends C> channelFactory) {
return channelFactory((ChannelFactory<C>) channelFactory);
}

public B channelFactory(ChannelFactory<? extends C> channelFactory) {
if (channelFactory == null) {
throw new NullPointerException("channelFactory");
}
if (this.channelFactory != null) {
throw new IllegalStateException("channelFactory set already");
}

this.channelFactory = channelFactory; // 设置 Channel 生成工厂实例即ReflectiveChannelFactory
return (B) this;
}

其中ReflectiveChannelFactory 类的继承关系

1
2
3
public class ReflectiveChannelFactory                                           
public interface ChannelFactory // io.netty.channel.ChannelFactory
public interface ChannelFactory // io.netty.bootstrap.channelFactory

ReflectiveChannelFactory 的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public ReflectiveChannelFactory(Class<? extends T> clazz) {                     
if (clazz == null) {
throw new NullPointerException("clazz");
}
this.clazz = clazz; // 设置自己需要生成的Channel 实例类型
}

// 工厂方法,后面会讲到其作用
public T newChannel() {
try {
return clazz.newInstance();
} catch (Throwable t) {
throw new ChannelException("Unable to create Channel from class " + clazz, t);
}
}

  1. 设置childHandler
1
2
3
4
5
6
7
8
9
10
11
12
13
b.childHandler(new ChannelInitializer<SocketChannel>() {
public void initChannel(SocketChannel ch) {
ch.pipeline().addLast(new DiscardServerHandler()); // 没来一次请求都放到pipeline 队列尾, 该函数由childHandler 调用
}
});

public ServerBootstrap childHandler(ChannelHandler childHandler) {
if (childHandler == null) {
throw new NullPointerException("childHandler");
}
this.childHandler = childHandler;
return this;
}

其中ChannelInitializer 的继承关系为

1
2
3
public class ChannelInitializer
public class ChannelHandlerAdapter
public interface ChannelHandler //定义了各种读写就绪接口

5 6. 都是添加ChannelOption, option由AbstractBootstrap调用,childOption由ServerBootstrap调用

  1. ChannelFuture f = b.bind(port).sync();

先看 bind 的实现逻辑
bind 在AbstractBootstrap 中有5个实现

1
2
3
4
5
public ChannelFuture bind() {
public ChannelFuture bind(int inetPort) // 本文中调用的
public ChannelFuture bind(String inetHost, int inetPort)
public ChannelFuture bind(InetAddress inetHost, int inetPort)
public ChannelFuture bind(SocketAddress localAddress)

最终都调了 doBind方法

1
private ChannelFuture doBind(final SocketAddress localAddress)

现在开始分析doBind 方法逻辑逻辑
AbstractBootstrap.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
private ChannelFuture doBind(final SocketAddress localAddress) {
final ChannelFuture regFuture = initAndRegister();
final Channel channel = regFuture.channel();
if (regFuture.cause() != null) {
return regFuture;
}

if (regFuture.isDone()) {
// At this point we know that the registration was complete and successful.
ChannelPromise promise = channel.newPromise();
doBind0(regFuture, channel, localAddress, promise);
return promise;
} else {
// Registration future is almost always fulfilled already, but just in case it's not.
final PendingRegistrationPromise promise = new PendingRegistrationPromise(channel);
regFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
Throwable cause = future.cause();
if (cause != null) {
// Registration on the EventLoop failed so fail the ChannelPromise directly to not cause an
// IllegalStateException once we try to access the EventLoop of the Channel.
promise.setFailure(cause);
} else {
// Registration was successful, so set the correct executor to use.
// See https://github.com/netty/netty/issues/2586
promise.executor = channel.eventLoop();
}
doBind0(regFuture, channel, localAddress, promise);
}
});
return promise;
}
}

首先
AbstractBootstrap.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
final ChannelFuture regFuture = initAndRegister();

// initAndRegister 方法逻辑
final ChannelFuture initAndRegister() {
// 生成 NioServerSocketChannel 实例(之前channel 方法设定的)
final Channel channel = channelFactory().newChannel(); // 1
try {
init(channel); // 2
} catch (Throwable t) {
channel.unsafe().closeForcibly();
// as the Channel is not registered yet we need to force the usage of the GlobalEventExecutor
return new DefaultChannelPromise(channel, GlobalEventExecutor.INSTANCE).setFailure(t);
}

ChannelFuture regFuture = group().register(channel);
if (regFuture.cause() != null) {
if (channel.isRegistered()) {
channel.close();
} else {
channel.unsafe().closeForcibly();
}
}

// If we are here and the promise is not failed, it's one of the following cases:
// 1) If we attempted registration from the event loop, the registration has been completed at this point.
// i.e. It's safe to attempt bind() or connect() now because the channel has been registered.
// 2) If we attempted registration from the other thread, the registration request has been successfully
// added to the event loop's task queue for later execution.
// i.e. It's safe to attempt bind() or connect() now:
// because bind() or connect() will be executed *after* the scheduled registration task is executed
// because register(), bind(), and connect() are all bound to the same thread.

return regFuture;
}

上述代码中 1 中 newInstance 方法进行分析
首先调用的是

1
2
3
public NioServerSocketChannel() {                                                                                    
this(newSocket(DEFAULT_SELECTOR_PROVIDER));
}

其中 DEFAULT_SELECTOR_PROVIDER 定义为

1
2
3
4
5
// 这句话的最终结果就是获得java上层Selector Provider
// 据系统的不同,IO复用机制也不一样,比如linux 2.6以上使用时epoll,以下则是select/poll
// 为什么不用jdk自带的呢?或许这样性能会有所提高吧???
// 具体源码在 java/nio/channels/spi/SelectorProvider.java
private static final SelectorProvider DEFAULT_SELECTOR_PROVIDER = SelectorProvider.provider();

接着newSocket 方法 => openServerSocketChannel[返回ServerSocketChannel] => 调用NioServerSocketChannel(返回ServerSocketChannel channel) 构造函数实例化

1
2


上述代码中 2 中 init 方法 源码实现如下
ServerBootstrap.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
void init(Channel channel) throws Exception {
// 获取之前设置父类的options
final Map<ChannelOption<?>, Object> options = options();
synchronized (options) {
channel.config().setOptions(options);
}

final Map<AttributeKey<?>, Object> attrs = attrs();
synchronized (attrs) {
for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) {
@SuppressWarnings("unchecked")
AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();
channel.attr(key).set(e.getValue());
}
}

ChannelPipeline p = channel.pipeline();

final EventLoopGroup currentChildGroup = childGroup;
final ChannelHandler currentChildHandler = childHandler;
final Entry<ChannelOption<?>, Object>[] currentChildOptions;
final Entry<AttributeKey<?>, Object>[] currentChildAttrs;
synchronized (childOptions) {
currentChildOptions = childOptions.entrySet().toArray(newOptionArray(childOptions.size()));
}
synchronized (childAttrs) {
currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(childAttrs.size()));
}

p.addLast(new ChannelInitializer<Channel>() {
@Override
public void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
ChannelHandler handler = handler();
if (handler != null) {
pipeline.addLast(handler);
}
pipeline.addLast(new ServerBootstrapAcceptor(
currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}

阅读此文

Sep 12 2015
java-blocking-queue-learn

Java BlockingQueue 接口在 java.util.concurrent中定义,他保证了线程线程间数据共享是安全的。这篇文章将会讲述 BlockingQueue 的使用。

阅读此文

Sep 11 2015
java-volatile-keyword-learn

java volatile 变量写的同时会将之前线程内变量写的变量值同时 refresh in main memory

java volatile 变量读的同时,也会将线程内变量的值同时 refresh from main memory

阅读此文

Sep 11 2015
Java并发编程学习

  1. 模型更加复杂
  2. 上下文切换消耗资源
阅读此文

Sep 8 2015
java-io-learning

阅读此文

Sep 7 2015
Java设计模式学习之中介者模式

中介者模式是行为型模式的一种,他一般用于系统中不同对象间消息的统一处理,在GoF中这样介绍:

通过某种封装,将不同对象松耦合,使之可以互相影响,消息可以互相转发,同时也允许不同对象互不依赖

当某个应用出现很多对象互相影响时,中介者模式就派上用场了。如果对象之间是强耦合的,这样就会导致维护难度大大增大,不易扩展。而中介者模式可以使对象间松耦合。

飞机场广播就是一个很好的例子,提供了不同飞机之间消息转发的一种机制。对于模式来说的话,他一般是作为一个中间路由,就好比游戏服务中gateway服务一样。

系统中互相交流的对象,我们称之为同事(-_-),我们通常用一个接口类或抽象类表示,然后针对不同的同事再实现具体类

Mediator Interface

首先我们创建一个 Mediator Interface,定义了中介者是如何工作的

ChatMediator.java

1
2
3
4
5
6
7
package com.walterlife.dp.MediatorDP;

public interface CharMediator {
public void sendMessage(String msg, User user);

public void addUser(User user);
}

Colleague Interface

同事间可以互相转发消息,可以将之定义为接口或抽象类,这里我把他定义为抽象类

User.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.walterlife.dp.MediatorDP;

public abstract class User {
CharMediator mediator;

String name;

public User(CharMediator mediator, String name) {
this.mediator = mediator;
this.name = name;
}

public abstract void sendMessage(String msg);

public abstract void receive(String msg);
}

在每个同事的内部维护着中介者的引用,这样就可以和其他同事间互相交流了

Concrete Mediator

现在开始实现具体的中介者,该中介者内部维护这 Colleagues list,同时提供了同事间交流的逻辑

ChatMediatorImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package com.walterlife.dp.MediatorDP;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

public class CharMediatorImpl implements CharMediator {

private static Logger logger = Logger.getLogger(CharMediatorImpl.class);

private List<User> users = new ArrayList<User>();

@Override
public void sendMessage(String msg, User user) {
// TODO Auto-generated method stub
for(User u: users) {
if(u != user) {
u.receive(msg);
}
}
}

@Override
public void addUser(User user) {
// TODO Auto-generated method stub
if(user != null) {
if(!users.contains(user)) {
users.add(user);
} else {
logger.warn("add user name " + user.getName() + " is already existing!!!");
}
} else {
logger.warn("add user param is null!!!");
}
}
}

Concrete Colleague

现在我们开始实现具体的Colleagues

UserImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.walterlife.dp.MediatorDP;

import org.apache.log4j.Logger;

public class UserImpl extends User {

private static Logger logger = Logger.getLogger(CharMediatorImpl.class);

public UserImpl(CharMediator mediator, String name) {
super(mediator, name);
}

@Override
public void sendMessage(String msg) {
// TODO Auto-generated method stub
logger.info("User " + this.name + " send msg " + msg + "!!!");
mediator.sendMessage(msg, this);
}

@Override
public void receive(String msg) {
// TODO Auto-generated method stub
logger.info("User " + this.name + " receive msg " + msg + "!!!");
}

}

在Colleague 进行发消息时,他是通过中介者来发送的,但是他是不知道中介者内部是如何处理的

测试代码

现在我们开始测试已经实现的中介者模式,主要实现是,先往中介者中添加Colleagues,然后其中一个Colleague 发送消息来测试逻辑的正确性

1
2
3
4
5
6
7
8
9
10
public static void testMediator() {
CharMediatorImpl mediator = new CharMediatorImpl();
UserImpl walter = new UserImpl(mediator, "walter");
mediator.addUser(walter);
mediator.addUser(new UserImpl(mediator, "ym"));
mediator.addUser(new UserImpl(mediator, "cj"));
mediator.addUser(new UserImpl(mediator, "test"));

walter.sendMessage("Hello World");
}

解释结果

1
2
3
4
2015-09-08 08:27:49 INFO  com.walterlife.dp.MediatorDP.UserImpl sendMessage:16 -> User walter send msg Hello World!!!
2015-09-08 08:27:49 INFO com.walterlife.dp.MediatorDP.UserImpl receive:23 -> User ym receive msg Hello World!!!
2015-09-08 08:27:49 INFO com.walterlife.dp.MediatorDP.UserImpl receive:23 -> User cj receive msg Hello World!!!
2015-09-08 08:27:49 INFO com.walterlife.dp.MediatorDP.UserImpl receive:23 -> User test receive msg Hello World!!!

阅读此文

Sep 7 2015
Java设计模式之模板方法模式

模板方法模式是行为型模式中一种,他通常只需实现一个根方法即可,该方法规定了各个方法的执行顺序。这些方法中可以是各个子类共有的,也可以是每个子类不一样的,该模板方法是父类独有的,一般可以定义为final,可以防止子类进行重写

现在我们以造房子为例子,一般造房子都是以规定的顺序开工的,先打地基,再搭骨架,然后砌墙,最后上玻璃。其中地基是不同房子基本都是一样的,骨架有的可以是木头的,有的可以是砖块的,有的是玻璃,墙也是同样的。这里我们以玻璃房和木头房举例子,这两个子类都继承房子的基类(HouseTemplate),他们的buildPillars 和 buildWalls 方法是不同的,但是他们的建造顺序都是一样的,在HouseTemplate中的buildHouse中实现

其中为了父类中的模板方法不被子类重写,我们把该方法定义为 final 方法

Template Method Abstract Class

因为父类中有点方法是不需要实现的,模板方法又必须实现的,故将该类定义为 abstract class

HouseTemplate.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.walterlife.dp.TemplateMethodDP;

import org.apache.log4j.Logger;

public abstract class HouseTemplate {

private Logger logger = Logger.getLogger(HouseTemplate.class);

// template method, order is fioxed
// final so subclasses can not override it
public final void buildHouse() {
buildFoudation();
buildPillers();
buildWalls();
buildWindows();
}

public void buildWindows() {
logger.info("HouseTemplate build windows!!!");
}

public abstract void buildWalls();

public abstract void buildPillers();

public void buildFoudation() {
logger.info("HouseTemplate build foudation!!!");
}
}

buildHouse() 是模板方法,该方法定义了建造房子固定的顺序

Template Method Concrete Classes

这里我们只以 木头房和 玻璃房为例

WoodenHouse.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.walterlife.dp.TemplateMethodDP;

import org.apache.log4j.Logger;

public class WoodenHouse extends HouseTemplate {

private Logger logger = Logger.getLogger(HouseTemplate.class);

@Override
public void buildWalls() {
// TODO Auto-generated method stub
logger.info("build house with wooden walls!!!");
}

@Override
public void buildPillers() {
// TODO Auto-generated method stub
logger.info("build house with wooden pills!!!");
}
}

GlassHouse.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.walterlife.dp.TemplateMethodDP;

import org.apache.log4j.Logger;

public class GlassHouse extends HouseTemplate {

private Logger logger = Logger.getLogger(HouseTemplate.class);

@Override
public void buildWalls() {
// TODO Auto-generated method stub
logger.info("build house with glass walls!!!");
}

@Override
public void buildPillers() {
// TODO Auto-generated method stub
logger.info("build house with glass pills!!!");
}
}

Test Method

现在开始测试我们刚刚实现的模板方法模式 代码

1
2
3
4
5
6
7
8
public static void testTemplateMethod() {
HouseTemplate house = new WoodenHouse();
house.buildHouse();
logger.info("================================");

house = new GlassHouse();
house.buildHouse();
}

输出

1
2
3
4
5
6
7
8
9
2015-09-07 22:43:28 INFO  com.walterlife.dp.TemplateMethodDP.HouseTemplate buildFoudation:27 -> HouseTemplate build foudation!!!
2015-09-07 22:43:28 INFO com.walterlife.dp.TemplateMethodDP.WoodenHouse buildPillers:18 -> build house with wooden pills!!!
2015-09-07 22:43:28 INFO com.walterlife.dp.TemplateMethodDP.WoodenHouse buildWalls:12 -> build house with wooden walls!!!
2015-09-07 22:43:28 INFO com.walterlife.dp.TemplateMethodDP.HouseTemplate buildWindows:19 -> HouseTemplate build windows!!!
2015-09-07 22:43:28 INFO com.walterlife.dp.App testTemplateMethod:24 -> ================================
2015-09-07 22:43:28 INFO com.walterlife.dp.TemplateMethodDP.HouseTemplate buildFoudation:27 -> HouseTemplate build foudation!!!
2015-09-07 22:43:28 INFO com.walterlife.dp.TemplateMethodDP.GlassHouse buildPillers:18 -> build house with glass pills!!!
2015-09-07 22:43:28 INFO com.walterlife.dp.TemplateMethodDP.GlassHouse buildWalls:12 -> build house with glass walls!!!
2015-09-07 22:43:28 INFO com.walterlife.dp.TemplateMethodDP.HouseTemplate buildWindows:19 -> HouseTemplate build windows!!!

阅读此文

Sep 6 2015
Java设计模式学习之代理模式

代理模式是结构型模式中的一种,在GOF中有如下介绍

为另外一个对象提供代理,以便可以访问该对象

当我们需要实现控制访问的功能,就可以使用该模式

就拿linux系统命令而言,并不是所有的命令普通用户都可以执行的,这里linux系统的用户的权限管理模块就是一种代理,当用户想要执行命令时,最终都会代理到该模块,然后执行相应的命令

我们就简单的以执行命令为例子来实现代理模式

首先从接口开始编写代码

接口类

CommandExecutor.java

1
2
3
4
5
package com.walterlife.dp.ProxyDP;

public interface CommandExecuter {
public void runCommand(String cmd) throws Exception;
}

接口实现类

CommandExecutorImp.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.walterlife.dp.ProxyDP;

import java.io.IOException;

import org.apache.log4j.Logger;

public class CommandExecuterImpl implements CommandExecuter {

private static Logger logger = Logger.getLogger(CommandExecuter.class);

public void runCommand(String cmd) throws IOException {
Runtime.getRuntime().exec(cmd);
logger.info("CommandExecuter run cmd: " + cmd);
}
}

阅读此文