首先使用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;
}