Java 如何减少spring引导控制器中的重复代码

Java 如何减少spring引导控制器中的重复代码,java,spring,spring-boot,Java,Spring,Spring Boot,我刚刚开始使用SpringBoot来提供服务。我有几个控制器使用相同的代码在他们的身体。例如,在每个控制器中,我必须检查从请求获得的请求对象是否为null: if (request == null){ throw new InvalidRequestException("the request object is null"); } 我知道在几个控制器中重复代码不是一个好方法,所以我想知道是否有办法防止代码重复,或者spring boot是否有解决上述问题的方法。只需将代码包装在一个方

我刚刚开始使用SpringBoot来提供服务。我有几个控制器使用相同的代码在他们的身体。例如,在每个控制器中,我必须检查从请求获得的请求对象是否为null:

if (request == null){
    throw new InvalidRequestException("the request object is null");
}

我知道在几个控制器中重复代码不是一个好方法,所以我想知道是否有办法防止代码重复,或者spring boot是否有解决上述问题的方法。

只需将代码包装在一个方法中:

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();
  }
}

基本上,您所做的是参数验证。这是一种横切关注点,是使用AOP方法的完美用例

Spring提供了非常好的方法来实现这一点

您可以像这样简单地使用
@validate

@PostMapping
    public ResponseEntity<Void> someMEthod(@Validated(CustomChecks.class) @RequestBody request yourRequest)
@PostMapping
公共响应属性someMEthod(@Validated(CustomChecks.class)@RequestBody request yourRequest)
然后可以将所有验证逻辑放入CustomChecks类中。(您可以找到大量示例)

如果您有非常小的通用验证,那么您也可以使用注释

在您的情况下,只需在请求类上添加@NotNull注释即可。检查这个


希望这对您使用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");
        }
   }
}
春季AOP

创建如下所示的方面类:

@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注释来处理文章中给出的具体案例


此外,使用过滤器可能是处理“执行控制器操作的先决条件”情况的另一种选择。我们使用复杂的逻辑来解决设计中所有控制器所需的访问权限。我们使用了一个过滤器来处理这个问题。

最好使用@Valid来检查有效负载,而不用手动检查。请按照下面的解释

您可以使用“导入org.springframework.validation.Errors;”和@Valid,如下所示

@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
}

在这个解释中,我使用了Person有效负载@Valid检查有效负载内容。一旦您收到没有必填字段的有效负载,您可以使用错误处理这种情况

您可以提供控制器的示例,特别是关于该请求对象来自何处的示例吗?您通常会使用包含公共代码的方法。但是对于这个具体的例子,请求怎么可能是空的呢?对于这种特殊情况,使用Bean验证和
@RequestBody@Valid MyObject request