#spring-boot #hibernate-validator #cglib #nhibernate-validator
#пружинный ботинок #спящий режим-валидатор #cglib #nhibernate-валидатор
Вопрос:
Я создал приложение spring boot (пользователь spring-boot-starter-parent версии 2.2.2.RELEASE) с контроллерами Rest, которые работают нормально, теперь я добавил зависимость к :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
И добавили @Validated в мой класс контроллера, чтобы все методы в нем должны быть проверены:
@RestController
@Validated
public class UserController {
@Autowired
private UserService userService;
@PostConstruct
public void init() {
System.out.println("test");
}
}
Теперь методы контроллера при вызове начинают выдавать NullPointerExceptions, потому что UserService имеет значение null; Я выполнил @PostConstruct в качестве теста. По-видимому, он вызывается на обычном нерегулируемом компоненте, у которого поля автоматически подключены правильно. Но при вызове контроллера через HTTP этот нерегулируемый компонент не вызывается, но это компонент класса UserController $$EnhancerBySpringCGLIB $$, и у него пользовательский контроллер не подключен автоматически. Я действительно не знаю, почему, потому что это должно быть очень просто, насколько я знаю, настраивать особо нечего. Поэтому я предполагаю, что по какой-то причине spring не вводит зависимости в расширенные классы CGLIB или просто вводит их в неправильный класс. Когда я удаляю @Validated, все снова работает нормально, но, конечно, проверки нет.
Ответ №1:
Это была самая нелепая ошибка, с которой я сталкивался целую вечность. Я по ошибке установил методы контроллера в моем первоначальном проекте как частные. Это привело к тому, что CGLIB не улучшал их, а вместо этого просто использовал их с исходным кодом. Весна не жаловалась и с удовольствием использует эти методы
Комментарии:
1. Хорошо, рад, что вы нашли это. Спасибо, что поделились своим решением.
Ответ №2:
Используя предоставленный вами код и создавая фиктивный UserService
класс, HTTP-запросы отлично работают в других средах.
Чтобы помочь решить проблему, с которой вы столкнулись, вам следует создать новый проект, добавив lombok
зависимости , starter-web
, и starter-validation
. Создайте следующие классы.
@RestController
@Validated
public class UserController {
@Autowired
private UserService userService;
@PostConstruct
public void init() {
System.out.println("test");
}
@GetMapping("/test")
public int test(){
return userService.getAge();
}
}
@Data
@Service
public class UserService {
private int age = 21;
}
Затем протестируйте http://localhost:8080/test
Если это не сработает для вас, вам следует попробовать аннулировать ваш кеш и перезапустить IDE. У Intellij есть опция для этого, если вы нажмете на File > Invalidate Caches / Restart ...
нее . Кроме того, вы можете удалить артефакты (или полное локальное хранилище) из своей папки .m2. C:Users<username>.m2repository
и перестроить с помощью maven.
Если это все еще не решает вашу проблему, пожалуйста, обновите свой вопрос более полным воспроизводимым примером вашей проблемы вместе с полным журналом консоли вашей ошибки, и я обновлю свой ответ.
Комментарии:
1. хорошо, сначала я проверил его независимо от IDE, запустив его с помощью mvn spring-boot: run с тем же эффектом. Затем я создал проект с теми же библиотеками, базовыми материалами и контроллером rest. Оказалось, что все работает нормально, и объекты проверены. Я поместил точку останова внутри метода контроллера и увидел, что «this» — это простой класс, в котором поле автоматически подключено. В то время как в исходном проекте это класс класса $$ EnhancerBySpringCGLIB $$, в котором поля не подключены автоматически. Он также имеет CGLIB$CALLBACK_1.target, ссылающийся на исходный класс
2. он также содержит ссылку на фабрику прокси: org.springframework.aop.framework. ProxyFactory: 0 интерфейсов []; 1 советник [org.springframework.aop.support. DefaultPointcutAdvisor: pointcut [AnnotationMatchingPointcut: org.springframework.aop.support.annotation. Аннотацияclassfilter: организация интерфейса.springframework.validation.annotation. Проверено, сопоставитель методов. TRUE]; Так что это также должно быть результатом проверки. Я не уверен, в чем различия, в исходной конфигурации проекта нет специальных аннотаций
3. хорошо, это была супер глупая ошибка, на которую мне потребовалось несколько часов, чтобы заметить. В исходном проекте методы контроллера были закрытыми, и это вызвало эффект, я не могу удалить свой вопрос сейчас :/