如何在Axis2生成的Web Service中为SOAP HTTP响应添加Header?
问题描述
我用Eclipse Mars工具,基于WSDL通过Apache Axis2生成了一个Web服务,部署在Tomcat 8.0上,包含自动生成的方法骨架、类型类,还有继承AbstractInOutMessageReceiver的InOut消息接收器。
目前所有请求返回的HTTP状态码都是200;如果发送缺少必填字段的XML请求,服务会返回500内部服务器错误,同时返回包含faultstring(ADBException)的XML。
我的服务实现逻辑写在骨架类里,现在需要在满足特定业务条件时返回HTTP 400状态码,但找不到设置HTTP响应头的地方——自动生成的响应对象只有字段和对应的setter方法。
自动生成的消息接收器里有invokeBusinessLogic方法,通过SOAPEnvelope对象发送响应,请问能不能给这个信封添加HTTP头?
补充代码示例
骨架类代码
public class GenServiceSkeleton { public TaskResponse taskResponse(TaskRequest request) { // 一些业务逻辑 // 示例代码 TaskResponse resp = new TaskResponse(); resp.setTask("1"); return resp; } }
其中TaskResponse是ADBBean的实现类。
消息接收器代码
public class GenServiceRecieverInOut extends org.apache.axis2.receivers.AbstractInOutMessageReceiver { public void invokeBusinessLogic(org.apache.axis2.context.MessageContext msgContext, org.apache.axis2.context.MessageContext newMsgContext) { try { // 获取Web服务的实现类实例 Object obj = getTheImplementationObject(msgContext); GenServiceSkeleton skel = (GenServiceSkeleton) obj; // 响应信封 org.apache.axiom.soap.SOAPEnvelope envelope = null; // .... // 以下是其他代码 // .... if("getTask".equals(methodName)){ TaskResponse taskResponse11 = null; TaskRequest wrappedParam = (TaskRequest)fromOM(msgContext.getEnvelope().getBody().getFirstElement(),TaskRequest.class); taskResponse11 = skel.taskResponse(wrappedParam); envelope = toEnvelope(getSOAPFactory(msgContext), taskResponse11, false,new javax.xml.namespace.QName("http://example.com", "TaskResponse")); } // .... } catch (Exception e) { // 异常处理 } } }
解决方案
1. 核心逻辑说明
SOAPEnvelope是SOAP协议层面的内容,HTTP头属于传输层,二者不属于同一层级,无法直接给信封添加HTTP头。要设置HTTP状态码,需要操作**MessageContext对象**。
2. 在骨架类中抛出自定义异常
在业务逻辑里触发需要返回400的条件时,抛出自定义异常,不要直接返回响应对象:
public class GenServiceSkeleton { public TaskResponse taskResponse(TaskRequest request) throws CustomBadRequestException { // 业务校验:比如必填字段缺失、参数非法等 if (request.getSomeRequiredField() == null || request.getSomeRequiredField().isEmpty()) { throw new CustomBadRequestException("必填字段someRequiredField缺失"); } // 正常业务逻辑 TaskResponse resp = new TaskResponse(); resp.setTask("1"); return resp; } } // 自定义异常类 public class CustomBadRequestException extends Exception { public CustomBadRequestException(String message) { super(message); } }
3. 在消息接收器中捕获异常并设置HTTP状态码
修改invokeBusinessLogic方法,捕获自定义异常后设置HTTP 400状态码,同时构造合法的SOAP Fault返回:
public class GenServiceRecieverInOut extends org.apache.axis2.receivers.AbstractInOutMessageReceiver { public void invokeBusinessLogic(org.apache.axis2.context.MessageContext msgContext, org.apache.axis2.context.MessageContext newMsgContext) { try { Object obj = getTheImplementationObject(msgContext); GenServiceSkeleton skel = (GenServiceSkeleton) obj; org.apache.axiom.soap.SOAPEnvelope envelope = null; if("getTask".equals(methodName)){ TaskRequest wrappedParam = (TaskRequest)fromOM(msgContext.getEnvelope().getBody().getFirstElement(),TaskRequest.class); TaskResponse taskResponse11 = skel.taskResponse(wrappedParam); envelope = toEnvelope(getSOAPFactory(msgContext), taskResponse11, false,new javax.xml.namespace.QName("http://example.com", "TaskResponse")); } // 将构造好的信封设置到响应MessageContext newMsgContext.setEnvelope(envelope); } catch (CustomBadRequestException e) { // 设置HTTP 400状态码 newMsgContext.setProperty(org.apache.axis2.context.MessageContextConstants.HTTP_RESPONSE_STATUS_CODE, 400); // 构造SOAP Fault返回给客户端 try { SOAPFactory soapFactory = getSOAPFactory(msgContext); SOAPFault fault = soapFactory.createFault(); fault.setFaultCode(new QName("http://example.com/errors", "BadRequest")); fault.setFaultString(e.getMessage()); newMsgContext.setEnvelope(soapFactory.createSOAPEnvelope(fault)); } catch (Exception ex) { ex.printStackTrace(); } } catch (Exception e) { // 其他异常保持原有500逻辑 newMsgContext.setProperty(org.apache.axis2.context.MessageContextConstants.HTTP_RESPONSE_STATUS_CODE, 500); e.printStackTrace(); } } }
4. 关键注意点
- HTTP状态码通过
MessageContext的setProperty方法设置,使用常量org.apache.axis2.context.MessageContextConstants.HTTP_RESPONSE_STATUS_CODE作为key,值为对应状态码整数。 - 即使设置了HTTP状态码,也必须构造合法的SOAP响应(或SOAP Fault),否则客户端可能无法正确解析响应内容。
- 自定义异常可精准标识业务错误场景,方便在消息接收器中区分不同错误类型,设置对应HTTP状态码。
内容的提问来源于stack exchange,提问作者xmm_581
相关产品推荐
相关产品推荐

