• 首页
  • 热点
  • 财经
  • 要闻
  • 经济
  • 快讯
  • 科技
  • 滚动
  • 行业
  • 教育
  • 综合
logo
  • 中陕网首页 >
  • 中陕网 > 财经 >
  • 正文

Spring Boot 项目设计业务操作日志功能,写得太好了!

2023-06-29 10:33:23 来源:博客园

前言

很久以前都想写这篇文章,一直没有空,但直到现在我对当时的情景还有印象,之所以有印象是因为需求很简单,业务操作日志的记录与查询的功能,但是具体实现真的很烂,具体的烂法会在反面示例里细说,领导以及客户层面很认可,一系列迷之操作,让我印象深刻。


(相关资料图)

需求描述与分析

客户侧提出需求很简单:要对几个关键的业务功能进行操作日志记录,即什么人在什么时间操作了哪个功能,操作前的数据报文是什么、操作后的数据报文是什么,必要的时候可以一键回退。

日志在业务系统中是必不可少的一个功能,常见的有系统日志、操作日志等:

系统日志

这里的系统日志是指的是程序执行过程中的关键步骤,根据实际场景输出的debug、info、warn、error等不同级别的程序执行记录信息,这些一般是给程序员或运维看的,一般在出现异常问题的时候,可以通过系统日志中记录的关键参数信息和异常提示,快速排除故障。

操作日志

操作日志,是用户实际业务操作行为的记录,这些信息一般存储在数据库里,如什么时间哪个用户点了某个菜单、修改了哪个配置等这类业务操作行为,这些日志信息是给普通用户或系统管理员看到。

通过对需求的分析,客户想要是一个业务操作日志管理的功能:

1、记录用户的业务操作行为,记录的字段有:操作人、操作时间、操作功能、日志类型、操作内容描述、操作内容报文、操作前内容报文

2、提供一个可视化的页面,可以查询用户的业务操作行为,对重要操作回溯;

3、提供一定的管理功能,必要的时候可以对用户的误操作回滚;

反面实现

明确需求后,就是怎么实现的问题了,这里先上一个反面的实现案例,也是因为这一个反面案例,才让我对这个简单的需求印象深刻。

这里我以一个人员管理的功能为例还原一下,当时的具体实现:

1、每个接口里都加一段记录业务操作日志的记录;

2、每个接口里都要捕获一下异常,记录异常业务操作日志;

下面是伪代码:

@RestController@Slf4j@BusLog(name = "人员管理")@RequestMapping("/person")public class PersonController2 {    @Autowired    private IPersonService personService;    @Autowired    private IBusLogService busLogService;    //添加人员信息    @PostMapping    public Person add(@RequestBody Person person) {       try{           //添加信息信息        Person result = this.personService.registe(person);        //保存业务日志        this.saveLog(person);        log.info("//增加person执行完成");               }catch(Exception e){           //保存异常操作日志           this.saveExceptionLog(e);              }        return result;    }}

这种通过硬编码实现的业务操作日志管理功能,最大的问题就是业务操作日志收集与业务逻辑耦合严重,和代码重复,新开发的接口在完成业务逻辑后要织入一段业务操作日志保存的逻辑,已开发上线的接口,还要重新再修改织入业务操作日志保存的逻辑并测试,且每个接口需要织入的业务操作日志保存的逻辑是一样的。

推荐一个开源免费的 Spring Boot 实战项目:

https://github.com/javastacks/spring-boot-best-practice

设计思路

如果对AOP有一些印象的话,最好的方法就是使用aop实现:

1、定义业务操作日志注解,注解内可以定义一些属性,如操作功能名称、功能的描述等;

2、把业务操作日志注解标记在需要进行业务操作记录的方法上(在实际业务中,一些简单的业务查询行为通常没有必要记录);

3、定义切入点,编写切面:切入点就是标记了业务操作日志注解的目标方法;切面的主要逻辑就是保存业务操作日志信息;

Spring AOP

AOP (Aspect Orient Programming),直译过来就是 面向切面编程,AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。面向切面编程,实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术,AOP可以拦截指定的方法并且对方法增强,而且无需侵入到业务代码中,使业务与非业务处理逻辑分离;

而SpringAOP,则是AOP的一种具体实现,Spring内部对SpringAOP的应用最经典的场景就是Spring的事务,通过事务注解的配置,Spring会自动在业务方法中开启、提交业务,并且在业务处理失败时,执行相应的回滚策略;与过滤器、拦截器相比,更加重要的是其适用范围不再局限于SpringMVC项目,可以在任意一层定义一个切点,织入相应的操作,并且还可以改变返回值;

Filter和HandlerInterceptor

之所以没有选择Filter和HandlerInterceptor,而是AOP来实现业务操作日志功能,是因为Filter和HandlerInterceptor自身的一些局限性:

过滤器

过滤器(Filter)是与servlet相关联的一个接口,主要适用于java web项目中,依赖于Servlet容器,是利用java的回调机制来实现过滤拦截来自浏览器端的http请求,可以拦截到访问URL对应的方法的请求和响应(ServletRequest request, ServletResponse response),但是不能对请求和响应信息中的值进行修改;一般用于设置字符编码、鉴权操作等;

如果想要做到更细一点的类和方法或者是在非servlet环境中使用,则是做不到的;所以凡是依赖Servlet容器的环境,过滤器都可以使用,如Struts2、SpringMVC;

拦截器

拦截器的(HandlerInterceptor)使用范围以及功能和过滤器很类似,但是也是有区别的。首先,拦截器(HandlerInterceptor)适用于SpringMVC中,因为HandlerInterceptor接口是SpringMVC相关的一个接口,而实现java Web项目,SpringMVC是目前的首选选项,但不是唯一选项,还有struts2等;因此,如果是非SpingMVC的项目,HandlerInterceptor无法使用的;

其次,和过滤器一样,拦截器可以拦截到访问URL对应的方法的请求和响应(ServletRequest request, ServletResponse response),但是不能对请求和响应信息中的值进行修改;一般用于设置字符编码、鉴权操作等;如果想要做到更细一点的类和方法或者是在非servlet环境中使用,则也是是做不到的;

总之,过滤器和拦截器的功能很类似,但是拦截器的适用范围比过滤器更小;

SpringAOP、过滤器、拦截器对比

在匹配中同一目标时,过滤器、拦截器、SpringAOP的执行优先级是:过滤器>拦截器>SpringAOP,执行顺序是先进后出,具体的不同则体现在以下几个方面:

1、作用域不同

  • 过滤器依赖于servlet容器,只能在 servlet容器,web环境下使用,对请求-响应入口处进行过滤拦截;
  • 拦截器依赖于springMVC,可以在SpringMVC项目中使用,而SpringMVC的核心是DispatcherServlet,而DispatcherServlet又属于Servlet的子类,因此作用域和过滤器类似;
  • SpringAOP对作用域没有限制,只要定义好切点,可以在请求-响应的入口层(controller层)拦截处理,也可以在请求的业务处理层(service层)拦截处理;

2、颗粒度的不同

  • 过滤器的控制颗粒度比较粗,只能在doFilter()中对请求和响应进行过虑和拦截处理;
  • 拦截器提供更精细颗粒度的控制,有preHandle()、postHandle()、afterCompletion(),可以在controller对请求处理之前、请求处理后、请求响应完毕织入一些业务操作;
  • SpringAOP,提供了前置通知、后置通知、返回后通知、异常通知、环绕通知,比拦截器更加精细化的颗粒度控制,甚至可以修改返回值;

实现方案

环境配置

  • jdk版本:1.8开发工具:Intellij iDEA 2020.1
  • springboot:2.3.9.RELEASE
  • mybatis-spring-boot-starter:2.1.4

依赖配置

    org.springframework.boot    spring-boot-starter-aop

表结构设计

create table if not exists bus_log(   id bigint auto_increment comment "自增id"      primary key,   bus_name varchar(100) null comment "业务名称",   bus_descrip varchar(255) null comment "业务操作描述",   oper_person varchar(100) null comment "操作人",   oper_time datetime null comment "操作时间",   ip_from varchar(50) null comment "操作来源ip",   param_file varchar(255) null comment "操作参数报文文件")comment "业务操作日志" default charset ="utf8";

代码实现

1、定义业务日志注解@BusLog,可以作用在控制器或其他业务类上,用于描述当前类的功能;也可以用于方法上,用于描述当前方法的作用;

/** * 业务日志注解 * 可以作用在控制器或其他业务类上,用于描述当前类的功能; * 也可以用于方法上,用于描述当前方法的作用; */@Target({ElementType.METHOD,ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)public @interface BusLog {      /**     * 功能名称     * @return     */    String name() default "";     /**     * 功能描述     * @return     */    String descrip() default ""; }

2、把业务操作日志注解BusLog标记在PersonController类和方法上;

@RestController@Slf4j@BusLog(name = "人员管理")@RequestMapping("/person")public class PersonController {    @Autowired    private IPersonService personService;    private Integer maxCount=100;     @PostMapping    @NeedEncrypt    @BusLog(descrip = "添加单条人员信息")    public Person add(@RequestBody Person person) {        Person result = this.personService.registe(person);        log.info("//增加person执行完成");        return result;    }    @PostMapping("/batch")    @BusLog(descrip = "批量添加人员信息")    public String addBatch(@RequestBody List personList){        this.personService.addBatch(personList);        return String.valueOf(System.currentTimeMillis());    }     @GetMapping    @NeedDecrypt    @BusLog(descrip = "人员信息列表查询")    public PageInfo list(Integer page, Integer limit, String searchValue) {       PageInfo pageInfo = this.personService.getPersonList(page,limit,searchValue);        log.info("//查询person列表执行完成");        return pageInfo;    }    @GetMapping("/{loginNo}")    @NeedDecrypt    @BusLog(descrip = "人员信息详情查询")    public Person info(@PathVariable String loginNo,String phoneVal) {        Person person= this.personService.get(loginNo);        log.info("//查询person详情执行完成");        return person;    }    @PutMapping    @NeedEncrypt    @BusLog(descrip = "修改人员信息")    public String edit(@RequestBody Person person) {         this.personService.update(person);        log.info("//查询person详情执行完成");        return String.valueOf(System.currentTimeMillis());    }    @DeleteMapping    @BusLog(descrip = "删除人员信息")    public String edit(@PathVariable(name = "id") Integer id) {         this.personService.delete(id);        log.info("//查询person详情执行完成");        return String.valueOf(System.currentTimeMillis());    }}

3、编写切面类BusLogAop,并使用@BusLog定义切入点,在环绕通知内执行过目标方法后,获取目标类、目标方法上的业务日志注解上的功能名称和功能描述, 把方法的参数报文写入到文件中,最后保存业务操作日志信息;

@Component@Aspect@Slf4jpublic class BusLogAop implements Ordered {    @Autowired    private BusLogDao busLogDao;     /**     * 定义BusLogAop的切入点为标记@BusLog注解的方法     */    @Pointcut(value = "@annotation(com.fanfu.anno.BusLog)")    public void pointcut() {    }     /**     * 业务操作环绕通知     *     * @param proceedingJoinPoint     * @retur     */    @Around("pointcut()")    public Object around(ProceedingJoinPoint proceedingJoinPoint) {        log.info("----BusAop 环绕通知 start");        //执行目标方法        Object result = null;        try {            result = proceedingJoinPoint.proceed();        } catch (Throwable throwable) {            throwable.printStackTrace();        }        //目标方法执行完成后,获取目标类、目标方法上的业务日志注解上的功能名称和功能描述        Object target = proceedingJoinPoint.getTarget();        Object[] args = proceedingJoinPoint.getArgs();        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();        BusLog anno1 = target.getClass().getAnnotation(BusLog.class);        BusLog anno2 = signature.getMethod().getAnnotation(BusLog.class);        BusLogBean busLogBean = new BusLogBean();        String logName = anno1.name();        String logDescrip = anno2.descrip();        busLogBean.setBusName(logName);        busLogBean.setBusDescrip(logDescrip);        busLogBean.setOperPerson("fanfu");        busLogBean.setOperTime(new Date());        JsonMapper jsonMapper = new JsonMapper();        String json = null;        try {            json = jsonMapper.writeValueAsString(args);        } catch (JsonProcessingException e) {            e.printStackTrace();        }        //把参数报文写入到文件中        OutputStream outputStream = null;        try {            String paramFilePath = System.getProperty("user.dir") + File.separator + DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN) + ".log";            outputStream = new FileOutputStream(paramFilePath);            outputStream.write(json.getBytes(StandardCharsets.UTF_8));            busLogBean.setParamFile(paramFilePath);        } catch (FileNotFoundException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        } finally {            if (outputStream != null) {                try {                    outputStream.flush();                    outputStream.close();                } catch (IOException e) {                    e.printStackTrace();                }             }        }        //保存业务操作日志信息        this.busLogDao.insert(busLogBean);        log.info("----BusAop 环绕通知 end");        return result;    }     @Override    public int getOrder() {        return 1;    }}

测试

调试方法

平时后端调试接口,一般都是使用postman,这里给大家安利一款工具,即Intellij IDEA的Test RESTful web service,功能和使用和postman差不多,唯一的好处就是不用在电脑上再额外装个postman,功能入口:工具栏的Tools-->http client-->Test RESTful web

另外还有一种用法,我比较喜欢用这种,简单几句就可以发起一个http请求,还可以一次批量执行;

验证结果

总结

业务操作日志记录中包含了用户操作的功能名称、功能描述、操作人、操作时间和操作的参数报文,参数报文之所以选择存储在文件中,是因为正常情况下,是不需要知道具体的参数报文,只有在回滚操作的时候才会用到,可以根据上一次的参数报文逆向操作。

版权声明:本文为CSDN博主「凡夫贩夫」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/fox9916/article/details/130175379

近期热文推荐:

1.1,000+ 道 Java面试题及答案整理(2022最新版)

2.劲爆!Java 协程要来了。。。

3.Spring Boot 2.x 教程,太全了!

4.别再写满屏的爆爆爆炸类了,试试装饰器模式,这才是优雅的方式!!

5.《Java开发手册(嵩山版)》最新发布,速速下载!

觉得不错,别忘了随手点赞+转发哦!

责任编辑:

免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。如稿件版权单位或个人不想在本网发布,可与本网联系,本网视情况可立即将其撤除。

    为您推荐

  • Spring Boot 项目设计业务操作日志功能,写得太好了!

    前言很久以前都想写这篇文章,一直没有空,但直到现在我对当时的情景
  • 密室逃脱之深红色房间下载(密室逃脱之深红色房间)

    导读1、找到俩,你看看哪个是你需要的  “密室逃脱之深红色房间”攻
  • 精彩看点:关于皇马小将阿里巴斯的动向塞尔吉奥·阿里巴斯和皇...

    关于皇马小将阿里巴斯的动向塞尔吉奥·阿里巴斯和皇家马德里认为是时候
  • 党建引领熔铸忠诚警魂|湖南日报|天天视点

    党建引领熔铸忠诚警魂——娄底市公安局“一切工作到支部”推动警务高质
  • 人才创新支撑江苏高水平科技自立自强

    记者从6月27日举行的江苏“推进高水平科技自立自强”专场新闻发布会上
  • 电力ETF:融资净偿还561.77万元,融资余额3828.25万元(06-28)_全球独家

    2023年6月28日电力ETF融资净偿还561 77万元,融资余额3828 25万元
  • 缴费二维码,竟成驶离停车场“拦路码”

    缴费二维码,竟成驶离停车场“拦路码”(主题)中工网讯(工人日报-中
  • 天天微速讯:偶像文化的“水土不服”该被重视了

    这次蔡徐坤的负面消息,体现出的问题不光是艺人个人的品行问题,同时,
  • 我州狠抓招商引资促经济平稳增长

    本网讯我州将作风革命、效能革命融入“招什么、哪里招、谁去招、怎么招
  • 今日份安利:PDF转Excel怎么转?_头条

    凯特是一名研究员,她的工作需要经常处理大量的文献资料。然而,很多文
  • 环球新动态:妖精的尾巴04(关于妖精的尾巴04的基本详情介绍)

    1、《妖精的尾巴3》是2010年湖北少儿出版社出版的图书。2、作者是(日)
  • 书单来了-书单网

    1、我就是写网文的,书单网一个小网站,不怎么入流。2、签约门槛本来就
  • 直播玩异度神剑2的弥央和火光p82-p85【授权转载/个人渣翻】-当前看点

    渣翻,尽量追上作者更新,如有问题请指正,翻译咨询感谢@DesertRyan作
  • 招联金融逾期四个月了会有什么后果?逾期协商分期可以吗?_今日快看

    近期,有消息称招联金融的一些客户出现了逾期还款的情况,其中有不少人
  • 大连造船与浙能集团签署绿色航运战略合作协议及风电制氢合成绿色甲醇项目合作备忘录 看热讯

    6月27日,中国船舶集团旗下中国重工子公司大连造船与浙能集团签署绿色
  • 高争民爆:2022年度权益分派10派1.5元 股权登记日7月4日|环球观热点

    2023年6月28日,高争民爆(002827 SZ)公告,公司2022年年度权益分派方案
  • 世界今热点:新时达:公司工业机器人主要运用于3C、锂电、光伏等行业

    新时达6月27日在接受投资者调研时称,公司工业机器人主要运用于3C、锂
  • 5亿高温补贴来了!

    据了解,即日起至9月30日,在全国300多座城市,根据不同城市天气情况,
  • 基金管理人频繁自购旗下基金!6月已合计自购3.27亿 多家公司呼吁:底部区域 保持耐心 焦点讯息

    桂东电力公告,目前公司主要业务主要有:一是以水电、火电发供电为主的
  • 焦点精选!电动车托运大概要多少钱_电动车托运

    1、物流公司在国内大部分地区省市收费是170-180元,首重10元 KG、续重4
  • 长安汽车张晓宇:长安坚持第三次创新创业计划-视点

    2023年6月28日,重庆长安汽车股份有限公司副总裁张晓宇出席2023金台汽
  • 河北人才网官网职称管理系统_河北人事职称网|天天微速讯

    1、2021年河北省中级职称已经公示了,可以去河北省人事考试网去查询,
  • soho公寓是什么(soho公寓什么意思)_环球新要闻

    小常来为大家解答以上问题。soho公寓是什么,soho公寓什么意思很多人还
  • 韩国女演员列传

    1、先锋之那时青春剧情 历史 战争年代:2016地区:大陆演员:马雪阳刘
  • 特斯拉撞树起火,华人母女在美身亡 丈夫:与妻子在清华相识相恋,不愿接受妻女离世现实-重点聚焦

    近日,美国加州圣克拉拉一对母女在一场由车祸引发的火灾中丧生。当时,
  • 中国旺旺公布年度业绩,股东应占利润同比减少19.77%-天天热头条

    中国旺旺公布年度业绩,股东应占利润同比减少19 77%。毛利率为43 9%,
  • 约880元!传音itel P40+手机曝光:搭载 7000mAh 电池

    据91mobiles报道,传音计划在今年7月第二周推出itelP40+手机,该机将搭
  • 短讯!招商轮船(601872)6月28日主力资金净卖出942.24万元

    截至2023年6月28日收盘,招商轮船(601872)报收于5 7元,上涨0 0%,换手
  • 太白县太白河镇:“保姆式”服务打造良好营商环境

    本报讯(记者张晓亮)“政府的服务太周到了,连门都没出,镇上帮我把营
  • 站台上抽根烟,丢了行李,落了自己

    人们常说,喝酒误事,没成想,抽烟也误事。6月27日,旅客陈先生从广东
  • 世界简讯:2023甬港经济合作论坛在港举行

    新华社香港6月27日电(记者谢妞)由宁波市人民政府和香港贸易发展局共
  • 河南省汝南县发布大风蓝色预警

    汝南县气象台2023年6月28日11时26分发布大风蓝色预警信号:预计未来24
  • 【报资讯】2023年博罗湖镇镇插班转学说明(小学+幼儿园)

    公办学校其它年级插班生需要转学插班的学生,需由父母或其他法定监护人
  • 工业利润降幅连续三个月收窄,下阶段走势如何?_天天快资讯

    随着宏观经济企稳向好、工业生产继续恢复,工业企业利润降幅持续收窄。
  • 周鸿祎晒清华博士录取通知书,53岁又“出征”上学

    6月27日晚间,周鸿祎在个人微博晒出清华大学录取通知书,称“终于考上
  • 全球微资讯!西瓜刀算管制刀具吗_西瓜刀

    1、不管什么名字。2、只要尺寸过了规定的数据就算。本文到此分享完毕,
  • 部分两岸直航点复航申请未获台湾方面批准,国台办回应_每日消息

    希望台方尽快撤除单方面设置的不合理限制,把两岸航线航班交给航空公司
  • 当前快讯:为填报高考志愿犯愁?南京这份紧缺人才需求目录也许能帮你(附创新产业岗位需求top5)

    交汇点讯这两天正值高考志愿填报,很多考生为选啥专业犯愁。在6月28日
  • 世界百事通!佩林卡:年轻球员在这个联盟中是很有影响力的 就像掘金的布劳恩

    今天,湖人为两位新秀席菲诺和马克斯维尔-刘易斯举行了新闻发布会,期
  • 中国正式接受WTO《渔业补贴协定》议定书 天天速看

    中新社北京6月27日电(记者李晓喻)中国商务部27日向世贸组织(WTO)递交中
  • 吉林省科技助力乡村振兴 专家服务工作交流会举行|世界热推荐

    吉林省科技助力乡村振兴专家服务工作交流会举行
  • 北京朝阳区户籍上朝阳区私立小学跨区转学要求|世界时快讯

    北京朝阳区开设了不少优质的私立小学,朝阳区人口密集,对学校的需求比
  • 诺贝尔奖百岁老人最后的愿望:汽车尾气 全部消失吧

    诺贝尔奖百岁老人最后的愿望:汽车尾气全部消失吧
  • 多国积极探索低碳农业之路(国际视点) 世界信息

    随着全球气候变化日益严峻,积极推动农业绿色低碳发展成为国际社会的共
  • 热点评!女儿高考估分635,父母高调办酒席庆祝,成绩出来后父母惨遭打脸

    无独有偶,其实每年高考过后,都会有一些家长“高兴的太早”,甚至直
  • 观察:白斑治疗!安康有哪些医院能治白癜风|推荐

    现在在生活种白癜风患者也是比较常见的,但是这种疾病对患者的影响还是
  • 柿落_关于柿落概略

    1、柿落,晋江文学城网络小说作家。文章到此就分享结束,希望对大家有
  • 世界今头条!因式分解概念及其公式 因式分解的概念教案

    今天来聊聊式分解概念及其公式,因式分解的概念教案的文章,现在就为大
  • 中概指数涨超3%-环球关注

    纳斯达克金龙中国指数一度上涨3 2%,成分股金山云涨9 4%,蔚来汽车目前
  • 韩晶:多措并举拓宽毕业生就业路|环球微动态

    今年高校毕业生预计将达到1158万人的历史新高。当前,毕业生就业工作已
  • 河南“书法家”作案后声称跳河,警方河里捞出帽子:是声东击西还是真跳河待查|当前热文

    6月27日,河南省商丘市永城市知情人士告诉上游新闻(报料邮箱:cnshang
  • 亿都(国际控股)(00259)6月27日耗资67.86万港元回购23.6万股_快播报

    来源:智通财经亿都(国际控股)(00259)公布,2023年6月27日耗资67 86万
  • 网传“在盒饭中发现疑似老鼠头” 重庆秀山县:认定异物为老鼠头

    据秀山网消息,6月27日,网传“在秀山县中医院食堂盒饭中疑似吃出老鼠
  • 什么叫柳下惠_柳下惠什么意思_观焦点

    1、柳下惠是对一些不乱的人的隐喻,他也描述了一些人的行为是正确的。
  • “创新融合发展共享共赢未来”2023首届中国城市酒店营销创新大会在西安隆重开幕

    2023年6月27日上午,2023首届中国城市酒店营销创新大会暨酒店管理论坛
  • 【环球报资讯】广康生化龙虎榜:机构净卖出710万元

    中国经济网北京6月27日讯广康生化(300804 SZ)今日股价收报39 35元,下

相关推荐

  • 天天微速讯:偶像文化的“水土不服
  • 我州狠抓招商引资促经济平稳增长
  • 今日份安利:PDF转Excel怎么转?_头条
  • 环球新动态:妖精的尾巴04(关于妖
  • 书单来了-书单网
  • 直播玩异度神剑2的弥央和火光p82-p8
  • 招联金融逾期四个月了会有什么后果
  • 大连造船与浙能集团签署绿色航运战
  • 高争民爆:2022年度权益分派10派1.5
  • 世界今热点:新时达:公司工业机器

阅读排行

  • Spring Boot 项目设计业务操作日志功能,写得太好了!
  • 密室逃脱之深红色房间下载(密室逃脱之深红色房间)
  • 精彩看点:关于皇马小将阿里巴斯的动向塞尔吉奥·阿里巴斯和皇...
  • 党建引领熔铸忠诚警魂|湖南日报|天天视点
  • 人才创新支撑江苏高水平科技自立自强
  • 电力ETF:融资净偿还561.77万元,融资余额3828.25万元(06-28)_全球独家
  • 缴费二维码,竟成驶离停车场“拦路码”
  • 天天微速讯:偶像文化的“水土不服”该被重视了
  • 我州狠抓招商引资促经济平稳增长
  • 今日份安利:PDF转Excel怎么转?_头条

联系方式:291 32 36@qq.com

Copyright © 1998-2023 by 中陕网版权 所有 京ICP备12018864号-5

营业执照公示信息