记录一个连表查询加分页的接口
table: api-request-daily 产品日统计表
product 产品表
项目结构:
matedata-app :service controller..
matedata-comon:entity,mapper..
1.写接口文档 ,确定需求 (GET 只有请求参数 ,无请求体 )
- 请求方式及地址
`GET` - `/product/{productCode}/daily-bill`
- 请求头
| 参数名 | 类型 | 说明 |
| :---: | :---: | :---: |
| token | string | 登录凭证 |
- 请求参数
| 参数名 | 类型 | 是否必传 | 说明 |
| :---: | :---: | :---: | :---: |
| startDate| string | 是 | 起始日,如“2019-03-01” |
| endDate| string | 是 | 截止日,如“2019-03-31” |
| pageNum | int | 是 | 页码 |
| pageSize | int | 是 | 分页量 |
- 响应体
| 参数名 | 类型 | 说明 |
| :---: | :---: | :---: |
| code | int | 状态码 |
| message | string | 状态信息 |
| total | long | 总数 |
| list | JsonArray | 数据列表 |
list集合
| 参数名 | 类型 | 说明 |
| :---: | :---: | :---: |
| statsDay| string| 统计日 |
| apiName| string | 接口名称 |
| requestQty | long | 请求次数 |
| chargeQty | long | 计费次数 |
| chargeAmt| string | 计费金额 |
- 响应体示例:
```
{
"code": 0,
"message": "ok",
"total": 12,
"list": [
{
"code": "P100001",
"statsDay": "2019-01-28",
"requestQty": 1,
"chargeQty": 1,
"chargeAmt": 100000
},
{
"code": "P100001",
"statsDay": "2019-01-30",
"requestQty": 71517,
"chargeQty": 66991,
"chargeAmt": 6699100
},
{
"code": "P100001",
"statsDay": "2019-01-31",
"requestQty": 538,
"chargeQty": 329,
"chargeAmt": 32900
}
]
}
```
2.dao层的实现 在atedata-comon 完成
2.1新建一个entity保存 查询出来的列段 (前面加 V eg.VApiRequestDaily)
package net.matedata.common.domain.entity;
public class VApiRequestDaily
{
private Integer statsDay;
private String apiName;
private Long requestQty;
private Long chargeQty;
private Long chargeAmt;
public Integer getStatsDay()
{
return statsDay;
}
public void setStatsDay(Integer statsDay)
{
this.statsDay = statsDay;
}
public String getApiName()
{
return apiName;
}
public void setApiName(String apiName)
{
this.apiName = apiName;
}
public Long getRequestQty()
{
return requestQty;
}
public void setRequestQty(Long requestQty)
{
this.requestQty = requestQty;
}
public Long getChargeQty()
{
return chargeQty;
}
public void setChargeQty(Long chargeQty)
{
this.chargeQty = chargeQty;
}
public Long getChargeAmt()
{
return chargeAmt;
}
public void setChargeAmt(Long chargeAmt)
{
this.chargeAmt = chargeAmt;
}
}
新建 mapper
package net.matedata.common.domain.mapper;
import net.matedata.common.domain.entity.VApiRequestDaily;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface VApiRequestDailyMapper
{
List<VApiRequestDaily> getListByParam(@Param("merchantId") Long merchantId,
@Param("productCode") String productCOde, @Param("startDate") Integer startDate,
@Param("endDate") Integer endDate);
}
mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="net.matedata.common.domain.mapper.VApiRequestDailyMapper">
<resultMap id="BaseResultMap" type="VApiRequestDaily">
<id column="id" property="id" jdbcType="BIGINT" />
<result column="stats_day" property="statsDay" jdbcType="INTEGER" />
<result column="api_name" property="apiName" jdbcType="VARCHAR" />
<result column="request_qty" property="requestQty" jdbcType="BIGINT" />
<result column="charge_qty" property="chargeQty" jdbcType="BIGINT" />
<result column="charge_amt" property="chargeAmt" jdbcType="BIGINT" />
</resultMap>
<!-- @formatter:off -->
<select id="getListByParam" resultMap="BaseResultMap">
select
a.`stats_day` as stats_day,
b.`code` as api_code,
b.`name` as api_name,
a.`request_qty` as request_qty,
a.`charge_qty` as charge_qty,
a.`charge_amt` as charge_amt
from `api_request_daily` a
left join `product_api` b
on a.`product_api_code` = b.`code`
<where>
<if test="merchantId != null">and a.`merchant_id` = #{merchantId}</if>
<if test="productCode != null">and a.`product_code` = #{productCode}</if>
<if test="startDay != null">and `stats_day` >= #{startDay}</if>
<if test="endDay != null">and `stats_day` < #{endDay}</if>
</where>
order by a.`create_time` desc
</select>
<!-- @formatter:on -->
</mapper>
3.matedata-app
get 没有请求体,只有请求参数
创建响应参数类 DailyRes
package net.matedata.app.model.response;
public class DailyRes
{
private String statsDay;
private String apiName;
private Long requestQty;
private Long chargeQty;
private String chargeAmt;
public String getStatsDay()
{
return statsDay;
}
public void setStatsDay(String statsDay)
{
this.statsDay = statsDay;
}
public String getApiName()
{
return apiName;
}
public void setApiName(String apiName)
{
this.apiName = apiName;
}
public Long getRequestQty()
{
return requestQty;
}
public void setRequestQty(Long requestQty)
{
this.requestQty = requestQty;
}
public Long getChargeQty()
{
return chargeQty;
}
public void setChargeQty(Long chargeQty)
{
this.chargeQty = chargeQty;
}
public String getChargeAmt()
{
return chargeAmt;
}
public void setChargeAmt(String chargeAmt)
{
this.chargeAmt = chargeAmt;
}
}
service
package net.matedata.app.service;
import net.matedata.app.model.request.DailyReq;
import net.matedata.app.model.response.DailyRes;
import net.matedata.app.model.response.MerProductRes;
import net.matedata.app.model.response.MyProductRes;
import net.matedata.common.model.PageResp;
import net.matedata.common.model.QueryPage;
public interface ProductService
{
void getListByParam(String productCode, Date startDate, Date endDate, QueryPage queryPage, PageResp<DailyRes> res);
}
serviceImpl (时间 :date 转 int a="20190322" 再转 string a="2019-03-22" )
package net.matedata.app.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import net.matedata.app.model.AppReqThread;
import net.matedata.app.model.request.DailyReq;
import net.matedata.app.model.response.DailyRes;
import net.matedata.app.model.response.MerProductRes;
import net.matedata.app.model.response.MyProductRes;
import net.matedata.app.service.ProductService;
import net.matedata.common.constant.TrueFalse;
import net.matedata.common.domain.entity.VApiRequestDaily;
import net.matedata.common.domain.entity.VMerchantProduct;
import net.matedata.common.domain.mapper.VApiRequestDailyMapper;
import net.matedata.common.model.PageResp;
import net.matedata.common.model.QueryPage;
import net.matedata.common.util.AmountUtils;
import net.matedata.common.util.MdDateUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Service
public class ProductServiceImpl implements ProductService
{
@Resource
private VApiRequestDailyMapper vApiRequestDailyMapper;
@Override
public void getListByParam(String productCode, Date startDate, Date endDate, QueryPage queryPage,
PageResp<DailyRes> res)
{
Page page = PageHelper.startPage(queryPage.getPageNum(), queryPage.getPageSize());
List<VApiRequestDaily> dailyList =
vApiRequestDailyMapper.getListByParam(AppReqThread.getMerchantId(), productCode,
MdDateUtils.intValueOfDay(startDate),
MdDateUtils.intValueOfDay(endDate)); //date 转 int
res.setTotal(page.getTotal());
List<DailyRes> list = new ArrayList<>();
if(CollectionUtils.isNotEmpty(dailyList))
{
DailyRes dailyRes;
for(VApiRequestDaily daily : dailyList)
{
dailyRes = new DailyRes();
dailyRes.setApiName(daily.getApiName());
dailyRes.setStatsDay(formatIntDateVal(daily.getStatsDay())); int 转 string
dailyRes.setRequestQty(daily.getRequestQty());
dailyRes.setChargeQty(daily.getChargeQty());
dailyRes.setChargeAmt(AmountUtils.centToString(daily.getChargeAmt()));
list.add(dailyRes);
}
}
res.setList(list);
}
private String formatIntDateVal(int intDate)
{
String strDate = String.valueOf(intDate);
return strDate.substring(0, 4) + "-" + strDate.substring(4, 6) + "-" + strDate.substring(6, 8);
}
}
类型转换工具类
package net.matedata.common.util;
import org.apache.commons.lang3.time.DateUtils;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
public class MdDateUtils
{
private MdDateUtils()
{
}
public static String format(Date date, String pattern)
{
return new SimpleDateFormat(pattern).format(date);
}
public static boolean inDayRange(Date date, Date from, Date to)
{
if(date != null && from != null && to != null)
{
int dateInt = Integer.parseInt(format(date, "yyyyMMdd"));
int fromInt = Integer.parseInt(format(from, "yyyyMMdd"));
int toInt = Integer.parseInt(format(to, "yyyyMMdd"));
return dateInt >= fromInt && dateInt <= toInt;
}
return false;
}
/**
* 获取当前月份
*/
public static Integer getMonth(Date date)
{
Calendar cal = Calendar.getInstance();
cal.setTime(date);
return cal.get(Calendar.MONTH) + 1;
}
public static Integer intValueOfDay(Date date)
{
return Integer.valueOf(format(date, "yyyyMMdd"));
}
public static List<Integer> getIntRange(Date date, int days)
{
List<Integer> list = new ArrayList<>();
Date startDate = DateUtils.addDays(date, -days);
Calendar calendar = Calendar.getInstance();
calendar.setTime(startDate);
while(!calendar.getTime().after(date))
{
list.add(intValueOfDay(calendar.getTime()));
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
return list;
}
}
biz就不上代码了
拦截器
package net.matedata.app.componet;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.convert.converter.Converter;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
public class StringToDateConverter implements Converter<String, Date>
{
@Override
public Date convert(@Nullable String source)
{
if(StringUtils.isBlank(source))
{
return null;
}
if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$"))
{
return parseToDate(source, "yyyy-MM-dd");
}
else if(source.matches("^\\d{4}/\\d{1,2}/\\d{1,2}$"))
{
return parseToDate(source, "yyyy/MM/dd");
}
else if(source.matches("^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$"))
{
return parseToDate(source, "yyyy-MM-dd HH:mm:ss");
}
else if(source.matches("^\\d{4}/\\d{1,2}/\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$"))
{
return parseToDate(source, "yyyy/MM/dd HH:mm:ss");
}
else if(source.matches("^\\d{4}-\\d{1,2}$"))
{
return parseToDate(source, "yyyy-MM");
}
else
{
throw new IllegalArgumentException("Invalid date value '" + source + "'");
}
}
private Date parseToDate(String str, String format)
{
try
{
return new SimpleDateFormat(format).parse(str);
}
catch(ParseException e)
{
return null;
}
}
}
controller
package net.matedata.app.controller;
import net.matedata.app.biz.ProductBiz;
import net.matedata.app.model.request.DailyReq;
import net.matedata.app.model.response.DailyRes;
import net.matedata.common.model.PageResp;
import net.matedata.common.model.QueryPage;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class ProductController
{
@Resource
private ProductBiz productBiz;
/**
* 产品请求日账单
*/
@LoginRequired
@GetMapping(value = "/product/{productCode}/daily-bill")
public PageResp<DailyRes> getListByParam(@PathVariable(value = "productCode") String productCode,
@RequestParam(value = "startDate") Date startDate, @RequestParam(value = "endDate") Date endDate,
@RequestParam(value = "pageNum") Integer pageNum, @RequestParam(value = "pageSize") Integer pageSize)
{
PageResp<DailyRes> res = new PageResp<>();
productBiz.getListByParam(productCode.toUpperCase(), startDate, endDate, new QueryPage(pageNum, pageSize), res);
return res;
}
代码到这里就完成了,用Postman测一下这个接口
请求头 :登录后拿到token
请求参数 以及结果的展示: