采集项目总结
一、项目简介
本采集系统的基本功能是通过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解析
.....
分享到:
相关推荐
### 基于Flink的风电数据实时采集项目总结 #### 一、项目背景与概述 随着可再生能源的发展,风力发电作为一种清洁且可持续的能源形式,在全球范围内得到了广泛的应用。为了更好地管理和优化风电场的运行效率,实时...
在本风电实时采集项目中,我们利用了先进的大数据处理框架Flink进行实时数据的收集、处理和分析。Flink作为一种强大的流处理和批处理引擎,因其低延迟、高吞吐量以及状态管理能力而在现代大数据解决方案中占据重要...
【基于ARMLinux 视频采集系统项目总结报告】 一、项目概述与市场需求 本项目旨在构建一个基于ARMLinux的视频采集系统,以满足现代信息技术发展的需求。随着后PC时代的到来,传统的视频采集设备(如CCD摄像头和采集...
MES智慧车间项目总结涉及的知识点主要包括MES系统的应用、智慧工厂的实现、生产管理与优化以及信息化在生产中的价值。 MES,即制造执行系统(Manufacturing Execution System),是智能制造和智慧工厂的重要组成...
装配工艺推荐项目和车间数据采集与分析项目 - 项目总结 - 对外学习版V_qyt.pptx
总结,本技术方案详尽规划了一个数据采集处理项目的实施路径,从引言到具体的技术实现,全面覆盖了项目的目标、原则、规范以及关键技术。通过实施该项目,投资商和企业可以充分利用数据资源,提升业务决策的科学性和...
### 装配工艺推荐项目和车间数据采集与分析项目 - 项目总结 #### 一、项目背景与目标 该项目旨在提升企业的装配工艺编制水平,实现工艺数据的有效管理和利用。通过对现有工艺数据进行整理和分析,建立知识数据库,...
### 装配工艺推荐项目和车间数据采集与分析项目知识点总结 #### 一、项目背景及概述 **装配工艺推荐项目**与**车间数据采集与分析项目**旨在提升制造业中的装配工艺效率,并通过数据分析来优化生产流程。项目主要...
总结,这个项目涉及到LabVIEW的声卡接口编程、语音信号处理、实时数据采集和分析等多个方面,通过使用LabVIEW 8.5,我们可以构建一个高效的语音信号处理系统,对声卡采集的语音信号进行详尽的分析。在实际操作中,...
总结,月入10W+的自动采集站项目涉及到的技术和环节众多,包括但不限于爬虫技术、数据处理、网站开发、SEO优化、流量获取以及合法合规运营。要实现该项目的成功,需要深入了解并掌握这些方面,同时不断学习和跟进...
在F列的第二行我们输入以采集模块 采集代码 数仓模块 分析 展示模块 web客户端 通用模块 工具和数据库之间的通用联系客户端下内容:="INSERT INTO student (id,sex,name,age,grade) VALUES ("&A2;&",'"&B2;&"','"&C2...
基于Python网络爬虫的二手房数据采集及可视化分析项目源码+使用教程+爬虫+报告PPT.zip已获导师认可并高分通过的毕业设计项目,代码完整,该资源代码都是经过测试运行成功,没有任何问题功能完整的情况下才上传的,...
在论文的结尾,作者会总结研究过程中的成果和经验,讨论系统可能存在的问题和改进方向。电信采集系统的持续发展将依赖于新技术的应用,例如人工智能和机器学习在数据预测和异常检测中的应用。 通过这篇毕业论文,...
在本案例中,“163K门户采集开源”可能是一个针对163K门户站点的开源采集项目,用户可以利用这个工具进行个性化的数据抓取。 对于"163K门户采集开源",我们可以推测这是一款专门针对163K门户站点设计的网络资源采集...
总结,C#串口数据采集与实时曲线显示是结合硬件通信和图形化界面的关键技术。通过SerialPort类处理串口通信,DataReceived事件监听数据,OxyPlot库绘制曲线,以及File类进行数据存储,我们可以构建出高效、实时的...
本文将详细探讨基于STM32微控制器的双路485总线实验项目,该实验项目主要目的是采集和传输按键次数信息。 项目硬件部分的设计重点在于确保稳定且可靠的485总线通信。为此,我们选择了SP3485作为485收发器,因其能在...
项目总结报告中建议的改进措施包括细化需求变更处理机制、加强内部沟通协作以及对配置管理工具的使用进行专门培训,这些建议都旨在进一步提高项目的执行效率和质量控制水平。 综上所述,EN-C200项目不仅是物联网...
总结,开发NI数据采集卡C++应用涉及安装必要的软件,理解API,编写代码并与硬件交互。通过实践和学习,你可以创建出高效、稳定的数据采集解决方案。在遇到问题时,NI社区和官方文档通常是寻求帮助的好资源。
数据采集卡在现代科技和工业领域中扮演着至关重要的角色,它主要用于...在实际项目中,开发者需要根据具体需求选择合适的数据采集卡,熟练掌握相关API,并结合实际应用优化编程策略,以实现高效、稳定的数据采集系统。