【问题标题】:How can i reduce repetitive code in spring boot controllers如何减少 Spring Boot 控制器中的重复代码
【发布时间】:2018-11-02 08:46:27
【问题描述】:

我刚刚开始为我的服务使用 Spring Boot。我很少有控制器在其体内使用相同的代码。例如,在每个控制器中,我必须检查从请求中获得的请求对象是否为空:

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

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

【问题讨论】:

  • 能否提供控制器的示例,尤其是请求对象来自哪里?
  • 您通常会使用一种方法来包含公共代码。但是对于这个具体的例子,请求怎么可能是空的呢?
  • 对于这种特殊情况,请使用 Bean Validation 和 @RequestBody @Valid MyObject request

标签: java spring spring-boot


【解决方案1】:

你使用的是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");
        }
   }
}

【讨论】:

    【解决方案2】:

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

    Spring 提供了非常好的方法

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

    @PostMapping
        public ResponseEntity<Void> someMEthod(@Validated(CustomChecks.class) @RequestBody request yourRequest)
    

    然后您可以将所有验证逻辑放入 CustomChecks 类中。 (你可以找到一些例子)

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

    在您的情况下,只需将 @NotNull 注释放在您的请求类上。检查这个example

    希望对你有帮助

    【讨论】:

      【解决方案3】:

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

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

      并在AbstractController 类中声明它。让你的控制器扩展这个类。

      【讨论】:

        【解决方案4】:

        让您的服务层根据您的条件抛出自定义异常,并在您的控制器中使用@ControllerAdvice 来处理抛出异常时的输出。

        【讨论】:

          【解决方案5】:

          一种方法是创建一个包含包装方法的抽象类,该方法将由扩展控制器调用。

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

          【讨论】:

            【解决方案6】:

            Spring AOP?

            像这样创建一个 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
                    }
                }
            
            }
            

            【讨论】:

              【解决方案7】:

              我同意@Niraj Sonawane 使用@Validated 注解来处理帖子中给出的具体情况。

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

              【讨论】:

                【解决方案8】:

                最好使用 @Valid 来检查有效负载,而无需手动检查。请按照以下说明进行操作。

                您可以使用“import 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 检查负载内容。一旦您收到没有必填字段的有效负载,您可以使用 errors 来处理这种情况。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2022-01-23
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多