Как я могу поддерживать метод PUT в моем приложении Spring Boot?

#spring #spring-boot

#spring #spring-boot

Вопрос:

Я использую Angular CLI и Spring Boot.

Все работает (getEmployee, deleteEmployee), но когда я хочу обновить или создать (тем же методом и той же HTML-формой) сотрудника, я получаю в HTML Console / Network эту ошибку:

 [ERROR] message: "Request method 'PUT' not supported"
  

Это мой контроллер:

 @RestController
@RequestMapping("/api")
public class EmployeeController {

    private final EmployeeServiceImpl employeeService;

    @Autowired
    public EmployeeController(EmployeeServiceImpl employeeService) {
        this.employeeService = employeeService;
    }

    @GetMapping("/employees")
    public List<Employee> getAllEmployees() {
        return employeeService.findAllEmployees();
    }

    @GetMapping("/employees/{id}")
    public ResponseEntity<Employee> getEmployeeById(@PathVariable(value = "id") Long employeeId) {
        Employee employee = employeeService.findById(employeeId).get();
        return ResponseEntity.ok().body(employee);
    }


    @PutMapping("/employees/{id}")
    public ResponseEntity<Employee> updateEmployee(@PathVariable(value = "id") Long employeeId,
                                                   @Valid @RequestBody Employee employeeDetails) {
        Employee employee = employeeService.findById(employeeId).get();

        employee.setEmailAddress(employeeDetails.getEmailAddress());
        employee.setLastName(employeeDetails.getLastName());
        employee.setFirstName(employeeDetails.getFirstName());
        employee.setStatus(employeeDetails.getStatus());
        employee.setSkills(employeeDetails.getSkills());
        final Employee updatedEmployee = employeeService.saveEmployee(employee);
        return ResponseEntity.ok(updatedEmployee);
    }

    @DeleteMapping("/employees/{id}")
    public Map<String, Boolean> deleteEmployee(@PathVariable(value = "id") Long employeeId) {
        Employee employee = employeeService.findById(employeeId).get();

        employeeService.deleteEmployee(employee);
        Map<String, Boolean> response = new HashMap<>();
        response.put("deleted", Boolean.TRUE);
        return response;
    }
}//close class
  

Это также мой CORSConfig:

 @Configuration
public class CORSConfiguration implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedHeaders("*")
                .allowedMethods("GET", "POST", "DELETE","PUT");
    }
}//close class
  

Здесь вы можете увидеть мой код Angular:

EmployeeDetail.ts

 export class EmployeeDetailsComponent implements OnInit {

  @Input()
  employee: Employee;
  skills;

  constructor(
    private route: ActivatedRoute, /* holds information about the route to this instance of the EmployeeDetailsComponent */
    private location: Location,
    private employeeService: EmployeeService,
    private skillService: SkillService
  ) {
  }

  ngOnInit() {
    this.getEmployee();
    this.skillService.getSkills().subscribe(res => this.skills = res);
  }

  getEmployee(): void {
    const id =  this.route.snapshot.paramMap.get('id');
    if (id === -1) {
      this.employee = new Employee();
    } else {
      this.employeeService.getEmployee(id)
        .subscribe(employee => this.employee = employee);
    }
  }

  save(): void {
    this.employeeService.updateEmployee(this.employee)
      .subscribe(() => this.goBack());
    console.log('test', this.employee);
  }

  goBack(): void {
    this.location.back();
  }
}
  

Когда я нажимаю «Сохранить», метод перенаправляет меня на метод обновления в моем сервисе;

service.ts

 const httpOptions = {
  headers: new HttpHeaders({'Content-Type': 'application/json'})
};

@Injectable({
  providedIn: 'root'
})
export class EmployeeService {

  private baseUrl = 'http://localhost:8080/api/employees';

  constructor(private http: HttpClient) { }


  /** GET Employees from the server */
  getEmployees(): Observable<Employee[]> {
    return this.http.get<Employee[]>(this.baseUrl);
  }

  getEmployee(id: number): Observable<Employee> {
    const url = this.baseUrl   '/'   id;
    return this.http.get<Employee>(url);
  }

  /** PUT: update the employee on the server */
  updateEmployee(employee: Employee): Observable<any> {
    return this.http.put(this.baseUrl, employee, httpOptions);
  }

  deleteEmployee(id: number): Observable<any> {
    return this.http.delete(`${this.baseUrl}/${id}`, { responseType: 'text' });
  }
}
  

Это мое первое приложение SpringBoot, также с Angular, поэтому я никогда раньше не видел этой ошибки.

Что я могу сделать?

Комментарии:

1. обновите свой метод addCorsMappings с помощью . Разрешенные методы (» * «) .Разрешенные исходные данные(» * «)

2. вот так? общедоступные пустые добавления corsmappings(реестр CorsRegistry) { registry.addMapping(«/**»).allowedHeaders(«*») .allowedMethods(«* «) .allowedOrigins(» * «);

3. можете ли вы опубликовать свой угловой код о том, как вы делаете запрос put?

4. @Configuration public class CORSConfiguration implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**").allowedHeaders("*").allowedMethods("*") .allowedOrigins("*"); } }

5. Похоже, что ваш код angular отправляет запрос в / api /employees, но сопоставление в коде spring — /api/employees /{id}.

Ответ №1:

Ваш код Angular показывает следующий метод

   updateEmployee(employee: Employee): Observable<any> {
    return this.http.put(this.baseUrl, employee, httpOptions);
  }
  

Вы не указали id в angular side. Но для вашей стороны spring boot требуется идентификатор. Поскольку вы не передаете идентификатор, фреймворк не может найти соответствующий метод, что приводит к ошибке 405 «метод не разрешен»

 @PutMapping("/employees/{id}")
public ResponseEntity<Employee> updateEmployee(@PathVariable(value = "id") Long employeeId,
                                               @Valid @RequestBody Employee employeeDetails) {
    Employee employee = employeeService.findById(employeeId).get();

    employee.setEmailAddress(employeeDetails.getEmailAddress());
    employee.setLastName(employeeDetails.getLastName());
    employee.setFirstName(employeeDetails.getFirstName());
    employee.setStatus(employeeDetails.getStatus());
    employee.setSkills(employeeDetails.getSkills());
    final Employee updatedEmployee = employeeService.saveEmployee(employee);
    return ResponseEntity.ok(updatedEmployee);
}
  

Комментарии:

1. Вы можете сделать это так же, как метод delete, или попытаться добавить идентификационные данные внутри объекта employee

2. Хорошо, я отредактировал следующим образом: updateEmployee(employee: Сотрудник): Наблюдаемый<любой> { верните this.http.put( ${this.baseUrl}/${employee.id} , employee, httpOptions); } Если я редактирую или создаю, я получаю эту ошибку: ошибка: «Ошибка внутреннего сервера» сообщение: «Значение отсутствует» путь: «/ api/ employees / 4» статус: 500

3. Редактирование ОБНОВЛЕНИЯ работает хорошо, создайте ошибку 500, как в предыдущем комментарии.

4. какова цель метода create?

5. метод create аналогичен методу update, я понимаю ошибку, идентификатор является автоинкрементным, поэтому мне нужно иметь возможность передавать новый идентификатор, поэтому он может найти нового пользователя. Но я не знаю, почему, когда я создаю нового пользователя, он не генерирует идентификатор. Есть идеи? (Я не устанавливал его в контроллере)