hello,我又回来了,有没有想我啊,哈哈~~
不和大家扯皮,我今天就分享一下,我的webService的荆棘之路!!!
今天领导给我发布一个任务,任务是一个文档,如图所示
这个一看我以为是正常的webService风格的接口,一般的webService接口不都是http格式请求,可是今天的这个不是,这是要做一个API请求,我一听API请求,为什么不传json,要传xml???
最后才知道客户,就是这样要求的,没有办法,那好咱们也不用想的太多,是祸躲不过,直接开干!!
1.请求参数
既然请求参数也是xml,那么我们就需要建立一个承载体,也就是实体类,代码如下:
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.Date;
@XmlRootElement(name = "requestBody")
public class StatisticsInfoDailyRequest {
@NotBlank(message = "hospId不能是空")
private String hospId;
//@NotBlank(message = "wardId不能是空")
private String wardId;
//@NotBlank(message = "deptId不能是空")
private String deptId;
//@NotNull(message = "statisticsDate不能是空")
private Date statisticsDate;
public String getHospId() {
return hospId;
}
public void setHospId(String hospId) {
this.hospId = hospId;
}
public String getWardId() {
return wardId;
}
public void setWardId(String wardId) {
this.wardId = wardId;
}
public String getDeptId() {
return deptId;
}
public void setDeptId(String deptId) {
this.deptId = deptId;
}
public Date getStatisticsDate() {
return statisticsDate;
}
public void setStatisticsDate(Date statisticsDate) {
this.statisticsDate = statisticsDate;
}
}
这一点我一共使用了3个注解
- 1.@XmlRootElement
- 2.@NotBlank
- 3.@NotNull
- 4.message = “”
顺便给大家讲一下这个注解的意思,知道的大神权当我放屁~~~~~~~~~~ - 1 XmlRootElement 便于对象与xml文件之间的转换,有了这个注解,就可以实现对象和xml之间的互转,如果传递过来的是xml,可以直接自动转换为对象
- 2 NotBlank 判断这个字段是否为null 这个比较坑 只能判断字符串
- 3 NotNull 这个是可以判断时间等其他类型的
- 4 message 是如果当这个字段为null时,你需要返回一个字符,比如一句话“不能为null”
2.返回参数
返回参数就比较复杂了,因为我们需要包装好几层,如下:
<responseInfo>
<responseBody>
<statisticsList>
<statisticsInfo>
<deptId></deptId>
<hospId>ddae6162af1747dba538383b37eb64d3</hospId>
<statisticsDate>2020-01-18 14:54:00</statisticsDate>
<statisticsKey>06</statisticsKey>
<statisticsType>1</statisticsType>
<statisticsValue>7</statisticsValue>
<wardId>80e6da44d1d84aed8f67d33d027ea7fc</wardId>
</statisticsInfo>
</statisticsList>
</responseBody>
<responseHeader>
<code>0</code>
<msg>查询成功</msg>
</responseHeader>
</responseInfo>
也就是我的对象是在里面的第四层,也就是我需要包裹三层,好崩溃!!!!
但是我却忘记了一个技能 那就是注解 哈哈哈~~~
这个时候就需要用到 XmlElementWrapper注解了
我可以带大家看一下源码分析
我们看1处 这个是没有加XmlElementWrapper注解前是这个,但是加了之后 就多了一层之后2处可以看出来多包装了一层。
让大家看一下代码
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
@XmlRootElement(name = "responseBody")
@XmlAccessorType(XmlAccessType.FIELD)
public class StatisticsInfoDailyBody {
@XmlElementWrapper(name = "statisticsList")
private List<StatisticsInfoDailyDto> statisticsList;
public List<StatisticsInfoDailyDto> getStatisticsList() {
return statisticsList;
}
public void setStatisticsList(List<StatisticsInfoDailyDto> statisticsList) {
this.statisticsList = statisticsList;
}
public StatisticsInfoDailyBody(List<StatisticsInfoDailyDto> statisticsList) {
this.statisticsList = statisticsList;
}
public StatisticsInfoDailyBody() {
}
}
给list集合加上XmlElementWrapper注解之后 外层的list标签就不用在去建一个dto了,是不是很舒服 哈哈哈~~~~
- XmlAccessorType注解说明
XmlAccessType.FIELD:映射这个类中的所有字段到XML
XmlAccessType.PROPERTY:映射这个类中的属性(get/set方法)到XML
XmlAccessType.PUBLIC_MEMBER:将这个类中的所有public的field或property同时映射到XML(默认)
XmlAccessType.NONE:不映射
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="responseHeader")
public class ResponseHeader {
private String code;
private String msg;
public ResponseHeader() {
super();
}
public ResponseHeader(String code, String msg) {
super();
this.code = code;
this.msg = msg;
}
@XmlElement(name="code")
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@XmlElement(name="msg")
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
- XmlElement 注解说明
- 字段,方法,参数级别的注解。该注解可以将被注解的(非静态)字段,或者被注解的get/set方法对应的字段映射为本地元素,也就是子元素。
- 参数 name :用于指定映射时的节点名称,指定生成元素的名字,若不指定,默认使用方法名小写作为元素名。
- 参数 namespace : 指定映射时的节点命名空间
- 参数 required : 字段是否必须,默认为false
- 参数 nillable : 是否处理空数据,默认为false
- 参数 type : 定义该字段或属性的关联类型
这一点其实可以使用XmlAccessorType注解 但是是之前的老代码 没有去动它。
最后就是最外层的ResponseInfo
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "responseInfo")
@XmlAccessorType(XmlAccessType.FIELD)
public class StatisticsInfoDailyResponseInfo {
private StatisticsInfoDailyBody responseBody;
private ResponseHeader responseHeader;
public StatisticsInfoDailyResponseInfo() {
}
public StatisticsInfoDailyResponseInfo(ResponseHeader responseHeader) {
this.responseHeader = responseHeader;
}
public StatisticsInfoDailyResponseInfo(ResponseHeader responseHeader, StatisticsInfoDailyBody responseBody) {
this.responseBody = responseBody;
this.responseHeader = responseHeader;
}
public StatisticsInfoDailyBody getResponseBody() {
return responseBody;
}
public void setResponseBody(StatisticsInfoDailyBody responseBody) {
this.responseBody = responseBody;
}
public ResponseHeader getResponseHeader() {
return responseHeader;
}
public void setResponseHeader(ResponseHeader responseHeader) {
this.responseHeader = responseHeader;
}
}
最关键的一点就是 你参数的命名 就是你返回时 的参数的命名。
//如果responseInfo中的返回信息头 你参数命名为private ResponseHeader header;
那么返回的结果就是
<header>
<code>0</code>
<msg>????</msg>
</header>
//如果是private ResponseHeader responseHeader; 自己定义
<responseHeader>
<code>0</code>
<msg>????</msg>
</responseHeader>
最后就是最关键的一点 控制器 ,代码如下
@RestController("PatientController")
@Scope("prototype")
@RequestMapping("/patient")
public class PatientController {
@Autowired
private PatientInfoBusiness patientInfoBusiness;
@Sign(auth=false)
@Permission(auth=false)
@RequestMapping(value = "/ws/getStatisticsInfo", method = RequestMethod.POST,produces = {"application/xml;charset=UTF-8"})
public String getStatisticsInfo(@RequestBody @Valid StatisticsInfoDailyRequest requestInfo, BindingResult bindingResult) {
if(bindingResult.hasErrors()){
String collect = bindingResult.getAllErrors().parallelStream().map(i -> i.getDefaultMessage()).collect(Collectors.joining(";"));
return new ResponseInfo(new ResponseHeader(MessageCode.PARAM_WRONG.getCode(), collect), null).toXml();
}
try {
List<StatisticsInfoDailyDto> statisticsInfo = this.patientInfoBusiness.getStatisticsInfo(requestInfo);
ResponseHeader header = new ResponseHeader(MessageCode.SUCCESS.getCode() + "", "查询成功");
String responseBody = XmlHelper.listObj2xmlStr(statisticsInfo, "statisticsList", "statisticsInfo");
ResponseInfo responseInfo = new ResponseInfo(header, responseBody);
return responseInfo.toXml();
} catch (BusinessException e)
{
return new ResponseInfo(new ResponseHeader(e.getCode() + "", e.getMessage()), null).toXml();
} catch (Exception e)
{
return new ResponseInfo(new ResponseHeader(MessageCode.EXCEPTION_EXECUTE_FAIL.getCode() + "", "getLisSampleInfo 执行异常"), null).toXml();
}
}
}
- produces 代表出参返回的是什么类型
- @Valid 就是和NotBlank 一起使用的 验证字段是否为空
- BindingResult 里面装的就是验证结果 如果没有 那就是验证成功
如图 我们测试的结果 没有传 hospId
剩下就是拼接xml 返回完整结构的xml
今天 的分享就到这里 如果有什么疑问 欢迎交流 !!!
来源:CSDN
作者:幽幽先生
链接:https://blog.csdn.net/weixin_43897673/article/details/104032023