英文:
"th:text/each" not displaying data (Spring Boot/Thymeleaf)
问题
这个应用程序应该从一个网页上获取关于冠状病毒的信息,并将其输出到我们自己网页上的漂亮表格中。
所有的表头都在,但是列本身是空的。
尽管数据在控制器中正确传递,但Thymeleaf不会显示传递给它的数据。我会感激任何输入,谢谢。
LocationStats.java (已编辑)
package io.javabrains.coronavirustracker.models;
public class LocationStats
{
private String state;
private String country;
private int latestTotalCases;
public String getState() { return this.state; }
public void setState(String state) { this.state = state; }
public String getCountry() { return this.country; }
public void setCountry(String country) { this.country = country; }
public int getLatestTotalCases() { return this.latestTotalCases; }
public void setLatestTotalCases(int latestTotalCases) { this.latestTotalCases = latestTotalCases; }
@Override
public String toString()
{
return "LocationStats{" + "state='" + state + '\'' + ", country='" + country + '\'' + ", latestTotalCases=" + latestTotalCases + '}';
}
}
CoronaVirusDataService.java
package io.javabrains.coronavirustracker.services;
import io.javabrains.coronavirustracker.models.LocationStats;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVRecord;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.StringReader;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.List;
@Service
public class CoronaVirusDataService
{
private static String VIRUS_DATA_URL = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv";
private List<LocationStats> allStats = new ArrayList<>();
public List<LocationStats> getAllStats() { return allStats; }
@PostConstruct
@Scheduled(cron = "* * 1 * * *")
public void fetchVirusData() throws IOException, InterruptedException
{
List<LocationStats> newStats = new ArrayList<>();
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(VIRUS_DATA_URL)).build();
HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(httpResponse.body()); // 如预期地打印出所有数据
StringReader csvBodyReader = new StringReader(httpResponse.body());
Iterable<CSVRecord> records = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(csvBodyReader);
for(CSVRecord record : records)
{
LocationStats locationStat = new LocationStats();
locationStat.setCountry(record.get("Country/Region"));
locationStat.setState(record.get("Province/State"));
locationStat.setLatestTotalCases(Integer.parseInt(record.get(record.size() - 1)));
newStats.add(locationStat);
System.out.println(locationStat); // 如预期地打印出数据
}
this.allStats = newStats;
}
}
HomeController.java
package io.javabrains.coronavirustracker.controllers;
import io.javabrains.coronavirustracker.models.LocationStats;
import io.javabrains.coronavirustracker.services.CoronaVirusDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.List;
@Controller
public class HomeController
{
@Autowired
CoronaVirusDataService coronaVirusDataService;
@GetMapping("/")
public String home(Model model)
{
List<LocationStats> allStats = coronaVirusDataService.getAllStats();
int testNumber = 999; // 用于测试属性
model.addAttribute("locationStats", allStats); // 实际属性
model.addAttribute("testInt", testNumber); // 测试属性
return "home";
}
}
home.html (已编辑)
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Corona Virus Tracker Application</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h1 th:text="${testInt}">-1</h1>
<table>
<tr>
<th>State</th>
<th>Country</th>
<th>Total Cases</th>
</tr>
<tr th:each="locationStat : ${locationStats}">
<td th:text="${locationStat.state}"></td>
<td th:text="${locationStat.country}"></td>
<td th:text="${locationStat.latestTotalCases}">0</td>
</tr>
</table>
</body>
</html>
CoronavirusTrackerApplication.java
package io.javabrains.coronavirustracker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class CoronavirusTrackerApplication
{
public static void main(String[] args)
{
SpringApplication.run(CoronavirusTrackerApplication.class, args);
}
}
pom.xml
<!-- 这里省略了 POM 文件的内容 -->
英文:
This application is supposed to take info on the corona virus from a webpage and output it into a nice table on our own webpage.
All table headers are there but the columns themselves are empty.
Thymeleaf doesn't display data passed to it in model despite data being passed correctly in the controller. I would appreciate any input, thank you.
LocationStats.java (Edited)
package io.javabrains.coronavirustracker.models;
public class LocationStats
{
private String state;
private String country;
private int latestTotalCases;
public String getState() { return this.state; }
public void setState(String state) { this.state = state; }
public String getCountry() { return this.country; }
public void setCountry(String country) { this.country = country; }
public int getLatestTotalCases() { return this.latestTotalCases; }
public void setLatestTotalCases(int latestTotalCases) { this.latestTotalCases = latestTotalCases; }
@Override
public String toString()
{
return "LocationStats{" + "state='" + state + '\'' + ", country='" + country + '\'' + ", latestTotalCases=" + latestTotalCases + '}';
}
}
CoronaVirusDataService.java
package io.javabrains.coronavirustracker.services;
import io.javabrains.coronavirustracker.models.LocationStats;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVRecord;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.StringReader;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.List;
@Service
public class CoronaVirusDataService
{
private static String VIRUS_DATA_URL = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv";
private List<LocationStats> allStats = new ArrayList<>();
public List<LocationStats> getAllStats() { return allStats; }
@PostConstruct
@Scheduled(cron = "* * 1 * * *")
public void fetchVirusData() throws IOException, InterruptedException
{
List<LocationStats> newStats = new ArrayList<>();
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(VIRUS_DATA_URL)).build();
HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(httpResponse.body()); // Prints all data as expected
StringReader csvBodyReader = new StringReader(httpResponse.body());
Iterable<CSVRecord> records = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(csvBodyReader);
for(CSVRecord record : records)
{
LocationStats locationStat = new LocationStats();
locationStat.setCountry(record.get("Country/Region"));
locationStat.setState(record.get("Province/State"));
locationStat.setLatestTotalCases(Integer.parseInt(record.get(record.size() - 1)));
newStats.add(locationStat);
System.out.println(locationStat); // Prints data as expected
}
this.allStats = newStats;
}
}
HomeController.java
package io.javabrains.coronavirustracker.controllers;
import io.javabrains.coronavirustracker.models.LocationStats;
import io.javabrains.coronavirustracker.services.CoronaVirusDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
public class HomeController
{
@Autowired
CoronaVirusDataService coronaVirusDataService;
@GetMapping("/")
public String home(Model model)
{
List<LocationStats> allStats = coronaVirusDataService.getAllStats();
int testNumber = 999; // For test attribute
model.addAttribute("locationStats", allStats); // Actual attribute
model.addAttribute("testInt", testNumber); // Test attribute
return "home";
}
}
home.html (Edited)
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Corona Virus Tracker Application</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<h1 th:text="${testInt}">-1</h1>
<table>
<tr>
<th>State</th>
<th>Country</th>
<th>Total Cases</th>
</tr>
<tr th:each="locationStat : ${locationStats}">
<td th:text="${locationStat.state}"></td>
<td th:text="${locationStat.country}"></td>
<td th:text="${locationStat.latestTotalCases}">0</td>
</tr>
</table>
</body>
</html>
CoronavirusTrackerApplication.java
package io.javabrains.coronavirustracker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class CoronavirusTrackerApplication
{
public static void main(String[] args)
{
SpringApplication.run(CoronavirusTrackerApplication.class, args);
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>io.javabrains</groupId>
<artifactId>coronavirus-tracker</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>coronavirus-tracker</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>14</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>14</source>
<target>14</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
答案1
得分: 0
Thymeleaf只能通过getters访问数据。在你的LocationStats类中添加getters。
澄清一下:
当你在Thymeleaf中编写:
<td th:text="${locationStat.state}"></td>
Thymeleaf中的.state
实际上在底层使用了你的类中定义的getter来获取state。没有getter就没有Thymeleaf表示。
英文:
Thymeleaf can only access data through getters. Add getters to your LocationStats class.
To clarify:
when you write in Thymeleaf:
<td th:text="${locationStat.state}"></td>
the .state
in Thymeleaf is under the hood using the getter defined in your class to retrieve state. No getter = no thymeleaf representation.
专注分享java语言的经验与见解,让所有开发者获益!
评论