Мне нужно иметь 2 отдельных метода @PostMapping, направленных на один и тот же URL

#java #spring

Вопрос:

Ниже приведено то, что у меня есть;

     @PostMapping("/profile")
    public String showUserAppointment(@RequestParam(value = "userCpr", required = false) Long cpr, Model model)
    {
        cpr = Long.parseLong(currentPrincipal());
        model.addAttribute("iTestCenterService", iTestCenterService);
        model.addAttribute("userCpr", iAppointmentService.findAppointmentByCpr(cpr));
        return "profile/profile";
    }

    @PostMapping("profile")
    public String showUserDetails(@RequestParam(value = "userCprDetails", required = false) long cpr, Model model)
    {
        cpr = Long.parseLong(currentPrincipal());
        model.addAttribute("iAddressService", iAddressService);
        model.addAttribute("userCprDetails", iUserService.findUserByCpr(cpr));
        return "profile/profile";
    }
 

Возможно ли это вообще сделать, указав и то, и другое на странице профиля?

Как я могу это сделать, если это невозможно?

Комментарии:

1. 1. Как вы думаете, на основе какого метода обработчика следует выбирать при поступлении запроса?; 2. Почему вам нужно, чтобы два разных метода отображались в одном и том же URI?

2. @GiorgiTsiklauri Я не уверен, что вы подразумеваете под первым вопросом. А что касается 2-го, то это потому, что у меня есть 2 отдельные таблицы, которые мне нужно отобразить на странице профиля в совершенно разных форматах, поэтому я предполагаю, что не смогу сделать это одним способом.

3. Если у вас есть разные данные для отображения, то у вас должны быть разные конечные точки для извлечения этих данных. Разделение забот .

4.Не похоже, что какой-либо из них должен быть конечными точками POST; они оба выглядят как GETs. Также неясно, какой вы хотите видеть свою собственную логику, поскольку вы вводите cpr параметры запроса, а затем немедленно перезаписываете их каким-то непрозрачным значением.

5. @chrylis-осторожно оптимистично — я перезаписываю их, потому что они раньше были функцией поиска, поэтому было бы определено пользователем, что такое cpr, но это вызывало проблемы с тем, что пользователи могли видеть данные других пользователей, и поскольку я не знаю, как это исправить с помощью разрешений, я решил, что просто попытаюсь передать текущего участника в качестве cpr и автоматически отображать только данные пользователей, а не предоставлять им возможность поиска.

Ответ №1:

Игнорируя драматизм дизайна в комментариях к вопросу, ответ заключается в том, что у вас должен быть один метод, аннотированный, @PostMapping а затем делегированный соответствующей функции обработчика на основе фактов.

В оригинале у вас есть две версии: /profile?userCpr=123 и /profile?userCprDetails=456 . Оба userCpr варианта и userCprDetails являются необязательными, поэтому вам решать, как поступить в ситуации, когда ни один из них не предусмотрен или оба не предусмотрены. Но для других случаев использования просто объявите оба необязательных параметра запроса в определении конечной точки:

 @PostMapping("/profile")
public String showUser(
    @RequestParam(value = "userCpr", required = false) Long userCpr,
    @RequestParam(value = "userCprDetails", required = false) Long userCprDetails,
    Model model) {

  // if both are defined, or neither is defined, you need to decide how to handle that (or 
  // if you should error)
  if (userCpr == null amp;amp; userCprDetails == null) || (userCpr != null amp;amp; userCprDetails != null) {
    // TODO: handle this situation
  } else if (userCpr != null) {
    return showUserAppointment(model);
  } else {
    return showUserDetails(model);
  }
}

public String showUserAppointment(Model model) {
  Long cpr = Long.parseLong(currentPrincipal());
  model.addAttribute("iTestCenterService", iTestCenterService);
  model.addAttribute("userCpr", iAppointmentService.findAppointmentByCpr(cpr));
  return "profile/profile";
}

public String showUserDetails(Model model) {
  Long cpr = Long.parseLong(currentPrincipal());
  model.addAttribute("iAddressService", iAddressService);
  model.addAttribute("userCprDetails", iUserService.findUserByCpr(cpr));
  return "profile/profile";
}
 

Мы даже не утруждаем себя передачей значений userCpr/userCprDetails методам обработчика, так как мы собираемся игнорировать значение и currentPrincipal() вместо этого использовать результат.

Конечно, поскольку подавляющее большинство обоих «обработчиков» идентично, вы можете просто упростить метод до одной конечной точки и полностью опустить методы «обработчика» :

 @PostMapping("/profile")
public String showUser(
    @RequestParam(value = "userCpr", required = false) Long userCpr,
    @RequestParam(value = "userCprDetails", required = false) Long userCprDetails,
    Model model) {

  // if both are defined, or neither is defined, you need to decide how to handle that (or 
  // if you should error)
  if (userCpr == null amp;amp; userCprDetails == null) || (userCpr != null amp;amp; userCprDetails != null) {
    // TODO: handle this situation
  } 
  Long cpr = Long.parseLong(currentPrincipal());
  model.addAttribute("iTestCenterService", iTestCenterService);

  if (userCpr != null) {
    model.addAttribute("userCpr", iAppointmentService.findAppointmentByCpr(cpr));
  } else {
    model.addAttribute("userCprDetails", iUserService.findUserByCpr(cpr));
  }
  return "profile/profile;
}
 

… но если вы на самом деле делаете больше вещей в этих методах обработчика, чем может иметь смысл, чтобы это не касалось самой конечной точки и отдельных функций обработчика.