如何使用 SpringMVC 调用外部 API
How to call an external API with SpringMVC
我正在尝试创建一个 Spring MVC 网络应用程序,它通过从“https://api.weather.gov/points 调用外部 API 检查当前天气/{纬度},{经度}”。纬度和经度需要是您从 html 表单中获取的用户输入,将其传递到您的控制器,然后在您进行外部调用时使用该纬度和经度。
来自 api 调用的 json 包含网格点,这再次需要进行另一个外部 API 调用“https://api.weather.gov/gridpoints/{gridX },{gridY}/forecast”然后提取结果显示在前端。
我的 html 表格看起来像这样。(homepage.html)
<div class="call-logs-info" id="call-logs-id">
<div class="logs-container" id="logs-container-id">
<form id="my-form" action="/getLatitude" method="post">
<div class="date-content">
<h1>Weather Checker</h1>
<div class="columns">
<div class="col col-1">
<p>Latitude:</p>
<input type="text" class="inputbox" name="latitude" id="lat" />
</div>
<div class="col col-2">
<p>Longitude:</p>
<input type="text" class="inputbox" name="longitude" id="lon" />
</div>
</div>
<div class="columns">
<div class="col col-2">
<button class="btn btn-primary" type="submit">Submit</button>
</div>
</div>
</div>
</form>
</div>
</div>
我有一个模型 class 看起来像这样。(Paths.java)
@Data
public class Paths {
@SerializedName("latitude")
public double latitude;
@SerializedName("longitude")
public double longitude;
}
我的@Controller class 从我调用 @RestController class 调用外部 API 看起来像 this.I 已经从中提取了纬度和经度class 使用 @ModelAttribute 并尝试将其传递给 getGridPoints() 方法。 (APIFetchController.java)
@Log4j2
@Controller
public class APIFetcherController {
@Autowired
private ExternalApiFetchController externalApiFetchController;
@GetMapping("/home")
public String showHomePage(){
return "homepage";
}
@PostMapping("/getLatitude")
public void formSubmit(@ModelAttribute Paths paths){
Double latitude = paths.getLatitude();
Double longitude = paths.getLongitude();
log.info("Latitude: {}", latitude);
log.info("Longitude: {}", longitude);
externalApiFetchController.getGridPoints(latitude,longitude);
}
}
最后但同样重要的是,我尝试调用外部 API 的 @RestController class 看起来像这样。我已经尝试使用 restTempelate 来做到这一点。(ExternalApiFetchController.java)
@Log4j2
@RestController
public class ExternalApiFetchController {
@GetMapping("/grids")
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
public List<Object> getGridPoints(Double latitude, Double longitude) {
log.info("Lat :{}", latitude);
log.info("Long :{}", longitude);
String url = "https://api.weather.gov/points/"+latitude + "," +longitude;
log.info("URL: {}", url);
RestTemplate restTemplate = new RestTemplate();
Object[] grids = restTemplate.getForObject(url, Object[].class);
return Arrays.asList(grids);
}
出于某种原因,这会在尝试检查 Postman 时抛出一个错误
“无法从对象值(标记 JsonToken.START_OBJECT
)反序列化类型 [Ljava.lang.Object;
的值”和其他一些错误。“
当我检查日志时,由于某种原因,从 Postman 中点击 API 后的纬度和经度值变为空值。
我知道这可以通过单独的前端完成,但我手头的任务是通过 springMVC 完成,我不知道这是否是完成任务的正确方法。现在任何帮助都是如此宝贵。
天气 API return 一个 json 对象作为结果。您告诉 spring 将其转换为对象数组。该错误指出您不能这样做,因为它期望 json 响应是 json 个对象的数组。
替换
Object[] grids = restTemplate.getForObject(url, Object[].class);
和
Object grid = restTemplate.getForObject(url, Object.class);
(https://www.weather.gov/documentation/services-web-api#/default/point)
我正在尝试创建一个 Spring MVC 网络应用程序,它通过从“https://api.weather.gov/points 调用外部 API 检查当前天气/{纬度},{经度}”。纬度和经度需要是您从 html 表单中获取的用户输入,将其传递到您的控制器,然后在您进行外部调用时使用该纬度和经度。 来自 api 调用的 json 包含网格点,这再次需要进行另一个外部 API 调用“https://api.weather.gov/gridpoints/{gridX },{gridY}/forecast”然后提取结果显示在前端。
我的 html 表格看起来像这样。(homepage.html)
<div class="call-logs-info" id="call-logs-id">
<div class="logs-container" id="logs-container-id">
<form id="my-form" action="/getLatitude" method="post">
<div class="date-content">
<h1>Weather Checker</h1>
<div class="columns">
<div class="col col-1">
<p>Latitude:</p>
<input type="text" class="inputbox" name="latitude" id="lat" />
</div>
<div class="col col-2">
<p>Longitude:</p>
<input type="text" class="inputbox" name="longitude" id="lon" />
</div>
</div>
<div class="columns">
<div class="col col-2">
<button class="btn btn-primary" type="submit">Submit</button>
</div>
</div>
</div>
</form>
</div>
</div>
我有一个模型 class 看起来像这样。(Paths.java)
@Data
public class Paths {
@SerializedName("latitude")
public double latitude;
@SerializedName("longitude")
public double longitude;
}
我的@Controller class 从我调用 @RestController class 调用外部 API 看起来像 this.I 已经从中提取了纬度和经度class 使用 @ModelAttribute 并尝试将其传递给 getGridPoints() 方法。 (APIFetchController.java)
@Log4j2
@Controller
public class APIFetcherController {
@Autowired
private ExternalApiFetchController externalApiFetchController;
@GetMapping("/home")
public String showHomePage(){
return "homepage";
}
@PostMapping("/getLatitude")
public void formSubmit(@ModelAttribute Paths paths){
Double latitude = paths.getLatitude();
Double longitude = paths.getLongitude();
log.info("Latitude: {}", latitude);
log.info("Longitude: {}", longitude);
externalApiFetchController.getGridPoints(latitude,longitude);
}
}
最后但同样重要的是,我尝试调用外部 API 的 @RestController class 看起来像这样。我已经尝试使用 restTempelate 来做到这一点。(ExternalApiFetchController.java)
@Log4j2
@RestController
public class ExternalApiFetchController {
@GetMapping("/grids")
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
public List<Object> getGridPoints(Double latitude, Double longitude) {
log.info("Lat :{}", latitude);
log.info("Long :{}", longitude);
String url = "https://api.weather.gov/points/"+latitude + "," +longitude;
log.info("URL: {}", url);
RestTemplate restTemplate = new RestTemplate();
Object[] grids = restTemplate.getForObject(url, Object[].class);
return Arrays.asList(grids);
}
出于某种原因,这会在尝试检查 Postman 时抛出一个错误
“无法从对象值(标记 JsonToken.START_OBJECT
)反序列化类型 [Ljava.lang.Object;
的值”和其他一些错误。“
当我检查日志时,由于某种原因,从 Postman 中点击 API 后的纬度和经度值变为空值。
我知道这可以通过单独的前端完成,但我手头的任务是通过 springMVC 完成,我不知道这是否是完成任务的正确方法。现在任何帮助都是如此宝贵。
天气 API return 一个 json 对象作为结果。您告诉 spring 将其转换为对象数组。该错误指出您不能这样做,因为它期望 json 响应是 json 个对象的数组。
替换
Object[] grids = restTemplate.getForObject(url, Object[].class);
和
Object grid = restTemplate.getForObject(url, Object.class);
(https://www.weather.gov/documentation/services-web-api#/default/point)