JAXB注解---转载自 http://blog.youkuaiyun.com/lw371496536/article/details/6942045

本文深入探讨了Java API for XML Binding (JAXB) 的原理及应用,通过具体示例展示了如何利用JAXB进行Java对象与XML的相互转换,包括Marshal过程(将Java对象转换为XML)和UnMarshal过程(将XML转换为Java对象)。介绍了关键注解及其作用,并提供了编码设置、格式化输出和片段处理等技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JAXB(Java API for XML Binding),提供了一个快速便捷的方式将Java对象与XML进行转换。在JAX-WS(Java的WebService规范之一)中,JDK1.6 自带的版本JAX-WS2.1,其底层支持就是JAXB

    JAXB 可以实现Java对象与XML的相互转换,在JAXB中,将一个Java对象转换为XML的过程称之为Marshal,将XML转换为Java对象的过程称之为UnMarshal。我们可以通过在 Java 类中标注注解的方式将一个Java对象绑定到一段XML,也就是说,在Java类中标注一些注解,这些注解定义了如何将这个类转换为XML,怎么转换,以及一段XML如何被解析成这个类所定义的对象;也可以使用JAXB的XJC工具,通过定义schema的方式实现Java对象与XML的绑定(这个下次研究)。

    下面来了解一下如何通过标注注解来完成 Marshal 和 UnMarshal 的过程。我用的是 JAXB2_20101209.jar ,可以到http://jaxb.java.net/下载最新版本。

 

首先看个小例子:



定义一个java类

Java代码
package com.why.jaxb;   
  
import javax.xml.bind.annotation.XmlRootElement;   
  
@XmlRootElement  
public class People {   
    public String id = "001";   
    public String name = "灰太狼";   
    public int age = 26;   
}  

//我们在实际中一般在get方法上添加相关注解
Java To XML(Marshal)

Java代码
package com.why.jaxb;   
  
import javax.xml.bind.JAXBContext;   
import javax.xml.bind.JAXBException;   
import javax.xml.bind.Marshaller;   
  
public class Java2XML {   
  
    /**  
     * @param args  
     * @throws JAXBException   
     */  
    public static void main(String[] args) throws JAXBException {   
        JAXBContext context = JAXBContext.newInstance(People.class);   
           
        Marshaller marshaller = context.createMarshaller();   
        marshaller.setProperty(Marshaller.JAXB_ENCODING,"gb2312");//编码格式

        //我在实际开发中重新封装了JAXB基本类,这里就使用到了该属性。不过默认的编码格式UTF-8

        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);//是否格式化生成的xml串   
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);//是否省略xml头信息(<?xml version="1.0" encoding="gb2312" standalone="yes"?>)   
           
        People people = new People();   
        marshaller.marshal(people, System.out);   
    }   
  
}  

XML To Java(UnMarshal)

Java代码
package com.why.jaxb;   
  
import java.io.File;   
import javax.xml.bind.JAXBContext;   
import javax.xml.bind.JAXBException;   
import javax.xml.bind.Unmarshaller;   
import org.xml.sax.SAXException;   
  
public class XML2Java {   
    /**  
     * @param args  
     * @throws JAXBException   
     * @throws JAXBException   
     * @throws SAXException   
     */  
    public static void main(String[] args) throws JAXBException {   
        JAXBContext context = JAXBContext.newInstance(People.class);   
        Unmarshaller unmarshaller = context.createUnmarshaller();   
        File file = new File("src/people.xml");   
        People people = (People)unmarshaller.unmarshal(file);   
        System.out.println(people.id);   
        System.out.println(people.name);   
        System.out.println(people.age);   
    }   
}

 

       其实Marshal 和 UnMarshal的过程并不复杂,只需要从JAXBContext中获得Marshaller或Unmarshaller对象,就可以让JAXB帮我们来进行转换了。我们需要操作的主要内容是定义一个规则,告诉JAXB如何将一个类、按照什么样的格式转换为XML,下面是JAXB中主要的一些注解。



@XmlRootElement   将一个Java类映射为一段XML的根节点

参数:name            定义这个根节点的名称

          namespace   定义这个根节点命名空间



@XmlAccessorType  定义映射这个类中的何种类型需要映射到XML。可接收四个参数,分别是:

      XmlAccessType.FIELD:映射这个类中的所有字段到XML

      XmlAccessType.PROPERTY:映射这个类中的属性(get/set方法)到XML

      XmlAccessType.PUBLIC_MEMBER:将这个类中的所有public的field或property同时映射到XML(默认)

      XmlAccessType.NONE:不映射



@XmlElement  指定一个字段或get/set方法映射到XML的节点。如,当一个类的XmlAccessorType 被标注为PROPERTY时,在某一个没有get/set方法的字段上标注此注解,即可将该字段映射到XML。

参数:defaultValue  指定节点默认值

         name             指定节点名称

         namespace    指定节点命名空间

         required         是否必须(默认为false)

         nillable           该字段是否包含 nillable="true" 属性(默认为false)

         type               定义该字段或属性的关联类型



@XmlAttribute  指定一个字段或get/set方法映射到XML的属性。

参数:name             指定属性名称

         namespace    指定属性命名空间

         required         是否必须(默认为false)



@XmlTransient  定义某一字段或属性不需要被映射为XML。如,当一个类的XmlAccessorType 被标注为PROPERTY时,在某一get/set方法的字段上标注此注解,那么该属性则不会被映射。



@XmlType 定义映射的一些相关规则

参数:propOrder        指定映射XML时的节点顺序

         factoryClass     指定UnMarshal时生成映射类实例所需的工厂类,默认为这个类本身

         factoryMethod  指定工厂类的工厂方法

         name               定义XML Schema中type的名称

         namespace      指定Schema中的命名空间



@XmlElementWrapper  为数组元素或集合元素定义一个父节点。如,类中有一元素为List items,若不加此注解,该元素将被映射为

    <items>...</items>

    <items>...</items>

这种形式,此注解可将这个元素进行包装,如:

    @XmlElementWrapper(name="items")
    @XmlElement(name="item")
    public List items;

将会生成这样的XML样式:

    <items>

        <item>...</item>

        <item>...</item>

    </items>



@XmlJavaTypeAdapter  自定义某一字段或属性映射到XML的适配器。如,类中包含一个接口,我们可以定义一个适配器(继承自 javax.xml.bind.annotation.adapters.XmlAdapter类),指定这个接口如何映射到XML。



@XmlSchema 配置整个包的namespace,这个注解需放在package-info.java文件中。

jaxb编码:

           JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            InputStreamReader reader=new InputStreamReader(inputStream,"GBK");   //在此修改编码
            return unmarshaller.unmarshal(reader);


<think>我们正在讨论如何在Spring MVC中配置BeanNameUrlHandlerMapping来发布SOAP接口。但是,请注意,通常我们使用Spring Web Services(Spring-WS)或者Apache CXF来发布SOAP服务,而不是直接使用BeanNameUrlHandlerMapping。BeanNameUrlHandlerMapping是Spring MVC中用于将URL映射到Bean名称的一种处理器映射策略,它通常用于简单的控制器映射。 不过,如果我们确实想使用BeanNameUrlHandlerMapping来发布SOAP服务,我们可以考虑以下思路: 1. 创建一个处理SOAP请求的控制器(Controller),该控制器需要实现特定的接口,例如`Controller`接口(或者使用`@Controller`注解,但需要配置相应的处理器映射器)。 2. 配置BeanNameUrlHandlerMapping,将特定的URL路径映射到该控制器的Bean名称。 3. 在控制器中处理SOAP请求,解析SOAP消息并生成SOAP响应。 但是,这种方式需要我们自己处理SOAP的解析和生成,通常不推荐,因为这样会复杂且容易出错。通常,我们会使用Spring-WS或CXF等框架,它们已经为我们处理了SOAP消息的解析、生成和路由。 考虑到用户可能希望使用Spring MVC原生的方式(尽管不常见),下面我将给出一个使用BeanNameUrlHandlerMapping发布SOAP接口的示例步骤,但请注意,这只是一个概念性的演示,实际生产环境建议使用Spring-WS或CXF。 ### 步骤1:添加依赖 首先,在`pom.xml`中添加Spring MVC和SOAP相关的依赖。由于我们要处理SOAP消息,需要添加SOAP消息处理的库,例如`javax.xml.soap`(SAAJ)的依赖。 ```xml <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.3.10</version> </dependency> <dependency> <groupId>com.sun.xml.messaging.saaj</groupId> <artifactId>saaj-impl</artifactId> <version>1.5.3</version> </dependency> ``` ### 步骤2:创建SOAP控制器 创建一个实现`Controller`接口的控制器,或者使用`@Controller`注解,但这里为了配合BeanNameUrlHandlerMapping,我们使用实现`Controller`接口的方式。 ```java import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.soap.MessageFactory; import javax.xml.soap.SOAPMessage; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; public class SoapController implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { // 从请求中获取SOAP消息 SOAPMessage soapRequest = MessageFactory.newInstance().createMessage(null, request.getInputStream()); // 处理SOAP请求,这里简化处理,实际需要解析SOAP消息并生成响应 // ... // 创建SOAP响应 SOAPMessage soapResponse = MessageFactory.newInstance().createMessage(); // 构建响应内容 // ... // 设置响应内容类型 response.setContentType("text/xml;charset=UTF-8"); // 将SOAP响应写入输出流 soapResponse.writeTo(response.getOutputStream()); // 返回null表示我们已经处理了响应 return null; } } ``` ### 步骤3:配置BeanNameUrlHandlerMapping 在Spring MVC的配置文件中(如`springmvc-servlet.xml`),配置BeanNameUrlHandlerMapping,并将URL映射到上面控制器的Bean名称。 ```xml <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <!-- 控制器Bean,其名称以"/"开头,这样BeanNameUrlHandlerMapping会将对应的URL映射到该控制器 --> <bean name="/soapService" class="com.example.SoapController"/> ``` ### 步骤4:配置视图解析器(可选) 由于我们的控制器直接写入了响应,因此不需要视图解析器。但如果有其他需要视图的控制器,可以配置。 ### 步骤5:部署和测试 部署应用并访问URL:`http://localhost:8080/your-app-context/soapService`,发送一个SOAP请求来测试。 ### 注意事项 1. 这种方式需要手动处理SOAP消息的解析和生成,对于复杂的服务会非常繁琐。 2. 通常,我们使用Spring-WS模块,它提供了基于消息的SOAP服务开发,并支持通过`@Endpoint`注解和`@PayloadRoot`注解来路由SOAP消息。 3. 如果使用Spring-WS,配置方式完全不同,它会使用`MessageDispatcherServlet`代替Spring MVC的`DispatcherServlet`,并且有自己的映射机制(如`PayloadRootAnnotationMethodEndpointMapping`)。 ### 推荐做法 考虑到实际开发,建议使用Spring-WS或Apache CXF来发布SOAP服务。例如,使用Spring-WS时,配置如下: 1. 添加Spring-WS依赖。 2. 配置`MessageDispatcherServlet`。 3. 编写使用`@Endpoint`注解的端点类。 4. 在端点方法中使用`@PayloadRoot`注解指定处理的SOAP消息。 这样,Spring-WS会自动处理SOAP消息的转换和路由,大大简化开发。 ### 相关问题 1. 如何在Spring MVC中集成Spring-WS发布SOAP服务? 2. 使用BeanNameUrlHandlerMapping和RequestMappingHandlerMapping有什么区别? 3. 如何为手动实现的SOAP控制器添加WS-Security支持?</think>### 如何在Spring MVC中配置BeanNameUrlHandlerMapping发布SOAP接口 #### 一、核心配置步骤 1. **配置BeanNameUrlHandlerMapping** 在Spring MVC配置文件(如`springmvc-servlet.xml`)中显式声明处理器映射器: ```xml <!-- 启用注解驱动(可选但推荐)[^1] --> <mvc:annotation-driven/> <!-- 显式配置BeanNameUrlHandlerMapping --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> <property name="order" value="1"/> <!-- 设置映射优先级 --> </bean> ``` 2. **创建SOAP服务端点Bean** 使用`SimpleJaxWsServiceExporter`导出SOAP服务,Bean名称需以`/`开头: ```xml <!-- SOAP服务实现类 --> <bean id="helloService" class="com.example.HelloServiceImpl"/> <!-- 通过BeanNameUrlHandlerMapping暴露SOAP端点 --> <bean name="/soap/hello" class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter"> <property name="service" ref="helloService"/> <property name="baseAddress" value="http://localhost:8080/services/"/> </bean> ``` - `name="/soap/hello"`:定义服务访问路径`/soap/hello` - `baseAddress`:指定服务基础URL[^2] 3. **服务接口与实现** ```java // SOAP服务接口 @WebService public interface HelloService { String sayHello(String name); } // 服务实现类 @WebService(endpointInterface = "com.example.HelloService") public class HelloServiceImpl implements HelloService { @Override public String sayHello(String name) { return "Hello, " + name + "!"; } } ``` 4. **配置DispatcherServlet** 在`web.xml`中确保DispatcherServlet处理所有请求: ```xml <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> <!-- 拦截所有请求 --> </servlet-mapping> ``` 5. **访问SOAP服务** - WSDL地址:`http://localhost:8080/soap/hello?wsdl` - SOAP端点:`http://localhost:8080/soap/hello` --- #### 二、关键原理说明 1. **BeanNameUrlHandlerMapping工作流程** - 扫描所有Bean定义,识别名称以`/`开头的Bean - 将Bean名称作为URL路径映射到对应的处理器 - 本例中`/soap/hello`映射到`SimpleJaxWsServiceExporter` 2. **与其他组件的交互**[^2] ```mermaid graph LR A[客户端请求 /soap/hello] --> B(DispatcherServlet) B --> C[BeanNameUrlHandlerMapping] C --> D[查找名为/soap/hello的Bean] D --> E[SimpleJaxWsServiceExporter] E --> F[处理SOAP请求] F --> G[返回SOAP响应] ``` 3. **与注解驱动的区别** | 配置方式 | 映射策略 | 适用场景 | |------------------------|-----------------------------|---------------------| | BeanNameUrlHandlerMapping | 基于Bean名称的URL映射 | 显式配置SOAP端点 | | `@RequestMapping` | 基于方法注解的动态映射 | RESTful控制器 | | `<mvc:annotation-driven>` | 自动注册注解处理器[^1] | 混合服务场景 | --- #### 三、高级配置技巧 1. **多版本SOAP服务共存** ```xml <!-- 版本1服务 --> <bean name="/v1/hello" class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter"> <property name="service" ref="helloServiceV1"/> </bean> <!-- 版本2服务 --> <bean name="/v2/hello" class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter"> <property name="service" ref="helloServiceV2"/> </bean> ``` 2. **自定义命名空间** 在服务实现类指定版本化命名空间: ```java @WebService( endpointInterface = "com.example.HelloService", targetNamespace = "http://v2.example.com/wsdl" ) public class HelloServiceV2Impl implements HelloService { ... } ``` 3. **安全拦截配置** ```xml <bean name="/secure/hello" class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter"> <property name="service" ref="helloService"/> <property name="inInterceptors"> <list> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"/> </list> </property> </bean> ``` --- #### 四、常见问题解决 1. **404错误** - 检查`<bean name>`是否以`/`开头 - 确认DispatcherServlet的`<url-pattern>`包含服务路径 2. **WSDL无法访问** - 添加`?wsdl`后缀访问 - 检查是否配置了`<mvc:annotation-driven>`导致冲突[^1] 3. **SOAP解析错误** ```xml <!-- 添加消息转换器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> <property name="messageConverters"> <list> <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/> </list> </property> </bean> ``` > 通过BeanNameUrlHandlerMapping配置的SOAP服务适合需要显式控制端点的场景,生产环境建议结合`<mvc:annotation-driven>`使用[^1][^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值