gen_server之操作坐席人员记录(CRUD)
gen_server 是一个很好的模式,代码简易
可能在大型集群服务器中应该是很重要的吧,所以现在还没连接集群工作机制,
但从gen_server模式我还是有点想法的,
到时候部署到服务器上的话,热替换代码或者更改服务器服务性能和功能的话就不用通过改服务器内部代码
而可以通过外部请求来解决这个问题..
下面是gen_server模式写的一个例子:用于座席人员记录的保存,查询,排序,输出,删除,和更新
首先是一个 agent.hrl 外部文件(保存记录):state(状态),logintime(登陆时间)
1 -record(
2 agent,
3 {
4 id,
5 name,
6 groupid,
7 state = ready::'pause'|'talk'|'wrappup',
8 logintime::{integer(), integer(), integer()}
9 }
10 ).
11
下面是主要的定义外部接口:(供外部调用使用)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 -module(agent).
2 -export([start/0, stop/0, update/2,
3 insert/5, deleteByItem/1, findByItem/1]).
4 -compile(export_all).
5
6 -include("agent.hrl").
7 -include_lib("eunit/include/eunit.hrl").
8 -behaviour(gen_server).
9
10 %%%
11 %%% 外部接口定义
12 %%%
13
14 % 开始(外部接口)
15 start() ->
16 gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
17
18 % 结束(外部接口)
19 stop() ->
20 gen_server:call(?MODULE, stop).
21
22 % 更新(外部接口)
23 update(Item, Ag_state) ->
24 % 更新状态, 可添加多个字段,现在只更行 agent中 state 字段
25 gen_server:call(?MODULE, {update, Item, Ag_state}).
26
27 % 插入(外部接口)
28 insert(Id, Name, Gid, State, LogTime) ->
29 gen_server:call(
30 ?MODULE,
31 {insert, #agent{id=Id, name=Name, groupid=Gid, state=State, logintime=LogTime}}
32 ).
33
34
35 % 删除(外部接口)
36 deleteByItem(Item) ->
37 gen_server:call(?MODULE, {deleteByItem, Item}).
38
39
40
41 % 根据ID查询(外部接口)
42 findByItem(Item) ->
43 gen_server:call(?MODULE, {findByItem, Item}).
下面是回调函数:我在表初始化的时候就给表中添加数据,下面的 test_example() 就是保存数据
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 %%%
2 %%% 回调函数
3 %%%
4
5 % 初始化
6 % Tab意义上和State一样,提供后续的使用
7 init([]) ->
8 Tab = ets:new(agent,[named_table, set, public,{keypos,#agent.id}]),
9 lists:foreach(fun(Info) -> ets:insert(agent, Info) end, test_example()), % 插入表
10 {ok, Tab}. % 返回 {ok, State},*重要*
11
12 % 测试的数据
13 test_example() ->
14 [
15 #agent{id=1, name='lin', groupid=1, state="talk", logintime={11, 1, 19}},
16 #agent{id=2, name='hao', groupid=1, state="pause", logintime={11, 1, 19}},
17 #agent{id=3, name='jie', groupid=1, state="wrappup", logintime={11, 1, 19}},
18 #agent{id=4, name='study', groupid=1, state="pause", logintime={11, 1, 19}}
19 ].
20
21 % exit()
22 % Reason = normal | shutdown | {shutdown,term()} | term()
23 handle_call(stop, _From, Tab) ->
24 {stop, normal, stopped, Tab}; % 正常退出
25
26 % 更新
27 handle_call({update, Item, Ag_state}, _From, Tab) ->
28 {match, _First, Match} = regexp:first_match(Ag_state, "(pause)?|(talk)?|(wrappup)?"), % 正则匹配
29 case Match > 0 of
30 true ->
31 Reply = case ets:lookup(agent, Item) of
32 [] ->
33 no_Item;
34 [_Any] ->
35 ets:update_element(agent, Item, {#agent.state, Ag_state}),
36 'Update Successful!'
37 end;
38 false ->
39 Reply = 'You have Fail to adjust the Term!'
40 end,
41
42 % return
43 {reply, Reply, Tab};
44
45 % 插入
46 handle_call({insert, Agent}, _From, Tab) ->
47 %%% 需要正则表达式判断每一个值的内容这里先不写了, 只判断状态
48 {match, _First, Match} = regexp:first_match(Agent#agent.state, "(pause)?|(talk)?|(wrappup)?"), % 正则匹配
49 case Match>0 of
50 true ->
51 Reply = case ets:insert(agent, Agent) of
52 true ->
53 'Insert Successful!';
54 false ->
55 'Insert Fail!'
56 end;
57 false ->
58 Reply = 'You have Fail to adjust the Term!'
59 end,
60
61 % return
62 {reply, Reply, Tab};
63
64 % 通过Item删除数据
65 handle_call({deleteByItem, Item}, _From, Tab) ->
66 Reply = case ets:delete(agent, Item) of
67 true ->
68 'Delete Successful!';
69 false ->
70 'Delete Fail!'
71 end,
72
73 %return
74 {reply, Reply, Tab};
75
76 % 通过Item查询
77 handle_call({findByItem, Item}, _From, Tab) ->
78 Reply = case ets:lookup(agent, Item) of
79 [] ->
80 'Not record in the Table';
81 [Res] ->
82 Res
83 end,
84
85 % return
86 {reply, Reply, Tab}.
87
88
89 handle_cast(_Msg, State) ->
90 {noreply,State}.
91
92 handle_info(_Info, State) ->
93 {noreply, State}.
94
95 % 退出执行的函数
96 terminate(_Reason, _State) ->
97 ok.
98
99 % 代码热替换
100 code_change(_OldVsn, State, _Extra) ->
101 {ok, State}.
eUnit 测试代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 %%%%%%% test
2 agent_test_() ->
3 [
4 ?_test(start()),
5 ?_assert(update(1, "wrappup") == 'Update Successful!'),
6 ?_assert(insert(6, 'testInsert', 6, "pause", {20, 20, 20}) == 'Insert Successful!'),
7 ?_assert(insert(7, 'testInsert', 7, "13213", {20, 20, 20}) == 'You have Fail to adjust the Term!'),
8 ?_assert(deleteByItem(3) == 'Delete Successful!'),
9 ?_assert(findByItem(4) == {agent,4,study,1,"pause",{11,1,19}}),
10 ?_assert(stop() == stopped)
11 ].
12
上面代码的话写的很简单, 主要还是实现了其中一些功能,gen_server 还有很多深层的功能的,呵呵...等待你发掘
至于 gen_server 的工作机制我就不说了,
其实也是挺简单的,就是调用和面向对象的界面和实现代码分离的差不多(呵呵, 可能说的有点错了)~
后续改进