“ th:text / each”不显示数据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()); // 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(已编辑)

<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>

Webpage's current state

解决方法

Thymeleaf只能通过getter访问数据。将吸气剂添加到LocationStats类。

要澄清:

用Thymeleaf书写时:

['Chihuahua','Japanese_spaniel','papillon','bloodhound']

Thymeleaf中的<td th:text="${locationStat.state}"></td> 可以使用您在类中定义的getter来获取状态。没有吸气剂=没有百里香叶表示。