#angular #spring-boot #http-post #angular-services #angular-components
Вопрос:
Я использую Angular 12 CLI и Spring Boot 2.5.5. Используя службу Angular, я пытаюсь передать JSON из компонента в Spring Boot, используя http-запрос POST. После того, как JSON поступит в Spring Boot, мне нужно распечатать его в консоли, но я не могу заставить его работать. Используя Postman, я правильно визуализирую JSON, поэтому я думаю, что проблема в интерфейсной стороне. Вот какой-то код:
users.service.ts
import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { HttpHeaders } from '@angular/common/http'; import { Observable } from 'rxjs'; import { User } from 'src/user'; @Injectable({ providedIn: 'root' }) export class UsersService { constructor(private http: HttpClient) { } getUsers(): Observablelt;User[]gt;{ return this.http.getlt;User[]gt;("http://localhost:8080/user/all") } addNewUser(user: User): void { const httpOptions = { headers: new HttpHeaders( { 'Content-Type': 'application/json' } ) }; let userJSON = JSON.stringify(user); this.http.post("http://localhost:8080/user/add", userJSON, httpOptions); } }
Пользовательский контроллер
package com.sporthub.backend.controller; import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import com.sporthub.backend.model.Role; import com.sporthub.backend.model.User; import com.sporthub.backend.repository.RoleRepository; import com.sporthub.backend.repository.UserRepository; @Controller @CrossOrigin(origins = "http://localhost:4200") @RequestMapping("/user") public class UserController { @Autowired private UserRepository userRepo; @Autowired private RoleRepository roleRepo; @GetMapping("/all") public @ResponseBody Iterablelt;Usergt; getUsers(){ return userRepo.findAll(); } @PostMapping("/add") public @ResponseBody String addUser(@RequestBody String user) { System.out.println(user); return user; } }
HTML Form
lt;form [formGroup]="checkoutForm" (ngSubmit)="onSubmit()"gt; lt;divgt; lt;label for="name"gt; Name lt;/labelgt; lt;input type="text" id="name" formControlName="name"gt; lt;/divgt; lt;divgt; lt;label for="lastname"gt; lastname lt;/labelgt; lt;input type="text" id="lastname" formControlName="lastname"gt; lt;/divgt; lt;input type="submit" value="Add new user"gt; lt;/formgt;
Компонент пользователей
import { Component, OnInit } from '@angular/core'; import { User } from 'src/user'; import { UsersService } from '../users.service'; import { FormBuilder } from '@angular/forms'; @Component({ selector: 'app-users', templateUrl: './users.component.html', styleUrls: ['./users.component.css'] }) export class UsersComponent implements OnInit { users : User[] = []; checkoutForm = this.formBuilder.group({ name: '', lastname: '' }); constructor( private usersService: UsersService, private formBuilder: FormBuilder ) { } onSubmit(): void { let name = this.checkoutForm.get('name')?.value; let lastname = this.checkoutForm.get('lastname')?.value; let user: User = { "name": name, "lastname": lastname }; console.log(user); this.usersService.addNewUser(user); } ngOnInit(): void { this.getUtenti(); console.log(this.users); } getUsers() : void{ this.usersService.getUsers().subscribe(users =gt; this.users = users); } }
Комментарии:
1. Нет необходимости в
JSON.stringify
теле заранее. Просто передайте объект, и пусть магия Angular сделает свою работу 🙂2. @jBuchholz спасибо за подсказку. Кстати, это не решило проблему 🙁
Ответ №1:
Вы добавляете заголовок типа контента в веб-сервис на стороне клиента, но не сообщаете об этом своему бэкенду.
Я думаю, вам следует переработать свой @PostMapping
метод, чтобы:
@PostMapping(path = "/add", produces = MediaType.APPLICATION_JSON_VALUE) // lt;- here public @ResponseBody String addUser(@RequestBody String user) { System.out.println(user); return user; }
В качестве альтернативы вы можете добавить его в @RequestMapping
, чтобы он был применим ко всем методам контроллера.
Кстати: вы возвращаете строку, а не объект (который будет проанализирован в json)
Поэтому я предлагаю вам изменить свое @RequestBody String user
@RequestBody YourUserDtoBackendType user
JSON.stringify(user)
«кому», удалить и передать a user
непосредственно в теле веб-службы на стороне клиента, после чего сериализация/десериализация должна выполняться автоматически Jackson
(что обеспечивает встроенную поддержку Spring Boot для этого).
Комментарии:
1. Добавление производит = тип носителя. APPLICATION_JSON_VALUE не решил проблему. Мне пришлось кое-что изменить в своем коде (добавив наблюдаемый тип возвращаемого значения и подписку на вызов метода внутри моего компонента). Я ответил прямо ниже, проверьте это.
Ответ №2:
Использовал наблюдаемый в качестве возвращаемого типа для моей функции addNewUser внутри моей службы пользователей
addNewUser(user: User): Observablelt;Usergt; { return this.http.postlt;Usergt;("http://localhost:8080/user/add", user, this.httpOptions); }
Затем я добавил метод .subscribe() в свою функцию onSubmit() внутри своего компонента.
this.usersService.addNewUser(user).subscribe(user =gt; console.log(user));