2017-02-27 1 views
0

ich einen Angular 2 Dienst haben, POSTs Daten anmelden, um einen Spring Boot@RestContollerWie kann ich generieren einen POJO von einem HTTP-POST-Anfrage in einer Frühlings-Boot-Anwendung

Der Login-Anfrage Körper:

{"_username": "test", "_password": "test"} 

The Rest Controller:

@RestController 
public class AuthControl { 
    @Autowired 
    AuthenticationService authenticationService; 

    @RequestMapping(value = "/someurl", method = RequestMethod.POST) 
    public LoginDto authenticate(HttpServletResponse response, LoginRequestDto requestDto) throws IOException, JSONException { 
     return authenticationService.authenticate(requestDto, response); 
    } 
} 

Jackson unmarshalls die Anforderung in diesem POJO

Wenn jedoch Jackson den POJO abmarschallt, werden die Feldwerte auf null gesetzt, anstatt "test"/"test". Daher schlägt der Anmeldeversuch mit einer Nachricht mit ungültigen Anmeldeinformationen fehl. Ich frage mich, ob ich eine Bibliothek oder etwas vermisse, das in der unpassenden Einstellung dieser Felder resultiert.

Abhängigkeiten von pom.xml

<parent> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-parent</artifactId> 
    <version>1.5.1.RELEASE</version> 
    <relativePath/> 
</parent> 

<dependencies> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-web</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-security</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-tomcat</artifactId> 
     <scope>provided</scope> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-data-jpa</artifactId> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-thymeleaf</artifactId> 
    </dependency> 
    <dependency><!-- implements Thymeleaf HTML5 parsing --> 
     <groupId>net.sourceforge.nekohtml</groupId> 
     <artifactId>nekohtml</artifactId> 
     <version>1.9.22</version> 
    </dependency> 
    <dependency> 
     <groupId>com.fasterxml.jackson.datatype</groupId> 
     <artifactId>jackson-datatype-json-org</artifactId> 
     <version>2.4.0</version> 
    </dependency> 
</dependencies> 

Tthe einzige Ausnahme angemeldet ist ein UsernameNotFoundException durch meine implmentation von Spring Security UserDetailsService geworfen. Mit dem Debugger kann ich die Werte aus der Anfrage manuell analysieren und die Werte in das POJO setzen. Nachdem die Anfrage abgeschlossen wurde, ist das Problem offensichtlich in der Unmarshalling-Phase.

Alle Gedanken oder Vorschläge würden sehr geschätzt werden.

Antwort

1

Das liegt daran, dass Jackson beim Deserialisieren standardmäßig den Standardkonstruktor verwendet. Sie müssen die Annotation verwenden, um jackson wissen zu lassen, welchen Konstruktor Sie verwenden möchten, und die Annotation @JsonProperty, um wissen zu lassen, wie Sie die Parameter mit den json-Eigenschaften binden können.

public class LoginRequestDto { 
    private String _username; 
    private String _password; 

    public LoginRequestDto() { } 

    @JsonCreator 
    public LoginRequestDto(@JsonProperty("_username") String u, 
          @JsonProperty("_password") String p) { 
     this._username = u; 
     this._password = p; 
    } 

    // getters and setters 
} 

Werfen Sie einen Blick auf den Abschnitt Konstrukteuren oder Factory-Methoden verwenden am jackson-annotations project.


Aktualisieren Sie Ihre Anfrage Mapping-Methode es Angabe verbraucht json und fügen Sie die @RequestBody Anmerkung der Methode param

@RestController 
public class AuthControl { 
    @Autowired 
    AuthenticationService authenticationService; 

    @RequestMapping(value = "/someurl", method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE }) 
    public LoginDto authenticate(HttpServletResponse response, @RequestBody LoginRequestDto requestDto) throws IOException, JSONException { 
     return authenticationService.authenticate(requestDto, response); 
    } 
} 
+0

Vielen Dank für die Eingabe. Ich fügte die Anmerkungen wie vorgeschlagen ohne Erfolg hinzu. Keine Änderung, der Standardkonstruktor wird immer noch aufgerufen. Das Auskommentieren des Standardkonstruktors enthüllt den Grund - Spring erstellt das POJO-Argument. Ist die einzige echte Option ein benutzerdefinierter Deserializer? –

+0

@TheHeadRush Was meinst du mit "Frühling schafft das POJO"? Es sollte funktionieren. Sie benötigen dafür keinen Custom Deserialiser, es ist ziemlich einfach. Sie verwenden eine alte Version von jackson-datatype-son-org. Schließen Sie Abhängigkeiten für Jackson-Core-, Jackson-Databind- und Jackson-Annotationen ein (v2.8.6). Wird Ihre Methode bei der Anfrage getroffen? Setzen Sie den Content-Type-Header? Es scheint, dass Spring denkt, dass es den Antragskörper nicht konvertieren muss – alfcope

+0

Wenn ich sage "Frühling schafft den POJO" meine ich, dass absichtlich POJO Instanziierung (durch Auskommentieren des Standardkonstruktors) in einem Stapel-Trace führt, der keine Frames enthält, die Jackson referenzieren. Die Abhängigkeit für 'jackson-datatype-son-org' wurde aktualisiert. Explizite Abhängigkeiten zu v2.8.6 der drei Jackson-Jars hinzugefügt. Die erwartete Controller-Methode wird getroffen, der Content-Type-Header wird auf "application/json" gesetzt. Ich bin verwirrt. –

Verwandte Themen