Java Servlet 提供 XML
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
-- 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
表。
$ 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
<?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
<?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
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
数据库表中保留一行。
@XmlRootElement(name = "car")
@XmlType(propOrder = {"id", "name", "price"})
使用@XmlRootElement
注解,我们设置元素的名称。 @XmlType
用于设置元素标签的生成顺序。
CarList.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 输出中的汽车标签周围创建包装器。
@XmlElementWrapper(name = "cars")
@XmlElementWrapper
注解在列表中的元素周围创建了一个包装。
@XmlElement(name = "car")
@XmlElement
注解设置包装元素的名称。
ServiceLocator.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
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
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
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
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
模块访问数据库。
private JdbcTemplate createJdbcTemplate() {
DataSource ds = ServiceLocator.getDataSource("java:comp/env/jdbc/testdb");
jtm = new JdbcTemplate(ds);
return jtm;
}
在createJdbcTemplate()
方法中,我们查找数据源并创建JdbcTemplate
。
CarsXmlConverter.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 数据的方法。
public ByteArrayOutputStream convertList(List<Car> cars) {
该方法返回ByteArrayOutputStream
。
JAXBContext context = JAXBContext.newInstance(CarList.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
创建了 JAXB 编组器。
CarList carsList = new CarList();
carsList.setCars(cars);
m.marshal(carsList, bos);
我们将 Java 表示形式编组为ByteArrayOutputStream
。
GetCars.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 数据返回。
@WebServlet(name = "GetCars", urlPatterns = {"/GetCars"})
Java 类用@WebServlet
注解修饰。 它映射到GetCars
URL 模式。
response.setContentType("application/xml;charset=UTF-8");
Servlet 将以 XML 输出数据,并且数据的编码设置为 UTF-8。
CarsService carsService = new CarsService();
List<Car> cars = carsService.findAllCars();
使用CarsService
的findAllCars()
,我们从数据库中检索所有汽车。
CarsXmlConverter xmlConverter = new CarsXmlConverter();
try (ByteArrayOutputStream bos = xmlConverter.convertList(cars)) {
OutputStream os = response.getOutputStream();
bos.writeTo(os);
}
我们使用CarsXmlConverter
将数据转换为 XML,并将字节写入ServletOutputStream
。
GetCar.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
<!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 焊接教程, Java Servlet 上传文件, Java Log4j 教程, Java Servlet RESTful 客户端 , Java RequestDispatcher
,从 Java Servlet 提供纯文本 , Java Servlet 图像教程或 Java 教程。