近期由于工作需要,需要做一个人口关系大图的存储及检索方案,我们主要的数据对象有:人口(年龄,身份证号码,性别。。) ;学校信息(学校地址,学校名称,学校级别,学校下边的年级班级。。);就职信息(公司名称,公司地址,公司企业信用代码。。)以及论文发布信息(论文主题,参与人,发布时间)

问题思考:

  1. 针对这类人口关系大图,或者叫图谱的数据一般都是非关系型,而且有多钟关系的存在,比如张三跟李四两个人,可能是同学,同事,老乡,配偶,夫妻,等多种关系,那一般如果采取关系型数据库(oracle)为例,可能就需要建立人员信息表, 同学关系表,同事关系表,老乡关系表,配偶关系表,夫妻关系表,这样一旦后续增加一个关系,就要增加一张表,增加一张表,而且后续数据库中就基本上只剩关系表了,后续的维护,扩充,代码的修改就机器的困难,简直就是噩梦。
  2. 通过上述的第一点,我们不难看出,采用关系型数据库来存储并不是最好的解决方案,那么就很容易想到采用关系型数据库存,那么目前比较流行的有哪些非关系型数据库么,redis,mongoDB,neo4j都能存储单个菲关系型的数据,但他们三者还是有区别的,前两者一般在项目中作为一个数据缓存的容器,将一些不经常变化的数据放在容器中,需者自取。而neoj4j专门用于网络图的存储,网络图,这个跟我们的项目需求不是不谋而合?于是心底暗自拍板,就你了 ,neo4j。

数据库设计:

通过关系表中存储的ID来进行关联;注意设置的时候是将与一个人所有关联的信息进行抽象出来并划分为五个对象,即上图的五个表单。 通过上图我们可以和明确的看出来有如下几种关系: 人 -就读->学校;

人 -发布论文->论文; 人-就职->企业; 人-居住->家庭;这四类的外部关系(以单个人节点为参照),另外一方面,人根根之间也是存在关系的,比如刚开始提到的同事,同学类的,那么这类属于内部关系,内部关系我们一般需要通过外部关系区分,比如张三和李四只有在同一个班级上学,那么菜算得上同学吧,只有在同一个公司就职才算得上同事吧.。这样的话,我们数据库设计出来,逻辑也梳理出来,尤其是内部关系外部关系。

实现方案:

我项目采用的是spring+springMvc的环境。

组件代码:

注意我是将neo4j的配置及实体放在一块的,至于其他的逻辑操作在其他的包中。

部分代码:

设置Configuration属性到neo4j中
package com.audaque.module.graphData.neo4j.config;

import org.neo4j.ogm.session.Session;
import org.neo4j.ogm.session.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.*;
import org.springframework.data.neo4j.config.Neo4jConfiguration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement; /***
*@ClassName AppConfiguration
*@desc TODO
*@Author xxxxxx
*@Date 2019/5/17 0017 下午 10:57
*@version 1.0.1
**/
@Configuration
@EnableNeo4jRepositories(basePackages = "com.audaque.module.graphData.neo4j.repos")
@EnableTransactionManagement
@ComponentScan("com.audaque.module.graphData.neo4j.config")
public class AppConfiguration extends Neo4jConfiguration {
@Autowired
private org.neo4j.ogm.config.Configuration config; @Bean
public org.neo4j.ogm.config.Configuration getConfiguration() {
return config;
}
@Override
@Bean
public SessionFactory getSessionFactory() {
// with domain entity base package(s)
return new SessionFactory(config,"com.audaque.module.graphData.neo4j.model");
}
@Override
@Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Session getSession() throws Exception {
return super.getSession();
}
}

  

动态设置属性到Configuration中属性到中
package com.audaque.module.graphData.neo4j.config;

import org.neo4j.ogm.authentication.UsernamePasswordCredentials;
import org.neo4j.ogm.config.Configuration; import static org.neo4j.ogm.config.DriverConfiguration.CREDENTIALS;
import static org.neo4j.ogm.config.DriverConfiguration.DRIVER;
import static org.neo4j.ogm.config.DriverConfiguration.URI; /***
*@ClassName MyConfiguration
*@desc 自定义bean动态配置neo4j数据源。
*@Author xiaokang.ma@audaque.com
*@Date 2019/5/24 9:14
*@version 1.0.1
**/
public class MyConfiguration extends Configuration {
public MyConfiguration(String driverClass,String driverURL,String userName,String password){
super.set(DRIVER[0],driverClass);
super.set(URI[0],driverURL);
super.set(CREDENTIALS[0],new UsernamePasswordCredentials(userName, password)); } }
PaperInfoRepository配置(实体的保存):
package com.audaque.module.graphData.neo4j.repos;

import com.audaque.module.graphData.neo4j.model.PaperInfo;
import org.springframework.data.neo4j.repository.GraphRepository;
import org.springframework.stereotype.Repository; /***
*@ClassName PaperInfoRepository
*@desc 论文信息接口
*@Author xxxx
*@Date 2019/5/17 0017 下午 5:43
*@version 1.0.1
**/
@Repository
public interface PaperInfoRepository extends GraphRepository<PaperInfo> { }

内部关系的Repository我采用的自定义查询语句查询,如下:

package com.audaque.module.graphData.neo4j.repos;

import com.audaque.module.graphData.neo4j.model.Neo4jRelationInfo;
import org.neo4j.consistency.store.paging.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.GraphRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository; import java.util.Collection;
import java.util.List;
import java.util.Map; /***
*@ClassName Neo4jRelationInfoRepository
*@desc 八大关系型数据。
*@Author xxxx
*@Date 2019/5/17 0017 下午 5:43
*@version 1.0.1
**/
@Repository
public interface Neo4jRelationInfoRepository extends GraphRepository<Neo4jRelationInfo> { /**
* pe - pe 邻居关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:pe) where a.ids={fromId} and b.ids={toId} merge (a) - [r:邻居{direction:{direction}}]->(b)")
Neo4jRelationInfo generateGraphDataRelation_LJ(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* pe -> pe 同学关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:pe) where a.ids={fromId} and b.ids={toId} merge (a) - [r:同学{direction:{direction}}]->(b)")
Neo4jRelationInfo generateGraphDataRelation_TX(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* pe -> pe 校友关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:pe) where a.ids={fromId} and b.ids={toId} merge (a) <- [r:校友{direction:{direction}}]->(b)")
Neo4jRelationInfo generateGraphDataRelation_XY(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* pe -> li 居住关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:li) where a.ids={fromId} and b.ids={toId} merge (a) - [r:居住{direction:{direction}}]->(b)")
Neo4jRelationInfo generateGraphDataRelation_JUZ(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* pe -> pe 同事关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:pe) where a.ids={fromId} and b.ids={toId} merge (a) - [r:同事{direction:{direction}}]-(b)")
Neo4jRelationInfo generateGraphDataRelation_TS(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* pe -> wu 就职关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:wu) where a.ids={fromId} and b.ids={toId} merge (a) - [r:就职{direction:{direction}}]->(b)")
Neo4jRelationInfo generateGraphDataRelation_JZGX(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* pe -> sc 毕业院校关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:sc) where a.ids={fromId} and b.ids={toId} merge (a) - [r:毕业{direction:{direction}}]->(b)")
Neo4jRelationInfo generateGraphDataRelation_BYYX(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* pe -> pa 论文参与关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:pa) where a.ids={fromId} and b.ids={toId} merge (a) - [r:参与者{direction:{direction}}]->(b)")
Neo4jRelationInfo generateGraphDataRelation_PA(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* pe -> pa 论文合作关系
* @param fromId
* @param toId
* @return
*/
@Query(value = "match(a:pe),(b:pe) where a.ids={fromId} and b.ids={toId} merge (a) - [r:论文合作{direction:{direction}}]->(b)")
Neo4jRelationInfo generateGraphDataRelation_LWHZ(@Param("fromId") String fromId, @Param("toId") String toId, @Param("direction") String direction); /**
* web查询接口,查询与当前节点为1的数据---根据节点编号,适用于登录第二次节点点击之后的查询
*/
@Query(value = "match(a)-[r]-(b) where a.ids={qid} return a,r,b")
List<Map<String,String>> queryRelationDataByIds(@Param("qid") String qid); /**
* web查询接口,查询与当前节点为1的数据
*/
@Query(value = "match(a:pe)-[r]-(b) where a.cardNo={cardNo} return a,r,b")
List<Map<String,String>> queryRelationDataByCardNo(@Param("cardNo") String cardNo); }

bean配置:

<!--初始化配置的Config-->
<bean id="myConfiguration" class="com.audaque.module.graphData.neo4j.config.MyConfiguration">
<constructor-arg name="driverClass" value="org.neo4j.ogm.drivers.http.driver.HttpDriver" index="0" type="java.lang.String"/>
<constructor-arg name="driverURL" value="http://10.229.183.142:7474" index="1" type="java.lang.String"/>
<constructor-arg name="userName" value="neo4j" index="2" type="java.lang.String"/>
<constructor-arg name="password" value="123456" index="3" type="java.lang.String"/>
</bean>

通过上述的简单配置就在spring环境中搭建到了neo4j。

业务逻辑代码:

  1. 存储所有的节点,直接读取数据中的人员信息,学校信息,居住信息,教育信息,工作信息,5张表的数据直接save到neo4j,部分代码如下.

  

 /**
* 初始化图数据需要的人员节点数据
*
* @param personBaseInfoRepository
* @return
*/
@Override
public void resetNeo4jPersonBaseInfoNode(PersonBaseInfoRepository personBaseInfoRepository) {
//查询人员节点列表
List<PersonBaseInfo> personBaseInfos = graphDataDao.queryPersonBaseInfo(); for (PersonBaseInfo personBaseInfo :personBaseInfos){
try {
personBaseInfoRepository.save(personBaseInfo);
}
catch (Throwable t){
//生成节点异常时,继续跳过。
continue;
}
}
}

初始化内部外部关心数据,代码如下:

 /********************************************开始初始化节点间关系的数据**********************************************/

    /**
* 初始化五大节点间的关系数据。
* @param neo4jRelationInfoRepository
* @return
*/
@Override
public void resetAllRelationInfo(Neo4jRelationInfoRepository neo4jRelationInfoRepository) {
long start = System.currentTimeMillis();
//初始化人员-->工作关系,人员->学校;人员->论文;人员->住房信息4个主关系的数据。
List<Map<String,Object>> lists = graphDataDao.queryEntityRelationInfo();
//计算内部关系信息 ,同事,校友,邻居,合作者关系。
Map<String,List<String>> schoolFriendMap = new ConcurrentHashMap<>(); //校友 Map<String,List<String>> workTogetherMap = new ConcurrentHashMap<>(); //同事 Map<String,List<String>> neighborMap = new ConcurrentHashMap<>(); //邻居
Map<String,List<String>> collaboratorMap = new ConcurrentHashMap<>();//论文合作者
for(Map<String,Object> map :lists){ String userId = "";
//获取人员信息
if(StringUtils.isNoneEmpty((String)map.get("USERID")) && StringUtils.isNoneEmpty((String)map.get("USERNAME"))){
//取工作单位字段 UNIT_ID , UNIT_NAME
if(StringUtils.isNoneEmpty((String)map.get("UNIT_ID")) && StringUtils.isNoneEmpty((String)map.get("UNIT_NAME"))){
//插入就职关系
neo4jRelationInfoRepository.generateGraphDataRelation_JZGX((String)map.get("USERID"),(String)map.get("UNIT_ID"),(String)map.get("USERID")+"->"+(String)map.get("UNIT_ID")); //处理同事关系
if(workTogetherMap.containsKey((String)map.get("UNIT_ID"))){
List<String> list = workTogetherMap.get((String)map.get("UNIT_ID"));
if(!list.contains((String)map.get("USERID"))){
list.add((String)map.get("USERID"));
workTogetherMap.put((String)map.get("UNIT_ID"),list);
}
}else{
List<String> lis = new ArrayList<String>();
lis.add((String)map.get("USERID"));
workTogetherMap.put((String)map.get("UNIT_ID"),lis);
} }
//取学校字段 SCHOOL_ID , SCHOOL_NAME
if(StringUtils.isNoneEmpty((String)map.get("SCHOOL_ID")) && StringUtils.isNoneEmpty((String)map.get("SCHOOL_NAME"))){
//插入毕业院校
neo4jRelationInfoRepository.generateGraphDataRelation_BYYX((String)map.get("USERID"),(String)map.get("SCHOOL_ID"),(String)map.get("USERID")+"->"+(String)map.get("SCHOOL_ID")); //处理校友关系
if(schoolFriendMap.containsKey((String)map.get("SCHOOL_ID"))){
List<String> list = schoolFriendMap.get((String)map.get("SCHOOL_ID"));
if(!list.contains((String)map.get("USERID"))){
list.add((String)map.get("USERID"));
schoolFriendMap.put(this.schoolFriend,list);
}
}else{
List<String> lis = new ArrayList<String>();
lis.add((String)map.get("USERID"));
schoolFriendMap.put((String)map.get("SCHOOL_ID"),lis);
} } //取住房信息字段 HOUSE_ID , HOUSE_ADDR
if(StringUtils.isNoneEmpty((String)map.get("HOUSE_ID")) && StringUtils.isNoneEmpty((String)map.get("HOUSE_ADDR"))){
//插入毕业院校
neo4jRelationInfoRepository.generateGraphDataRelation_JUZ((String)map.get("USERID"),(String)map.get("HOUSE_ID"),(String)map.get("USERID")+"->"+(String)map.get("HOUSE_ID")); //处理邻居关系
if(neighborMap.containsKey((String)map.get("HOUSE_ID"))){
List<String> list = neighborMap.get((String)map.get("HOUSE_ID"));
if(!list.contains((String)map.get("USERID"))){
list.add((String)map.get("USERID"));
neighborMap.put((String)map.get("HOUSE_ID"),list);
}
}else{
List<String> lis = new ArrayList<String>();
lis.add((String)map.get("USERID"));
neighborMap.put((String)map.get("HOUSE_ID"),lis);
}
}
//取论文信息字段 LW_ID , LW_TITLE
if(StringUtils.isNoneEmpty((String)map.get("LW_ID")) && StringUtils.isNoneEmpty((String)map.get("LW_TITLE"))){
//插入毕业院校
neo4jRelationInfoRepository.generateGraphDataRelation_PA((String)map.get("USERID"),(String)map.get("LW_ID"),(String)map.get("USERID")+"->"+(String)map.get("LW_ID"));
//处理合作者关系
if(collaboratorMap.containsKey((String)map.get("LW_ID"))){
List<String> list = collaboratorMap.get((String)map.get("LW_ID"));
if(!list.contains((String)map.get("USERID"))){
list.add((String)map.get("USERID"));
collaboratorMap.put((String)map.get("LW_ID"),list);
}
}else{
List<String> lis = new ArrayList<String>();
lis.add((String)map.get("USERID"));
collaboratorMap.put((String)map.get("LW_ID"),lis);
}
} }
} //开始剔除长度为1的数据,没有对应的关系。
schoolFriendMap.forEach((key,value) -> {
//独立个体无法形成关系,剔除
if(((List<String>)value).size()<=1){
schoolFriendMap.remove(key);
}
});
workTogetherMap.forEach((key,value) -> {
//独立个体无法形成关系,剔除
if(((List<String>)value).size()<=1){
workTogetherMap.remove(key);
}
});
neighborMap.forEach((key,value) -> {
//独立个体无法形成关系,剔除
if(((List<String>)value).size()<=1){
neighborMap.remove(key);
}
});
collaboratorMap.forEach((key,value) -> {
//独立个体无法形成关系,剔除
if(((List<String>)value).size()<=1){
collaboratorMap.remove(key);
}
}); //开始遍历校友关系数据,生成节点。
schoolFriendMap.forEach((key,value) -> {
List<String> li = (List<String>)value;
for(int st = 0;st<li.size() ; st++){
for(int ss = li.size()-1;ss>st;ss--){
System.out.println("生成关系"+li.get(st)+"->"+li.get(ss));
neo4jRelationInfoRepository.generateGraphDataRelation_XY(li.get(st),li.get(ss),"<->"); }
}
});
//同事关系
workTogetherMap.forEach((key,value) -> {
List<String> li = (List<String>)value;
for(int st = 0;st<li.size() ; st++){
for(int ss = li.size()-1;ss>st;ss--){
System.out.println("生成关系"+li.get(st)+"->"+li.get(ss));
neo4jRelationInfoRepository.generateGraphDataRelation_TS(li.get(st),li.get(ss),"<->"); }
}
});
//邻居关系
neighborMap.forEach((key,value) -> {
List<String> li = (List<String>)value;
for(int st = 0;st<li.size() ; st++){
for(int ss = li.size()-1;ss>st;ss--){
System.out.println("生成关系"+li.get(st)+"->"+li.get(ss));
neo4jRelationInfoRepository.generateGraphDataRelation_LJ(li.get(st),li.get(ss),"<->"); }
}
});
//合作者关系
collaboratorMap.forEach((key,value) -> {
List<String> li = (List<String>)value;
for(int st = 0;st<li.size() ; st++){
for(int ss = li.size()-1;ss>st;ss--){
System.out.println("生成关系"+li.get(st)+"->"+li.get(ss));
neo4jRelationInfoRepository.generateGraphDataRelation_LWHZ(li.get(st),li.get(ss),"<->"); }
}
});
System.out.println("总共花费时间:" + (System.currentTimeMillis() - start) + "ms"); }

然后Control中对外暴露三个接口, 1.初始化节点,  2.初始化关系。 就可以了。

然后通过浏览器直接可以看到图数据的结构,分享下我做出来的效果。

至此一个从数据库存入到neo4j数据库中,然后可以对外开放一个查询的接口,返回与之有关系并且深度为1的数据,方便其他系统展示,接口如下:

/**
* web查询接口,查询与当前节点为1的数据---根据节点编号,适用于登录第二次节点点击之后的查询。
*/
@Query(value = "match(a)-[r]-(b) where a.ids={qid} return a,r,b")
List<Map<String,String>> queryRelationDataByIds(@Param("qid") String qid); /**
* web查询接口,用户登录之后第一次查询,需根据身份证号码查询。第二次查询就直接会调用上一个查询。
*/
@Query(value = "match(a:pe)-[r]-(b) where a.cardNo={cardNo} return a,r,b")
List<Map<String,String>> queryRelationDataByCardNo(@Param("cardNo") String cardNo);

基于neo4j图数据库,实现人口关系大图的基本思路及实现方案。的更多相关文章

  1. Neo4j图数据库管理系统开发笔记之一:Neo4j Java 工具包

    1 应用开发概述 基于数据传输效率以及接口自定义等特殊性需求,我们暂时放弃使用Neo4j服务器版本,而是在Neo4j嵌入式版本的基础上进行一些封装性的开发.封装的重点,是解决Neo4j嵌入式版本Emb ...

  2. Neo4j图数据库从入门到精通

    目录 第一章:介绍 Neo4j是什么 Neo4j的特点 Neo4j的优点 第二章:安装 1.环境 2.下载 3.开启远程访问 4.启动 第三章:CQL 1.CQL简介 2.Neo4j CQL命令/条款 ...

  3. Neo4j图数据库从入门到精通(转)

    add by zhj: 转载时,目录没整理好,还会跳转到原文 其实RDB也可以存储多对多的关系,使用的是中间表,GDB使用的是边,RDB中的实体存储在数据表,而GDB存储在节点.两者使用的底层技术不同 ...

  4. 使用neo4j图数据库的import工具导入数据 -方法和注意事项

    背景 最近我在尝试存储知识图谱的过程中,接触到了Neo4j图数据库,这里我摘取了一段Neo4j的简介: Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中.它是一个嵌 ...

  5. Neo4j资料 Neo4j教程 Neo4j视频教程 Neo4j 图数据库视频教程

    课程发布地址 地址: 腾讯课堂<Neo4j 图数据库视频教程> https://ke.qq.com/course/327374?tuin=442d3e14 作者 庞国明,<Neo4j ...

  6. Neo4j视频教程 Neo4j 图数据库视频教程

    课程名称 课程发布地址 地址: 腾讯课堂<Neo4j 图数据库视频教程> https://ke.qq.com/course/327374?tuin=442d3e14 作者 庞国明,< ...

  7. Ubuntu16.04下Neo4j图数据库官网安装部署步骤(图文详解)(博主推荐)

    不多说,直接上干货! 说在前面的话  首先,查看下你的操作系统的版本. root@zhouls-virtual-machine:~# cat /etc/issue Ubuntu LTS \n \l r ...

  8. Ubuntu14.04下Neo4j图数据库官网安装部署步骤(图文详解)(博主推荐)

    不多说,直接上干货! 说在前面的话  首先,查看下你的操作系统的版本. root@zhouls-virtual-machine:~# cat /etc/issue Ubuntu 14.04.4 LTS ...

  9. Neo4j教程 Neo4j视频教程 Neo4j 图数据库视频教程

    课程发布地址 地址: 腾讯课堂<Neo4j 图数据库视频教程> https://ke.qq.com/course/327374?tuin=442d3e14 作者 庞国明,<Neo4j ...

随机推荐

  1. android 开发-Toast控件的实现

    Toast吐司: Toast内容简单,不做过多介绍,Toast支持自带简单吐司,自定义吐司.内容简单可见代码,详见API.A toast provides simple feedback about ...

  2. PHP面向对象编程一

    php面向对象编程(一)   类与对象关系: 类就像一个人类的群体 我们从类中实例化一个对象 就像是制定一个人. 面向对象程序的单位就是对象,但对象又是通过类的实例化出来的,所以我们首先要做的就是如何 ...

  3. FFmpeg编译i386 OSX 脚本

    话不多说, 直接上脚本 #!/bin/sh # directories PLATFORM="OSX" # FFmpeg脚本目录 SOURCE="ffmpeg-2.8.7& ...

  4. C# 的两种debug 方法

    第一种:需要把调试方法改成debug代码用 #if DEBUG 包裹 using System; using System.Collections.Generic; using System.Text ...

  5. Intellij IDEA 最头大的问题,如何自定义注释模板?

    想栈长我当初从 Eclipse 转用 IDEA 真是纠结,放弃然后尝试了N次,不过现在已经算是转型成功了,可以完全脱离 Eclipse 撸码了,虽然说我现在真的撸得非常少了.. 说到 IDEA 的痛点 ...

  6. Android——dpi相关知识总结

    1.术语和概念 术语 说明 备注 Screen size(屏幕尺寸) 指的是手机实际的物理尺寸,比如常用的2.8英寸,3.2英寸,3.5英寸,3.7英寸...... nexus4手机是4.7英寸 As ...

  7. 关闭VAX的拼写检查_解决中文红色警告问题

    菜单VAssistX->Visual Assistant X Options->Advanced->Underlines下 取消“Underline spelling errors  ...

  8. 合理设置apache的最大连接数

    手头有一个网站在线人数增多,访问时很慢.初步认为是服务器资源不足了,但经反复测试,一旦连接上,不断点击同一个页面上不同的链接,都能迅速打开,这种现象就是说明apache最大连接数已经满了,新的访客只能 ...

  9. spring 中使用quartz实现定时任务

    一般开发系统,使用定时任务非常常见.当然也可以用Java实现.比如定时器.大致如下: 1: public static void main(String[] args) { 2: Timer time ...

  10. matplotlib学习之(四)设置线条颜色、形状

    本文是学习<matplotlib for python developers>的一点笔记plot画图时可以设定线条参数.包括:颜色.线型.标记风格.1)控制颜色颜色之间的对应关系为b--- ...