在本教程中,我们从WEB-INF目录中的 CSV 文件读取数据。 我们使用 servlet,JSP 文件和 JSTL 库。 Web 应用已部署在 Jetty 上。 OpenCSV 库用于读取 CSV 数据。
CSV
CSV(逗号分隔值)格式是在电子表格和数据库中使用的非常流行的导入和导出格式。
在以下 Web 应用中,我们从 WAR 文件中的 CSV 文件读取数据,并将数据显示在网页中。 标记人口超过一亿的国家。
pom.xmlsrc├───main│ ├───java│ │ └───com│ │ └───zetcode│ │ ├───bean│ │ │ Country.java│ │ ├───service│ │ │ CountryService.java│ │ └───web│ │ ReadCountries.java│ ├───resources│ │ countries.csv│ └───webapp│ index.jsp│ listCountries.jsp│ showError.jsp└───test└───java
这是项目结构。
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.0http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.zetcode</groupId><artifactId>readcsvfromwar</artifactId><version>1.0-SNAPSHOT</version><packaging>war</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>12</maven.compiler.source><maven.compiler.target>12</maven.compiler.target></properties><dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></dependency><dependency><groupId>com.opencsv</groupId><artifactId>opencsv</artifactId><version>4.6</version></dependency><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-war-plugin</artifactId><version>3.2.2</version></plugin><plugin><groupId>org.eclipse.jetty</groupId><artifactId>jetty-maven-plugin</artifactId><version>9.4.14.v20181114</version></plugin></plugins></build></project>
该项目使用以下依赖项:avax.servlet-api,opencsv和jstl。
resources/countries.csv
Name, PopulationSlovakia,5429000Norway,5271000Croatia,4225000Russia,143439000Mexico,122273000Vietnam,95261000Sweden,9967000Iceland,337600Israel,8622000Hungary,9830000Germany,82175700Japan,126650000
这是countries.csv文件。 它位于src/main/resources目录中。 生成应用后,文件将复制到 WAR 的WEB-INF/classes目录。
com/zetcode/bean/Country.java
package com.zetcode.bean;import com.opencsv.bean.CsvBindByName;import java.util.Objects;public class Country {@CsvBindByNameprivate String name;@CsvBindByNameprivate int population;public Country() {}public Country(String name, int population) {this.name = name;this.population = population;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getPopulation() {return population;}public void setPopulation(int population) {this.population = population;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Country country = (Country) o;return population == country.population &&Objects.equals(name, country.name);}@Overridepublic int hashCode() {return Objects.hash(name, population);}}
这是一个Country bean,具有两个属性:name和population。
@CsvBindByNameprivate String name;
@CsvBindByName将name属性映射到Name列中的字段。
com/zetcode/CountryService.java
package com.zetcode.service;import com.opencsv.bean.CsvToBean;import com.opencsv.bean.CsvToBeanBuilder;import com.opencsv.bean.HeaderColumnNameMappingStrategy;import com.zetcode.bean.Country;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.nio.charset.StandardCharsets;import java.util.List;import java.util.Optional;public class CountryService {public static Optional<List<Country>> getListOfCountries() throws IOException {List<Country> countries;try (InputStream is = CountryService.class.getClassLoader().getResourceAsStream("countries.csv")) {if (is == null) {return Optional.empty();}HeaderColumnNameMappingStrategy<Country> strategy= new HeaderColumnNameMappingStrategy<>();strategy.setType(Country.class);try (var br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {CsvToBean<Country> csvToBean = new CsvToBeanBuilder<Country>(br).withType(Country.class).withMappingStrategy(strategy).withIgnoreLeadingWhiteSpace(true).build();countries = csvToBean.parse();}}return Optional.of(countries);}}
CountryService从 CSV 文件读取数据。
try (InputStream is = CountryService.class.getClassLoader().getResourceAsStream("countries.csv")) {
我们使用getResourceAsStream()方法将InputStream转换为countries.csv文件。
if (is == null) {return Optional.empty();}
如果未打开输入流,则返回空Optional。 这用于避免null值。
HeaderColumnNameMappingStrategy<Country> strategy= new HeaderColumnNameMappingStrategy<>();strategy.setType(Country.class);
我们使用 OpenCSV 的HeaderColumnNameMappingStrategy将Country bean 映射到 CSV 文件中的行。 每行都转换为一个 bean。 映射是在@CsvBindByName注解的帮助下完成的。
try (var br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {CsvToBean<Country> csvToBean = new CsvToBeanBuilder<Country>(br).withType(Country.class).withMappingStrategy(strategy).withIgnoreLeadingWhiteSpace(true).build();countries = csvToBean.parse();}
使用CsvToBeanBuilder,我们解析 CSV 文件并将行转换为Country bean 列表。
com/zetcode/web/ReadCountries.java
package com.zetcode.web;import com.zetcode.bean.Country;import com.zetcode.service.CountryService;import javax.servlet.ServletException;import javax.servlet.annotation.WebServlet;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.util.List;import java.util.Optional;@WebServlet(name = "ReadCountries", urlPatterns = {"/read"})public class ReadCountries extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType("text/html;charset=UTF-8");Optional<List<Country>> countries = CountryService.getListOfCountries();String templateName;if (countries.isPresent()) {request.setAttribute("countries", countries.get());templateName = "listCountries.jsp";} else {templateName = "showError.jsp";}var dispatcher = request.getRequestDispatcher(templateName);dispatcher.forward(request, response);}}
在ReadCountries Servlet 中,我们称为getListOfCountries()服务方法。 如果有一些国家,我们将返回的国家列表设置为request对象作为属性。 处理被传送到listCountries.jsp。 如果找不到数据,则返回错误消息。
webapp/listCountries.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%><%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %><!DOCTYPE html><html><head><meta charset="UTF-8"><title>Countries</title><style>.marked { color: chocolate }</style></head><body><table><thead><tr><th>Country</th><th>Population</th></tr></thead><tbody><c:forEach items="${countries}" var="count"><c:if test="${count.population > 100000000}"><tr class="marked"><td><c:out value="${count.name}"/></td><td><fmt:formatNumber type="number" value="${count.population}" /></td></tr></c:if><c:if test="${count.population < 100000000}"><tr><td><c:out value="${count.name}"/></td><td><fmt:formatNumber type="number" value="${count.population}" /></td></tr></c:if></c:forEach></tbody></table></body></html>
在listCountries.jsp文件中,我们在 HTML 表中显示数据。
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %><%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
我们使用两个 JSTL 标签库:核心库和格式库。
<c:forEach items="${countries}" var="count">
使用<c:forEach>标签,我们遍历countries对象。
<c:if test="${count.population > 100000000}"><tr class="marked"><td><c:out value="${count.name}"/></td><td><fmt:formatNumber type="number" value="${count.population}" /></td></tr></c:if>
如果该国家/地区的人口超过一亿,则使用marked类作为行;否则,使用marked类作为行。 它以另一种颜色显示行。 该测试使用 JSTL 的<c:if>标签执行。 <fmt:formatNumber>标签用于格式化该值。
webapp/index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%><!DOCTYPE html><html><head><meta charset="UTF-8"><title>List countries</title></head><body><a href="read">List countries</a></body></html>
index.jsp包含一个调用ReadCountries servlet 的链接。 Servlet 从 CSV 文件读取数据,然后将数据以视图的形式返回给浏览器。
webapp/showError.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%><!DOCTYPE html><html><head><meta charset="UTF-8"><title>Error</title></head><body><p>No countries found</p></body></html>
此模板文件显示错误消息。
在本教程中,我们展示了如何读取 WAR 文件中的 CSV 数据。
您可能也对以下相关教程感兴趣: Java 教程, Jersey 应用中的 Web URL , Java 验证教程和 OpenCSV 教程。
