Möglicherweise möchten Sie den Inhalt eines Objekts in einer Zeichenfolge kombinieren und in ein Protokoll ausgeben. Zu diesem Zeitpunkt möchte ich dieses Feld nicht protokollieren! Gibt es so etwas? Es ist ein bisschen nervig, toString () zu implementieren, nicht wahr?
Cart.java
package jp.co.pmtech.iwata;
public class Cart {
/**Warenkorb-ID*/
private int id;
/**Artikel im Warenkorb*/
private List<Syohin> syohinList;
//Getter oder Setter
}
Syohin.java
package jp.co.pmtech.iwata;
public class Syohin {
/**Produkt ID*/
private int id;
/**Produktname*/
private String name;
/**Preis*/
private BigDecimal price;
//Getter oder Setter
}
App.java
public final class App {
public static void main(String[] args) {
Syohin syohin1 = new Syohin();
syohin1.setId(1);
syohin1.setName("Kugelschreiber");
syohin1.setPrice(new BigDecimal(120));
Syohin syohin2 = new Syohin();
syohin2.setId(2);
syohin2.setName("Gewebe");
syohin2.setPrice(new BigDecimal(298));
List<Syohin> list = new ArrayList<>();
list.add(syohin1);
list.add(syohin2);
Cart cart = new Cart();
cart.setId(1);
cart.setSyohinList(list);
}
}
Dies kann durch Implementierung wie folgt erreicht werden.
Übrigens hat RecursiveToStringStyle von commons-lang3.2 zugenommen, und Sie können es verwenden, um es rekursiv in eine Zeichenfolge zu konvertieren. Da ReflectionToStringBuilder jedoch intern aufgerufen wird, kann das auszugebende Feld nicht gesteuert werden. Aus diesem Grund habe ich mich entschlossen, ToStringStyle dieses Mal selbst zu erweitern. (Details zu RecursiveToStringStyle werden später im Bonus-Teil beschrieben.)
LogIgnore.java
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogIgnore {
}
Dieses Mal werde ich versuchen, den Preis des Produkts nicht anzugeben (Syohin # Preis).
Syohin.java
public class Syohin {
/**Produkt ID*/
private int id;
/**Produktname*/
private String name;
/**Preis*/
@LogIgnore
private BigDecimal price;
}
Es scheint, dass ReflectionToStringBuilder # accept () das zu stringifizierende Feld bestimmt. Überschreiben Sie dies also.
LoggingToStringBuilder.java
public class LoggingToStringBuilder extends ReflectionToStringBuilder {
public LoggingToStringBuilder(final Object object, final ToStringStyle style) {
super(object, style);
}
public static String reflectionToString(final Object object, final ToStringStyle style) {
LoggingToStringBuilder builder = new LoggingToStringBuilder(object, style) {
@Override
protected boolean accept(final Field field) {
if (!super.accept(field)) {
return false;
}
if (field.getAnnotation(LogIgnore.class) != null) {
return false;
}
return true;
}
};
return builder.toString();
}
}
Vor commons-lang3.2 haben Sie es anscheinend selbst gemacht.
Erstellen Sie eine Klasse, die ToStringStyle erweitert, indem Sie auf den folgenden Artikel verweisen. (Da der Name zufällig commons-lang ist, habe ich ihn diesmal mit dem Klassennamen LoggingToStringStyle erstellt.) Rückwirkende Ausgabe mit ReflectionToString - Ein Memorandum
Sie können die Klasse kopieren und einfügen, ändern Sie jedoch nur die folgenden Punkte.
LoggingToStringStyle.java
protected void appendDetail(StringBuffer buffer, String fieldName, Object value) {
for(String packaz : recursivePackags) {
if (value.getClass().getCanonicalName().startsWith(packaz)) {
// buffer.append(ToStringBuilder.reflectionToString(value, this));
//↓ Hier ändern
buffer.append(LoggingToStringBuilder.reflectionToString(value, this));
return;
}
}
buffer.append(value);
}
App.config
String str = LoggingToStringBuilder.toString(cart, new LoggingToStringStyle("jp.co.pmtech.iwata"));
System.out.println(str);
Ergebnis
jp.co.pmtech.iwata.Cart[id=1,syohinList=[jp.co.pmtech.iwata.Syohin[id=1,name=Kugelschreiber],jp.co.pmtech.iwata.Syohin[id=2,name=Gewebe]]]
Der Inhalt von Cart und Syohin ist korrekt und der Preis wird nicht angezeigt.
Der Zweck dieser Zeit ist die Ausgabe in das Protokoll, daher ist mir das Ausgabeformat egal. Lassen Sie uns die JSON-Version mit Jackson anzeigen. Wenn Sie die JsonIgnore-Annotation hinzufügen, unterliegt sie keiner JSON-Serialisierung.
Syohin.java
public class Syohin {
/**Produkt ID*/
private int id;
/**Produktname*/
private String name;
/**Preis*/
@JsonIgnore
private BigDecimal price;
}
App.java
ObjectMapper mapper = new ObjectMapper();
String str = mapper.writeValueAsString(cart);
System.out.println(str);
Ergebnis
{"id":1,"syohinList":[{"id":1,"name":"Kugelschreiber"},{"id":2,"name":"Gewebe"}]}
Ich kann den Preiswert nicht bekommen.
Es gibt nur ein Problem: Es scheint, dass der Rest Controller von Spring Boot von Jackson in JSON konvertiert wurde. Ich habe diese Methode nicht verwendet, weil ich den Preis in die API-Rückgabe aufnehmen wollte. Wenn Sie Jackson nicht verwenden, können Sie diese Methode verwenden.
Wie oben erwähnt, wurde RecursiveToStringStyle seit 3.2 von commons-lang hinzugefügt. Lass es uns für einen Moment tun. Fügen Sie den folgenden Code am Ende von main ein und führen Sie ihn aus.
App.java
String str = ReflectionToStringBuilder.toString(cart, new RecursiveToStringStyle());
System.out.println(str);
Ergebnis
jp.co.pmtech.iwata.Cart@610455d6[id=1,syohinList=java.util.ArrayList@2c7b84de{jp.co.pmtech.iwata.Syohin@5a07e868[id=1,name=Kugelschreiber,price=java.math.BigDecimal@36baf30c[intVal=<null>,scale=0]],jp.co.pmtech.iwata.Syohin@76ed5528[id=2,name=Gewebe,price=java.math.BigDecimal@24d46ca6[intVal=<null>,scale=0]]}]
Es scheint, dass es rekursiv in eine Zeichenfolge konvertiert wird, aber die Objekt-ID wird angezeigt und ist etwas verrauscht. Darüber hinaus ist der Preis von Big Decimal nicht herausgekommen ...
Es ist eine gute Verwendung, aber vielleicht ist es nur ein Holzspucken ... Aus Sicherheitsgründen möchten Sie keine persönlichen Informationen und Kennwörter im Protokoll ausspucken. Ist es auch ein sehr großes Objekt, das Sie protokollieren möchten? ??
Abhängig von den Anforderungen ist JSON oder Commons-lang RecursiveToStringStyle in Ordnung. Der Quellcode wird auf github veröffentlicht. Bitte beziehen Sie sich darauf. https://github.com/pmt-iwata/LoggingToStringBuilder
Recommended Posts