基于JWS的WebService的两种发布方式及获取客户端IP的方法

本文介绍如何使用JAX-WS开发WebService,包括定义接口、实现接口、发布服务及客户端调用流程。涵盖发布方式的选择与具体实施步骤。

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

首先使用JAX-WS开发WebService

步骤:写接口–实现接口–发布–生成客户端(测试或者使用)
写接口
package service;

import java.util.Date;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;

/**
 * 作为测试的WebService接口
 * 
 * @author Johness
 * 
 */
@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)
public interface SayHiService {

    /**
     * 执行测试的WebService方法
     */
    @WebMethod
    void SayHiDefault();

    /**
     * 执行测试的WebService方法(有参)
     * 
     * @param name
     */
    @WebMethod
    void SayHi(@WebParam(name = "name") String name);

    /**
     * 执行测试的WebService方法(用于时间校验)
     * 
     * @param clentTime 客户端时间
     * @return 0表示时间校验失败 1表示校验成功
     */
    @WebMethod
    @WebResult(name = "valid")
    int CheckTime(@WebParam(name = "clientTime") Date clientTime);
}
实现接口
package service.imp;

import java.text.SimpleDateFormat;
import java.util.Date;

import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;

import service.SayHiService;

/**
 * 作为测试的WebService实现类
 * 
 * @author Johness
 * 
 */
@WebService(endpointInterface = "service.SayHiService")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class SayHiServiceImp implements SayHiService {

    @Override
    public void SayHiDefault() {
        System.out.println("Hi, Johness!");
    }

    @Override
    public void SayHi(String name) {
        System.out.println("Hi, " + name + "!");
    }

    @Override
    public int CheckTime(Date clientTime) {
        // 精确到秒
        String dateServer = new java.sql.Date(System.currentTimeMillis())
                .toString()
                + " "
                + new java.sql.Time(System.currentTimeMillis());
        String dateClient = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                .format(clientTime);
        return dateServer.equals(dateClient) ? 1 : 0;
    }

}
然后是发布

发布方式一般有两种:
1)以 Endpoint.publish 发布

package mian;

import javax.xml.ws.Endpoint;

import service.imp.SayHiServiceImp;

public class Main {

    /**
     * 发布WebService
     * 简单
     */
    public static void main(String[] args) {
        Endpoint.publish("http://localhost:8080/testjws/service/sayHi", new SayHiServiceImp());
    }

}

2)基于Web服务器Servlet方式发布
以Tomcat为例,首先编写 sun-jaxws.xml文件放到WEB-INF下:

<?xml version="1.0" encoding="UTF-8"?>
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
    version="2.0">
    <endpoint name="SayHiService"  //接口
        implementation="service.imp.SayHiServiceImpl"  //接口实现
        url-pattern="/service/sayHi" /> //发布的url的后缀
</endpoints>

然后改动web.xml ,添加listener和servlet(url-pattern 要和sun-jaxws.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" version="2.5">
    
    <listener>  
        <listener-class>
            com.sun.xml.ws.transport.http.servlet.WSServletContextListener  
        </listener-class>
    </listener>
    <servlet>
        <servlet-name>SayHiService</servlet-name>  
        <servlet-class>
            com.sun.xml.ws.transport.http.servlet.WSServlet  
        </servlet-class>
    </servlet>  
    <servlet-mapping>  
        <servlet-name>SayHiService</servlet-name>  
        <url-pattern>/service/sayHi</url-pattern>  
    </servlet-mapping>
    
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.htm</welcome-file>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

最后打包成war包,发布到tomcat上面,使用第二种发布方式,需要引入jar包:
在这里插入图片描述

注意:
  • 项目需要使用UTF-U编码(至少 sun-jsxws.xml 必须是UTF-8格式的);
  • 对于MyEclipse的内置Tomcat,可能会出现不需要手动添加上述jar包,但独立部署时需 要添加,因为它们使用的class-path不一样;
  • 多个不同路径的接口也要使用同一个WSServlet;
  • 最好加上@SOAPBinding(style=SOAPBinding.Style.RPC)注解

部署好以后,就可以输入网址:http://localhost:8080/testjws/service/sayHi?wsdl ,如果能看到东西,说明部署成功了;
其中 8080是tomcat端口号,testjws是项目名,service/sayHi是配置文件中的url-pattern

对应两种不同的发布方式,获取客户端真实IP的方法

想要获取到真实的IP,必须去获取HttpServletRequest对象

1)对于第一种发布方式,获取客户端ip方法(当存在多重代理时,无法获取真实IP):

@Resource
	private WebServiceContext webServiceContext;
MessageContext mc = webServiceContext.getMessageContext();
//第一种发布方式,只能获取的HttpExchange对象,因为获取HttpServletRequest为NULL
HttpExchange exchange = (HttpExchange)mc.get(JAXWSProperties.HTTP_EXCHANGE);
InetSocketAddress isa = exchange.getRemoteAddress();
ip = isa.getAddress().getHostAddress(); //如果有多重代理,则获取到的IP并非真实IP

2)对于第二种发布方式,获取IP的方法(可以获取真实IP):

@Resource
	private WebServiceContext webServiceContext;
MessageContext mc = webServiceContext.getMessageContext();
//第二种发布方式,是获取HttpServletRequest对象
HttpServletRequest request= (HttpServletRequest)(mc.get(MessageContext.SERVLET_REQUEST));
String ip = IPUtil.getIpAddr(request);

从request中获取真实IP的方法getIpAddr 的实现:

public static String getIpAddr(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
			// 多次反向代理后会有多个ip值,第一个ip才是真实ip
			if (ip.indexOf(",") != -1) {
				ip = ip.split(",")[0];
			}
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("X-Real-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值