У меня есть запрос data transfer object (DTO), который предназначен для приема тела POST API. Этот DTO имеет ключ ENUM объекта X. Я создал настраиваемую аннотацию проверки и проверяю, что ENUM существует в моей системе через его репозиторий сущностей, который возвращает сущность или ноль в зависимости от его существования.
Я хочу передать этот проверенный объект X своему контроллеру. Я не хочу снова получать эту сущность X с помощью ENUM в моей бизнес-логике, потому что я уже сделал это при проверке.
Я сохраняю этот объект в статической переменной из класса валидатора аннотаций и обращаюсь к нему позже, когда я хочу это в бизнес-логике, но если API попадает одновременно, моя статическая переменная переопределяется вторым запросом и когда моя бизнес-логика первого запроса извлекает X entity, он получает объект второго запроса из-за проблемы переопределения.
Я хочу, чтобы этот объект сущности X находился в пределах своего собственного цикла запроса и уничтожался или сборщик мусора после завершения запроса, как и другие объекты. Как я могу этого добиться?
Мой пользовательский валидатор:
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ValidateXimpl.class)
@Documented
public @interface ValidateX {
String message() default "Message";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default{};
}
Реализация кастомного валидатора:
public class ValidateXimpl implements ConstraintValidator<ValidateX, String> {
@Autowired
DBRepo dbRepo;
@Override
public void initialize(ValidateX annotation) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext ctx) {
try {
XEntity X = dbRepo.findByEnum(value); // I want this entity in my controller
return (!value.isEmpty() && X != null);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
Мой DTO, в котором я разместил свою проверку:
public class DTO{
....
@ValidateX
String xEntityEnum
....
}
Мой контроллер:
@RequestMapping(value = '/x', method = RequestMethod.POST)
public @ResponseBody
Map<String, Object> createX(@Validated @RequestBody DTO dto, BindingResult errors) {
// I want that entity here which I get from db repo in my validator
}
это пример: stackoverflow.com/a/28010820/3959856
Нет, я создал другой объект в моем настраиваемом валидаторе и хочу, чтобы этот объект был передан в контроллер.
Хмм хорошо. один из способов - просто проверить данные, а затем создать новый объект в методе get для этого поля в dto. это сработает? кстати, какой-нибудь код поможет
Ваш маркированный список делает ваш вопрос нечитаемым. Пожалуйста, перефразируйте свой вопрос. Не используйте маркированный список, если вы действительно не перечисляете элементы. Для вопроса используйте обычную прозу.
@MarkRotteveel Редактирую свой вопрос. Спасибо, что указали на это. Я позабочусь о




Я только что решил это с RequestContextHolder
Код решения:
Реализация валидатора
public class ValidateXimpl implements ConstraintValidator<ValidateX, String> {
@Autowired
DBRepo dbRepo;
@Override
public void initialize(ValidateX annotation) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext ctx) {
try {
XEntity X = dbRepo.findByEnum(value); // I want this entity in my controller
RequestContextHolder.getRequestAttributes().setAttribute(
"XEntity", X, RequestAttributes.SCOPE_REQUEST
); // I saved it in RequestContextHolder
return (!value.isEmpty() && X != null);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
Мой Контроллер
@RequestMapping(value = '/x', method = RequestMethod.POST)
public @ResponseBody
Map<String, Object> createX(@Validated @RequestBody DTO dto, BindingResult errors) {
// I want that entity here which I get from db repo in my validator
System.out.println(
RequestContextHolder.getRequestAttributes().getAttribute(
"XEntity",
RequestAttributes.SCOPE_REQUEST
)
); // I get that from RequestContextHolder
}
Это то, что мне действительно нужно. RequestContextHolder очищается при завершении запроса и также доступен только в собственном потоке запроса из-за настройки области запроса в функции setAttribute.
Если вы используете объект формы для получения параметров запроса, вы можете проверить поля в этом объекте, и он будет передан методу контроллера.