有没有办法显示约束消息
Is there a way to show constraint message
我有 class CategoryDTO,我想在其余文档中显示消息 "Description can't be null" 而不是 "Must not be null"。虽然我知道我可以通过创建约束属性文件来更改此消息并添加下面一行
javax.validation.constraints.NotNull.description=Must not be blank or null
但我想在 NotNull 注释中显示消息
public class CategoryDTO
{
private String id;
@NotNull(message = "Description can't be null")
@Size(min = 2 , max=30 , message = "Size must be greater than 2 and less than 30")
private String description;
}
Edit:
@Test
void testFindAll()
{
CategoryDTO fruits = new CategoryDTO();
fruits.setDescription("Fruits");
fruits.setId(UUID.randomUUID().toString());
CategoryDTO Nuts = new CategoryDTO();
Nuts.setDescription("Nuts");
Nuts.setId(UUID.randomUUID().toString());
ConstrainedFields fields = new ConstrainedFields(CategoryDTO.class);
BDDMockito.when(categoryService.findAll()).thenReturn(Flux.just(fruits,Nuts));
webTestClient.get().uri(CategoryController.rootURL + "/categories")
.exchange().expectBodyList(CategoryDTO.class).
hasSize(2).consumeWith(WebTestClientRestDocumentationWrapper.document("v1/get-all-categories",
responseFields(
fields.withPath("[]").description("An array of categories"),
fields.withPath("[].id").description("Id of category"),
fields.withPath("[].description").description("Description of category")
)
));
}
默认情况下,REST Docs 的 ConstraintDescriptions
使用 ResourceBundleConstraintDescriptionResolver
来获取每个约束的描述。顾名思义,它使用 ResourceBundle
来提供描述。您可以提供自己的 ConstraintDescriptionResolver
实现以使用不同的机制。在您的情况下,您希望使用约束注释中的 message
,如以下示例所示:
ConstraintDescriptions descriptions = new ConstraintDescriptions(CategoryDTO.class, (constraint) -> {
return (String) constraint.getConfiguration().get("message");
});
List<String> descriptionProperty = descriptions.descriptionsForProperty("description");
System.out.println(descriptionProperty);
执行时,上面会输出如下:
[Description can't be null, Size must be greater than 2 and less than 30]
如果您不总是配置 message
属性,您可能希望回退到资源包解析器,如下例所示:
ResourceBundleConstraintDescriptionResolver fallback = new ResourceBundleConstraintDescriptionResolver();
ConstraintDescriptions descriptions = new ConstraintDescriptions(CategoryDTO.class, (constraint) -> {
String message = (String) constraint.getConfiguration().get("message");
if (message != null) {
return message;
}
return fallback.resolveDescription(constraint);
});
在 Andy 的回答的帮助下,这里是最终结果
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.snippet.Attributes.key;
import java.util.regex.Pattern;
import org.springframework.restdocs.constraints.ConstraintDescriptions;
import org.springframework.restdocs.constraints.ResourceBundleConstraintDescriptionResolver;
import org.springframework.restdocs.payload.FieldDescriptor;
import org.springframework.util.StringUtils;
public class ConstrainedFields
{
private final ConstraintDescriptions constraintDescriptions;
public ConstrainedFields(Class<?> input) {
ResourceBundleConstraintDescriptionResolver fallback = new ResourceBundleConstraintDescriptionResolver();
this.constraintDescriptions = new ConstraintDescriptions(input, (constraint) -> {
String message = (String) constraint.getConfiguration().get("message");
if (message != null && !Pattern.compile("\{(.*?)\}").matcher(message).matches()) {
return message;
}
return fallback.resolveDescription(constraint);
});
}
public FieldDescriptor withPath(String path)
{
return fieldWithPath(path).attributes(key("constraints").value(StringUtils
.collectionToDelimitedString(constraintDescriptions
.descriptionsForProperty(path), ". ")));
}
}
我有 class CategoryDTO,我想在其余文档中显示消息 "Description can't be null" 而不是 "Must not be null"。虽然我知道我可以通过创建约束属性文件来更改此消息并添加下面一行
javax.validation.constraints.NotNull.description=Must not be blank or null
但我想在 NotNull 注释中显示消息
public class CategoryDTO
{
private String id;
@NotNull(message = "Description can't be null")
@Size(min = 2 , max=30 , message = "Size must be greater than 2 and less than 30")
private String description;
}
Edit:
@Test
void testFindAll()
{
CategoryDTO fruits = new CategoryDTO();
fruits.setDescription("Fruits");
fruits.setId(UUID.randomUUID().toString());
CategoryDTO Nuts = new CategoryDTO();
Nuts.setDescription("Nuts");
Nuts.setId(UUID.randomUUID().toString());
ConstrainedFields fields = new ConstrainedFields(CategoryDTO.class);
BDDMockito.when(categoryService.findAll()).thenReturn(Flux.just(fruits,Nuts));
webTestClient.get().uri(CategoryController.rootURL + "/categories")
.exchange().expectBodyList(CategoryDTO.class).
hasSize(2).consumeWith(WebTestClientRestDocumentationWrapper.document("v1/get-all-categories",
responseFields(
fields.withPath("[]").description("An array of categories"),
fields.withPath("[].id").description("Id of category"),
fields.withPath("[].description").description("Description of category")
)
));
}
默认情况下,REST Docs 的 ConstraintDescriptions
使用 ResourceBundleConstraintDescriptionResolver
来获取每个约束的描述。顾名思义,它使用 ResourceBundle
来提供描述。您可以提供自己的 ConstraintDescriptionResolver
实现以使用不同的机制。在您的情况下,您希望使用约束注释中的 message
,如以下示例所示:
ConstraintDescriptions descriptions = new ConstraintDescriptions(CategoryDTO.class, (constraint) -> {
return (String) constraint.getConfiguration().get("message");
});
List<String> descriptionProperty = descriptions.descriptionsForProperty("description");
System.out.println(descriptionProperty);
执行时,上面会输出如下:
[Description can't be null, Size must be greater than 2 and less than 30]
如果您不总是配置 message
属性,您可能希望回退到资源包解析器,如下例所示:
ResourceBundleConstraintDescriptionResolver fallback = new ResourceBundleConstraintDescriptionResolver();
ConstraintDescriptions descriptions = new ConstraintDescriptions(CategoryDTO.class, (constraint) -> {
String message = (String) constraint.getConfiguration().get("message");
if (message != null) {
return message;
}
return fallback.resolveDescription(constraint);
});
在 Andy 的回答的帮助下,这里是最终结果
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.snippet.Attributes.key;
import java.util.regex.Pattern;
import org.springframework.restdocs.constraints.ConstraintDescriptions;
import org.springframework.restdocs.constraints.ResourceBundleConstraintDescriptionResolver;
import org.springframework.restdocs.payload.FieldDescriptor;
import org.springframework.util.StringUtils;
public class ConstrainedFields
{
private final ConstraintDescriptions constraintDescriptions;
public ConstrainedFields(Class<?> input) {
ResourceBundleConstraintDescriptionResolver fallback = new ResourceBundleConstraintDescriptionResolver();
this.constraintDescriptions = new ConstraintDescriptions(input, (constraint) -> {
String message = (String) constraint.getConfiguration().get("message");
if (message != null && !Pattern.compile("\{(.*?)\}").matcher(message).matches()) {
return message;
}
return fallback.resolveDescription(constraint);
});
}
public FieldDescriptor withPath(String path)
{
return fieldWithPath(path).attributes(key("constraints").value(StringUtils
.collectionToDelimitedString(constraintDescriptions
.descriptionsForProperty(path), ". ")));
}
}