后端开发小技巧 (七)

后端开发小技巧 (七)

1. 自动更新任务

一、 启动程序 添加注解

@EnableScheduling
@SpringBootApplication
@MapperScan("cn.piesat.sar.dao")
public class MessageApplication {
    public static void main(String[] args) {

        SpringApplication.run(MessageApplication.class, args);
    }

}

二、 quartz/ AutoScanTask 注入其他服务的Mapper

  
@Component
public class AutoScanTask {

    private final Logger logger = LoggerFactory.getLogger(AutoScanTask.class);


    @Autowired
    private ThematicTaskMapper taskInfoMapper;


    @Autowired
    private RedisUtil redisUtil;
     /** 
     * 每10分钟调用一次, 程序启动延迟10s执行 1000 毫秒fixedRate 每time 调用一次
     * initalDelay 延迟多长时间
     */
    @Scheduled(fixedRate = 10 * 60 * 1000, initialDelay = 10 * 1000)
    public void updateTaskStatus() {
        System.out.println("自动启动");
        try {
            //查询出数据库中指定时间段内待执行或者执行中的任务
            Integer unfinishedTaskCount = taskInfoMapper.getUnfinishedTaskCount();
            logger.info(String.format("自动任务扫描符合条件的[%d]条主任务", unfinishedTaskCount));
            if (unfinishedTaskCount != null && unfinishedTaskCount > 0) {

                List<ThematicTask> taskInfoList = taskInfoMapper.getUnfinishedTask();
                if (taskInfoList != null && taskInfoList.size() > 0) {
                        for (ThematicTask taskInfo : taskInfoList) {
                            taskInfo.setStatus(1);
                            taskInfoMapper.updateSubTaskStatus(taskInfo);
                            System.out.println("更新状态成功"+taskInfo.toString());
//                          更新任务状态
//                          updateSubTaskStatus(taskInfo);
                        }
                    }
//                }
            }
        } catch (Exception e) {
            logger.error("Update task workflow status error:", e);
        }
    }
    
}

三、 调用其他服务下的mapper.xml


<!--
//    任务未完成的条数
    Integer getUnfinishedTaskCount();

//    未完成的任务
    List<ThematicTask> getUnfinishedTask();
//    更新任务状态
    int updateSubTaskStatus(ThematicTask taskInfo);
-->
<!--    &lt;!&ndash; 查询未完成的主任务数量 &ndash;&gt;-->
    <select id="getUnfinishedTaskCount" resultType="Integer">
        SELECT COUNT(1)
        FROM sar_thematic_product_task
        WHERE "status" != 3 AND "status" != 4;
    </select>
    <select id="getUnfinishedTask" parameterType="java.util.HashMap" resultType="cn.piesat.sar.entity.ThematicTask">
        SELECT
        s1.id, s1.require_task_id "requireTaskId", s1.priority, s1.special_product_level "specialProductLevel", s1.standard_product_list "standardProductList", s1.receive_time "receiveTime", s1.status, s1.rtask_result "rtaskResult", s1.rtask_progress "rtaskProgress",s1.msg_type "msgType"
        FROM sar_thematic_product_task s1
        where
        s1.status=0
        order by s1.receive_time desc
        <if test="pageNum != null and pageSize != null and pageSize > 0">
            limit #{pageSize} OFFSET #{pageNum}
        </if>
    </select>

    <update id="updateSubTaskStatus">
        UPDATE sar_thematic_product_task
        <set>
            <if test="status != null and status != ''">
                status=#{status}
            </if>
        </set>
        WHERE id = #{id}
    </update>

2. 消息服务 message-service

一、 将消息接收储存 ServiceImpl

package cn.piesat.sar.service.impl;

import cn.piesat.sar.base.Config;
import cn.piesat.sar.entity.ServiceResult;
import cn.piesat.sar.service.TaskMessageService;
import cn.piesat.sar.utils.ClientConfiguration;
import cn.piesat.sar.utils.TestData;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class TaskMessageServicempl implements TaskMessageService {

    @Autowired
    TestData testData; // 工具类 测试数据
    @Autowired
    Config config; // 路径
    @Autowired
    ClientConfiguration clientConfiguration; //请求 工具类
    @Value("${task.alg.param}")
    private String taskAlgParam; //文件校验规则

    public void sendDataNotifyMessage(String msg) {

        Map <String,Object> param = new HashMap<>();
        param.put("appKey","");
        param.put("bizCode","");
        param.put("message",msg);
        //发送数据完成通知消息
        String mqUrl = config.getMqApi()+"send";
        clientConfiguration.sendPost(mqUrl,JSON.toJSONString(param, SerializerFeature.WriteMapNullValue));
    }

    @Override
    public ServiceResult receiveThematicProductTaskMessage(String msg) {
        ServiceResult result = new ServiceResult(false);
        try {
            String taskMessage = testData.getTaskMessage();//模拟任务跟踪消息

            String url = config.getDataServiceUrl()+"thematictask/add";
            JSONObject jsonObject = clientConfiguration.sendPost(url,taskMessage);
            if(jsonObject.getBoolean("success")){
                result.setMessage("消息处理成功");
                result.setSuccess(true);
            }
        }catch (Exception e){
            e.printStackTrace();
            result.setMessage("消息处理失败");
        }
        return result;
    }

    private void taskMessageToStorage(String taskMessage, boolean flag) {
        String thematicTaskUrl = config.getDataServiceUrl()+"thematictask/add";
        JSONObject jsonObject = JSONObject.parseObject(taskMessage);
        JSONObject param = new JSONObject();
        param.put("requireTaskId",jsonObject.getString("requireTaskId"));
        param.put("priority",jsonObject.getString("priority"));
        param.put("targetLevel",jsonObject.getString("targetLevel"));
        param.put("geoJsonString",jsonObject.getString("geoJsonString"));

        param.put("standardProductList",jsonObject.getString("standardProductList"));
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        param.put("receiveTime",jsonObject.getString(  sdf.format(new Date())));

        if(flag){
            param.put("status",0);
        }else {
            param.put("status",1);
        }
        clientConfiguration.sendPost(thematicTaskUrl,JSON.toJSONString(param));
    }


}

3. pg sql 主键自增

一、 创建表时设置主键自增

mysql 主键自增使用AUTO_INCREMENT关键字,postgresql自增使用SERIAL关键字。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7y3ZzZX1-1649897596118)(C:\Users\HTHT\AppData\Roaming\Typora\typora-user-images\image-20220401131257039.png)]

二、修改menu表id字段为主键自增

1. 在Postgre sql当中,实现ID自增实现创建一个关联序列,一些sql语句是创建一个序列:
CREATE SEQUENCE menu_id_seq START 6000001;

序列名称是menu_id_seq,起始数为6000001

2. 然后在字段默认值里设 nextval(‘menu_id_seq’::regclass)即可

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pIFSvgzm-1649897596119)(C:\Users\HTHT\AppData\Roaming\Typora\typora-user-images\image-20220401131539241.png)]

3. 保存字段属性变更
ALTER TABLE public.menu ALTER COLUMN id SET DEFAULT nextval('menu_id_seq'::regclass);

三、 修改id的自增起始数

把当前最大的id作为当前的id自增起始数

select setval('gx_history_id_seq',(select max(id) from gx_history)) 

补充

UndefinedTable: relation “ ****_id_seq“ does not exist解决方法

查阅部分资料有的说是postgresql9版本的问题 10已经修复

相关技能

    查询所有自增序列
    SELECT "c"."relname" FROM "pg_class" "c" WHERE "c"."relkind" = 'S';
    pgSQL导表或者创建表的时候,检查是否存在自增字段序列,然后创建
    CREATE SEQUENCE IF NOT EXISTS tablename_id_seq;
    创建自增序列
    CREATE SEQUENCE tablename_id_seq
    CREATE SEQUENCE tablename_id_seq START 10;
    删除某个自增序列
    DROP SEQUENCE tablename_id_seq
    更新某个自增序列
    alter sequence tablename_id_seq restart with 100
    查询下一个序列
    select nextval('tablename_id_seq ');
    使用自增序列
    nextval('tablename_id_seq'::regclass)
————————————————
版权声明:本文为CSDN博主「手心守贝」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_35771567/article/details/103616842

4. 消息接收 ,以及验证消息完整ALG

一、 ServiceImpl

 /**
     * 校验规则
     * 文件示例:JH0451_HT1A_0001_1024_1_20220211150123_20220211150223.dat
     1、文件包数量和接口消息中的【文件包数量】是否一致;
     2、每个文件包名称中的数据类型是否规范:如果文件包数量是1,数据类型应该为0;如果文件包数量是2,每个文件包中的数据类型不能相同,应该分别为1和2。
     3、按照文件包进行分别校验:
     (1)文件命名校验
        每个文件包名字中的测站代号和接口消息中的【测站标识】是否一致;
        每个文件包名字中的卫星代号和接口消息中的【卫星代号】是否一致;
        每个文件包名称和接口消息中的【原始文件名】是否一致; (通过验证文件是否存在解决需求)
     (2)文件大小校验
     每个文件包大小和接口消息中的【原始文件长度】是否一致;
     *
     * */

    public boolean verifyRule(String dataMessage) {
        boolean flag = true;
        JSONObject jsonObject = JSONObject.parseObject(dataMessage);
        JSONArray jsonArray = jsonObject.getJSONArray("fileList");
        int fileNumber = jsonObject.getInteger("fileNumber");
        //文件数量验证
        if(fileNumber!=jsonArray.size()){
            return false;
        }
        // 文件包数量类型验证
        if(fileNumber==1){
            String fileName = jsonArray.getJSONObject(0).getString("fileName");
            int dataType = Integer.parseInt(fileName.split("_")[4]);
            if(dataType!=0){
                return false;
            }
        }else if(fileNumber==2){
            for(int i=0;i<jsonArray.size();i++){
                String fileName = jsonArray.getJSONObject(i).getString("fileName");
                int dataType = Integer.parseInt(fileName.split("_")[4]);
                if(dataType!=2 && dataType!=1){
                    return false;
                }
            }
        }
        //文件命名验证
        for(int i=0;i<jsonArray.size();i++){
            JSONObject data = jsonArray.getJSONObject(i);
            String path = config.getDataDir();
            String fileName = data.getString("fileName");
            Integer fileLength = data.getInteger("fileLength");

            //文件命名校验
            String antenna = data.getString("antenna");
            String satellite = data.getString("satellite");
            if(!antenna.equals(fileName.split("_")[0])){
                return false;
            }
            if(!satellite.equals(fileName.split("_")[1])){
                return false;
            }
            //文件大小校验
            File f= new File(path+fileName);
            if (f.exists() && f.isFile()){
                if(f.length()!=fileLength){
                    return false;
                }
            } else {
                return false;
            }
        }
        return flag;
    }


5. 杀死进程,重新启动该任务

***************************
APPLICATION FAILED TO START
***************************

Description:

Web server failed to start. Port 8082 was already in use.

Action:

Identify and stop the process that's listening on port 8082 or configure this application to listen on another port.

使用 命令

netstat -ano |findstr 8082

找到

杀死 该进程

taskkill -PID 19772 -F

6. linux 部署常用命令

启动 .jar测试 是否成功

java -jar xxx.jar

标识 查看服务是否成功

ksar get svc

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QYiJY49n-1649897596119)(C:\Users\HTHT\AppData\Roaming\Typora\typora-user-images\image-20220402151921233.png)]

ls 目录 cd 进入文件 cat 查看 vi 编辑 :wq退出保存 i插入 exit 退出

遇到问题 先看报错 日志

常用 K8S 命令

kubectl get svc # 查看service服务
kubectl get po # 查看pod
kubectl logs xxxx # 查看某个pod的日志
kubectl apply -f xxx.yaml # 部署某个已经写好配置文件的服务
kubectl delete -f xxx.yaml # 删除某个已经写好配置文件的服务
kubectl describe pod xxx # 当容器启动报错时可以使用该方法查看报错细节
kubectl exec -ti xxx bash # 进入某个容器
kubectl get pv # 查看持久卷
kubectl get node # 查看集群状态
kubectl get po -o wide # 可以查看这些容器具体跑在哪些节点

7. 空网关

先看报错 日志

常用 K8S 命令

kubectl get svc # 查看service服务
kubectl get po # 查看pod
kubectl logs xxxx # 查看某个pod的日志
kubectl apply -f xxx.yaml # 部署某个已经写好配置文件的服务
kubectl delete -f xxx.yaml # 删除某个已经写好配置文件的服务
kubectl describe pod xxx # 当容器启动报错时可以使用该方法查看报错细节
kubectl exec -ti xxx bash # 进入某个容器
kubectl get pv # 查看持久卷
kubectl get node # 查看集群状态
kubectl get po -o wide # 可以查看这些容器具体跑在哪些节点

7. 空网关

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值