JWS实现WebService

本文详细介绍了使用Java JWS实现WebService的过程,包括@WebService、@WebMethod和@WebParam注解的使用,服务端和客户端的搭建方法,如直接在启动类开启服务、使用ApplicationContext事件机制、利用CXF消息总线发布等。此外,还讨论了客户端通过wsimport、JDK API、URLConnection和Ajax等方式创建和调用服务。
摘要由CSDN通过智能技术生成

    WebService估计大家都有听过或者使用过。Java有几种常用的方式实现webservice,本文主要是讨论JWS实现。

什么是webservice

    简单而言,webservice就是通过SOAP协议在Web上提供的服务,使用WSDL文件进行说明。其特点是走SOAP协议而不是http协议,且传输的数据格式是xml而不是字符串。因为xml的特性,webservice具有跨语言跨平台的特点,而且xml可以封装复杂的对象,甚至可以使用xml加密数据。但由于涉及xml解析,速度相对慢一些。

实现webservice的方式

    webservice分为服务端和客户端。服务端提供功能接口,客户端通过wsdl文件(xml格式)获取相关信息并调用接口。服务端搭建常用的方式有3种:JWS、Axis(Axis2)、CXF。客户端常用的调用方式有6种:wsimport、JDK提供的相关API、URLConnection、Ajax、axis、cxf。

    我们先了解一下JWS提供的一些注解:

@WebService

    @WebService:用于指定该类是webservice的服务器类。其属性值有:

  • serviceName:对外发布的服务名,对应wsdl:service,缺省值为Java类名+Service

  • endpointInterface:服务端点接口的完整, 指定SEI(Service EndPoint Interface)服务端点接口,一般使用接口在项目的相对路径

  • name:webservice的名称。在默认情况下,该值是实现XML webservice的类的名称,对应wsdl:portType 。缺省值为 Java 类或接口的非限定名称

  • portName:webservice的端口名称。对应wsdl:portName。缺省值为WebService.name+Port

  • targetNamespace:指定名称空间,一般使用接口实现类的包名的反缀

  • wsdlLocation:指定用于定义webservice的wsdl文档的 Web 地址,默认是发布地址+?wsdl。

@WebMethod

    @WebMethod:用于指定服务接口(SEI)上的方法,或JavaBeans 端点的服务器端点实现类。注意@WebMethod必须使用在@WebService注释的类中。其属性值有:

  • operationName:对应wsdl:opereation。即客户端调用时的方法名,可以理解为隐藏服务端实际的方法名而对外暴露用于调用的方法名。缺省值为方法名

  • action:定义此操作的行为。对于SOAP绑定,此值将确定SOAPAction头的值。缺省值为Java方法的名称

  • exclude:指定是否从WebService中排除某一方法。缺省值为false

@WebParam

    @WebParam:注释用于定制从单个参数至WebService消息部件和XML元素的映射。注意要用在SEI的方法,或JavaBeans 端点的服务器端点实现类。

  • name:参数的名称。如果不指定,参数名将会默认逐个替换成arg0、arg1…至argn(假设参数个数为n+1个)

  • partName:定义用于表示此参数的 wsdl:part属性的名称

  • targetNamespace:指定参数的XML名称空间。缺省值为WebService的targetNamespace

  • mode:参数的流向(IN、OUT、INOUT的一种)

  • header:指定参数是在消息头还是消息体中。缺省值为 false

搭建webservice服务端

    先创建一个springboot的项目,具体操作这里就省略了,大伙都懂得怎么搭建的。下面的案例就以查找学生成绩作为例子。

     idea提供快速搭建webservice项目的功能,虽然是很方便,但很多情况下都是在已有的项目中引用webservice,那么快速搭建项目的功能就显得不够灵活。这里就省略不说了。

    好了,我们看看怎么用JWS搭建webservice服务端吧~

服务接口和服务接口实现类

    为了方便后续客户端的调用,这里采用面向接口编程。

import com.javatest.po.StudentScore;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;/**
 * webservice服务端接口类
 */
@WebService
public interface JAXTestService {
   
    /**提供调用的方法,使用@WebMethod注释*/
    @WebMethod(operationName = "getStudentScoreById")
    StudentScore getStudentScore(@WebParam(name = "id") long id);
}

    创建对应的实现类。如果不采用面向接口编程,直接创建服务类也是可以的。

import com.javatest.po.StudentScore;
import com.javatest.service.StudentScoreService;
import com.javatest.webservice.server.JAXTestService;
import org.springframework.beans.factory.annotation.Autowired;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
​
/**
 * webservice服务端实现类。注意,如果使用面向接口,那么在此实现类中必须通过endpointInterface指定服务端接口类
 */
@WebService(targetNamespace = "http://impl.server.webservice.javatest.com/",    // 命名空间一般为包名的倒置
        endpointInterface = "com.javatest.webservice.server.JAXTestService"
)
@Service
public class JAXTestServiceImpl implements JAXTestService {
    @Autowired
    private StudentScoreService service;
    @Override
    public StudentScore getStudentScore(long id) {
        return service.selectByPrimaryKey(id);
    }
    // 发布服务
    public static void main(String[] args) {
        // 指定服务url
            String url = "http://localhost:9010/javatest/webservice/getJAX";
        // 指定服务实现类
        JAXTestService server = new JAXTestServiceImpl();
        // 通过Endpoint发布服务
        Endpoint.publish(url, server);
    }
}

    执行main方法就可以发布webservice了。在浏览器中输入http://localhost:9010/javatest/webservice/getJAX?wsdl,如果返回下图,则说明服务发布成功。
在这里插入图片描述
    这里要注意哦:wsdl文档在执行发布服务的方法后就已经确定,后续手动修改wsdl文档是无法生效的,需要重新发布。

不完美的优化

    上述的部署的方式有个弊端,一旦springboot项目部署,这个main方法就无法手动执行了,自然webservice的服务端就无法启动。首先想到的是在启动类上添加webservice,或者在开启服务的同时也开启webservice。但这样会存在端口冲突的问题。在不使用其他技术的前提下,找了很久也没有找到共用端口的方法。当然,用cxf的Springbus就能解决这个问题,这个在后面会讲述。
    注意:下面两种方式api接口和webservice不能共用同一个端口,相当于同时开启两个服务。

方法1:直接在启动类上开启webservice服务

    注意:SpringApplication.run必须写在webservice服务上面

@SpringBootApplication
@MapperScan("com.javatest.dao")
@ServletComponentScan
public class JavaTestApplication {
   
    public static void main(String[] args) {
   
        SpringApplication.run(JavaTestApplication.class);
        // 指定服务url,注意,配置的api接口的端口号与webservice接口的端口号不能一致
        String url = "http://localhost:9011/javatest/webservice/getJAX";
        // 指定服务实现类
        JAXTestService server = new JAXTestServiceImpl();
        // 通过Endpoint发布服务
        Endpoint.publish(url, server);
    }
}
方法2:使用ApplicationContext事件机制。

    创建一个ApplicationListener的子类,配置webservice服务。
    注意:使用该方法时,webservice的实现类可以用@Service注解。而前述的ApplicationListener子类则必须用@Service,@Component或者@Configuration注解,以便交给Spring容器管理

import com.javatest.webservice.server.impl.JAXTestServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import javax.xml.ws.Endpoint;@Configuration
public class WebServiceApplication implements ApplicationListener<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值