[JAVA] Spring 4.2 vs 4.3: Unterschied im Bindungswert zum Sammlungstyp beim Senden des Kontrollkästchens leer

Diesmal eine Prüfung, die mit einer Komponente generiert wurde, die die von Spring bereitgestellte View-Implementierung (JSP-Tag-Bibliothek, Freemarker-Makro usw.) und einer Kooperationskomponente eines Drittanbieters (Dialekt für die Spring-Kooperation von Thymeleaf usw.) unterstützt. Wenn Sie ein Formular mit leerem Feld (= nicht ausgewählt) senden, ändert sich der im Formularobjekt definierte Wert für den Typ "Sammlung" ("Liste", "Satz" usw.) zwischen Spring 4.2 und Spring 4.3. Ich werde darüber reden.

Note:

Übrigens ... Wenn Sie ein Array anstelle des Typs "Collection" verwenden, ändert sich das Verhalten nicht. (Ein Array von leeren Elementen wird gesetzt)

Was ist der Unterschied zwischen Feder 4.2 und Feder 4.3?

Plötzlich aus dem Fazit ... In Spring 4.2 ist null gebunden, ab Spring 4.3 ist jedoch ein leeres Element Collection-Objekt gebunden.

Note:

Die Betriebsspezifikationen wurden gegenüber Spring 4.3 aufgrund von Verbesserungswünschen von Spring-Benutzern geändert (SPR-13502).

Wenn ich es tatsächlich überprüfe ...

Sehen wir uns ein konkretes Beispiel mit Thymeleaf (Thymeleaf-Spring) an. Hier erstellen wir einfach einen Controller und eine Formularklasse in der Spring Boot-Anwendung.

package com.example;

import java.util.List;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@SpringBootApplication
public class CheckboxDemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(CheckboxDemoApplication.class, args);
	}

	@RequestMapping("/sample")
	@Controller
	static class SampleController {

		@ModelAttribute //Methode zum Speichern des Formulars im Modell
		SampleForm setUpForm() {
			return new SampleForm();
		}

		@RequestMapping //Handler-Methode zum Anzeigen des Formularbildschirms
		String form() {
			return "sample/form";
		}

		@RequestMapping(method = RequestMethod.POST) //Handler-Methode zum Empfangen von Einsendungen vom Formularbildschirm
		String submit(SampleForm form) {
			System.out.println("-----------------------");
			System.out.println("list :" + form.getList());
			return "sample/form";
		}
	}

	static class SampleForm {

		private List<String> list; //Eigenschaften zum Halten des Werts des Kontrollkästchens

		public List<String> getList() {
			return list;
		}

		public void setList(List<String> list) {
			this.list = list;
		}

	}

}
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>Sample</title>
</head>

<body>

<div class="container">

    <form method="post" th:object="${sampleForm}">
        <div class="form-group">
            <label>List</label> <!--Es stehen zwei Auswahlwerte für Kontrollkästchen zur Verfügung-->
            <ul>
                <li>
                    <input type="checkbox" th:field="*{list}" value="1"/>
                    <label th:for="${#ids.prev('list')}">A</label>
                </li>
                <li>
                    <input type="checkbox" th:field="*{list}" value="2"/>
                    <label th:for="${#ids.prev('list')}">B</label>
                </li>
            </ul>
        </div>
        <button class="btn btn-default">Submit</button>
    </form>

</div>
</body>

</html>

Wenn Sie die Spring Boot-Anwendung starten und auf "[http: // localhost: 8080 / sample](http: // localhost: 8080 / sample)" zugreifen, wird der folgende Bildschirm (shoboi w) angezeigt.

checkbox-form.png

Im Frühjahr 4.2?

Wenn Sie in Spring Boot 1.3.8.RELEASE (neueste Release-Version für Spring 4.2-Serie) auf der Konsole auf die Schaltfläche "Senden" klicken ...

...
2016-12-23 19:40:42.727  INFO 38839 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 13 ms
-----------------------
list :null

Es wird angezeigt. Mit anderen Worten ... null ist gebunden.

Im Frühjahr 4.3?

Auf der anderen Seite ... Wenn Sie in Spring Boot 1.4.3.RELEASE (neueste Release-Version für Spring 4.3-Serie) auf der Konsole auf die Schaltfläche "Senden" klicken ...

...
2016-12-23 19:40:42.727  INFO 38839 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 13 ms
-----------------------
list :[]

Es wird angezeigt. Dies bedeutet, dass eine leere Liste anstelle von "null" gebunden ist.

Stimmt etwas nicht oder hat dies Auswirkungen?

Ob "null" zu einer Sammlung leerer Elemente wird oder nicht, ist ein Problem oder wirkt sich auf die Erstellung Ihrer Anwendung aus. Zum Beispiel ... Ich denke, dass es kein Problem (= kein Effekt) in Anwendungen gibt, die ursprünglich "null" und leere Elemente als dasselbe behandeln. Anwendungen, die "null" und leere Elemente als unterschiedliche Dinge behandeln, müssen möglicherweise etwas dagegen tun.

Zum Beispiel ... Wenn die erforderliche Prüfung für das Kontrollkästchenelement durchgeführt wird, indem angegeben wird, ob es "null" ist oder nicht, wie unten gezeigt, fließt der Prozess zur Logikschicht, indem die Eingabeprüfung umgangen wird.

static class SampleForm {

	@NotNull // Bad ...Ein leeres Element ist gebunden, daher ist eine Nullprüfung NG! !!
	private List<String> list;

	// ...

}

In diesem Fall sollte der Bean-Validierungsstandard "@ Size" "@ NotEmpty" verwenden, das vom Hibernate Validator bereitgestellt wird.

static class SampleForm {
	@Size(min = 1) // Good
	private List<String> list;
	// ...
}

or

static class SampleForm {
	@NotEmpty // Good
	private List<String> list;
	// ...
}

Wie wird der Anfangswert (Standardwert) eingestellt?

Generieren Sie Kontrollkästchen und Auswahlfelder mit Komponenten, die die von Spring bereitgestellte View-Implementierung (JSP-Tag-Bibliothek, Freemarker-Makros usw.) und Komponenten für die Zusammenarbeit von Drittanbietern (Dialekt für die Spring-Zusammenarbeit von Thymeleaf usw.) unterstützen. Anschließend werden spezielle Parameter (Parameter, die mit "_" beginnen) zum Initialisieren der Eigenschaften des Formularobjekts als ausgeblendete Elemente eingebettet. (In diesem Beitrag wird dieser spezielle Parameter im Folgenden als "Rücksetzparameter" bezeichnet.)

Von Thymeleaf generierter HTML-Inhalt



<!DOCTYPE html>


<html xmlns="http://www.w3.org/1999/xhtml">

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Sample</title>
</head>

<body>

<div class="container">

    <form method="post">
        <div class="form-group">
            <label>List</label>
            <ul>
                <li>
                    <input type="checkbox" value="1" id="list1" name="list" /><input type="hidden" name="_list" value="on" />
                    <label for="list1">A</label>
                </li>
                <li>
                    <input type="checkbox" value="2" id="list2" name="list" /><input type="hidden" name="_list" value="on" />
                    <label for="list2">B</label>
                </li>
            </ul>
            
        </div>
        <button class="btn btn-default">Submit</button>
    </form>

</div>
</body>

</html>

In diesem Beispiel ist "_list" der Rücksetzparameter. Der Wert ist " on ", aber da dieser Rücksetzparameter ein Markierungsparameter ist, hat der Wert keine Bedeutung.

Was macht Spring MVC, wenn Sie einen Reset-Parameter senden? Wenn Sie einen Rücksetzparameter senden ... Wenn ein normaler Anforderungsparameter (list im obigen Beispiel) nicht als Anforderungsparameter gesendet wird (= wird nicht gesendet, wenn das Kontrollkästchen leer ist), der Eigenschaftswert des Formularobjekts Wird initialisiert.

Der zum Zeitpunkt dieser Initialisierung verwendete Wert war bis Spring 4.2 "null", ab Spring 4.3 ist er jedoch zu einer Sammlung leerer Elemente geworden.

Note:

Insbesondere ... Der bei der Initialisierung festzulegende Wert wird in der Methode "getEmptyValue" von "org.springframework.web.bind.WebDataBinder" festgelegt. Ab Spring 4.3 haben sich die Anfangswerte für die Implementierungsklasse "java.util.Collection" und die Implementierungsklasse "java.util.Map" geändert.

Warum müssen Sie Parameter zurücksetzen?

Benötigen Sie Parameter zurücksetzen? ?? ?? Vielleicht haben einige Leute das gedacht. Abschließend ... ist es notwendig.

Insbesondere ... Wenn das Formularobjekt im Sitzungsbereich mit "@ SessionAttributes" verwaltet wird, werden die folgenden Vorgänge ausgeführt ...

  1. Zeigen Sie den Formularbildschirm an
  2. Aktivieren Sie ein Kontrollkästchen auf dem Formularbildschirm und senden Sie es ab
  3. Kehren Sie erneut zum Formularbildschirm zurück, deaktivieren Sie das Kontrollkästchen und senden Sie es ab

Wenn Sie dies tun, kehrt der ausgewählte Status des Kontrollkästchens zum ursprünglichen Status zurück (dem Status, in dem einer aktiviert ist). Der Grund, warum der Status zurückgegeben wird, ist ... Wenn alle Kontrollkästchen deaktiviert sind, wird der Anforderungsparameter des entsprechenden Elements zum Zeitpunkt der Übermittlung nicht gesendet, sodass der Prozess zum Aktualisieren des Status des in der Sitzung verwalteten Formularobjekts ausgeführt wird. Infolgedessen bleibt der vorherige Zustand erhalten.

Spring MVC bietet einen speziellen Parameter namens "Reset-Parameter", um die obige Situation zu vermeiden.

Note:

Wenn das Eingabeelement deaktiviert ist, wird der Anforderungsparameter zum Zeitpunkt der Übermittlung nicht gesendet. Wenn die Benutzeroberfläche also durch Benutzerbedienung zwischen aktiv und inaktiv wechseln soll, tritt dasselbe Phänomen auf, sofern der Rücksetzparameter nicht zusammen gesendet wird. Es kann vorkommen.

Zusammenfassung

Dieses Mal habe ich über den Wert gesprochen, der beim Anwenden des von Spring MVC bereitgestellten Rücksetzparameters zwischen Spring 4.2 und 4.3 festgelegt wurde. Ist es relativ üblich, "null" mit einem leeren Element gleichzusetzen? Ich fürchte, aber was ist mit Ihrer Bewerbung? Bei der Aktualisierung auf Spring 4.3 sollten Sie vorerst vorsichtig mit Kontrollkästchen und Auswahlelementen umgehen.

Recommended Posts

Spring 4.2 vs 4.3: Unterschied im Bindungswert zum Sammlungstyp beim Senden des Kontrollkästchens leer
Achten Sie bei Verwendung des Float-Typs auf die Grenzprüfung des Eingabewerts
Wenn Sie InputStream in JDBI3 binden möchten
So binden Sie mit einer Eigenschaftendatei in Spring Boot
[String type vs String Builder] Unterschied in der Verarbeitungsgeschwindigkeit in der String-Kombination