You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写可同时接收解析XML与JSON请求的Servlet程序?

Servlet同时支持JSON/XML请求及分支判断问题修复

一、Content-Type分支无法进入的问题修复

两个分支无法匹配的核心原因有两个:

  • 字符串比较逻辑错误:Java中字符串内容比较必须使用equals()方法,==对比的是字符串对象的内存地址,请求头返回的字符串和常量字符串内存地址不同,永远返回false
  • Content-Type存在附加参数:实际请求的Content-Type通常会携带编码等后缀,例如application/json;charset=utf-8,直接全等匹配会失败,推荐使用contains()方法模糊匹配,或者直接调用Servlet原生的getContentType()方法简化获取

修复后的判断逻辑参考:

// 先获取content-type,统一转小写避免大小写问题
String contentType = request.getContentType() == null ? "" : request.getContentType().toLowerCase();
ObjectMapper objectMapper = new ObjectMapper();
if (contentType.contains("application/json")) {
    System.out.println("json ");
    Symbol symbolContainerFromJson = objectMapper.readValue(request.getReader(), Symbol.class);
    System.out.println(symbolContainerFromJson.getSymbol());
} else if (contentType.contains("application/xml")) {
    System.out.println("xml");
    Symbol symbolContainerFromXml = new XmlMapper().readValue(request.getReader(), Symbol.class);
    System.out.println(symbolContainerFromXml.getSymbol());
} else {
    // 不支持的媒体类型返回415状态码
    response.setStatus(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
    return;
}

二、完整的JSON/XML请求兼容实现

前置依赖

如果使用Jackson做序列化/反序列化,需要引入XML支持包(Maven示例):

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.15.2</version> <!-- 和你使用的jackson-databind版本保持一致即可 -->
</dependency>

定义参数接收实体类

import jakarta.xml.bind.annotation.XmlRootElement;
import lombok.Data;

@Data // Lombok注解,自动生成get/set方法,也可以手动编写
@XmlRootElement // XML序列化必须的根节点注解
public class Symbol {
    private List<String> Symbol;

    // 手动编写get/set示例
    // public List<String> getSymbol() { return Symbol; }
    // public void setSymbol(List<String> symbol) { Symbol = symbol; }
}

对应XML请求格式示例:

<Symbol>
    <Symbol>OLM</Symbol>
    <Symbol>ASC</Symbol>
</Symbol>

完整doPost实现

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.setCharacterEncoding("UTF-8");
    // 先把请求体缓存为字符串,避免输入流只能读取一次的问题
    BufferedReader reader = request.getReader();
    StringBuilder bodySb = new StringBuilder();
    String line;
    while ((line = reader.readLine()) != null) {
        bodySb.append(line);
    }
    String requestBody = bodySb.toString();

    String contentType = request.getContentType() == null ? "" : request.getContentType().toLowerCase();
    ObjectMapper jsonMapper = new ObjectMapper();
    XmlMapper xmlMapper = new XmlMapper();
    Symbol symbolContainer = null;

    try {
        if (contentType.contains("application/json")) {
            symbolContainer = jsonMapper.readValue(requestBody, Symbol.class);
        } else if (contentType.contains("application/xml")) {
            symbolContainer = xmlMapper.readValue(requestBody, Symbol.class);
        } else {
            response.setStatus(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
            response.getWriter().write("仅支持application/json和application/xml格式的请求");
            return;
        }
    } catch (Exception e) {
        e.printStackTrace();
        response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
        response.getWriter().write("请求体格式解析失败,请检查格式是否正确");
        return;
    }

    // 后续业务逻辑,直接从symbolContainer获取Symbol列表即可
    List<String> symbolList = symbolContainer.getSymbol();
    // 其他业务处理...
}

注意事项

  • 实体类的属性名要和请求里的键名完全一致,比如JSON里的键是Symbol,实体类的属性名也要是Symbol,如果要自定义名称可以加@JsonProperty(JSON场景)和@JacksonXmlProperty(XML场景)注解
  • 如果不想用实体类映射,也可以用DOM4J等原生XML解析工具,直接从请求体字符串中提取Symbol标签的内容

内容的提问来源于stack exchange,提问作者sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 02:18:01