Skocz do zawartości

Temat został przeniesiony do archiwum

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

Elzulninho

Problem z walidacją Spring

Rekomendowane odpowiedzi

Cześć mam taki kalkulator BMR:

Zrobiłem na klasie modelowej walidację jednak problem jest po stronie kontrolera , coś źle piszę , czegoś brakuje... w każdym razie walidacja nie działa

Formularz wygląda tak (plik bmrform)

<form class="list-inline"  th:object="${operationModel}" th:action="@{/bmr}" th:method="post" >
       <div class="form-group" >
           <label class="control-label">Wzrost:</label>
           <input type="text" class="form-control" th:field="*{height}" placeholder="Wzrost w centymetrach"/>
           <p th:if="${#fields.hasErrors('height')}" th:errors="*{height}"/>
       </div>

       <div class="form-group" >
           <label class="control-label">Masa ciała:</label>
           <input type="text" class="form-control" th:field="*{bodyweight}" placeholder="Masa ciała w kg"/>
           <p th:if="${#fields.hasErrors('bodyweight')}" th:errors="*{bodyweight}"/>
       </div>
       <div class="form-group" >
           <label class="control-label">Wiek:</label>
           <input type="text" class="form-control" th:field="*{age}" placeholder="Wiek"/>
           <p th:if="${#fields.hasErrors('age')}" th:errors="*{age}"/>
       </div>

 

Metody w kontrolerze

@RequestMapping("/bmr")
   public String createOperationModel(Model model) {
       model.addAttribute("operationModel", new CalculatorFromBmr());
       return "bmrform";
   }

   @RequestMapping(path="/bmr", method = RequestMethod.POST)
   public String add(@ModelAttribute("operationModel") CalculatorFromBmr calculatorFromBmr, Model model) {
       model.addAttribute("result", calculatorBmr.calculate(calculatorFromBmr.getHeight(),calculatorFromBmr.getBodyweight(),calculatorFromBmr.getAge()));
       return "bmrform";
   }

I METODA Z WALIDACJA, W KTÓREJ CZEGOŚ BRAKUJE...

@RequestMapping( method = RequestMethod.POST)
   public String saveResult(@Valid CalculatorFromBmr calculatorFromBmr, BindingResult bindingResult) {

       if (bindingResult.hasErrors()) {
           System.out.println("There were errors");
           bindingResult.getAllErrors().forEach(error -> {
                       System.out.println(error.getObjectName() + " " + error.getDefaultMessage());
                   }
           );
           return "bmrform";
       } else {
           return "redirect:/bmr";
       }

   }

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Pokaż konfig beanów Spring i dependencje , jakie zaciągasz przez maven/gradle.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter</artifactId>
	</dependency>

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-thymeleaf</artifactId>
	</dependency>

 

Tutaj część od kontrolera
@Controller
public class CalculatorBmrController {
   @Autowired
   CalculatorBmr calculatorBmr;

 

Tutaj klasa z metodą

@Component
public class CalculatorBmr {

   public double calculate(double height, double bodyweight,int age){
return 66+(13.7*bodyweight)+(5*height)-(6.76*age);
   }

}

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Formularz strzela POST pod /bmr, a w kontrolerze w metodzie zmapowanej pod ten adres nie ma @Valid. @Valid masz w zupełnie innej metodzie.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Więc muszę coś zrobić z tą drugą metodą, a ta 3 metoda w kontrolerze jest niepotrzebna? Próbowałem w ten sposób ale oczywiście robię coś źle...

 @RequestMapping(path="/bmr", method = RequestMethod.POST)
   public String add(@ModelAttribute("operationModel")@Valid CalculatorFromBmr calculatorFromBmr, Model model,BindingResult bindingResult) {
       model.addAttribute("result", calculatorBmr.calculate(calculatorFromBmr.getHeight(),calculatorFromBmr.getBodyweight(),calculatorFromBmr.getAge()));
       if (bindingResult.hasErrors()) {
           System.out.println("There were errors");
           bindingResult.getAllErrors().forEach(error -> {
                       System.out.println(error.getObjectName() + " " + error.getDefaultMessage());
                   }
           );
           return "bmrform";
       } else {
           return "redirect:/bmr";
       }
   }

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Tak, ma być jedna metoda dla GET i jedna dla POST. Na moje oko masz źle zmapowany th:object w thymleaf i nazwę w @ModelAttribute kontrolera, więc Spring nie ma pojęcia, że to jest to samo.

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Ale jakby nie miał pojęcia, że to to samo to by przypadkiem nie zwracał wyniku liczenia? Bo wszystko działa oprócz walidacji

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

Masz różne błędy, które na siebie wpływają i ciężko jest coś wywróżyć bez całego kodu. Do tego polecam dbać o formatowanie kodu i nazewnictwo zmiennych, bo to ułatwia życie.

 

 

Po pierwsze object w thymleaf i argument @ModelAttribute w kontrolerze muszą być takie same. Po drugie kolejność argumentów w metodach kontrolera ma znaczenie - bindingResult musi być po modelu formularza, którego dotyczy.

<form class="list-inline" th:object="${bmrFormData}" th:action="@{/bmr}" th:method="post">
(...)
</form>

   @RequestMapping("/bmr")
   public String showForm(Model model) {
       model.addAttribute("bmrFormData", new BmrCalculatorForm());
       return "bmrform";
   }

   @RequestMapping(path = "/bmr", method = RequestMethod.POST)
   public String calculate(@Valid @ModelAttribute("bmrFormData") BmrCalculatorForm bmrCalculatorForm,
                     BindingResult bindingResult,
                     Model model) {

       if (bindingResult.hasErrors()) {
           return "bmrform";
       }

       double result = bmrCalculator.calculate(bmrCalculatorForm.getHeight(), bmrCalculatorForm.getBodyWeight(), bmrCalculatorForm.getAge());
       model.addAttribute("result", result);
       return "redirect:/bmr";
   }

Kolejna rzecz, to jakieś zasady walidacji.

public class BmrCalculatorForm {

   @NotNull(message = "Puste pole")
   private Integer height;
   @NotNull(message = "Puste pole")
   private Integer bodyWeight;
   @NotNull(message = "Puste pole")
   @Min(value = 10, message = "Minimum 10")
   private Integer age;

   // get / set
}

 

I to wszystko, co jest potrzebne w standardowym przypadku. Ty używasz wzorca post-redirect-get, który uniemożliwia wielokrotne wysłanie formularza, co jest bardzo dobrą praktyką, ale ma swoje konsekwencje. W przypadku udanego obsłużenia POST w metodzie calculate wymuszone jest od przeglądarki wysłanie kolejnego zapytania GET: return "redirect:/bmr;". Co za tym idzie, użytkownik zobaczy stronę wygenerowaną przez metodę showBmrForm, a tam nic nie wiadomo o warości result. Można sobie z tym poradzić modyfikując fragment powyższego kodu:

   @RequestMapping(path = "/bmr", method = RequestMethod.POST)
   public String calculate(@Valid @ModelAttribute("bmrFormData") BmrCalculatorForm bmrCalculatorForm,
                     BindingResult bindingResult,
                     RedirectAttributes redirectAttributes) {

       if (bindingResult.hasErrors()) {
           return "bmrform";
       }

       double result = bmrCalculator.calculate(bmrCalculatorForm.getHeight(), bmrCalculatorForm.getBodyWeight(), bmrCalculatorForm.getAge());
       redirectAttributes.addFlashAttribute("result", result);
       return "redirect:/bmr";
   }

Udostępnij tę odpowiedź


Odnośnik do odpowiedzi
Udostępnij na innych stronach

  • Ostatnio przeglądający   0 użytkowników

    Brak zarejestrowanych użytkowników przeglądających tę stronę.

×
×
  • Dodaj nową pozycję...