采集项目总结
一、项目简介
本采集系统的基本功能是通过TCP/IP协议长连接基站,将基站上传的字节流根据协议解析为相应的基站和定位卡信息,过滤后进行持久化,提供访问页面供用户查询定位信息;用户可通过采集系统须对基站、位置、卡等相关实体进行管理。
系统用户分为两类,应用系统用户和管理员。
二、项目架构图
三、Ehcache在项目中的应用
Ehcache缓存数据,在Mina handler类中收到卡定位信息后直接放到缓存中,不直接与数据库交互,与数据库的交互放在缓存监听器类中。这里有一个问题是ehcache与Spring 的整合中没有提供缓存与监听器的绑定。只能手工实现,例:
A、
<cache name="alarmrecordCache" maxElementsInMemory="200"
eternal="false"
timeToIdleSeconds="30" overflowToDisk="false"
memoryStoreEvictionPolicy="LFU">
<cacheEventListenerFactory
class="com.**.listener.CacheEventListenerFactory"
properties="bean=alarmRecordListener"/>
</cache>
B、
<bean id="alarmRecordListener"
class="com.**.listener.AlarmRecordListener" lazy-init="false">
<property name="alarminfoService" ref="alarminfoService">
</property>
</bean>
C、
public class CacheEventListenerFactory extends
net.sf.ehcache.event.CacheEventListenerFactory{
@Override
public CacheEventListener createCacheEventListene (Properties properties) {
String beanName = properties.getProperty( "bean" );
if ( beanName == null ) {
throw new IllegalArgumentException( "缓存监听器名字未定义" );
}
return (CacheEventListener)
SpringContextTool.getApplicationContext().getBean( beanName );
}
}
四、基站分2种:小区与CDMA ,小区基站有固定ip ,CDMA基站无固定ip,通过发送消息通过sim卡->移动->互联网,所以CDMA的ip地址是变动的。业务中有要求给CDMA下发指令,因为没有固定ip ,所以只能广播。这样就有一个问题,广播时会有很多“远程主机已经关闭”错误,因为该ip的连接已经没有了。
解决:将所有下发的命令先存放在一个HashMap(Integer,List),integer 为基站编号,List 中存放命令,命令可能有多条。当CDMA基站向服务器发送信息,SessionOpened 时间中增加代码:根据基站编号查询命令并下发。即:CDMA打开连接时下发命令,基本上这个时候连接还在的。
A、
public class CdmaSendCommandSupport {
/**
* 数据存放格式 integer -> 基站号 List<AbstractCommond> -> 命令LIST
*/
public static HashMap<Integer, List<AbstractCommond>> cdmaCommandMap = new HashMap<Integer, List<AbstractCommond>>();
/**
* 把命令放到 Map 中去
*/
public static void putCommandToQueue(int readerid, AbstractCommond c) {
if (readerid == 0) {
ApplicationContext appContext = SpringContextTool.getApplicationContext();
ReaderService readerService = (ReaderService) appContext.getBean("readerService");
@SuppressWarnings("rawtypes")
List idList = readerService.loadAllCdmaReaderid();
for (int i = 0; i < idList.size(); i++) {
List<AbstractCommond> cList = CdmaSendCommandSupport.cdmaCommandMap
.get((Integer) idList.get(i));
if (cList == null) {
cList = new ArrayList<AbstractCommond>();
}
cList.add(c);
CdmaSendCommandSupport.cdmaCommandMap.put((Integer) idList.get(i), cList);
}
} else {
List<AbstractCommond> cList = CdmaSendCommandSupport.cdmaCommandMap
.get(new Integer(readerid));
if (cList == null) {
cList = new ArrayList<AbstractCommond>();
}
cList.add(c);
CdmaSendCommandSupport.cdmaCommandMap.put(new Integer(readerid),cList);
}
}
}
B、
// 1、处理未发送的命令
List<AbstractCommond> cList = CdmaSendCommandSupport.cdmaCommandMap
.get(readerState.getReaderId());
if (cList != null) {
for (AbstractCommond c : cList)
session.write(c);
CdmaSendCommandSupport.cdmaCommandMap.remove(readerState
.getReaderId());
}
五、枚举的应用
业务中遇到这样的问题,卡的类型,基站的类型,报警的类型都是使用的固定值,程序中要定义常量,数据库中也存在记录。容易造成不一致,最后采用了枚举,hibernate中有一个UserType接口用用来自定义与数据库的映射,注意这样修改后,相关的前台显示与查询均要修改。
public class EnumUserType<E extends Enum<E>> implements UserType {
private static final int[] sqlTypes = {Types.INTEGER };
private Class<E> clazz = null;
protected EnumUserType(Class<E> c) {
clazz = c;
if(!clazz.isEnum()){//检查是否是枚举类
throw new IllegalArgumentException(c+"不是枚举类");
}
if(!Identifiable.class.isAssignableFrom(clazz)){//检查是否实现Identifiable接口
throw new IllegalArgumentException(c+"未实现Identifiable接口");
}
}
@Override
public int[] sqlTypes() {
return sqlTypes;
}
@Override
public Class<E> returnedClass() {
return clazz;
}
@Override
public boolean equals(Object x, Object y){
if (x == y)
return true;
if (x == null || y == null)
return false;
else
return x.equals(y);
}
@Override
public int hashCode(Object x) {
return x.hashCode();
}
/**
* 把数据库中的查询结果集转换成相应的枚举类
*/
@Override
public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
throws HibernateException, SQLException {
int id = rs.getInt(names[0]);
Object result = null;
if (!rs.wasNull())
result = getEnumByID(id);
return result;
}
/**
* 私有方法,配合Identifiable接口通过ID返回相应的枚举值
*/
private E getEnumByID(int id) {
E[] values = clazz.getEnumConstants();
E type = null;
for(E t : values){
if(id==((Identifiable)t).getID()){
type = t;
break;
}
}
if(type==null){
throw new HibernateException("ID为"+id+"的枚举类"+clazz.getName()+"不存在");
}
return type;
}
/**
* 配合Identifiable接口将枚举值转成int类型以存入数据库
*/
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index)
throws HibernateException, SQLException {
if (null == value)
st.setNull(index, Types.INTEGER);
else
st.setInt(index, ((Identifiable) value).getID());//必须实现Identifiable接口
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
@Override
public Object assemble(Serializable cached, Object owner)
throws HibernateException {
return cached;
}
@Override
public Object replace(Object original, Object targer, Object owner)
throws HibernateException {
return original;
}
六、帮助类的应用
使用帮助类能更好的减低程序的耦合, 并且这些帮助类和方法一般定义为static,能减少内存占用,但是帮助类中经常会需要用到其他类,直接声明显然不太好。Spring有获取上下文,进而获取bean的方法。正好能用。
A、/**
* 持有Spring上下文
*/
public class SpringContextTool implements ApplicationContextAware {
private static ApplicationContext context;
public void setApplicationContext(ApplicationContext acx) {
context = acx;
}
public static ApplicationContext getApplicationContext() {
return context;
}
}
B、<bean name="springContextTool" class="com.yixun.middleware.util.SpringContextTool" lazy-init="false"></bean>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="springContextTool">
<property name="location">
<value>classpath:system.properties</value>
</property>
</bean>
C、public static NioSocketAcceptor getNioSocketAcceptor() {
ApplicationContext context = SpringContextTool.getApplicationContext();
return (NioSocketAcceptor) context.getBean("areaNioAcceptor");
}
七、关于Mina解析
.....
分享到:
相关推荐
风电实时采集项目总结,很不错的资料,带实际开发的代码及设计。
本文档讲述了集群的搭建步骤,flume的安装及配置,kafka集群配置,flink集群配置、hbase的安装、opentsdb数据库的安装以及各个组件的连接运行可视化
基于STM32的采集按键次数的双路485总线实验项目总结.docx 基于STM32的采集按键次数的双路485总线实验项目总结.docx 基于STM32的采集按键次数的双路485总线实验项目总结.docx 基于STM32的采集按键次数的双路485总线...
seatunnel 2.1.3版本bin包
基于ARMLinux 视频采集系统项目总结报告.doc
装配工艺推荐项目和车间数据采集与分析项目 - 项目总结qy.pptx
在F列的第二行我们输入以采集模块 采集代码 数仓模块 分析 展示模块 web客户端 通用模块 工具和数据库之间的通用联系客户端下内容:="INSERT INTO student (id,sex,name,age,grade) VALUES ("&A2;&",'"&B2;&"','"&C2...
传输综合网管和c、g网网管系统被交接给子公司已越半年。随着子公司业务和维护能力增强,发现...这里结合近期项目实际工作,总结相关经验以抛砖引玉,和各位同事分享交流一下网管系统后台采集框架搭建的架构设计经验。
标准SK信息采集程序,是我研究很久的总结!
本资源是基于MATLAB的信号(包括声音和图像)的采集、分析与处理的程序和报告,里面有详细地项目使用说明书和项目总结报告,可以便于读者下载后查看,有个总体的了解,希望下载后的资源对您能有一定的帮助,本资源为...
。。。
C#采集新浪博客文章 这个都是本人收藏了3年的资源 现放出 都是总结了很多系统 软件项目实施过程中的经验的 慢慢积累的
Alexa流量信息自动采集器 这个都是本人收藏了3年的资源 现放出 都是总结了很多系统 软件项目实施过程中的经验的 慢慢积累的
本人从零基础开始做zigbee实验,总结出来的一点入门级经验,希望能给大家帮助!如果觉得满意,也可以线上单独交流,共同学习~
4.1数据采集模块 10 4.2数据库模块 15 4.3 Swing界面模块 17 五.模块层次图 20 六.技术报告 21 6.1 结果演示 21 6.2 项目中遇到的问题 25 七.实验总结 25 7.1 项目的缺陷 25 7.2 实验心得 26
1.1 项目背景 1 1.2 国内外发展状况和存在问题 2 第二章 系统的可行性分析 3 2.1 数据采集系统的概念 3 2.2 目前正在使用的系统 3 2.3 新系统的逻辑模型 4 2.4 设计新系统的可行方法 4 第三章 通信网络设备 6 3.1...
本作品着眼于实际需要,采集大棚数据并进行自动控制,使大棚状态维持在恒定的范围之内。并且加入了无线传输模块,实现了数据的远距离传输与状态的远距离控制,有利于形成网络。
人工智能-项目实践-可视化-基于Python的南京二手房数据采集及可视化分析 首先通过爬虫采集链家网上所有南京二手房的房源数据,并对采集到的数据进行清洗;然后,对清洗后的数据进行可视化分析,探索隐藏在大量数据...
基于现有资料,通过在实际项目中的积累,我总结出来一套结合opencv和mfc的摄像头采集框架。具有以下特点: 1、基于directshow,兼容性好,速度快。到目前为止,无论是工业相机还是普通相机,没发现不兼容的; 2、...