Spring Boot 2.2.0 – WebMvc.fn


Spring Boot 2.2.0 – WebMvc.fn

Pojawienie się wersji Spring Boota 2.2.0 niesie za sobą nową funkcjonalność WebMvc.fn. Jest to podejście które pozwala na definiowanie endpointów w sposób funkcyjny. Nie musimy rezygnować ze starego podejścia z użyciem adnotacji @Controller. Te dwa podejścia mogą być używane wymiennie. Do dzieła!

Tworzymy nowy projekt Spring Boot (wersja 2.2.0.BUILD-SNAPSHOT) – plik pom.xml:

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

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

<repositories>
	<repository>
		<id>spring-snapshots</id>
		<name>Spring Snapshots</name>
		<url>https://repo.spring.io/snapshot</url>
		<snapshots>
			<enabled>true</enabled>
		</snapshots>
	</repository>
	<repository>
		<id>spring-milestones</id>
		<name>Spring Milestones</name>
		<url>https://repo.spring.io/milestone</url>
	</repository>
</repositories>

<pluginRepositories>
	<pluginRepository>
		<id>spring-snapshots</id>
		<name>Spring Snapshots</name>
		<url>https://repo.spring.io/snapshot</url>
		<snapshots>
			<enabled>true</enabled>
		</snapshots>
	</pluginRepository>
	<pluginRepository>
		<id>spring-milestones</id>
		<name>Spring Milestones</name>
		<url>https://repo.spring.io/milestone</url>
	</pluginRepository>
</pluginRepositories>

Klasa modelu:

public class User {

    String name;
    String surname;

    public User() {
    }

    public User(String name, String surname) {
        this.name = name;
        this.surname = surname;
    }

  // getters & setters
}

Klasa serwisu:

public interface UserDataService {
     List<User> getAllUsers();
     void addNewUser(User jsonUser);
}

Implementacja serwisu:

@Service
class UserDataServiceImpl implements UserDataService {

    @Override
    public List<User> getAllUsers() {
        return UsersDatabaseHelper.getAllUsers();
    }

    @Override
    public void addNewUser(User jsonUser) {
        UsersDatabaseHelper.addUser(jsonUser);
    }
}

Klasa konfiguracyjna dla kontrolera:

Metoda oznaczona adnotacją @Bean tworzy ziarno zarządzane przez Springa. Jako argument do metody Spring wstrzykuje obiekt UserDataService ponieważ jest to ziarno zarządzane przez Springa o czym świadczy użycie adnotacji @Service dla klasy UserDataServiceImpl.

@Configuration
public class ConfigurationControllersRouting {

    @Bean
    public RouterFunction<ServerResponse> routes(UserDataService userDataService) {
        return route()
                .GET("/getAllUsers", serverRequest ->
                        ServerResponse.ok()
                                .body(userDataService.getAllUsers()))
                .
                POST("/addNewUser", request -> {
                            userDataService.addNewUser(request.body(User.class));
                                return ServerResponse.created(URI.create("/location")).build();
                            })
                .build();
    }
}

Klasa pomocnicza która generuje przykładowych użytkowników:

public class UsersDatabaseHelper {

    static List<User> users = new ArrayList();

    static {
        User user1 = new User("user-1", "user-1");
        User user2 = new User("user-2", "user-2");
        User user3 = new User("user-3", "user-3");
        User user4 = new User("user-4", "user-4");
        User user5 = new User("user-5", "user-5");

        users.add(user1);
        users.add(user2);
        users.add(user3);
        users.add(user4);
        users.add(user5);
    }

    public static List<User> getAllUsers() {
        return users;
    }

    public static void addUser(User user) {
        users.add(user);
    }
}

Testy:

Pobranie wszystkich użytkowników – żądanie GET:

http://localhost:8080/getAllUsers

Dodanie nowego użytkownika z użyciem narzędzia Advanced Rest Client – żądanie POST:

http://localhost:8080/addNewUser

JSON:

{"name":"newUser","surname":"newUser"}

Zamieszczony wyżej kod można usprawnić tworząc klasę która reprezentuje wykonywane operacje dla poszczególnych metod protokołu HTTP, np. dla metody POST będzie to:

@Component
    class Handler {
        public ServerResponse handlePost(ServerRequest serverRequest)
                throws ServletException, IOException {
            userDataService.addNewUser(serverRequest.body(User.class));
            return ServerResponse.created(URI.create("/location")).build();
        }
}

Wtedy klasa ConfigurationControllersRouting po modyfikacji wygląda następująco:

@Configuration
public class ConfigurationControllersRouting {

    @Autowired
    UserDataService userDataService;

    @Component
    class Handler {
        public ServerResponse handlePost(ServerRequest serverRequest)
                throws ServletException, IOException {
            userDataService.addNewUser(serverRequest.body(User.class));
            return ServerResponse.created(URI.create("/location")).build();
        }
    }

    @Bean
    public RouterFunction<ServerResponse> routes(Handler handler) {
        return route()

                .GET("/getAllUsers", serverRequest ->
                        ServerResponse.ok()
                                .body(userDataService.getAllUsers()))

                .POST("/addNewUser", handler::handlePost)
                .build();
    }
}

Polecam dodatkowo materiał dostępny na oficjalnej stronie springa:


Leave a comment

Your email address will not be published.


*