前言
这篇说的是 自定义拦截器 通过自定义拦截器我们可以实现一些自定义的需求 还是非常灵活的
Server端代码
我们还是首先通过 getInInterceptors 来设置拦截器
在咱们的服务端代码中加入如下一行 这里的MyInterceptors是咱们自己需要创建的拦截器
jaxWsServerFactoryBean.getInInterceptors().add(new MyInterceptors());
拦截器类的内容 这里做的是一个比较简单认证 在我们的Soap消息中获取头部标签内的内容 因为是XML传输的吗 所以这里使用的XML的解析方式进行对应的解析 接受一个uname和pwd的参数这个参数是我们在客户端传递的 如果不匹配我们就抛出对应的错误 如果完全匹配 那么久通过拦截器的认证
同时我们是需要继承AbstractPhaseInterceptor类泛型为SoapMessage
super(Phase.PRE_INVOKE); 这句话的意思就是在之前调用的意思
public class MyInterceptors extends AbstractPhaseInterceptor<SoapMessage> {
public MyInterceptors() {
super(Phase.PRE_INVOKE);
}
public void handleMessage(SoapMessage message) throws Fault {
List<Header> headers = message.getHeaders(); //根据soap消息获取头部
if(headers == null && headers.size() == 0) {
throw new Fault(new IllegalArgumentException("没有Header,拦截器实施拦截"));
}
Header firstHeader = headers.get(0); //我们等会只传一个头部过来
Element elm = (Element) firstHeader.getObject();//将该头部转成一个Element对象
NodeList userList = elm.getElementsByTagName("uname"); //根据标签获取值
NodeList pwdList = elm.getElementsByTagName("pwd");
// 进行身份认证
if(userList.getLength() != 1) {//只有一个用户
System.out.println("uname format error !");
throw new Fault(new IllegalArgumentException("用户名格式不对"));
}
if(pwdList.getLength() != 1) {//只有一个密码
System.out.println("pwd format error !");
throw new Fault(new IllegalArgumentException("密码格式不对"));
}
String username = userList.item(0).getTextContent(); //因为就一个,所以获取第一个即可
String password= pwdList.item(0).getTextContent();
if(!username.equals("lwx") || !password.equals("123456")) {
System.out.println("username or password error !");
throw new Fault(new IllegalArgumentException("用户名或者密码错误"));
}
}
}
这里的话咱们的服务端代码就结束了
Client 端代码
下来修改客户端代码 其实差不多
也是需要首先要添加一个拦截器 只不过是再出的时候添加的
这里的构造器内的参数是我们需要传递过去认证的啦
client.getOutInterceptors().add(new MyInterpator("lwx", "123456"));
对应的还是 创建一个MyInterpator 类继承AbstractPhaseInterceptor类泛型为SoapMessage
在内部重写需要的方法 获取到 对应的 头部 然后在创建对应的元素添加到我们的头部中 携带到服务端 服务端获取之后进行认证即可
super(Phase.PREPARE_SEND); 这是在准备发送我们的消息的时候调用的拦截器
public class MyInterpator extends AbstractPhaseInterceptor<SoapMessage> {
private String username;
private String password;
public MyInterpator(String username, String password) {
super(Phase.PREPARE_SEND); //准备发送soap消息的时候调用拦截器
this.username = username;
this.password = password;
}
@Override
public void handleMessage(SoapMessage soapMessage) throws Fault {
List<Header> headerList = soapMessage.getHeaders();
Document doc = DOMUtils.createDocument();
// 定义三个对象
Element elm = doc.createElement("authenticationHeader");
Element userElm = doc.createElement("uname");
Element pwdElm = doc.createElement("pwd");
// 给用户名和密码对象赋值
userElm.setTextContent(username);
pwdElm.setTextContent(password);
// 将用户名和密码的对象添加到elm中
elm.appendChild(userElm);
elm.appendChild(pwdElm);
headerList.add(new Header(new QName("head"), elm));//往soap消息头部中添加这个elm元素
}
}
之后我们进行客户端的启动 调用服务端程序 如果你传入的uname和pwd不符合服务端要求 那么就会跑出对应的错误 我们可以通过看控制台就可以得出结果 对应的日志也是可以的
从下面的日志中可以看出我们的authenticationHeader中包含了咱们的uname和pwd
Inbound Message
----------------------------
ID: 3
Address: http://localhost/helloworld
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=UTF-8
Headers: {Accept=[*/*], Cache-Control=[no-cache], connection=[keep-alive], Content-Length=[287], content-type=[text/xml; charset=UTF-8], Host=[localhost], Pragma=[no-cache], SOAPAction=[""], User-Agent=[Apache-CXF/3.3.3]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header><authenticationHeader><uname>lwx</uname><pwd>123456</pwd></authenticationHeader></soap:Header><soap:Body><ns2:getAllUserRole xmlns:ns2="http://service.server.liwenxiang.top/"/></soap:Body></soap:Envelope>
--------------------------------------
一切正常的话咱们的返回时就会是如下了吧 这里还是参考咱们上一届的代码哦 不要迷惑这里 如要你的没有报错就万事大吉
Programmer,1
结语
下一篇就开始来说如何与Spring整合使用 ~
来源:https://blog.csdn.net/qq_39057639/article/details/102752469