需求

提供一个根据商品ID(itemID)返回质检报告图片URL的链接。

问题与相应的解决方案

问题1. 根据商品ID获取质检报告图片URL需要查询DB 解决方案: 因为质检报告基本就是不会更新,另外,实时性也不是很高。所以可以考虑用Cache。本地化Cache或者Memcachd都可以。

问题2. 恶意用户使用随机商品ID拼凑URL进行调用攻击 解决方案:对于错误的商品ID,往Cache存入null值,下次直接返回,避免走DB。不过恶意用户可能可以拉取到真正的商品ID,所以中级解决方案要做一个调用鉴权(比如签名),不过这样对接入用户是一个伤害,所以这里只考虑错误商品ID的处理情况。

/**
 * 提供查询QT报告图片URL给商品组,不需要验证。
 * 
 * @author arganzheng
 * @date 2013-12-9
 */
@Controller
@RequestMapping("/ui/qt")
public class QtReportFrontController {

    private static final Logger logger                  = Logger.getLogger(QtReportFrontController.class);

    private static final String KEY_PREFIX              = "QT_REPORT_URL";

    // 24小时
    private static int          ExpireInterval          = 24 * 3600 * 1000;
    // 反正DOS攻击
    private static int          Anti_Dos_ExpireInterval = 1 * 3600 * 1000;

    @Autowired
    private QtReportService     qtService;

    @Autowired
    private CacheServiceHelper  cacheServiceHelper;

    @RequestMapping(value = "/{itemId}", method = GET)
    public String qtReportDetail(@PathVariable
    String itemId) {
        String qtReportUrlKey = KEY_PREFIX + "_" + itemId;

        if (cacheServiceHelper.exist(qtReportUrlKey)) {
            String reportUrl = (String) cacheServiceHelper.get(qtReportUrlKey);
            return "redirect:" + reportUrl;
        } else {
            List<QtReport> reports = qtService.getQtReportByItemId(itemId);
            if (CollectionUtils.isEmpty(reports)) {
                logger.error("Can not find Qt Report for ItemId: " + itemId);
                cacheServiceHelper.put(qtReportUrlKey, null, Anti_Dos_ExpireInterval);
                return "appstore/error";
            }
            // 重定向到reportUrl去
            String reportUrl = reports.get(0).getReportUrl();
            cacheServiceHelper.put(qtReportUrlKey, reportUrl, ExpireInterval);
            return "redirect:" + reportUrl;
        }
    }
}

结论

做什么事情多想一步,才能成为优秀的程序员:)