首页 > 解决方案 > 如何避免 if-else 树代码?

问题描述

我有一个休息控制器,其中包括一种根据“标题”和“作者”参数查找书籍的方法。

你能给我任何提示如何摆脱 if-else 结构吗?现在它并不复杂,但将来参数的数量可能会增加,这将导致混乱。

    @GetMapping
    public ResponseEntity<List<Book>> searchBooksByTitleAndAuthor(
            @RequestParam(value = "title", required = false) String title,
            @RequestParam(value = "author", required = false) String author) {

        if (title == null && author == null) {
            log.info("Empty request");
            return new ResponseEntity<>(HttpStatus.NO_CONTENT);
        } else if (title != null && author == null) {
            log.info("Retrieving books by title");
            List<Book> books = bookService.getBooksByTitle(title);
            if (books.isEmpty()) {
                log.info("No books with this title");
                return new ResponseEntity<>(HttpStatus.NO_CONTENT);
            }
            return new ResponseEntity<>(books, HttpStatus.OK);
        } else if (author != null && title == null) {
            List<Book> books = bookService.getBooksByTitle(title);
            if (books.isEmpty()) {
                log.info("No books with this title");
                return new ResponseEntity<>(HttpStatus.NO_CONTENT);
            }
            return new ResponseEntity<>(books, HttpStatus.OK);
        } else {
            List<Book> books = bookService.getBooksByTitleAndAuthor(title, author);
            if (books.isEmpty()) {
                log.info("No books with matching this title and author");
                return new ResponseEntity<>(HttpStatus.NO_CONTENT);
            }
            return new ResponseEntity<>(books, HttpStatus.OK);
        }

    }

标签: javaspringrest

解决方案


由于您的计划是最终支持更多参数,因此您最好的选择可能是研究Hibernate 的Criteriaclass。这允许您动态构建查询。它不会避免if语句,但避免else语句并使支持新参数变得非常容易。在您的存储库/DAO 级别:

Criteria criteria = session.createCriteria(Book.class);
if (author != null && !author.isEmpty()) {
    criteria.add(Restriction.eq("author", author));
}
if (title != null && !title.isEmpty()) {
    criteria.add(Restriction.eq("title", title));
}
criteria.addOrder(Order.asc("publishDate"));
return (List<Book>) criteria.list();

这有一些显着的好处:

  1. 要支持新参数,您只需将参数添加到控制器,然后将参数传递到存储库,并将参数添加到此块。

  2. 您最终可以使您的排序可配置,例如:

    ?sort=title:asc&author=Bobby%20Tables

但是,有一些缺点,最明显的是它依赖于字符串值来引用您的属性。如果您的属性名称发生更改(注意这是 POJO 属性,而不是 DB 列名称),则需要更改此代码。但是,我认为这是一种非常罕见的情况,除非在最新的新项目中数据库模式仍在不断变化,并且在建立数据库模式之后,这种缺点很少会引起问题。

另一个提示,一旦你达到了一定数量的传入参数(例如 4-5 个),就创建一个参数对象来将你的参数包装成一个可以传递的漂亮对象。


推荐阅读