Извините, я не поправлял вас. Я пытался объяснить основную проблему, которую вы исправили, для людей, которые искали резюме.

я есть веб-приложение Spring Boot 2, в котором мне нужно идентифицировать посетителя сайта по cookie и собирать статистику просмотра страниц. Поэтому мне нужно перехватить каждый веб-запрос. Код, который я должен был написать, более сложен, чем обратный вызов в ад (сама проблема, которую должен был решить реактор Spring).

Вот код:

package mypack.conf;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;
import org.springframework.http.HttpCookie;
import org.springframework.http.ResponseCookie;
import org.springframework.web.reactive.config.ResourceHandlerRegistry;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;

import mypack.dao.PageViewRepository;
import mypack.dao.UserRepository;
import mypack.domain.PageView;
import mypack.domain.User;
import mypack.security.JwtProvider;

import reactor.core.publisher.Mono;
@Configuration


@ComponentScan(basePackages = "mypack")
@EnableReactiveMongoRepositories(basePackages = "mypack")
public class WebConfig implements WebFluxConfigurer {

    @Autowired
    @Lazy
    private UserRepository userRepository;

    @Autowired
    @Lazy
    private PageViewRepository pageViewRepository;


    @Autowired
    @Lazy
    JwtProvider jwtProvider;


    @Bean
    public WebFilter sampleWebFilter()  {
        return new WebFilter() {

            @Override
            public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {

                String uri = exchange.getRequest().getURI().toString();
                String path = exchange.getRequest().getPath().pathWithinApplication().value();


                HttpCookie  cookie = null;
                String token = "";
                Map<String, List<HttpCookie>> cookies = exchange.getRequest().getCookies();


                try {
                    if((exchange.getRequest().getCookies().containsKey("_token") )
                            &&  (exchange.getRequest().getCookies().getFirst("_token"))!=null  ) {

                        cookie = exchange.getRequest().getCookies().getFirst("_token");
                        token = cookie.getValue();


                        return userRepository.findByToken(token).map(user -> {

                                exchange.getAttributes().put("_token", user.getToken());


                                PageView pg = PageView.builder().createdDate(LocalDateTime.now()).URL(uri).build();
                                pageViewRepository.save(pg).subscribe(pg1 -> {user.getPageviews().add(pg1); });

                                userRepository.save(user).subscribe();
                                    return user;
                            })


                            .flatMap(user-> chain.filter(exchange)); // ultimately this step executes regardless user exist or not

                    // handle case when brand new user first time visits website    
                    } else {
                        token = jwtProvider.genToken("guest", UUID.randomUUID().toString());
                        User user = User.builder().createdDate(LocalDateTime.now()).token(token).emailId("guest").build();
                        userRepository.save(user).subscribe();
                        exchange.getResponse().getCookies().remove("_token");

                        ResponseCookie rcookie  = ResponseCookie.from("_token", token).httpOnly(true).build();
                        exchange.getResponse().addCookie(rcookie);
                        exchange.getAttributes().put("_token", token);

                    }

                } catch (Exception e) {

                    e.printStackTrace();
                }



                return chain.filter(exchange);
            } // end of  Mono<Void> filter method
        }; // end of New WebFilter (anonymous class)
    }

}

Другие соответствующие классы:

@Repository
public interface PageViewRepository extends   ReactiveMongoRepository<PageView, String>{

    Mono<PageView> findById(String id);

}


@Repository
public interface UserRepository extends   ReactiveMongoRepository<User, String>{

    Mono<User> findByToken(String token);

}





@Data
@AllArgsConstructor
@Builder
@NoArgsCo,nstructor
public class User {

    @Id
    private String id;
    private String token;


    @Default
    private LocalDateTime createdDate = LocalDateTime.now();

    @DBRef
    private List<PageView> pageviews;

}



Data
@Document
@Builder
public class PageView {
    @Id
    private String id;

    private String URL;

    @Default
    private LocalDateTime createdDate = LocalDateTime.now();
}

Соответствующая часть файла Gradle:

buildscript {
    ext {

        springBootVersion = '2.0.1.RELEASE'
    }
    repositories {
        mavenCentral()

    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

dependencies {

    compile('org.springframework.boot:spring-boot-starter-data-mongodb-reactive')
    compile('org.springframework.boot:spring-boot-starter-security')
    compile('org.springframework.boot:spring-boot-starter-thymeleaf')

    compile('org.springframework.boot:spring-boot-starter-webflux')

    compile('org.springframework.security:spring-security-oauth2-client')
    compile('org.springframework.security.oauth:spring-security-oauth2:2.3.4.RELEASE')
    runtime('org.springframework.boot:spring-boot-devtools')
    compileOnly('org.projectlombok:lombok')
    compile "org.springframework.security:spring-security-jwt:1.0.9.RELEASE"
    compile "io.jsonwebtoken:jjwt:0.9.0"

    testCompile('org.springframework.boot:spring-boot-starter-test')

    testCompile('io.projectreactor:reactor-test')

    compile('com.fasterxml.jackson.core:jackson-databind')
}

Проблема в этих строках:

PageView pg = PageView.builder (). CreateDate (LocalDateTime.now ()). URL (uri) .build (); pageViewRepository.save (pg) .subscribe (pg1 -> {user.getPageviews (). add (pg1);});

который вешает браузер (продолжает ждать ответа).

По сути, я хочу вот что: не должен использовать block (), который даже не работает в коде веб-фильтра, так как block также приводит к зависанию браузера. Сохранить просмотр страницы в Монго БД. После того, как оно сохранено, просмотр страницы имеет действительный идентификатор mongodb, который необходимо сохранить в качестве ссылки в списке просмотров пользователя. Поэтому только после того, как он будет сохранен в БД, следующим шагом будет обновление списка просмотров страниц пользователя. Следующим шагом является сохранение обновленного пользователя без влияния на методы контроллера нисходящего потока, которые также могут обновлять пользователя и, возможно, также должны сохранять пользователя. Все это должно работать в заданном контексте WebFilter.

Как решить эту проблему?

Предоставленное решение должно убедиться, что пользователь сохранен в веб-фильтре, прежде чем перейти к действиям контроллера, некоторые из которых также сохраняют пользователя с другими значениями из параметров строки запроса.

Ответы на вопрос(3)

Ваш ответ на вопрос