当前位置 : 主页 > 网页制作 > Nodejs >

4.6Webservice

来源:互联网 收集:自由互联 发布时间:2021-06-24
个人印象笔记 在Web工程中发布Webservice WebService的安全设置即webservice的头部消息处理 Handler处理链的使用 1:在Web工程中发布Webservice: 1.1方法一: 先建一个Web工程,然后把要发布的Webse
个人印象笔记
在Web工程中发布Webservice WebService的安全设置即webservice的头部消息处理 Handler处理链的使用 1:在Web工程中发布Webservice: 1.1方法一: 先建一个Web工程,然后把要发布的Webservice的接口和实现类拷到Web工程的一个包下,并且 在接口类前加上 @SOAPBinding(style = SOAPBinding.Style.RPC)。 再写一个监听器,用来发布Webservice的,它会在工程启动的时候,自动发布我们的Webserice服务。 (建立监听器的步骤:建一个java类且实现ServletContextListener,然后实现contextInitialized()和contextDestroyed这两个函数,最后要在web.xml中配置 <listener><listener-class>com.listener.PublishServiceListener</listener-class></listener>)。 注意:这时候有个问题,就是当我们访问的时候,如果我们访问的是Webservice里的方法,就得访问 http://localhost:7070/first, 如果我们访问的方法是部署在Tomcat下的方法,就得访问 http://localhost:8080这个地址。 这样有个麻烦就是我们得记住两个端口号。 监听器的代码:
package com.listener;
import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.xml.ws.Endpoint;
import com.webservice.First;
/**  * 用于发布WebService  *  * @author ctd  *  */ public class PublishServiceListener implements ServletContextListener {
@Override public void contextInitialized(ServletContextEvent arg0) { System.out.println("工程初始化的操作"); /** * 发布WebService */ Endpoint.publish("http://localhost:7070/first", new First()); System.out.println("通过WEB的方式发布Fist服务成功"); } @Override public void contextDestroyed(ServletContextEvent arg0) {      System.out.println("工程销毁的操作"); }
}
客户端调用类:
package com.test;
import java.io.IOException;
import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils;
public class TestMain { public static void main(String[] args) { TestMain.callServlet(); TestMain.callService(); }
private static void callServlet() { DefaultHttpClient httpClient = new DefaultHttpClient(); String url = "http://localhost:8080/WebService_Server_04/servlet/TestServlet"; HttpGet httpGet = new HttpGet(url);
try { HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
System.out.println("enity = " + entity); String responseStr = EntityUtils.toString(entity);
System.out.println(responseStr); } catch (Exception e) { e.printStackTrace(); } }
private static void callService() {
DefaultHttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost("http://localhost:7070/first?wsdl");
try {
StringBuffer soapXML = new StringBuffer(); soapXML .append("<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">"); soapXML.append("<SOAP-ENV:Header/>"); soapXML.append("<SOAP-ENV:Body>"); soapXML.append("<ns:add xmlns:ns=\"http://webservice.com/\">");//这里的命名空间要和你自己的对应 soapXML.append("<x>11</x>"); soapXML.append("<y>55</y>"); soapXML.append("</ns:add>");
soapXML.append("</SOAP-ENV:Body>"); soapXML.append("</SOAP-ENV:Envelope>");
StringEntity soapEntity = new StringEntity(soapXML.toString()); httpPost.setEntity(soapEntity); httpPost.setHeader("Content-Type", "text/xml; charset=UTF-8"); HttpResponse response = httpClient.execute(httpPost); HttpEntity entity = response.getEntity(); String str = EntityUtils.toString(entity);
//System.out.println("str = " + str);
String addResult = str.substring(str.indexOf("<addResult>") + 11, str.indexOf("</addResult>")); System.out.println("addResult = " + addResult);
} catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); }
} }
1.2方法二: 服务端: Webservice和Web工程是合在一起的。 步骤:      这时要建立一个Web Service Project (optional Maven support)(不选加入Maven)工程,写一个Servlet类,运行看是否可以正常运行。然后建一个包名叫sss.webservice,在这个包里写一个实现类Login类,当要发布这个类的时候,右击这个包,选择New Web Service,然后根据自己的情况选择Strategy(假设选第二个),点击下一步。等到完成时,会生成一个代理类( 这个代理类才是WebService.Web service不一定要用接口,只是推荐使用接口而已.)和一个WSDL文件和Sun-jaxws.xml,然后Web.xml里会多了这些东西:
  //WSServlet这个类是帮助我们在Web工程中发布Web service的时候用到的   //它最主要的任务是发布webservice <servlet> <servlet-name>PubSerivceServlet</servlet-name> <servlet-class> com.sun.xml.ws.transport.http.servlet.WSServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>PubSerivceServlet</servlet-name> <url-pattern>/LoginPort</url-pattern> </servlet-mapping>

注意:其中 com.sun.xml.ws.transport.http.servlet.WSServlet 这个类jdk里是没有的,所以得自己加jar包 就是 导入了myeclipse 的两个libraries就可以了,步骤: 工程上右键-》properties-》java build path -》 add libraries -》 选myeclipse libraries -》next 拉到最后选择最后两个库(jax-ws runtime 和 jax-ws api)。 最后像平常发布Web工程那样发布就好了,访问正常的Servlet还是和平常一样,访问Webservice时,后面得加 /LoginPort 这个( <url-pattern>/LoginPort</url-pattern>)。 前面说的这些,主要是解决两个端口变为一个端口的问题而已,这两种方式都可以用。 客户端调用:和平常的类似。
2、WebService的安全设置即webservice的头部消息处理
3种方案      2.1名称/密码 直接定义在方法中。(String content,String userid,String password);(最常用)
     2.2名称/密码 不定义在方法中。 (Soap消息,分为head和body):                     2.2.1:放在显示的header消息中                     2.2.2:放在隐示的header消息中 2.1:直接定义在方法上:      建工程名叫webservice06,在里面建一个包,在包里建一个实现类叫header_one,实现代码如下:
package sss.webservice;
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.HashMap; import java.util.Map;
import com.google.gson.Gson; import com.util.JdbcUtil;
public class Header_One { public static Map<String, String> systemMap = new HashMap<String, String>();
static { systemMap.put("OA", "111111"); systemMap.put("CRM", "222222"); systemMap.put("ERP", "33333"); }
public String login(String username, String password, String systemIdentity, String systemToken) { if ((systemIdentity == null || systemIdentity.equals("")) || (systemToken == null || systemToken.equals(""))) { throw new RuntimeException("服务端异常:系统标识与系统令牌不能为空 "); } else { if (systemMap.containsKey(systemIdentity) == false) { throw new RuntimeException("服务端异常:没有该系统标识 "); } else { String tempToken = systemMap.get(systemIdentity); if (systemToken.equals(tempToken) == false) { throw new RuntimeException("服务端异常:令牌与系统不匹配 "); } else { Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; String sql = null; Map<String, Object> jsonMap = new HashMap<String, Object>(); try { sql = "Select user_name,user_pw From T_user where user_name = ?"; conn = JdbcUtil.getConnection(); stmt = conn.prepareStatement(sql); stmt.setString(1, username); rs = stmt.executeQuery(); if (rs.next()) { String db_password = rs.getString("user_pw");
if (password.equals(db_password)) { jsonMap.put("flag", true); } else { jsonMap.put("flag", false); jsonMap.put("errorMsg", "密码不正确"); } } else { jsonMap.put("flag", false); jsonMap.put("errorMsg", "用户名不正确"); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("服务端异常 = " + e.getMessage()); } finally {
} Gson gson = new Gson(); String jsonStr = gson.toJson(jsonMap); return jsonStr; } } } } }
然后按照上面的方法二,在web工程中结合webservice的方法写好服务端。在客户端呢,就利用wsdl地址来生成客户端,并写测试类就好了。 服务端接口:
package com.webservice;
import javax.jws.WebParam; import javax.jws.WebResult;
@javax.jws.WebService(targetNamespace = "http://webservice.com/", serviceName = "Header_OneService", portName = "Header_OnePort") public class Header_OneDelegate {
com.webservice.Header_One header_One = new com.webservice.Header_One();
@WebResult(name = "loginResult") public String login(@WebParam(name = "username") String username, @WebParam(name = "password") String password, @WebParam(name = "systemIdentity") String systemIdentity, @WebParam(name = "systemToken") String systemToken) { return header_One .login(username, password, systemIdentity, systemToken); } } 客户端测试:
package com.webservice_client.header_one;
import javax.xml.ws.soap.SOAPFaultException;
public class TestMain { public static void main(String[] args) { HeaderOneDelegate headerOne = new HeaderOneService().getHeaderOnePort(); try { String jsonStr = headerOne.login("admin", "123", "OA", "111111"); System.out.println(jsonStr); } catch (SOAPFaultException e) { System.out.println(e.getMessage()); }
} }

 2.2.1:放在显示的header消息中 服务端的实现类和上面的Header_One是一样的,生成的接口类也是一样的,只是在参数要放在header里的@webparam里加了Header = true;代码如下:
package com.webservice;
import javax.jws.WebParam; import javax.jws.WebResult;
@javax.jws.WebService(targetNamespace = "http://webservice.com/", serviceName = "Header_TwoService", portName = "Header_TwoPort") public class Header_TwoDelegate {
com.webservice.Header_Two header_Two = new com.webservice.Header_Two();
@WebResult(name = "loginResult") public String login(@WebParam(name = "username") String username, @WebParam(name = "password") String password, @WebParam(name = "systemIdentity", header = true) String systemIdentity, @WebParam(name = "systemToken", header = true) String systemToken) { return header_Two .login(username, password, systemIdentity, systemToken); }
} 然后发布和客户端生成,都和上面的是一样的。只是测试类有所不同:
package com.webservice_client.header_two; //客户端测试类 public class TestMain { public static void main(String[] args) { HeaderTwoDelegate twoService = new HeaderTwoService() .getHeaderTwoPort();
Login parameters = new Login(); parameters.setUsername("admin"); parameters.setPassword("123"); LoginResponse loginResponse = twoService.login(parameters, "CRM", "222222"); String jsonStr = loginResponse.loginResult; System.out.println(jsonStr); } }
此外,生成的wsdl文件也有不同之处,详情请自己去比较吧!  2.2.2:放在隐示的header消息中:      2.2.2.1在此之前先讲一个 Handler的建立与使用(与过滤器和监听器类似)。      步骤:在上面的工程中,新建一个包叫com.webservice.handler,在里面建一个 PrintMessageHandler类,这个类得实现SOAPHandler<SOAPMessageContext>接口,重载它的方法。代码如下:
package com.webservice.handler;

import java.util.HashMap; import java.util.Map; import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.ws.handler.MessageContext; import javax.xml.ws.handler.soap.SOAPHandler; import javax.xml.ws.handler.soap.SOAPMessageContext;

public class PrintMessageHandler implements SOAPHandler<SOAPMessageContext> { public Set<QName> getHeaders() { System.out.println("getHeaders方法..."); return null; }
public void close(MessageContext arg0) { System.out.println("close方法..."); }
public boolean handleFault(SOAPMessageContext arg0) { System.out.println("handleFault方法..."); return false; }
public boolean handleMessage(SOAPMessageContext context) {
  System.out.println("handleMessage方法...."); return false; }
}
然后写一个名叫server_chain.xml的东西,里面的内容为
<?xml version="1.0" encoding="UTF-8"?> <javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <javaee:handler-chain> <javaee:handler> <javaee:handler-class>   com.webservice.handler.PrintMessageHandler </javaee:handler-class> </javaee:handler> </javaee:handler-chain> </javaee:handler-chains> 最后服务端要用这个处理类,就在接口类前写上@HandlerChain(file = "../../server_chain.xml")。客户端要用处理类,就得把这个写在实现类前。  2.2.2.2: 服务端:
package com.webservice; //实现类,和前面的是一样的。 import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.HashMap; import java.util.Map;
import com.google.gson.Gson; import com.util.JdbcUtil;
public class Header_Three { public String login_xx(String username, String password) { Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; String sql = null; Map<String, Object> jsonMap = new HashMap<String, Object>(); try { sql = "Select username,password From T_Userinfo where username = ?"; conn = JdbcUtil.getConn(); stmt = conn.prepareStatement(sql); stmt.setString(1, username); rs = stmt.executeQuery(); if (rs.next()) { String db_password = rs.getString("password");
if (password.equals(db_password)) { jsonMap.put("flag", true); } else { jsonMap.put("flag", false); jsonMap.put("errorMsg", "密码不正确"); } } else { jsonMap.put("flag", false); jsonMap.put("errorMsg", "用户名不正确"); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("服务端异常 = " + e.getMessage()); } finally { JdbcUtil.closeResource(rs, stmt, conn); } Gson gson = new Gson(); String jsonStr = gson.toJson(jsonMap); return jsonStr; }
}
生成的webservice是:因为要用到处理类,所有手动加了 @HandlerChain(file = "../../server_chain.xml")
package com.webservice;
import javax.jws.HandlerChain; import javax.jws.WebParam;
@javax.jws.WebService(targetNamespace = "http://webservice.com/", serviceName = "Header_ThreeService", portName = "Header_ThreePort") @HandlerChain(file = "../../server_chain.xml") public class Header_ThreeDelegate { com.webservice.Header_Three header_Three = new com.webservice.Header_Three();
public String login_xx(@WebParam(name = "username") String username, @WebParam(name = "password") String password) { return header_Three.login_xx(username, password); } } 服务端处理类的代码:
package com.webservice.handler;
import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Set;
import javax.xml.namespace.QName; import javax.xml.rpc.soap.SOAPFaultException; import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPFault; import javax.xml.soap.SOAPHeader; import javax.xml.soap.SOAPMessage; import javax.xml.ws.handler.MessageContext; import javax.xml.ws.handler.soap.SOAPHandler; import javax.xml.ws.handler.soap.SOAPMessageContext;
import org.w3c.dom.Element; import org.w3c.dom.NodeList;
public class PrintMessageHandler implements SOAPHandler<SOAPMessageContext> {
public static Map<String, String> systemMap = new HashMap<String, String>();
static { systemMap.put("OA", "111111"); systemMap.put("CRM", "222222"); systemMap.put("ERP", "33333"); }
public Set<QName> getHeaders() { System.out.println("getHeaders方法..."); return null; }
public void close(MessageContext arg0) { System.out.println("close方法..."); }
public boolean handleFault(SOAPMessageContext arg0) { System.out.println("handleFault方法..."); return false; }
public boolean handleMessage(SOAPMessageContext context) { System.out.println("handleMessage方法...");
Boolean is_out = (Boolean) context .get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY); if (is_out == true) { System.out.println("服务端返回消息:"); } else { System.out.println("服务端接收消息:"); }
SOAPMessage message = context.getMessage();
try { message.writeTo(System.out);
System.out.println(""); System.out.println(""); System.out.println(""); } catch (Exception e) { e.printStackTrace(); }
/** * 处理消息 */ if (is_out == false) { SOAPEnvelope envelope; try { envelope = message.getSOAPPart().getEnvelope(); SOAPHeader header = envelope.getHeader(); SOAPBody body = envelope.getBody(); SOAPFault fault = body.getFault(); if (fault == null) { fault = body.addFault(); }
System.out.println(header); NodeList nodeList = header.getElementsByTagName("checkinfo"); if (nodeList == null || nodeList.getLength() == 0) { System.out.println("checkinfo为空"); fault.setFaultCode("500"); fault.setFaultString("Header中的checkinfo节点为空值"); throw new javax.xml.ws.soap.SOAPFaultException(fault); } else { Element checkinfo = (Element) nodeList.item(0); String systemIdentity = checkinfo.getElementsByTagName( "systemIdentity").item(0).getFirstChild() .getNodeValue(); String systemToken = checkinfo.getElementsByTagName( "systemToken").item(0).getFirstChild() .getNodeValue();
System.out.println("systemIdentity = " + systemIdentity);
System.out.println("systemToken = " + systemToken);
if (systemMap.containsKey(systemIdentity) == false) { fault.setFaultCode("500"); fault.setFaultString("checkinfo中systemIdentity不正确"); throw new javax.xml.ws.soap.SOAPFaultException(fault); } else { String db_value = systemMap.get(systemIdentity); if (db_value.equals(systemToken) == false) { fault.setFaultCode("500"); fault.setFaultString("checkinfo中验证令牌不正确"); throw new javax.xml.ws.soap.SOAPFaultException( fault); } else { return true; }
} } } catch (SOAPException e) { e.printStackTrace(); } }
return true; }
}
客户端: 测试类代码:
package com.webservice_client.header_three;
import java.io.IOException;
import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils;
import sun.awt.windows.ThemeReader;
public class TestMain { public static void main(String[] args) { // TestMain.HttpClient_SendHeader();
TestMain.ClientStub_SendHeader(); }
/** * 通过客户端桩的方式来发送,这时就需要用到ClientHeaderChain这个处理链 */ private static void ClientStub_SendHeader() { HeaderThreeDelegate threeService = new HeaderThreeService() .getHeaderThreePort();
String jsonStr = threeService.loginXx("admin", "123");
System.out.println(jsonStr);
}
/** * 通过HttpClient来发送Soap中的Header消息 */ private static void HttpClient_SendHeader() {
DefaultHttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost( "http://localhost:8080/WebService_Server_06/Header_ThreeService?wsdl");
try {
StringBuffer soapXML = new StringBuffer(); soapXML .append("<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:web=\"http://webservice.com/\">"); soapXML.append("<soapenv:Header>");
soapXML.append("<checkinfo>"); soapXML.append("<systemIdentity>OA</systemIdentity>"); soapXML.append("<systemToken>111111</systemToken>"); soapXML.append("</checkinfo>"); soapXML.append("</soapenv:Header>");
soapXML.append("<soapenv:Body>"); soapXML.append("<web:login_xx>"); soapXML.append("<username>admin</username>"); soapXML.append("<password>1111</password>"); soapXML.append("</web:login_xx>");
soapXML.append("</soapenv:Body>"); soapXML.append("</soapenv:Envelope>");
StringEntity soapEntity = new StringEntity(soapXML.toString()); httpPost.setEntity(soapEntity); httpPost.setHeader("Content-Type", "text/xml; charset=UTF-8"); HttpResponse response = httpClient.execute(httpPost); HttpEntity entity = response.getEntity(); String str = EntityUtils.toString(entity);
System.out.println("str = " + str);
if (str.indexOf("<faultcode>") != -1) { /** * 说明有错误消息 */
String faultcode = str.substring( str.indexOf("<faultcode>") + 11, str .indexOf("</faultcode>"));
String faultstring = str.substring( str.indexOf("<faultstring>") + 13, str .indexOf("</faultstring>"));
System.out.println("faultCoe = " + faultcode); System.out.println("faultstring = " + faultstring); } else { /** * 正确 */
String result = str.substring(str.indexOf("<return") + 17, str .indexOf("</return>"));
System.out.println("result = " + result); }
} catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } }
客户端用到的处理类代码:建处理类的步骤如上。
package com.webservice_client.header_three;
import java.util.Set;
import javax.xml.namespace.QName; import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPHeader; import javax.xml.soap.SOAPHeaderElement; import javax.xml.soap.SOAPMessage; import javax.xml.ws.handler.MessageContext; import javax.xml.ws.handler.soap.SOAPHandler; import javax.xml.ws.handler.soap.SOAPMessageContext;
public class ClientHeaderChain implements SOAPHandler<SOAPMessageContext> { /** * 客户端要加入checkinfo的头部消息,供服务端解析 */ public boolean handleMessage(SOAPMessageContext context) { Boolean is_out = (Boolean) context .get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY); if (is_out == true) { /** * 加入Header消息 */ SOAPMessage message = context.getMessage(); try { SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); SOAPBody body = envelope.getBody(); SOAPHeader header = envelope.getHeader(); if (header == null) { header = envelope.addHeader(); } QName checkinfo = new QName("http://webservice.com/", "checkinfo"); SOAPHeaderElement checkInfoElement = header .addHeaderElement(checkinfo); checkInfoElement.addChildElement("systemIdentity").setValue( "CRM"); checkInfoElement.addChildElement("systemToken").setValue("222222");
} catch (SOAPException e) { e.printStackTrace(); } } return true; }
public Set<QName> getHeaders() { return null; }
public void close(MessageContext arg0) { }
public boolean handleFault(SOAPMessageContext arg0) { // TODO Auto-generated method stub return false; }
}
注意点:      比较合理的方式。通过SoapHandler来传递与接收头部消息。      抛异常不能使用throw new RuntimeException的方式,要使用throw new SOAPFaultException(fault);      从服务端角度看:inbound表示接收客户端消息,outbound表示响应消息给客户端..从客户端角度看时正好与之相反
上一篇:PostMan测试WebService
下一篇:4.5Webservice
网友评论