1、注解式开发实现HelloWorld

  1.1、配置依赖

  在SpringBoot的基础依赖中添加了如下:

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

 1. 2、编写控制器

如下:

@RestController
public class HelloWorldController {
    @GetMapping("/helloworld")
    public Mono<String> helloworld(){
        return Mono.just("This is WebFlux demo");
    }

}

1.3、编写启动类

如下:

@SpringBootApplication
public class WebFluxDemoHelloWorldApplication {

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

2、注解式开发模拟用户新增、修改、删除

主要是模拟一个业务流程,如何获取数据。

2.1、创建实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private long id;
    private String name;
    private int age;

}

2.2、编写控制器

实现WebFlux的操作数据功能

@RestController
@RequestMapping(path = "/user")
public class UserController {
    Map<Long, User> users = new HashMap<>();

    @PostConstruct//依赖关系注入完成之后,执行初始化
    public void init() throws Exception {
        users.put(Long.valueOf(1), new User(1, "郭大狗", 22));
        users.put(Long.valueOf(2), new User(2, "郭二狗", 21));
    }

    /**
     * 获取所有用户
     *
     * @return
     */
    @GetMapping("/list")
    public Flux<User> getAll() {
        return Flux.fromIterable(users.entrySet().stream()
                .map(entry -> entry.getValue())
                .collect(Collectors.toList()));
    }

    /**
     * 获取单个用户
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public Mono<User> getUser(@PathVariable Long id) {
        return Mono.justOrEmpty(users.get(id));
    }

    /**
     * 创建用户
     *
     * @param user
     * @return
     */
    @PostMapping("")
    public Mono<ResponseEntity<String>> addUser(User user) {
        users.put(user.getId(), user);
        return Mono.just(new ResponseEntity<>("添加成功", HttpStatus.CREATED));
    }

    /**
     * 修改用户
     *
     * @param id
     * @param user
     * @return
     */
    @PutMapping("/{id}")
    public Mono<ResponseEntity<User>> putUser(@PathVariable Long id, User user) {
        user.setId(id);
        users.put(id, user);
        return Mono.just(new ResponseEntity<>(user, HttpStatus.CREATED));
    }

    /**
     * 删除用户
     *
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    public Mono<ResponseEntity<String>> deleteUser(@PathVariable Long id) {
        users.remove(id);
        return Mono.just(new ResponseEntity<>("删除成功", HttpStatus.ACCEPTED));
    }
}

3、测试API功能

 3.1、获取数据

启动项目后访问路径"http://localhost:8080/user/list"会得到两个初始化成功的数据。

[{"id":1,"name":"郭大狗","age":22},{"id":2,"name":"郭二狗","age":21}]

如果要得到id为1的对象信息,可以访问路径:"http://localhost:8080/user/1"

{"id":1,"name":"郭大狗","age":22}

3.2、修改数据

通过PUT方式进行数据的修改。

spring data rest 响应式 spring响应式编程 pdf_spring

修改后的数据为

spring data rest 响应式 spring响应式编程 pdf_数据_02


3.3、添加数据

通过POST方式提交了数据

spring data rest 响应式 spring响应式编程 pdf_spring boot_03

可以查看:

spring data rest 响应式 spring响应式编程 pdf_spring_04


3.4、删除数据

通过DELETE方式删除数据。

spring data rest 响应式 spring响应式编程 pdf_数据_05

再看看目前的数据有多少,是否删除成功:

spring data rest 响应式 spring响应式编程 pdf_spring_06


3、用响应式方式开发WebFlux

3.1、编写处理类Handler

Handler相当于MVC中的Controller,用于提供实现功能的方法。代码如下:

import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

/**
 * @Author: 
 * @License: (C) Copyright 2019-2029, wrwl Corporation Limited.
 * @Date: 2020/12/17 14:09
 * @Description: ::
 */
@Component
public class HelloWorldHandler {

    public Mono<ServerResponse> sayHello(ServerRequest serverRequest) {
        return ServerResponse.ok().contentType(MediaType.TEXT_PLAIN).body(Mono.just("This is WebFlux demo"), String.class);
    }

}

3.2、编写路由器类Router

Router主要是提供路由映射,相当于MVC模式中的注解RequestMapping。

import com.zqj.handler.HelloWorldHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
/**
 * @Author: 
 * @License: (C) Copyright 2019-2029, wrwl Corporation Limited.
 * @Date: 2020/12/17 14:14
 * @Description: ::
 */
@Configuration
public class Router {

    @Autowired
    private HelloWorldHandler helloWorldHandler;

    @Bean
    public RouterFunction<ServerResponse> getString(){
        return route(GET("/helloworld"),req->helloWorldHandler.sayHello(req));
    }

}

上诉代码中,通过 return route(GET("/helloworld"),req->helloWorldHandler.sayHello(req));来指定路由,baohanHTTP方法和对应的功能方法。


3.3、启动类

@SpringBootApplication
public class WebFluxApplication {

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

}

整体启动即可。


4、用WebFlux模式操作MongoDB数据库,实现对数据库的增删改查

 4.1、添加依赖

要实现对数据库的操作,可以通过Springboot对MongoDB的依赖进行快速配置和操作。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 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>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.3.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>WebFluxMongodb</name>
	<description>Demo project for Spring Boot</description>

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

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

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

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>io.projectreactor</groupId>
			<artifactId>reactor-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

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

</project>

在配置文件中配置MongoDB地址信息(MongoDB2.4版本以上)

spring.data.mongodb.uri=mongodb://127.0.0.1:27017/test

格式如下:

spring.data.mongodb.uri=mongodb://用户名:密码@ip地址:端口号/数据库

4.2、创建实体

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @Id
    private String id;
//    为name创建索引,如果需要值唯一,则设置@Indexed(unique = true)。
    private String name;
    private int age;

}

4.3、编写接口

Spring Boot 的Starter 提供了ReactiveMongoRepository接口,用于操作Mongo数据库:

public interface UserRepository extends ReactiveMongoRepository<User,String> {

}

4.4、编写API

通过用WebFlux模式操作数据的API,具体参考以下代码:

@RestController
@RequestMapping(path = "/user")
public class UserController {
    @Autowired
    private UserRepository userRepository;

    @GetMapping(value = "/list")
    public Flux<User> getAll() {
        return userRepository.findAll();
    }

    //启动测试就可以发现查询是一个一个出来的,而不是一下返回。
    @GetMapping(value = "/listdelay", produces = MediaType.APPLICATION_STREAM_JSON_VALUE)
    public Flux<User> getAlldelay() {
        return userRepository.findAll().delayElements(Duration.ofSeconds(1));
    }

    @GetMapping("/{id}")
    public Mono<ResponseEntity<User>> getUser(@PathVariable String id) {

        return userRepository.findById(id)
                .map(getUser -> ResponseEntity.ok(getUser))
                .defaultIfEmpty(ResponseEntity.notFound().build());
    }

    @PostMapping("")
    public Mono<User> createUser(@Valid User user) {
        return userRepository.save(user);
    }

    @PutMapping("/{id}")
    public Mono updateUser(@PathVariable(value = "id") String id,
                           @Valid User user) {
        return userRepository.findById(id)
                .flatMap(existingUser -> {
                    existingUser.setName(user.getName());
                    return userRepository.save(existingUser);
                })
                .map(updateUser -> new ResponseEntity<>(updateUser, HttpStatus.OK))
                .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }


    @DeleteMapping("/{id}")
    public Mono<ResponseEntity<Void>> deleteUser(@PathVariable(value = "id") String id) {

        return userRepository.findById(id)
                .flatMap(existingUser ->
                        userRepository.delete(existingUser)
                                .then(Mono.just(new ResponseEntity<Void>(HttpStatus.OK)))
                )
                .defaultIfEmpty(new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }
}

4.5、启动类编写

@ComponentScan(basePackages = {"com.example.*"}) //根据自己配置来添加
@EnableReactiveMongoRepositories
@SpringBootApplication
public class WebFluxMongodbApplication {

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

}

代码解释如下:

 

  • produces = MediaType.APPLICATION_ STREAM_ JSON_ VALUE:这里媒体类型必须是APPLICATION_ STREAM JSON_ _VALUE,否则调用端无法滚动得到结果,将一直阻塞直到数据流结束或超时。
  • Duration.ofSeconds(1): 代表一 秒-秒地返回数据,而不是下 全部返回。
  • ResponseEntity.ok: ResponseEntity继承了HttpEntity, 是HttpEntity的子类,且可以添加HttpStatus状态码。
  • flatMap: 返回的是迭代器中的元素。
  • HttpStatus.NOT_ FOUND:代表HTTP状态是404,表示没有找到。
  • HttpStatus.OK: 代表HTTP状态是200,表示处理成功。
     

结尾:

做了两年开发,发现对Spring Boot 的认知上缺少了很多东西。因此想重新认识 Spring Boot 框架 仅此而已。