跳转至

Java Servlet 提供 XML

原文: 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

-- 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();

使用CarsServicefindAllCars(),我们从数据库中检索所有汽车。

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



回到顶部