后台用一个Jkid的枚举来定义前端请求数据接口
public enum Jkid {
UploadYkData("1"),
DownloadYkData("2"),
private String value;
public String getValue() {
return value;
}
Jkid(String value) {
this.value = value;
}
public static Jkid toJkid(String value) {
for (Jkid jkid : Jkid.values()) {
if (jkid.getValue().equals(value))
return jkid;
}
return null;
}
}
工程包目录
DAO持久层 service:业务层代码,实现业务拦截;model:数据模型,实体类,以及映射文件 ; utils:其他工具类
既然用到了spring就不能不提注释了
java用@interface Annotation{}定义一个注解@Annotation,一个注解是一个类。@Override,@Deprecated,@SuppressWarnings为常见的3个注解。
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
/**
* 接口注解<br/>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Component
public @interface JKService {
/**
* 枚举接口
*/
Jkid jkid();
/**
* @return 参数对象类型
*/
Class<?>[] cls() default Object.class;
/**
* 编码解码类型
* @return
*/
CodecType codecType() default CodecType.PROTOBUF;
boolean log() default true;
定义一个IAppService.java接口
package com.device.appservice.service;
import com.device.protobuf.response.ServiceResponse;
import com.device.appservice.request.ServiceRequest;
public interface IAppService {
/**
* 处理业务逻辑
* @param request 客户端请求
* @return 同一返回
* @throws Exception 将跑出异常 controller
*/
ServiceResponse doService(ServiceRequest request) throws Exception;
}
这里的ServiceRequest.java
package com.device.appservice.request;
import com.device.appservice.core.CodecType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull;
import java.util.HashMap;
import java.util.Map;
/**
* 客户端请求参数<br/>
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class ServiceRequest {
@NotNull(message = "接口ID不能为空")
private String jkId;// 接口编号
private String sign;// 接口签名
private String time;// 时间戳
@NotNull(message = "版本号不能为空")
private String v;// 接口版本
private String source;// 来源
private String deviceId; // 用户id
/**
* 编码解码方式,客户端可以在消息头里指定,以客户端指定的方式优先
*/
private CodecType codecType;
// --------- 以上参数在url中获取
/**
* 客户端参数原始数据
*/
private byte[] bytes;
/**
* 客户端参数解析后的对象,从 bytes 解析而来
*/
private Object paramObj;
/**
* 附加对象
*/
private Map<String, Object> attachments;
/**
* 添加一个附件
* @param key 附加key
* @param o 附加对象
*/
public void addAtachment(String key, Object o) {
if (attachments == null) {
attachments = new HashMap<>();
}
attachments.put(key, o);
}
/**
* 查找一个附加对象
* @param key 对象key
* @return 附加的对象
*/
public Object getAttachment(String key) {
if (attachments == null) {
return null;
}
return attachments.get(key);
}
}
package com.device.protobuf.response;
import com.baidu.bjf.remoting.protobuf.FieldType;
import com.baidu.bjf.remoting.protobuf.annotation.Protobuf;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 下行,返回给客户端
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ServiceResponse {
@Protobuf(fieldType = FieldType.STRING, order = 1)
private String code;//返回码
@Protobuf(fieldType = FieldType.STRING, order = 2)
private String msg;//返回信息
private Object data;//返回数据
//添加transient关键字标识这个字段对于【Gson】会忽略这个字段,对于【protobuf】不影响
//未验证对其它JSON是否有同样功能
@Protobuf(fieldType = FieldType.BYTES, order = 3)
private transient byte[] bytes;
}
然后BaseServiceImpl.java
package com.device.appservice.service;
import com.device.appservice.codec.IMultiCodec;
import com.device.appservice.core.Code;
import com.device.appservice.core.JKService;
import com.device.appservice.core.Jkid;
import com.device.appservice.core.WebTransException;
import com.device.appservice.domain.manager.ClientParamChecker;
import com.device.appservice.request.ServiceRequest;
import com.device.model.db.TransLine;
import com.device.protobuf.response.ServiceResponse;
import com.device.redis.entity.MemDeviceInfo;
import com.device.redis.service.DeviceMemService;
import com.device.service.TransLineService;
import com.cxy.utils.GsonUtils;
import com.cxy.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.Date;
import java.util.Objects;
import java.util.Observable;
import java.util.UUID;
public abstract class BaseServiceImpl extends Observable implements IAppService {
protected static final Logger LOGGER = LoggerFactory.getLogger(BaseServiceImpl.class);
public static final String DEVICE_INFO_KEY = "deviceInfo";
/**
* 编码解码器
*/
@Autowired
protected IMultiCodec codec;
@Autowired
private ClientParamChecker paramChecker;
@Resource
TransLineService transLineService;
@Resource
@Qualifier("mvcValidator")
private Validator validator;
@Autowired
DeviceMemService deviceMemService;
public ServiceResponse doService(ServiceRequest serviceRequest) throws Exception {
long startTime = System.currentTimeMillis();
serviceRequest = decodeAndCheckParameter(serviceRequest);
serviceRequest.setDeviceId(serviceRequest.getDeviceId().replaceFirst("^0*", ""));
ServiceResponse response = getOKServiceResponse();
//日志入口
logIn(serviceRequest);
doServiceBefore(serviceRequest, response);
TransLine transLine = saveTransLine(serviceRequest);
response = doBusiness(serviceRequest, response);
encodeParam(response, serviceRequest);
doServiceAfter(serviceRequest, response);
//更新业务流水
updateTransLine(response, transLine);
//出口日志
logOut(serviceRequest, response, startTime, transLine);
return response;
}
public ServiceResponse getOKServiceResponse() {
ServiceResponse response = new ServiceResponse();
response.setCode(Code.交易成功.responseCode());
response.setMsg(Code.交易成功.resonseMsg());
return response;
}
private ServiceRequest decodeAndCheckParameter(ServiceRequest serviceRequest) throws Exception {
if (isEmptyData(serviceRequest)) {
return serviceRequest;
}
decodeParam(serviceRequest);
checkParam(serviceRequest.getParamObj());
paramChecker.checkSign(serviceRequest);
return serviceRequest;
}
private boolean isEmptyData(ServiceRequest request) {
return Objects.isNull(request) || Objects.isNull(request.getBytes());
}
/**
* 解码,将字节码转换成对象
*
* @param serviceRequest
* @return request 对象
* @throws ClassNotFoundException
* @throws IOException
*/
private ServiceRequest decodeParam(ServiceRequest serviceRequest) throws Exception {
Class paramRequestClass = getRequestClass();
if (paramRequestClass.equals(Object.class)) {
return serviceRequest;
}
if (serviceRequest.getBytes() == null || serviceRequest.getBytes().length == 0) {
return serviceRequest;
}
Object paramObj = codec.decode(serviceRequest.getBytes(), paramRequestClass,
serviceRequest.getCodecType());
serviceRequest.setParamObj(paramObj);
return serviceRequest;
}
/**
* 获取参数解析类
*
* @return request 类
* @throws ClassNotFoundException
*/
protected Class getRequestClass() throws ClassNotFoundException {
JKService jkservice = AnnotationUtils.findAnnotation(this.getClass(), JKService.class);
Class<?>[] cls = jkservice.cls();
for (Class<?> cl : cls) {
if (cl.getName().contains("Request"))
return cls[0];
}
return cls[0];
}
/**
* 参数有效性检查
*
* @param request 客户端请求
* @throws WebTransException if invalid
*/
protected void checkParam(Object request) throws WebTransException {
Errors errors = new BeanPropertyBindingResult(request, request.getClass().getName());
validator.validate(request, errors);
if (errors.getErrorCount() == 0) {
return;
}
final StringBuffer stringBuffer = new StringBuffer();
errors.getFieldErrors().forEach(err -> {
String str = ":";
String separator = "|";
stringBuffer.append(err.getField()).append(str).append(err.getDefaultMessage()).append(separator);
});
String errStr = stringBuffer.toString();
LOGGER.error("参数错误 {}", errStr);
throw new WebTransException(Code.接口方法参数错误.responseCode(), errStr);
}
/**
* 做业务前准备
*
* @param request
*/
protected void doServiceBefore(ServiceRequest request, ServiceResponse response) throws WebTransException {
MemDeviceInfo device = deviceMemService.getDeviceInfo(request.getDeviceId());
if (device == null) {
throw new WebTransException(Code.设备不存在.responseCode(), Code.设备不存在.resonseMsg() + " : " + request.getDeviceId());
}
request.addAtachment(DEVICE_INFO_KEY, device);
}
/**
* 办理业务
*
* @param serviceRequest
* @param serviceResponse
* @return serviceResponse
* @throws WebTransException
*/
protected abstract ServiceResponse doBusiness(ServiceRequest serviceRequest, ServiceResponse serviceResponse) throws WebTransException, IOException;
/**
* 做业务前准备
*
* @param request
*/
protected void doServiceAfter(ServiceRequest request, ServiceResponse response) {
}
/**
* 保存业务流水
*
* @param request serviceRequest that decoded
*/
private TransLine saveTransLine(ServiceRequest request) {
if (isLog()) {
TransLine transLine = new TransLine();
// UUID uuid = UUID.randomUUID();
// transLine.setId(uuid.toString());
transLine.setJkId(String.valueOf(request.getJkId()));
transLine.setImei(request.getDeviceId());
transLine.setReqData(GsonUtils.bean2json(request.getParamObj()));
transLine.setTransTime(new Date());
transLineService.save(transLine);
return transLine;
}
return null;
}
/**
* 更新业务流水
*/
private void updateTransLine(ServiceResponse response, TransLine transLine) {
if (isLog()) {
String value = GsonUtils.bean2json(response.getData());
if (StringUtils.isNotEmptyByTrim(value) && value.length() >= 4000)
value = value.substring(0, 1000) + "...." + value.substring(value.length() - 1000);
transLine.setRespData(value);
transLineService.save(transLine);
}
}
/**
* 编码参数
*
* @param serviceResponse 包含客户端参数类
* @param serviceRequest
* @return 同一返回
* @throws IOException if can not encode
*/
protected ServiceResponse encodeParam(ServiceResponse serviceResponse, ServiceRequest serviceRequest) throws IOException {
if (Objects.isNull(serviceResponse.getData())) {
return serviceResponse;
}
byte[] bytes = codec.encode(serviceResponse.getData(), serviceRequest.getCodecType());
serviceResponse.setBytes(bytes);
return serviceResponse;
}
/**
* 获取参数对象
*
* @param serviceRequest include param
* @param clazz param class
* @param <T> param type
* @return param object
*/
protected <T> T getParam(ServiceRequest serviceRequest, Class<T> clazz) throws WebTransException {
if (Objects.isNull(serviceRequest.getParamObj())) {
throw new WebTransException(Code.接口方法参数错误.responseCode(), "没有参数,加入参数");
}
return (T) serviceRequest.getParamObj();
}
protected <T> T getParam(ServiceRequest serviceRequest) throws WebTransException {
if (Objects.isNull(serviceRequest.getParamObj())) {
throw new WebTransException(Code.接口方法参数错误.responseCode(), "没有参数,加入参数");
}
return (T) serviceRequest.getParamObj();
}
protected boolean isLog() {
JKService jkservice = AnnotationUtils.findAnnotation(this.getClass(), JKService.class);
return jkservice.log();
}
/**
* 设置参数对象
*
* @param serviceResponse 同一返回
* @param data 参数对象
* @return
*/
protected ServiceResponse setData(ServiceResponse serviceResponse, Object data) {
serviceResponse.setData(data);
return serviceResponse;
}
public void logIn(ServiceRequest serviceRequest) {
if (isLog()) {
LOGGER.info("\n[业务入口] :"
+ "\n硬件标识 : {}"
+ "\n服务接口 : {}"
+ "\n接口名称 : {}"
+ "\n请求数据 : {}"
, serviceRequest.getDeviceId()
, serviceRequest.getJkId()
, Jkid.toJkid(serviceRequest.getJkId()).name()
, GsonUtils.bean2json(serviceRequest.getParamObj()));
}
}
protected void logOut(ServiceRequest serviceRequest, ServiceResponse serviceResponse,
long startTime, TransLine transLine) {
if (isLog()) {
long ss = System.currentTimeMillis() - startTime;
String transLineId = (transLine == null ? "" : transLine.getId());
LOGGER.info(getFormat()
, transLineId
, serviceRequest.getDeviceId()
, serviceResponse.getCode()
, serviceResponse.getMsg()
, GsonUtils.bean2json(serviceResponse.getData()),
ss);
}
}
private String getFormat() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("\n[业务出口] :")
.append("\n流水号 : {}")
.append("\n硬件标识 : {}")
.append("\n返回编码 : {}")
.append("\n返回信息 : {}")
.append("\n返回数据 : {}")
.append("\n服务耗时 : {}");
return stringBuilder.toString();
}
}
看一个具体的服务实现
package com.device.appservice.service.impl;
import com.device.appservice.core.*;
import com.device.appservice.request.ServiceRequest;
import com.device.appservice.service.BaseServiceImpl;
import com.device.dao.repo.DeviceVehicleRelRepo;
import com.device.dao.repo.UserTraffinfoRepo;
import com.device.model.db.UserTraffinfo;
import com.device.model.db.Vehicle;
import com.device.protobuf.response.ServiceResponse;
import com.device.protobuf.violation.GetVehicleJszInfo;
import com.device.thirdparty.eagleeye.CheckVehicleService;
import com.device.traffservice.api.TraffService;
import com.cxy.utils.DateUtils;
import com.cxy.utils.GsonUtils;
import com.cxy.utils.StringUtils;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 获取车辆、驾驶证信息
*/
@JKService(jkid = Jkid.GetVehicleJszInfo, cls={GetVehicleJszInfo.Request.class, GetVehicleJszInfo.Response.class}, codecType = CodecType.JSON)
public class GetVehicleAndJszServiceImpl extends BaseServiceImpl{
@Autowired
private DeviceVehicleRelRepo deviceVehicleRelRepo;
@Autowired
TraffService traffService;
@Autowired
UserTraffinfoRepo userTraffinfoRepo;
@Override
protected ServiceResponse doBusiness(ServiceRequest serviceRequest, ServiceResponse serviceResponse) throws WebTransException, IOException {
GetVehicleJszInfo.Response responseData = new GetVehicleJszInfo.Response();
GetVehicleJszInfo.Request paramObj = (GetVehicleJszInfo.Request)serviceRequest.getParamObj();
Map<String, String> map = new HashedMap();
List<UserTraffinfo> userTraffinfoList = userTraffinfoRepo.findByImei(serviceRequest.getDeviceId());
Vehicle vehicleByImei = deviceVehicleRelRepo.findVehicleByImei(serviceRequest.getDeviceId());
if(vehicleByImei != null){
map.put("hphm", vehicleByImei.getHphm());
if(userTraffinfoList != null && userTraffinfoList.size() > 0){
UserTraffinfo userTraffinfo = userTraffinfoList.get(0);
//获取车辆违法笔数
Integer traffcount = userTraffinfo.getTraffcount();
if(traffcount != null)
map.put("traffinfo", traffcount.toString());
map.put("jszhm", userTraffinfo.getJszhm());
map.put("jsr", userTraffinfo.getJsr());
//获取车辆年审到期日
String yxqz = userTraffinfo.getNsdqr();
if(StringUtils.isNotEmptyByTrim(yxqz)){
Date yxqzDate = DateUtils.stringToDate(yxqz, "yyyy-MM-dd HH:mm:ss");
Date now = new Date();
long yxqzLong = yxqzDate.getTime();
long nowLong = now.getTime();
long days = (yxqzLong -nowLong)/(1000*60*60*24);
String value = Math.abs(days >= 0 ? (days + 1) : days) + "";
map.put("nsdqr", value);
}
//获取驾驶证清分日期
String cclzrq = userTraffinfo.getQfrq();
if(StringUtils.isNotEmptyByTrim(cclzrq)){
Date today = new Date();
String qfrq = DateUtils.getQFRQ(cclzrq);
Date qfrqDate = DateUtils.stringToDate(qfrq, "yyyyMMdd");
int jlqfDate = (int) ((qfrqDate.getTime() - today.getTime()) / (24 * 60 * 60 * 1000));
map.put("qfrq", jlqfDate+"");
}
}
//获取车所属单位
if(paramObj != null){
CheckVehicleService.CheckVehicleRequest checkVehicleRequest =
new CheckVehicleService.CheckVehicleRequest(paramObj.getAreaCode().substring(0, 4) + "00",vehicleByImei.getHphm(), vehicleByImei.getHpzl());
com.cxy.cxydevice.thirdparty.common.ServiceResponse checkVehicleResponse = CheckVehicleService.getEagleeyeService()
.doService(checkVehicleRequest);
if (checkVehicleResponse != null && checkVehicleResponse instanceof CheckVehicleService.CheckVehicleResponse) {
CheckVehicleService.CheckVehicleResponse response = (CheckVehicleService.CheckVehicleResponse) checkVehicleResponse;
if (response.isHasVehicle()) {
String orgname = response.getVehicle().getOrgname();
map.put("orgname", orgname);
}
}
}
}
if(!map.isEmpty()){
responseData.setVehicleJszInfo(GsonUtils.bean2json(map));
serviceResponse.setCode(Code.交易成功.responseCode());
serviceResponse.setMsg(Code.交易成功.resonseMsg());
serviceResponse.setData(responseData);
}else{
serviceResponse.setCode(Code.用户登记的资料不完整.responseCode());
serviceResponse.setCode(Code.用户登记的资料不完整.resonseMsg());
}
return serviceResponse;
}
}
接着给出DAO与model差不多就完整了
package com.device.dao.repo;
import com.device.model.db.TCxyUserRoadline;
import com.device.model.db.UserTraffinfo;
import com.cxy.e.core.repository.GenericRepository;
import java.util.List;
public interface UserTraffinfoRepo extends GenericRepository<UserTraffinfo, String> {
List<UserTraffinfo> findByImei(String imei);
}
package com.device.model.db;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import java.util.Date;
@Entity
@Table(name = "t_cxy_user_traffinfo")
public class UserTraffinfo implements com.cxy.e.core.entity.Entity<String> {
//columns START
/**
* 用户交罚业务相关数据 db_column: id
*/
private java.lang.String id;
/**
* 设备编号 db_column: imei
*/
private java.lang.String imei;
/**
* 违法笔数 db_column: traffcount
*/
private java.lang.Integer traffcount;
/**
* 年审到期日 db_column: nsdqr
*/
private java.lang.String nsdqr;
/**
* 清分日期 db_column: qfrq
*/
private java.lang.String qfrq;
/**
* 驾驶人 db_column: jsr
*/
private java.lang.String jsr;
/**
* 车牌号 db_column: hphm
*/
private java.lang.String hphm;
/**
* 驾驶证号 db_column: jszhm
*/
private java.lang.String jszhm;
/**
* 更新时间 db_column: update_time
*/
private java.util.Date update_time;
//columns END
public UserTraffinfo(){
}
public UserTraffinfo(
java.lang.String id
){
this.id = id;
}
public void setId(java.lang.String value) {
this.id = value;
}
@Id @GeneratedValue(generator="custom-id")
@GenericGenerator(name="custom-id", strategy = "uuid")
@Column(name = "id", unique = true, nullable = false, insertable = true, updatable = true, length = 40)
public java.lang.String getId() {
return this.id;
}
@Column(name = "imei", unique = false, nullable = false, insertable = true, updatable = true, length = 30)
public java.lang.String getImei() {
return this.imei;
}
public void setImei(java.lang.String value) {
this.imei = value;
}
@Column(name = "traffcount", unique = false, nullable = true, insertable = true, updatable = true, length = 10)
public java.lang.Integer getTraffcount() {
return this.traffcount;
}
public void setTraffcount(java.lang.Integer value) {
this.traffcount = value;
}
@Column(name = "nsdqr", unique = false, nullable = true, insertable = true, updatable = true, length = 20)
public java.lang.String getNsdqr() {
return this.nsdqr;
}
public void setNsdqr(java.lang.String value) {
this.nsdqr = value;
}
@Column(name = "qfrq", unique = false, nullable = true, insertable = true, updatable = true, length = 20)
public java.lang.String getQfrq() {
return this.qfrq;
}
public void setQfrq(java.lang.String value) {
this.qfrq = value;
}
@Column(name = "jsr", unique = false, nullable = true, insertable = true, updatable = true, length = 45)
public java.lang.String getJsr() {
return this.jsr;
}
public void setJsr(java.lang.String value) {
this.jsr = value;
}
@Column(name = "hphm", unique = false, nullable = true, insertable = true, updatable = true, length = 10)
public java.lang.String getHphm() {
return this.hphm;
}
public void setHphm(java.lang.String value) {
this.hphm = value;
}
@Column(name = "jszhm", unique = false, nullable = true, insertable = true, updatable = true, length = 20)
public java.lang.String getJszhm() {
return this.jszhm;
}
public void setJszhm(java.lang.String value) {
this.jszhm = value;
}
@Column(name = "update_time", unique = false, nullable = true, insertable = true, updatable = true, length = 0)
public Date getUpdate_time() {
return update_time;
}
public void setUpdate_time(Date update_time) {
this.update_time = update_time;
}
}
APP端的看下一篇吧