之前一直用web service,不过一直用的都是客户端调用服务端,没做过服务端的开发,突然好奇,就简单的做了一个服务器端。
先说说一般的做法,再说说结合spring的。
先新建工程,把xfire 的jar包加入工程,
新建一个接口
package com.winit.service;
import com.winit.entity.Book;
/**
?* Interface definition book
?* @author Winit
?*这个接口就是对外开放的接口
?*/
public interface IBookService {
public String readBook(String bookName,String author);
?
public String getBook(int bookId);
}
package com.winit.service.imp;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.winit.entity.Book;
import com.winit.service.IBookService;
/**
?* 这个就是要具体做什么操作的类
?* @author Winit
?*?
?*/
public class BookService implements IBookService {
? ? ? @Override
public String readBook(String bookName,String author) {
return null;
}
@Override
public String getBook(int bookId) {
System.out.println("bookId-------------"+bookId);
?return "ok";
}
}
然后在webroot -->META-INF目录下新建文件夹xfire,在该目录下新建services.xml .该文件内容如下
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<service xmlns="http://xfire.codehaus.org/config/1.0"
? ? ? ? ?xmlns:s="http://www.springframework.org/schema/beans"
? ? ? ? ?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
? ? ? ? ?xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.8.xsd">
<name>BookService</name>
<serviceClass>com.winit.service.IBookService</serviceClass>
<implementationClass>com.winit.service.imp.BookService</implementationClass>
<style>wrapped</style>
<use>literal</use>
<scope>application</scope>
</service>
</beans>
这里可能会出现目录找不到,就需要将文件夹和文件一起拷贝到classes目录下。
配置web.xml 的代码
? ? ? ?<servlet>
<servlet-name>XFireServlet</servlet-name>
<servlet-class>org.codehaus.xfire.transport.http.XFireConfigurableServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/servlet/XFireServlet/*</url-pattern>
</servlet-mapping>
测试启动tomcat,通过http://localhost:post/工程名/services ? ?,大致是这样做的,如有不对的地方,可以留言交流。
下面来说说结合spring 发布webservices,加入相应的spring jar包
?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:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="?
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd?
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd?
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd?
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<import resource="classpath:org/codehaus/xfire/spring/xfire.xml" />
<bean id="baseWebService" class="org.codehaus.xfire.spring.remoting.XFireExporter"
lazy-init="false" abstract="true">
<property name="serviceFactory" ref="xfire.serviceFactory"></property>
<property name="xfire" ref="xfire"></property>
</bean>
<bean name="bookWS" class="com.winit.service.imp.BookService"></bean>
<bean id="bookService" parent="baseWebService">
<property name="serviceBean" ref="bookWS"></property>
<property name="serviceClass" value="com.winit.service.IBookService"></property>
</bean>
</beans>
web.xml文件的配置
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>xfire</servlet-name>
<servlet-class>org.codehaus.xfire.spring.XFireSpringServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>xfire</servlet-name>
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
测试启动tomcat,通过http://localhost:post/工程名/services ? ?,大致是这样做的,如有不对的地方,可以留言交流。
仅供参考。
xfire webService 加入用户名密码验证
1.需要的jar包
???????除了xfire和spring必要的包外?还需要?wss4j-1.5.1.jar?和?commons-codec-1.3.jar
2.servicebean配置如下
<bean?name="ticketcheckService"?class="org.codehaus.xfire.spring.ServiceBean">
???????<property?"serviceBean"?ref="ticketcheckWS"?/>
"name"?value="checkTicket"></property>
"serviceClass"
???????????"ticketcheck.service.IticketCheck"?/>
"inHandlers">
???????????<list>
??????????????<ref?bean="addressingHandler"?/>
?????????? ????<"domInHandler"?/>
"wss4jHandler"?/>
???????????</ ???????</
? ? ??<"properties">
? ? ? ? ??<props>
<!-- 等待HttpConnectionManager从连接池中返回空闲连接的超时时间 -->
<prop?key="http.connection.manager.timeout">2000</prop>
<!-- 等待建立连接的超时时间 -->
<key="http.connection.manager.timeout">3000</prop>
<!-- 等待服务器返回数据超时时间 -->
<>5000</prop>
<!-- 连接到单个服务器的连接数上限 -->
>10</prop>
<!-- 连接到所有服务器的连接个数上限 -->
>30</prop>
??? ?</props>
???????</property>
????</bean>
?
????<id="addressingHandler"?"org.codehaus.xfire.addressing.AddressingInHandler"?/>
"domInHandler"?"org.codehaus.xfire.util.dom.DOMInHandler"?/>
???
"wss4jHandler"??"org.codehaus.xfire.security.wss4j.WSS4JInHandler"??>
"properties">
??? ????????<!--
??? ??????? <props>
??? ??????? <prop key="action">UsernameToken</prop>
??? ??????? <prop key="passwordCallbackClass">ticketcheck.service.impl.PasswordHandlerImpl</prop>
??? ??????? </props>
??? ??????? ?-->
??? ???????<map>
??? ?????? ??<entry?key="action"?"UsernameToken"></entry>
"passwordCallbackRef"?value-ref="securityHandler"?>??</ ??? ???????</ ????????</property>
?????</bean>
"securityHandler"?"ticketcheck.service.impl.PasswordHandlerImpl">
"userInfo">
"user1"?"pwd1"></"user2"?"pwd2"></bean>
这里?在wss4jHandler配置中原先?用<props>?是无法实现passwordCallback的bean?注入(应用properties值都是字符的所以passwordCallbackRef?在<props>中是不起作用的)
下面就是实现securityHandler
?
3.PasswordHandlerImpl
?
import?java.io.IOException;
import?java.util.HashMap;
import?org.apache.ws.security.WSConstants;
import?org.apache.ws.security.WSPasswordCallback;
import?org.apache.ws.security.WSSecurityException;
import?javax.security.auth.callback.Callback;
import?javax.security.auth.callback.CallbackHandler;
import?javax.security.auth.callback.UnsupportedCallbackException;
/**
?*?验证用户密码
*/
public?class?PasswordHandlerImpl?implements?CallbackHandler {
????private?HashMap<String,String>?userInfo?;?//保存的用户名密码信息?
void?setUserInfo(HashMap<String,String>?userInfo) {
???????this.userInfo?=?userInfo;
??? }
void?handle(Callback[] callbacks)?throws?IOException,
?????????? UnsupportedCallbackException {
?????? WSPasswordCallback callback = (WSPasswordCallback) callbacks[0];获取回调对象
?????? String id = callback.getIdentifer();//获取用户名
String validPw =?userInfo.get(id);
if(validPw ==?null){
???????????throw?new?WSSecurityException("no such user");
?????? }
if?(WSConstants.PASSWORD_TEXT.equals(callback.getPasswordType())) {如果是明文密码直接进行判断?
?????????? String pw = callback.getPassword();
if?(pw ==?null?|| !pw.equalsIgnoreCase(validPw)) {
??????????????"password not match");
?????????? }
?????? }?else?{如果是密码摘要,向回调设置正确的密码(明文密码)这段主要是在service客户端用到
?????????? callback.setPassword(validPw);
?????? }
??? }
}