使用dubbo 框架 使用 validation 进行参数校验
首先创建类
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Getter
@Setter
@ToString
public class OrderDeductRequestInfo{
/** 订单号 */
@JsonProperty(value = "ORDER_NO")
@NotNull(message = "missing parameter orderNo")
private String orderNo;
}
其次创建接口 及 实现
@Path("/test")
@Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
@Produces({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8})
public interface SuningApi {
@POST
@Path("/pay")
HttpResponseInfo pay(@NotNull(message = "missing request body") OrderDeductRequestInfo info);
}
实现
@Slf4j
@Service(interfaceClass = cn.easysw.bts.suning.controller.api.SuningApi.class,validation = "true")
public class SuningApiImpl implements SuningApi{
@Override
public HttpResponseInfo pay(OrderDeductRequestInfo info){
return new HttpResponseInfo("测试");
}
}
注意创建实现时要开启 service 的 validation 属性
这是注解形式可以 可以使用 xml形式注册实现 开启 validation 属性
此时的 验证已有响应
下面我们进行响应优化做成自己想要的返回数据
我的返回实体
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class HttpResponseInfo{
/**交易状态码,000000 表示成功,非全0表示错误码*/
@JSONField(name = "RSPCD")
private String rspcd;
/**交易描述*/
@JSONField(name = "RSPMSG")
private String rspmsg;
/**响应体,交易定义有返回数据时,数据都在body结点下*/
@JSONField(name = "BODY")
private Object body;
public HttpResponseInfo(Object body){
this.body=body;
this.rspcd="000000";
this.rspmsg="success";
}
public HttpResponseInfo(String rspcd,String rspmsg){
this.body=null;
this.rspcd=rspcd;
this.rspmsg=rspmsg;
}
}
创建dubbo filter
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.protocol.rest.RpcExceptionMapper;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.lang.reflect.Field;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.constraints.NotNull;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.xml.bind.annotation.XmlElement;
import org.hibernate.validator.constraints.NotEmpty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RpcExceptionMapperSupport extends RpcExceptionMapper {
private static final Logger logger = LoggerFactory.getLogger(RpcExceptionMapper.class);
WarnExceptionMapper warnExceptionMapper = new WarnExceptionMapper();
public RpcExceptionMapperSupport() {
}
public Response toResponse(RpcException e) {
FailedResponse faild = null;
if (e.getCause() instanceof ConstraintViolationException) {
ConstraintViolationException cve = (ConstraintViolationException)e.getCause();
ConstraintViolation<?> cv = (ConstraintViolation)cve.getConstraintViolations().iterator().next();
String message = cv.getMessage();
if (message != null && message.length() != 0) {
if (this.isNeedMessageFormat(cv)) {
message = this.formatMessage(cv);
}
} else {
message = this.getDefaultMessage(cv);
}
faild = new HttpResponseInfo(40001, message);
}
return Response.status(Status.OK).entity(faild).type("application/json; charset=UTF-8").build();
}
private boolean isNeedMessageFormat(ConstraintViolation<?> cv) {
String template = cv.getMessageTemplate();
String message = cv.getMessage();
return message.length() > 0 && !message.equals(template) && message.indexOf("{field}") > 0;
}
private String formatMessage(ConstraintViolation<?> cv) {
String message = cv.getMessage();
String fieldName = this.getFieldName(cv);
return message.replace("{field}", fieldName);
}
private String getDefaultMessage(ConstraintViolation<?> cv) {
Object annotation = cv.getConstraintDescriptor().getAnnotation();
if (annotation instanceof NotNull) {
return "Missing parameter";
} else {
return annotation instanceof NotEmpty ? "Empty parameter" : "default";
}
}
private String getFieldName(ConstraintViolation<?> cv) {
String fieldName = cv.getPropertyPath().toString();
try {
Field field = cv.getRootBeanClass().getDeclaredField(fieldName);
XmlElement xmlAnnotation = (XmlElement)field.getAnnotation(XmlElement.class);
JsonProperty jsonAnnotation = (JsonProperty)field.getAnnotation(JsonProperty.class);
if (xmlAnnotation != null && xmlAnnotation.name() != null) {
return xmlAnnotation.name();
} else {
return jsonAnnotation != null && jsonAnnotation.value() != null ? jsonAnnotation.value() : field.getName();
}
} catch (SecurityException | NoSuchFieldException var6) {
var6.printStackTrace();
return fieldName;
}
}
}
接下来在配置中添加
<dubbo:protocol name="rest" port="${rest.protocol.port}"
threads="${rest.protocol.threads}" contextpath="${rest.protocol.contextpath}"
server="${rest.protocol.server}" accepts="${rest.protocol.accepts}"
serialization="${rest.protocol.serialization}"
extension=" cn.webapi.filter.RpcExceptionMapperSupport"/>
这时候返回出来的数据就是我们进行处理过的数据了