JAXとspringのシームレスな統合(一)

25988 ワード

JAX-WSとspringの統合にはいくつかの方法があります.
1つ目:
jaxws-rtによりwebserviceの起動を実現します.
OK:プロファイルsun-jaxwsを追加作成する必要があります.xmlでspringのオートインジェクション機能が使えず、BeanFactoryからbeanを取得するしか受信できません!
に頼る
<!--   servlet  jax -->
<dependency>
	<groupId>com.sun.xml.ws</groupId>
	<artifactId>jaxws-rt</artifactId>
</dependency>

 
Webで必要です.xmlでサーブレットを構成する
<listener>
	<listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
</listener>
<servlet>
	<servlet-name>StudentWsService</servlet-name>
	<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>StudentWsService</servlet-name>
	<url-pattern>/ws</url-pattern>
</servlet-mapping>

 
プロファイルを追加する必要があります:sun-jaxws.xml
<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">
	
	<!-- name          implementation          url-pattern              -->
	<endpoint name="StudentWsService" 
		implementation="com.hqh.student.ws.StudentWSServiceImpl" 
		url-pattern="/ws"/>

</endpoints>

 
2つ目(推奨):
springが提供するjarパッケージによるJAX-WSとのシームレスな統合
利点:webserviceオブジェクトはspringによって管理され、springは注入を完了することができます!
1、依存パッケージ(デフォルト依存spring 2.0を除外する必要があります.そうしないと、プロジェクトで使用されているspring 3.0と競合します)
pom.xml
<!--   spring   servlet  jax -->
<dependency>
  <groupId>org.jvnet.jax-ws-commons.spring</groupId>
  <artifactId>jaxws-spring</artifactId>
  <!--     spring2.0    -->
  <exclusions>
  	<exclusion>
  		<groupId>org.springframework</groupId>
  		<artifactId>spring</artifactId>
  	</exclusion>
  </exclusions>
</dependency>

 
2、WSSpringServiceの構成
<!--   spring    jax    -->
<servlet>
	<servlet-name>StudentWsService-WSSpringServlet</servlet-name>
	<servlet-class>com.sun.xml.ws.transport.http.servlet.WSSpringServlet</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>StudentWsService-WSSpringServlet</servlet-name>
	<url-pattern>/jaxws-spring</url-pattern>
</servlet-mapping>

 
 
3、jaxwsとspringの統合を別のプロファイルに配置する.xml
ネーミングスペースを導入し、eclipseにschemaファイルを導入します(XML Catalog:Add...)
(xsdファイルは、Maven Dependenciesのjaxws-spring-1.8.jarから入手可能)
xmlns:wsとxmlns:wssは新しく追加されたネーミングスペースです
 
<?xml version="1.0" encoding="UTF-8"?>
<beans  xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:ws="http://jax-ws.dev.java.net/spring/core"
        xmlns:wss="http://jax-ws.dev.java.net/spring/servlet"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd  
           http://jax-ws.dev.java.net/spring/core http://jax-ws.dev.java.net/spring/core.xsd
           http://jax-ws.dev.java.net/spring/servlet http://jax-ws.dev.java.net/spring/servlet.xsd">
	
	<context:annotation-config/>
	
	<context:component-scan base-package="com.hqh.student"/>
	
	<!-- url must same with the url pattern of StudentWsService-WSSpringServlet in web.xml -->
	<wss:binding url="/jaxws-spring">
		<wss:service>
<!-- bean        "#",studentWsService     bean       --> 
			<ws:service bean="#studentWsService">
				<ws:metadata>
					<value>/WEB-INF/wsdl/student.xsd</value>
				</ws:metadata>
			</ws:service>
		</wss:service>
	</wss:binding>
	
	<!--     ( :jaxws   spring    ,            ,        !) -->
	<!-- Web service methods 
	<bean id="studentWsService" class="com.hqh.student.ws.StudentWSServiceImpl">
		<property name="studentService" ref="StudentService"></property>
	</bean>
	
	<bean id="StudentService" class="com.hqh.student.service.StudentServiceImpl"/>
	-->	
</beans>

 
 
4、web.xmlにインフラストラクチャを追加
<!-- spring       -->
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>classpath:applicationContext.xml,classpath:applicationContext-jaxws.xml</param-value>
</context-param>

 
5、webservice実装クラスで注釈を用いて注入を完了する
package com.hqh.student.ws;

import java.util.List;

import javax.annotation.Resource;
import javax.jws.WebService;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.util.WebUtils;

import com.hqh.student.context.BeanFactoryUtil;
import com.hqh.student.context.WebUtil;
import com.hqh.student.model.Reward;
import com.hqh.student.model.Student;
import com.hqh.student.service.StudentService;


@WebService(endpointInterface="com.hqh.student.ws.IStudentWSService",
			serviceName="StudentWSService",
			portName="studentServicePort",
			targetNamespace="http://ws.student.hqh.com",
			wsdlLocation="/WEB-INF/wsdl/student.wsdl")
//     spring  ,studentWsService       bean    name
@Component("studentWsService")
public class StudentWSServiceImpl implements IStudentWSService{
	
//	private static final BeanFactory factory = new ClassPathXmlApplicationContext("beans.xml");
//	public StudentWSServiceImpl() {
//		if(studentService==null) {
//			studentService = factory.getBean(StudentService.class);
//		}
//	}
	
	//    
	@Resource
	private StudentService studentService;
	
	
	@Override
	public Student getStudent(String number) {
//		studentService = (StudentService) WebUtil.getBean(StudentService.class);
//		studentService = (StudentService) BeanFactoryUtil.getBean(StudentService.class);
		return studentService.getStudent(number);
	}

	@Override
	public List<Student> list() {
//		studentService = (StudentService) WebUtil.getBean(StudentService.class);
//		studentService = (StudentService) BeanFactoryUtil.getBean(StudentService.class);
		return studentService.list();
	}

	@Override
	public List<Reward> listReward(String number, String year) {
//		studentService = (StudentService) WebUtil.getBean(StudentService.class);
//		studentService = (StudentService) BeanFactoryUtil.getBean(StudentService.class);
		return studentService.listReward(number, year);
	}

}

 
jettyサーバを起動し、次のアドレスにアクセスします.
http://localhost:8080/student-web/jaxws-spring?wsdl
完了!
 
クライアントの作成
クライアントとサービス側は異なる2つのアプリケーションであるため、本例ではサービス側はTomcatをコンテナとして、クライアントはjettyをコンテナとして使用する
1、サービス側のプラグインを修正し、tomcatを使用する
 
<!-- cargo     tomcat -->
<!--      :     -->
<plugin>
	<groupId>org.codehaus.cargo</groupId>
	<artifactId>cargo-maven2-plugin</artifactId>
	<configuration>
		<container>
			<containerId>tomcat6x</containerId>
			<home>E:\technology-hqh\soft\server\apache-tomcat-6.0.29</home>
		</container>
		<configuration>
			<!--      -->
			<type>standalone</type>
			<home>${project.build.directory}/tomcat6x</home>
			<properties>
				<!--        -->
				<cargo.servlet.port>9999</cargo.servlet.port>
			</properties>
		</configuration>
		<deployables>
	    <deployable>
	      <type>war</type>
	      <properties>
	      	<!--            -->
	        <context>/server</context>
	      </properties>
	    </deployable>
	  </deployables>
	</configuration>
</plugin>

2、クライアントの作成開始
基本手順:
jaxws-maven-pluginを使用してwsdlをローカルjavaファイルに変換
springMVCによるプレゼンテーションレイヤの機能
Jaxws-springを使用してJAX-WSとspringを統合し、主にクライアントにendpointサービスオブジェクトを注入します.
maven-jetty-pluginプラグインを使用してjettyをクライアントのサーバとして使用
 
pom.xml
 
<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/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.hqh.student</groupId>
	<artifactId>student-cient-remote</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>

	<name>student-cient-remote Maven Webapp</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<spring.version>3.0.5.RELEASE</spring.version>
	</properties>

	<dependencies>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.10</version>
			<scope>test</scope>
		</dependency>
		<!-- SPRING -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<!-- servlet+jstl+jsp -->
		<dependency>
			<groupId>servletapi</groupId>
			<artifactId>servletapi</artifactId>
			<version>2.4</version>
			<scope>provided</scope>
		</dependency>
		
	<!--             jaxws-rt :
		java.lang.ClassNotFoundException: com.sun.istack.XMLStreamReaderToContentHandler -->
		<dependency>
			<groupId>com.sun.xml.ws</groupId>
			<artifactId>jaxws-rt</artifactId>
			<version>2.1.3</version> 
			<!--    activation,       java.lang.LinkageError: loader constraint violation-->
			<exclusions>
				<exclusion>
				<groupId>javax.activation</groupId>
					<artifactId>activation</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

		<!-- jax  spring    -->
		<dependency>
			<groupId>org.jvnet.jax-ws-commons.spring</groupId>
			<artifactId>jaxws-spring</artifactId>
			<version>1.8</version>
			<exclusions>
				<exclusion>
					<groupId>org.springframework</groupId>
					<artifactId>spring</artifactId>
				</exclusion>
				<!--    activation-->
				<exclusion>
				<groupId>javax.activation</groupId>
					<artifactId>activation</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<build>
		<finalName>student-cient-remote</finalName>
		<!--      jetty   -->
		<plugins>
			<!-- jetty   -->
			<plugin>
				<groupId>org.mortbay.jetty</groupId>
				<artifactId>maven-jetty-plugin</artifactId>
				<version>6.1.10</version>
				<configuration>
					<scanIntervalSeconds>1000</scanIntervalSeconds>
				</configuration>
			</plugin>
			<!--    -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<configuration>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
			
			<!--jaxws  -->
			<plugin>
				  <groupId>org.codehaus.mojo</groupId>
				  <artifactId>jaxws-maven-plugin</artifactId>
				  <version>1.9</version>
				  <configuration>
				  	<wsdlUrls>
						<wsdlUrl>http://localhost:9999/server/jaxws-spring?wsdl</wsdlUrl>
					</wsdlUrls>
				  </configuration>
				  <executions>
				  	<execution>
				  		<phase>compile</phase>
				  		<goals>
				  			<goal>wsimport</goal>
				  		</goals>
				  	</execution>
				  </executions>
			</plugin>
		</plugins>
	</build>
</project>

 
web.xml
 
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	
	<!-- spring       -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:applicationContext.xml</param-value>
	</context-param>
	
	<!--    beanFactory -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	
	<!-- springMVC -->
	<servlet>
		<servlet-name>srpingMVC</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>srpingMVC</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
	
	<!--   spring    jax    -->
	<servlet>
		<servlet-name>StudentWsService-WSSpringServlet</servlet-name>
		<servlet-class>com.sun.xml.ws.transport.http.servlet.WSSpringServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>StudentWsService-WSSpringServlet</servlet-name>
		<url-pattern>/jaxws-spring</url-pattern>
	</servlet-mapping>
	
	
</web-app>

 
srpingMVC-servlet.xml
 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
    <mvc:annotation-driven/>

    <!--           -->
    <context:component-scan base-package="com.hqh"/>

	<!--                  -->
	<mvc:resources location="/resources/" mapping="/resources/**"/>
    
    <!--            :  +    +   -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    	<property name="prefix" value="/WEB-INF/jsp/"/>
    	<property name="suffix" value=".jsp"/>
    </bean>
    
</beans>

 
applicationContext.xml
 
<?xml version="1.0" encoding="UTF-8"?>
<beans  xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	    xmlns:aop="http://www.springframework.org/schema/aop"
	    xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:ws="http://jax-ws.dev.java.net/spring/core"
        xmlns:wss="http://jax-ws.dev.java.net/spring/servlet"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd  
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
           http://jax-ws.dev.java.net/spring/core http://jax-ws.dev.java.net/spring/core/spring-jax-ws-core.xsd
           http://jax-ws.dev.java.net/spring/servlet http://jax-ws.dev.java.net/spring/servlet/spring-jax-ws-servlet.xsd">
	<context:annotation-config/>
	<context:component-scan base-package="com.hqh.client"/>
	
	<!--   spring  webservice     ! -->
	<!-- Accessing web services using JAX-WS -->
	<bean id="wsService" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
	    <property name="serviceInterface" value="com.hqh.student.ws.IStudentWSService"/>
	    <property name="wsdlDocumentUrl" value="http://localhost:9999/server/jaxws-spring?wsdl"/>
	    <property name="namespaceUri" value="http://ws.student.hqh.com"/>
	    <property name="serviceName" value="StudentWSService"/>
	    <property name="portName" value="studentServicePort"/>
    </bean>
    
    <!--      -->
	<bean id="client" class="com.hqh.client.ws.controller.ClientController">
		<property name="studentWsService" ref="wsService"></property>
	</bean>   
    
</beans>

 
Controller
 
package com.hqh.client.ws.controller;


import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.hqh.student.ws.IStudentWSService;
import com.hqh.student.ws.Student;

@Controller
public class ClientController {

	/**
	 *         ,   setters    ,   2   ,ClientController        
	 *   studentWsService NULL,  ,    static          webservice       
	 *               spring            
	 *            ?
	 */
	private static IStudentWSService studentWsService;
	
	//  setters      !
	public void setStudentWsService(IStudentWSService wsService) {
		studentWsService = wsService;
	}

	@RequestMapping(value="/getStudent",method=RequestMethod.GET)
	public String getStudent() {
		return "index";
	}
	
	@RequestMapping(value="/getStudent",method=RequestMethod.POST)
	public String getStudent(String number,Model model) {
		Student stu = studentWsService.getStudent(number);
		System.out.println(stu);
		if(stu==null) {
			model.addAttribute("error", "   !");
		} else {
			model.addAttribute(stu);
		}
		return "index";
	}
	
}

 
その間に2つの異常に遭遇して、とても苦労してやっと解決しました!
異常1
java.lang.NoClassDefFoundError: com/sun/istack/XMLStreamReaderToContentHandler
	at com.sun.xml.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:227)
	at com.sun.xml.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:296)
	at com.sun.xml.ws.encoding.StreamSOAPCodec.decode(StreamSOAPCodec.java:128)
	at com.sun.xml.ws.encoding.SOAPBindingCodec.decode(SOAPBindingCodec.java:287)
	at com.sun.xml.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:171)
	at com.sun.xml.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:86)
	at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:595)
	at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:554)
	at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:539)
	at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:436)
	at com.sun.xml.ws.client.Stub.process(Stub.java:248)

解決策:
jaxws-rtに依存することを増やして、この問題は解決しました!
 
異常二
 
java.lang.LinkageError: loader constraint violation: when resolving overridden method "com.sun.xml.ws.message.jaxb.AttachmentMarshallerImpl.addMtomAttachment(Ljavax/activation/DataHandler;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;" the class loader (instance of org/mortbay/jetty/webapp/WebAppClassLoader) of the current class, com/sun/xml/ws/message/jaxb/AttachmentMarshallerImpl, and its superclass loader (instance of <bootloader>), have different Class objects for the type javax/activation/DataHandler used in the signature
	at com.sun.xml.ws.message.jaxb.JAXBMessage.writePayloadTo(JAXBMessage.java:311)
	at com.sun.xml.ws.message.AbstractMessageImpl.writeTo(AbstractMessageImpl.java:142)
	at com.sun.xml.ws.encoding.StreamSOAPCodec.encode(StreamSOAPCodec.java:108)
	at com.sun.xml.ws.encoding.SOAPBindingCodec.encode(SOAPBindingCodec.java:258)
	at com.sun.xml.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:142)
	at com.sun.xml.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:86)
	at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:595)
	at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:554)
	at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:539)
	at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:436)
	at com.sun.xml.ws.client.Stub.process(Stub.java:248)
	at com.sun.xml.ws.client.sei.SEIStub.doProcess(SEIStub.java:135)
	at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:109)
	at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:89)
	at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:118)

解決策:
衝突を排除し、依存パケットはコンテナ内のjarパケットと衝突し、jaxws-rtとjaxws-springの依存からactivation 1を排除する.1.jar