java如何将输入转换为程序能够理解的方法
我目前正在做关于客户机和服务器主题的家庭作业:
我创建了一个名为VehileRequest.java
的类,它将从Client.java
中获取三个变量(年份、品牌、模型),并将它们传递给Server.java
,然后Server
将从VehicleRespone.java
中获取信息,并显示有关价格、里程和价格的信息
据我所知,程序无法识别传递到响应文件的请求
我无法将请求传递给响应,以便响应能够理解。请帮忙。多谢各位
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ObjectMapper;
public class VehicleResponse {
private VehicleRequest request;
private int milesOnVehicle;
private int price;
private int numberOfSeats;
private int numberOfDoors;
private String[] options;
@JsonIgnore
private static final ObjectMapper objectMapper = new ObjectMapper();
public static String toJSON(VehicleResponse vehicle) throws Exception {
return objectMapper.writeValueAsString(vehicle);
}
public static VehicleResponse fromJSON(String input) throws Exception{
return objectMapper.readValue(input, VehicleResponse.class);
}
protected VehicleResponse() {}
public VehicleResponse(VehicleRequest request, int milesOnVehicle,int price, int numberOfSeats, int numberOfDoors,String[] options) {
this.request=request;
this.milesOnVehicle=milesOnVehicle;
this.price=price;
this.numberOfSeats=numberOfSeats;
this.numberOfDoors=numberOfDoors;
this.options=options;
}
@Override
public String toString() {
return String.format(
"Vehicle request:[miles=%d, price=%d, number of seats=%d,number of doors=%d, option='%s']",
milesOnVehicle,price,numberOfSeats,numberOfDoors,options);
}
public VehicleRequest getRequest() {return request;}
public int getMilesOnVehicle(){return milesOnVehicle;};
public int getPrice(){return price;}
public int getNumberOfDoors() {return numberOfDoors;}
public int getNumberOfSeats() {return numberOfSeats;}
public String[] getOptions() {return options;}
public void setRequest(VehicleRequest request) {
this.request = request;
}
public void setMilesOnVehicle(int milesOnVehicle) {
this.milesOnVehicle = milesOnVehicle;
}
public void setPrice(int price) {
this.price = price;
}
public void setNumberOfSeats(int numberOfSeats) {
this.numberOfSeats = numberOfSeats;
}
public void setNumberOfDoors(int numberOfDoors) {
this.numberOfDoors = numberOfDoors;
}
public void setOptions(String[] options) {
this.options = options;
}
}
这是车辆请求文件
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.ObjectMapper;
public class VehicleRequest {
private int year;
private String make;
private String model;
@JsonIgnore
private static final ObjectMapper objectMapper = new ObjectMapper();
public static String toJSON(VehicleRequest vehicle) throws Exception {
return objectMapper.writeValueAsString(vehicle);
}
public static VehicleRequest fromJSON(String input) throws Exception{
return objectMapper.readValue(input, VehicleRequest.class);
}
protected VehicleRequest() {}
public VehicleRequest(int year, String make, String model) {
this.year = year;
this.make =make;
this.model=model;
}
@Override
public String toString() {
return String.format(
"Vehicle: [year=%d, make='%s', model='%s']",
year,make,model);
}
public int getYear() {
return year;
}
public String getMake(){return make;}
public String getModel(){return model;}
public void setYear(int year) {
this.year = year;
}
public void setMake(String make){
this.make=make;
}
public void setModel(String model){
this.model=model;
}
}
这是服务器
public class Server {
private ServerSocket serverSocket;
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public void start(int port) throws Exception {
serverSocket = new ServerSocket(port);
clientSocket = serverSocket.accept();
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
VehicleRequest request = VehicleRequest.fromJSON(inputLine);
VehicleResponse response = new VehicleResponse(request,10000,12000,5,4, null);
out.println(VehicleResponse.toJSON(response));
}
}
public void stop() throws IOException {
in.close();
out.close();
clientSocket.close();
serverSocket.close();
}
public static void main(String[] args) {
Server server = new Server();
try {
server.start(4444);
server.stop();
} catch(Exception e) {
e.printStackTrace();
}
}
}
这是客户
public class Client {
private Socket clientSocket;
private PrintWriter out;
private BufferedReader in;
public void startConnection(String ip, int port) throws IOException {
clientSocket = new Socket(ip, port);
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
}
public VehicleRequest sendRequest() throws Exception {
out.println(VehicleRequest.toJSON(new VehicleRequest(2008,"Honda","Civic")));
return VehicleRequest.fromJSON(in.readLine());
}
public void stopConnection() throws IOException {
in.close();
out.close();
clientSocket.close();
}
public static void main(String[] args) {
Client client = new Client();
try {
client.startConnection("127.0.0.1", 4444);
System.out.println(client.sendRequest().toString());
client.stopConnection();
} catch(Exception e) {
e.printStackTrace();
}
}
}
我得到的结果是
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "request" (class edu.sdccd.cisc191.template.VehicleRequest), not marked as ignorable (3 known properties: "model", "year", "make"])
at [Source: (String)"{"request":{"year":2008,"make":"Honda","model":"Civic"},"milesOnVehicle":10000,"price":12000,"numberOfSeats":5,"numberOfDoors":4,"options":null}"; line: 1, column: 13] (through reference chain: edu.sdccd.cisc191.template.VehicleRequest["request"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:855)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1212)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1604)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1582)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:299)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:156)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4482)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3434)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3402)
at edu.sdccd.cisc191.template.VehicleRequest.fromJSON(VehicleRequest.java:17)
at edu.sdccd.cisc191.template.Client.sendRequest(Client.java:32)
at edu.sdccd.cisc191.template.Client.main(Client.java:44)
}
# 1 楼答案
在
VehicleRequest.fromJSON(in.readLine());
行中,您试图解析输入的内容,它似乎是:但是,您希望它能够解析为
VehicleRequest
,这是不可能的,因为它只包含3个参数,而不是所有参数。您可以将其解析为VehicleResponse
,如下所示:或者将输入更改为可以解析为
VehicleRequest
的内容:如果我正确理解了您的代码,那么您正试图在
Client
和Server
之间进行通信。在这种情况下,您需要更改Client
代码:# 2 楼答案
尽管João Dias already solved your lapse by fixing the response-type,我还是想分享一些关于JSON转换的实用建议,特别是在实现web API facades时,比如您的
Client
/Server
类:send(request)
生成的代码可能会对您有吸引力
请求响应:
send
作为纯函数通常,客户机的职责是发送多个不同的请求。因此,请参数化
send
方法设计问题
Before:没有参数,只有静态硬编码请求。因此不可测试
注意:方法签名
...Request sendRequest()
可以像“output=produceInput()”一样读取。这种设计方法或函数的风格被称为pure function:它通常将一个输入转换为一个新的输出——它产生一些东西,比如响应设计问题: 这里无法提供任何输入。返回的产品或答案可能总是相同的。你不想问不同的问题或发送不同的请求吗。因此,预期的答案取决于给定的请求
改善
After:添加参数以使不同的
request
可测试。方法名称简化这可以在
main
或类似response = client.send(new VehicleRequest(2008,"Honda","Civic"))
的测试中调用对象表示:单独关注JSON转换
有一些基本的表示格式,如
String
,它们与每个类紧密耦合。在Java中,这个关注点继承自Object
类的方法toString()
以及一些包装类,如Integer.valueOf(String s)
然而,更复杂的表示,特别是REST或HTTP相关的表示,如JSON,
XML
,HTML
,以及二进制格式,通常由称为Separation of Concerns的设计原则处理。特别是在web应用程序(如简化的客户机-服务器体系结构)中,这会导致不同的层(最佳实践):Client
/Server
类和Jackson的ObjectMapper
处理JSON转换Vehicle..
类请参见这些单独的关注点,如维基百科Multi-tier Architecture或罗伯特·C·马丁的Clean Architecture中的分层说明
设计问题
外部依赖项Jackson被复制到DTO类的一部分,如
..Request
和..Response
。所以两者都依赖于Jackson和JSON格式以前:表示层的关注点混合到DTO类中,这些类可能会随着业务层的变化而变化。现在,它们需要根据每种格式进行更改,客户机也可以支持(强耦合和两个更改原因)
注意:您可以将这个横切(由许多类使用)关注点移动到客户机中。通过这种方式,您的(实体)类保持独立于格式/映射框架,并且客户端可以很容易地扩展以支持将来的其他格式(如XML)
改善
之后:在REST格式中是表示层的关注点。客户负责内容协商和转换
通过这种方式,您可以在main方法中通过如下配置创建一个支持XML的特殊客户机
Client xmlClient = new Client(new XmlMapper())
或按原样使用(JSON作为内容交换格式):Client client = new Client(new ObjectMapper())
对于你的CS课程和家庭作业来说,这可能太多太过工程化了
然而,在“真正的代码”中,正如在像
Spring
这样的专业web框架中所看到的,这是良好或最佳实践,有助于可扩展和可维护的软件,请参见SOLID