Anonymous
Как это исправить: разрешение [org.springframework.web.httprequestmethodnotsupportedException: метод запроса 'post' не п
Сообщение
Anonymous » 20 фев 2025, 19:21
У меня есть API Spring Boot Rest, и он работает отлично при тестировании через почтальон - все методы HTTP функционируют, как и ожидалось. Однако, когда я пытаюсь взаимодействовать с API из приложения на стороне клиента, я сталкиваюсь с ошибками как на бэкэнд, так и на фронта. /> Решение [org.springframework.web.httprequestmethodnotsupportedException: метод запроса 'post' не поддерживается]
ошибка Frontend < /strong>
[! [Введите описание изображения здесь] [1]] [1] < /p>
Код: Выделить всё
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping("/api/v1/persons")
@CrossOrigin(origins = "http://localhost:4200")
public class PersonController {
@Autowired
private PersonRepository personRepository;
public PersonController(PersonRepository personRepository) {
this.personRepository = personRepository;
}
@RequestMapping(
value = "/api/v1/persons",
produces = "application/json",
consumes = { MediaType.MULTIPART_FORM_DATA_VALUE },
method = RequestMethod.GET)
public ResponseEntity createPerson(
@RequestParam String firstname,
@RequestParam String lastname,
@RequestParam String email,
@RequestParam int age,
@RequestPart(value = "photo", required = false) MultipartFile photo,
@RequestPart(value = "cv", required = false) MultipartFile cv){
try {
Person person = new Person();
person.setFirstname(firstname);
person.setLastname(lastname);
person.setEmail(email);
person.setAge(age);
if (photo != null && !photo.isEmpty()) {
person.setPhoto(photo.getBytes());
}
if (cv != null && !cv.isEmpty()) {
person.setCv(cv.getBytes());
}
System.out.println("Save and upload of the files successfully done");
return ResponseEntity.ok(personRepository.save(person));
} catch (IOException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
// Get All Persons
@GetMapping
public List getAllPersons() {
return personRepository.findAll();
}
// Get Person by ID
@GetMapping("/{id}")
public ResponseEntity getPersonById(@PathVariable Long id) {
Optional person = personRepository.findById(id);
return person.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build());
}
// Update Person
@PutMapping("/{id}")
public ResponseEntity updatePerson(
@PathVariable Long id,
@RequestParam String firstname,
@RequestParam String lastname,
@RequestParam String email,
@RequestParam int age,
@RequestParam(value = "photo", required = false) MultipartFile photo,
@RequestParam(value = "cv", required = false) MultipartFile cv) {
Optional existingPerson = personRepository.findById(id);
if (existingPerson.isPresent()) {
Person person = existingPerson.get();
person.setFirstname(firstname);
person.setLastname(lastname);
person.setEmail(email);
person.setAge(age);
try {
if (photo != null && !photo.isEmpty()) {
person.setPhoto(photo.getBytes());
}
if (cv != null && !cv.isEmpty()) {
person.setCv(cv.getBytes());
}
} catch (IOException e) {
System.out.println("There is something going waring: " + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
return ResponseEntity.ok(personRepository.save(person));
} else {
return ResponseEntity.notFound().build();
}
}
// Download Person's Photo
@GetMapping("/{id}/photo")
public ResponseEntity getPersonPhoto(@PathVariable Long id) {
Optional person = personRepository.findById(id);
if (person.isPresent() && person.get().getPhoto() != null) {
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, "image/png")
.body(person.get().getPhoto());
}
return ResponseEntity.notFound().build();
}
// Download Person's CV
@GetMapping("/{id}/cv")
public ResponseEntity getPersonCv(@PathVariable Long id) {
Optional person = personRepository.findById(id);
if (person.isPresent() && person.get().getCv() != null) {
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_TYPE, "application/pdf")
.body(person.get().getCv());
}
return ResponseEntity.notFound().build();
}
// Delete Person
@DeleteMapping("/{id}")
public ResponseEntity deletePerson(@PathVariable Long id) {
if (personRepository.existsById(id)) {
personRepository.deleteById(id);
return ResponseEntity.noContent().build();
} else {
return ResponseEntity.notFound().build();
}
}
}< /code>
< /div>
< /div>
< /p>
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.List;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // Disable CSRF
.cors(cors -> cors.configurationSource(corsConfigurationSource())) // Enable CORS
.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.POST,"/api/v1/persons/**").permitAll() // Allow all requests to this path
.anyRequest().permitAll() // Allow all requests globally (disable authentication)
);
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(List.of("http://localhost:4200"));
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(List.of("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}< /code>
< /div>
< /div>
< /p>
4.0.0
org.springframework.boot
spring-boot-starter-parent
3.4.2
nl.alexandarabski
person-details
0.0.1-SNAPSHOT
person-details
Person details project for Spring Boot
17
org.springframework.boot
spring-boot-starter-data-jpa
org.springframework.boot
spring-boot-starter-web
org.postgresql
postgresql
runtime
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-starter-security
org.springframework.boot
spring-boot-maven-plugin
< /code>
< /div>
< /div>
< /p>
server:
port: 8081
spring:
mvc:
hiddenmethod:
filter:
enabled: true
datasource:
url: jdbc:postgresql://localhost:5333/personsdetails
hikari:
username: sanny
password: sanny13
jpa:
hibernate:
ddl-auto: update
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
format_sql: true
show-sql: true
servlet:
multipart:
enabled: true
max-file-size: 5MB
max-request-size: 10MB
main:
web-application-type: servlet< /code>
< /div>
< /div>
< /p>
export interface Person {
id?: number;
firstname: string;
lastname: string;
email: string;
age: number;
photo: File | null;
cv: File | null;
}< /code>
< /div>
< /div>
< /p>
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { Person } from './person';
@Injectable({
providedIn: 'root'
})
export class PersonService {
private baseUrl: string = "http://localhost:8081/api/v1/persons";
//headers: HttpHeaders | { [header: string]: string | string[]; } | undefined;
constructor(private _httpClient: HttpClient) { }
fetchAllPersons(): Observable {
return this._httpClient.get(this.baseUrl).pipe(
map((persons: Person[]) => persons.map(person => ({
...person,
photo: person.photo ? `data:image/png;base64,${person.photo}` : null,
cv: person.cv ? `data:application/pdf;base64,${person.cv}` : null
})))
);
}
createPerson(personData: FormData): Observable {
return this._httpClient.post(`${this.baseUrl}`, personData);
}
updatePerson(personId: number, personData: FormData): Observable {
return this._httpClient.put(`${this.baseUrl} ${personId}`, personData);
}
deletePerson(id: number): Observable {
return this._httpClient.delete(`${this.baseUrl}/${id}`);
}
}< /code>
< /div>
< /div>
< /p>
import { ChangeDetectionStrategy, Component,NgModule, inject } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MAT_DIALOG_DATA, MatDialogActions, MatDialogContent, MatDialogModule, MatDialogRef, MatDialogTitle } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatIconModule } from '@angular/material/icon';
import { Person } from '../person';
import { PersonService } from '../person.service';
import { CommonModule } from '@angular/common';
import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
@Component({
selector: 'app-person-form',
imports: [
MatDialogModule,
MatDialogContent,
MatDialogActions,
MatButtonModule,
MatFormFieldModule,
MatIconModule,
MatInputModule,
CommonModule,
ReactiveFormsModule,
FormsModule
],
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './person-form.component.html',
styleUrl: './person-form.component.css'
})
export class PersonFormComponent {
personForm: FormGroup;
selectedPhoto: File | null = null;
selectedCv: File | null = null;
readonly dialogRef = inject(MatDialogRef);
data = inject(MAT_DIALOG_DATA);
constructor(private personService: PersonService, private fb: FormBuilder) {
this.personForm = this.fb.group({
id: [this.data?.id || null],
firstname: [this.data?.firstname || '', Validators.required],
lastname: [this.data?.lastname || '', Validators.required],
email: [this.data?.email || '', [Validators.required, Validators.email]],
age: [this.data?.age || null, [Validators.required, Validators.min(1)]]
});
}
onFileSelected(event: any, fileType: string) {
const file = event.target.files[0];
if (file) {
if (fileType === 'photo') {
this.selectedPhoto = file;
} else if (fileType === 'cv') {
this.selectedCv = file;
}
}
}
addOrUpdatePerson() {
const formData = new FormData();
formData.append('firstname', this.personForm.value.firstname);
formData.append('lastname', this.personForm.value.lastname);
formData.append('email', this.personForm.value.email);
formData.append('age', String(this.personForm.value.age)); // Convert age to string
if (this.selectedPhoto) {
formData.append('photo', this.selectedPhoto);
}
if (this.selectedCv) {
formData.append('cv', this.selectedCv);
}
if (this.personForm.value.id) {
// Update existing person (PUT)
this.personService.updatePerson(this.personForm.value.id, formData).subscribe({
next: (response) => {
console.log('Person updated successfully', response);
this.dialogRef.close(response); // Close the dialog with updated data
},
error: (error) => console.error('Error updating person:', error)
});
} else {
// Create new person (POST)
this.personService.createPerson(formData).subscribe({
next: (response) => {
console.log('Person created successfully', response);
this.dialogRef.close(response); // Close the dialog with new data
},
error: (error) => console.error('Error creating person:', error)
});
}
}
}< /code>
< /div>
< /div>
< /p>
import { Component, ViewChild, AfterViewInit, inject } from '@angular/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { MatCardModule } from '@angular/material/card';
import { Person } from '../person';
import { PersonService } from '../person.service';
import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
import { CommonModule } from '@angular/common';
import { MatSort, MatSortModule } from '@angular/material/sort';
import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { PersonFormComponent } from '../person-form/person-form.component';
@Component({
selector: 'app-home',
imports: [
MatFormFieldModule, MatInputModule, MatButtonModule, MatTableModule,
MatCardModule, CommonModule, MatSortModule, MatPaginatorModule, MatDialogModule
],
templateUrl: './home.component.html',
styleUrl: './home.component.css'
})
export class HomeComponent implements AfterViewInit {
person: Person = { // ✅ Add this property
id: 0,
firstname: '',
lastname: '',
email: '',
age: 0,
photo: null,
cv: null
};
displayedColumns: string[] = ['id', 'firstname', 'lastname', 'email', 'age', 'photo', 'cv', 'edit', 'delete'];
dataSource = new MatTableDataSource();
persons: Person[] = [];
filteredPersons: Person[] = [];
readonly dialog = inject(MatDialog);
@ViewChild(MatSort) sort!: MatSort;
@ViewChild(MatPaginator) paginator!: MatPaginator;
constructor(private personService: PersonService, private sanitizer: DomSanitizer) {}
ngAfterViewInit(): void {
this.loadPersons();
}
loadPersons(): void {
this.personService.fetchAllPersons().subscribe((data) => {
this.persons = data;
this.dataSource = new MatTableDataSource(this.persons);
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
});
}
searchPerson(input: string): void {
this.filteredPersons = this.persons.filter(item =>
item.firstname.toLowerCase().includes(input.toLowerCase()) ||
item.lastname.toLowerCase().includes(input.toLowerCase()) ||
item.email.toLowerCase().includes(input.toLowerCase()) ||
item.age.toString().includes(input)
);
this.dataSource = new MatTableDataSource(this.filteredPersons);
}
openDialog(person?: Person): void {
const dialogRef = this.dialog.open(PersonFormComponent, {
data: person
});
dialogRef.afterClosed().subscribe(result => {
if (result) {
this.loadPersons();
}
});
}
deletePerson(id: number): void {
const isConfirmed = window.confirm('Are you sure you want to delete?');
if (isConfirmed) {
this.personService.deletePerson(id).subscribe(() => {
this.persons = this.persons.filter(item => item.id !== id);
this.dataSource.data = this.persons;
});
}
}
}< /code>
< /div>
< /div>
< /p>
Close
Person Form
Upload Photo
Upload CV
Submit
Cancel
< /code>
< /div>
< /div>
< /p>
Full Stack wiht Angular 19, SpringBoot and Docker[/b]
Add +
Id
{{person.id}}
First Name
{{person.firstname}}
Last Name
{{person.lastname}}
Email
{{person.email}}
Age
{{person.age}}
Photo
CV
Download CV
Edit
Edit
Delete
Delete
Подробнее здесь:
https://stackoverflow.com/questions/794 ... tsupported
1740068460
Anonymous
У меня есть API Spring Boot Rest, и он работает отлично при тестировании через почтальон - все методы HTTP функционируют, как и ожидалось. Однако, когда я пытаюсь взаимодействовать с API из приложения на стороне клиента, я сталкиваюсь с ошибками как на бэкэнд, так и на фронта. /> Решение [org.springframework.web.httprequestmethodnotsupportedException: метод запроса 'post' не поддерживается] [b] ошибка Frontend < /strong> [! [Введите описание изображения здесь] [1]] [1] < /p> [code]import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.util.List; import java.util.Optional; @RestController @RequestMapping("/api/v1/persons") @CrossOrigin(origins = "http://localhost:4200") public class PersonController { @Autowired private PersonRepository personRepository; public PersonController(PersonRepository personRepository) { this.personRepository = personRepository; } @RequestMapping( value = "/api/v1/persons", produces = "application/json", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }, method = RequestMethod.GET) public ResponseEntity createPerson( @RequestParam String firstname, @RequestParam String lastname, @RequestParam String email, @RequestParam int age, @RequestPart(value = "photo", required = false) MultipartFile photo, @RequestPart(value = "cv", required = false) MultipartFile cv){ try { Person person = new Person(); person.setFirstname(firstname); person.setLastname(lastname); person.setEmail(email); person.setAge(age); if (photo != null && !photo.isEmpty()) { person.setPhoto(photo.getBytes()); } if (cv != null && !cv.isEmpty()) { person.setCv(cv.getBytes()); } System.out.println("Save and upload of the files successfully done"); return ResponseEntity.ok(personRepository.save(person)); } catch (IOException e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); } } // Get All Persons @GetMapping public List getAllPersons() { return personRepository.findAll(); } // Get Person by ID @GetMapping("/{id}") public ResponseEntity getPersonById(@PathVariable Long id) { Optional person = personRepository.findById(id); return person.map(ResponseEntity::ok).orElseGet(() -> ResponseEntity.notFound().build()); } // Update Person @PutMapping("/{id}") public ResponseEntity updatePerson( @PathVariable Long id, @RequestParam String firstname, @RequestParam String lastname, @RequestParam String email, @RequestParam int age, @RequestParam(value = "photo", required = false) MultipartFile photo, @RequestParam(value = "cv", required = false) MultipartFile cv) { Optional existingPerson = personRepository.findById(id); if (existingPerson.isPresent()) { Person person = existingPerson.get(); person.setFirstname(firstname); person.setLastname(lastname); person.setEmail(email); person.setAge(age); try { if (photo != null && !photo.isEmpty()) { person.setPhoto(photo.getBytes()); } if (cv != null && !cv.isEmpty()) { person.setCv(cv.getBytes()); } } catch (IOException e) { System.out.println("There is something going waring: " + e.getMessage()); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); } return ResponseEntity.ok(personRepository.save(person)); } else { return ResponseEntity.notFound().build(); } } // Download Person's Photo @GetMapping("/{id}/photo") public ResponseEntity getPersonPhoto(@PathVariable Long id) { Optional person = personRepository.findById(id); if (person.isPresent() && person.get().getPhoto() != null) { return ResponseEntity.ok() .header(HttpHeaders.CONTENT_TYPE, "image/png") .body(person.get().getPhoto()); } return ResponseEntity.notFound().build(); } // Download Person's CV @GetMapping("/{id}/cv") public ResponseEntity getPersonCv(@PathVariable Long id) { Optional person = personRepository.findById(id); if (person.isPresent() && person.get().getCv() != null) { return ResponseEntity.ok() .header(HttpHeaders.CONTENT_TYPE, "application/pdf") .body(person.get().getCv()); } return ResponseEntity.notFound().build(); } // Delete Person @DeleteMapping("/{id}") public ResponseEntity deletePerson(@PathVariable Long id) { if (personRepository.existsById(id)) { personRepository.deleteById(id); return ResponseEntity.noContent().build(); } else { return ResponseEntity.notFound().build(); } } }< /code> < /div> < /div> < /p> import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import java.util.List; @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) // Disable CSRF .cors(cors -> cors.configurationSource(corsConfigurationSource())) // Enable CORS .authorizeHttpRequests(auth -> auth .requestMatchers(HttpMethod.POST,"/api/v1/persons/**").permitAll() // Allow all requests to this path .anyRequest().permitAll() // Allow all requests globally (disable authentication) ); return http.build(); } @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(List.of("http://localhost:4200")); configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")); configuration.setAllowedHeaders(List.of("*")); configuration.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; }< /code> < /div> < /div> < /p> 4.0.0 org.springframework.boot spring-boot-starter-parent 3.4.2 nl.alexandarabski person-details 0.0.1-SNAPSHOT person-details Person details project for Spring Boot 17 org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-web org.postgresql postgresql runtime org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-maven-plugin < /code> < /div> < /div> < /p> server: port: 8081 spring: mvc: hiddenmethod: filter: enabled: true datasource: url: jdbc:postgresql://localhost:5333/personsdetails hikari: username: sanny password: sanny13 jpa: hibernate: ddl-auto: update properties: hibernate: dialect: org.hibernate.dialect.PostgreSQLDialect format_sql: true show-sql: true servlet: multipart: enabled: true max-file-size: 5MB max-request-size: 10MB main: web-application-type: servlet< /code> < /div> < /div> < /p> export interface Person { id?: number; firstname: string; lastname: string; email: string; age: number; photo: File | null; cv: File | null; }< /code> < /div> < /div> < /p> import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { Person } from './person'; @Injectable({ providedIn: 'root' }) export class PersonService { private baseUrl: string = "http://localhost:8081/api/v1/persons"; //headers: HttpHeaders | { [header: string]: string | string[]; } | undefined; constructor(private _httpClient: HttpClient) { } fetchAllPersons(): Observable { return this._httpClient.get(this.baseUrl).pipe( map((persons: Person[]) => persons.map(person => ({ ...person, photo: person.photo ? `data:image/png;base64,${person.photo}` : null, cv: person.cv ? `data:application/pdf;base64,${person.cv}` : null }))) ); } createPerson(personData: FormData): Observable { return this._httpClient.post(`${this.baseUrl}`, personData); } updatePerson(personId: number, personData: FormData): Observable { return this._httpClient.put(`${this.baseUrl} ${personId}`, personData); } deletePerson(id: number): Observable { return this._httpClient.delete(`${this.baseUrl}/${id}`); } }< /code> < /div> < /div> < /p> import { ChangeDetectionStrategy, Component,NgModule, inject } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MAT_DIALOG_DATA, MatDialogActions, MatDialogContent, MatDialogModule, MatDialogRef, MatDialogTitle } from '@angular/material/dialog'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatIconModule } from '@angular/material/icon'; import { Person } from '../person'; import { PersonService } from '../person.service'; import { CommonModule } from '@angular/common'; import { FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'; @Component({ selector: 'app-person-form', imports: [ MatDialogModule, MatDialogContent, MatDialogActions, MatButtonModule, MatFormFieldModule, MatIconModule, MatInputModule, CommonModule, ReactiveFormsModule, FormsModule ], changeDetection: ChangeDetectionStrategy.OnPush, templateUrl: './person-form.component.html', styleUrl: './person-form.component.css' }) export class PersonFormComponent { personForm: FormGroup; selectedPhoto: File | null = null; selectedCv: File | null = null; readonly dialogRef = inject(MatDialogRef); data = inject(MAT_DIALOG_DATA); constructor(private personService: PersonService, private fb: FormBuilder) { this.personForm = this.fb.group({ id: [this.data?.id || null], firstname: [this.data?.firstname || '', Validators.required], lastname: [this.data?.lastname || '', Validators.required], email: [this.data?.email || '', [Validators.required, Validators.email]], age: [this.data?.age || null, [Validators.required, Validators.min(1)]] }); } onFileSelected(event: any, fileType: string) { const file = event.target.files[0]; if (file) { if (fileType === 'photo') { this.selectedPhoto = file; } else if (fileType === 'cv') { this.selectedCv = file; } } } addOrUpdatePerson() { const formData = new FormData(); formData.append('firstname', this.personForm.value.firstname); formData.append('lastname', this.personForm.value.lastname); formData.append('email', this.personForm.value.email); formData.append('age', String(this.personForm.value.age)); // Convert age to string if (this.selectedPhoto) { formData.append('photo', this.selectedPhoto); } if (this.selectedCv) { formData.append('cv', this.selectedCv); } if (this.personForm.value.id) { // Update existing person (PUT) this.personService.updatePerson(this.personForm.value.id, formData).subscribe({ next: (response) => { console.log('Person updated successfully', response); this.dialogRef.close(response); // Close the dialog with updated data }, error: (error) => console.error('Error updating person:', error) }); } else { // Create new person (POST) this.personService.createPerson(formData).subscribe({ next: (response) => { console.log('Person created successfully', response); this.dialogRef.close(response); // Close the dialog with new data }, error: (error) => console.error('Error creating person:', error) }); } } }< /code> < /div> < /div> < /p> import { Component, ViewChild, AfterViewInit, inject } from '@angular/core'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatButtonModule } from '@angular/material/button'; import { MatTableDataSource, MatTableModule } from '@angular/material/table'; import { MatCardModule } from '@angular/material/card'; import { Person } from '../person'; import { PersonService } from '../person.service'; import { DomSanitizer, SafeUrl } from '@angular/platform-browser'; import { CommonModule } from '@angular/common'; import { MatSort, MatSortModule } from '@angular/material/sort'; import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator'; import { MatDialog, MatDialogModule } from '@angular/material/dialog'; import { PersonFormComponent } from '../person-form/person-form.component'; @Component({ selector: 'app-home', imports: [ MatFormFieldModule, MatInputModule, MatButtonModule, MatTableModule, MatCardModule, CommonModule, MatSortModule, MatPaginatorModule, MatDialogModule ], templateUrl: './home.component.html', styleUrl: './home.component.css' }) export class HomeComponent implements AfterViewInit { person: Person = { // ✅ Add this property id: 0, firstname: '', lastname: '', email: '', age: 0, photo: null, cv: null }; displayedColumns: string[] = ['id', 'firstname', 'lastname', 'email', 'age', 'photo', 'cv', 'edit', 'delete']; dataSource = new MatTableDataSource(); persons: Person[] = []; filteredPersons: Person[] = []; readonly dialog = inject(MatDialog); @ViewChild(MatSort) sort!: MatSort; @ViewChild(MatPaginator) paginator!: MatPaginator; constructor(private personService: PersonService, private sanitizer: DomSanitizer) {} ngAfterViewInit(): void { this.loadPersons(); } loadPersons(): void { this.personService.fetchAllPersons().subscribe((data) => { this.persons = data; this.dataSource = new MatTableDataSource(this.persons); this.dataSource.sort = this.sort; this.dataSource.paginator = this.paginator; }); } searchPerson(input: string): void { this.filteredPersons = this.persons.filter(item => item.firstname.toLowerCase().includes(input.toLowerCase()) || item.lastname.toLowerCase().includes(input.toLowerCase()) || item.email.toLowerCase().includes(input.toLowerCase()) || item.age.toString().includes(input) ); this.dataSource = new MatTableDataSource(this.filteredPersons); } openDialog(person?: Person): void { const dialogRef = this.dialog.open(PersonFormComponent, { data: person }); dialogRef.afterClosed().subscribe(result => { if (result) { this.loadPersons(); } }); } deletePerson(id: number): void { const isConfirmed = window.confirm('Are you sure you want to delete?'); if (isConfirmed) { this.personService.deletePerson(id).subscribe(() => { this.persons = this.persons.filter(item => item.id !== id); this.dataSource.data = this.persons; }); } } }< /code> < /div> < /div> < /p> Close Person Form Upload Photo Upload CV Submit Cancel < /code> < /div> < /div> < /p> Full Stack wiht Angular 19, SpringBoot and Docker[/b] Add + Id {{person.id}} First Name {{person.firstname}} Last Name {{person.lastname}} Email {{person.email}} Age {{person.age}} Photo CV Download CV Edit Edit Delete Delete [/code] Подробнее здесь: [url]https://stackoverflow.com/questions/79455166/how-to-fix-this-resolved-org-springframework-web-httprequestmethodnotsupported[/url]