某自动化制造业生产,需要在A-5工位上打标并生成真实的生产条形码,生成的真实条形码需要覆盖之前的A-1,A-2,A-3,A-4的虚拟条形码。并且B工站组,C攻占组,.....N工站组都有相同的需求。而且需要覆盖的工站不固定。
设计思路
插入的json格式
package com.smartflow.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* @author haita
*/
public class AddCLStationDeviceDTO {
private String LinkTableName;
private Object Object;
@Override
public String toString() {
return "AddCLStationDeviceDTO{" +
"LinkTableName='" + LinkTableName + '\'' +
", Object=" + Object +
'}';
}
@JsonProperty("LinkTableName")
public String getLinkTableName() {
return LinkTableName;
}
public void setLinkTableName(String linkTableName) {
LinkTableName = linkTableName;
}
@JsonProperty("Object")
public java.lang.Object getObject() {
return Object;
}
public void setObject(java.lang.Object object) {
Object = object;
}
}
object是通用的数据,因为有100多个工站,所以会有100多个表。
利用这样的数据格式可以很好的利用java的反射原理。(可以在我以前的文章中找到)进行通用接口的数据插入。
接着根据表名判断是否需要,重写之前的表中的虚拟条形码。
package com.smartflow.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.smartflow.common.stationenum.StationEnumUtil;
import com.smartflow.dto.AddCLStationDeviceDTO;
import com.smartflow.service.CL_StationService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author haita
*/
@RestController
@RequestMapping("/api/CLStation")
public class ClStationController extends BaseController{
private static Logger logger = Logger.getLogger(ClStationController.class);
private final
CL_StationService clStationService;
private static final int ERROR_CODE=0;
private static final int SUCEESS_CODE=200;
private static final String SERIAL_ARG="SERIALNUMBER";
@Autowired
public ClStationController(CL_StationService clStationService
) {
this.clStationService = clStationService;
}
/**
* 添加工站设备生产信息
* @return 返回前端是否添加成功信息
*/
@CrossOrigin(origins="*",maxAge=3600)
@PostMapping(value="/AddCLStationDevice")
public Map<String, Object> addclstationdevice
(@RequestBody AddCLStationDeviceDTO clStationDeviceDTO){
Map<String, Object> json = new HashMap<>(16);
String linkTableName = clStationDeviceDTO.getLinkTableName();
String className = "com.smartflow.model."+linkTableName;
if(StringUtils.isEmpty(linkTableName)){
json = this.setJson(ERROR_CODE, "添加失败:要添加的表名不能为空", -1);
return json;
}
if(clStationDeviceDTO.getObject() == null){
json = this.setJson(ERROR_CODE, "添加失败:要添加对象不能为空", -1);
return json;
}
try {
JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(clStationDeviceDTO.getObject()));
Integer workOrderId = clStationService.getCurrentActivedWorkOrder();
jsonObject.put("WorkOrderId",workOrderId);
String serialNumber = jsonObject.get(SERIAL_ARG) == null ? null : jsonObject.get(SERIAL_ARG).toString();
clStationDeviceDTO.setObject(reWrite(serialNumber,jsonObject,linkTableName));
clStationService.addCLStationDevice(className, parseToEntity(linkTableName, clStationDeviceDTO));
json = this.setJson(SUCEESS_CODE, "添加成功!", 1);
}
catch (Exception e)
{
logger.info(e.getCause());
e.printStackTrace();
}
return json;
}
/**
* 利用反射根据表名生成实体
* @param linkedName 表名
* @param clStationDeviceDTO 请求参数
* @return 返回请求实体
* @throws ClassNotFoundException 根据表名未查到相应的类
*/
@SuppressWarnings("unckecked")
private Object parseToEntity(String linkedName,AddCLStationDeviceDTO clStationDeviceDTO) throws ClassNotFoundException {
Class<?> classEntity=Class.forName("com.smartflow.model."+linkedName);
return JSON.parseObject
(JSON.toJSONString(clStationDeviceDTO.getObject()),
classEntity);
}
/**
* 根据seialNumber和linkTableName判断是否覆盖op50以前的serialNumber
* @param serialNumber 条形码
* @param jsonObject 请求实体
* @param linkTableName 请求表名
* @return 返回修饰的请求实体
*/
private JSONObject reWrite(String serialNumber,JSONObject jsonObject,String linkTableName) {
/*
* 判断是否是需要覆盖的表,覆盖的表有state,且初始的时候置0
* 包含工站组Tu,Re,Im
*/
if (StationEnumUtil.isReWriteStation(linkTableName)) {
jsonObject.put("state", 0);
}
/*
* 请求实体中未包含二维条码,会按日期格式生成二维序列码
*/
jsonObject.put("SerialNumber", new Date().toString());
/*
* 判断是否是最后一个工站Tuop50,Imop15,Reop45,是的话覆盖前面的工站
*/
if (StationEnumUtil.isLastStation(linkTableName)) {
Date date = new Date();
if (serialNumber == null||"".equals(serialNumber)
) {
jsonObject.put(SERIAL_ARG, date.toString());
clStationService.reWriteSerialNumber(date.toString(),linkTableName);
} else {
jsonObject.put(SERIAL_ARG, serialNumber);
clStationService.reWriteSerialNumber(serialNumber,linkTableName);
}
}
return jsonObject;
}
}
覆盖算法
private void setSerialNumber(String serialNumber,String tableName) throws ClassNotFoundException {
try {
List<?> stationList = hibernateTemplate.find
("from "+tableName +
" where state=0 order by CREATE_DATE ");
if (!stationList.isEmpty()) {
Object station = stationList.get(0);
String jsonString=JSONObject.toJSONString(station);
JSONObject jsonObject=JSONObject.parseObject(jsonString);
jsonObject.put("SerialNumber",serialNumber);
jsonObject.put("State",1);
Class<?> classEntity=Class.forName
("com.smartflow.model."+tableName);
hibernateTemplate.clear();
hibernateTemplate.update
(JSON.parseObject(jsonObject.toString(),
classEntity));
}
}catch (Exception e)
{
e.printStackTrace();
throw e;
}
}
可以看到我利用先进先出的规范,根据时间找到最晚未被覆盖的那条数据,也是就是state为0,利用state是否为0来表示是否是被覆盖过的。
更加通用的写法,可以把各个攻占组将要覆盖的工站表,建立一个枚举。
package com.smartflow.common.stationenum;
/**
* @author :tao
* @date :Created in 2020/8/14 14:48
*/
public enum StationNameRe {
/**
* RE工站需要覆盖的工站
*/
RE_OP10A("RE_OP10A"),RE_OP10B("RE_OP10B");
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
StationNameRe(String name)
{
this.name=name;
}
}
package com.smartflow.common.stationenum;
/**
* @author :tao
* @date :Created in 2020/8/10 15:51
*/
public enum StationNameTu {
/**
* TUOP描述
*/
CL_TUOP20("CL_TUOP20"),CL_TU0P25("CL_TU0P25"),CL_TUOP30("CL_TUOP30"),
CL_TUOP45("CL_TUOP45"),CL_WLZPDM("CL_WLZPDM");
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
StationNameTu(String name)
{
this.name=name;
}
}
package com.smartflow.common.stationenum;
/**
* @author :tao
* @date :Created in 2020/8/14 14:50
*/
public enum StationNameIm {
/**
* IM工站需要覆盖的工站位
*/
IM_OP20("IM_OP20"),IM_OP25("IM_OP25"),IM_OP30("IM_OP30"),IM_OP40("IM_OP40");
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
StationNameIm(String name){
this.name=name;
}
}
然后可以根据不同的枚举类去做不同的覆盖队列
@Transactional(rollbackFor = Exception.class)
@Override
public void reWriteSerialNumber(String serialNumber,String tableName) {
try {
if (StationEnumUtil.isRe(tableName)) {
for (StationNameRe stationNameRe : StationNameRe.values()) {
setSerialNumber(serialNumber, stationNameRe.getName());
}
}
if (StationEnumUtil.isTu(tableName))
{
for (StationNameTu stationNameTu:StationNameTu.values())
{
setSerialNumber(serialNumber, stationNameTu.getName());
}
}
if (StationEnumUtil.isIm(tableName))
{
for (StationNameIm stationNameIm:StationNameIm.values())
{
setSerialNumber(serialNumber, stationNameIm.getName());
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
当然以上还是最基本的在最理想的状态下的做法。未来要进行生产的话还需要大量的NG处理,事物的回滚,防错等等。