首页 > 滚动 > > 内容页

Spring @InitBinder注解使用及原理详解

2023-06-24 15:16:51 脚本之家
目录
前言一. @InitBinder注解使用说明二. 实现自定义Editor三. WebDataBinder初始化原理解析四. @InitBinder注解修饰的方法的加载总结

前言

由@InitBinder注解修饰的方法用于初始化WebDataBinder对象,能够实现:从request获取到handler方法中由@RequestParam注解或@PathVariable注解修饰的参数后,假如获取到的参数类型与handler方法上的参数类型不匹配,此时可以使用初始化好的WebDataBinder对获取到的参数进行类型处理。


(资料图)

一个经典的例子就是handler方法上的参数类型为Date,而从request中获取到的参数类型是字符串,SpringMVC在默认情况下无法实现字符串转Date,此时可以在由@InitBinder注解修饰的方法中为WebDataBinder对象注册CustomDateEditor,从而使得WebDataBinder能将从request中获取到的字符串再转换为Date对象。

通常,如果在@ControllerAdvice注解修饰的类中使用@InitBinder注解,此时@InitBinder注解修饰的方法所做的事情全局生效(前提是@ControllerAdvice注解没有设置basePackages字段);如果在@Controller注解修饰的类中使用@InitBinder注解,此时@InitBinder注解修饰的方法所做的事情仅对当前Controller生效。本篇文章将结合简单例子,对@InitBinder注解的使用,原理进行学习。

SpringBoot版本:2.4.1

一. @InitBinder注解使用说明

以前言中提到的字符串转Date为例,对@InitBinder的使用进行说明。

@RestController
public class DateController {
    private static final String SUCCESS = "success";
    private static final String FAILED = "failed";
    private final List dates = new ArrayList<>();
    @RequestMapping(value = "/api/v1/date/add", method = RequestMethod.GET)
    public ResponseEntity addDate(@RequestParam("date") Date date) {
        ResponseEntity response;
        try {
            dates.add(date);
            response = new ResponseEntity<>(SUCCESS, HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            response = new ResponseEntity<>(FAILED, HttpStatus.INTERNAL_SERVER_ERROR);
        }
        return response;
    }
}

上面写好了一个简单的Controller,用于获取Date并存储。然后在单元测试中使用TestRestTemplate模拟客户端向服务端发起请求,程序如下。

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class DateControllerTest {
    @Autowired
    private TestRestTemplate restTemplate;
    @Test
    void 测试Date字符串转换为Date对象() {
        ResponseEntity response = restTemplate
                .getForEntity("/api/v1/date/add?date=20200620", String.class);
        assertThat(response.getStatusCodeValue(), is(HttpStatus.OK.value()));
    }
}

由于此时并没有使用@InitBinder注解修饰的方法向WebDataBinder注册CustomDateEditor对象,运行测试程序时断言会无法通过,报错会包含如下信息。

Failed to convert value of type "java.lang.String" to required type "java.util.Date"

由于无法将字符串转换为Date,导致了参数类型不匹配的异常。

下面使用@ControllerAdvice注解和@InitBinder注解为WebDataBinder添加CustomDateEditor对象,使SpringMVC框架为我们实现字符串转Date。

@ControllerAdvice
public class GlobalControllerAdvice {
    @InitBinder
    public void setDateEditor(WebDataBinder binder) {
        binder.registerCustomEditor(Date.class,
                new CustomDateEditor(new SimpleDateFormat("yyyyMMdd"), false));
    }
}

此时再执行测试程序,断言通过。

小节:由@InitBinder注解修饰的方法返回值类型必须为void,入参必须为WebDataBinder对象实例。如果在@Controller注解修饰的类中使用@InitBinder注解则配置仅对当前类生效,如果在@ControllerAdvice注解修饰的类中使用@InitBinder注解则配置全局生效。

二. 实现自定义Editor

现在假如需要将日期字符串转换为LocalDate,但是SpringMVC框架并没有提供类似于CustomDateEditor这样的Editor时,可以通过继承PropertyEditorSupport类来实现自定义Editor。首先看如下的一个Controller。

@RestController
public class LocalDateController {
    private static final String SUCCESS = "success";
    private static final String FAILED = "failed";
    private final List localDates = new ArrayList<>();
    @RequestMapping(value = "/api/v1/localdate/add", method = RequestMethod.GET)
    public ResponseEntity addLocalDate(@RequestParam("localdate") LocalDate localDate) {
        ResponseEntity response;
        try {
            localDates.add(localDate);
            response = new ResponseEntity<>(SUCCESS, HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
            response = new ResponseEntity<>(FAILED, HttpStatus.INTERNAL_SERVER_ERROR);
        }
        return response;
    }
}

同样的在单元测试中使用TestRestTemplate模拟客户端向服务端发起请求。

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class LocalDateControllerTest {
    @Autowired
    private TestRestTemplate restTemplate;
    @Test
    void 测试LocalDate字符串转换为LocalDate对象() {
        ResponseEntity response = restTemplate
                .getForEntity("/api/v1/localdate/add?localdate=20200620", String.class);
        assertThat(response.getStatusCodeValue(), is(HttpStatus.OK.value()));
    }
}

此时直接执行测试程序断言会不通过,会报错类型转换异常。现在实现一个自定义的Editor。

public class CustomLocalDateEditor extends PropertyEditorSupport {
    private static final DateTimeFormatter dateTimeFormatter
            = DateTimeFormatter.ofPattern("yyyyMMdd");
    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        if (StringUtils.isEmpty(text)) {
            throw new IllegalArgumentException("Can not convert null.");
        }
        LocalDate result;
        try {
            result = LocalDate.from(dateTimeFormatter.parse(text));
            setValue(result);
        } catch (Exception e) {
            throw new IllegalArgumentException("CustomDtoEditor convert failed.", e);
        }
    }
}

CustomLocalDateEditor是自定义的Editor,最简单的情况下,通过继承PropertyEditorSupport并重写setAsText() 方法可以实现一个自定义Editor。通常,自定义的转换逻辑在setAsText() 方法中实现,并将转换后的值通过调用父类PropertyEditorSupport的setValue() 方法完成设置。

同样的,使用@ControllerAdvice注解和@InitBinder注解为WebDataBinder添加CustomLocalDateEditor对象。

@ControllerAdvice
public class GlobalControllerAdvice {
    @InitBinder
    public void setLocalDateEditor(WebDataBinder binder) {
        binder.registerCustomEditor(LocalDate.class,
                new CustomLocalDateEditor());
    }
}

此时再执行测试程序,断言全部通过。

小节:通过继承PropertyEditorSupport类并重写setAsText()方法可以实现一个自定义Editor

三. WebDataBinder初始化原理解析

已经知道,由@InitBinder注解修饰的方法用于初始化WebDataBinder,并且在详解SpringMVC-RequestMappingHandlerAdapter这篇文章中提到:从request获取到handler方法中由@RequestParam注解或@PathVariable注解修饰的参数后,便会使用WebDataBinderFactory工厂完成对WebDataBinder的初始化。下面看一下具体的实现。

AbstractNamedValueMethodArgumentResolver#resolveArgument部分源码如下所示。

public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
        NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
    // ...
    // 获取到参数
    Object arg = resolveName(resolvedName.toString(), nestedParameter, webRequest);
    // ...
    if (binderFactory != null) {
        // 初始化WebDataBinder
        WebDataBinder binder = binderFactory.createBinder(webRequest, null, namedValueInfo.name);
        try {
            arg = binder.convertIfNecessary(arg, parameter.getParameterType(), parameter);
        }
        catch (ConversionNotSupportedException ex) {
            throw new MethodArgumentConversionNotSupportedException(arg, ex.getRequiredType(),
                    namedValueInfo.name, parameter, ex.getCause());
        }
        catch (TypeMismatchException ex) {
            throw new MethodArgumentTypeMismatchException(arg, ex.getRequiredType(),
                    namedValueInfo.name, parameter, ex.getCause());
        }
        if (arg == null && namedValueInfo.defaultValue == null &&
                namedValueInfo.required && !nestedParameter.isOptional()) {
            handleMissingValue(namedValueInfo.name, nestedParameter, webRequest);
        }
    }
    handleResolvedValue(arg, namedValueInfo.name, parameter, mavContainer, webRequest);
    return arg;
}

实际上,上面方法中的binderFactory是ServletRequestDataBinderFactory工厂类,该类的类图如下所示。

createBinder() 是由接口WebDataBinderFactory声明的方法,ServletRequestDataBinderFactory的父类DefaultDataBinderFactory对其进行了实现,实现如下。

public final WebDataBinder createBinder(
        NativeWebRequest webRequest, @Nullable Object target, String objectName) throws Exception {
    // 创建WebDataBinder实例
    WebDataBinder dataBinder = createBinderInstance(target, objectName, webRequest);
    if (this.initializer != null) {
        // 调用WebBindingInitializer对WebDataBinder进行初始化
        this.initializer.initBinder(dataBinder, webRequest);
    }
    // 调用由@InitBinder注解修饰的方法对WebDataBinder进行初始化
    initBinder(dataBinder, webRequest);
    return dataBinder;
}

initBinder() 是DefaultDataBinderFactory的一个模板方法,InitBinderDataBinderFactory对其进行了重写,如下所示。

public void initBinder(WebDataBinder dataBinder, NativeWebRequest request) throws Exception {
    for (InvocableHandlerMethod binderMethod : this.binderMethods) {
        if (isBinderMethodApplicable(binderMethod, dataBinder)) {
            // 执行由@InitBinder注解修饰的方法,完成对WebDataBinder的初始化
            Object returnValue = binderMethod.invokeForRequest(request, null, dataBinder);
            if (returnValue != null) {
                throw new IllegalStateException(
                        "@InitBinder methods must not return a value (should be void): " + binderMethod);
            }
        }
    }
}

如上,initBinder() 方法中会遍历加载的所有由@InitBinder注解修饰的方法并执行,从而完成对WebDataBinder的初始化。

小节:WebDataBinder的初始化是由WebDataBinderFactory先创建WebDataBinder实例,然后遍历WebDataBinderFactory加载好的由@InitBinder注解修饰的方法并执行,以完成WebDataBinder的初始化。

四. @InitBinder注解修饰的方法的加载

由第三小节可知,WebDataBinder的初始化是由WebDataBinderFactory先创建WebDataBinder实例,然后遍历WebDataBinderFactory加载好的由@InitBinder注解修饰的方法并执行,以完成WebDataBinder的初始化。本小节将学习WebDataBinderFactory如何加载由@InitBinder注解修饰的方法。

WebDataBinderFactory的获取是发生在RequestMappingHandlerAdapter的invokeHandlerMethod() 方法中,在该方法中是通过调用getDataBinderFactory() 方法获取WebDataBinderFactory。下面看一下其实现。

RequestMappingHandlerAdapter#getDataBinderFactory源码如下所示。

private WebDataBinderFactory getDataBinderFactory(HandlerMethod handlerMethod) throws Exception {
    // 获取handler的Class对象
    Class handlerType = handlerMethod.getBeanType();
    // 从initBinderCache中根据handler的Class对象获取缓存的initBinder方法集合
    Set methods = this.initBinderCache.get(handlerType);
    // 从initBinderCache没有获取到initBinder方法集合,则执行MethodIntrospector.selectMethods()方法获取handler的initBinder方法集合,并缓存到initBinderCache中
    if (methods == null) {
        methods = MethodIntrospector.selectMethods(handlerType, INIT_BINDER_METHODS);
        this.initBinderCache.put(handlerType, methods);
    }
    // initBinderMethods是WebDataBinderFactory需要加载的initBinder方法集合
    List initBinderMethods = new ArrayList<>();
    // initBinderAdviceCache中存储的是全局生效的initBinder方法
    this.initBinderAdviceCache.forEach((controllerAdviceBean, methodSet) -> {
        // 如果ControllerAdviceBean有限制生效范围,则判断其是否对当前handler生效
        if (controllerAdviceBean.isApplicableToBeanType(handlerType)) {
            Object bean = controllerAdviceBean.resolveBean();
            // 如果对当前handler生效,则ControllerAdviceBean的所有initBinder方法均需要添加到initBinderMethods中
            for (Method method : methodSet) {
                initBinderMethods.add(createInitBinderMethod(bean, method));
            }
        }
    });
    // 将handler的所有initBinder方法添加到initBinderMethods中
    for (Method method : methods) {
        Object bean = handlerMethod.getBean();
        initBinderMethods.add(createInitBinderMethod(bean, method));
    }
    // 创建WebDataBinderFactory,并同时加载initBinderMethods中的所有initBinder方法
    return createDataBinderFactory(initBinderMethods);
}

上面的方法中使用到了两个缓存,initBinderCache和initBinderAdviceCache,表示如下。

private final Map, Set> initBinderCache = new ConcurrentHashMap<>(64);
private final Map> initBinderAdviceCache = new LinkedHashMap<>();

其中initBinderCache的key是handler的Class对象,value是handler的initBinder方法集合,initBinderCache一开始是没有值的,当需要获取handler对应的initBinder方法集合时,会先从initBinderCache中获取,如果获取不到才会调用MethodIntrospector#selectMethods方法获取,然后再将获取到的handler对应的initBinder方法集合缓存到initBinderCache中。

initBinderAdviceCache的key是ControllerAdviceBean,value是ControllerAdviceBean的initBinder方法集合,initBinderAdviceCache的值是在RequestMappingHandlerAdapter初始化时调用的afterPropertiesSet() 方法中完成加载的,具体的逻辑在详解SpringMVC-RequestMappingHandlerAdapter有详细说明。

因此WebDataBinderFactory中的initBinder方法由两部分组成,一部分是写在当前handler中的initBinder方法(这解释了为什么写在handler中的initBinder方法仅对当前handler生效),另外一部分是写在由@ControllerAdvice注解修饰的类中的initBinder方法,所有的这些initBinder方法均会对WebDataBinderFactory创建的WebDataBinder对象进行初始化。

最后,看一下createDataBinderFactory() 的实现。

RequestMappingHandlerAdapter#createDataBinderFactory

protected InitBinderDataBinderFactory createDataBinderFactory(List binderMethods)
        throws Exception {
    return new ServletRequestDataBinderFactory(binderMethods, getWebBindingInitializer());
}

ServletRequestDataBinderFactory#ServletRequestDataBinderFactory

public ServletRequestDataBinderFactory(@Nullable List binderMethods,
        @Nullable WebBindingInitializer initializer) {
    super(binderMethods, initializer);
}

InitBinderDataBinderFactory#InitBinderDataBinderFactory

public InitBinderDataBinderFactory(@Nullable List binderMethods,
        @Nullable WebBindingInitializer initializer) {
    super(initializer);
    this.binderMethods = (binderMethods != null ? binderMethods : Collections.emptyList());
}

可以发现,最终创建的WebDataBinderFactory实际上是ServletRequestDataBinderFactory,并且在执行ServletRequestDataBinderFactory的构造函数时,会调用其父类InitBinderDataBinderFactory的构造函数,在这个构造函数中,会将之前获取到的生效范围内的initBinder方法赋值给InitBinderDataBinderFactory的binderMethods变量,最终完成了initBinder方法的加载。

小节:由@InitBinder注解修饰的方法的加载发生在创建WebDataBinderFactory时,在创建WebDataBinderFactory之前,会先获取对当前handler生效的initBinder方法集合,然后在创建WebDataBinderFactory的构造函数中将获取到的initBinder方法集合加载到WebDataBinderFactory中。

总结

由@InitBinder注解修饰的方法用于初始化WebDataBinder,从而实现请求参数的类型转换适配,例如日期字符串转换为日期Date类型,同时可以通过继承PropertyEditorSupport类来实现自定义Editor,从而增加可以转换适配的类型种类。

以上就是Spring @InitBinder注解使用及原理详解的详细内容,更多关于Spring @InitBinder注解原理的资料请关注脚本之家其它相关文章!

x 广告
最近更新

Spring @InitBinder注解使用及原理详解

2023-06-24

到底造句问句_到底造句

2023-06-24

6月份沪牌拍卖结果公布,中标率11.5%

2023-06-24

即时:​浙江龙游县发生5车追尾事故致6人死亡

2023-06-24

世界讯息:高考生查分竟显示“0分”?老师知道后喜笑颜开,985大学随便选

2023-06-24

世界最资讯丨全国性赛事!阳江帆船队包揽男子甲组冠亚军

2023-06-24

成都宇辉人才市场最新招聘_成都宇辉人才市场 即时看

2023-06-24

黄山旅游集团成功发行8亿元优质旅游类公司债券

2023-06-24

拔牙后不能吃哪些食物_拔牙之后不能吃什么食物

2023-06-24

全球今热点:2023年 年轻人被迫流行功能机了?

2023-06-24

环球热门:丿这个符号怎么打 丿这个符号怎么打

2023-06-24

宋曌晗

2023-06-24

创维 EV6 II 汽车上市:CLTC 续航最高 620 公里,15.68 万元起

2023-06-23

环球观速讯丨红楼梦梗概每回200字左右_红楼梦梗概每回

2023-06-23

端午小长假第二日 西安大唐不夜城迎大量游客

2023-06-23

黄海波到底犯了什么事_黄海波犯了什么事 世界新消息

2023-06-23

全球快资讯:水利部和中国气象局联合发布橙色山洪灾害气象预警

2023-06-23

天天热推荐:i never told you歌曲_i never told you陈冠希

2023-06-23

新华全媒+|沉浸式体验!沪苏轨交11号线“牵手”亮点满满

2023-06-23

当前消息!立体爱心怎么折步骤图片_用钱叠戒指的步骤图片

2023-06-23

端午假期首日,北京各公园景区总收入与去年同期相比增加615%

2023-06-23

“昨夜你答应我的,你这个臭流氓!”连云港健身模特大赛内幕曝光-当前最新

2023-06-23

“熊猫邮局”登上列车 熊猫专列移动邮局首次发车

2023-06-23

知名女星戚薇爆被潜规则,7天7夜500万,不同意就删除戏份!

2023-06-23

秀才书院秀文笔 乡宁才子书院品菊韵

2023-06-23

到 2020 年 比特币 价格超过 30,000 美元的 3 个主要原因

2023-06-23

图书情报专硕就业前景_图书情报硕士就业前景|环球今头条

2023-06-23

每日热点:多地优化住房公积金提取政策

2023-06-23

算命先生说:3星座不简单,下半年红鸾星闪耀,你准备好脱单了吗_看点

2023-06-23

全球今热点:世体主编:老佛爷正在亲自和巴黎老板谈姆巴佩转会,越过了纳赛尔

2023-06-23

银行也会要的!福建一老板不收破的10元,男子和老板吵半个小时 热点

2023-06-23

半个好莱坞来捧场他的LV首秀,结果满场马赛克?

2023-06-23

米家自动化抄作业之:六 门口自动化门未关提醒-天天最新

2023-06-23

年产可达数百万 龙舟背后的“生意经”|当前时讯

2023-06-22

不服不行,国产安卓第一,还得是它们 天天速递

2023-06-22

天天微动态丨今日pd990钯金回收价格查询(2023年06月22日)

2023-06-22

快播:做好数据的统计和分析工作_如何做好数据统计工作

2023-06-22

高温天气下 美国得州一邮递员工作时死亡 焦点报道

2023-06-22

当前短讯!小高考是什么意思?考几门_小高考是什么

2023-06-22

天天最资讯丨纪录片如何在国际舞台上讲好中国故事?

2023-06-22

天天微速讯:姚琛上海虹馆热烈开唱 首场海外粉丝见面会即将开唱

2023-06-22

首都机场临空经济区入选首批“首都跨境电商新生态”共建单位

2023-06-22

我国最长深水油气管道铺设完工_焦点要闻

2023-06-22

ChatGPT:驶进人工智能与汽车行业的新篇章

2023-06-22

电脑怎么连接手柄(电脑怎么连接扫描仪)

2023-06-22

关于人生路坎坷的句子_坎坷人生路感悟句子-世界头条

2023-06-22

七一二:6月21日融资买入2695.07万元,融资融券余额2.69亿元

2023-06-22

天天微速讯:男方提出离婚需要怎么写离婚协议

2023-06-22

老婆生日送什么礼物合适_老婆生日送什么礼物_天天热资讯

2023-06-22

世界看热讯:dec中恒导航仪使用_中恒导航仪如何更新地图

2023-06-22

镇报集团等推出“我们的节日·端午”H5互动产品

2023-06-22

交往礼仪论文2000字(交往礼仪)

2023-06-22

安倍晋三菠萝_安倍沙罗

2023-06-22

国家能源局原监管总监李冶一行到西电常变、西高院常州公司视察指导

2023-06-21

8个领域、39个发展方向!广东发布新型储能技术创新路线图

2023-06-21

新能源汽车车辆购置税减免政策延长至2027年年底|世界快播

2023-06-21

广州发展(600098.SH):2023年度财务主要预算指标营业总收入516.2亿元

2023-06-21

topgear20季2集(topgear20季)

2023-06-21

英马斯集团(08136)发布年度业绩 股东应占溢利612.6万港元 同比减少46.13% 新要闻

2023-06-21

环球消息!戴姆勒卡车CEO称对公司2023年财务表现充满信心

2023-06-21

不审核直接放款5000的平台有哪些 这些审核门槛低容易借款

2023-06-21

天天头条:家里蹲大学生是什么意思(家里蹲大学)

2023-06-21

夏至.诗词|每日动态

2023-06-21

新田:夏至时节插秧忙 世界今日报

2023-06-21

环球快消息!2023陕西高考一分一段表公布 理科成绩排名出炉

2023-06-21

当前看点!吉利百矿集团国家级铝产业研究院办公区域项目主体结构提前封顶

2023-06-21

全球看热讯:证监会同意恒达新材等3家公司创业板IPO注册

2023-06-21

从“台前”到“幕后”,北京国安幕后支持者,中赫集团的艰与难

2023-06-21

广东省养老金上调今日公布最新消息了吗?广东养老金上调方案2023计算方法最新消息 天天简讯

2023-06-21

总决赛期间喜迎爱的结晶!乐福夫妇近日首次公开爱子照片-环球报资讯

2023-06-21

刘昌用:密码经济是一个朝气蓬勃的领域

2023-06-21

员工离职“顺走”企业商业秘密获刑_视讯

2023-06-21

从“村BA”到“村超”,是赛事更是新路|快播报

2023-06-21

全球热头条丨2023呼和浩特玉泉区幼儿园录取结果查询时间及官网入口

2023-06-21

甘肃省市场监管局等八部门联合推进服务认证 全面促进服务业高质量发展

2023-06-21

百普赛斯(301080):6月20日北向资金减持5.13万股 天天视讯

2023-06-21

当前看点!ps文字有下划线怎么去掉_ps中文字的下划线如何去除

2023-06-21

中央六套节目表电视猫(中央六套节目表)-今日热文

2023-06-21

环球快看点丨2023年06月20日股市盘中盘后重要消息

2023-06-21

20万元能存银行大额存单吗?有什么技巧?

2023-06-20

环球头条:工行陕西分行大兴调查研究之风 推动主题教育走深走实

2023-06-20

每日焦点!乔治白:公司以职业装定制服务为主

2023-06-20

热消息:明天开始到6月底鸿运当头的生肖

2023-06-20

昆明到抚仙湖直通车_昆明到抚仙湖

2023-06-20

深中通道东人工岛主体结构施工全面完成

2023-06-20

容州路(关于容州路介绍)

2023-06-20

关于哭的文案-焦点热闻

2023-06-20

你已进入无人监考考场!这8个班352名学生自愿赴考,不仅仅完成了学业大考-天天滚动

2023-06-20

武契奇:金砖国家潜力巨大,与塞尔维亚未来几代人息息相关

2023-06-20

怎么查询手机流量剩余(怎么查询手机流量剩余多少) 当前资讯

2023-06-20

端午节假期,洛阳龙门站将增开旅客列车 焦点速读

2023-06-20

出借银行卡帮助“代购” 两女子被三亚警方拘留|全球热闻

2023-06-20

【小康路上看老乡】陇南成县:绿色田园种出“彩色庄稼” 圣女果实力圈粉闯市场

2023-06-20

农机企业创新要紧盯实用好用

2023-06-20

世界速读:全新DS 4将于7月13日国内上市 具有跨界风格

2023-06-20

充电5分钟,续航200公里!江苏超级快充示范充电站来啦!|天天观察

2023-06-20

汝城县朱敏:退役不褪色 干出新精彩

2023-06-20

【全球新视野】hpv18阳性是什么意思_女性hpv阳性怎么办

2023-06-20

粤港澳大湾区车展新能源车盘点,腾势N7、小鹏G6等

2023-06-20

小米耳机和红米耳机

2023-06-20

有声记忆 2级部分(对于有声记忆 2级部分简单介绍)

2023-06-20

了解 Stable Diffusion 的一些基础术语 天天关注

2023-06-20

U23摔跤亚锦赛落幕 中国队收获8金3银1铜

2023-06-19

来头不小!这位“顶流”来广西定居,后来有人为他建了一栋建筑……|天天看热讯

2023-06-19

乌军反攻受挫 俄军展示缴获的法国制造装甲战车

2023-06-19

防御“龙舟水” 科技利器齐上阵

2023-06-19

2023年6月19日《万宁新闻》完整版 天天报道

2023-06-19

双黄米酒招商加盟官网主站

2023-06-19

人民日报:在教育“双减”中做好科学教育加法

2023-06-19

当前热点-宇邦新材:850万股限售股6月27日解禁

2023-06-19

明细账的对应科目怎么填_企业明细账填写模板-世界资讯

2023-06-19

四川天府新区举办“舞动绿色、跳动青春”环保主题运动会

2023-06-19

热议:厦门生育险交9个月就生了能报销吗?究竟是怎么回事?

2023-06-19

朗姿股份:拟3800万元参与设立医美创投基金

2023-06-19

12VHPWR 电源连接器再次熔化 这次是从 PSU 端开始

2023-06-19

天天日报丨布林肯访问是否会鼓励更多美方官员来访华?外交部回应

2023-06-19

突发!波音撞上空客 机身剧烈抖动 资讯

2023-06-19

世界今日讯!开增值税专用发票资料_开增值税专用发票需要提供什么资料

2023-06-19

每日资讯:让非遗绽放更加迷人的光彩!一起看看宝山吹塑版画的前世今生

2023-06-19

华侨城A(000069.SZ)1-5月销售金额170亿元 同比增11%

2023-06-19

加拿大人口2021总人数 当前头条

2023-06-19

《狂野之心》现已推出“凶恶彼岸飞”内容更新-速讯

2023-06-19

简讯:登峰书屋:初高中衔接公益讲座第四期

2023-06-19

山西36个县区享受法考“放宽政策” 今日热搜

2023-06-19

沪深股通|威海广泰6月16日获外资买入0.02%股份

2023-06-19

健身房回应男子满背疙瘩进泳池:皮肤病不准下水,会加强监管-环球时快讯

2023-06-19

【世界报资讯】威胜信息旗下威铭能源“NB-IoT物联网水表软件V1.0”入选2023年度湖南省首版次软件产品认定名单

2023-06-19

卫星化学高开2.7% 速读

2023-06-19

世界观点:iPhone 14 Plus白屏解决方法介绍

2023-06-19

2019年保育员工作总结 天天动态

2023-06-19

世界短讯!内测和公测的区别 内测

2023-06-19

玖姿哪里的品牌女装 玖姿哪里的品牌女装是正品

2023-06-19

采购经理人资格证书_采购资格证书 全球消息

2023-06-19

2017国庆节看天安门升旗时间表 提前几点去排队合适

2023-06-19

环球热头条丨研究揭示复杂脑自发活动中意识状态简要神经表征

2023-06-18

高铁轴承产业化进程缓慢 国机精工未按期收回对参股公司的借款

2023-06-18

环球速看:第一回合就KO对手!蒂姆·茨尤击败奥坎波,剑指世界拳王小查洛

2023-06-18

外域食谱出处_外域食谱

2023-06-18

深圳东莞影视后期制作有前途吗

2023-06-18

辽阳公安纪检部门找准“小切口”推动“大转变”

2023-06-18

世界头条:越来越安卓化的iOS17,路还能走多远?

2023-06-18

容大感光最新公告:上半年净利同比预增98%-128%

2023-06-18

捷信分期买手机逾期怎么办_捷信分期买手机靠谱吗 今日视点

2023-06-18

研究揭示了遵循地中海饮食的另一个重要原因|世界热文

2023-06-18

永州市医学会举办心理学与精神病学专业委员会2023年年会暨精神心理卫生知识培训班

2023-06-18

每日消息!三星s7屏幕锁密码_三星s7屏幕

2023-06-18

@高考考生,快来领取你的专属福利!|当前快讯

2023-06-18

一分钟入戏三分钟追完,如何看待追剧短视频?

2023-06-18

白酒板块午盘微跌 贵州茅台股价涨0.49%-环球播报

2023-06-18

国际乒联7月大变动!陈梦将重回第2,孙颖莎太稳,王曼昱跌到垫底-今日快讯

2023-06-18

政务管家团值守“办不成事”窗口,帮市民办理疑难问题_天天要闻

2023-06-18

焦点滚动:第一次信息技术革命标志_第一次信息技术革命

2023-06-18

会成队友吗?阿德巴约曾穿比尔球衣接受采访 球衣秒变紧身衣

2023-06-18

当前热门:从梅西到村超:天气很热 球迷们的热情更热

2023-06-18

世界微头条丨耀州区气象台发布大雾黄色预警【Ⅲ级/较重】【2023-06-18】

2023-06-18

观天下!橙锤属性增强_橙锤属性

2023-06-18

今日最新!618买啥都别买洗地机 纯纯大冤种!

2023-06-18

每日热议!向佐高调宣示家庭幸福!网友惊叹:这才是郭碧婷婚姻的正确打开方式!

2023-06-18

乘地铁被冤枉偷拍的成都男子再发声:已准备起诉!

2023-06-18

文件顽固删不掉怎么办(金山文件粉碎机详细使用方法) 环球微速讯

2023-06-18

关注:伊能静,内娱最后的纯爱战士。

2023-06-18

多图+视频丨龙舟不仅比快还要比美!彩龙竞艳,哪款你最“心水”? 天天热消息

2023-06-17

东吴证券:5月餐饮等服务消费继续恢复 后续关注可选消费品6月大促表现 每日速看

2023-06-17

dnf银色陨石在哪换(dnf银色陨石)|天天热门

2023-06-17

iPhone中开启双重认证功能的步骤 当前速递

2023-06-17

世界通讯!张杰的腾讯微博_张杰腾讯微博

2023-06-17

【天天报资讯】值得深思的生活感悟

2023-06-17

江苏雷利:子公司荣获国家级专精特新“小巨人”企业认定|全球观点

2023-06-17

每日看点!广州港南沙港区:海铁联运串联湾区连接世界

2023-06-17

创业板或见底 港股可看高一线

2023-06-17

奥伊米亚康村是哪个国家的(奥伊米亚康村)

2023-06-17

最后卢小嘉死的很惨吗(暴揍黄金荣的军阀之子卢小嘉的结局)-焦点快播

2023-06-17

美国计划向乌克兰提供F-16战机 俄称已向美方发出外交照会

2023-06-17

马克龙宣布多项举措促进低排放飞机研发

2023-06-17

一个地址可以注册几个公司厦门_一个地址可以注册几个公司 环球头条

2023-06-17

世界互联网大会数字文明尼山对话将举行 全球头条

2023-06-17

今日聚焦!2023闵行区爱心暑托班报名攻略(时间+入口+步骤)

2023-06-17

消费市场继续回升向好!5月份社会消费品零售总额同比增长12.7%-焦点简讯

2023-06-17

顺利完成首航!佛山机场最高礼遇迎接“佛山号”彩绘飞机-每日速递

2023-06-17

今日看点:军体格斗术1-5组合分解动作图解_军体格斗术

2023-06-17

凭借《无名》《长空之王》,王一博收获首个电影专业表演奖

2023-06-17

公交“车医生” 钻“烤箱”修车

2023-06-17

秦皇岛市举办中式烹调师技能大赛

2023-06-17

敦煌沙漠旅游“火热”进行时

2023-06-17

全球速读:中国西电(601179):6月16日北向资金增持568.42万股

2023-06-17

主板IPO年内第二单“暂缓表决”!两大问题绊住巍华新材

2023-06-17

又一90后干部被查!龚建华受审!美国查获大案,足以杀死210万人……

2023-06-17

区块链的代币和人工智能的股票为何不能等同看待

2023-06-17

春天,针织衫依然很流行,搭配牛仔裤或者半身裙,更加时髦有品位

2023-06-17

23年金球奖:梅西输给哈兰德

2023-06-17

谁在“唱衰”宁德时代?

2023-06-17

excel官方网(excel下载官方网)-热头条

2023-06-17

普京:第一部分核装置已运抵白俄罗斯境内

2023-06-16

焦点速递!豌豆笑传漫画全集阅读下载_豌豆笑传漫画全集阅读

2023-06-16

青春激扬 筑梦空港|河南郑州航空港举行“高校学子港区行”活动 激发青年才俊来港就业创业激情

2023-06-16

王一博获最受传媒关注男主角 徐峥赵雅芝钟欣潼等助阵颁奖礼 热闻

2023-06-16

马桶 承重_马桶承重多少会蹲坏-环球百事通

2023-06-16

吹掉单刀!裁判有多帮国足?结束哨引争议,缅甸球员教练不满

2023-06-16

环保标语大全_100条_环保条幅标语大全

2023-06-16

Berry Avenue 代码——我们什么时候可以期待它们?_天天即时看

2023-06-16