openxava / 文档 / 第二十二章:在验证中调用 REST 服务

课程:1. 入门教学 | 2. 基本域模型(上) | 3. 基本域模型(下) | 4. 优化用户界面 | 5. 敏捷开发 | 6. 映射式超类继承 | 7. 实体继承 | 8. 视图继承(View) | 9. Java 属性 | 10. 计算属性 | 11. 用在集合的 @DefaultValueCalculator | 12. @Calculation 和集合总计 | 13. 从外部文件的 @DefaultValueCalculator | 14. 手动更改 schema | 15. 多用户时默认值的计算 | 16. 同步持久属性和计算属性 | 17. 从数据库中的逻辑 | 18. 使用 @EntityValidator 进行验证 | 19. 验证替代方案 | 20. 删除时验证 21. 自定义 Bean Validation 注解 | 22. 在验证中调用 REST 服务 | 23. 注解中的属性 | 24. 改进标准行为 | 25. 行为与业务逻辑 | 26. 参照与集合 | A. Architecture & philosophy | B. Java Persistence API | C. Annotations | D. Automated testing

目录

第二十二章:在验证中调用 REST 服务
调用 REST web service 來验证 ISBN
总结
在上一章,您看到了如何创建自定义的 Bean Validation 注解。在本章,您将了解如何调用 REST web service 来验证 ISBN。

调用 REST web service 來验证 ISBN

尽管大多验证器都有简单的逻辑,但如果需要,您可以创建具有复杂逻辑的验证器。例如,对于我们的 ISBN,我们不仅要验证格式是否正确,还要检查具有该 ISBN 的书是否确实存在。其中一种方法是使用 web services。
如您所知,web services 是位于伺服器中的一种功能,可以由程序调用。传统开发 web services 的方法是是通过 WS-* 的标准,如 SOAP、UDDI、等。不过当今开发服务最简单的方法是 REST。 REST 的基本思想是使用互联网已经存在的“工作方式”进行程序间的数据交换。要调用 REST 服务可使用常规的网址从网路服务器中获取资源;该资源通常是 XML、HTML、JSON 或任何其它格式的数据。换句话说,这些程序使用互联网的样子就像用户使用浏览器一样。
有很多带有 SOAP 和 REST web service 的网站以供我们查阅书籍的 ISBN,我们将使用 openlibrary.org,它提供免费查阅其书籍目录的 REST API。要试一试 Open Library API,请打开浏览器并到以下连结:
https://openlibrary.org/api/books?jscmd=data&format=json&bibkeys=ISBN:9780932633439
最后一个参数是书籍的 ISBN,从中您将获得包含该书籍数据的 JSON,如下:

validation040.png


JSON 只是具有键/值的数据,并使用 {} 和 [] 进行嵌套和重复。如果您尝试获取不存在的书籍的数据时,例如:
https://openlibrary.org/api/books?jscmd=data&format=json&bibkeys=ISBN:9791034369997
您会得到一个空的 JSON,像这样:

validation050.png


也就是说,一个空的 JSON,只是 {}。
要调用此 web service,我们将使用 JAX-RS。 JAX-RS 是调用 REST Web 服务的 Java 标准。 OpenXava 支持使用 JAX-RS 调用 web service,因此您无需添加任何库。
让我们修改 ISBNValidator 以使用此 REST 服务:
package com.yourcompany.invoicing.validators; 

import javax.validation.*;
import javax.ws.rs.client.*; // 使用 JAX-RS
import com.yourcompany.invoicing.annotations.*;
import org.apache.commons.logging.*; // 使用日志
import org.openxava.util.*;
 
public class ISBNValidator
    implements ConstraintValidator<ISBN, Object> {
	
    private static Log log = LogFactory.getLog(ISBNValidator.class); // 将日志实例化
 
    private static org.apache.commons.validator.routines.ISBNValidator
        validator = 
            new org.apache.commons.validator.routines.ISBNValidator();
 
    public void initialize(ISBN isbn) {
 
    }
 
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        if (Is.empty(value)) return true;
        if (!validator.isValid(value.toString())) return false;
        return isbnExists(value); // 在这里调用 REST
    }
    
    private boolean isbnExists(Object isbn) {
        try {
            // 这里我们使用 JAX-RS 调用 REST 服务
            String response = ClientBuilder.newClient()
                .target("http://openlibrary.org/") // 站点
                .path("/api/books") // 服务的路径
                .queryParam("jscmd", "data") // 参数
                .queryParam("format", "json")
                .queryParam("bibkeys", "ISBN:" + isbn) // ISBN 是一个参数
                .request()
                .get(String.class); // 带有 JSON 的字符串
            return !response.equals("{}"); // JSON 是空的吗?对于我们的情况来说已经足够了。
        }
        catch (Exception ex) {
            log.warn("无法连线至 openlibrary.org " +
                "验证 ISBN. 验证失败", ex);
            return false; // 如果有错误,验证则失败
        }
    }
    
}
我们只需打开附有 ISBN 作为请求参数的网址。如果生成的 JSON 是空的,也就是说 {},搜索将失败,相反的话我们则找到这本书。对于这种情况,将 JSON 作为字符串进行简单比较是最简单的方法,不过 JAX-RS 可以将 JSON 解析为您自己的类(例如 Book)的 Java 对象,并填充相应的属性,只需使用 .get (Book.class) 而不是 .get(String.class) 这是在调用的最后一行。
现在只要运行应用程序,您会发现如果输入不存在的 ISBN,验证将失败。

总结

恭喜!您已经学到如何调用 REST web service 来验证 ISBN。在下一章,您将了解到如何在注解中添加属性。
 
下载本课源代码

对这节课有什么问题吗? 前往论譠 一切都顺利吗? 前往第二十三章