Mkyong 中文博客翻译(五十四)

原文:Mkyong

协议:CC BY-NC-SA 4.0

Spring Boot WebFlux +服务器发送的事件示例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/spring-boot/spring-boot-webflux-server-sent-events-example/

在本文中,我们将向您展示如何使用服务器发送的事件开发一个反应式 web 应用程序

  • Spring Boot 2.1.2 .版本
  • Spring WebFlux 5.1.4 .发行版
  • 百里香叶
  • JUnit 5.3.2
  • maven3

在 Spring 中,返回 JSON 和 header MediaType.TEXT_EVENT_STREAM_VALUE

 @RestController
public class CommentController {
    
    

    @GetMapping(path = "/comment/stream", 
		produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<Comment> feed() {
    
    
        //...
    }

} 

在 Javascript 中,使用EventSource向上述端点发送请求。

 function loadComments () {
    
    

    this.source = null;

    this.start = function () {
    
    

        this.source = new EventSource("/comment/stream");

        this.source.addEventListener("message", function (event) {
    
    

            var comment = JSON.parse(event.data);

            //... update somewhere

        });

        this.source.onerror = function () {
    
    
            this.close();
        };

    };

    this.stop = function() {
    
    
        this.source.close();
    }

}

comment = new loadComments();

window.onload = function() {
    
    
    comment.start();
};
window.onbeforeunload = function() {
    
    
    comment.stop();
} 

1.项目目录

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 ## 2.专家

pom.xml

 <?xml version="1.0" encoding="UTF-8"?>
<project 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
		 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mkyong.spring.reactive</groupId>
    <artifactId>webflux-thymeleaf-sse</artifactId>
    <version>1.0</version>

    <properties>
        <java.version>1.8</java.version>
        <junit-jupiter.version>5.3.2</junit-jupiter.version>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.2.RELEASE</version>
    </parent>

    <dependencies>

        <!-- webflux reactive -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <!-- thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <!-- exclude junit 4, prefer junit 5 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- junit 5 -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${
    
    junit-jupiter.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.0</version>
            </plugin>

        </plugins>
    </build>

</project> 

显示项目依赖关系。

 $ mvn dependency:tree

[INFO] com.mkyong.spring.reactive:webflux-thymeleaf-sse:jar:1.0
[INFO] +- org.springframework.boot:spring-boot-starter-webflux:jar:2.1.2.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:2.1.2.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.1.2.RELEASE:compile
[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.2.3:compile
[INFO] |  |  |  |  \- ch.qos.logback:logback-core:jar:1.2.3:compile
[INFO] |  |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.11.1:compile
[INFO] |  |  |  |  \- org.apache.logging.log4j:log4j-api:jar:2.11.1:compile
[INFO] |  |  |  \- org.slf4j:jul-to-slf4j:jar:1.7.25:compile
[INFO] |  |  +- javax.annotation:javax.annotation-api:jar:1.3.2:compile
[INFO] |  |  \- org.yaml:snakeyaml:jar:1.23:runtime
[INFO] |  +- org.springframework.boot:spring-boot-starter-json:jar:2.1.2.RELEASE:compile
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.9.8:compile
[INFO] |  |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.9.0:compile
[INFO] |  |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.9.8:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.9.8:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.9.8:compile
[INFO] |  |  \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.9.8:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-reactor-netty:jar:2.1.2.RELEASE:compile
[INFO] |  |  \- io.projectreactor.netty:reactor-netty:jar:0.8.4.RELEASE:compile
[INFO] |  |     +- io.netty:netty-codec-http:jar:4.1.31.Final:compile
[INFO] |  |     |  \- io.netty:netty-codec:jar:4.1.31.Final:compile
[INFO] |  |     +- io.netty:netty-codec-http2:jar:4.1.31.Final:compile
[INFO] |  |     +- io.netty:netty-handler:jar:4.1.31.Final:compile
[INFO] |  |     |  +- io.netty:netty-buffer:jar:4.1.31.Final:compile
[INFO] |  |     |  \- io.netty:netty-transport:jar:4.1.31.Final:compile
[INFO] |  |     |     \- io.netty:netty-resolver:jar:4.1.31.Final:compile
[INFO] |  |     +- io.netty:netty-handler-proxy:jar:4.1.31.Final:compile
[INFO] |  |     |  \- io.netty:netty-codec-socks:jar:4.1.31.Final:compile
[INFO] |  |     \- io.netty:netty-transport-native-epoll:jar:linux-x86_64:4.1.31.Final:compile
[INFO] |  |        +- io.netty:netty-common:jar:4.1.31.Final:compile
[INFO] |  |        \- io.netty:netty-transport-native-unix-common:jar:4.1.31.Final:compile
[INFO] |  +- org.hibernate.validator:hibernate-validator:jar:6.0.14.Final:compile
[INFO] |  |  +- javax.validation:validation-api:jar:2.0.1.Final:compile
[INFO] |  |  +- org.jboss.logging:jboss-logging:jar:3.3.2.Final:compile
[INFO] |  |  \- com.fasterxml:classmate:jar:1.4.0:compile
[INFO] |  +- org.springframework:spring-web:jar:5.1.4.RELEASE:compile
[INFO] |  |  \- org.springframework:spring-beans:jar:5.1.4.RELEASE:compile
[INFO] |  +- org.springframework:spring-webflux:jar:5.1.4.RELEASE:compile
[INFO] |  |  \- io.projectreactor:reactor-core:jar:3.2.5.RELEASE:compile
[INFO] |  |     \- org.reactivestreams:reactive-streams:jar:1.0.2:compile
[INFO] |  \- org.synchronoss.cloud:nio-multipart-parser:jar:1.1.0:compile
[INFO] |     +- org.slf4j:slf4j-api:jar:1.7.25:compile
[INFO] |     \- org.synchronoss.cloud:nio-stream-storage:jar:1.1.3:compile
[INFO] +- org.springframework.boot:spring-boot-starter-thymeleaf:jar:2.1.2.RELEASE:compile
[INFO] |  +- org.thymeleaf:thymeleaf-spring5:jar:3.0.11.RELEASE:compile
[INFO] |  |  \- org.thymeleaf:thymeleaf:jar:3.0.11.RELEASE:compile
[INFO] |  |     +- org.attoparser:attoparser:jar:2.0.5.RELEASE:compile
[INFO] |  |     \- org.unbescape:unbescape:jar:1.1.6.RELEASE:compile
[INFO] |  \- org.thymeleaf.extras:thymeleaf-extras-java8time:jar:3.0.2.RELEASE:compile
[INFO] +- org.springframework.boot:spring-boot-starter-test:jar:2.1.2.RELEASE:test
[INFO] |  +- org.springframework.boot:spring-boot-test:jar:2.1.2.RELEASE:test
[INFO] |  +- org.springframework.boot:spring-boot-test-autoconfigure:jar:2.1.2.RELEASE:test
[INFO] |  +- com.jayway.jsonpath:json-path:jar:2.4.0:test
[INFO] |  |  \- net.minidev:json-smart:jar:2.3:test
[INFO] |  |     \- net.minidev:accessors-smart:jar:1.2:test
[INFO] |  |        \- org.ow2.asm:asm:jar:5.0.4:test
[INFO] |  +- org.assertj:assertj-core:jar:3.11.1:test
[INFO] |  +- org.mockito:mockito-core:jar:2.23.4:test
[INFO] |  |  +- net.bytebuddy:byte-buddy:jar:1.9.7:test
[INFO] |  |  +- net.bytebuddy:byte-buddy-agent:jar:1.9.7:test
[INFO] |  |  \- org.objenesis:objenesis:jar:2.6:test
[INFO] |  +- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] |  +- org.hamcrest:hamcrest-library:jar:1.3:test
[INFO] |  +- org.skyscreamer:jsonassert:jar:1.5.0:test
[INFO] |  |  \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test
[INFO] |  +- org.springframework:spring-core:jar:5.1.4.RELEASE:compile
[INFO] |  |  \- org.springframework:spring-jcl:jar:5.1.4.RELEASE:compile
[INFO] |  +- org.springframework:spring-test:jar:5.1.4.RELEASE:test
[INFO] |  \- org.xmlunit:xmlunit-core:jar:2.6.2:test
[INFO] |     \- javax.xml.bind:jaxb-api:jar:2.3.1:test
[INFO] |        \- javax.activation:javax.activation-api:jar:1.2.0:test
[INFO] +- org.junit.jupiter:junit-jupiter-engine:jar:5.3.2:test
[INFO] |  +- org.apiguardian:apiguardian-api:jar:1.0.0:test
[INFO] |  +- org.junit.platform:junit-platform-engine:jar:1.3.2:test
[INFO] |  |  +- org.junit.platform:junit-platform-commons:jar:1.3.2:test
[INFO] |  |  \- org.opentest4j:opentest4j:jar:1.1.1:test
[INFO] |  \- org.junit.jupiter:junit-jupiter-api:jar:5.3.2:test
[INFO] \- org.springframework.boot:spring-boot-devtools:jar:2.1.2.RELEASE:compile (optional)
[INFO]    +- org.springframework.boot:spring-boot:jar:2.1.2.RELEASE:compile
[INFO]    |  \- org.springframework:spring-context:jar:5.1.4.RELEASE:compile
[INFO]    |     +- org.springframework:spring-aop:jar:5.1.4.RELEASE:compile
[INFO]    |     \- org.springframework:spring-expression:jar:5.1.4.RELEASE:compile
[INFO]    \- org.springframework.boot:spring-boot-autoconfigure:jar:2.1.2.RELEASE:compile 

3.Spring Boot +春网流量

3.1 基于 Spring WebFlux 注释的控制器。启用数据流。写produces = MediaType.TEXT_EVENT_STREAM_VALUE

CommentController.java

 package com.mkyong.reactive.controller;

import com.mkyong.reactive.model.Comment;
import com.mkyong.reactive.repository.CommentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

@RestController
public class CommentController {
    
    

    @Autowired
    private CommentRepository commentRepository;

    @GetMapping(path = "/comment/stream", 
		produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<Comment> feed() {
    
    
        return this.commentRepository.findAll();
    }

} 

MainController.java

 package com.mkyong.reactive.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class MainController {
    
    

    @GetMapping("/")
    public String index(final Model model) {
    
    
        return "index";
    }

} 

3.2 在repository中,返回一个Flux对象。

CommentRepository.java

 package com.mkyong.reactive.repository;

import com.mkyong.reactive.model.Comment;
import reactor.core.publisher.Flux;

public interface CommentRepository {
    
    

    Flux<Comment> findAll();

} 

ReactiveCommentRepository.java

 package com.mkyong.reactive.repository;

import com.mkyong.reactive.model.Comment;
import com.mkyong.reactive.utils.CommentGenerator;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;

import java.time.Duration;
import java.util.Arrays;
import java.util.List;

@Repository
public class ReactiveCommentRepository implements CommentRepository {
    
    

    @Override
    public Flux<Comment> findAll() {
    
    

        //simulate data streaming every 1 second.
        return Flux.interval(Duration.ofSeconds(1))
                .onBackpressureDrop()
                .map(this::generateComment)
                .flatMapIterable(x -> x);

    }

    private List<Comment> generateComment(long interval) {
    
    

        Comment obj = new Comment(
			CommentGenerator.randomAuthor(), 
			CommentGenerator.randomMessage(), 
			CommentGenerator.getCurrentTimeStamp());
        return Arrays.asList(obj);

    }

} 

3.3 生成随机注释的 utils 类。

CommentGenerator.java

 package com.mkyong.reactive.utils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

public class CommentGenerator {
    
    

    private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
    private static final Random RANDOM = new Random(System.currentTimeMillis());

    private static final List<String> COMMENT_AUTHOR =
            Arrays.asList(
                    "Mkyong", "Oliver", "Jack", "Harry", "Jacob",
                    "Isla", "Emily", "Poppy", "Ava", "Isabella");

    private static final List<String> COMMENT_MESSAGE =
            Arrays.asList(
                    "I Love this!",
                    "Me too!",
                    "Wow",
                    "True!",
                    "Hello everyone here?",
                    "Good!");

    public static String randomAuthor() {
    
    
        return COMMENT_AUTHOR.get(RANDOM.nextInt(COMMENT_AUTHOR.size()));
    }

    public static String randomMessage() {
    
    
        return COMMENT_MESSAGE.get(RANDOM.nextInt(COMMENT_MESSAGE.size()));
    }

    public static String getCurrentTimeStamp() {
    
    
        return dtf.format(LocalDateTime.now());
    }
} 

3.4 评论模式。

Movie.java

 package com.mkyong.reactive.model;

public class Comment {
    
    

    private String author;
    private String message;
    private String timestamp;

    //getter, setter and constructor
} 

3.5 开始 Spring Boot。

CommentWebApplication.java

 package com.mkyong.reactive;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class CommentWebApplication {
    
    

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

} 

4.百里香叶

百里香模板中没有特殊的反应标签,只是使用了普通的循环。

resources/templates/index.html

 <!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link data-th-href="@{/css/bootstrap.min.css}" rel="stylesheet">
    <link data-th-href="@{/css/main.css}" rel="stylesheet">
</head>
<body>

<div class="container">

    <div class="row">
        <div id="title">
            <h1>Spring WebFlux + Server Sent Events</h1>
        </div>

        <table id="comments" class="table table-striped">
            <thead>
            <tr>
                <th width="10%">Author</th>
                <th width="60%">Message</th>
                <th width="30%">Date</th>
            </tr>
            </thead>
            <tbody>
            <tr class="result" data-th-each="comment : ${comments}">
                <td>[[${
    
    comment.author}]]</td>
                <td>[[${
    
    comment.message}]]</td>
                <td>[[${
    
    comment.timestamp}]]</td>
            </tr>
            </tbody>
        </table>
    </div>

</div>

<script data-th-src="@{/js/main.js}"></script>

</body>

</html> 

5.JavaScript 事件源。

关键是使用 Javascript EventSource类发送请求并监听message事件,并将流数据反应性地更新到一个表中。

resources/static/js/main.js

 function loadComments () {
    
    

    this.source = null;

    this.start = function () {
    
    

        var commentTable = document.getElementById("comments");

        this.source = new EventSource("/comment/stream");

        this.source.addEventListener("message", function (event) {
    
    

            // These events are JSON, so parsing and DOM fiddling are needed
            var comment = JSON.parse(event.data);

            var row = commentTable.getElementsByTagName("tbody")[0].insertRow(0);
            var cell0 = row.insertCell(0);
            var cell1 = row.insertCell(1);
            var cell2 = row.insertCell(2);

            cell0.className = "author-style";
            cell0.innerHTML = comment.author;

            cell1.className = "text";
            cell1.innerHTML = comment.message;

            cell2.className = "date";
            cell2.innerHTML = comment.timestamp;

        });

        this.source.onerror = function () {
    
    
            this.close();
        };

    };

    this.stop = function() {
    
    
        this.source.close();
    }

}

comment = new loadComments();

/*
 * Register callbacks for starting and stopping the SSE controller.
 */
window.onload = function() {
    
    
    comment.start();
};
window.onbeforeunload = function() {
    
    
    comment.stop();
} 

6.单元测试

WebTestClient流响应进行单元测试

TestCommentWebApplication.java

 package com.mkyong.reactive;

import com.mkyong.reactive.model.Comment;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.reactive.server.WebTestClient;

import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class TestCommentWebApplication {
    
    

    @Autowired
    private WebTestClient webClient;

    @Test
    public void testCommentStream() {
    
    

        List<Comment> comments = webClient
                .get().uri("/comment/stream")
                .accept(MediaType.valueOf(MediaType.TEXT_EVENT_STREAM_VALUE))
                .exchange()
                .expectStatus().isOk()
                .returnResult(Comment.class)
                .getResponseBody()
                .take(3) // take 3 comment objects
                .collectList()
                .block();

        comments.forEach(x -> System.out.println(x));

        assertEquals(3, comments.size());

    }

} 

7.演示

 $ mvn spring-boot:run

2019-02-11 15:41:17.657  INFO 257192 --- [  restartedMain] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port(s): 8080 

URL =http://localhost:8080
数据是流式的,每 1 秒就会显示随机评论。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下载源代码

$ git clone https://github.com/mkyong/spring-boot.git
$ cd webflux-thymeleaf-serversentevent
$ mvn spring-boot:run

参考

junit 5 reactive spring boot sse thymeleaf webflux

Spring Boot WebFlux +百里香叶反应实例

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/spring-boot/spring-boot-webflux-thymeleaf-reactive-example/

在本文中,我们将向您展示如何开发一个反应式 web 应用程序。

  • Spring Boot 2.1.2 .版本
  • Spring WebFlux 5.1.4 .发行版
  • 百里香叶
  • maven3

Spring Boot 将配置一切,关键是使用百里香叶ReactiveDataDriverContextVariable来启用百里香叶模板中的数据驱动模式。

 @RequestMapping("/")
    public String index(final Model model) {
    
    

        // data streaming, data driven mode.
        IReactiveDataDriverContextVariable reactiveDataDrivenMode =
                new ReactiveDataDriverContextVariable(movieRepository.findAll(), 1);

        model.addAttribute("movies", reactiveDataDrivenMode);

        return "view";

    } 

Note
Working on the Spring Boot WebFlux + Thymeleaf + Server-Sent Events (SSE) integeration. To be updated here.

1.项目目录

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.专家

pom.xml

 <?xml version="1.0" encoding="UTF-8"?>
<project 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
	 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.mkyong.spring.reactive</groupId>
    <artifactId>webflux-thymeleaf</artifactId>
    <version>1.0</version>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.2.RELEASE</version>
    </parent>

    <dependencies>

        <!-- reactive -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <!-- just include the normal thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project> 

显示项目依赖关系。

 $ mvn dependency:tree

[INFO] com.mkyong.spring.webflux:ReactiveApp:jar:1.0-SNAPSHOT
[INFO] +- org.springframework.boot:spring-boot-starter-webflux:jar:2.1.2.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:2.1.2.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:2.1.2.RELEASE:compile
[INFO] |  |  |  \- org.springframework:spring-context:jar:5.1.4.RELEASE:compile
[INFO] |  |  |     +- org.springframework:spring-aop:jar:5.1.4.RELEASE:compile
[INFO] |  |  |     \- org.springframework:spring-expression:jar:5.1.4.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:2.1.2.RELEASE:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.1.2.RELEASE:compile
[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.2.3:compile
[INFO] |  |  |  |  \- ch.qos.logback:logback-core:jar:1.2.3:compile
[INFO] |  |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.11.1:compile
[INFO] |  |  |  |  \- org.apache.logging.log4j:log4j-api:jar:2.11.1:compile
[INFO] |  |  |  \- org.slf4j:jul-to-slf4j:jar:1.7.25:compile
[INFO] |  |  +- javax.annotation:javax.annotation-api:jar:1.3.2:compile
[INFO] |  |  \- org.yaml:snakeyaml:jar:1.23:runtime
[INFO] |  +- org.springframework.boot:spring-boot-starter-json:jar:2.1.2.RELEASE:compile
[INFO] |  |  +- com.fasterxml.jackson.core:jackson-databind:jar:2.9.8:compile
[INFO] |  |  |  +- com.fasterxml.jackson.core:jackson-annotations:jar:2.9.0:compile
[INFO] |  |  |  \- com.fasterxml.jackson.core:jackson-core:jar:2.9.8:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.9.8:compile
[INFO] |  |  +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.9.8:compile
[INFO] |  |  \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.9.8:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-reactor-netty:jar:2.1.2.RELEASE:compile
[INFO] |  |  \- io.projectreactor.netty:reactor-netty:jar:0.8.4.RELEASE:compile
[INFO] |  |     +- io.netty:netty-codec-http:jar:4.1.31.Final:compile
[INFO] |  |     |  \- io.netty:netty-codec:jar:4.1.31.Final:compile
[INFO] |  |     +- io.netty:netty-codec-http2:jar:4.1.31.Final:compile
[INFO] |  |     +- io.netty:netty-handler:jar:4.1.31.Final:compile
[INFO] |  |     |  +- io.netty:netty-buffer:jar:4.1.31.Final:compile
[INFO] |  |     |  \- io.netty:netty-transport:jar:4.1.31.Final:compile
[INFO] |  |     |     \- io.netty:netty-resolver:jar:4.1.31.Final:compile
[INFO] |  |     +- io.netty:netty-handler-proxy:jar:4.1.31.Final:compile
[INFO] |  |     |  \- io.netty:netty-codec-socks:jar:4.1.31.Final:compile
[INFO] |  |     \- io.netty:netty-transport-native-epoll:jar:linux-x86_64:4.1.31.Final:compile
[INFO] |  |        +- io.netty:netty-common:jar:4.1.31.Final:compile
[INFO] |  |        \- io.netty:netty-transport-native-unix-common:jar:4.1.31.Final:compile
[INFO] |  +- org.hibernate.validator:hibernate-validator:jar:6.0.14.Final:compile
[INFO] |  |  +- javax.validation:validation-api:jar:2.0.1.Final:compile
[INFO] |  |  +- org.jboss.logging:jboss-logging:jar:3.3.2.Final:compile
[INFO] |  |  \- com.fasterxml:classmate:jar:1.4.0:compile
[INFO] |  +- org.springframework:spring-web:jar:5.1.4.RELEASE:compile
[INFO] |  |  \- org.springframework:spring-beans:jar:5.1.4.RELEASE:compile
[INFO] |  +- org.springframework:spring-webflux:jar:5.1.4.RELEASE:compile
[INFO] |  |  \- io.projectreactor:reactor-core:jar:3.2.5.RELEASE:compile
[INFO] |  |     \- org.reactivestreams:reactive-streams:jar:1.0.2:compile
[INFO] |  \- org.synchronoss.cloud:nio-multipart-parser:jar:1.1.0:compile
[INFO] |     +- org.slf4j:slf4j-api:jar:1.7.25:compile
[INFO] |     \- org.synchronoss.cloud:nio-stream-storage:jar:1.1.3:compile
[INFO] +- org.springframework.boot:spring-boot-starter-thymeleaf:jar:2.1.2.RELEASE:compile
[INFO] |  +- org.thymeleaf:thymeleaf-spring5:jar:3.0.11.RELEASE:compile
[INFO] |  |  \- org.thymeleaf:thymeleaf:jar:3.0.11.RELEASE:compile
[INFO] |  |     +- org.attoparser:attoparser:jar:2.0.5.RELEASE:compile
[INFO] |  |     \- org.unbescape:unbescape:jar:1.1.6.RELEASE:compile
[INFO] |  \- org.thymeleaf.extras:thymeleaf-extras-java8time:jar:3.0.2.RELEASE:compile
[INFO] \- org.springframework.boot:spring-boot-starter-test:jar:2.1.2.RELEASE:test
[INFO]    +- org.springframework.boot:spring-boot-test:jar:2.1.2.RELEASE:test
[INFO]    +- org.springframework.boot:spring-boot-test-autoconfigure:jar:2.1.2.RELEASE:test
[INFO]    +- com.jayway.jsonpath:json-path:jar:2.4.0:test
[INFO]    |  \- net.minidev:json-smart:jar:2.3:test
[INFO]    |     \- net.minidev:accessors-smart:jar:1.2:test
[INFO]    |        \- org.ow2.asm:asm:jar:5.0.4:test
[INFO]    +- junit:junit:jar:4.12:test
[INFO]    +- org.assertj:assertj-core:jar:3.11.1:test
[INFO]    +- org.mockito:mockito-core:jar:2.23.4:test
[INFO]    |  +- net.bytebuddy:byte-buddy:jar:1.9.7:test
[INFO]    |  +- net.bytebuddy:byte-buddy-agent:jar:1.9.7:test
[INFO]    |  \- org.objenesis:objenesis:jar:2.6:test
[INFO]    +- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO]    +- org.hamcrest:hamcrest-library:jar:1.3:test
[INFO]    +- org.skyscreamer:jsonassert:jar:1.5.0:test
[INFO]    |  \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test
[INFO]    +- org.springframework:spring-core:jar:5.1.4.RELEASE:compile
[INFO]    |  \- org.springframework:spring-jcl:jar:5.1.4.RELEASE:compile
[INFO]    +- org.springframework:spring-test:jar:5.1.4.RELEASE:test
[INFO]    \- org.xmlunit:xmlunit-core:jar:2.6.2:test
[INFO]       \- javax.xml.bind:jaxb-api:jar:2.3.1:test
[INFO]          \- javax.activation:javax.activation-api:jar:1.2.0:test 

3.Spring Boot +春网流量

3.1 基于 Spring WebFlux 注释的控制器。用ReactiveDataDriverContextVariable包装数据,将在百里香模板中启用反应式数据驱动模型。

MovieController.java

 package com.mkyong.reactive.controller;

import com.mkyong.reactive.repository.MovieRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.thymeleaf.spring5.context.webflux.IReactiveDataDriverContextVariable;
import org.thymeleaf.spring5.context.webflux.ReactiveDataDriverContextVariable;

@Controller
public class MovieController {
    
    

    @Autowired
    private MovieRepository movieRepository;

    @RequestMapping("/")
    public String index(final Model model) {
    
    

        // loads 1 and display 1, stream data, data driven mode.
        IReactiveDataDriverContextVariable reactiveDataDrivenMode =
                new ReactiveDataDriverContextVariable(movieRepository.findAll(), 1);

        model.addAttribute("movies", reactiveDataDrivenMode);

        // classic, wait repository loaded all and display it.
        //model.addAttribute("movies", movieRepository.findAll());

        return "index";

    }

} 

3.2 在repository中,返回一个Flux对象。

MovieRepository.java

 package com.mkyong.reactive.repository;

import com.mkyong.reactive.Movie;
import reactor.core.publisher.Flux;

public interface MovieRepository {
    
    

    Flux<Movie> findAll();

} 

ReactiveMovieRepository.java

 package com.mkyong.reactive.repository;

import com.mkyong.reactive.Movie;
import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;

@Repository
public class ReactiveMovieRepository implements MovieRepository {
    
    

    private static List<Movie> movie = new ArrayList<>();

    static {
    
    
        movie.add(new Movie("Polar (2019)", 64));
        movie.add(new Movie("Iron Man (2008)", 79));
        movie.add(new Movie("The Shawshank Redemption (1994)", 93));
        movie.add(new Movie("Forrest Gump (1994)", 83));
        movie.add(new Movie("Glass (2019)", 70));
    }

    @Override
    public Flux<Movie> findAll() {
    
    
        //Simulate big list of data, streaming it every 2 second delay
        return Flux.fromIterable(movie).delayElements(Duration.ofSeconds(2));
    }

} 

3.3 电影模式。

Movie.java

 package com.mkyong.reactive;

public class Movie {
    
    

    private String name;
    private Integer score;

    //getter, setter and constructor
} 

3.4 启动 Spring Boot。

MovieWebApplication.java

 package com.mkyong.reactive;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MovieWebApplication {
    
    

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

} 

4.百里香叶

百里香模板中没有特殊的反应标签,只是使用了普通的循环。

resources/templates/index.html

 <!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link data-th-href="@{/css/bootstrap.min.css}" rel="stylesheet">
    <link data-th-href="@{/css/main.css}" rel="stylesheet">
</head>
<body>

<div class="container">

    <div class="row">
        <div id="title">
            <h1>Spring WebFlux + Thymeleaf</h1>
        </div>
        <table id="allMovies" class="table table-striped">
            <thead>
            <tr>
                <th width="70%">Name</th>
                <th>Score</th>
            </tr>
            </thead>
            <tbody>
            <tr class="result" data-th-each="movie : ${movies}">
                <td>[[${
    
    movie.name}]]</td>
                <td>[[${
    
    movie.score}]]</td>
            </tr>
            </tbody>
        </table>
    </div>

</div> 

定义了块大小。

application.properties

 spring.thymeleaf.reactive.max-chunk-size=8192 

完成了。

5.演示

 $ mvn spring-boot:run 

URL =http://localhost:8080
数据是流式的,将每 2 秒钟以反应方式显示一次。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下载源代码

$ git clone https://github.com/mkyong/spring-boot.git
$ cd webflux-thymeleaf
$ mvn spring-boot:run

参考

Spring Boot——从哪门主课开始

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/spring-boot/spring-boot-which-main-class-to-start/

如果 Spring Boot 项目包含多个主类,Spring Boot 将无法启动或打包进行部署。

Terminal

 $ mvn package 
#or
$ mvn spring-boot:run

Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:1.4.2.RELEASE:run (default-cli) 
Execution default-cli of goal org.springframework.boot:spring-boot-maven-plugin:1.4.2.RELEASE:run failed: 
Unable to find a single main class from the following candidates 
 [com.mkyong.Test, com.mkyong.SpringBootWebApplication] -> [Help 1] 

Maven 示例

1.1 通过start-class属性定义单个主类

pom.xml

 <properties>
      <!-- The main class to start by executing java -jar -->
      <start-class>com.mkyong.SpringBootWebApplication</start-class>
  </properties> 

1.2 或者,在spring-boot-maven-plugin中定义主类

pom.xml

 <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.mkyong.SpringBootWebApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build> 

参考

  1. Spring Boot——可执行的 jar 格式
  2. Spring Boot Maven 插件–用途

executable jar jar main class spring boot war外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 (function (i,d,s,o,m,r,c,l,w,q,y,h,g) { var e=d.getElementById®;if(e=null){ var t = d.createElement(o); t.src = g; t.id = r; t.setAttribute(m, s);t.async = 1;var n=d.getElementsByTagName(o)[0];n.parentNode.insertBefore(t, n); var dt=new Date().getTime(); try{i[l]w+y;}catch(er){i[h]=dt;} } else if(typeof i[c]!‘undefined’){i[c]++} else{i[c]=1;} })(window, document, ‘InContent’, ‘script’, ‘mediaType’, ‘carambola_proxy’,‘Cbola_IC’,‘localStorage’,‘set’,‘get’,‘Item’,‘cbolaDt’,‘//web.archive.org/web/20190217051121/http://route.carambo.la/inimage/getlayer?pid=myky82&did=112239&wid=0’)

Spring Boot YAML 的例子

原文:http://web.archive.org/web/20230101150211/https://mkyong.com/spring-boot/spring-boot-yaml-example/

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在本文中,我们将向您展示如何使用 YAML 来代替 Spring Boot 中的属性文件。

测试对象:

  • Spring Boot 2.1.2 .版本
  • maven3
  • 蛇瓶:1.23

简而言之,在src/resources文件夹中创建一个application.yml,Spring Boot 会自动加载并解析.yml文件,并将值绑定到标注有@ConfigurationProperties的类中

不能使用@PropertySource 加载 P.S YAML 文件

1.YAML 和房地产

application.yml

 logging:
  level:
    org.springframework: ERROR
    com.mkyong: DEBUG

spring:
  profiles:
    active: dev
  main:
    banner-mode: off

email: yaml@mkyong.com
thread-pool: 10

wordpress:
  menus:
    - title: Home
      name: Home
      path: /
    - title: About
      name: About
      path: /about
  themes:
    default-folder: /wp-content/themes/mkyong
  servers:
    - ip: 127.0.0.1
      path: /dev1
    - ip: 127.0.0.2
      path: /dev2
    - ip: 127.0.0.3
      path: /dev3 

application.properties

 # Spring Boot
logging.level.org.springframework=ERROR
logging.level.com.mkyong=DEBUG
spring.profiles.active=dev
spring.main.banner-mode=off

# Global
email=properties@mkyong.com
thread-pool=10

# WordPress
wordpress.menus[0].title=Home
wordpress.menus[0].name=Home
wordpress.menus[0].path=/
wordpress.menus[1].title=About
wordpress.menus[1].name=About
wordpress.menus[1].path=/about
wordpress.themes.default-folder=/wp-content/themes/mkyong
wordpress.servers[0].ip=127.0.0.1
wordpress.servers[0].path=/dev1
wordpress.servers[1].ip=127.0.0.2
wordpress.servers[1].path=/dev2
wordpress.servers[2].ip=127.0.0.3
wordpress.servers[2].path=/dev3 

2.项目结构

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.项目依赖性

Spring Boot 使用 SnakeYAML 库解析 YAML 文件,SnakeYAML 库由spring-boot-starter提供

pom.xml

 <?xml version="1.0" encoding="UTF-8"?>
<project 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
	http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <artifactId>spring-boot-yaml-example</artifactId>
    <packaging>jar</packaging>
    <name>Spring Boot YAML Example</name>
    <url>https://www.mkyong.com</url>
    <version>1.0</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.2.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.0</version>
            </plugin>

        </plugins>
    </build>
</project> 

项目依赖关系:

 +- org.springframework.boot:spring-boot-starter:jar:2.1.2.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot:jar:2.1.2.RELEASE:compile
[INFO] |  |  \- org.springframework:spring-context:jar:5.1.4.RELEASE:compile
[INFO] |  |     +- org.springframework:spring-aop:jar:5.1.4.RELEASE:compile
[INFO] |  |     +- org.springframework:spring-beans:jar:5.1.4.RELEASE:compile
[INFO] |  |     \- org.springframework:spring-expression:jar:5.1.4.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot-autoconfigure:jar:2.1.2.RELEASE:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.1.2.RELEASE:compile
[INFO] |  |  +- ch.qos.logback:logback-classic:jar:1.2.3:compile
[INFO] |  |  |  \- ch.qos.logback:logback-core:jar:1.2.3:compile
[INFO] |  |  +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.11.1:compile
[INFO] |  |  |  \- org.apache.logging.log4j:log4j-api:jar:2.11.1:compile
[INFO] |  |  \- org.slf4j:jul-to-slf4j:jar:1.7.25:compile
[INFO] |  +- javax.annotation:javax.annotation-api:jar:1.3.2:compile
[INFO] |  +- org.springframework:spring-core:jar:5.1.4.RELEASE:compile
[INFO] |  |  \- org.springframework:spring-jcl:jar:5.1.4.RELEASE:compile
[INFO] |  \- org.yaml:snakeyaml:jar:1.23:runtime <<------------- SnakeYAML 

4.Spring Boot + YAML

4.1 Spring Boot 将加载并解析 YAML 文件,并将值绑定到下面的@ConfigurationProperties类中。

GlobalProperties.java

 package com.mkyong.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties // no prefix, root level.
public class GlobalProperties {
    
    

    //thread-pool , relax binding
    private int threadPool;
    private String email;

    //... getters and setters, toString()
} 

WordPressProperties.java

 package com.mkyong.config;

import com.mkyong.config.model.Menu;
import com.mkyong.config.model.Server;
import com.mkyong.config.model.Theme;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

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

@Component
@ConfigurationProperties("wordpress")
public class WordPressProperties {
    
    

    private List<Menu> menus = new ArrayList<>();
    private Theme themes;
    private List<Server> servers = new ArrayList<>();

    //... getters and setters, toString()
} 

4.2 模型,没什么特别的,就是一些标准类。

Menu.java

 package com.mkyong.config.model;

public class Menu {
    
    

    private String name;
    private String path;
    private String title;

    //... getters and setters, toString()
} 

Server.java

 package com.mkyong.config.model;

public class Server {
    
    

    private String ip;
    private String path;

    //... getters and setters, toString()
} 

Theme.java

 package com.mkyong.config.model;

public class Theme {
    
    

    private String defaultFolder;

    //... getters and setters, toString()
} 

4.3 正常启动 Spring Boot,并打印出数值。

Application.java

 package com.mkyong;

import com.mkyong.config.GlobalProperties;
import com.mkyong.config.WordpressProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application implements CommandLineRunner {
    
    

    @Autowired
    private WordPressProperties wpProperties;

    @Autowired
    private GlobalProperties globalProperties;

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

    @Override
    public void run(String... args) {
    
    
        System.out.println(globalProperties);
        System.out.println(wpProperties);
    }
} 

5.演示

打包并运行它。

 # run spring boot directly
$ mvn spring-boot:run

# or package and run it 
$ mvn package
$ java -jar target/spring-boot-yaml-example-1.0.jar 

输出

 GlobalProperties{
    
    
	threadPool=10, 
	email='[email protected]'
}

WordpressProperties{
    
    
	menus=[
		Menu{
    
    name='Home', path='/', title='Home'}, 
		Menu{
    
    name='About', path='/about', title='About'}
	], 
	themes=Theme{
    
    defaultFolder='/wp-content/themes/mkyong'}, 
	servers=[
		Server{
    
    ip='127.0.0.1', path='/dev1'}, 
		Server{
    
    ip='127.0.0.2', path='/dev2'}, 
		Server{
    
    ip='127.0.0.3', path='/dev3'}
	]
} 

YAML Multi-Profiles
Refer to this Spring Boot + Multiple Profiles YAML example

下载源代码

$ git clone https://github.com/mkyong/spring-boot.git
$ cd yaml-simple
$ mvn spring-boot:run

参考

Spring 集合(列表、集合、映射和属性)示例

原文:http://web.archive.org/web/20230101150211/http://www.mkyong.com/spring/spring-collections-list-set-map-and-properties-example/

Spring 示例向您展示了如何将值注入集合类型(列表、集合、映射和属性)。支持 4 种主要集合类型:

  • 列表—
  • 设置-
  • 地图—
  • 属性—

春豆

一个客户对象,具有四个集合属性。

 package com.mkyong.common;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class Customer 
{
    
    
	private List<Object> lists;
	private Set<Object> sets;
	private Map<Object, Object> maps;
	private Properties pros;

	//...
} 

查看不同的代码片段以在 bean 配置文件中声明集合。

1.列表示例

 <property name="lists">
		<list>
			<value>1</value>
			<ref bean="PersonBean" />
			<bean class="com.mkyong.common.Person">
				<property name="name" value="mkyongList" />
				<property name="address" value="address" />
				<property name="age" value="28" />
			</bean>
		</list>
	</property> 

2.树立榜样

 <property name="sets">
		<set>
			<value>1</value>
			<ref bean="PersonBean" />
			<bean class="com.mkyong.common.Person">
				<property name="name" value="mkyongSet" />
				<property name="address" value="address" />
				<property name="age" value="28" />
			</bean>
		</set>
	</property> 

3.地图示例

 <property name="maps">
		<map>
			<entry key="Key 1" value="1" />
			<entry key="Key 2" value-ref="PersonBean" />
			<entry key="Key 3">
				<bean class="com.mkyong.common.Person">
					<property name="name" value="mkyongMap" />
					<property name="address" value="address" />
					<property name="age" value="28" />
				</bean>
			</entry>
		</map>
	</property> 

4.属性示例

 <property name="pros">
		<props>
			<prop key="admin">admin@nospam.com</prop>
			<prop key="support">support@nospam.com</prop>
		</props>
	</property> 

完整的 Spring 的 bean 配置文件。

 <beans 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

	<bean id="CustomerBean" class="com.mkyong.common.Customer">

		<!-- java.util.List -->
		<property name="lists">
			<list>
				<value>1</value>
				<ref bean="PersonBean" />
				<bean class="com.mkyong.common.Person">
					<property name="name" value="mkyongList" />
					<property name="address" value="address" />
					<property name="age" value="28" />
				</bean>
			</list>
		</property>

		<!-- java.util.Set -->
		<property name="sets">
			<set>
				<value>1</value>
				<ref bean="PersonBean" />
				<bean class="com.mkyong.common.Person">
					<property name="name" value="mkyongSet" />
					<property name="address" value="address" />
					<property name="age" value="28" />
				</bean>
			</set>
		</property>

		<!-- java.util.Map -->
		<property name="maps">
			<map>
				<entry key="Key 1" value="1" />
				<entry key="Key 2" value-ref="PersonBean" />
				<entry key="Key 3">
					<bean class="com.mkyong.common.Person">
						<property name="name" value="mkyongMap" />
						<property name="address" value="address" />
						<property name="age" value="28" />
					</bean>
				</entry>
			</map>
		</property>

		<!-- java.util.Properties -->
		<property name="pros">
			<props>
				<prop key="admin">admin@nospam.com</prop>
				<prop key="support">support@nospam.com</prop>
			</props>
		</property>

	</bean>

	<bean id="PersonBean" class="com.mkyong.common.Person">
		<property name="name" value="mkyong1" />
		<property name="address" value="address 1" />
		<property name="age" value="28" />
	</bean>

</beans> 

运行它…

 package com.mkyong.common;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App 
{
    
    
    public static void main( String[] args )
    {
    
    
    	ApplicationContext context = new ClassPathXmlApplicationContext("SpringBeans.xml");

    	Customer cust = (Customer)context.getBean("CustomerBean");
    	System.out.println(cust);

    }
} 

输出

 Customer [

lists=[
1, 
Person [address=address 1, age=28, name=mkyong1], 
Person [address=address, age=28, name=mkyongList]
], 

maps={
    
    
key 1=1,
key 2=Person [address=address 1, age=28, name=mkyong1], 
key 3=Person [address=address, age=28, name=mkyongMap]
}, 

pros={
    
    admin=admin@nospam.com, support=support@nospam.com}, 

sets=[
1, 
Person [address=address 1, age=28, name=mkyong1], 
Person [address=address, age=28, name=mkyongSet]]
] 

下载源代码

Download it – Spring-Collection-Example.zip (6 KB)spring

Spring 数据 MongoDB–自动序列 ID 示例

原文:http://web.archive.org/web/20230101150211/http://www.mkyong.com/mongodb/spring-data-mongodb-auto-sequence-id-example/

在本教程中,我们将向您展示如何在 MongoDB + Spring 数据环境中生成一个自动递增的序列 id。

本项目中使用的工具:

  1. Spring Data MongoDB 1.2.1.RELEASE
  2. MongoDB 2.4.5
  3. Eclipse 4.2
  4. maven3

在本教程结束时,如果保存了集合名称“hosting ”,将会分配一个新的自动递增序列 id。下面是生成序列 id 的 Java 代码片段。

 public long getNextSequenceId(String key) {
    
    

	Query query = new Query(Criteria.where("_id").is(key));

        Update update = new Update();
	update.inc("seq", 1);

	FindAndModifyOptions options = new FindAndModifyOptions();
	options.returnNew(true);

	SequenceId seqId = 
            mongoOperation.findAndModify(query, update, options, SequenceId.class);

	return seqId.getSeq();

  } 

1.项目结构

查看项目目录结构,这是一个标准的 Maven 项目。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 ## 2.Maven Pom

如果您对项目依赖关系感兴趣。

pom.xml

 <project ...>
	<properties>
		<jdk.version>1.6</jdk.version>
		<spring.version>3.2.2.RELEASE</spring.version>
		<mongojavadriver.version>2.11.1</mongojavadriver.version>
		<springdata.version>1.2.1.RELEASE</springdata.version>
	</properties>

	<dependencies>

		<!-- Spring Core -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${
    
    spring.version}</version>
		</dependency>

		<!-- need this for @Configuration -->
		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib</artifactId>
			<version>2.2.2</version>
		</dependency>

		<!-- Spring Data for MongoDB -->
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-mongodb</artifactId>
			<version>${
    
    springdata.version}</version>
		</dependency>

		<!-- Java MongoDB Driver -->
		<dependency>
			<groupId>org.mongodb</groupId>
			<artifactId>mongo-java-driver</artifactId>
			<version>${
    
    mongojavadriver.version}</version>
		</dependency>

	</dependencies>
	<build>
		<finalName>SpringData</finalName>
		<plugins>
		  <plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-compiler-plugin</artifactId>
			<version>2.3.2</version>
			<configuration>
				<source>${
    
    jdk.version}</source>
				<target>${
    
    jdk.version}</target>
			</configuration>
		  </plugin>
		</plugins>
	</build>

</project> 

3.序列集合

我们创建一个名为“sequence”的集合来存储自动增加的序列 id。参考下面的SequenceDaoImpl.java,它显示了生成序列 id 的代码。

Note
Create the “sequence” collection in your MongoDB first!

 db.sequence.insert({
    
    _id: "hosting",seq: 0}) 

SequenceId.java

 package com.mkyong.seq.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "sequence")
public class SequenceId {
    
    

	@Id
	private String id;

	private long seq;

	//get, set, toString...
} 

SequenceDao.java

 package com.mkyong.seq.dao;

import com.mkyong.seq.exception.SequenceException;

public interface SequenceDao {
    
    

	long getNextSequenceId(String key) throws SequenceException;

} 

SequenceDaoImpl.java

 package com.mkyong.seq.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Repository;

import com.mkyong.seq.exception.SequenceException;
import com.mkyong.seq.model.SequenceId;

@Repository
public class SequenceDaoImpl implements SequenceDao {
    
    

	@Autowired
	private MongoOperations mongoOperation;

	@Override
	public long getNextSequenceId(String key) throws SequenceException {
    
    

	  //get sequence id
	  Query query = new Query(Criteria.where("_id").is(key));

	  //increase sequence id by 1
	  Update update = new Update();
	  update.inc("seq", 1);

	  //return new increased id
	  FindAndModifyOptions options = new FindAndModifyOptions();
	  options.returnNew(true);

	  //this is the magic happened.
	  SequenceId seqId = 
            mongoOperation.findAndModify(query, update, options, SequenceId.class);

	  //if no id, throws SequenceException
          //optional, just a way to tell user when the sequence id is failed to generate.
	  if (seqId == null) {
    
    
		throw new SequenceException("Unable to get sequence id for key : " + key);
	  }

	  return seqId.getSeq();

	}

} 

SequenceException.java

 package com.mkyong.seq.exception;

public class SequenceException extends RuntimeException {
    
    

	private static final long serialVersionUID = 1L;

	private String errCode;
	private String errMsg;

	//get, set...
	public SequenceException(String errMsg) {
    
    
		this.errMsg = errMsg;
	}

} 

4.获取序列 ID

为了获得序列 id,使用sequenceDao.getNextSequenceId("key")

HostingBo.java

 package com.mkyong.hosting.bo;

import com.mkyong.seq.exception.SequenceException;

public interface HostingBo {
    
    

	void save(String name) throws SequenceException;

} 

HostingBoImpl.java

 package com.mkyong.hosting.bo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mkyong.hosting.dao.HostingDao;
import com.mkyong.hosting.model.Hosting;
import com.mkyong.seq.dao.SequenceDao;
import com.mkyong.seq.exception.SequenceException;

@Service
public class HostingBoImpl implements HostingBo {
    
    

	private static final String HOSTING_SEQ_KEY = "hosting";

	@Autowired
	private SequenceDao sequenceDao;

	@Autowired
	private HostingDao hostingDao;

	@Override
	public void save(String name) throws SequenceException {
    
    

		Hosting hosting = new Hosting();

		hosting.setId(sequenceDao.getNextSequenceId(HOSTING_SEQ_KEY));
		hosting.setName(name);
		hostingDao.save(hosting);

		System.out.println(hosting);

	}

} 

5.测试

运行一个简单的测试。

 package com.mkyong;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.mkyong.config.AppConfig;
import com.mkyong.hosting.bo.HostingBo;
import com.mkyong.seq.exception.SequenceException;

public class App {
    
    

  public static void main(String[] args) {
    
    

	ApplicationContext ctx = 
            new AnnotationConfigApplicationContext(AppConfig.class);
	HostingBo hostingBo = (HostingBo) ctx.getBean("hostingBoImpl");

	try {
    
    

		hostingBo.save("cloud.google.com");
		hostingBo.save("heroku.com");
		hostingBo.save("cloudbees.com");

	} catch (SequenceException e) {
    
    
		System.out.println(e.getErrMsg());
	}

  }
} 

输出–Java 控制台

 Hosting [id=1, name=cloud.google.com]
Hosting [id=2, name=heroku.com]
Hosting [id=3, name=cloudbees.com] 

MongoDB 控制台。

 >mongo

> db.sequence.find()
{
    
     "_id" : "hosting", "seq" : 3 }

> db.hosting.find()
{
    
     "_id" : NumberLong(1), "_class" : "com.mkyong.hosting.model.Hosting", "name" : "cloud.google.com" }
{
    
     "_id" : NumberLong(2), "_class" : "com.mkyong.hosting.model.Hosting", "name" : "heroku.com" }
{
    
     "_id" : NumberLong(3), "_class" : "com.mkyong.hosting.model.Hosting", "name" : "cloudbees.com" }
> 

6.常见问题

q . sequence exception–无法获取密钥的序列 id:hosting?
A .记得创建“序列”集合!

 db.sequence.insert({
    
    _id: "hosting",seq: 0}) 

下载源代码

Download – SpringData-Auto-Sequence-Example.zip (24 KB)

参考

  1. MongoDB–创建一个自动递增序列字段

sequence id spring-data

Spring Data MongoDB:删除文档

原文:http://web.archive.org/web/20230101150211/http://www.mkyong.com/mongodb/spring-data-mongodb-delete-document/

在 MongoDB 的 Spring data 中,可以使用remove()findAndRemove()从 MongoDB 中删除文档。

  1. remove()–删除单个或多个文档。
  2. 删除单个文档,并返回被删除的文档。

Common Mistake
Don’t use findAndRemove() to perform a batch delete (remove multiple documents), only the first document that matches the query will be removed. Refer query4 below:

1.删除文档示例

查看完整的示例,了解 remove()和 findAndRemove()的用法。

 package com.mkyong.core;

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

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import com.mkyong.config.SpringMongoConfig;
import com.mkyong.model.User;

/**
 * Delete example
 * 
 * @author mkyong
 * 
 */

public class DeleteApp {
    
    

	public static void main(String[] args) {
    
    

		ApplicationContext ctx = 
                      new AnnotationConfigApplicationContext(SpringMongoConfig.class);
		MongoOperations mongoOperation = 
                      (MongoOperations) ctx.getBean("mongoTemplate");

		// insert 6 users for testing
		List<User> users = new ArrayList<User>();

		User user1 = new User("1001", "ant", 10);
		User user2 = new User("1002", "bird", 20);
		User user3 = new User("1003", "cat", 30);
		User user4 = new User("1004", "dog", 40);
		User user5 = new User("1005", "elephant", 50);
		User user6 = new User("1006", "frog", 60);
		users.add(user1);
		users.add(user2);
		users.add(user3);
		users.add(user4);
		users.add(user5);
		users.add(user6);
		mongoOperation.insert(users, User.class);

		Query query1 = new Query();
		query1.addCriteria(Criteria.where("name").exists(true)
			.orOperator(
                           Criteria.where("name").is("frog"), 
                           Criteria.where("name").is("dog")
                        ));
		mongoOperation.remove(query1, User.class);

		Query query2 = new Query();
		query2.addCriteria(Criteria.where("name").is("bird"));
		User userTest2 = mongoOperation.findOne(query2, User.class);
		mongoOperation.remove(userTest2);

		// The first document that matches the query is returned and also
		// removed from the collection in the database.
		Query query3 = new Query();
		query3.addCriteria(Criteria.where("name").is("ant"));
		User userTest3 = mongoOperation.findAndRemove(query3, User.class);
		System.out.println("Deleted document : " + userTest3);

		// either cat or elephant is deleted only, 
                // common mistake, don't use for batch delete.
		/*
		  Query query4 = new Query(); 
                  query4.addCriteria(Criteria.where("name") .exists(true)
		       .orOperator(
                             Criteria.where("name").is("cat"),
		             Criteria.where("name").is("elephant")
                        )
                  );
		  mongoOperation.findAndRemove(query4, User.class);
		  System.out.println("Deleted document : " + userTest4);
		 */

		System.out.println("\nAll users : ");
		List<User> allUsers = mongoOperation.findAll(User.class);
		for (User user : allUsers) {
    
    
			System.out.println(user);
		}

		mongoOperation.dropCollection(User.class);

	}

} 

输出

 Deleted document : User [id=5162e0153004c3cb0a907370, ic=1001, name=ant, age=10]

All users : 
User [id=5162e0153004c3cb0a907372, ic=1003, name=cat, age=30]
User [id=5162e0153004c3cb0a907374, ic=1005, name=elephant, age=50] 

下载源代码

Download it – SpringMongoDB-Delete-Example.zip (24 KB) ## 参考

  1. 从 MongoDB 中保存、更新和删除文档
  2. Java MongoDB 删除示例/

delete mongodb spring-data

Spring 数据 MongoDB hello world 示例

原文:http://web.archive.org/web/20230101150211/http://www.mkyong.com/mongodb/spring-data-mongodb-hello-world-example/

在本教程中,我们将向您展示如何使用" SpringData for MongoDB "框架,通过 Spring 的注释和 XML schema 在 MongoDB 中执行 CRUD 操作。

Updated on 1/04/2013
Article is updated to use latest SpringData v 1.2.0.RELEASE, it was v1.0.0.M2.

使用的工具和技术:

  1. spring Data MongoDB–1 . 2 . 0 . release
  2. 弹簧芯–3 . 2 . 2 .释放
  3. Java Mongo 驱动程序–2 . 11 . 0
  4. eclipse–4.2
  5. jdk 1.6
  6. maven–3 . 0 . 3

P.S Spring 数据要求 JDK 6.0 及以上,Spring Framework 3.0.x 及以上。

1.项目结构

一个经典的 Maven 风格的 Java 项目目录结构。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.属国

需要以下库:

spring-data-mongodb
Currently, the “spring-data-mongodb” jar is only available in “http://maven.springframework.org/milestone“, so, you have to declare this repository also.

更新于 2012 年 13 月 9 日
spring-data-mongodb在 Maven 中央存储库中可用,不再需要 Spring 存储库。

pom.xml

 <project  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
	http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.mkyong.core</groupId>
	<artifactId>SpringMongoDBExample</artifactId>
	<packaging>jar</packaging>
	<version>1.0</version>
	<name>SpringMongoExample</name>
	<url>http://maven.apache.org</url>

	<dependencies>

		<!-- Spring framework -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>3.2.2.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>3.2.2.RELEASE</version>
		</dependency>

		<!-- mongodb java driver -->
		<dependency>
			<groupId>org.mongodb</groupId>
			<artifactId>mongo-java-driver</artifactId>
			<version>2.11.0</version>
		</dependency>

		<!-- Spring data mongodb -->
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-mongodb</artifactId>
			<version>1.2.0.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib</artifactId>
			<version>2.2.2</version>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.0</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-eclipse-plugin</artifactId>
				<version>2.9</version>
				<configuration>
					<downloadSources>true</downloadSources>
					<downloadJavadocs>true</downloadJavadocs>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project> 

3.Spring 配置、注释和 XML

在这里,我们向您展示了两种配置 Spring 数据和连接到 MongoDB 的方法,分别是通过注释和 XML schema。

Note
Refer to this official reference Connecting to MongoDB with Spring.

3.1 注释
扩展了AbstractMongoConfiguration是最快的方式,它有助于配置你需要启动的一切,像mongoTemplate对象。

SpringMongoConfig.java

 package com.mkyong.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;

import com.mongodb.Mongo;
import com.mongodb.MongoClient;

@Configuration
public class SpringMongoConfig extends AbstractMongoConfiguration {
    
    

	@Override
	public String getDatabaseName() {
    
    
		return "yourdb";
	}

	@Override
	@Bean
	public Mongo mongo() throws Exception {
    
    
		return new MongoClient("127.0.0.1");
	}
} 

或者,我更喜欢这个,更灵活地配置一切。

SpringMongoConfig1.java

 package com.mkyong.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;

import com.mongodb.MongoClient;

@Configuration
public class SpringMongoConfig1 {
    
    

	public @Bean
	MongoDbFactory mongoDbFactory() throws Exception {
    
    
		return new SimpleMongoDbFactory(new MongoClient(), "yourdb");
	}

	public @Bean
	MongoTemplate mongoTemplate() throws Exception {
    
    

		MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory());

		return mongoTemplate;

	}

} 

并载入AnnotationConfigApplicationContext:

 ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringMongoConfig.class);
    MongoOperations mongoOperation = (MongoOperations)ctx.getBean("mongoTemplate"); 

3.2 XML 模式

SpringConfig.xml

 <beans 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mongo="http://www.springframework.org/schema/data/mongo"
	xsi:schemaLocation="http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-3.0.xsd
          http://www.springframework.org/schema/data/mongo
          http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
          http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

	<mongo:mongo host="127.0.0.1" port="27017" />
	<mongo:db-factory dbname="yourdb" />

	<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
		<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
	</bean>

</beans> 

并将其包含在 Spring 的GenericXmlApplicationContext:

 ApplicationContext ctx = new GenericXmlApplicationContext("SpringConfig.xml");
   MongoOperations mongoOperation = (MongoOperations)ctx.getBean("mongoTemplate"); 

So, XML or Annotation?
Actually, both are doing the same thing, it’s just based on personal preferences. Personally, I like XML to configure things.

4.用户模型

一个用户对象,annotated @ Document——保存哪个集合。稍后,我们将向您展示如何使用 Spring 数据将该对象绑定到 MongoDB 或从 MongoDB 绑定。

User.java

 package com.mkyong.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "users")
public class User {
    
    

	@Id
	private String id;

	String username;

	String password;

	//getter, setter, toString, Constructors

} 

5.演示–CRUD 操作

完整的示例向您展示了如何使用 Spring 数据在 MongoDB 中执行 CRUD 操作。Spring 数据 API 非常简洁,应该是不言自明的。

App.java

 package com.mkyong.core;

import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import com.mkyong.config.SpringMongoConfig;
import com.mkyong.model.User;
//import org.springframework.context.support.GenericXmlApplicationContext;

public class App {
    
    

    public static void main(String[] args) {
    
    

	// For XML
	//ApplicationContext ctx = new GenericXmlApplicationContext("SpringConfig.xml");

	// For Annotation
	ApplicationContext ctx = 
             new AnnotationConfigApplicationContext(SpringMongoConfig.class);
	MongoOperations mongoOperation = (MongoOperations) ctx.getBean("mongoTemplate");

	User user = new User("mkyong", "password123");

	// save
	mongoOperation.save(user);

	// now user object got the created id.
	System.out.println("1\. user : " + user);

	// query to search user
	Query searchUserQuery = new Query(Criteria.where("username").is("mkyong"));

	// find the saved user again.
	User savedUser = mongoOperation.findOne(searchUserQuery, User.class);
	System.out.println("2\. find - savedUser : " + savedUser);

	// update password
	mongoOperation.updateFirst(searchUserQuery, 
                         Update.update("password", "new password"),User.class);

	// find the updated user object
	User updatedUser = mongoOperation.findOne(searchUserQuery, User.class);

	System.out.println("3\. updatedUser : " + updatedUser);

	// delete
	mongoOperation.remove(searchUserQuery, User.class);

	// List, it should be empty now.
	List<User> listUser = mongoOperation.findAll(User.class);
	System.out.println("4\. Number of user = " + listUser.size());

    }

} 

输出

 1\. user : User [id=516627653004953049d9ddf0, username=mkyong, password=password123]
2\. find - savedUser : User [id=516627653004953049d9ddf0, username=mkyong, password=password123]
3\. updatedUser : User [id=516627653004953049d9ddf0, username=mkyong, password=new password]
4\. Number of user = 0 

下载源代码

Download it – SpringMongoDB-HelloWorld-Example.zip (24 KB)

参考

  1. 【MongoDB 的春季数据
  2. 用 Spring 连接到 MongoDB】
  3. 奥雷利春天数据 mongodb 教程
  4. 又一个好的春季数据 mongodb 教程

Tags : hello world mongodb spring-data

相关文章

猜你喜欢

转载自blog.csdn.net/wizardforcel/article/details/143497716