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

时间:2018-04-30 14:58:42

标签: rest spring-boot spring-rest

我有一个使用Spring启动的Restful webservice。响应是bean EmployeeResponseData,它在春天转换为json。根据业务,当输入员工ID匹配时,Web服务应返回员工详细信息,否则应返回带有错误的json响应,如下所示

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

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

如果自定义异常,我如何返回带有所需错误的JSON,而不必形成json并返回而不是使用bean作为返回对象,因为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;
    }


}

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

2 个答案:

答案 0 :(得分:1)

首先,编写一个名为ApiErrorReponse.java的POJO类

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

答案 1 :(得分:1)

您可以使用@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);
}

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