发表于: 2017-10-19 22:17:02

1 669


一.今天完成的主要事情

1.准备并讲解小课堂,总结接口中如何处理service返回的结果

1.背景介绍

写接口的时候,经常会有对service的操作,那service操作之后返回的结果该如何处理呢?

主要有以下三个问题:

对Service返回的结果是否要判空,为什么?

Service返回的结果是否需要打日志,为什么?

如果需要打日志,应该打什么样的日志,为什么?

2.知识剖析

主要从软件设计原则中的健壮性入手来谈谈自己的理解

健壮性是软件设计时非常重要的一个指标,是指软件对于规范要求以外的输入情况的处理能力。所谓健壮的系统是指对于规范要求以外的输入能够判断出这个输入不符合规范要求,并能有合理的处理方式

通俗点说就是不能只考虑正常情况,还要考虑异常情况.而且根据"墨菲定律",只要你能想到某种异常情况可能会发生,那么这种异常情况就一定会发生.所以这时候对异常情况的处理就至关重要,必不可少.

3.三个问题的解决方案

问题一:对Service返回的结果是否要判空,为什么?

答案是:绝大多数情况下都需要对Service返回的结果进行判空.

通常调用service之后返回的结果有两种用途:

一种是作为下一个操作的入参.在这种情况下就必须要判空

另外一种是作为最后的结果返回.在这种情况下还需要继续细分;如果这个结果可以为空,那么就不用判断,直接返回,如果这个结果不能为空,那么还要继续判断,并要处理异常情况.

问题二:Service返回的结果是否需要打日志,为什么?

答案:需要.目前在项目中,所有的从Service返回的结果都要打日志.这个问题很好理解,日志是我们了解程序运行,问题追踪的工具.如果从Service返回的结果不打日志,以后出现问题,我们就不能快速的定位到问题所在.

问题三:如果需要打日志,应该打什么样的日志,为什么?

答案:视情况而定

一种情况是数据是一个基本类型或者对象类型,比如通过条件获取ID,或者根据Id获取对象等.

这时还要分两种情况

1.我只需要该对象的属性,比如是否为空,具体返回的数据的值是什么,我们不关心的,就不需要在日志中打印返回的结果的值(代码举例,userController,用户实名接口)

2.我除了要判断该对象的属性,还需要用到该数据的值,比如作为结果返回,或者是作为下一步操作的入参,那么就需要在日志中打印结果,以后如果出现问题,能够方便我们进行调试.

对于第二种情况一般是直接打印这个对象即可,但还要注意不能将用户的敏感信息打印出来,比如说密码,身份证号之类的敏感信息(代码举例,userController,用户实名接口)

另外一种情况是数据是一个集合类型,比如数组,List等.

这种如果没有特殊需求,只需要打印List的长度即可,不需要将所有的list中数据的具体值记录日志,因为这样会特别影响性能,而且打印长度基本也满足了我们对日志功能的需求.(代码举例,producController,查询产品列表接口)

2.继续接口的编写

贴一个比较难一些的接口,查询用户投资的产品列表

/**
* 16. 查询用户投资产品列表
*
* @param
* @return
* @throws ServiceException
* @throws ServiceDaoException
*/

@RequestMapping(value = "/a/u/product/list", method = RequestMethod.GET)
public String getUserProductList(HttpServletRequest request,
HttpServletResponse response, ModelMap model, Integer page,
Integer size, Long userId, Integer productType) throws Exception {


log.info("getUserProductList() parameters : userId : " + userId + ", productType : " + productType);
if (page == null) {
page = 1;
}
if (size == null) {
size = 10;
}
int start = (page - 1) * size;
if (start < 0) {
start = 0;
}
log.info("pageList : page= " + start + " , size=" + size);

if (DataUtils.isNullOrEmpty(userId) || DataUtils.isNullOrEmpty(productType)) {
log.info("Parameters userId or productType can not be NULL");
model.addAttribute("code", -1000);
return "/common/failure";
}
if ((productType != 0) && (productType != 1)) {
log.info("Error parameter value. Error productType is: " + productType);
model.addAttribute("code", -1001);
return "/common/failure";
}


List<Long> productIds = new ArrayList<>();
List<Product> products;
UserProductRelation upr = null;
try {
List<Long> userProductRelationIds = userProductRelationService.getUserProductRelationIdsByUserId(userId,
0, Integer.MAX_VALUE);
log.info("get countUserProductRelationIdsByUserId size is : " + userProductRelationIds.size());
if (CollectionUtils.isEmpty(userProductRelationIds)) {
model.addAttribute("code", 0);
return "/common/success";
}

List<UserProductRelation> userProductRelations = userProductRelationService.getObjectsByIds(
userProductRelationIds);
log.info("get userProductRelation data size is : " + userProductRelations.size());

//找出除用户已经续投的所有产品
       if (productType == 0) {
//使用迭代器迭代List
           Iterator<UserProductRelation> it = userProductRelations.iterator();
while (it.hasNext()) {
upr = it.next();
//如果该记录的状态字段为NULL或是已经续投的产品,则从List中剔除
               if (DataUtils.isNullOrEmpty(upr.getStatus()) || upr.getStatus() == 3) {
it.remove();
continue;
}
//记录相应的产品ID
               if (DataUtils.isNotNullOrEmpty(upr.getProductId())) {
productIds.add(upr.getProductId());
}
}

log.info("get userProductRelation except continued investment products data size : " +
userProductRelations.size());
log.info("get product ids from userProductRelation size : " + productIds.size());
if (CollectionUtils.isEmpty(userProductRelations) || CollectionUtils.isEmpty(productIds)) {
model.addAttribute("code", 0);
return "/common/success";
}
} else {
//从常量表中获取投资到期提醒天数
           Long constantId = constantService.getConstantIdByStatus(0);
log.info("get constantIdByStatus, constantId is: " + constantId + ", status is :" + 0);
if (DataUtils.isNullOrEmpty(constantId)) {
log.info("Parameter constantId can not be NULL!");
model.addAttribute("code", -4);
return "/common/failure";
}
Constant constant = constantService.getObjectById(constantId);
log.info("get constant data by id, constant is: " + constant);
Integer remindDays = constant.getInvestRemindDays();
log.info("get field investRemindDays by constant, investRemindDays is: " + remindDays);
if (DataUtils.isNullOrEmpty(remindDays)) {
log.info("Field investRemindDays can not be NULL!");
model.addAttribute("code", -40002);
return "/common/failure";
}

//获取在售并且不限购的产品的IDList
           productIds = productService.getProductIdsByStatusOrderByLevel(1, 0, Integer.MAX_VALUE);
log.info("get countproductIdsByStatusOrderByLevel size is : " + productIds.size());
if (CollectionUtils.isEmpty(productIds)) {
log.info("Parameters productIds can not be NULL!");
model.addAttribute("code", -4);
return "/common/failure";
}
products = productService.getObjectsByIds(productIds);
log.info("get product data size is : " + products);

for (Product product : products) {
if (DataUtils.isNullOrEmpty(product.getLimited()) || product.getLimited() == 1) {
productIds.remove(product.getId());
continue;
}
}
log.info("After filter, product ids size is: " + productIds.size());

Long nowTime = System.currentTimeMillis();
Iterator<UserProductRelation> iterator = userProductRelations.iterator();
while (iterator.hasNext()) {
upr = iterator.next();
//如果该记录的状态字段为NULL或是退出中和已退出的产品,则从List中剔除
               if (DataUtils.isNullOrEmpty(upr.getStatus()) || upr.getStatus() < 2) {
iterator.remove();
continue;
}

//如果是投资中的产品,继续判断
               if (upr.getStatus() == 2) {
//如果该产品已经被用户确认续投,则继续从List中剔除
                   if (DataUtils.isNullOrEmpty(upr.getAgainInvestmentId()) || upr.getAgainInvestmentId() > 0) {
iterator.remove();
continue;
}

//如果当前该产品的投资到期日期-当前日期 > 投资到期提醒天数,说明该产品还不能续投,剔除
                   if (DataUtils.isNullOrEmpty(upr.getDueDate()) ||
((upr.getDueDate() - nowTime) > remindDays * 1000 * 3600 * 24)) {
iterator.remove();
continue;
}
}

//如果投资的产品已经下线或者是限购的产品,则不允许续投,剔除

               if (DataUtils.isNullOrEmpty(upr.getProductId()) || !(productIds.contains(upr.getProductId()))){
iterator.remove();
continue;
}

//记录相应的产品ID
               if (DataUtils.isNotNullOrEmpty(upr.getProductId())) {
productIds.add(upr.getProductId());
}
}
}
products = productService.getObjectsByIds(productIds);
log.info("get product data size is : " + products);

model.addAttribute("code", 0);
model.addAttribute("productList", products);
model.addAttribute("userProductRelationList", userProductRelations);
} catch (Throwable t) {
t.printStackTrace();
log.error(t.getMessage());
log.error("get userProductRelation list error,page is  " + start + " , size "
               + size);
model.addAttribute("code", -1);
}


return "/polyFinance-business-service/userProductRelation/json/userProductRelationListJson";
}

二,明天计划完成的事情

1.继续投资列表story的功能实现

三.遇到的问题

暂无

四.收获

以上

五.项目进度情况

已经申请第一次延期


返回列表 返回列表
评论

    分享到