接了个webService的老项目,记录一下处理常见xml转化验证的处理工具方式
工具类XmlUtil
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.**.healthcardadapter.constant.ExceptionConstant;
import com。**.healthcardadapter.dto.request.RequestActionBaseDTO;
import com.**.healthcardadapter.exception.BusinessException;
import com.**.healthcardadapter.exception.ErrorCode;
import lombok.extern.slf4j.Slf4j;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
/**
* Description XmlUtil转化工具
*/
@Slf4j
public class XmlUtil {
/**
* 对象转XML
*
* @param obj 目标对象
* @return 返回string格式的xml报文
*/
public static String objToXml(Object obj) {
StringWriter sw = new StringWriter();
String result = null;
try {
JAXBContext context = JAXBContext.newInstance(obj.getClass());
Marshaller marshaller = context.createMarshaller();
// 去除换行
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, false);
// 除去xml的默认报文头部
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8";
// 处理字段为空值时候不返回不生成字段问题
marshaller.setListener(new Marshaller.Listener() {
@Override
public void beforeMarshal(Object source) {
Field[] fields = source.getClass().getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
try {
//对象为空且类型为String时候设置空值
if (f.getType() == String.class && f.get(source) == null) {
f.set(source, "");
}
} catch (IllegalAccessException e) {
e.printStackTrace();
log.error("对象转化xml处理空值字段时错误" + e.getMessage());
}
}
}
});
marshaller.marshal(obj, sw);
result = sw.toString();
} catch (JAXBException e) {
log.error("对象转XML异常:{}", e.getMessage());
throw BusinessException.create(ErrorCode.SystemDefaultCode.INTERNAL_SERVER_ERROR, ExceptionConstant.SYS_ERROR);
} finally {
try {
sw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return result;
}
/**
* Description xmlSring 转对象
*
* @param xmlStr xmlStr
* @param clazz clazz
* @return T
*
*/
public static <T> T fromXml(String xmlStr, Class<T> clazz) {
T result = null;
// 处理CDATA
if (StrUtil.isNotEmpty(xmlStr) && xmlStr.trim().startsWith("<![CDATA[") && xmlStr.trim().endsWith("]]>")) {
xmlStr = xmlStr.trim().substring(9, xmlStr.length() - 3);
}
StringReader reader = new StringReader(xmlStr);
try {
JAXBContext context = JAXBContext.newInstance(clazz);
Unmarshaller unmarshaller = context.createUnmarshaller();
result = (T) unmarshaller.unmarshal(reader);
} catch (JAXBException e) {
log.error("xml转对象异常:{}", e.getMessage());
throw BusinessException.create(ErrorCode.SystemDefaultCode.INTERNAL_SERVER_ERROR, ExceptionConstant.SYS_ERROR);
} finally {
reader.close();
}
return result;
}
public static void main(String[] args) {
String message ="<![CDATA[<request><msgGuid>7163D5BA71974456BFE7436D57F9F923 </msgGuid><msgType>1</msgType><msgCreateTime>2022-06-10 09:38:36</msgCreateTime><bussinessCode>RHC_E0005</bussinessCode><orgId>630000000000</orgId><appCode></appCode><userName>test</userName><userPwd>test123123123</userPwd><stdVerCode>1.0.0</stdVerCode></request>]]>";
RequestActionBaseDTO messageDTO = XmlUtil.fromXml(message, RequestActionBaseDTO.class);
System.out.println(JSONUtil.toJsonStr(messageDTO));
}
转化对象类,XmlJavaTypeAdapter xml转对象属性去除空格
@XmlRootElement(name = "request")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlJavaTypeAdapter(value = CollapsedStringAdapter.class)
@Data
public class RequestActionBaseDTO {
/**
* 消息标识符号
* 32位消息流水号,消息唯一标识
*/
@Length(max = 32)
@NotBlank
@XmlJavaTypeAdapter(value = CollapsedStringAdapter.class)
private String msgGuid;
/**
* 消息类别
* 标识消息的类别,
* 接口平台指定固定值为:1
*/
@Length(max = 7)
@NotBlank
@XmlJavaTypeAdapter(value = CollapsedStringAdapter.class)
private String msgType;
@Length(max = 50)
@NotBlank
@XmlJavaTypeAdapter(value = CollapsedStringAdapter.class)
private String bussinessCode;
/**
* 消息创建时间
* 消息创建时间为调用接口的当前时间,格式为YYYY-MM-DDHH:mm:ss
*/
@Length(max = 17)
@NotBlank
@DateTimeValidte
@XmlJavaTypeAdapter(value = CollapsedStringAdapter.class)
private String msgCreateTime;
@Length(max = 32)
@XmlJavaTypeAdapter(value = CollapsedStringAdapter.class)
private String orgId;
@Length(max = 6)
@XmlJavaTypeAdapter(value = CollapsedStringAdapter.class)
private String appCode;
@Length(max = 32)
@NotBlank
@XmlJavaTypeAdapter(value = CollapsedStringAdapter.class)
private String userName;
@Length(max = 32)
@NotBlank
@XmlJavaTypeAdapter(value = CollapsedStringAdapter.class)
private String userPwd;
/**
* 版本
*/
@Length(max = 1)
@NotBlank
@XmlJavaTypeAdapter(value = CollapsedStringAdapter.class)
private String stdVerCode;
@Length(max = 100)
@NotBlank
@XmlJavaTypeAdapter(value = CollapsedStringAdapter.class)
private String encryption;
}
java校验注解手动触发工具类
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.HibernateValidator;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Iterator;
import java.util.Set;
/**
* Description dto注解校验手动触发工具类
*
* @ClassName ValidatorUtils
*/
@Slf4j
public class ValidatorUtils {
private static Validator validatorFast = Validation.byProvider(HibernateValidator.class).configure().failFast(true).buildValidatorFactory().getValidator();
private static Validator validatorAll = Validation.byProvider(HibernateValidator.class).configure().failFast(false).buildValidatorFactory().getValidator();
/**
* 校验遇到第一个不合法的字段直接返回不合法字段,后续字段不再校验
* @param <T>
* @param domain
* @return
* @throws IllegalArgumentException
*/
public static <T> Set<ConstraintViolation<T>> validateFast(T domain) {
Set<ConstraintViolation<T>> validateResult = validatorFast.validate(domain);
if(validateResult.size()>0) {
log.error(validateResult.iterator().next().getPropertyPath() +":"+ validateResult.iterator().next().getMessage());
}
return validateResult;
}
/**
* 校验遇到第一个不合法的字段直接返回不合法字段,后续字段不再校验,返回webService错误信息
* @param <T>
* @param domain
*/
public static <T> String validateXmlFast(T domain) {
Set<ConstraintViolation<T>> validateResult = validatorFast.validate(domain);
if(validateResult.size()>0) {
return BusinessException.create(ResultCodeEnum.RESULT_CODE_1601, validateResult.iterator().next().getPropertyPath() +":"+ validateResult.iterator().next().getMessage());
}
return "";
}
/**
* 校验所有字段并返回不合法字段
* @param <T>
* @param domain
* @return
* @throws IllegalArgumentException
*/
public static <T> Set<ConstraintViolation<T>> validateAll(T domain) throws IllegalArgumentException {
Set<ConstraintViolation<T>> validateResult = validatorAll.validate(domain);
if(validateResult.size()>0) {
Iterator<ConstraintViolation<T>> it = validateResult.iterator();
while(it.hasNext()) {
ConstraintViolation<T> cv = it.next();
log.error(cv.getPropertyPath()+":"+cv.getMessage());
}
}
return validateResult;
}
public static void main(String[] args) {
String message = "<![CDATA[<request><id_card>632822197101030026</id_card><id_type>01</id_type></request>]]>";
RequestQueryQRMessageDTO messageDTO = XmlUtil.fromXml(message, RequestQueryQRMessageDTO.class);
// 注解手动触发基本校验测试
String validatorStr = ValidatorUtils.validateXmlFast(messageDTO);
if (StrUtil.isNotEmpty(validatorStr)) {
return validatorStr;
}
}
}