Я только начал использовать Spring boot для своих услуг. У меня есть несколько контроллеров, которые используют один и тот же код в своих телах. например, в каждом контроллере я должен проверить, является ли объект запроса, полученный из запроса, нулевым или нет:
if (request == null){
throw new InvalidRequestException("the request object is null");
}
Я знаю, что повторение кода в нескольких контроллерах не является хорошим подходом, поэтому мне было интересно, есть ли способ предотвратить повторение кода или есть ли у весенней загрузки решение упомянутой проблемы.
Обычно вы используете метод, содержащий общий код. Но как в этом конкретном примере запрос может быть нулевым?
В этом конкретном случае используйте Bean Validation и @RequestBody @Valid MyObject request.




Просто оберните этот код в метод:
protected void checkRequest(Object request){
if (request == null){
throw new InvalidRequestException("the request object is null");
}
}
и объявите его в классе AbstractController. Позвольте вашим контроллерам расширить этот класс.
Сделайте так, чтобы ваш уровень обслуживания генерировал пользовательские исключения в соответствии с вашими условиями и использовал @ControllerAdvice в вашем контроллере для обработки вывода при возникновении исключений.
Один из подходов - создать абстрактный класс, который будет содержать метод упаковки, который будет вызываться расширяющим контроллером.
public abstract class CoreController {
protected void validateRequest(MyRequest request) {
if (request == null) throw new InvalidRequestException("the request object is null");
}
}
Расширьте свои контроллеры с помощью этого класса и вызовите метод validateRequest
public class MyController extends CoreController {
@PostMapping("/some_endpoint")
public MyResponse endpointMethod (@RequestBody MyRequest request) {
validateRequest(request);
...
return new MyResponse();
}
}
В основном то, что вы делаете, - это проверка параметров. Это своего рода сквозные проблемы и идеальный вариант использования подхода АОП.
Spring предоставляет очень хороший способ сделать это
вы можете просто использовать @validate вот так
@PostMapping
public ResponseEntity<Void> someMEthod(@Validated(CustomChecks.class) @RequestBody request yourRequest)
Затем вы можете поместить всю свою логику проверки в класс CustomChecks. (Вы можете найти несколько примеров)
если у вас очень маленькие и универсальные проверки, вы также можете использовать аннотации.
в вашем случае просто поместите аннотацию @Ненулевой в свой класс запроса. Отметьте это пример
надеюсь это поможет
Вы используете SpringBoot, поэтому в своем приложении, где вы определяете аннотацию @SpringBootApplication, вы можете указать следующий @Bean:
@Bean
public HttpRequestHandler httpRequestHandler () {
return new MyHttpRequestHandler();
}
Также создайте класс MyHttpRequestHandler, где вы можете сделать любую свою логику с этим:
public class MyHttpRequestHandler implements HttpRequestHandler {
@Override
public void handleRequest (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (request == null) {
throw new InvalidRequestException("the request object is null");
}
}
}
Spring АОП?
создайте класс Aspect следующим образом:
@Aspect
class AopDemo{
@Around("execution(* com.demo.controller.*(..))")
public Object release(JoinPoint jp){
try{
Object[] args = jp.getArgs();
for(Object arg: args){
if (arg == null){
throw new InvalidRequestException("the request object is null");
}
}
return jp.proceed(args);
}catch(InvalidRequestException ire){
// handle InvalidRequestException
}catch(Exception ex){
// handle Exception
}
}
}
Я согласен с @Niraj Sonawane на использование аннотации @Validated для решения конкретного случая, указанного в сообщении.
В дополнение к этому, использование фильтров может быть еще одним вариантом для работы со случаями, которые попадают в «предварительные требования для выполнения действий контроллера». Мы использовали сложную логику для разрешения прав доступа, которые требовались для всех контроллеров, которые у нас были в проекте. И мы использовали фильтр, чтобы справиться с этим.
Лучше использовать @Действительный для проверки полезной нагрузки, не проверяя ее вручную. Пожалуйста, следуйте приведенному ниже объяснению.
Вы можете использовать «import org.springframework.validation.Errors;» и @Действительный, как показано ниже.
@PostMapping("/test")
public ResponseEntity<String> editStatus(@Valid @RequestBody Person person, Errors errors) {
String responseMessage;
if (errors.hasErrors()) {
responseMessage = "'" + errors.getFieldError().getField() + "' " + errors.getFieldError().getDefaultMessage();
} else {
// You can do ur logic here
responseMessage = "result";
}
return ResponseEntity.accepted().body(responseMessage);
}
Полезную нагрузку человека вы можете проверить, как показано ниже.
public class Person {
@NotNull
private String firstName;
@NotNull
private String lastName;
private String city;
//Getter
//Setter
}
В этом объяснении я использовал полезную нагрузку Человек. @Действительный проверяет содержимое полезной нагрузки. Как только вы получите полезную нагрузку без обязательных полей, вы можете справиться с ситуацией, используя ошибки.
Можете ли вы предоставить образец контроллера, особенно относительно того, откуда берется этот объект запроса?