【问题标题】:Restlet accepts JSON input from client and respond with POSTRestlet 接受来自客户端的 JSON 输入并以 POST 响应
【发布时间】:2016-05-03 03:34:03
【问题描述】:

我正在编写一个程序,它接受来自客户端的以下格式的 JSON 输入:

{
    "campaignID": 1,
    "clientID": 1,
    "pmapID": 1,
    "ward": "1-Bedded (Private)",
    "age": 20,
    "attr1": "EXA1(A)",
    "attr2": "EO",
    "attr3": "11/02/2012",
    "attr4": "SIN",
    "attr5": "N",
    "attr6": "Y"
}

我想读取 JSON 输入,将所有属性保存到局部变量(String、int、...)中,最后以 POST("JSON") 响应,它将返回单个浮点/双精度值(例如 {"PMC": 30.12} )。

public class RestletApplication extends Application
{
    @Override
    public synchronized Restlet createInboundRoot()
    {
        Router router = new Router(getContext());
        router.attach("/pmc/calculate", PMCResource.class);
        return router;
    }
}

到目前为止,我已经编写了该函数,但不知道如何读取 JSON 输入:

 public class PMCResource extends ServerResource
    {   
        @Post("JSON")
        public Representation post(Representation entity) throws ResourceException {
            try {
                if (entity.getMediaType().isCompatible(MediaType.APPLICATION_JSON))
                {
                    // Read JSON file and parse onto local variables

                    // Do processing & return a float value

                }
            } catch (Exception e) {
                getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
            }
        }
    }

2016 年 5 月 5 日 - 编辑了资源类

// Imports

public class PMCResource extends ServerResource
{
    static Logger LOGGER = LoggerFactory.getLogger(PMCResource.class);

    @Override
    @Post("JSON")
    public Representation post(Representation entity) throws ResourceException
    {
        PMCMatrixDAO matrix = new PMCMatrixDAOImpl();
        JsonObjectBuilder response = Json.createObjectBuilder();

        try
        {
            if (entity.getMediaType().isCompatible(MediaType.APPLICATION_JSON))
            {
                InputStream is = new FileInputStream(getClass().getResource("/input.json").getFile());

                try (JsonReader reader = Json.createReader(is)) {
                    JsonObject obj = reader.readObject();
                    double result = matrix.calculatePMC(obj);
                    response.add("PMC", result);
                }
            }

        } catch (Exception e) {
            getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
        }

        return new StringRepresentation(response.build().toString());
    }
}

实现类

public class PMCMatrixDAOImpl implements PMCMatrixDAO
{       
    public double calculatePMC(JsonObject obj) 
    {   
        int campaignID = obj.getInt("campaignID");
        int clientID = obj.getInt("clientID");
        int pmapID = obj.getInt("pmapID");
        String ward = obj.getString("ward");
        int age = obj.getInt("age");
        String attr1 = obj.getString("attr1");
        String attr2 = obj.getString("attr2");
        String attr3 = obj.getString("attr3");
        String attr4 = obj.getString("attr4");
        String attr5 = obj.getString("attr5");
        String attr6 = obj.getString("attr6");

        // SQL processing
        double dPMC = sqlQueryCall(...);

        return dPMC;
    }
}

【问题讨论】:

  • 您的 JSON 数据是否包含在您的 Representation 实体中?
  • 对不起@aribeiro,我不太明白你的问题。你能用外行的话解释一下,让这个新手可以理解吗?
  • 好吧,您只是想读取您的 JSON 文件,您将评论放在哪里?或者您想知道如何执行包含上述内容的 POST 请求?
  • @aribeiro 将 JSON 文件解析为局部变量后,我将执行 SQL 查询以从数据库中检索值(十进制)。然后我必须将此值作为 JSON 发布回客户端,以便他们可以在门户上显示它。

标签: json rest maven jakarta-ee restlet


【解决方案1】:

为了解析您的 JSON 文件,并且由于您使用的是 Maven,我假设您的类路径中有它,您可以使用 FileInputStreamFileReader 来完成。因此,假设您的 JSON 文件名为 input.json 并且它位于 src/main/resources 文件夹的根目录中,您可以通过以下方式加载它:

  • 使用 FileInputStream:

    InputStream is = new FileInputStream(getClass().getResource("/input.json").getFile());
    
    try (JsonReader reader = Json.createReader(is)) {
        // file processing is done here
    }
    
  • 使用 FileReader:

    FileReader fr = new FileReader(getClass().getResource("/input.json").getFile());
    
    try (JsonReader reader = Json.createReader(fr)) {
        // file processing is done here
    }
    

好的,现在我们已经创建了 JsonReader,让我们检索 JSON 文件的内容:

InputStream is = new FileInputStream(getClass().getResource("/input.json").getFile());

try (JsonReader reader = Json.createReader(is)) {
    JsonObject obj = reader.readObject();

    // retrieve JSON contents
    int campaingID = obj.getInt("campaignID");
    int clientID = obj.getInt("clientID");
    int pmapID = obj.getInt("pmapID");
    String ward = obj.getString("ward");
    int age = obj.getInt("age");
    String attr1 = obj.getString("attr1");
    String attr2 = obj.getString("attr2");
    String attr3 = obj.getString("attr3");
    String attr4 = obj.getString("attr4");
    String attr5 = obj.getString("attr5");
    String attr6 = obj.getString("attr6");
}

作为在您的方法中使用多个变量的替代方法,您可以创建一个简单的 POJO,将这些变量作为属性,然后使用 Jackson populate it

public class MyPojo {

    private int campaingID;
    private int clientID;
    private int pmapID;
    private String ward;
    private int age;
    private String attr1;
    private String attr2;
    private String attr3;
    private String attr4;
    private String attr5;
    private String attr6;

    // getters & setters
}

最后,为了将响应发送回您的客户,您可以这样做:

JsonObject response = Json.createObjectBuilder().add("PMC", 30.12).build();

return new StringRepresentation(response.toString());

所以,整个解决方案可能如下所示:

@Override
@Post("JSON")
public Representation post(Representation entity) throws ResourceException {
    JsonObjectBuilder response = Json.createObjectBuilder();

    try {
        if (entity.getMediaType().isCompatible(MediaType.APPLICATION_JSON)) {
            InputStream is = new FileInputStream(getClass().getResource("/input.json").getFile());

            try (JsonReader reader = Json.createReader(is)) {
                JsonObject obj = reader.readObject();

                // retrieve JSON contents
                int campaingID = obj.getInt("campaignID");
                int clientID = obj.getInt("clientID");
                int pmapID = obj.getInt("pmapID");
                String ward = obj.getString("ward");
                int age = obj.getInt("age");
                String attr1 = obj.getString("attr1");
                String attr2 = obj.getString("attr2");
                String attr3 = obj.getString("attr3");
                String attr4 = obj.getString("attr4");
                String attr5 = obj.getString("attr5");
                String attr6 = obj.getString("attr6");
            }

            // Do processing & execute your SQL query call here
            double result = sqlQueryCall(...);

            response.add("PMC", result);
        }
    } catch (Exception e) {
        getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
    }

    return new StringRepresentation(response.build().toString());
}

附带说明,JsonReader 类属于 Java EE API,出于编译目的,它是可以的。尽管出于运行目的,一个requires 在一个人的Maven 项目中声明了一个JSON-API 实现依赖项。例如:

<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.json</artifactId>
    <version>1.0.4</version>
</dependency>

以下是通过客户端与 REST Web 服务通信的方式:

  1. 创建一个包含要发送的信息的简单 POJO 对象,如上所述 (MyPojo)。

  2. 您的 REST 服务将如下所示:

    public class PMCResource extends ServerResource {
    
        static Logger LOGGER = Logger.getLogger(RestletMain.class.getName());
    
        @Post("JSON")
        public Representation post(MyPojo entity) throws ResourceException {
            PMCMatrixDAO matrix = new PMCMatrixDAOImpl();
            JsonObjectBuilder response = Json.createObjectBuilder();
    
            try {
                double result = matrix.calculatePMC(entity);
                response.add("PMC", result);
            } catch (Exception e) {
                getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
            }
    
            return new StringRepresentation(response.build().toString());
        }
    }
    
  3. 修改您的 PMCMatrixDAOImpl 以处理您的 POJO:

    public double calculatePMC(MyPojo pojo) {
        (...)
    }
    
  4. 创建一个允许您测试 REST 服务的客户端:

    public class PMCResourceMain {
    
        public static void main(String[] args) {
            // take into account the context-root, if exists, and path to your REST service
            ClientResource resource = new ClientResource("http://<host>:<port>");
    
            MyPojo myPojo = new MyPojo();
            myPojo.setCampaingID(1);
            myPojo.setClientID(1);
            myPojo.setPmapID(1);
            myPojo.setWard("1-Bedded (Private)");
            myPojo.setAge(20);
            myPojo.setAttr1("EXA1(A)");
            myPojo.setAttr2("EO");
            myPojo.setAttr3("11/02/2012");
            myPojo.setAttr4("SIN");
            myPojo.setAttr5("N");
            myPojo.setAttr6("Y");
    
            try {
                resource.post(myPojo, MediaType.APPLICATION_JSON).write(System.out);
            } catch (ResourceException | IOException e) {
                e.printStackTrace();
            }
        }
    }
    

完整的 Restlet 文档可以在 here 找到。

【讨论】:

  • 感谢示例程序,非常感谢。我决定将整个 JSON 对象传递给 Implementation 类以检索内容并进行所有处理。由于客户端是发送 JSON 文件的人,这是否意味着我必须指示他们保存 JSON 文件的位置,或者我只需要创建一个空的 JSON 文件并指示他们在需要时写入它?最后,你能告诉我如何编写一个简单的客户端类来测试吗?
  • 我不确定您的意思是什么决定将整个 JSON 对象传递给Implementation,我也不明白客户端是一个发送 JSON 文件。您是否可以用您打算实现的目标来更新您的原始帖子 (OP)? :)
  • 对不起,如果我让你感到困惑,可能我没有使用正确的语法来解释它。我已经编辑了我的 OP 以反映这一点。基本上我试图避免对表示类进行任何处理。
  • 我正在做一个协作项目。软件供应商负责设计会员门户(会员可以在这里注册详细信息),而我负责计算部分。然后,供应商会将计算所需的所有相关信息作为 JSON 文件(通过 Web 服务)传递。我会拿起 JSON,读取它,进行处理,最后返回一个值,以便它可以显示在门户上。
  • 我已经完成了其他只需要最少输入的更简单的 web 服务。我构造了诸如http://localhost:9090/fwd-PMAP/pmap/client/1之类的URI,然后我使用getRequestAttributes()直接从URI中检索值,进行处理并返回值。但是,对于这个特定的 Web 服务,由于需要大量信息,因此不建议使用相同的方法(URI 将是真正的 looonnngggg)。然后供应商建议使用 JSON,这就是我迷路的时候。 :p
【解决方案2】:

为了那些与我处于相同情况的人的利益,这是我的解决方案:

资源类

@Override
@Post("JSON")
public Representation post(Representation entity) throws ResourceException
{
    PMCMatrixDAO matrix = new PMCMatrixDAOImpl();
    JsonObjectBuilder response = Json.createObjectBuilder();

    try {
        String json = entity.getText(); // Get JSON input from client
        Map<String, Object> map = JsonUtils.toMap(json); // Convert input into Map
        double result = matrix.calculatePMC(map);
        response.add("PMC", result);
    } catch (IOException e) {
        LOGGER.error(this.getClass() + " - IOException - " + e);
        getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
    }

    return new StringRepresentation(response.build().toString());       
}

JSON 转换实用程序类

public class JsonUtils {

    private static final Logger LOG = LoggerFactory.getLogger(JsonUtils.class);

    private JsonUtils() {
    }

    public static String toJson(Object object) {
        String jsonString = null;

        ObjectMapper mapper = new ObjectMapper();
        try {
            jsonString = mapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            LOG.error(e.getMessage(), e);
        }

        return jsonString;
    }

    public static Map<String, Object> toMap(String jsonString) {
        Map<String, Object> map = new ConcurrentHashMap<>();

        ObjectMapper mapper = new ObjectMapper();

        try {
            map = mapper.readValue(jsonString, new TypeReference<Map<String, Object>>() {
            });
        } catch (IOException e) {
            LOG.error(e.getMessage(), e);
        }

        return map;
    }
}

以及处理所有处理的实现类

public class PMCMatrixDAOImpl implements PMCMatrixDAO
{       
    public double calculatePMC(Map<String, Object> map) 
    {   
        int campaignID  = (int) map.get("campaignID");
        int clientID    = (int) map.get("clientID");
        int pmapID      = (int) map.get("pmapID");
        String ward     = (String) map.get("ward");
        int age         = (int) map.get("age");
        String attr1 = (String) map.get("attr1");
        String attr2 = (String) map.get("attr2");
        String attr3 = (String) map.get("attr3");
        String attr4 = (String) map.get("attr4");
        String attr5 = (String) map.get("attr5");
        String attr6 = (String) map.get("attr6");

        // SQL processing
        double dPMC = sqlQueryCall(...);

        return dPMC;
    }
}

【讨论】:

  • 您的解决方案似乎没问题! :) 但是,考虑到您所遵循的方法,我认为您可以进一步改进它。尝试删除 JSON 转换实用程序类和 Representation 参数,并强制使用 POJO。它会让你的代码更简洁,更不容易出错。
猜你喜欢
  • 2012-12-16
  • 2015-09-07
  • 2014-03-02
  • 1970-01-01
  • 1970-01-01
  • 2016-10-20
  • 1970-01-01
  • 2016-08-16
  • 1970-01-01
相关资源
最近更新 更多