💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# Java Servlet 提供 XML > 原文: [http://zetcode.com/articles/javaservletservexml/](http://zetcode.com/articles/javaservletservexml/) Java Servlet 服务 XML 展示了如何从 Java Servlet 服务 XML 数据。 数据存储在 MySQL 表中。 该 Web 应用已部署在 Tomcat Web 服务器上。 ## XML 格式 可扩展标记语言(XML)是一种流行的人类可读和机器可读的标记语言。 XML 的设计目标强调互联网的简单性,通用性和可用性。 它是一种文本数据格式,并通过 Unicode 对不同的人类语言提供了强大的支持。 XML 最初是为大规模电子出版而设计的,被广泛用于在软件组件,系统和企业之间交换各种数据。 XML 是由万维网联盟(W3C)开发的行业标准。 它不受任何编程语言或软件供应商的束缚。 XML 是可扩展的,与平台无关的,并且支持国际化。 ## JAXB 用于 XML 绑定的 Java 架构(JAXB)提供了 API 和工具,可自动执行 XML 文档和 Java 对象之间的映射。 JAXB 允许将 XML 内容解组为 Java 表示形式,访问和更新 Java 表示形式,并将 XML 内容的 Java 表示形式编组为 XML 内容。 ## Java Servlet Servlet 是 Java 类,可响应特定类型的网络请求-最常见的是 HTTP 请求。 Java servlet 用于创建 Web 应用。 它们在 servlet 容器(例如 Tomcat 或 Jetty)中运行。 现代 Java Web 开发使用在 servlet 之上构建的框架。 ## Java Servlet 服务 XML 示例 在下面的 Web 应用中,我们从 MySQL 表加载数据并将其显示为 XML 到客户端。 我们使用 JAXB 解析器将 Java 类转换为 XML。 `cars_mysql.sql` ```java -- SQL for the Cars table CREATE TABLE Cars(Id BIGINT PRIMARY KEY AUTO_INCREMENT, Name VARCHAR(150), Price INTEGER); INSERT INTO Cars(Name, Price) VALUES('Audi', 52642); INSERT INTO Cars(Name, Price) VALUES('Mercedes', 57127); INSERT INTO Cars(Name, Price) VALUES('Skoda', 9000); INSERT INTO Cars(Name, Price) VALUES('Volvo', 29000); INSERT INTO Cars(Name, Price) VALUES('Bentley', 350000); INSERT INTO Cars(Name, Price) VALUES('Citroen', 21000); INSERT INTO Cars(Name, Price) VALUES('Hummer', 41400); INSERT INTO Cars(Name, Price) VALUES('Volkswagen', 21600); ``` 该 SQL 脚本在 MySQL 中创建`Cars`表。 ```java $ tree . ├── nb-configuration.xml ├── pom.xml └── src ├── main │ ├── java │ │ └── com │ │ └── zetcode │ │ ├── converter │ │ │ └── CarsXmlConverter.java │ │ ├── dao │ │ │ ├── CarsDAO.java │ │ │ └── ICarsDAO.java │ │ ├── model │ │ │ ├── Car.java │ │ │ └── CarList.java │ │ ├── service │ │ │ ├── CarsService.java │ │ │ └── ICarsService.java │ │ ├── util │ │ │ └── ServiceLocator.java │ │ └── web │ │ ├── GetCar.java │ │ └── GetCars.java │ ├── resources │ └── webapp │ ├── index.html │ ├── META-INF │ │ └── context.xml │ └── WEB-INF └── test └── java ``` 这是项目结构。 `pom.xml` ```java <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zetcode</groupId> <artifactId>JavaServletServeXml</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>JavaServletServeXml</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.0.2.RELEASE</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.45</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.3</version> <configuration> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </build> </project> ``` 这是 Maven POM 文件。 `javax.servlet-api`工件用于 servlet。 `spring-jdbc`依赖项用于`JdbcTemplate`库,该库简化了 Java 中的数据库编程。 `mysql-connector-java`是 Java 语言的 MySQL 驱动程序。 `maven-war-plugin`负责收集 Web 应用的所有工件依赖项,类和资源,并将它们打包到 Web 应用存档(WAR)中。 `context.xml` ```java <?xml version="1.0" encoding="UTF-8"?> <Context path="/JavaServletServeXml"> <Resource name="jdbc/testdb" auth="Container" type="javax.sql.DataSource" username="user12" password="s$cret" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/testdb" maxActive="10" maxIdle="4"/> </Context> ``` 在 Tomcat `context.xml`文件中,我们定义了上下文路径和 MySQL 数据源。 `Car.java` ```java package com.zetcode.model; import java.util.Objects; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; @XmlRootElement(name = "car") @XmlType(propOrder = {"id", "name", "price"}) public class Car { private Long id; private String name; private int price; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } @Override public int hashCode() { int hash = 7; hash = 79 * hash + Objects.hashCode(this.id); hash = 79 * hash + Objects.hashCode(this.name); hash = 79 * hash + this.price; return hash; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Car other = (Car) obj; if (this.price != other.price) { return false; } if (!Objects.equals(this.name, other.name)) { return false; } return Objects.equals(this.id, other.id); } } ``` `Car` bean 从`Cars`数据库表中保留一行。 ```java @XmlRootElement(name = "car") @XmlType(propOrder = {"id", "name", "price"}) ``` 使用`@XmlRootElement`注解,我们设置元素的名称。 `@XmlType`用于设置元素标签的生成顺序。 `CarList.java` ```java package com.zetcode.model; import java.util.List; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementWrapper; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(namespace = "com.zetcode") @XmlAccessorType(XmlAccessType.FIELD) public class CarList { @XmlElementWrapper(name = "cars") @XmlElement(name = "car") private List<Car> cars; public List<Car> getCars() { return cars; } public void setCars(List<Car> cars) { this.cars = cars; } } ``` `CarList`是一个帮助器类,其中包含 JAXB 映射注解,以在 XML 输出中的汽车标签周围创建包装器。 ```java @XmlElementWrapper(name = "cars") ``` `@XmlElementWrapper`注解在列表中的元素周围创建了一个包装。 ```java @XmlElement(name = "car") ``` `@XmlElement`注解设置包装元素的名称。 `ServiceLocator.java` ```java package com.zetcode.util; import java.util.logging.Level; import java.util.logging.Logger; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; public class ServiceLocator { public static DataSource getDataSource(String jndiName) { Context ctx = null; DataSource ds = null; try { ctx = new InitialContext(); ds = (DataSource) ctx.lookup(jndiName); } catch (NamingException ex) { Logger.getLogger(ServiceLocator.class.getName()).log( Level.SEVERE, null, ex); } return ds; } } ``` `ServiceLocator`通过给定的 JNDI 名称查找数据源,并将其返回给调用方。 `ICarsService.java` ```java package com.zetcode.service; import com.zetcode.model.Car; import java.util.List; public interface ICarsService { public Car findCarById(long id); public List<Car> findAllCars(); } ``` `ICarsService`包含两种服务合同方法:`findCarById()`和`findAllCars()`。 `CarsService.java` ```java package com.zetcode.service; import com.zetcode.dao.CarsDAO; import com.zetcode.model.Car; import java.util.List; public class CarsService implements ICarsService { private CarsDAO carsDao; public CarsService() { carsDao = createDao(); } @Override public Car findCarById(long id) { Car car = carsDao.findById(id); return car; } @Override public List<Car> findAllCars() { List<Car> cars = carsDao.findAll(); return cars; } private CarsDAO createDao() { carsDao = new CarsDAO(); return carsDao; } } ``` `CarsService`包含`ICarsService`接口的实现。 服务类调用 DAO 对象的方法,该对象是数据库的中间层。 `ICarsDAO.java` ```java package com.zetcode.dao; import com.zetcode.model.Car; import java.util.List; public interface ICarsDAO { public Car findById(long id); public List<Car> findAll(); } ``` 在这里,我们有 DAO 合同方法。 `CarsDAO.java` ```java package com.zetcode.dao; import com.zetcode.model.Car; import com.zetcode.util.ServiceLocator; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.sql.DataSource; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; public class CarsDAO implements ICarsDAO { private JdbcTemplate jtm; public CarsDAO() { createJdbcTemplate(); } @Override public Car findById(long id) { String sql = "SELECT * FROM Cars WHERE Id=?"; Car car = new Car(); try { car = (Car) jtm.queryForObject(sql, new Object[]{id}, new BeanPropertyRowMapper(Car.class)); } catch (EmptyResultDataAccessException ex) { Logger.getLogger(CarsDAO.class.getName()).log( Level.SEVERE, null, ex); } return car; } @Override public List<Car> findAll() { String sql = "SELECT * FROM Cars"; List<Car> cars = new ArrayList<>(); try { cars = jtm.query(sql, new BeanPropertyRowMapper(Car.class)); } catch (EmptyResultDataAccessException ex) { Logger.getLogger(CarsDAO.class.getName()).log( Level.SEVERE, null, ex); } return cars; } private JdbcTemplate createJdbcTemplate() { DataSource ds = ServiceLocator.getDataSource("java:comp/env/jdbc/testdb"); jtm = new JdbcTemplate(ds); return jtm; } } ``` `CarsDAO`包含 DAO 方法的实现。 我们使用 Spring 的`JdbcTemplate`模块访问数据库。 ```java private JdbcTemplate createJdbcTemplate() { DataSource ds = ServiceLocator.getDataSource("java:comp/env/jdbc/testdb"); jtm = new JdbcTemplate(ds); return jtm; } ``` 在`createJdbcTemplate()`方法中,我们查找数据源并创建`JdbcTemplate`。 `CarsXmlConverter.java` ```java package com.zetcode.converter; import com.zetcode.model.Car; import com.zetcode.model.CarList; import java.io.ByteArrayOutputStream; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; public class CarsXmlConverter { private ByteArrayOutputStream bos; public ByteArrayOutputStream convertList(List<Car> cars) { bos = new ByteArrayOutputStream(); try { JAXBContext context = JAXBContext.newInstance(CarList.class); Marshaller m = context.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); CarList carsList = new CarList(); carsList.setCars(cars); m.marshal(carsList, bos); } catch (JAXBException ex) { Logger.getLogger(CarsXmlConverter.class.getName()).log(Level.SEVERE, null, ex); } return bos; } public ByteArrayOutputStream convertObject(Car car) { bos = new ByteArrayOutputStream(); try { JAXBContext context = JAXBContext.newInstance(Car.class); Marshaller m = context.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); m.marshal(car, bos); } catch (JAXBException ex) { Logger.getLogger(CarsXmlConverter.class.getName()).log(Level.SEVERE, null, ex); } return bos; } } ``` `CarsXmlConverter`包含将 Java 类转换为 XML 数据的方法。 ```java public ByteArrayOutputStream convertList(List<Car> cars) { ``` 该方法返回`ByteArrayOutputStream`。 ```java JAXBContext context = JAXBContext.newInstance(CarList.class); Marshaller m = context.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); ``` 创建了 JAXB 编组器。 ```java CarList carsList = new CarList(); carsList.setCars(cars); m.marshal(carsList, bos); ``` 我们将 Java 表示形式编组为`ByteArrayOutputStream`。 `GetCars.java` ```java package com.zetcode.web; import com.zetcode.converter.CarsXmlConverter; import com.zetcode.model.Car; import com.zetcode.service.CarsService; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(name = "GetCars", urlPatterns = {"/GetCars"}) public class GetCars extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("application/xml;charset=UTF-8"); CarsService carsService = new CarsService(); List<Car> cars = carsService.findAllCars(); CarsXmlConverter xmlConverter = new CarsXmlConverter(); try (ByteArrayOutputStream bos = xmlConverter.convertList(cars)) { OutputStream os = response.getOutputStream(); bos.writeTo(os); } } } ``` `GetCars` Servlet 将`Cars`表中的所有数据作为 XML 数据返回。 ```java @WebServlet(name = "GetCars", urlPatterns = {"/GetCars"}) ``` Java 类用`@WebServlet`注解修饰。 它映射到`GetCars` URL 模式。 ```java response.setContentType("application/xml;charset=UTF-8"); ``` Servlet 将以 XML 输出数据,并且数据的编码设置为 UTF-8。 ```java CarsService carsService = new CarsService(); List<Car> cars = carsService.findAllCars(); ``` 使用`CarsService`的`findAllCars()`,我们从数据库中检索所有汽车。 ```java CarsXmlConverter xmlConverter = new CarsXmlConverter(); try (ByteArrayOutputStream bos = xmlConverter.convertList(cars)) { OutputStream os = response.getOutputStream(); bos.writeTo(os); } ``` 我们使用`CarsXmlConverter`将数据转换为 XML,并将字节写入`ServletOutputStream`。 `GetCar.java` ```java package com.zetcode.web; import com.zetcode.converter.CarsXmlConverter; import com.zetcode.model.Car; import com.zetcode.service.CarsService; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.List; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(name = "GetCar", urlPatterns = {"/GetCar"}) public class GetCar extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { long id = Long.parseLong(request.getParameter("carId")); response.setContentType("application/xml;charset=UTF-8"); CarsService carsService = new CarsService(); Car car = carsService.findCarById(id); CarsXmlConverter xmlConverter = new CarsXmlConverter(); try (ByteArrayOutputStream bos = xmlConverter.convertObject(car)) { OutputStream os = response.getOutputStream(); bos.writeTo(os); } } } ``` `GetCar` Servlet 以 XML 格式返回一辆汽车。 `index.html` ```java <!DOCTYPE html> <html> <head> <title>Home page</title> <meta charset="UTF-8"> </head> <body> <a href="GetCars">Get cars</a> <br> <a href="GetCar?carId=5">Get car with id 5</a> </body> </html> ``` 这是主页。 它包含两个链接。 一个检索所有汽车,另一个检索具有 ID 5 的汽车。 在本教程中,我们创建了一个 Java Web 应用,该应用从 MySQL 数据库中选择数据,将其转换为 XML,然后将 XML 数据返回给客户端。 您可能也对以下相关教程感兴趣: [Java Servlet 焊接教程](/articles/javaservletweld/), [Java Servlet 上传文件](/articles/javaservletuploadfile/), [Java Log4j 教程](/java/log4j/), [Java Servlet RESTful 客户端](/articles/javaservletrestclient/) , [Java `RequestDispatcher`](/java/requestdispatcher/) ,[从 Java Servlet 提供纯文本](/articles/javaservlettext/) , [Java Servlet 图像教程](/articles/javaservletimage/)或 [Java 教程](/lang/java/)。