如何为 Spring Boot Rest 使用自定义异常?

Posted

技术标签:

【中文标题】如何为 Spring Boot Rest 使用自定义异常?【英文标题】:How to use Custom Exception for Spring Boot Rest? 【发布时间】:2016-10-31 10:54:30 【问题描述】:

我正在使用 Spring Boot 连接到 mysql 5 数据库(通过 JPA)以及用于服务器端的 Spring Rest。

我的 POJO:

@Entity
public class Employee 

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String firstName;
    private String lastName;

    public String getFirstName() 
        return firstName;
    

    public void setFirstName(String firstName) 
        this.firstName = firstName;
    

    public String getLastName() 
        return lastName;
    

    public void setLastName(String lastName) 
        this.lastName = lastName;
    

EmployeRespository:

@RepositoryRestResource(collectionResourceRel = "employee", path = "employee")
public interface EmployeeRepository extends PagingAndSortingRepository<Employee, Long> 

    Collection<Employee> findByLastName(@Param("name") String name);


员工服务:

@RestController
@RequestMapping("/employee")
public class EmployeeService 

    @Autowired
    private EmployeeRepository employeeRepository;

    @RequestMapping(value = "/findByLastName?lastName=", method = RequestMethod.GET)
    Object getEmployees(@PathVariable String lastName) 
        Collection<Employee> result = this.employeeRepository.findByLastName(lastName);
        if (result == null) 
            throw new EmployeeNotFoundException(lastName);
        
        return result;
    

EmployeeNotFoundException:

public class EmployeeNotFoundException extends RuntimeException 

    private static final long serialVersionUID = 1L;

    public EmployeeNotFoundException(String id) 
        super("Could not find Employee " + id);
    

现在当调用我的 REST API 时,我得到以下结果:

这个在我的数据库中不存在并且没有抛出 EmployeeNotFoundException:

curl -X GET -H "Content-Type:application/json" http://localhost:8080/employee/search/findByLastName?name="Smith"

结果:


    "_embedded" : 
        "employee" : [ ]
    ,
    "_links" : 
        "self" : 
            "href" : "http://localhost:8080/employee/search/findByLastName?name=Smith"
        
    

问题:

    为什么会抛出我的 EmployeeNotFoundException?有没有更好的方法来实现这一点(可能还会显示 HTTP 状态代码)?

    任何有关如何进行单元测试的 URL 都会很棒(以及最好的单元测试库)...

感谢您抽出宝贵时间阅读本文。

【问题讨论】:

【参考方案1】:

如果您想知道 EmployeeNotFoundException,它会被抛出但未被处理。 您至少需要一个 @ExceptionHandler 注释方法来处理它。

 @ExceptionHandler(EmployeeNotFoundException.class)
        public void handleException(EmployeeNotFoundException  e) 
        // do something
        

像这样:

 @RestController
    @RequestMapping("/employee")
    public class EmployeeService 

        @Autowired
        private EmployeeRepository employeeRepository;

        @RequestMapping(value = "/findByLastName?lastName=", method = RequestMethod.GET)
        Object getEmployees(@PathVariable String lastName) 
            Collection<Employee> result = this.employeeRepository.findByLastName(lastName);
            if (result == null) 
                throw new EmployeeNotFoundException(lastName);
            
            return result;
        

       @ExceptionHandler(EmployeeNotFoundException.class)
        public void handleException(EmployeeNotFoundException  e) 
         System.out.println("Exception triggered");
        

    

【讨论】:

抱歉,您的建议仍然无效...我在标准输出的任何地方都没有看到“异常触发”。【参考方案2】:

这是因为,下一行返回的不是 null,而是一个空列表。

Collection<Employee> result = this.employeeRepository.findByLastName(lastName);

您既可以检查空列表是否抛出异常,也可以只返回空列表。我不建议为查找/搜索抛出异常。我个人,只为getById 之类的get 方法抛出任何NotFoundException。否则我只返回空列表。

if (result == null || result.isEmpty()) 
    throw new EmployeeNotFoundException(lastName);

另外,修改 Hey-men-wattsup 的代码以发送错误代码,而不是在 Controller 中抛出异常。这将发送 404,NotFound 代码。

@ExceptionHandler(EmployeeNotFoundException.class)
    public void handleException(EmployeeNotFoundException  e, , HttpServletResponse response) 
    response.sendError(HttpStatus.NOT_FOUND.value(), e.getMessage());

Spring Boot Test 的 MockMvc 类结合 Mockito 提供了对控制器进行单元测试所需的方法。

【讨论】:

以上是关于如何为 Spring Boot Rest 使用自定义异常?的主要内容,如果未能解决你的问题,请参考以下文章

如何为 Spring Boot 应用程序配置端口

如何为 Webflux、Spring-Security、okta-spring-boot-starter 和 Okta-React 正确使用 CORS?

如何为批量插入配置spring boot和data jpa

如何为 ZuulException 自定义 Spring Boot 控制器 API 响应

如何为我的 Spring Boot webapp 选择 URL?

如何为我的 Spring Boot 控制器执行单元测试?