我有一个Spring Boot 1.4.2应用程序.在启动期间使用的一些代码如下所示:
@Component
class SystemTypeDetector{
public enum SystemType{ TYPE_A, TYPE_B, TYPE_C }
public SystemType getSystemType(){ return ... }
}
@Component
public class SomeOtherComponent{
@Autowired
private SystemTypeDetector systemTypeDetector;
@PostConstruct
public void startup(){
switch(systemTypeDetector.getSystemType()){ // <-- NPE here in test
case TYPE_A: ...
case TYPE_B: ...
case TYPE_C: ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
有一个组件可以确定系统类型.在从其他组件启动期间使用此组件.在生产中一切正常.
现在我想使用Spring 1.4的@MockBean添加一些集成测试.
测试看起来像这样:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyWebApplication.class, webEnvironment = RANDOM_PORT)
public class IntegrationTestNrOne {
@MockBean
private SystemTypeDetector systemTypeDetectorMock;
@Before
public void initMock(){
Mockito.when(systemTypeDetectorMock.getSystemType()).thenReturn(TYPE_C);
}
@Test
public void testNrOne(){ …Run Code Online (Sandbox Code Playgroud) 我们编写了一个小型Spring Boot REST应用程序,它在另一个REST端点上执行REST请求.
@RequestMapping("/api/v1")
@SpringBootApplication
@RestController
@Slf4j
public class Application
{
@Autowired
private WebClient webClient;
@RequestMapping(value = "/zyx", method = POST)
@ResponseBody
XyzApiResponse zyx(@RequestBody XyzApiRequest request, @RequestHeader HttpHeaders headers)
{
webClient.post()
.uri("/api/v1/someapi")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromObject(request.getData()))
.exchange()
.subscribeOn(Schedulers.elastic())
.flatMap(response ->
response.bodyToMono(XyzServiceResponse.class).map(r ->
{
if (r != null)
{
r.setStatus(response.statusCode().value());
}
if (!response.statusCode().is2xxSuccessful())
{
throw new ProcessResponseException(
"Bad status response code " + response.statusCode() + "!");
}
return r;
}))
.subscribe(body ->
{
// Do various things
}, throwable ->
{
// …Run Code Online (Sandbox Code Playgroud) 我正在尝试在我的WebClient上设置超时,这是当前代码:
SslContext sslContext = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE).build();
ClientHttpConnector httpConnector = new ReactorClientHttpConnector(opt -> {
opt.sslContext(sslContext);
HttpClientOptions option = HttpClientOptions.builder().build();
opt.from(option);
});
return WebClient.builder().clientConnector(httpConnector).defaultHeader("Authorization", xxxx)
.baseUrl(this.opusConfig.getBaseURL()).build();
Run Code Online (Sandbox Code Playgroud)
我需要添加超时和汇集策略,我正在考虑这样的事情:
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(this.applicationConfig.getHttpClientMaxPoolSize());
cm.setDefaultMaxPerRoute(this.applicationConfig.getHttpClientMaxPoolSize());
cm.closeIdleConnections(this.applicationConfig.getServerIdleTimeout(), TimeUnit.MILLISECONDS);
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(this.applicationConfig.getHttpClientSocketTimeout())
.setConnectTimeout(this.applicationConfig.getHttpClientConnectTimeout())
.setConnectionRequestTimeout(this.applicationConfig.getHttpClientRequestTimeout()).build();
CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).setConnectionManager(cm).build();
Run Code Online (Sandbox Code Playgroud)
但我无法弄清楚如何在我的webclient中设置httpClient
现在有两种方法可以在Spring 5中公开http端点.
控制器:通过制作休息控制器.
@RestController
@RequestMapping("persons")
public class PersonController {
@Autowired
private PersonRepo repo;
@GetMapping("/{id}")
public Mono<Person> personById(@PathVariable String id){
retrun repo.findById(id);
}
}
Run Code Online (Sandbox Code Playgroud)路由器:通过路由器.例如:
@Bean
public RouterFunction<ServerResponse> personRoute(PersonRepo repo) {
return route(GET("/persons/{id}"), req -> Mono.justOrEmpty(req.pathVariable("id"))
.flatMap(repo::getById)
.flatMap(p -> ok().syncBody(p))
.switchIfEmpty(notFound().build()));
}
Run Code Online (Sandbox Code Playgroud)使用任何一种方法有任何性能差异吗?从头开始编写应用程序时,我应该使用哪一个.
我试图通过扩展 AbstractErrorWebExceptionHandler 来实现我的自定义 GlobalExceptionHandler 类(默认实现是 DefaultErrorWebExceptionHandler 类),但无法这样做,因为缺少构造函数初始化所需的 bean(如下所述)。我不确定为什么默认情况下会发生这种情况实现工作正常,通过提供我自己的实现,它要求一个 bean,请帮忙
@Component
@Order(-2)
public class GlobalExceptionHandler extends AbstractErrorWebExceptionHandler{
public GlobalExceptionHandler(ErrorAttributes errorAttributes, Resources resources, ApplicationContext applicationContext) {
super(errorAttributes, resources, applicationContext);
}
@Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
return RouterFunctions.route(RequestPredicates.all(),this::formatErrorResponse);
}
private Mono<ServerResponse> formatErrorResponse(ServerRequest request){
Map<String, Object> errorAttributesMap = getErrorAttributes(request, ErrorAttributeOptions.defaults());
int status = (int) Optional.ofNullable(errorAttributesMap.get("status")).orElse(500);
return ServerResponse
.status(status)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(errorAttributesMap));
}
}
Run Code Online (Sandbox Code Playgroud)
我得到的错误是:
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 1 of constructor in com.example.userManagementSystem.demoApp.exception.GlobalExceptionHandler required a bean of type 'org.springframework.boot.autoconfigure.web.WebProperties$Resources' that …Run Code Online (Sandbox Code Playgroud) 这是一段代码
@Test
public void test_mono_void_mono_empty() {
Mono.just("DATA")
.flatMap(s -> Mono.just(s.concat("-")
.concat(s))
.doOnNext(System.out::println)
.then())
.switchIfEmpty(Mono.just("EMPTY")
.doOnNext(System.out::println)
.then())
.block();
}
Run Code Online (Sandbox Code Playgroud)
这将向控制台提供以下结果:
DATA-DATA
EMPTY
Run Code Online (Sandbox Code Playgroud)
这意味着第一个链flatMap被识别为空链。
另一方面,Reactor 具有以下由方法返回的MonoEmpty类。最重要的是,该方法说明如下:Mono.empty()
/**
* Create a {@link Mono} that completes without emitting any item.
*
* <p>
* <img class="marble" src="doc-files/marbles/empty.svg" alt="">
* <p>
* @param <T> the reified {@link Subscriber} type
*
* @return a completed {@link Mono}
*/
public static <T> Mono<T> empty() {
return MonoEmpty.instance();
}
Run Code Online (Sandbox Code Playgroud)
没有发出任何项目- …
我Spring WebFlux在我的项目中使用。我想创建一个拦截器来计算每个API花费的时间。在Spring MVC我们所HandlerInterceptor没有的spring-boot-starter-webflux。我尝试添加spring-boot-starter-web并编写了拦截器,但没有成功。这是代码:
@Component
public class TimeInterceptor implements HandlerInterceptor {
public static Logger logger = Logger.getLogger(TimeInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
long startTime = System.currentTimeMillis();
request.setAttribute("startTime", startTime);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
long totaltime = System.currentTimeMillis() - (long) request.getAttribute("startTime");
request.setAttribute("totaltime", totaltime);
logger.info("Logging total time" + totaltime);
}
...
...
Run Code Online (Sandbox Code Playgroud)
我想向我的应用程序添加类似的功能,并拦截每次调用所花费的时间。
提前致谢。
我正在运行Spring Boot@2.2.x带有公开 WebSocket 端点的服务器。这是我的WebSocketConfiguration:
@Slf4j
@Configuration
public class WebSocketConfiguration {
private static final String WS_PATH = "/ws/notifications";
@Bean
public HandlerMapping webSocketHandlerMapping() {
Map<String, WebSocketHandler> handlersMap = new HashMap<>();
handlersMap.put(WS_PATH, session -> session.send(session.receive()
.map(WebSocketMessage::getPayloadAsText)
.doOnEach(logNext(log::info))
.map(msg -> format("notification for your msg: %s", msg))
.map(session::textMessage)));
SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
handlerMapping.setOrder(Ordered.HIGHEST_PRECEDENCE);
handlerMapping.setUrlMap(handlersMap);
return handlerMapping;
}
@Bean
public WebSocketHandlerAdapter handlerAdapter(WebSocketService webSocketService) {
return new WebSocketHandlerAdapter(webSocketService);
}
@Bean
public WebSocketService webSocketService() {
return new HandshakeWebSocketService(new ReactorNettyRequestUpgradeStrategy());
}
}
Run Code Online (Sandbox Code Playgroud)
问题是如何使用Basic …
websocket spring-boot spring-websocket java-websocket spring-webflux
我有一个使用 WebFlux 和 REST API 的反应式 Spring 应用程序。每当用户调用我的 API 时,我都需要调用公开 WSDL 的 SOAP 服务,执行一些操作并返回结果。
如何将对 SOAP 服务的调用与 Reactive WebFlux 框架结合起来?
在我看来,我可以通过两种不同的方式来做到这一点:
第一种方法是我的偏好,但我不知道该怎么做。
这里也提出了类似的问题: Reactive Spring WebClient - Making a SOAP call,它引用了这篇博客文章(https://blog.godatadriven.com/jaxws-reactive-client)。但我无法让这个例子发挥作用。
在 Gradle 插件中使用,wsdl2java我可以使用异步方法创建客户端界面,但我不明白如何使用它。使用时WebServiceGatewaySupport,我根本不使用生成的接口或其方法。相反,我调用通用marshalSendAndReceive方法
public class MySoapClient extends WebServiceGatewaySupport {
public QueryResponse execute() {
Query query = new ObjectFactory().createQuery();
// Further create and set the domain object …Run Code Online (Sandbox Code Playgroud) 最近我注意到我的团队在如何在 Reactor 中编写测试时遵循两种方法。第一个是借助.block()方法。它看起来像这样:
@Test
void set_entity_version() {
Entity entity = entityRepo.findById(ID)
.block();
assertNotNull(entity);
assertFalse(entity.isV2());
entityService.setV2(ID)
.block();
Entity entity = entityRepo.findById(ID)
.block();
assertNotNull(entity);
assertTrue(entity.isV2());
}
Run Code Online (Sandbox Code Playgroud)
第二个是关于使用StepVerifier. 它看起来像这样:
@Test
void set_entity_version() {
StepVerifier.create(entityRepo.findById(ID))
.assertNext(entity -> {
assertNotNull(entity);
assertFalse(entity.isV2());
})
.verifyComplete();
StepVerifier.create(entityService.setV2(ID)
.then(entityRepo.findById(ID)))
.assertNext(entity -> {
assertNotNull(entity);
assertTrue(entity.isV2());
})
.verifyComplete();
}
Run Code Online (Sandbox Code Playgroud)
以我的拙见,第二种方法看起来更具反应性。此外,官方文档对此也说得很清楚:
StepVerifier 提供了一种声明性方式,通过表达对订阅时将发生的事件的期望,为异步发布者序列创建可验证脚本。
不过,我真的很好奇,应该鼓励使用什么方式作为在 Reactor 中进行测试的主要途径。该.block()方法应该完全放弃还是在某些情况下可能有用?如果是,那么此类案例是什么?
谢谢!
我正在尝试保留一个singleton类,并且我想确保它保持单身。同步方法调用的正确方法是什么Spring WebFlux?
我有以下服务方法:
public Mono<SingletonClass> saveOrUpdate(SingletonClass singletonClass) {
return this.getTheSingletonClass()
.map(someLogicAndSave)
.switchIfEmpty(singletonClassRepository.save(singletonClass);
}
Run Code Online (Sandbox Code Playgroud)
我应该在方法中添加synchronized关键字吗saveOrUpdate?
java ×6
spring ×5
spring-boot ×4
mocking ×2
reactor ×2
unit-testing ×2
reactive ×1
record ×1
rest ×1
sealed ×1
sealed-class ×1
soap ×1
spring-mvc ×1
spring-ws ×1
testing ×1
websocket ×1