Java笔记-springframework.ws中拦截器的使用(SOAP)
這里首先說下客戶端攔截器。
這里要實現的效果
這里的打印都是在攔截器中打印的!
下面要介紹如下的東西,如何在攔截器中打印這些東西,其次是在攔截器中添加一個head
?
對應的Maven
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.16.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>demo</artifactId><version>0.0.1-SNAPSHOT</version><name>demo</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>wsdl4j</groupId><artifactId>wsdl4j</artifactId><version>1.6.1</version></dependency><dependency><groupId>org.springframework.ws</groupId><artifactId>spring-ws-core</artifactId><version>3.0.8.RELEASE</version></dependency><dependency><groupId>org.springframework.ws</groupId><artifactId>spring-ws-security</artifactId></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version></dependency><dependency><groupId>org.apache.ws.security</groupId><artifactId>wss4j</artifactId><version>1.6.19</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><groupId>org.jvnet.jaxb2.maven2</groupId><artifactId>maven-jaxb2-plugin</artifactId><version>0.14.0</version><executions><execution><goals><goal>generate</goal></goals></execution></executions><configuration><schemaLanguage>WSDL</schemaLanguage><generatePackage>com.example.demo.wsdl</generatePackage><schemas><schema><url>http://127.0.0.1:8080/ws/countries.wsdl</url></schema></schemas></configuration></plugin></plugins></build></project>在客戶端中連接器要實現ClientInterceptor接口:
@Component public class GlobalInterceptor implements ClientInterceptor {public final QName SessionID_QNAME = new QName("http://xml.example.com/ws/session", "sessionID");@Overridepublic boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {HttpLoggingUtils.logMessage("Client Request Message start", messageContext.getRequest());SoapMessage soapMessage = (SoapMessage) messageContext.getRequest();SoapHeaderElement soapHeaderElement = soapMessage.getSoapHeader().addHeaderElement(SessionID_QNAME);HttpLoggingUtils.logMessage("Client Request Message end", messageContext.getRequest());return true;}@Overridepublic boolean handleResponse(MessageContext messageContext) throws WebServiceClientException {HttpLoggingUtils.logMessage("Client Response Message", messageContext.getResponse());return true;}@Overridepublic boolean handleFault(MessageContext messageContext) throws WebServiceClientException {System.out.println("handleFault");return true;}@Overridepublic void afterCompletion(MessageContext messageContext, Exception e) throws WebServiceClientException {System.out.println("afterCompletion");}}這里可以在兩個地方加,如果僅僅是HTTP協議的,可以直接加。
如CountryClient.java
public class CountryClient extends WebServiceGatewaySupport {@Beanpublic Wss4jSecurityInterceptor securityInterceptor(){Wss4jSecurityInterceptor wss4jSecurityInterceptor = new Wss4jSecurityInterceptor();wss4jSecurityInterceptor.setSecurementActions("Timestamp UsernameToken");wss4jSecurityInterceptor.setSecurementUsername("admin");wss4jSecurityInterceptor.setSecurementPassword("secret");return wss4jSecurityInterceptor;}private static final Logger log = LoggerFactory.getLogger(CountryClient.class);public GetCountryResponse getCountry(String country) {GetCountryRequest request = new GetCountryRequest();request.setName(country);log.info("Requesting location for " + country);ClientInterceptor[] interceptors = new ClientInterceptor[] {new GlobalInterceptor()};getWebServiceTemplate().setInterceptors(interceptors);GetCountryResponse response = (GetCountryResponse) getWebServiceTemplate().marshalSendAndReceive("http://localhost:8080/ws/countries", request,new SoapActionCallback("http://spring.io/guides/gs-producing-web-service/GetCountryRequest"));return response;} }如果是要SSL雙向認證的建議在@Configuration中進行配置
@Configuration public class SoapConfig {private static final Resource KEYSTORE_LOCATION = new ClassPathResource("client.jks");private static final String KEYSTORE_PASSWORD = "cccccc";private static final String KEY_ALIAS = "client";@BeanJaxb2Marshaller marshaller(){Jaxb2Marshaller marshaller = new Jaxb2Marshaller();marshaller.setContextPath("com.example.myData");return marshaller;}@BeanKeyStoreFactoryBean keyStore(){KeyStoreFactoryBean factoryBean = new KeyStoreFactoryBean();factoryBean.setLocation(KEYSTORE_LOCATION);factoryBean.setPassword(KEYSTORE_PASSWORD);return factoryBean;}@BeanTrustManagersFactoryBean trustManagers(KeyStoreFactoryBean keyStore){TrustManagersFactoryBean factoryBean = new TrustManagersFactoryBean();factoryBean.setKeyStore(keyStore.getObject());return factoryBean;}@BeanHttpsUrlConnectionMessageSender messageSender(KeyStoreFactoryBean keyStore,TrustManagersFactoryBean trustManagers) throws Exception{HttpsUrlConnectionMessageSender sender = new HttpsUrlConnectionMessageSender();KeyManagersFactoryBean keyManagersFactoryBean = new KeyManagersFactoryBean();keyManagersFactoryBean.setKeyStore(keyStore.getObject());keyManagersFactoryBean.setPassword(KEYSTORE_PASSWORD);keyManagersFactoryBean.afterPropertiesSet();sender.setKeyManagers(keyManagersFactoryBean.getObject());sender.setTrustManagers(trustManagers.getObject());return sender;}@BeanCryptoFactoryBean cryptoFactoryBean() throws IOException{CryptoFactoryBean cryptoFactoryBean = new CryptoFactoryBean();cryptoFactoryBean.setKeyStoreLocation(KEYSTORE_LOCATION);cryptoFactoryBean.setKeyStorePassword(KEYSTORE_PASSWORD);return cryptoFactoryBean;}@BeanWss4jSecurityInterceptor securityInterceptor(CryptoFactoryBean cryptoFactoryBean) throws Exception {Wss4jSecurityInterceptor securityInterceptor = new Wss4jSecurityInterceptor();securityInterceptor.setSecurementActions("Signature");securityInterceptor.setSecurementUsername(KEY_ALIAS);securityInterceptor.setSecurementPassword(KEYSTORE_PASSWORD);securityInterceptor.setSecurementSignatureKeyIdentifier("DirectReference");securityInterceptor.setSecurementSignatureAlgorithm(WSS4JConstants.RSA_SHA1);securityInterceptor.setSecurementSignatureDigestAlgorithm(WSS4JConstants.SHA1);securityInterceptor.setSecurementSignatureCrypto(cryptoFactoryBean.getObject());return securityInterceptor;}@BeanMyDataClient myDataClient(Jaxb2Marshaller marshaller,HttpsUrlConnectionMessageSender messageSender,Wss4jSecurityInterceptor securityInterceptor){MyDataClient myDataClient = new MyDataClient();myDataClient.setInterceptors(new ClientInterceptor[]{securityInterceptor, new GlobalInterceptor()});myDataClient.setMessageSender(messageSender);myDataClient.setMarshaller(marshaller);myDataClient.setUnmarshaller(marshaller);return myDataClient;}@BeanMyUserClient myUserClient(Jaxb2Marshaller marshaller,HttpsUrlConnectionMessageSender messageSender,Wss4jSecurityInterceptor securityInterceptor){MyUserClient myUserClient = new MyUserClient();myUserClient.setInterceptors(new ClientInterceptor[]{securityInterceptor});myUserClient.setMessageSender(messageSender);myUserClient.setMarshaller(marshaller);myUserClient.setUnmarshaller(marshaller);return myUserClient;} }其中Client有2個!
一個是MyDataClient.java
public class MyDataClient extends WebServiceGatewaySupport {public GetMyDataResponse getMyDataResponse(Integer id){GetMyDataRequest request = new GetMyDataRequest();request.setId(id);return (GetMyDataResponse) getWebServiceTemplate().marshalSendAndReceive("https://localhost:8080/ws/myData", request);} }一個是MyUserClient.java
public class MyUserClient extends WebServiceGatewaySupport {public GetUserResponse getUserResponse(String usrName, String password){GetUserRequest request = new GetUserRequest();request.setName(usrName);request.setPassword(password);return (GetUserResponse) getWebServiceTemplate().marshalSendAndReceive("https://localhost:8080/ws/myData", request);} }下面是關于與在攔截器中對每次發送添加一個頭:
@Overridepublic boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {HttpLoggingUtils.logMessage("Client Request Message start", messageContext.getRequest());SoapMessage soapMessage = (SoapMessage) messageContext.getRequest();SoapHeaderElement soapHeaderElement = soapMessage.getSoapHeader().addHeaderElement(SessionID_QNAME);soapHeaderElement.setText("12345678");HttpLoggingUtils.logMessage("Client Request Message end", messageContext.getRequest());return true;}首先將messageContext.getRequest()轉成SoapMessage。
隨后getSoapHeader()獲取頭,再addHeaderElement()添加頭部這里需要QName。
目前我這邊是這么填寫QName的:
public final QName SessionID_QNAME = new QName("http://xml.example.com/ws/session", "sessionID");如果要里面填寫值,addHeaderElement()后返回一個SoapHeaderElement,只需要調用其setText()即可。
?
下面是如何打印那些數據,這里我用了工具類:
@Overridepublic boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {HttpLoggingUtils.logMessage("Client Request Message start", messageContext.getRequest());................HttpLoggingUtils.logMessage("Client Request Message end", messageContext.getRequest());return true;}其中代碼如下:
public class HttpLoggingUtils extends TransformerObjectSupport {private static final Logger LOGGER = LoggerFactory.getLogger(HttpLoggingUtils.class);private static final String NEW_LINE = System.getProperty("line.separator");private HttpLoggingUtils() {}public static void logMessage(String id, WebServiceMessage webServiceMessage) {try {ByteArrayTransportOutputStream byteArrayTransportOutputStream =new ByteArrayTransportOutputStream();webServiceMessage.writeTo(byteArrayTransportOutputStream);String httpMessage = new String(byteArrayTransportOutputStream.toByteArray());LOGGER.info(NEW_LINE + "----------------------------" + NEW_LINE + id + NEW_LINE+ "----------------------------" + NEW_LINE + httpMessage + NEW_LINE);} catch (Exception e) {LOGGER.error("Unable to log HTTP message.", e);}} }這里的ByteArrayTransportOutputStream為:
public class ByteArrayTransportOutputStream extends TransportOutputStream {private static final String NEW_LINE = System.getProperty("line.separator");private ByteArrayOutputStream byteArrayOutputStream;@Overridepublic void addHeader(String name, String value) throws IOException {createOutputStream();String header = name + ": " + value + NEW_LINE;byteArrayOutputStream.write(header.getBytes());}@Overrideprotected OutputStream createOutputStream() throws IOException {if (byteArrayOutputStream == null) {byteArrayOutputStream = new ByteArrayOutputStream();}return byteArrayOutputStream;}public byte[] toByteArray() {return byteArrayOutputStream.toByteArray();} }?
下面是服務端的攔截器。
構造服務端連接器要實現EndpointInterceptor類
@Component public class GlobalEndpointInterceptor implements EndpointInterceptor {private static final Log LOG = LogFactory.getLog(GlobalEndpointInterceptor.class);@Overridepublic boolean handleRequest(MessageContext messageContext, Object o) throws Exception {LOG.info("GlobalEndpointInterceptor handleRequest");System.out.println("GlobalEndpointInterceptor handleRequest");return true;}@Overridepublic boolean handleResponse(MessageContext messageContext, Object o) throws Exception {LOG.info("GlobalEndpointInterceptor handleResponse");System.out.println("GlobalEndpointInterceptor handleResponse");return true;}@Overridepublic boolean handleFault(MessageContext messageContext, Object o) throws Exception {LOG.info("GlobalEndpointInterceptor handleFault");System.out.println("GlobalEndpointInterceptor handleFault");return true;}@Overridepublic void afterCompletion(MessageContext messageContext, Object o, Exception e) throws Exception {LOG.info("GlobalEndpointInterceptor afterCompletion");System.out.println("GlobalEndpointInterceptor afterCompletion");} }在config中配置即可
@EnableWs @Configuration public class WebServiceConfig extends WsConfigurerAdapter {@Beanpublic ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {MessageDispatcherServlet servlet = new MessageDispatcherServlet();servlet.setApplicationContext(applicationContext);servlet.setTransformWsdlLocations(true);return new ServletRegistrationBean(servlet, "/ws/*");}@Bean(name = "countries")public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();wsdl11Definition.setPortTypeName("CountriesPort");wsdl11Definition.setLocationUri("/ws");wsdl11Definition.setTargetNamespace("http://it1995.com/example/demo");wsdl11Definition.setSchema(countriesSchema);return wsdl11Definition;}@Beanpublic XsdSchema countriesSchema() {return new SimpleXsdSchema(new ClassPathResource("countries.xsd"));}@Overridepublic void addInterceptors(List<EndpointInterceptor> interceptors) {interceptors.add(new GlobalEndpointInterceptor());} }下面提下,如何在攔截器中獲取客戶端發來的頭
這里給出一個例子:
@Overridepublic boolean handleRequest(MessageContext messageContext, Object o) throws Exception {SoapMessage soapMessage = (SoapMessage) messageContext.getRequest();..............................SoapHeader soapHeader = soapMessage.getSoapHeader();Iterator<SoapHeaderElement> qn = soapHeader.examineAllHeaderElements();while (qn.hasNext()) {SoapElement elem = qn.next();QName name = elem.getName();String localPart = name.getLocalPart();if(localPart.equals("userToken")){String text = ((SoapHeaderElement) elem).getText();........................}}throw new Exception("無UserToken");}?
總結
以上是生活随笔為你收集整理的Java笔记-springframework.ws中拦截器的使用(SOAP)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux笔记-为操作系统配ntp服务地
- 下一篇: Android逆向笔记-IDA Pro动