feat:框架完善,增加完整的支持
This commit is contained in:
parent
9100c2214a
commit
c6682526eb
@ -0,0 +1,20 @@
|
|||||||
|
package com.flyfish.framework.validation.spi;
|
||||||
|
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.TYPE;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指定动态分组
|
||||||
|
* @author wangyu
|
||||||
|
*/
|
||||||
|
@Target({TYPE})
|
||||||
|
@Retention(RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface ConditionalGroup {
|
||||||
|
|
||||||
|
Class<? extends ConditionalValidGroupProvider<?>>[] value() default {};
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.flyfish.framework.validation.spi;
|
||||||
|
|
||||||
|
import javax.validation.groups.Default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 条件化的验证分组
|
||||||
|
*
|
||||||
|
* @author wangyu
|
||||||
|
*/
|
||||||
|
public interface ConditionalValidGroupProvider<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据数据返回不同的验证分组
|
||||||
|
*
|
||||||
|
* @param data 数据
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
Class<?>[] provide(T data);
|
||||||
|
}
|
@ -24,6 +24,6 @@ public class MoneyValidator implements ConstraintValidator<Money, Long> {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid(Long value, ConstraintValidatorContext context) {
|
public boolean isValid(Long value, ConstraintValidatorContext context) {
|
||||||
return value >= 9;
|
return null == value || value >= 9;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,9 @@ public class PhoneValidator implements ConstraintValidator<Phone, String> {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid(String value, ConstraintValidatorContext context) {
|
public boolean isValid(String value, ConstraintValidatorContext context) {
|
||||||
|
if (null == value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
if (type == PhoneType.ALL) {
|
if (type == PhoneType.ALL) {
|
||||||
return isMobile(value) || isTel(value);
|
return isMobile(value) || isTel(value);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,10 @@ package com.flyfish.framework.configuration;
|
|||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.flyfish.framework.configuration.resolver.PageQueryArgumentResolver;
|
import com.flyfish.framework.configuration.resolver.PageQueryArgumentResolver;
|
||||||
|
import com.flyfish.framework.configuration.resolver.RequestContextBodyArgumentResolver;
|
||||||
import com.flyfish.framework.configuration.resolver.UserArgumentResolver;
|
import com.flyfish.framework.configuration.resolver.UserArgumentResolver;
|
||||||
|
import com.flyfish.framework.configuration.resolver.ValidRequestBodyMethodArgumentResolver;
|
||||||
|
import com.flyfish.framework.context.SpringContext;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
@ -17,7 +20,9 @@ import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
|||||||
import org.springframework.web.reactive.config.EnableWebFlux;
|
import org.springframework.web.reactive.config.EnableWebFlux;
|
||||||
import org.springframework.web.reactive.config.WebFluxConfigurer;
|
import org.springframework.web.reactive.config.WebFluxConfigurer;
|
||||||
import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
|
import org.springframework.web.reactive.result.method.annotation.ArgumentResolverConfigurer;
|
||||||
|
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,9 +38,6 @@ public class WebfluxConfig implements WebFluxConfigurer {
|
|||||||
@Value("${spring.jackson.date-format}")
|
@Value("${spring.jackson.date-format}")
|
||||||
private String dateFormat = "yyyy-MM-dd HH:mm:ss";
|
private String dateFormat = "yyyy-MM-dd HH:mm:ss";
|
||||||
|
|
||||||
// @Resource
|
|
||||||
// private RequestMappingHandlerAdapter requestMappingHandlerAdapter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure resolvers for custom {@code @RequestMapping} method arguments.
|
* Configure resolvers for custom {@code @RequestMapping} method arguments.
|
||||||
*
|
*
|
||||||
@ -44,10 +46,11 @@ public class WebfluxConfig implements WebFluxConfigurer {
|
|||||||
@Override
|
@Override
|
||||||
public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
|
public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
|
||||||
ReactiveAdapterRegistry registry = ReactiveAdapterRegistry.getSharedInstance();
|
ReactiveAdapterRegistry registry = ReactiveAdapterRegistry.getSharedInstance();
|
||||||
|
ServerCodecConfigurer serverCodecConfigurer = SpringContext.getBean(ServerCodecConfigurer.class);
|
||||||
configurer.addCustomResolver(new PageQueryArgumentResolver(registry));
|
configurer.addCustomResolver(new PageQueryArgumentResolver(registry));
|
||||||
configurer.addCustomResolver(new UserArgumentResolver(registry));
|
configurer.addCustomResolver(new UserArgumentResolver(registry));
|
||||||
// configurer.addCustomResolver(new RequestContextBodyArgumentResolver(
|
configurer.addCustomResolver(new ValidRequestBodyMethodArgumentResolver(serverCodecConfigurer.getReaders(), registry));
|
||||||
// requestMappingHandlerAdapter.getMessageReaders(), registry));
|
configurer.addCustomResolver(new RequestContextBodyArgumentResolver(serverCodecConfigurer.getReaders(), registry));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.flyfish.framework.configuration.annotations;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 附带校验的请求体
|
||||||
|
* 天然支持条件校验
|
||||||
|
* @author wangyu
|
||||||
|
*/
|
||||||
|
@Target(ElementType.PARAMETER)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface ValidRequestBody {
|
||||||
|
|
||||||
|
boolean required() default true;
|
||||||
|
}
|
@ -17,7 +17,7 @@ import reactor.core.publisher.Mono;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 附带上下文你的请求参数解析器
|
* 附带上下文里的请求参数解析器
|
||||||
*
|
*
|
||||||
* @author wangyu
|
* @author wangyu
|
||||||
*/
|
*/
|
||||||
@ -25,7 +25,6 @@ public class RequestContextBodyArgumentResolver extends AbstractMessageReaderArg
|
|||||||
|
|
||||||
public RequestContextBodyArgumentResolver(List<HttpMessageReader<?>> readers,
|
public RequestContextBodyArgumentResolver(List<HttpMessageReader<?>> readers,
|
||||||
ReactiveAdapterRegistry registry) {
|
ReactiveAdapterRegistry registry) {
|
||||||
|
|
||||||
super(readers, registry);
|
super(readers, registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,7 +37,6 @@ public class RequestContextBodyArgumentResolver extends AbstractMessageReaderArg
|
|||||||
@Override
|
@Override
|
||||||
public Mono<Object> resolveArgument(
|
public Mono<Object> resolveArgument(
|
||||||
MethodParameter param, BindingContext bindingContext, ServerWebExchange exchange) {
|
MethodParameter param, BindingContext bindingContext, ServerWebExchange exchange) {
|
||||||
|
|
||||||
RequestBody ann = param.getParameterAnnotation(RequestBody.class);
|
RequestBody ann = param.getParameterAnnotation(RequestBody.class);
|
||||||
Assert.state(ann != null, "No RequestBody annotation");
|
Assert.state(ann != null, "No RequestBody annotation");
|
||||||
return readBody(param, ann.required(), bindingContext, exchange)
|
return readBody(param, ann.required(), bindingContext, exchange)
|
||||||
|
@ -0,0 +1,191 @@
|
|||||||
|
package com.flyfish.framework.configuration.resolver;
|
||||||
|
|
||||||
|
import com.flyfish.framework.configuration.annotations.ValidRequestBody;
|
||||||
|
import com.flyfish.framework.validation.spi.ConditionalGroup;
|
||||||
|
import com.flyfish.framework.validation.spi.ConditionalValidGroupProvider;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
import org.springframework.core.*;
|
||||||
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
|
import org.springframework.core.codec.DecodingException;
|
||||||
|
import org.springframework.core.codec.Hints;
|
||||||
|
import org.springframework.core.io.buffer.DataBuffer;
|
||||||
|
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||||
|
import org.springframework.data.util.CastUtils;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.codec.HttpMessageReader;
|
||||||
|
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||||
|
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
import org.springframework.lang.Nullable;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.web.bind.support.WebExchangeBindException;
|
||||||
|
import org.springframework.web.bind.support.WebExchangeDataBinder;
|
||||||
|
import org.springframework.web.reactive.BindingContext;
|
||||||
|
import org.springframework.web.reactive.result.method.annotation.AbstractMessageReaderArgumentResolver;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
import org.springframework.web.server.ServerWebInputException;
|
||||||
|
import org.springframework.web.server.UnsupportedMediaTypeStatusException;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import javax.validation.groups.Default;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 私有校验逻辑支持的body
|
||||||
|
*
|
||||||
|
* @author wangyu
|
||||||
|
* 支持条件校验,更高级的骚操作,大量重写
|
||||||
|
*/
|
||||||
|
public class ValidRequestBodyMethodArgumentResolver extends AbstractMessageReaderArgumentResolver {
|
||||||
|
|
||||||
|
private static final Set<HttpMethod> SUPPORTED_METHODS =
|
||||||
|
EnumSet.of(HttpMethod.POST, HttpMethod.PUT, HttpMethod.PATCH);
|
||||||
|
|
||||||
|
private final List<MediaType> supportedMediaTypes;
|
||||||
|
|
||||||
|
public ValidRequestBodyMethodArgumentResolver(List<HttpMessageReader<?>> readers, ReactiveAdapterRegistry registry) {
|
||||||
|
super(readers, registry);
|
||||||
|
supportedMediaTypes = readers.stream()
|
||||||
|
.flatMap(converter -> converter.getReadableMediaTypes().stream())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsParameter(MethodParameter parameter) {
|
||||||
|
return parameter.hasParameterAnnotation(ValidRequestBody.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Object> resolveArgument(
|
||||||
|
MethodParameter param, BindingContext bindingContext, ServerWebExchange exchange) {
|
||||||
|
|
||||||
|
ValidRequestBody ann = param.getParameterAnnotation(ValidRequestBody.class);
|
||||||
|
Assert.state(ann != null, "No RequestBody annotation");
|
||||||
|
return readBody(param, ann.required(), bindingContext, exchange);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Mono<Object> readBody(MethodParameter bodyParam, @Nullable MethodParameter actualParam,
|
||||||
|
boolean isBodyRequired, BindingContext bindingContext, ServerWebExchange exchange) {
|
||||||
|
|
||||||
|
ResolvableType bodyType = ResolvableType.forMethodParameter(bodyParam);
|
||||||
|
ResolvableType actualType = (actualParam != null ? ResolvableType.forMethodParameter(actualParam) : bodyType);
|
||||||
|
Class<?> resolvedType = bodyType.resolve();
|
||||||
|
ReactiveAdapter adapter = (resolvedType != null ? getAdapterRegistry().getAdapter(resolvedType) : null);
|
||||||
|
ResolvableType elementType = (adapter != null ? bodyType.getGeneric() : bodyType);
|
||||||
|
isBodyRequired = isBodyRequired || (adapter != null && !adapter.supportsEmpty());
|
||||||
|
|
||||||
|
ServerHttpRequest request = exchange.getRequest();
|
||||||
|
ServerHttpResponse response = exchange.getResponse();
|
||||||
|
|
||||||
|
MediaType contentType = request.getHeaders().getContentType();
|
||||||
|
MediaType mediaType = (contentType != null ? contentType : MediaType.APPLICATION_OCTET_STREAM);
|
||||||
|
|
||||||
|
if (mediaType.isCompatibleWith(MediaType.APPLICATION_FORM_URLENCODED)) {
|
||||||
|
return Mono.error(new IllegalStateException(
|
||||||
|
"In a WebFlux application, form data is accessed via ServerWebExchange.getFormData()."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug(exchange.getLogPrefix() + (contentType != null ?
|
||||||
|
"Content-Type:" + contentType :
|
||||||
|
"No Content-Type, using " + MediaType.APPLICATION_OCTET_STREAM));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (HttpMessageReader<?> reader : getMessageReaders()) {
|
||||||
|
if (reader.canRead(elementType, mediaType)) {
|
||||||
|
Map<String, Object> readHints = Hints.from(Hints.LOG_PREFIX_HINT, exchange.getLogPrefix());
|
||||||
|
if (adapter != null && adapter.isMultiValue()) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug(exchange.getLogPrefix() + "0..N [" + elementType + "]");
|
||||||
|
}
|
||||||
|
Flux<?> flux = reader.read(actualType, elementType, request, response, readHints);
|
||||||
|
flux = flux.onErrorResume(ex -> Flux.error(handleReadError(bodyParam, ex)));
|
||||||
|
if (isBodyRequired) {
|
||||||
|
flux = flux.switchIfEmpty(Flux.error(() -> handleMissingBody(bodyParam)));
|
||||||
|
}
|
||||||
|
flux = flux.doOnNext(target -> validate(target, bodyParam, bindingContext, exchange));
|
||||||
|
return Mono.just(adapter.fromPublisher(flux));
|
||||||
|
} else {
|
||||||
|
// Single-value (with or without reactive type wrapper)
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug(exchange.getLogPrefix() + "0..1 [" + elementType + "]");
|
||||||
|
}
|
||||||
|
Mono<?> mono = reader.readMono(actualType, elementType, request, response, readHints);
|
||||||
|
mono = mono.onErrorResume(ex -> Mono.error(handleReadError(bodyParam, ex)));
|
||||||
|
if (isBodyRequired) {
|
||||||
|
mono = mono.switchIfEmpty(Mono.error(() -> handleMissingBody(bodyParam)));
|
||||||
|
}
|
||||||
|
mono = mono.doOnNext(target -> validate(target, bodyParam, bindingContext, exchange));
|
||||||
|
return (adapter != null ? Mono.just(adapter.fromPublisher(mono)) : Mono.from(mono));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No compatible reader but body may be empty..
|
||||||
|
|
||||||
|
HttpMethod method = request.getMethod();
|
||||||
|
if (contentType == null && method != null && SUPPORTED_METHODS.contains(method)) {
|
||||||
|
Flux<DataBuffer> body = request.getBody().doOnNext(buffer -> {
|
||||||
|
DataBufferUtils.release(buffer);
|
||||||
|
// Body not empty, back to 415..
|
||||||
|
throw new UnsupportedMediaTypeStatusException(mediaType, this.supportedMediaTypes, elementType);
|
||||||
|
});
|
||||||
|
if (isBodyRequired) {
|
||||||
|
body = body.switchIfEmpty(Mono.error(() -> handleMissingBody(bodyParam)));
|
||||||
|
}
|
||||||
|
return (adapter != null ? Mono.just(adapter.fromPublisher(body)) : Mono.from(body));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Mono.error(new UnsupportedMediaTypeStatusException(mediaType, this.supportedMediaTypes, elementType));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 核心,从对象抽取出验证的group
|
||||||
|
*
|
||||||
|
* @param target 目标对象
|
||||||
|
* @return 结果
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
private Object[] extractValidationHints(Object target) {
|
||||||
|
ConditionalGroup group = AnnotationUtils.findAnnotation(target.getClass(), ConditionalGroup.class);
|
||||||
|
if (null != group && ArrayUtils.isNotEmpty(group.value())) {
|
||||||
|
List<Class<?>> groups = new ArrayList<>();
|
||||||
|
for (Class<? extends ConditionalValidGroupProvider<?>> clazz : group.value()) {
|
||||||
|
try {
|
||||||
|
groups.addAll(Arrays.asList(clazz.newInstance().provide(CastUtils.cast(target))));
|
||||||
|
} catch (InstantiationException | IllegalAccessException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CollectionUtils.isNotEmpty(groups)) {
|
||||||
|
return groups.toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Object[]{};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validate(Object target, MethodParameter param,
|
||||||
|
BindingContext binding, ServerWebExchange exchange) {
|
||||||
|
Object[] validationHints = extractValidationHints(target);
|
||||||
|
String name = Conventions.getVariableNameForParameter(param);
|
||||||
|
WebExchangeDataBinder binder = binding.createDataBinder(exchange, target, name);
|
||||||
|
binder.validate(validationHints);
|
||||||
|
if (binder.getBindingResult().hasErrors()) {
|
||||||
|
throw new WebExchangeBindException(param, binder.getBindingResult());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Throwable handleReadError(MethodParameter parameter, Throwable ex) {
|
||||||
|
return (ex instanceof DecodingException ?
|
||||||
|
new ServerWebInputException("Failed to read HTTP message", parameter, ex) : ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ServerWebInputException handleMissingBody(MethodParameter parameter) {
|
||||||
|
String paramInfo = parameter.getExecutable().toGenericString();
|
||||||
|
return new ServerWebInputException("Request body is missing: " + paramInfo, parameter);
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import com.flyfish.framework.bean.Result;
|
|||||||
import com.flyfish.framework.bean.SyncVo;
|
import com.flyfish.framework.bean.SyncVo;
|
||||||
import com.flyfish.framework.configuration.annotations.CurrentUser;
|
import com.flyfish.framework.configuration.annotations.CurrentUser;
|
||||||
import com.flyfish.framework.configuration.annotations.PagedQuery;
|
import com.flyfish.framework.configuration.annotations.PagedQuery;
|
||||||
|
import com.flyfish.framework.configuration.annotations.ValidRequestBody;
|
||||||
import com.flyfish.framework.constant.ReactiveConstants;
|
import com.flyfish.framework.constant.ReactiveConstants;
|
||||||
import com.flyfish.framework.context.UserContext;
|
import com.flyfish.framework.context.UserContext;
|
||||||
import com.flyfish.framework.domain.base.Domain;
|
import com.flyfish.framework.domain.base.Domain;
|
||||||
@ -16,7 +17,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,7 +51,7 @@ public abstract class BaseController<T extends Domain, Q extends Qo<T>> implemen
|
|||||||
|
|
||||||
@PostMapping("")
|
@PostMapping("")
|
||||||
@Operation.Create
|
@Operation.Create
|
||||||
public Result<T> create(@RequestBody @Valid T entity, @CurrentUser User user) {
|
public Result<T> create(@ValidRequestBody T entity, @CurrentUser User user) {
|
||||||
userContext.setUser(user);
|
userContext.setUser(user);
|
||||||
return Result.accept(service.create(entity));
|
return Result.accept(service.create(entity));
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ public abstract class BaseController<T extends Domain, Q extends Qo<T>> implemen
|
|||||||
|
|
||||||
@PutMapping("{id}")
|
@PutMapping("{id}")
|
||||||
@Operation.Update
|
@Operation.Update
|
||||||
public Result<T> update(@RequestBody @Valid T entity, @CurrentUser User user) {
|
public Result<T> update(@ValidRequestBody T entity, @CurrentUser User user) {
|
||||||
userContext.setUser(user);
|
userContext.setUser(user);
|
||||||
return Result.accept(service.updateSelectiveById(entity));
|
return Result.accept(service.updateSelectiveById(entity));
|
||||||
}
|
}
|
||||||
@ -110,7 +110,7 @@ public abstract class BaseController<T extends Domain, Q extends Qo<T>> implemen
|
|||||||
* reactive接口
|
* reactive接口
|
||||||
*/
|
*/
|
||||||
@PostMapping(value = "", headers = ReactiveConstants.USE_REACTIVE)
|
@PostMapping(value = "", headers = ReactiveConstants.USE_REACTIVE)
|
||||||
public Mono<Result<T>> reactiveCreate(@RequestBody @Valid T entity) {
|
public Mono<Result<T>> reactiveCreate(@ValidRequestBody T entity) {
|
||||||
return reactiveService.create(entity).map(Result::accept);
|
return reactiveService.create(entity).map(Result::accept);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ public abstract class BaseController<T extends Domain, Q extends Qo<T>> implemen
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PutMapping(value = "{id}", headers = ReactiveConstants.USE_REACTIVE)
|
@PutMapping(value = "{id}", headers = ReactiveConstants.USE_REACTIVE)
|
||||||
public Mono<Result<T>> reactiveUpdate(@RequestBody @Valid T entity) {
|
public Mono<Result<T>> reactiveUpdate(@ValidRequestBody T entity) {
|
||||||
return reactiveService.updateById(entity)
|
return reactiveService.updateById(entity)
|
||||||
.map(Result::accept)
|
.map(Result::accept)
|
||||||
.defaultIfEmpty(Result.notFound());
|
.defaultIfEmpty(Result.notFound());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user