Возврат ответа JSON с ошибкой в ​​случае CustomException вместо обычного ответа json, сопоставленного с bean-компонентом в загрузке Sping Restful ws

У меня есть веб-сервис Restful, использующий Spring boot. Ответом является компонент EmployeeResponseData, который весной преобразуется в json. В соответствии с бизнесом веб-служба должна возвращать сведения о сотруднике, когда входной идентификатор сотрудника совпадает, иначе должен быть возвращен ответ json с ошибкой, как показано ниже.

{"Error ": "Employee not not found for empId "+ **empId** }

На данный момент я получаю правильный ответ json в соответствии с bean-компонентом EmployeeResponseData, если входной empId совпадает. Но я становлюсь пустым, если empId не совпадает.

Как я могу вернуть JSON с желаемой ошибкой в ​​случае настраиваемого исключения, без необходимости формировать json и возвращать вместо использования beans в качестве возвращаемого объекта, поскольку он автоматически преобразуется в jSON с помощью Spring.

Ниже приведен код.

Бобы

EmployeeRequestData

package com.beans;

import org.springframework.stereotype.Component;

@Component
public class EmployeeRequestData {
    private int EmpoyeeId;

    public int getEmpoyeeId() {
        return EmpoyeeId;
    }

    public void setEmpoyeeId(int empoyeeId) {
        EmpoyeeId = empoyeeId;
    }


}

EmployeeResponseData

package com.beans;

import java.util.ArrayList;

import org.springframework.stereotype.Component;

@Component
public class EmployeeResponseData {

    private int employeeId;
    private String name;
    private String department;
    private ArrayList<String> skills; 

    public int getEmployeeId() {
        return employeeId;
    }
    public void setEmployeeId(int employeeId) {
        this.employeeId = employeeId;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getDepartment() {
        return department;
    }
    public void setDepartment(String department) {
        this.department = department;
    }
    public ArrayList<String> getSkills() {
        return skills;
    }
    public void setSkills(ArrayList<String> skills) {
        this.skills = skills;
    }   
}

Контроллер

package com.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.beans.EmployeeResponseData;
import com.service.ServiceRequest;

@RestController
public class WebServiceController {

    @Autowired
    private ServiceRequest serviceRequest;

    @RequestMapping(value = "restws/getEmpDetails/{empId}",method=RequestMethod.GET)
    //@ResponseBody   // not required since using @RestController
    public EmployeeResponseData getEmployeeDetails(@PathVariable("empId") int empId) {
        return serviceRequest.getEmployeeDetails(empId);
    }
}

Услуга

package com.service;

import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.beans.EmployeeResponseData;
import com.exception.EmployeeNotFoundException;

@Service
public class ServiceRequest {

    private static Logger LOGGER = LoggerFactory.getLogger(ServiceRequest.class);

    @Autowired
    private EmployeeResponseData employeeResponseData;

    public EmployeeResponseData getEmployeeDetails(int empId) {

             ArrayList<String> employeeSkills = (ArrayList<String>) Stream.of("Core Java"
                    ,"Restful web services"
                    ,"Spring Boot"
                    ,"PLSQL").collect(Collectors.toList());

            employeeResponseData.setEmployeeId(empId);
            employeeResponseData.setName("Priyanjan Kumar");
            employeeResponseData.setDepartment("ENGNE");
            employeeResponseData.setSkills(employeeSkills);
        }else {
            try {
                throw new EmployeeNotFoundException(empId);
            } catch (EmployeeNotFoundException e) {
                LOGGER.info("Employee data not found for empId :"+empId);
            }
        }
        return employeeResponseData;
    }
}

Пользовательское исключение

package com.exception;

public class EmployeeNotFoundException extends Exception{

    private String message = "Employee not found";

    public EmployeeNotFoundException() {
        // super(message); it takes only static variable
    }

    public EmployeeNotFoundException(int empId) {
        message = message+" for Employee : "+ Integer.toString(empId);
    }

    @Override
    public String toString() {
        return message;
    }
}

SpringBootApplication

package com;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class);
    }
}
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
331
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Сначала напишите класс POJO с именем ApiErrorReponse.java.

public class ApiErrorResponse{
    private final String error;
    //Any addtional info you might later want to add to it
    public ApiErrorResponse(String error){
        this.error = error;
    }

    public String getError(){
        return this.error;
    }
}

Теперь в вашем контроллере измените конечную точку на.

@RequestMapping(value = "restws/getEmpDetails/{empId}",method=RequestMethod.GET)
public ResponseEntity<?> getEmployeeDetails(@PathVariable("empId") int empId) {
    EmployeeResponseData data = serviceRequest.getEmployeeDetails(empId);

    if (data != null){
        return new ResponseEntity<EmployeeResponseData>(data, HttpStatus.OK);
    }

    ApiErrorResponse errorReponseDto = new ApiErrorResponse("Employee not not found for empId "+ empId);
    return  new ResponseEntity<ApiErrorResponse>(errorReponseDto, HttpStatus.NOT_FOUND);
}

Возможно, вы захотите улучшить основы, ваш класс обслуживания плохо написан и может работать не всегда.

РЕДАКТИРОВАТЬ

Итак, согласно вашему комментарию, вы можете генерировать исключения в своем классе обслуживания и в вашем контроллере, перехватывать эти исключения и возвращать сообщение об исключении в качестве ответа об ошибке.

@RequestMapping(value = "restws/getEmpDetails/{empId}",method=RequestMethod.GET)
public ResponseEntity<?> getEmployeeDetails(@PathVariable("empId") int empId) {

    try{
        EmployeeResponseData data = serviceRequest.getEmployeeDetails(empId);
        return new ResponseEntity<EmployeeResponseData>(data, HttpStatus.OK);
    }
    catch(Exception ex){
        ApiErrorResponse errorReponseDto = new ApiErrorResponse(ex.getMessage());
        return  new ResponseEntity<ApiErrorResponse>(errorReponseDto, HttpStatus.NOT_FOUND);    
    }
}

Спасибо за ответ. Это почти то, что я хочу. Но вместо установки ошибки в контроллере я хочу установить ошибку в классе обслуживания, поэтому, если я установил сообщение об ошибке в классе обслуживания, то как мне получить этот объект ApiErrorResponse, который имеет сообщение об ошибке в контроллере. потому что есть разные случаи ошибок, и кодировать все это в контроллере - не лучшая идея. Также данные могут быть не нулевыми, но только мы не можем отправить их в ответ, поскольку запрашивающая сторона не имеет права просматривать данные. Мой класс обслуживания я жестко запрограммировал, чтобы дать только базовую идею.

prnjn 01.05.2018 18:08
Ответ принят как подходящий

Вы можете использовать аннотацию @ControllerAdvice для обработки различных типов исключений, возникающих в приложении.

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html

Ниже приведен пример кода, как это выглядит:

@ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(EmployeeNotFoundException.class)
    public ResponseEntity<String> handleEntityNotFoundException(HttpServletRequest request, Exception ex) {
        return ResponseUtil.buildErrorResponseEntity(ex.getMessage(), HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleGenericException(HttpServletRequest request, Exception ex) {
        return ResponseUtil.buildErrorResponseEntity(ex.getMessage(), HttpStatus.BAD_REQUEST);
    }
}

Вы можете написать метод для создания сообщений об ошибках в соответствии с вашими требованиями.

Кроме того, вам нужно добавить объявление исключения throws в свой контроллер следующим образом:

public EmployeeResponseData getEmployeeDetails(@PathVariable("empId") int empId) throws Exception {
    return serviceRequest.getEmployeeDetails(empId);
}

Возможно, вам придется переписать логику вашего класса обслуживания, чтобы получить данные из какого-либо ресурса или БД, и на основе результата вы можете создать ответ bean-компонента в случае успеха или соответственно сгенерировать исключение.

public EmployeeResponseData getEmployeeDetails(int empId) {

     // Get data from resource/DB based on empId
     EmployeeResponseData employeeResponseData = new EmployeeResponseData();
     if (data != null) {
         ArrayList<String> employeeSkills = (ArrayList<String>) Stream.of("Core Java"
                ,"Restful web services"
                ,"Spring Boot"
                ,"PLSQL").collect(Collectors.toList());

        employeeResponseData.setEmployeeId(empId);
        employeeResponseData.setName("Priyanjan Kumar");
        employeeResponseData.setDepartment("ENGNE");
        employeeResponseData.setSkills(employeeSkills);
    } else {
           throw new EmployeeNotFoundException(empId);
        }
    }
    return employeeResponseData;
}

Я получаю ошибку компиляции, говоря, что ResponseUtil не может быть разрешен в классе RestExceptionHandler. Мне нужно добавить для этого дополнительную зависимость?

prnjn 03.05.2018 23:26

Это настраиваемый класс, который может быть написан вами для обработки различных типов ответов, таких как успешный ответ и ответ об ошибке. Я просто привел пример.

Abhay Jain 05.05.2018 13:38

Другие вопросы по теме