您的位置:首页 > 其它

毕设项目,系统搭建笔记文档

2013-12-06 15:05 337 查看
代码结构:



主体系统启动流程:

在dynamic web project中添加全局监听类RootListener,继承ServletContextListener接口,实现public void contextInitialized(ServletContextEvent sce),调用系统初始化入口类ArchtechRoot。在ArchtechRoot中根据spring配置文件进行系统各模块的初始化。从root bean读取SystemInitDO,用于获取配置文件中的子配置文件,即各层模块配置文件,并将其中的bean进行装配。RPCServer为RPC服务的基础server模块,对应rpcRoot bean。

ApplicationContext context = new ClassPathXmlApplicationContext("springContext-*.xml");
SystemInitDO initDO = (SystemInitDO) context.getBean("root");
RPCServer rpcRoot = (RPCServer) context.getBean("rpcRoot");


子配置文件:

<bean id="root" class=" com.multiagent.hawklithm.davinci.init.SystemInitDO">
<property name="configFileList">
<list>
<value>spring-config/spring-asyntask.xml</value>
<value>spring-config/spring-EventListener.xml</value>
<value>spring-config/spring-dao.xml</value>
<value>spring-config/spring-manager.xml</value>
<value>spring-config/spring-module.xml</value>
<value>spring-config/spring-ibatis.xml</value>
<value>spring-config/spring-net.xml</value>
<value>spring-config/spring-transaction.xml</value>
<value>spring-config/spring-session.xml</value>
</list>
</property>
</bean>


子配置文件中几个关键注册管理机

bean 分类注册管理机

<!-- bean分类注册管理机 -->
<bean class="com.multiagent.hawklithm.davinci.init.AutoRegister"/>


异步任务注册机

<!-- 异步任务注册机 -->
<bean id="asynTaskRegManager" class="com.multiagent.hawklithm.davinci.AsynTaskRegisterMachine" />


消息注册管理机

<!-- 消息注册管理机 -->
<bean id=" wardenManager" class="com.multiagent.hawklithm.shadowsong.manager.WardenManager"/>


生产过程模块管理机

<!-- 生产过程模块管理注册机 -->
<bean id="pmRegManager" class="com.multiagent.hawklithm.leon.manager.ProcessModuleRegisterManager"/>


bean注册管理机

public class AutoRegister implements BeanPostProcessor {
private AsynTaskRegisterMachine asynTaskRegManager;
private ProxyFactoryBean accountService;
private ProcessModuleRegisterManager pmRegManager;

public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof AsynTaskRegister) {
System.out.println("bean name: "+beanName+" regist AsynTaskRegister");
asynTaskRegManager.regist(bean);//异步任务注册
}else if (bean instanceof IProcessModule){
System.out.println("bean name: "+beanName+" regist EquipmentObject");
pmRegManager.regist(bean);//过程模块注册
}
return bean;
}

}


如代码所示,根据类类型就行分类注册

RPC接口注册:

RPC接口定义在springContext-rpc.xml中

如以下示例接口定义

<bean class="com.multiagent.hawklithm.davinci.rpc.DO.RPCSystemServerProxy">
<property name="interfaceName" value="com.multiagent.hawklithm.rpc.Interfacetest"/>
<property name="version" value="1.0.0.hawk"/>
<property name="className" value="com.multiagent.hawklithm.rpc.impl.ImplTest"/>
<property name="comment" value="此处填写接口介绍"/>
<property name="visible" value="true" />
</bean>


RPCServer创建

<bean id="rpcRoot" class="com.multiagent.hawklithm.davinci.rpc.Server.RPCServer">
<constructor-arg>
<value>10007</value>
</constructor-arg>

</bean>


在RPCServer.java中,Rpc接口bean注册

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof RPCSystemServerProxy) {
RPCregManager.regist((RPCSystemServerProxy) bean);
}
return bean;
}


将已注册RPC接口与已注册模块关联:

ArchtechRoot.java

对已填充beanId字段的RPC接口类进行关联

for (RPCSystemServerProxy object : rpcRoot.getRPCregManager().getRegList()) {
if (StringUtils.hasLength(object.getBeanId())) {
try {
Object target = tempContext.getBean(object.getBeanId());
object.setTarget(target);
System.out.println(object.getInterfaceName() + "关联成功");
} catch (NoSuchBeanDefinitionException e) {
// TODO 打印日志RPC配置文件中bean缺失
System.out.println("RPC配置文件中缺失bean:[" + object.getBeanId() + "]");
}
}
}


对未填充beanId字段的RPC接口类进行实例创建(目前均使用单例模式)

for (RPCSystemServerProxy object : rpcRoot.getRPCregManager().getRegList()) {
if (!object.isLinked()) {
object.setTarget(Class.forName(object.getClassName()).newInstance());
System.out.println(object.getClassName() + "生成实例成功");
}
}


以上完成所有模块的创建和注册关联工作

启动异步任务注册机中的所有异步任务:

regManager.startAll();


消息注册部分Shadowsong

消息注册管理机WardenManager.java

public class WardenManager implements IRegisterManager, IMessagePusher<WardenMessage> {

public boolean regist(Object object) {
/**具体见源码*/
}

/**
* Warden接收消息的异步线程
* @author hawklithm
*
*/
private class WardenThread implements Runnable {
/**具体见源码*/
@Override
public void run() {
object.receiveMessage(message);
}

}

/**
* 推送消息
*/
public void push(WardenMessage message) {
Set<Warden> list = map.get(message.getKind());
for (Warden object : list) {
exec.execute(new WardenThread(object, message));
}
}

}


使用消息注册机时先进行消息注册

wardenManager.registWarden(new Warden(“MessageReceiver”, “MessageType”) {

//message对应消息结构体WardenMessage中的note属性
@Override
public void asynchronizedProcess(String message) {
/**接收到消息后的行为*/
}

});


发送消息:

wardenManager.push(message);


message类型为WardenMessage

纯虚类EquipmentObjetc类型继承了WardenOperator接口实现方法

public void sendOutMessage(WardenMessage message) {
wardenManager.push(message);
}


所以继承了EquipmentObject的类直接调用sendOutMessage(WardenMessage message)即可。

举例:

读卡器模块初始化时(读卡器模块继承了EquipmentObject)

this.registWarden(new Warden(String.valueOf(this.getRfid()) + WardenMessage.TARGET_TYPE_READER, WardenMessage.KIND_NEW_DATA_COMING + WardenMessage.DIR_ENTER) {

@Override
public void asynchronizedProcess(String message) {
WardenMessage wardenMessage = new WardenMessage();
wardenMessage.setNote(message);
wardenMessage.setTarget(String.valueOf(targetRFID) + targetKind);
wardenMessage.setKind(targetMessageKind + targetMessageDir);
sendOutMessage(wardenMessage);
}

});


以上代码截取自Reader.java表示在接收到warden消息后将其信息实体取出并重新定义warden消息的目标和类型并转发,我们现在做一个约定:

消息接收者:目标RFID+目标类型

消息类型:消息类型+消息流向

WardenMessage.java中展示预设了几种消息类型

/**
* 消息类型
*/
public static String KIND_RFID_FROM_READER = "wm_rfidfromreader";//从读卡器模块发送来的RFID数据
public static String KIND_NEW_DATA_COMING = "new_data_coming";//接收到从RFID实体来的数据
/**
* 目标类型
*/
public static String TARGET_TYPE_READER = "target_type_reader";//数据接收目标类型为读卡器
public static String TARGET_TYPE_MACHINE = "target_type_machine";//数据接收目标类型为设备模块
/**
* 数据流方向
*/
public static String DIR_ENTER = "wm_enter";
public static String DIR_EXIT = "wm_exit";


模块间信息交互和数据传输均可使用该消息系统

生产过程管理模块(静态模块系统leon)

public class ProcessModuleRegisterManager implements IRegisterManager {
private List<IProcessModule> regList = new ArrayList<IProcessModule>();
public boolean regist(Object thing) {
/**过程模块注册*/
}

public IProcessModule getProcessModuleByName(String name) throws ProcessModuleNotFoundException {
/**根据模块名称(ID)获取已注册的过程模块*/
}

public EquipmentObject getEquipmentByRFID(int id) throws ProcessModuleNotFoundException {
/**根据设备名称(ID)获取已注册的过程模块中的设备模块*/
}
}


过程注册模块中包含所有已注册的过程模块信息

生产过程模块(静态模块):

统一继承IProcessModule,具体见IProcessModule.java

public interface IProcessModule {
/**
* 获取模块名称
* @return 模块名称
*/
String getName();
/**
* 根据设备RFID从过程模块中获取设备
* @param id 设备RFID
* @return
* @throws EquipmentNotFoundException
*/
EquipmentObject getEquipmentByRFID(int id) throws EquipmentNotFoundException;
}


在过程模块中建立设备列表,通过spring bean注入设备,可达到过程对设备的一个管理,实例见SortingProcess.java

对应bean的spring配置参考spring-module.xml,如下:

<bean id="sorting_process_module" class="com.multiagent.hawklithm.leon.process.SortingProcess">
<property name="equipmentList">
<list>
<ref bean="reader1"/>
<ref bean="sorting_equipment1" />
<ref bean="reader2" />
<ref bean="singleRead3"/>
<ref bean="sorting_equipment2" />

</list>
</property>
</bean>


设备模块

统一继承纯虚类EquipmentObject,在EquipmentObject.java中已实现设备的基本功能方法

public abstract class EquipmentObject implements Module, WardenOperator {
private int rfid ;
private Set<Integer> itemRFIDs = new HashSet<Integer>();
private Set<Integer> packageRFIDs = new HashSet<Integer>();
private int staffRFID;
private WardenManager wardenManager;

/**
* 设置设备属性
*/
abstract public void doSetEquipmentParameter();

/**
* 获取设备属性
* @return
*/
abstract public String doGetEquipmentSummaryInfo();

/**
* 初始化Warden
*/
abstract public void initWarden();

public void sendOutMessage(WardenMessage message) {
wardenManager.push(message);
}

public void registWarden(Warden warden) {
wardenManager.regist(warden);
}

public void addItem(int RFID) {
itemRFIDs.add(Integer.valueOf(RFID));
}

public void addPackage(int RFID) {
packageRFIDs.add(Integer.valueOf(RFID));
}

public boolean removeItem(int RFID) {
return itemRFIDs.remove(Integer.valueOf(RFID));
}

public boolean removePackage(int RFID) {
return packageRFIDs.remove(Integer.valueOf(RFID));
}

// public EquipmentObject() {
// warden = new Warden(this);
// wardenManager.regist(warden);
// }

public String doGetModuleSummaryInfo() {
return doGetEquipmentSummaryInfo();
}

public int getStaffRFID() {
return staffRFID;
}

public void setStaffRFID(int staffRFID) {
this.staffRFID = staffRFID;
}

public WardenManager getWardenManager() {
return wardenManager;
}

public void setWardenManager(WardenManager wardenManager) {
this.wardenManager = wardenManager;
}
}


在配置设备bean时注意设置init-method="initWarden"从而调用initWarden函数进行消息注册

例:

<bean id="sorting_equipment1"    class="com.multiagent.hawklithm.leon.module.SortingEquipmentModule"  init-method="initWarden" >
<property name="rfid" value="1024"/>
</bean>


initWarden中的注册warden见上文消息注册管理Shadowsong部分,具体实现见com.multiagent.hawklithm.leon.module包下的模块类

RPC系统

rpc client端在rpc工程中,server端在davinci中,rpc所有spring bean配置文件均在springContext-rpc.xml中,rpc接口信息通过interfaceInfoDAO保存到数据库中。

RPCServer.java

在initNetty()函数中创建Netty服务端实现通信

private void initNetty() {
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {

@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("UP_FRAME_HANDLER", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 2, 0, 2));
pipeline.addLast("DOWN_FRAME_HANDLER", new LengthFieldPrepender(2, false));
pipeline.addLast("myHandler", rpcServerNettyHandler);
// return Channels.pipeline(rpcServerNettyHandler);
return pipeline;
}

});
bootstrap.bind(new InetSocketAddress(port));
System.out.println("RPC server开启成功");
}


NettyHandler继承SimpleChannelHandler对通信接口进行一些基本封装

public class NettyHandler extends SimpleChannelHandler {

@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
/**接收到数据将通信相关数据取出并传入onMessageReceived方法*/
ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
String recvMsg=buffer.toString(Charset.defaultCharset());
System.out.println("receive: " +recvMsg);
onMessageReceived(recvMsg,e.getChannel());
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
/**异常处理*/
}

public void sendMessage(String message,Channel channel) throws MessageTransportException {
if (channel == null) {
throw new MessageTransportException(new NullPointerException());
}
ChannelBuffer buffer = ChannelBuffers.buffer(message.length());
buffer.writeBytes(message.getBytes());
channel.write(buffer);
}
/**
* 重写该函数可获取传输数据
*/
public void onMessageReceived(String message,Channel channel) throws MessageTransportException {

}
}


RPCServerNettyHandler继承NettyHandler

重写onMessageReceived

@Override
public void onMessageReceived(String msg, Channel cha) throws MessageTransportException {
System.out.println(msg);
RPCSystemProtocol rpcMessage = gson.fromJson(msg, RPCSystemProtocol.class);
if (!aclManager.verifyRPCInterfaceCall(rpcMessage)) {//权限控制
rpcMessage.setReturnObject("have no permission");
return;
}
if (!rpcMessage.selfCheck()) {//数据自检
throw new MessageTransportException("RPC包错误");
}
try {
Object instance = RPCregManager.getTarget(rpcMessage);
Object ret = rpcExec.exec(rpcMessage.getClassName(), rpcMessage.getMethodName(), rpcMessage.getParamsType(), instance, rpcMessage.getParameters());//通过反射机制调用响应类的方法执行并得出结果
rpcMessage.setReturnObject(gson.toJson(ret));
if (!watcher.insert(new RPCConnectInfo(gson.toJson(rpcMessage), cha))) {//将需要返回的结果插入发送队列,由于开发RPC时还没有开始设计消息管理中心,所以使用其独立的RPCBufferCallBackWatcher类进行返回数据队列的管理,详见RPCBufferCallBackWatcher
// TODO 打印日志
}
} catch (RPCInterfaceNotFoundException e) {
// TODO 打印日志
e.printStackTrace();
return;
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return;
}
}


rpc client端

客户端进行RPC调用思路:

在配置文件中注册需要使用rpc的bean,通过该bean获取一个实例并使用对应的接口方法,利用spring的特性对该接口方法进行代理,将方法的实现转换成netty通信,把调用方法的参数发送给rpc server,并在rpcLockManager中进行一个注册并阻塞当前方法执行线程,等待server返回结果;当server返回结果后,在rpcLockManager中对等待结果的调用进行解锁并唤醒线程,传入server发过来的结果,再又代理返回方法调用结果。使客户端程序员的编码结构不发生任何改变的情况下实现远程调用。

RPCClient.java

基本上和RCPServer.java类似,不过这里创建的是netty服务端

public void initRPCClient() {
ClientBootstrap bootstrap = new ClientBootstrap(new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
handler = new NettyHandler() {

private Gson gson = new Gson();

@Override
public void onMessageReceived(String msg, Channel cha) throws MessageTransportException {
RPCSystemProtocol rpcMessage = gson.fromJson(msg, RPCSystemProtocol.class);
if (!rpcMessage.selfCheck()) {
throw new MessageTransportException("RPC包错误");
}
// announcer.insert(rpcMessage);
lockManager.AnswerReceived(rpcMessage.uuid, rpcMessage);//接收到服务端回复后将结果返回并将rpc调用解锁

}

@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
channel = e.getChannel();
}
};
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("UP_FRAME_HANDLER", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 2, 0, 2));
pipeline.addLast("DOWN_FRAME_HANDLER", new LengthFieldPrepender(2, false));
// return Channels.pipeline(handler);
pipeline.addLast("myHandler", handler);
return pipeline;
}
});
bootstrap.connect(new InetSocketAddress(address, port));
}


用SpringMethodInterceptor对rpc调用类的实现进行代理

public class SpringMethodInterceptor implements MethodInterceptor {

public Object invoke(MethodInvocation inv) throws Throwable {
System.out.println(inv.getMethod().getDeclaringClass().getName() + " " + inv.getArguments());
String version=rpcProxyRegManager.getVersion(inv.getMethod().getDeclaringClass().getName());
RPCSystemProtocol message=RPCSystemProtocolPackageUtil.getRPCProtocolPackage(inv.getMethod(),inv.getArguments(),version);
rpcClient.sendRPCProtocol(message);//发送调用协议
UUID uuidOrigin=message.uuid;
RPCSystemProtocol recvMessage=lockManager.waitforAnswer(uuidOrigin);//阻塞当前线程,等待rpcServer返回调用结果
Class<?> returnType=inv.getMethod().getReturnType();
return gson.fromJson(recvMessage.getReturnObject(),returnType);

}

}


读卡器部分:

采用netty接收读卡器数据

public void initReaderServer() {
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {

@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("UP_FRAME_HANDLER", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 2, 0, 2));
pipeline.addLast("DOWN_FRAME_HANDLER", new LengthFieldPrepender(2, false));
pipeline.addLast("myHandler", readerNettyHandler);
// return Channels.pipeline(rpcServerNettyHandler);
return pipeline;
}

});
bootstrap.bind(new InetSocketAddress(port));
System.out.println("reader data server开启成功");
}


接收到读卡器数据后的操作如下,详见ReaderDataManager.java

public void OriginalDataDealing(RFIDOriginalInfos infos){
submitData(infos.getInfos());//存入数据库
sendOutDataComingMessage(infos);//发送消息给读卡器模块进行状态定义
}


通过消息中心将接收到的读卡器数据推送给读卡器模块

private void sendOutDataComingMessage(RFIDOriginalInfos infos){
WardenMessage msg=new WardenMessage();
msg.setKind(WardenMessage.KIND_NEW_DATA_COMING+WardenMessage.DIR_ENTER);
String target="";
for (String s:infos.getTargets()){
target+=s+WardenMessage.TARGET_TYPE_READER+"|";
}
msg.setTarget(target);

msg.setNote(gson.toJson(infos.getInfos()));
readerMessageComingPusher.sendOutMessage(msg);
}


由上文设备模块的创建方法可创建读卡器设备模块,详情见Reader.java

public class Reader extends EquipmentObject {

private int targetRFID = 0;
private String targetMessageKind = "";
private String targetKind = "";
private String targetMessageDir = "";

@Override
public void initWarden() {

this.registWarden(new Warden(String.valueOf(this.getRfid()) + WardenMessage.TARGET_TYPE_READER, WardenMessage.KIND_NEW_DATA_COMING + WardenMessage.DIR_ENTER) {

@Override
public void asynchronizedProcess(String message) {
WardenMessage wardenMessage = new WardenMessage();
wardenMessage.setNote(message);
wardenMessage.setTarget(String.valueOf(targetRFID) + targetKind);
wardenMessage.setKind(targetMessageKind + targetMessageDir);
sendOutMessage(wardenMessage);
}

});
}

}


在reader模块中注册了对读卡器新接收到数据的信息的监听
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: