RESTAPI使用jax rs在json数组中同时发送多个错误

6psbrbz9  于 2021-07-07  发布在  Java
关注(0)|答案(1)|浏览(397)

我正在学习如何用javaee和jax-rs创建api,但是我在internet上找不到任何关于我的问题的答案。
我有一条“注册”路线:

@POST
    @Path("/signup")
    @Produces(MediaType.APPLICATION_JSON)
    public Response register(@FormParam("email") String email, @FormParam("pseudo") String pseudo, @FormParam("password") String password,@FormParam("firstname") String firstname) {
                List<HashMap<String, String>> errorMsgs = authManager.register(email, pseudo, password, firstname, lastname);

        if (errorMsgs.isEmpty()) { // Si la liste est vide, il n'y a pas eu d'erreur
            HashMap<String, String> success = new HashMap<>();
            success.put("title", "Inscription réussie");
            success.put("message", "L'utilisateur a été ajouté en base de données.");
            return Response.ok().entity(success).build();
        } else {
            HashMap<String, List<HashMap<String, String>>> errors = new HashMap<>();
            errors.put("errors", errorMsgs);

            return Response.status(422).entity(errors).build();
        }
    }

目前,要发送我需要的所有错误消息,我使用以下命令:

public List<HashMap<String, String>> register(String email, String pseudo, String password, String firstname, String lastname) {
        List<HashMap<String, String>> errors = new ArrayList<>();

        errors.addAll(checkEmail(email));
        errors.addAll(checkPseudo(pseudo));
        errors.addAll(checkPassword(password));
        errors.addAll(checkFirstname(firstname));
        errors.addAll(checkLastname(lastname));

        if (errors.isEmpty()) {
            userDAO.create(new User(pseudo, email, password, firstname, lastname));
        }

        return errors;
    }

    private List<HashMap<String, String>> checkEmail(String email) {
        List<HashMap<String, String>> errors = new ArrayList<>();

        if (email != null && !email.isEmpty()) {
            if (email.matches("([^.@]+)(\\.[^.@]+)*@([^.@]+\\.)+([^.@]+)")) {
                Optional<User> user = userDAO.findByEmail(email);
                if(user.isPresent()) {
                    HashMap<String, String> error = new HashMap<>();
                    error.put("code", CODE_FIELD_ALREADY_EXIST);
                    error.put("field", "email");
                    error.put("title", "L'adresse email existe déjà dans la base de données.");
                    error.put("message", "Essayez de choisir une autre adresse email qui n'est pas déjà utilisé.");

                    errors.add(error);
                }
            } else {
                HashMap<String, String> error = new HashMap<>();
                error.put("code", CODE_BAD_FORMAT);
                error.put("field", "email");
                error.put("title", "L'adresse email n'est pas au bon format.");
                error.put("message", "Vous devez entrer un email au format valide (exemple@domaine.fr)");
                errors.add(error);
            }
        } else {
            HashMap<String, String> error = new HashMap<>();
            error.put("code", CODE_EMPTY_FIELD);
            error.put("field", "email");
            error.put("title", "Le champ email est vide.");
            error.put("message", "L'adresse email est obligatoire.");
            errors.add(error);
        }

        return errors;
    }

    private List<HashMap<String, String>> checkPseudo(String pseudo) {
        List<HashMap<String, String>> errors = new ArrayList<>();

        if (pseudo != null && !pseudo.isEmpty()) {
            if (pseudo.length() > 50) {
                HashMap<String, String> error = new HashMap<>();
                error.put("code", CODE_TOO_LONG_FIELD);
                error.put("field", "pseudo");
                error.put("title", "Le pseudo est trop long.");
                error.put("message", "Votre pseudo ne peut pas faire plus de 50 caractères.");

                errors.add(error);
            } else {
                if (userDAO.findByPseudo(pseudo).isPresent()) {
                    HashMap<String, String> error = new HashMap<>();
                    error.put("code", CODE_FIELD_ALREADY_EXIST);
                    error.put("field", "pseudo");
                    error.put("title", "Le pseudo " + pseudo + " existe déjà dans la base de données.");
                    error.put("message", "Essayez de choisir un pseudo qui n'est pas déjà utilisé.");

                    errors.add(error);
                }
            }
        } else {
            HashMap<String, String> error = new HashMap<>();
            error.put("code", CODE_EMPTY_FIELD);
            error.put("field", "pseudo");
            error.put("title", "Le champ pseudo est vide");
            error.put("message", "Le pseudo est obligatoire.");
            errors.add(error);
        }

        return errors;
    }

    private List<HashMap<String, String>> checkPassword(String password) {
        List<HashMap<String, String>> errors = new ArrayList<>();

        if (password != null && !password.isEmpty()) {
            if (password.length() < 8) {
                HashMap<String, String> error = new HashMap<>();
                error.put("code", CODE_TOO_SHORT_FIELD);
                error.put("field", "password");
                error.put("title", "Le mot de passe est trop court.");
                error.put("message", "Votre mot de passe doit faire au minimum 8 caractères.");

                errors.add(error);
            }
        } else {
            HashMap<String, String> error = new HashMap<>();
            error.put("code", CODE_EMPTY_FIELD);
            error.put("field", "password");
            error.put("title", "Le champ est vide");
            error.put("message", "Le mot de passe est obligatoire.");

            errors.add(error);
        }

        return errors;
    }

    private List<HashMap<String, String>> checkFirstname(String firstname) {
        List<HashMap<String, String>> errors = new ArrayList<>();

        if (firstname != null && !firstname.isEmpty()) {
            if (firstname.length() > 50) {
                HashMap<String, String> error = new HashMap<>();
                error.put("code", CODE_TOO_LONG_FIELD);
                error.put("field", "firstname");
                error.put("title", "Le prénom est trop long");
                error.put("message", "Votre prénom doit avoir un maximum de 50 caractères.");

                errors.add(error);
            }
        } else {
            HashMap<String, String> error = new HashMap<>();
            error.put("code", CODE_EMPTY_FIELD);
            error.put("field", "firstname");
            error.put("title", "Le champ est vide");
            error.put("message", "Le prénom est obligatoire.");

            errors.add(error);
        }

        return errors;
    }

    private List<HashMap<String, String>> checkLastname(String lastname) {
        List<HashMap<String, String>> errors = new ArrayList<>();

        if (lastname != null && !lastname.isEmpty()) {
            if (lastname.length() > 50) {
                HashMap<String, String> error = new HashMap<>();
                error.put("code", CODE_TOO_LONG_FIELD);
                error.put("field", "lastname");
                error.put("title", "Le nom est trop long");
                error.put("message", "Votre nom doit avoir un maximum de 50 caractères.");

                errors.add(error);
            }
        } else {
            HashMap<String, String> error = new HashMap<>();
            error.put("code", CODE_EMPTY_FIELD);
            error.put("field", "lastname");
            error.put("title", "Le champ est vide");
            error.put("message", "Le nom est obligatoire.");

            errors.add(error);
        }

        return errors;
    }
}

这段代码基本上向我发送了这种类型的响应:

这是我想要的,但代码真的很难看,将成为一个真正的混乱,我不认为这是一个好的做法。所以我在网上寻找更好的方法。我发现有些人使用异常处理,或者使用“exceptionapper”或者webapplicationexception,但问题是它一次只能处理一个问题,所以,这不是我需要的,因为我想一次发送多个错误响应。所以我想知道你们中有没有人能解决这个问题,因为我没有找到任何关于我的问题的答案:|!
谢谢:)!

lpwwtiir

lpwwtiir1#

下面是两种处理错误的方法,使其更易于理解
1.使用 javax.validation 您可以修改jax-rs端点以接受java类并让 javax.validation 为您处理验证。
这就是jax-rs端点的样子:

@POST
    @Path("/signup")
    @Produces(MediaType.APPLICATION_JSON)
    public Response register(@Valid RegisterationOptions registrationOptions) {

      ...
}

以及 RegistrationOptions.java 班级:

public class RegistrationOptions {

@NotNull
String email; 

@NotNull
String pseudo;

@NotNull
String password;

@NotNull
String firstname;

 .....

}

有多个注解可用于验证。如。 @Min, @Max, @Negative, @Size, @Email, @Future .
他们都接受 message 参数,如果验证未成功,则可以在其中记录自定义消息。
但是请记住,您需要创建一个excationMap器来将抛出的验证异常Map到一个有效的jax-rs响应。
据我所知,对于任何不满足您设置的条件的值,这都会引发异常。它不会为每次验证都抛出异常。但我可能错了。
2.对错误消息使用自定义类
如果您想向用户显示多个错误,那么为错误对象创建pojo而不是创建hashmaps列表可能会更干净、更容易。
例如:

public class RegistrationError {
  private enum Field {
    email,password,pseudo,firstname;

    String getFieldFullName() {
      switch (this) {
        case email:
          return "Email Address";
        case password:
          return "Password";
        case pseudo:
          return "Pseudo";
        case firstname:
          return "First Name";
      }
    }
  }
  private enum ErrorCodes {
    FIELD_ALREADY_EXIST,EMPTY_FIELD, TOO_LONG_FIELD,
  }

  private final String code;
  private final String field;
  private final String title;
  private final String message;

  private RegistrationError(String code, String field, String title, String message) {
    this.code = code;
    this.field = field;
    this.title = title;
    this.message = message;
  }

  public static RegistrationError generateError(ErrorCodes errorCodes, Field field){
    final String errorTitle = RegistrationError.getErrorTitle(errorCodes, field);
    final String errorMessage = RegistrationError.getErrorMessage(errorCodes, field);
    return new RegistrationError(errorCodes.name(), field.name(), errorTitle, errorMessage);
  }

  public static String getErrorTitle(ErrorCodes errorCodes, Field field) {
    switch (errorCodes) {
      case FIELD_ALREADY_EXIST:
        return field.getFieldFullName() + " already exists in DB";
      case EMPTY_FIELD:
        return field.getFieldFullName() + " cannot be empty";
      case TOO_LONG_FIELD:
        return field.getFieldFullName() + " is too long";
      default:
        return field.getFieldFullName() + " is invalid";
    }
  }

  public static String getErrorMessage(ErrorCodes errorCodes, Field field) {
    switch (errorCodes) {
      case FIELD_ALREADY_EXIST:
        return field.getFieldFullName() + " already exists in DB";
      case EMPTY_FIELD:
        return field.getFieldFullName() + " cannot be empty";
      case TOO_LONG_FIELD:
        return field.getFieldFullName() + " is too long";
      default:
        return field.getFieldFullName() + " is invalid";
    }
  }

  public String getCode() {
    return code;
  }

  public String getField() {
    return field;
  }

  public String getTitle() {
    return title;
  }

  public String getMessage() {
    return message;
  }
}

然后您可以在方法中使用它,在方法中验证字段:

public List<RegistrationError> register(String email, String pseudo, String password, String firstname, String lastname) {
    List<RegistrationError> errors = new ArrayList<>();

    errors.addAll(checkEmail(email));
    errors.addAll(checkPseudo(pseudo));
    errors.addAll(checkPassword(password));
    errors.addAll(checkFirstname(firstname));
    errors.addAll(checkLastname(lastname));

    if (errors.isEmpty()) {
      userDAO.create(new User(pseudo, email, password, firstname, lastname));
    }

    return errors;
  }

  private List<RegistrationError> checkEmail(String email) {
    List<RegistrationError> errors = new ArrayList<>();

    if (email != null && !email.isEmpty()) {
      if (email.matches("([^.@]+)(\\.[^.@]+)*@([^.@]+\\.)+([^.@]+)")) {
        Optional<User> user = userDAO.findByEmail(email);
        if(user.isPresent()) {
          errors.add(RegistrationError.generateError(RegistrationError.ErrorCodes.FIELD_ALREADY_EXIST, RegistrationError.Field.email));
        }
      } else {
        errors.add(RegistrationError.generateError(RegistrationError.ErrorCodes.EMPTY_FIELD, RegistrationError.Field.email));
      }
    } else {
      errors.add(RegistrationError.generateError(RegistrationError.ErrorCodes.EMPTY_FIELD, RegistrationError.Field.email));
    }

    return errors;
  }

  private List<RegistrationError> checkPseudo(String pseudo) {
    List<RegistrationError> errors = new ArrayList<>();

    if (pseudo != null && !pseudo.isEmpty()) {
      if (pseudo.length() > 50) {
        errors.add(RegistrationError.generateError(RegistrationError.ErrorCodes.EMPTY_FIELD, RegistrationError.Field.pseudo));
      } else {
        if (userDAO.findByPseudo(pseudo).isPresent()) {
          errors.add(RegistrationError.generateError(RegistrationError.ErrorCodes.FIELD_ALREADY_EXIST, RegistrationError.Field.email));
        }
      }
    } else {
      errors.add(RegistrationError.generateError(RegistrationError.ErrorCodes.EMPTY_FIELD, RegistrationError.Field.email));
    }

    return errors;
  }

  private List<RegistrationError> checkPassword(String password) {
    List<RegistrationError> errors = new ArrayList<>();

    if (password != null && !password.isEmpty()) {
      if (password.length() < 8) {
        errors.add(RegistrationError.generateError(RegistrationError.ErrorCodes.EMPTY_FIELD, RegistrationError.Field.email));
      }
    } else {
      errors.add(RegistrationError.generateError(RegistrationError.ErrorCodes.EMPTY_FIELD, RegistrationError.Field.email));
    }

    return errors;
  }

  private List<RegistrationError> checkFirstname(String firstname) {
    List<RegistrationError> errors = new ArrayList<>();

    if (firstname != null && !firstname.isEmpty()) {
      if (firstname.length() > 50) {
        errors.add(RegistrationError.generateError(RegistrationError.ErrorCodes.EMPTY_FIELD, RegistrationError.Field.email));
      }
    } else {
      errors.add(RegistrationError.generateError(RegistrationError.ErrorCodes.EMPTY_FIELD, RegistrationError.Field.email));
    }

    return errors;
  }

  private List<RegistrationError> checkLastname(String lastname) {
    List<RegistrationError> errors = new ArrayList<>();

    if (lastname != null && !lastname.isEmpty()) {
      if (lastname.length() > 50) {
        errors.add(RegistrationError.generateError(RegistrationError.ErrorCodes.EMPTY_FIELD, RegistrationError.Field.email));
      }
    } else {
      errors.add(RegistrationError.generateError(RegistrationError.ErrorCodes.EMPTY_FIELD, RegistrationError.Field.email));
    }

    return errors;
  }

(使用前需要更正错误和字段)
您的jax-rs方法可以将此数组发送为:

List<RegistrationError> errorMsgs = authManager.register(email, pseudo, password, firstname, lastname);

...

            HashMap<String, List<RegistrationErrors>> errors = new HashMap<>();
            errors.put("errors", errorMsgs);

            return Response.status(422).entity(errors).build();

您还可以将此方法与 javax.validation 如果您构建一个异常Map器,则使用包方法。

相关问题