Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 约束检查控制器层与服务层_Java_Spring_Rest_Model View Controller - Fatal编程技术网

Java 约束检查控制器层与服务层

Java 约束检查控制器层与服务层,java,spring,rest,model-view-controller,Java,Spring,Rest,Model View Controller,我正在努力学习spring,并从零开始构建REST应用程序。我不知道应该在哪里检查应用程序中的约束:控制器层还是服务层。 例如,在createuser方法中,我想检查是否有其他用户使用相同的电子邮件,因为电子邮件在我的数据库中是唯一的。我还想检查密码是否匹配(密码和“确认密码”字段)等 目前,在我的实现中,所有这些都是在控制器层进行验证的,所以我可以为每种方法返回一个ResponseEntity @PostMapping("/signUp") public ResponseEnt

我正在努力学习spring,并从零开始构建REST应用程序。我不知道应该在哪里检查应用程序中的约束:控制器层还是服务层。 例如,在createuser方法中,我想检查是否有其他用户使用相同的电子邮件,因为电子邮件在我的数据库中是唯一的。我还想检查密码是否匹配(密码和“确认密码”字段)等

目前,在我的实现中,所有这些都是在控制器层进行验证的,所以我可以为每种方法返回一个ResponseEntity

    @PostMapping("/signUp")
    public ResponseEntity<Object> createUser(@RequestBody RegisterUserDto user) {

        if (userService.getUserByEmail(user.getEmailAddress()) != null) {

            return ResponseEntity.badRequest().body("email already exists");
        }

        if (!user.getPassword().equals(user.getConfirmPassword())) {

            return ResponseEntity.badRequest().body("passwords are not the same");
        }

        User savedUser = null;

        try {

            savedUser = userService.createUser(userDtoConversions.convertToEntityRegister(user));

        } catch (ParseException e) {

            e.printStackTrace();
        }

        URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}")
                .buildAndExpand(savedUser.getId()).toUri();

        return ResponseEntity.created(location).build();
    }

那么哪种方法更好呢?如果我在服务层中检查约束和验证,我应该返回什么以便在控制器中知道创建用户失败的原因?

在我看来,处理异常的最佳位置是服务层。对于我来说,REST控制器方法最多应该处理请求并将其传递给服务方法

使用这种方法,您可以非常清楚地定义层,这些层可以完成非常清楚定义的工作。例如,您的服务层将处理请求的验证、持久化操作,并且还将(如果需要)向控制器提供一个返回对象,然后该返回对象将封装到相应的响应对象中(
ResponseEntity

记住这一点,没有什么能阻止您在服务层抛出任何类型的异常,并将其转化为正确的响应。Spring有一个非常简洁而强大的机制,可以精确地执行被称为异常处理程序的操作

因此,对于密码检查操作,您可以执行以下操作:

if (!user.getPassword().equals(user.getConfirmPassword())) {
    throw new PasswordMismatchException("Passwords are not the same for user:: " + user.getName());
}
其中,
密码不匹配异常
是一个运行时异常。使用类似的方法,您可以继续设置ExceptionHandler,并使用适当的方法来截取它并将其转换为响应。一个简单的例子是:

@RestControllerAdvice
public class ApplicationExceptionHandler {

   @ExceptionHandler(PasswordMismatchException.class)
   public ResponseEntity<String> handleBadPasswords(PasswordMismatchException e) {
       return ResponseEntity.badRequest().body(e.getMessage());
   }

}
@RestControllerAdvice
公共类ApplicationExceptionHandler{
@ExceptionHandler(PasswordMismatchException.class)
公共响应手柄密码(密码不匹配例外e){
返回ResponseEntity.badRequest().body(e.getMessage());
}
}
您可以阅读Spring文档中的更多内容:


将其视为一个漏斗是一个有用的方法:我可以设想多个接口来更新该记录吗?(JSON API和HTML接口是两个很好的例子。)如果是这样,那么该功能将进入两个接口使用的公共服务中,从而减少重复。(在您的特定情况下,您可能只希望在数据库列上有一个不区分大小写的唯一约束。您可能还是想查询它。最后,如果可能,请使用
Instant
而不是
Date
@RestControllerAdvice
public class ApplicationExceptionHandler {

   @ExceptionHandler(PasswordMismatchException.class)
   public ResponseEntity<String> handleBadPasswords(PasswordMismatchException e) {
       return ResponseEntity.badRequest().body(e.getMessage());
   }

}