SpringBoot + docker + neo4j 从单一搭建到整合

第一步:创建SpringBoot项目

****对springboot非常了解或是springboot项目已构建完成的可以跳过此步骤直接看第二步***

.系统要求:

1.使用Maven(3.2)以上的版本

2.目前Spring Boot正式版为1.5.1.RELEASE默认情况下,Spring Boot 1.5.1.RELEASE需要Java 7和Spring Framework 4.3.6.RELEASE或更高版本,你也可以使用Spring Boot with Java 6和一些额外的配置(不建议)。推荐使用Java8。

.初始化SpringBoot项目

构建一个Sping Boot的Maven项目,推荐使用Spring官方提供的Spring Initializr 来构建。它不仅完美支持IDEA和Eclipse,而且能自动生成启动类和单元测试代码,给开发人员带来极大的便利!!从本质上来说Spring Initializr就是一个Web应用程序,能为你生成Spring Boot项目结构。

下面说说Spring Initializr的几种用法:

.通过Web界面使用

1.访问:http://start.spring.io/

2.选择构建工具Maven Project、Spring Boot版本1.5.10以及一些工程基本信息(工程基本信息可根据项目实际情况自定义),可参考下图所示

3.点击Generate Project下载项目压缩包

4.导入到你的工程,如果是IDEA,则需要:

a.菜单中选择File–>New–>Project from Existing Sources...**

b.选择解压后的项目文件夹,点击OK

c.点击Import project from external model并选择Maven,点击Next到底为止。

d.若你的环境有多个版本的JDK,注意到选择Java SDK的时候请选择Java 7以上的版本

.通过IntelliJ IDEA使用(个人推荐)

版本要求:IntelliJ IDEA 14.1及以上(IntelliJ IDEA 是在 14.1 开始支持Spring Boot的

创建Spring Boot操作步骤如下:

1.在File菜单里面选择 New > Project,然后选择Spring Initializr,接着如下图一步步操作即可。

.项目结构

根据上面的操作已经初始化了一个Spring Boot的框架了,项目结构如下:

如你所见,项目里面基本没有代码,除了几个空目录外,还包含如下几样东西。

pom.xml:Maven构建说明文件。

SbdnApplication.java:一个带有main()方法的类,用于启动应用程序(关键)。

SbdnApplicationTests.java:一个空的Junit测试类,它加载了一个使用Spring Boot字典配置功能的Spring应用程序上下文。

application.properties:一个空的properties文件,你可以根据需要添加配置属性。

到目前为止一个完整的SpringBoot项目已经搭建完成,其他的一些配置和操作在此就不做过多的说明了,如后续需要再行添加。


第二步:使用docker启动一个neo4j服务

.控制台运行命令,下拉镜像

docker pull neo4j

.启动镜像(-d:以后台模式启动;-p:将容器的端口映射到主机相应的端口)

docker run -d -p 7473:7473 -p 7687:7687 -p 7474:7474 neo4j

.打开浏览器访问 —— http://localhost:7474/browser/

初始的用户名/密码都为:neo4j

第一次登陆时需要修改密码

登陆成功后的页面如下,此时就可以使用neo4j数据库了


第三步:neo4j接入springboot

.在pom中添加依赖
(我有使用lombok,所以有添加依赖,并非neo4j的必须依赖。lombok是一个可以通过简单的注解的形式来帮助我们简化消除一些必须有但显得很臃肿的 Java 代码的工具

    <!-- neo4j依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-neo4j</artifactId>
        </dependency>
        <dependency>
            <groupId>com.voodoodyne.jackson.jsog</groupId>
            <artifactId>jackson-jsog</artifactId>
            <version>1.1.1</version>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>

添加Actor类
(使用lombok后直接用 @Setter和@Getter代替了之前的一大长串的set和get方法的代码)

package com.gtrj.sbdn.neo4jdemo;

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.voodoodyne.jackson.jsog.JSOGGenerator;
import lombok.Getter;
import lombok.Setter;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;


@JsonIdentityInfo(generator = JSOGGenerator.class)
@NodeEntity
@Setter
@Getter
public class Actor {

    @GraphId
    Long id;

    private String name;

    private String born;
}

添加Movie类

package com.gtrj.sbdn.neo4jdemo;

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.voodoodyne.jackson.jsog.JSOGGenerator;
import lombok.Getter;
import lombok.Setter;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.Relationship;

import java.util.ArrayList;
import java.util.List;


@JsonIdentityInfo(generator = JSOGGenerator.class)
@NodeEntity
@Setter
@Getter
public class Movie {

    @GraphId
    Long id;

    String title;

    String year;

    String tagline;

    @Relationship(type = "ACTS_IN",direction = Relationship.INCOMING)
    List<Role> roles = new ArrayList<>();


    public Movie() {
    }

    public Role addRole(Actor actor,  String name){
        Role role = new Role(name, actor, this);
        this.roles.add(role);
        return role;
    }
}

添加Role类

package com.gtrj.sbdn.neo4jdemo;

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.voodoodyne.jackson.jsog.JSOGGenerator;
import lombok.Getter;
import lombok.Setter;
import org.neo4j.ogm.annotation.EndNode;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.RelationshipEntity;
import org.neo4j.ogm.annotation.StartNode;


@JsonIdentityInfo(generator = JSOGGenerator.class)
@RelationshipEntity(type = "ACTS_IN")
@Setter
@Getter
public class Role {

    @GraphId
    Long id;

    String role;

    @StartNode
    Actor actor;

    @EndNode
    Movie movie;


    public Role() {
    }

    public Role(String role, Actor actor, Movie movie) {
        this.role = role;
        this.actor = actor;
        this.movie = movie;
    }
}

添加查询接口MovieRepository

package com.gtrj.sbdn.neo4jdemo;

import org.springframework.data.neo4j.repository.GraphRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

@Repository
public interface MovieRepository extends GraphRepository<Movie> {

    Movie findByTitle(@Param("title") String title);
}

添加自动配置
(也可添加一个@Configuration配置类,这里不做说明)

package com.gtrj.sbdn;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;

//开启自动配置
@EnableNeo4jRepositories
@EnableTransactionManagement

@SpringBootApplication
public class SbdnApplication {

    public static void main(String[] args) {
        SpringApplication.run(SbdnApplication.class, args);
    }
}

在application.properties中添加配置
(注意这里是spring.data.neo4j 不是 spring.datasource)

compiler=org.neo4j.ogm.compiler.MultiStatementCypherCompiler
driver=org.neo4j.ogm.drivers.http.driver.HttpDriver
URI=http://localhost:7474
spring.data.neo4j.username=neo4j
spring.data.neo4j.password=123456

编写单元测试

package com.gtrj.sbdn.neo4jdemo;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;


@RunWith(SpringRunner.class)
@SpringBootTest
public class MovieRepositoryTest {

    private static Logger logger= LoggerFactory.getLogger(MovieRepositoryTest.class);


    @Autowired
    MovieRepository movieRepository;

    @Before
    public void initData(){

        movieRepository.deleteAll();

        Movie matrix1=new Movie();
        matrix1.setTitle("The Matrix");
        matrix1.setYear("1999-03-31");

        Movie matrix2=new Movie();
        matrix2.setTitle("The Matrix Reloaded");
        matrix2.setYear("2003-05-07");

        Movie matrix3=new Movie();
        matrix3.setTitle("The Matrix Revolutions");
        matrix3.setYear("2003-10-27");

        Actor keanu=new Actor();
        keanu.setName("Keanu Reeves");
        keanu.setBorn("1988-10-04");

        Actor laurence=new Actor();
        laurence.setName("Laurence Fishburne");
        laurence.setBorn("1987-05-28");

        Actor carrieanne=new Actor();
        carrieanne.setName("Carrie-Anne Moss");
        carrieanne.setBorn("1976-09-22");


        matrix1.addRole(keanu,"Neo");
        matrix1.addRole(laurence,"Morpheus");
        matrix1.addRole(carrieanne,"Trinity");
        movieRepository.save(matrix1);
        Assert.assertNotNull(matrix1.getId());

        matrix2.addRole(keanu,"Neo");
        matrix2.addRole(laurence,"Morpheus");
        matrix2.addRole(carrieanne,"Trinity");
        movieRepository.save(matrix2);
        Assert.assertNotNull(matrix2.getId());

        matrix3.addRole(keanu,"Neo");
        matrix3.addRole(laurence,"Morpheus");
        matrix3.addRole(carrieanne,"Trinity");
        movieRepository.save(matrix3);
        Assert.assertNotNull(matrix3.getId());
    }

    @Test
    public void findByTitle() throws Exception {
        Movie movie=movieRepository.findByTitle("The Matrix");
        Assert.assertNotNull(movie);
        logger.info("===movie===movie:{},{}",movie.getTitle(),movie.getYear());
        for(Role role:movie.getRoles()){
            logger.info("=====actor:{},role:{}",role.getActor().getName(),role.getRole());
        }
    }
}

测试运行结果


打开浏览器访问---http://localhost:7474/

查看节点信息图
Actor-Node

Movie-Node

查看关系类型图

注:测试的数据来自网络


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容