Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何避免if-else树代码?_Java_Spring_Rest - Fatal编程技术网

Java 如何避免if-else树代码?

Java 如何避免if-else树代码?,java,spring,rest,Java,Spring,Rest,我有一个rest控制器,它包含一个根据“title”和“author”参数查找书籍的方法 你能给我一些提示如何摆脱if-else结构吗? 现在并不复杂,但将来参数的数量可能会增加,这将导致混乱 @GetMapping public ResponseEntity<List<Book>> searchBooksByTitleAndAuthor( @RequestParam(value = "title", required = fals

我有一个rest控制器,它包含一个根据“title”和“author”参数查找书籍的方法

你能给我一些提示如何摆脱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);
        }

    }
@GetMapping
公共响应Titleandautor提供的书目搜索(
@RequestParam(value=“title”,required=false)字符串标题,
@RequestParam(value=“author”,required=false)字符串(author){
if(title==null&&author==null){
log.info(“空请求”);
返回新的响应属性(HttpStatus.NO_内容);
}else if(title!=null&&author==null){
log.info(“按标题检索图书”);
List books=bookService.getBooksByTitle(title);
if(books.isEmpty()){
log.info(“没有此标题的书籍”);
返回新的响应属性(HttpStatus.NO_内容);
}
返回新的响应属性(books,HttpStatus.OK);
}else if(author!=null&&title==null){
List books=bookService.getBooksByTitle(title);
if(books.isEmpty()){
log.info(“没有此标题的书籍”);
返回新的响应属性(HttpStatus.NO_内容);
}
返回新的响应属性(books,HttpStatus.OK);
}否则{
List books=bookService.getbooksbytitleandautor(标题、作者);
if(books.isEmpty()){
log.info(“没有与此标题和作者匹配的书籍”);
返回新的响应属性(HttpStatus.NO_内容);
}
返回新的响应属性(books,HttpStatus.OK);
}
}

我只想写以下内容:

@GetMapping
public List<Book> searchBooksByTitleAndAuthor(@RequestParam String title, @RequestParam String author) {
    return bookService.getBooksByTitleAndAuthor(title, author);
}
@GetMapping
公共列表SearchBooksByTitleandautor(@RequestParam字符串标题,@RequestParam字符串作者){
returnbookservice.getbooksbytitleandautor(标题、作者);
}
我将把
响应属性
创建和
HttpStatus
管理留给Spring。至于
null
或空值管理,我将把它留给后面的服务或数据库查询

此外,您在RequestParam注释中编写的参数是默认值,可以简化


最后,为什么要记录所有查询?重点是什么?如果您的目标是生产,那么您的信息日志将被大量的查询垃圾发送,而且业务信息无论如何都不属于技术日志。

没有很好的解决方案。如果我是你,我会将其重构为:

@GetMapping
public ResponseEntity<List<Book>> searchBooksByTitleAndAuthor(
        @RequestParam(value = "title", required = false) String title,
        @RequestParam(value = "author", required = false) String author) {
    List<Book> books;
    if (StringUtils.isBlank(title) && StringUtils.isBlank(author)) {
        log.info("Empty request");
        return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
    } else if (!StringUtils.isBlank(title) && !StringUtils.isBlank(author)) {
        books = bookService.getBooksByTitleAndAuthor(title, author);
    } else if (StringUtils.isBlank(author)) {
        books = bookService.getBooksByTitle(title);
    } else {
        books = bookService.getBooksByAuthor(author);
    }
    if (books.isEmpty()) {
        log.info("No books found with title = " + title + " and author = " + author);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }
    return new ResponseEntity<>(books, HttpStatus.OK);
}
@GetMapping
公共响应Titleandautor提供的书目搜索(
@RequestParam(value=“title”,required=false)字符串标题,
@RequestParam(value=“author”,required=false)字符串(author){
列出书籍;
if(StringUtils.isBlank(标题)和&StringUtils.isBlank(作者)){
log.info(“空请求”);
返回新的响应属性(HttpStatus.BAD_请求);
}如果(!StringUtils.isBlank(标题)和&!StringUtils.isBlank(作者)){
books=bookService.getbooksbytitleandautor(标题、作者);
}else if(StringUtils.isBlank(author)){
books=bookService.getBooksByTitle(title);
}否则{
books=bookService.getBooksByAuthor(author);
}
if(books.isEmpty()){
log.info(“未找到标题为=“+title+”和作者为=“+author”的书籍);
返回新的响应属性(HttpStatus.NO_内容);
}
返回新的响应属性(books,HttpStatus.OK);
}
使用此解决方案,您将处理一次响应


一个提示


当没有发送参数时,返回一个错误的请求,说明此服务至少需要一个参数。

由于您的计划是最终支持更多参数,您最好的选择可能是查看。这允许您动态构造查询。它不会避免使用
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();
Criteria=session.createCriteria(Book.class);
if(author!=null&&!author.isEmpty()){
标准.添加(限制.eq(“作者”,作者));
}
if(title!=null&&!title.isEmpty()){
标准。添加(限制。等式(“标题”,标题));
}
标准.addOrder(Order.asc(“publishDate”);
返回(列表)条件。列表();
这有一些显著的好处:

  • 要支持新参数,只需将参数添加到控制器,然后将参数向下传递到存储库,并将参数添加到此块

  • 您最终可以配置您的排序,例如:

    ?排序=标题:asc&author=Bobby%20表格

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


    另一个技巧是,一旦你输入了一定数量的参数(例如4-5个),创建一个简单的、好的对象来封装你的参数,这样就可以传递了。

    一点嵌套可能会有所帮助。 这将最大限度地减少重复测试。 一些代码:

    if (StringUtils.isNotBlank(blam) || StringUtils.isNotBlank(kapow))
    {
        if (StringUtils.isBlank(blam))
        {
            // kapow is not blank.
        }
        else if (StringUtils.isBlank(kapow))
        {
            // blam is not blank.
        }
        else
        {
            // neither kapow nor blam is blank.
        }
    }
    else
    {
       // both empty.  error.
    }
    
    我喜欢布赖恩的答案, 但我永远不会推荐使用Hibernate。 MyBatis还支持条件where子句。

    我建议。
    它的灵感来自领域驱动的设计/模型,实现依赖于JPA标准,允许灵活地构建查询

    下面是一个示例(未经测试,但您应该了解总体思路)

    BookSpec
    public class BookSpecifications {
    
        private BookSpecifications(){
        }
    
        public static Specification<Book> withAuthor(String author) {
            return new Specification<Book>() {
                public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                    return cb.equal(root.get("author"), author);
                }
            };
        }
    
        public static Specification<Book> withTitle(String title) {
            return new Specification<Book>() {
                public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                    return cb.equal(root.get("title"), title);
                }
            };
        }
    }
    
    public class BookController {
        @GetMapping
        public ResponseEntity<List<Book>> searchBooksByTitleAndAuthor(
                @RequestParam(value = "title", required = false) String title,
                @RequestParam(value = "author", required = false) String author) {
    
    
            List<Book> books = bookService.findAll(title, author);
    
            if (books.isEmpty()) {
                log.info("No books with this specification ");
                return new ResponseEntity<>(HttpStatus.NO_CONTENT);
            }
            return new ResponseEntity<>(books, HttpStatus.OK);
    
        }
    }
    
    public class BookService {
    
        private BookRepository bookRepository;
    
        public BookService(BookRepository bookRepository){
             this.bookRepository = bookRepository;
        }
    
        public List<Book> findAll(String title, String author) {
    
           if (Stream.of(title, author)
                     .filter(s-> s == null || s.equals(""))
                     .count() == 0) {
                return new ArrayList<>();
            }
    
            Specification<Book> specification = createSpecification(specification, title, () -> BookSpecifications.withTitle(title));
            specification = createSpecification(specification, author, () -> BookSpecifications.withAuthor(author));
            List<Book> books = bookRepository.findAll(specification);
            return books;
    
        }
    
        Specification<Book> createSpecification(Specification<Book> currentSpecification, String arg, Callable<Specification<Book>> callable) {
    
            // no valued parameter so we return
            if (arg == null) {
                return currentSpecification;
            }
    
            try {
    
               // Specification instance already created : reuse it
                if (currentSpecification != null) { 
                    return currentSpecification.and(callable.call());
                }
    
               // Specification instance not created yes : create a new one
                return callable.call();
            } catch (Exception e) {
                // handle the exception... if any
            }
    
        }
    }
    
    // existing
    Specification<Book> specification = createSpecification(specification, title, () -> BookSpecifications.withTitle(title));
    specification = createSpecification(specification, author, () -> BookSpecifications.withAuthor(author));
    // change below !
    specification = createSpecification(specification, anotherColumn, () -> BookSpecifications.withAnotherColumn(anotherColumn));
    
    List<T> findAll(@Nullable Specification<T> spec);
    
    @Repository
    public interface BookRepository extends JpaRepository<Book, Long> , JpaSpecificationExecutor<Book>  {    
    }
    
    public class BookSpecifications {
    
        private BookSpecifications(){
        }
    
        public static Specification<Book> withAttribute(String name, T value) {
            return new Specification<Book>() {
                public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                    return cb.equal(root.get(name), value);
                }
            };
        }
    
    }
    
    private static long toKey(Object ... args) {
        long key = 0L;
        for(int i = 0; i < args.length; i++) {
            if(args[i] != null) {
                key |= (1L << i);
            }
        }
        return key;
    }
    
    private static interface BookFinder {
        ResponseEntity<List<Book>> search(String title, String author);
    }
    
    private static Map<Long, BookFinder> _keyToFinderMap = new HashMap<>();
    
    static {
        _keyToFinderMap.put(toKey(null, null), new BookFinder() {
            public ResponseEntity<List<Book>> search(String title, String author) {
                log.info("Empty request");
                return new ResponseEntity<>(HttpStatus.NO_CONTENT);
            }
        });
        _keyToFinderMap.put(toKey("", null), new BookFinder() {
            public ResponseEntity<List<Book>> search(String title, String author) {
                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);
            }
        });
        // Other cases
    };
    
    @GetMapping
    public ResponseEntity<List<Book>> searchBooksByTitleAndAuthor(
            @RequestParam(value = "title", required = false) String title,
            @RequestParam(value = "author", required = false) String author) {
        return _keyToFinderMap.get(toKey(title, author)).search(title, author);
    }