在 CustomException 的情况下返回错误 JSON 响应而不是常规 json 响应映射到 Sping 引导中的 bean Restful ws

Returning error JSON response in case of CustomException instead of regular json response mapped to bean in Sping boot Restful ws

我有一个使用 Spring 引导的 Restful 网络服务。响应是一个 bean EmployeeResponseData,它被 spring 转换为 json。根据业务,当输入的员工 ID 匹配时,Web 服务应 return 员工详细信息,否则 json 错误响应应 return 编辑如下

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

截至目前,如果输入 empId 匹配,我将根据 bean EmployeeResponseData 得到正确的 json 响应。但如果 empId 不匹配,我就会变得空白。

我如何 return JSON 在自定义异常的情况下出现所需的错误,而不必形成 json 和 return 而不是使用 bean 作为 return 对象,因为它被 Spring.

自动转换为 jSON

下面是代码。

豆子

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;
    }


}

员工响应数据

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);
    }
}

首先写一个POJO class 命名为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);
}

您可能想提高基础知识,您的服务 class 写得不好,可能无法一直运行。

编辑

因此,根据您的评论,您可以做的是在您的服务 class 和控制器中抛出异常,捕获这些异常并将异常消息 return 作为错误响应。

@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);    
    }
}

您可以使用@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 Exception 声明,如下所示:

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

您可能需要重新编写您的服务 class 逻辑以从某些资源或数据库中获取数据,并根据结果,您可以在成功案例中构建 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;
}