2021-01-31

5年老码农,update语句误用一个双引号,生产数据全变0了

一、前言

最近经常碰到开发误删除误更新数据,这不,他们又给我找了个麻烦,我们来看下整个过程,把我坑得够惨。2021Java面试宝典

二、过程

由于开发需要在生产环节中修复数据,需要执行120条SQL语句,需要将数据进行更新,于是开发连上了生产数据库,首先执行了第一条SQL

update tablename set source_name = "bj1062-北京市朝阳区常营北辰福第" where source_name =  "-北京市朝阳区常营北辰福第"

我们仔细看了下,这个SQL,的确没有什么问题,where条件也是正常的,大意就是将这个地址的前面加字符串bj1062,是真的没有错误么?是的没有错误。开发执行完成后,结果的确是符合预期。

然后开发执行了剩下的SQL,都是和上面的SQL一样,将地址进行更新。执行完成后,开发懵逼了,发现source_name都变成了0,开发赶紧给我打电话说:

涛哥,我执行了update,where条件都是对的,set的值也是对的,但是set后的字段全部都变成了0,你赶紧帮我看看,看看能不能恢复数据。

我赶紧登上服务器,查看了这段时间的binlog,发现了大量的update tablename set source_name=0的语句,利用binlog2sql进行了解析,项目地址:

binlog2sql github.com/danfengcao/…

 

 

赶紧和开发确定了操作的时间点,生成flashback的SQL,进行了数据恢复,同时保留现场证据。

然后对开发执行的SQL进行了check,发现了几条很诡异的SQL

这几条SQL的引号位置跑到了where 字段名字后面,简化后的SQL变成了:

update tbl_name set str_col="xxx" = "yyy"

那么这个SQL在MySQL他是如何进行语义转化的呢?

可能是下面这样的么?

update tbl_name set (str_col="xxx" )= "yyy"

这样就语法错误了,那么只会是下面这样的形式,

update tbl_name set str_col=("xxx" = "yyy")

select "xxx" = "yyy" 

的值是0,所以

update tbl_name set str_col="xxx" = "yyy"

等价于

update tbl_name set str_col=0

所以就导致了source_name字段全部更新成了0.

我们再研究下select形式这种语句会怎么样。

mysql [localhost] {msandbox} (test) > select id,str_col from tbl_name where str_col="xxx" = "yyy";+----+---------+| id | str_col |+----+---------+| 1 | aaa  || 2 | aaa  || 3 | aaa  || 4 | aaa  |+----+---------+

我们发现,这个SQL将str_col='aaa'的记录也查找出来了,为什么呢?

mysql [localhost] {msandbox} (test) > warningsShow warnings enabled.mysql [localhost] {msandbox} (test) > explain extended select id,str_col from tbl_name where str_col="xxx" = "yyy"\G*************************** 1. row ***************************   id: 1 select_type: SIMPLE  table: tbl_name   type: indexpossible_keys: NULL   key: idx_str  key_len: 33   ref: NULL   rows: 4  filtered: 100.00  Extra: Using where; Using index1 row in set, 1 warning (0.00 sec)Note (Code 1003): /* select#1 */ select `test`.`tbl_name`.`id` AS `id`,`test`.`tbl_name`.`str_col` AS `str_col` from `test`.`tbl_name` where ((`test`.`tbl_name`.`str_col` = 'xxx') = 'yyy')

这里他把where条件转化成了

((`test`.`tbl_name`.`str_col` = 'xxx') = 'yyy')

这个条件的首先判断str_col 和'xxx'是否相等,如果相等,那么里面括号的值为1,如果不相等,就是0

然后0或者1再和和'yyy'进行判断,由于等号一边是int,另外一边是字符串,两边都转化为float进行比较,这就是MySQL中隐式转换导致的查询结果出现错误。'yyy'转化为浮点型为0,0和0比较恒等于1

mysql [localhost] {msandbox} (test) > select 'yyy'+0.0;+-----------+| 'yyy'+0.0 |+-----------+|   0 |+-----------+1 row in set, 1 warning (0.00 sec)mysql [localhost] {msandbox} (test) > select 0=0;+-----+| 0=0 |+-----+| 1 |+-----+1 row in set (0.00 sec)

这样导致结果恒成立,也就是select语句等价于以下SQL

select id,str_col from tbl_name where 1=1;

将查询出所有的记录。

三、小结

在写SQL的过程中,一定要小心引号的位置是否正确,有时候引号位置错误,SQL依然是正常的,但是却会导致执行结果全部错误。在执行前必须在测试环境执行测试,结合IDE的语法高亮发现相应的问题。2021Java面试宝典












原文转载:http://www.shaoqun.com/a/521240.html

跨境电商:https://www.ikjzd.com/

tineye:https://www.ikjzd.com/w/448

智邦:https://www.ikjzd.com/w/2376


一、前言最近经常碰到开发误删除误更新数据,这不,他们又给我找了个麻烦,我们来看下整个过程,把我坑得够惨。2021Java面试宝典二、过程由于开发需要在生产环节中修复数据,需要执行120条SQL语句,需要将数据进行更新,于是开发连上了生产数据库,首先执行了第一条SQLupdatetablenamesetsource_name="bj1062-北京市朝阳区常营北辰福第"wheres
打折网:打折网
捷汇:捷汇
口述:我的婚姻遭遇冷暴力(2/2):口述:我的婚姻遭遇冷暴力(2/2)
韩蓬:一站式、全自动化亚马逊广告投放和优化解决方案:韩蓬:一站式、全自动化亚马逊广告投放和优化解决方案
世界杯捞金大法:世界杯捞金大法

2021最新 SpringMVC面试题精选(附刷题小程序)

推荐使用小程序阅读

为了能让您更加方便的阅读
本文所有的面试题目均已整理至小程序《面试手册
可以通过微信扫描(或长按)下图的二维码享受更好的阅读体验!

ah_xct


目录
  • 推荐使用小程序阅读
  • 1. Spring MVC基础
    • 1.1 什么是Spring MVC?
    • 1.2 Spring MVC的优点有那些?
    • 1.3 Spring MVC的主要组件?
    • 1.4 什么是DispatcherServlet?
    • 1.5 什么是Spring MVC框架的控制器?
    • 1.6 Spring MVC的控制器是单例的吗?
    • 1.7 Spring MVC的单例控制器会带来什么问题?如何处理?
    • 1.8 简述一下DispatcherServlet 的工作流程
    • 1.9 MVC是什么?
    • 1.10 MVC设计模式的好处有哪些?
    • 1.11 Spring MVC与Struts2区别?
    • 1.12 WebApplicationContext有什么作用?
  • 2. Spring MVC注解
    • 2.1 注解原理是什么?
    • 2.2 Spring MVC常用的注解有哪些?
    • 2.3 Sping MVC中的控制器注解是什么?
    • 2.4 @Controller注解的作用
    • 2.5 @RequestMapping注解的作用?
    • 2.6 @ResponseBody注解的作用是什么?
    • 2.7 @PathVariable和@RequestParam的区别?
  • 3. Spring MVC运用
    • 3.1 Spring MVC怎么样设定重定向和转发的?
    • 3.2 Spring MVC怎么和AJAX相互调用的?
    • 3.3 Spring MVC如何解决GET、POST请求中文乱码问题?
    • 3.4 Spring MVC如何处理异常?
    • 3.5 Spring MVC如何拦截GET请求?
    • 3.6 如何在方法里面得到Request,或者Session?
    • 3.7 Spring MVC如何获取请求传参?
    • 3.8 SpringMVC多个参数如何优雅接收?
    • 3.9 Spring MVC中函数的返回值是什么?
    • 3.10 Spring MVC用什么对象从后台向前台传递数据的?
    • 3.11 怎么把ModelMap里面的数据放入Session里面?
    • 3.12 Spring MVC拦截器如何使用?
  • 4. 其他
    • 4.1 SpringMVC 中系统如何分层 ?


1. Spring MVC基础

1.1 什么是Spring MVC?

Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把模型-视图-控制器分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。

1.2 Spring MVC的优点有那些?

  1. 可以支持各种视图技术,而不仅仅局限于JSP;
  2. 与Spring框架集成(如IoC容器、AOP等);
  3. 清晰的角色分配:
    • 前端控制器(dispatcherServlet) ;
    • 请求到处理器映射(handlerMapping);
    • 处理器适配器(HandlerAdapter);
    • 视图解析器(ViewResolver)。
  4. 支持各种请求资源的映射策略。

1.3 Spring MVC的主要组件?

  1. DispatcherServlet:
    中央控制器,把请求给转发到具体的控制类
  2. Controller:
    具体处理请求的控制器
  3. HandlerMapping:
    映射处理器,负责映射中央处理器转发给controller时的映射策略
  4. ModelAndView:
    服务层返回的数据和视图层的封装类
  5. ViewResolver:
    视图解析器,解析具体的视图
  6. Interceptors :
    拦截器,负责拦截我们定义的请求然后做处理工作

1.4 什么是DispatcherServlet?

Spring的MVC框架是围绕DispatcherServlet来设计的,它用来处理所有的HTTP请求和响应。

1.5 什么是Spring MVC框架的控制器?

控制器提供一个访问应用程序的行为,此行为通常通过服务接口实现。控制器解析用户输入并将其转换为一个由视图呈现给用户的模型。Spring用一个非常抽象的方式实现了一个控制层,允许用户创建多种用途的控制器。

1.6 Spring MVC的控制器是单例的吗?

是单例的。

1.7 Spring MVC的单例控制器会带来什么问题?如何处理?

  • 问题
    多线程访问的时候有线程安全问题;
  • 解决方案
    在控制器里面不能写字段。

1.8 简述一下DispatcherServlet 的工作流程

  1. 用户发送请求至前端控制器DispatcherServlet;
  2. DispatcherServlet收到请求后,调用HandlerMapping处理器映射器,请求获取Handle;
  3. 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
  4. DispatcherServlet 调用 HandlerAdapter处理器适配器;
  5. HandlerAdapter 经过适配调用 具体处理器(Handler,也叫后端控制器);
  6. Handler执行完成返回ModelAndView;
  7. HandlerAdapter将Handler执行结果ModelAndView返回给DispatcherServlet;
  8. DispatcherServlet将ModelAndView传给ViewResolver视图解析器进行解析;
  9. ViewResolver解析后返回具体View;
  10. DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)
  11. DispatcherServlet响应用户。

1.9 MVC是什么?

MVC是一种设计模式:

  • 模型(model)
  • 视图(view)
  • 控制器(controller)

三层架构的设计模式。用于实现前端页面的展现与后端业务数据处理的分离。

1.10 MVC设计模式的好处有哪些?

  1. 分层设计,实现了业务系统各个组件之间的解耦,有利于业务系统的可扩展性,可维护性。

  2. 有利于系统的并行开发,提升开发效率。

1.11 Spring MVC与Struts2区别?

  • 相同点

    都是基于mvc的表现层框架,都用于web项目的开发。

  • 不同点

    1. 前端控制器不一样。Spring MVC的前端控制器是servlet:DispatcherServlet。struts2的前端控制器是filter:StrutsPreparedAndExcutorFilter。

    2. 请求参数的接收方式不一样。Spring MVC是使用方法的形参接收请求的参数,基于方法的开发,线程安全,可以设计为单例或者多例的开发,推荐使用单例模式的开发(执行效率更高),默认就是单例开发模式。struts2是通过类的成员变量接收请求的参数,是基于类的开发,线程不安全,只能设计为多例的开发。

    3. Struts采用值栈存储请求和响应的数据,通过OGNL存取数据,Spring MVC通过参数解析器是将request请求内容解析,并给方法形参赋值,将数据和视图封装成ModelAndView对象,最后又将ModelAndView中的模型数据通过reques域传输到页面。Jsp视图解析器默认使用jstl。

    4. 与spring整合不一样。Spring MVC是spring框架的一部分,不需要整合。在企业项目中,Spring MVC使用更多一些。

1.12 WebApplicationContext有什么作用?

WebApplicationContext 继承了ApplicationContext 并增加了一些WEB应用必备的特有功能,它不同于一般的ApplicationContext ,因为它能处理主题,并找到被关联的servlet。

2. Spring MVC注解

2.1 注解原理是什么?

注解本质是一个继承了Annotation的特殊接口,其具体实现类是Java运行时生成的动态代理类。我们通过反射获取注解时,返回的是Java运行时生成的动态代理对象。通过代理对象调用自定义注解的方法,会最终调用AnnotationInvocationHandler的invoke方法。该方法会从memberValues这个Map中索引出对应的值。而memberValues的来源是Java常量池。

2.2 Spring MVC常用的注解有哪些?

  • @RequestMapping
    用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中的所有响应请求的方法都是以该地址作为父路径。

  • @RequestBody
    注解实现接收http请求的json数据,将json转换为java对象。

  • @ResponseBody
    注解实现将conreoller方法返回对象转化为json对象响应给客户。

2.3 Sping MVC中的控制器注解是什么?

一般用@Controller注解;
也可以使用@RestController

@RestController注解相当于@ResponseBody + @Controller

2.4 @Controller注解的作用

在Spring MVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理层处理之后封装成一个Model ,然后再把该Model 返回给对应的View 进行展示。在Spring MVC 中提供了一个非常简便的定义Controller 的方法,你无需继承特定的类或实现特定的接口,只需使用@Controller 标记一个类是Controller ,然后使用@RequestMapping 和@RequestParam 等一些注解用以定义URL 请求和Controller 方法之间的映射,这样的Controller 就能被外界访问到。此外Controller 不会直接依赖于HttpServletRequest 和HttpServletResponse 等HttpServlet 对象,它们可以通过Controller 的方法参数灵活的获取到。

@Controller 用于标记在一个类上,使用它标记的类就是一个Spring MVC Controller 对象。分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping 注解。@Controller 只是定义了一个控制器类,而使用@RequestMapping 注解的方法才是真正处理请求的处理器。单单使用@Controller 标记在一个类上还不能真正意义上的说它就是Spring MVC 的一个控制器类,因为这个时候Spring 还不认识它。那么要如何做Spring 才能认识它呢?这个时候就需要我们把这个控制器类交给Spring 来管理。有两种方式:

  • 在Spring MVC 的配置文件中定义MyController 的bean 对象。
  • 在Spring MVC 的配置文件中告诉Spring 该到哪里去找标记为@Controller 的Controller 控制器。

2.5 @RequestMapping注解的作用?

RequestMapping是一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。

RequestMapping注解有六个属性

  • value
    指定请求的实际地址,指定的地址可以是URI Template 模式(后面将会说明);

  • method
    指定请求的method类型, GET、POST、PUT、DELETE等;

  • consumes
    指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;

  • produces:
    指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回;

  • params
    指定request中必须包含某些参数值是,才让该方法处理。

  • headers
    指定request中必须包含某些指定的header值,才能让该方法处理请求。

2.6 @ResponseBody注解的作用是什么?

  • 作用
    该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。

  • 使用时机
    返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、

2.7 @PathVariable和@RequestParam的区别?

  • @PathVariable
    可以用来获取请求路线上面的变量;
    如请求路径 >@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)

    来获取路径在的变量id

  • @RequestParam
    用来获得静态的URL请求入参 spring注解时action里用到。

3. Spring MVC运用

3.1 Spring MVC怎么样设定重定向和转发的?

  • 转发
    在返回值前面加"forward:"
    如:"forward:user.do?name=method4"

  • 重定向
    在返回值前面加"redirect:",
    如:"redirect id="32-spring-mvc怎么和ajax相互调用的?">3.2 Spring MVC怎么和AJAX相互调用的?

    通过Jackson框架就可以把Java里面的对象直接转化成Js可以识别的Json对象。具体步骤如下 :

    1. 加入Jackson.jar

    2. 在配置文件中配置json的映射

    3. 在接受Ajax方法里面可以直接返回Object,List等,但方法前面要加上@ResponseBody注解。

    3.3 Spring MVC如何解决GET、POST请求中文乱码问题?

    • GET乱码:

      • 方式一:
        修改tomcat配置文件添加编码与工程编码一致,如下:

        <ConnectorURIEncoding="utf-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
      • 方式二:
        参数进行重新编码:

        String userName = new String(request.getParamter("userName").getBytes("ISO8859-1"),"utf-8")

        ISO8859-1是tomcat默认编码,需要将tomcat编码后的内容按utf-8编码。

    • POST请求乱码问题:
      在web.

      <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param>  <param-name>encoding</param-name>  <param-value>utf-8</param-value> </init-param></filter><filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern></filter-mapping>

    3.4 Spring MVC如何处理异常?

    可以将异常抛给Spring框架,由Spring框架来处理;我们只需要配置简单的异常处理器,在异常处理器中添视图页面即可

    3.5 Spring MVC如何拦截GET请求?

    可以在@RequestMapping注解里面加上method=RequestMethod.GET。

    3.6 如何在方法里面得到Request,或者Session?

    直接在方法的形参中声明request,Spring MVC就自动把request对象传入。

    3.7 Spring MVC如何获取请求传参?

    直接在方法的形参里面声明这个参数就可以

    名字和传过来的参数一样。

    3.8 SpringMVC多个参数如何优雅接收?

    直接在方法中声明这个对象,Spring MVC就自动会把属性赋值到这个对象里面。

    3.9 Spring MVC中函数的返回值是什么?

    返回值可以有很多类型,有String, ModelAndView。ModelAndView类把视图和数据都合并的一起的,但一般用String比较好。

    3.10 Spring MVC用什么对象从后台向前台传递数据的?

    通过ModelMap对象,可以在这个对象里面调用put方法,把对象加到里面,前台就可以通过el表达式拿到。

    3.11 怎么把ModelMap里面的数据放入Session里面?

    可以在类上面加上@SessionAttributes注解,里面包含的字符串就是要放入session里面的key。

    3.12 Spring MVC拦截器如何使用?

    • 定义拦截器,实现HandlerInterceptor接口;接口中提供三个方法。

      • preHandle
        进入 Handler方法之前执行,用于身份认证、身份授权,比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行
      • postHandle
        进入Handler方法之后,返回modelAndView之前执行,应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图
      • afterCompletion
        执行Handler完成执行此方法,应用场景:统一异常处理,统一日志处理
    • 拦截器配置

      • 针对HandlerMapping配置(不推荐):
        SpringMVC拦截器针对HandlerMapping进行拦截设置,如果在某个HandlerMapping中配置拦截,经过该 HandlerMapping映射成功的handler最终使用该 拦截器。(一般不推荐使用)
      • 类似全局的拦截器
        SpringMVC配置类似全局的拦截器,SpringMVC框架将配置的类似全局的拦截器注入到每个HandlerMapping中

    4. 其他

    4.1 SpringMVC 中系统如何分层 ?

    • 系统分为表现层(UI):
      数据的展现,操作页面,请求转发。
    • 业务层(服务层):
      封装业务处理逻辑
    • 持久层(数据访问层):
      封装数据访问逻辑

    各层之间的关系: 表示层通过接口调用业务层,业务层通过接口调用持久层,这样,当下一层发生变化改变,不影响上一层的数据。 MVC是一种表现层的架构


    感谢您的点赞、评论、关注;
    您还可以扫码关注"公众号"获取粉丝福利。









    原文转载:http://www.shaoqun.com/a/521232.html

    跨境电商:https://www.ikjzd.com/

    折扣网:https://www.ikjzd.com/w/74

    eprice:https://www.ikjzd.com/w/1325


    推荐使用小程序阅读为了能让您更加方便的阅读本文所有的面试题目均已整理至小程序《面试手册》可以通过微信扫描(或长按)下图的二维码享受更好的阅读体验!目录推荐使用小程序阅读1.SpringMVC基础1.1什么是SpringMVC?1.2SpringMVC的优点有那些?1.3SpringMVC的主要组件?1.4什么是DispatcherServlet?1.5什么是SpringMVC框架的控制器?1.6S
    weebly:weebly
    etoro:etoro
    做亚马逊,对不同的产品要用不同的方法!:做亚马逊,对不同的产品要用不同的方法!
    购物车权重算法改变!大多数卖家都忽略了这个变化!:购物车权重算法改变!大多数卖家都忽略了这个变化!
    口述:我拒绝男友求欢 他哭得我心烦意乱:口述:我拒绝男友求欢 他哭得我心烦意乱

所以说读者们才是最优秀的 | 某读者喜提offer后的分享

这是小编的一个读者喜提offer后在群里做的分享,文中隐藏了读者的个人隐私信息,小编这里把他的面经分享出来供大家学习。
群友们看到后都纷纷表示【我酸了,现在我就是个柠檬精系列】。

file
file

关于如何学习/准备面试的总结

首先说一说本人的情况

本人普通本科,非计算机专业(之前一直对这个耿耿于怀,后来想通了觉得60%从事软件开发的都是非计算机专业,之后的面试直接说我是非计算机专业,这一块的诚实很重要,
也没有必要瞒着,因为公司看中的是你的开发能力,能不能帮公司解决问题)。对于群里的大牛来说,看了之后肯定会笑话我,哈哈,不过我的能力就这么大,每年有进步就很开心。

怎么学习群主的帖子

群主基本每周都会对帖子有更新,我是一个比较细心的人,每天上班去公司要2个小时左右,然后在地铁上的时间都会在看群主的帖子,一是为了拓展见识,二是为了夯实基础知识。对于我公司开发项目有相似的帖子,会进行收藏,之后做好笔记,理解群主说这个技术栈的思路,为什么要这样搞,而不是单单的对里边的理论知识进行记忆,这一点很重要,特别是面试的时候能说出这些东西,都可以让面试官耳目一新。

我记得特别深刻的是群主在kafak和spark那一块的讲解,kafka怎么实现实时性(pagecage页缓存,顺序写磁盘,零复制技术等等),面试官问到这一块的时候,我都有说的很详细,然后面试官都会跟我说:嗯,你的基础能力很扎实。还有spark调优那一块,这个是我的强项。我把自己掌握和实践中用的方法用自己的语言总结了一部分(数据倾斜,内存溢出,开发调优,资源调优,shuffle调优等),每一个点都能够自己总结出一个例子出来,说给面试官听,之后面试官都会给出高度的评价。

注意事项

知识的学习要结合自己简历中的项目和技术架构,不能原封不动的抄袭;公司做的有哪些项目,那么安排上,再从群主的帖子里去找灵感,这一点很重要,你不能拿着没有做过的项目来套这些东西,因为一个项目会牵涉到业务场景,项目背景以及实现中的很多细节,乱编的项目肯定有考虑不到的地方,有一些细节都会被问出来,结果让面试官对你产生了怀疑。基于真实项目的技术架构,吸收帖子里边的一些思想,加上自己的思考,这样进步就会很快。

遇到的面试题

Java基础

JVM优化和多线程必问。

数仓必问

mapreduce的底层原理(shuffle重点);hivesql怎么转化为mapreduce;数据倾斜怎么处理(大表join大表,大小表join,参数调优等等);hive的优化;数仓分层细节,数仓建模;拉链表;缓慢变化维;星型模型和雪花模型区别;数据库三范式;事实表的分类;具体场景写sql;

Spark部分

spark的运行原理;spark数据倾斜;spark内存溢出;spark的调优;spark的rdd算子细节(map,mappartition,groupbykey,reducebykey等等很多,需要自己逐一的梳理);sparksql(sparksql怎么解析、dataframe、dateset);spark的内存模型;spark的shuffle原理,shuffle优化。

kafka部分

kafak负载均衡;kafka数据一致性;kafka的ack机制;kafka的exact once语义;kafka分区策略;kafka分区的目的等等。

zk部分

zk选举机制,zk用到的算法;zk的数据一致性;zk 节点宕机如何处理;负载均衡;zk一些接口。

hbase

读写原理;rowkey设计;热点问题;数据版本;habse的优化。

elasticsearch

es的读写原理;es的倒排索引;es的优化(重点必问);场景下的es提问。

自己的感受

感觉越往高级的面,就会倾向于问你组件调优以及架构方面的知识:如分布式;CAP理论;数据一致性以及知识掌握的全面性,这些部分都是我需要学习的地方,不说了,再说就感觉自己的水平很low了,哈哈。

然后就是写简历的时候不贪多,把每个项目的实现细节都给搞清楚,很容易就面过,基于此我基本每家单位的一面都能过,二面三面的时候一方面看知识的深度,另一方面靠自己的表达能力。最后就是感觉现在好多公司喜欢搞数据中台,数据治理这一块,这一块我在我们公司搞过一点,感觉可能也是一个加分项。

最后弱弱的给小编打个广告,后台回复【知识星球】,可以加到圈子里来。未来一段时间都在持续更新面试题系列。
欢迎关注,《大数据成神之路》系列文章

欢迎关注,《大数据成神之路》系列文章

欢迎关注,《大数据成神之路》系列文章









原文转载:http://www.shaoqun.com/a/521222.html

跨境电商:https://www.ikjzd.com/

stylenanda:https://www.ikjzd.com/w/1675.html

贸发局:https://www.ikjzd.com/w/1621


这是小编的一个读者喜提offer后在群里做的分享,文中隐藏了读者的个人隐私信息,小编这里把他的面经分享出来供大家学习。群友们看到后都纷纷表示【我酸了,现在我就是个柠檬精系列】。关于如何学习/准备面试的总结首先说一说本人的情况本人普通本科,非计算机专业(之前一直对这个耿耿于怀,后来想通了觉得60%从事软件开发的都是非计算机专业,之后的面试直接说我是非计算机专业,这一块的诚实很重要,也没有必要瞒着,因
浩方:浩方
let go:let go
小米和Jumia开启无缝合作 / 又一批亚马逊卖家信息被泄露:小米和Jumia开启无缝合作 / 又一批亚马逊卖家信息被泄露
外贸课堂:给外贸新人的5个小提示,让你少走弯路!:外贸课堂:给外贸新人的5个小提示,让你少走弯路!
情感口述:孤单已经成为了习惯;伪装坚强也成为了一种习惯:情感口述:孤单已经成为了习惯;伪装坚强也成为了一种习惯

男人护好前列腺,一定要记住这5个护腺常识

核心提示:蔬菜水果对前列腺健康也起着很重要的作用,我们平时常吃的苹果就有保护前列腺的功效,瑞士研究者表示,这可能是苹果中的锌在起作用。

  前列腺作为男性特有的腺体,是男人的健康卫士,可以分泌稀薄奶样的前列腺液,构成了精液的一部分。当男人40岁以后,前列腺体积开始增长,50岁以上的男性大概有一半患良性前列腺增生症。护好前列腺,男人一定要记住这些护腺常识!

  1、前列腺也会"感冒"

  很多人不知道,前列腺也是怕冷的器官。在冬天除了心血管疾病和呼吸疾病,男人的前列腺疾病也会因气温急降而发作。因此,天气冷了,前列腺也要防寒保暖。

  冬季降温后要及时增加衣物,着装、鞋袜、坐垫要保暖;特别是身体下半身切勿受寒,外出时不要坐在石凳上。

  2、抽烟太多会"扰腺"

  黑夜里一副深邃的眼神,再加上一根没抽完的香烟,勾勒出了一副魅力熟男的画面。

  然而现实中,抽烟太多会危害前列腺。香烟中的烟碱、焦油、尼古丁、亚硝胺类等有毒物质能干扰支配血管的神经功能,使前列腺血液循环受影响,从而导致前列腺充血。香烟的有毒物质还会直接毒害前列腺组织,使功能紊乱,抵抗力下降,导致疾病发生。

  因此,男人要尽量避免抽烟,这不仅是为了你的心血管健康,还为了你的前列腺。


  3、纵欲、寡欲都伤前列腺

  虽说纵欲是前列腺的"大敌",但寡欲亦非前列腺"伙伴"。性生活适度最和谐。

  性生活太频繁会导致前列腺过度充血,诱发前列腺炎。而过度压抑性欲,则会使前列腺液大量囤积,诱发炎症。


原文转载:http://health.shaoqun.com/a/148975.html

跨境电商:https://www.ikjzd.com/

grab:https://www.ikjzd.com/w/841

代购公司:https://www.ikjzd.com/w/1982


核心提示:蔬菜水果对前列腺健康也起着很重要的作用,我们平时常吃的苹果就有保护前列腺的功效,瑞士研究者表示,这可能是苹果中的锌在起作用。   前列腺作为男性特有的腺体,是男人的健康卫士,可以分泌稀薄奶样的前列腺液,构成了精液的一部分。当男人40岁以后,前列腺体积开始增长,50岁以上的男性大概有一半患良性前列腺增生症。护好前列腺,男人一定要记住这些护腺常识!  1、前列腺也会"感冒"  很多人不知道,
递四方:递四方
海豚村:海豚村
口述:我爱爱时做面膜 害老公性冷淡爱爱爱美美容:口述:我爱爱时做面膜 害老公性冷淡爱爱爱美美容
怎么办?Facebook广告表现越来越差了!:怎么办?Facebook广告表现越来越差了!
英国最受欢迎的50个B2C网站:英国最受欢迎的50个B2C网站

258斤锡安多强壮?单挑字母哥推土机上篮,两届MVP被碾压力量完败_鹈鹕

原标题:258斤锡安多强壮?单挑字母哥推土机上篮,两届MVP被碾压力量完败

北京时间1月30日,鹈鹕爆了一个不小的冷门,他们掀翻了东部夺冠热门雄鹿。这一战,锡安和字母哥上演了NBA顶级的天赋对决,状元郎表现不输两届MVP,两人在场上的单挑镜头,锡安还欺负了字母哥。

这场比赛锡安得到了21分9篮板7助攻,是球队爆冷的大工程。字母哥下半场复苏,拿到了38分11篮板5助攻2抢断2封盖,无奈在落后29分的情况下,没能大逆转。

比赛第三节还剩1分14秒,两人上演了直接对话。锡安低位单挑字母哥,他持球面筐,随后转身背打字母哥。体重达到了258斤的锡安利用身体顶住了字母哥,他直接扛着字母哥往篮下走。

就像是一辆推土机,锡安把字母哥顶到了篮下。众所周知,字母哥也是这个联盟的天赋怪,有着超长的臂展和惊人的弹跳,但是,在力量对抗上,字母哥根本顶不住锡安。

杀到篮下,锡安强起,顶开了字母哥,拉杆上篮。字母哥被彻底压制,甚至无法起跳封盖,只能举着双手,但是形同虚设。

相比上赛季,锡安还是让人看到了进步。上赛季两队的交手,字母哥没少封盖锡安,但现在鹈鹕状元打法更加丰富了,而且,他还会传球,没有一味蛮干,7次助攻就是最好的说明。如果锡安能持续进步,鹈鹕还是有机会触底反弹,打进季后赛,毕竟现在他们距离西部第八的开拓者也只有2个胜场的差距。返回搜狐,查看更多

责任编辑:

原文转载:http://sport.shaoqun.com/a/389636.html

跨境电商:https://www.ikjzd.com/

易趣:https://www.ikjzd.com/w/210

腾邦:https://www.ikjzd.com/w/1382


原标题:258斤锡安多强壮?单挑字母哥推土机上篮,两届MVP被碾压力量完败北京时间1月30日,鹈鹕爆了一个不小的冷门,他们掀翻了东部夺冠热门雄鹿。这一战,锡安和字母哥上演了NBA顶级的天赋对决,状元郎表现不输两届MVP,两人在场上的单挑镜头,锡安还欺负了字母哥。这场比赛锡安得到了21分9篮板7助攻,是球队爆冷的大工程。字母哥下半场复苏,拿到了38分11篮板5助攻2抢断2封盖,无奈在落后29分的情况
雨果:雨果
五洲会海购:五洲会海购
亚马逊更新时尚类商品名称要求 / 亚马逊将推出八月银行假日促销:亚马逊更新时尚类商品名称要求 / 亚马逊将推出八月银行假日促销
亚马逊信用卡海淘选择(刷单):亚马逊信用卡海淘选择(刷单)
做亚马逊侵权,可不是闹着玩的:做亚马逊侵权,可不是闹着玩的

2021-01-30

在对外太空的探索中拍摄到的不明飞行物,到底如何解释?

人类的好奇和幻想总是无限的,对于幻想人们的第一想法就是不断去探寻,不断去认知,人类对于天空外太空的认知从古代就一直存在着,从最早的神话中后羿射日,嫦娥奔月,天圆地方的理论都表现了人们不断的求知欲。虽然很多人说但是感兴趣,也不能私自到外太空进行探索,但是这一次的事件就是发生在一个民众的身上,通过自己的天文摄影机拍摄到了难得的不明飞行物,到底是什么?

图片5.png 

  这次出现在外太空的不明飞行物像是UFO一直环绕在月球的周围,很多人都说这一次拍摄的有可能就是环绕在月球周围的探测器,但是通过仔细的对于拍照者的视频进行研究,他的样子还有外形,都并不像探测器,反而像UFO的构造。就有很多人说这一次所谓的视频很可能就是视频的发表者自己p图进行编造的,对于外太空中UFO的想法总是多种多样的。

   都说外太空是永无止境的,是人类还没有完全探索的。就算是月球的背面也是人类所没有到达的。所以都有着它不为人知的秘密,或者是没有探索清楚的事件。对于外太空,对于大自然我们一定要保持敬畏,还有探索的热情。就算有些事情经过验证后结果并不尽如人意。但是人类的认知永远都比不上大自然的鬼斧神工。总有一天会真相水落石出的。




原文转载:http://tech.shaoqun.com/a/317688.html

跨境电商:https://www.ikjzd.com/

巴克莱:https://www.ikjzd.com/w/2775

海拍客:https://www.ikjzd.com/w/1742


人类的好奇和幻想总是无限的,对于幻想人们的第一想法就是不断去探寻,不断去认知,人类对于天空外太空的认知从古代就一直存在着,从最早的神话中后羿射日,嫦娥奔月,天圆地方的理论都表现了人们不断的求知欲。虽然很多人说但是感兴趣,也不能私自到外太空进行探索,但是这一次的事件就是发生在一个民众的身上,通过自己的天文摄影机拍摄到了难得的不明飞行物,到底是什么?这次出现在外太空的不明飞行物像是UFO一直环绕在月球
yiqu:yiqu
Sunrate:Sunrate
重磅消息!亚马逊发货限制下调!:重磅消息!亚马逊发货限制下调!
蓝海国家! 2019年俄罗斯网购人数比例增长10%:蓝海国家! 2019年俄罗斯网购人数比例增长10%
亚马逊店铺被关后,你的产品竟被别人拿来赚钱?!:亚马逊店铺被关后,你的产品竟被别人拿来赚钱?!

“洞察”号火星探测器成功在火星埃律西昂平原着陆!

  11月26日,“洞察”号火星探测器成功在火星埃律西昂平原着陆,开始了对火星内部结构和现象的探测。

  “洞察”号着陆的埃律西昂平原是一片火星赤道附近的巨大的火山平原,距离“好奇”号火星车着陆的盖尔撞击坑仅约600公里。

  而就在数天前,美国国家航空航天局(NASA)还公布了下一代火星车“火星2020”号的计划着陆地点。

  杰泽罗撞击坑从三个备选着陆点中脱颖而出,成为了“火星2020”号火星车的目的地。

  虽然火星的个头相对地球要小,但在其约一亿四千万平方公里的表面上为价值连城的火星探测器选定一个合适的着陆点仍然不是一件容易的事,需要工程师与科学家相互配合共同完成。

  和地球一样,火星表面有各种地形地貌,既有一望无际的平原,又有深达6000米的峡谷和落差达27000米的太阳系第一高山。

  对于地球上的汽车驾驶员来说,在平坦的地面上停车显然要比把车停在斜坡上更为容易,因为既不用担心汽车溜坡,也不用在起步时实施相对复杂的坡起流程。
  对于火星车来说,在相对平坦的地形上着陆同样是风险更小、成功率更高的选择。火星的地形存在明显的南北差异。

  南半球遍布着高低起伏的山脉与峡谷,及大大小小的陨石坑,北半球的地形则相对比较平坦。因此,除了具备特殊探测使命的探测器外,绝大多数的火星着陆探测器都降落在北半球及赤道附近。

  探测器在着陆时,一般都需要通过与大气相互作用来减速,在着陆的最后阶段才使用自身发动机提供的动力实现软着陆。

  火星的大气相对稀薄,如果着陆点的地理高程(与地球上的海拔概念类似)过高,那么探测器还没有被大气充分减速时就已经与火星表面接触。因此,一般都要选择高程较低的区域作为着陆点。

  长时间在火星工作的探测器要借助太阳能电池来产生电力。同时,用来导航和检测障碍的光敏感器也需要较好的光照条件。

  火星的高纬地区无法获得充足的光照,因此火星探测器大都会选择在纬度小于30度的区域着陆。

  低纬度地区良好的光照条件也带来了比较温和的昼夜温差,不会像高纬度地区那样出现极端的昼夜温差和夜间低温,从而使探测器更容易维持自身的热平衡。

  如果探测器不慎降落在一片充满岩石的区域,将会给探测器的工作带来很大的麻烦。

  岩石会破坏探测器的着陆缓冲机构,阻碍减速发动机的正常工作。

  同时,对于火星车来说,遍布的岩石还会对它们的移动带来阻碍。因此,一般要选择岩石较为稀少的地方作为着陆点。

  除了在火星上着陆的探测器外,还有MRO、MAVEN等探测器以围绕火星飞行的方式为我们带来火星的全球信息。

  利用这些轨道器的探测数据,科学家和工程师们可以对火星各个区域是否符合以上硬性约束做出判断,给出可能的着陆点选项。



原文转载:http://tech.shaoqun.com/a/317686.html

跨境电商:https://www.ikjzd.com/

ask me:https://www.ikjzd.com/w/2459

东西网:https://www.ikjzd.com/w/1238


11月26日,&ldquo;洞察&rdquo;号火星探测器成功在火星埃律西昂平原着陆,开始了对火星内部结构和现象的探测。&ldquo;洞察&rdquo;号着陆的埃律西昂平原是一片火星赤道附近的巨大的火山平原,距离&ldquo;好奇&rdquo;号火星车着陆的盖尔撞击坑仅约600公里。而就在数天前,美国国家航空航天局(NASA)还公布了下一代火星车&a
ask me:ask me
prezi:prezi
2019征战全球万亿市场,跨境电商如何All in?:2019征战全球万亿市场,跨境电商如何All in?
店铺流量不发愁,阿里速卖通这项服务来助力!:店铺流量不发愁,阿里速卖通这项服务来助力!
亚马逊FBA清库存神器:亚马逊Outlet!:亚马逊FBA清库存神器:亚马逊Outlet!

Soul中使用的zookeeper监听功能尝试和nacos同步源码解读

Soul中使用的zookeeper监听功能尝试

一直很好奇soul中基于zookeeper的数据变更是如何做到的。虽然看到了是基于zkClient的实现的,还是想自己尝试下

zookeeper监听尝试

首先新建一个maven项目,引入zkClient

  <dependency>   <groupId>com.101tec</groupId>   <artifactId>zkclient</artifactId>   <version>0.10</version>  </dependency>

尝试着对zokkeeper中的数据和节点做一些改变,而这个改变就是Soul使用zookeeper中对于插件,选择器和规则变化将其映射到zookeeper上的结果

public class ZkClientTest { public static final String connect = "127.0.0.1:2181"; private static ZkClient zkClient = null; private static String nodePath = "/zkclient1"; private static String nodeChildPath = "/zkclient1/n1/n11/n111/n1111"; public static void main(String[] args) throws Exception{  //初始化  init(connect,5000);  //订阅节点数据改变或者子节点变化,只需要订阅一次,便可以一直使用。而原生zookeeper的监听是一次性的,需要重复注册。  subscribe();  //新增  create(nodePath,"n1");  //递归新增  createRecursion(nodeChildPath,"n1");  //查询  query(nodePath);  //修改  update(nodePath,"n11");  //单个节点删除//  delete(nodePath);  //递归删除  deleteRecursion(nodePath);  Thread.sleep(5000); } private static void deleteRecursion(String path) {  boolean result = zkClient.deleteRecursive(path);  System.out.println("delete:"+"["+path+"],result:"+result); } private static void delete(String path) {  boolean result = zkClient.delete(path);  System.out.println("delete:"+"["+path+"],result:"+result); } private static void update(String path, String data) {  zkClient.writeData(path, data);  System.out.println();  //System.out.println("setData:"+"["+path+"],stat:"+stat); } private static void query(String path) {  Object o = zkClient.readData(path);  System.out.println("query:"+"["+path+"],result:"+o); } private static void createRecursion(String path,String data) {  zkClient.createPersistent(path,true);  System.out.println("create:"+"["+path+"-->"+data); } private static void create(String path, String data) {  boolean exists = zkClient.exists(path);  if(exists){   System.out.println("节点["+path+"]已存在,不能新增");   return;  }  String result = zkClient.create(path, data, CreateMode.PERSISTENT);  System.out.println("create:"+"["+path+"-->"+data+"],result:"+result); } private static void subscribe() {  //订阅节点内容改变  zkClient.subscribeDataChanges(nodePath, new IZkDataListener() {     public void handleDataChange(String dataPath, Object data) throws Exception {      System.out.println("handleDataChange----->"+dataPath+"|"+data);     }     public void handleDataDeleted(String dataPath) throws Exception {      System.out.println("handleDataDeleted----->"+dataPath);     }    }  );  //订阅子节点改变  zkClient.subscribeChildChanges(nodePath, new IZkChildListener() {   public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {    System.out.println("handleChildChange----->"+parentPath+"|"+currentChilds);   }  }); } private static void init(String connect, int sessionTimeout) {  zkClient = new ZkClient(connect, sessionTimeout); }}

具体的日志表现如下图所示
file
而在具体的zKclient类中可以看到,zkclient实际上是维护了一个while循环用来监听数据以及节点的变化
file
这就是Soul在ZookeeperDataChangedListener实际使用的具体的时候的具体使用的方案
file

Soul中Nacos是如何监听数据变化的

nacos的监听与zk类似,soul中的nacos一开始就监听了soul各个层级的数据的变化

 /**  * Start.  */ public void start() {  watcherData(PLUGIN_DATA_ID, this::updatePluginMap);  watcherData(SELECTOR_DATA_ID, this::updateSelectorMap);  watcherData(RULE_DATA_ID, this::updateRuleMap);  watcherData(META_DATA_ID, this::updateMetaDataMap);  watcherData(AUTH_DATA_ID, this::updateAuthMap); }

然后通过函数式编程的方式将数据通过各个方法更新到缓存中

 protected void watcherData(final String dataId, final OnChange oc) {  Listener listener = new Listener() {   @Override   public void receiveConfigInfo(final String configInfo) {    oc.change(configInfo);   }   @Override   public Executor getExecutor() {    return null;   }  };  oc.change(getConfigAndSignListener(dataId, listener));  LISTENERS.getOrDefault(dataId, new ArrayList<>()).add(listener); }

这里的最关键是Listener接口的获取配置信息的两个方法。可以看到这个即是通过预先定义号的元数据id,规则id来进行监听数据是否发生变化的

上面就是nacos和zookeeper监听数据变化的过程,现在可以想到。不管是配置中心或者注册中心。数据变化的监听都是有必要的,可以为使用的应用做出跟随配置改变而改变应用逻辑的能力。这也是Soul网关中很重要的一项能力

欢迎搜索关注本人与朋友共同开发的微信面经小程序【大厂面试助手】和公众号【微瞰技术】,以及总结的分类面试题https://github.com/zhendiao/JavaInterview

file
file









原文转载:http://www.shaoqun.com/a/521198.html

跨境电商:https://www.ikjzd.com/

indiegogo:https://www.ikjzd.com/w/265

tenso:https://www.ikjzd.com/w/1552


Soul中使用的zookeeper监听功能尝试一直很好奇soul中基于zookeeper的数据变更是如何做到的。虽然看到了是基于zkClient的实现的,还是想自己尝试下zookeeper监听尝试首先新建一个maven项目,引入zkClient<dependency><groupId>com.101tec</groupId><artifactId>z
西农:西农
gem:gem
2020黑五网一在即!船长BI带你解锁旺季制胜大招:2020黑五网一在即!船长BI带你解锁旺季制胜大招
你还在发自嗨式的开发信吗?:你还在发自嗨式的开发信吗?
口述:女友讲述和上司在车里的爱爱经历:口述:女友讲述和上司在车里的爱爱经历

丁俊晖微笑认输!赛前5字豪言被打脸,外媒:为糟糕表现付出代价_鲁姆普

原标题:丁俊晖微笑认输!赛前5字豪言被打脸,外媒:为糟糕表现付出代价

北京时间1月30日凌晨,2021斯诺克德国大师赛8进4淘汰赛,丁俊晖3-5不敌特鲁姆普,遗憾出局。赛前,丁俊晖表示,"我没那么差。"但事实证明,丁俊晖状态很一般。赛后,《eurosport》直言,特鲁姆普状态一般,但还是赢了,因为丁俊晖表现糟糕。

前三局,丁俊晖状态低迷。第一局,一番防守后,丁俊晖打进左侧底袋红球,但蓝球不进。特鲁姆普单杆17分清到蓝球后,以61-34先胜一局。第二局,世界第一单杆101分清至蓝球,以102-2再胜一局,大比分2-0领先。第三局,鲁姆普再获上手机会,单杆79分,以84-0再胜一局,大比分3-0领先。

9局5胜制的比赛,丁俊晖0-3开局,局面相当被动。

丁俊晖没有放弃,第四局,丁俊晖打进上手,单杆83分,以87-0扳回一局,大比分1-3进入中场休息。第五局,丁俊晖单杆93分一杆清台,以133-6再扳一局,大比分追至2-3。可惜第六局,丁俊晖本来有机会,但自己连续失误,2-4送出赛点。第七局,特鲁姆普出现失误,丁俊晖扳回一城。第八局,双方鏖战,都有机会,但丁俊晖连续漏球,最终输掉比赛。

最后时刻,丁俊晖犯规被罚4分后认输,甚至,丁俊晖还笑了,这是礼貌性的微笑,丁俊晖用笑容在恭喜对手特鲁姆普拿下胜利。

赛前,丁俊晖表示,"自从上赛季英锦赛夺冠后,我还没赢得过冠军,我正期待着赢得另一个冠军,我没那么差!"

赛后,《eurosport》总结了这场比赛,直言特鲁姆普其实状态一般,但丁俊晖开局糟糕透了,并且后面也有关键失误,最终付出了代价,输掉比赛。

球迷则感叹,"没进攻没防守,能不输吗!"返回搜狐,查看更多

责任编辑:

原文转载:http://sport.shaoqun.com/a/389623.html

跨境电商:https://www.ikjzd.com/

rfq:https://www.ikjzd.com/w/251

海淘贝:https://www.ikjzd.com/w/1726


原标题:丁俊晖微笑认输!赛前5字豪言被打脸,外媒:为糟糕表现付出代价北京时间1月30日凌晨,2021斯诺克德国大师赛8进4淘汰赛,丁俊晖3-5不敌特鲁姆普,遗憾出局。赛前,丁俊晖表示,"我没那么差。"但事实证明,丁俊晖状态很一般。赛后,《eurosport》直言,特鲁姆普状态一般,但还是赢了,因为丁俊晖表现糟糕。前三局,丁俊晖状态低迷。第一局,一番防守后,丁俊晖打进左侧底袋红球,但蓝球不进。特鲁姆
terapeak:terapeak
五洲会海购:五洲会海购
平成30年,风云总结录:平成30年,风云总结录
(精品分析)亚马逊美国站香薰机类目市场调查数据报告:(精品分析)亚马逊美国站香薰机类目市场调查数据报告
五个方法帮你打造亚马逊最佳关键词!:五个方法帮你打造亚马逊最佳关键词!

浅析 record 使用场景

record

浅析 record 使用场景

Intro

之前我们有介绍过 record 基本知识,record 会实现基于值的类型比较,最近遇到的几个问题觉得用 record 来解决会非常方便,分享一下

基于值的类型比较

最近有遇到一个场景,需要比较两个 JSON 字符串是否相等,字符串比较简单,就是一个固定值的 Dictionary,或者认为它就是一个简单的 Model,但是 JSON 字符串的的属性顺序可能不同,比如说下面的这个示例:

{"Id":1, "Name":"Tom"}, {"Name":"Tom", "Id":1},这两个字符串从字符串上来说顺序不同,自然不相等,但是对应的属性的值是相同的,怎么比较方便的进行比较呢,使用 record 可以比较方便进行比较,来看代码:

record Person(int Id, string Name);[Fact]public void RecordTest(){ var str1 = "{\"Id\":1, \"Name\":\"Tom\"}"; var p1 = JsonConvert.DeserializeObject<Person>(str1); var str2 = "{\"Name\":\"Tom\",\"Id\":1}"; var p2 = JsonConvert.DeserializeObject<Person>(str2); Assert.True(p1 == p2); Assert.Equal(p1, p2);}

基于值比较的去重

我们有一个 API 有收到反馈说,调用多次返回的结果不同,于是我就想写一段代码调用个一百次看是否会有重复,大致代码如下:

public record Result{ public string Data { get; set;} public int Code { get; set; }}var i = 100;var results = new HashSet<Result>();using var httpClient = new HttpClient();while(i-- > 0){ var responseText = await httpClient.GetStringAsync(""); var result = JsonConvert.DeserializeObject<Result>(responseText); results.Add(result);}Console.WriteLine(results.Count);

因为 record 不仅会重写 Equals 方法还会重写 GetHashCode 方法,所以可以使用 HashSet 或者 Dictionary 来实现去重

对象克隆

record 提供了 with 表达式来方便的克隆一个新的对象,所以在需要克隆的时候可以考虑使用 record,另外所有原型模式的地方都可以考虑使用 record 来实现

之前我实现了一个简单的日志框架,有一个日志对象,定义如下:

public class LogHelperLoggingEvent : ICloneable{ public string CategoryName { get; set; } public DateTimeOffset DateTime { get; set; } public string MessageTemplate { get; set; } public string Message { get; set; } public LogHelperLogLevel LogLevel { get; set; } public Dictionary<string, object> Properties { get; set; } public LogHelperLoggingEvent Copy()  {  var newEvent = new LogHelperLoggingEvent()  {   CategoryName = CategoryName,   DateTime = DateTime,   MessageTemplate = MessageTemplate,   Message = Message,   LogLevel = LogLevel  };  if (Properties != null)  {   newEvent.Properties = new Dictionary<string, object>();   foreach (var property in Properties)   {    newEvent.Properties[property.Key] = property.Value;   }  }  return newEvent; }}

我们可以使用 MemberwiseClone 做一个简化

public class LogHelperLoggingEvent : ICloneable{ public string CategoryName { get; set; } public DateTimeOffset DateTime { get; set; } public string MessageTemplate { get; set; } public string Message { get; set; } public LogHelperLogLevel LogLevel { get; set; } public Dictionary<string, object> Properties { get; set; } public LogHelperLoggingEvent Copy() {  var newEvent = (LogHelperLoggingEvent)MemberwiseClone();  if (Properties != null)  {   newEvent.Properties = new Dictionary<string, object>();   foreach (var property in Properties)   {    newEvent.Properties[property.Key] = property.Value;   }  }  return newEvent; }}

使用了 record 之后如下,with 表达式返回的是强类型的对象,不再需要自己做强制类型转换了,上面的做法还是比较取巧的办法,使用了 MemberwiseClone 去做复制,如果自己写代码一个一个复制,将会更加繁琐,使用 record 之后就很简单了,只是我们需要注意一下,with 表达式也只是浅复制,如果内部包含复杂引用类型,需要小心使用

public record LogHelperLoggingEvent{ public string CategoryName { get; set; } public DateTimeOffset DateTime { get; set; } public string MessageTemplate { get; set; } public string Message { get; set; } public LogHelperLogLevel LogLevel { get; set; } public Dictionary<string, object> Properties { get; set; } public LogHelperLoggingEvent Copy() {  var newEvent = this with{ };  if (Properties != null)  {   newEvent.Properties = new Dictionary<string, object>();   foreach (var property in Properties)   {    newEvent.Properties[property.Key] = property.Value;   }  }  return newEvent; }}

More

record 在很多场景下能够简化我们的代码,使得代码更加干净简洁,在合适的场景下不要忘记使用哦~

微软的反向代理项目 YARP 也使用了 record 来简化原来代码中 DeepClone 的功能,可以参考 PR:https://github.com/microsoft/reverse-proxy/pull/662









原文转载:http://www.shaoqun.com/a/521163.html

跨境电商:https://www.ikjzd.com/

reverb:https://www.ikjzd.com/w/1273

母婴团购网:https://www.ikjzd.com/w/716


record浅析record使用场景Intro之前我们有介绍过record基本知识,record会实现基于值的类型比较,最近遇到的几个问题觉得用record来解决会非常方便,分享一下基于值的类型比较最近有遇到一个场景,需要比较两个JSON字符串是否相等,字符串比较简单,就是一个固定值的Dictionary,或者认为它就是一个简单的Model,但是JSON字符串的的属性顺序可能不同,比如说下面的这个
parser:parser
五洲会海购:五洲会海购
Noon平台怎么样? Noon平台入驻要求、流程揭秘!:Noon平台怎么样? Noon平台入驻要求、流程揭秘!
【干货】亚马逊的这些工具一定要会用!:【干货】亚马逊的这些工具一定要会用!
B2C五步攻略法,轻松拿下海外电商市场!:B2C五步攻略法,轻松拿下海外电商市场!

2021-01-29

女人想分手会怎样 女人铁了心分手的表现

在感情当中,一个女孩想要分手,到底会有什么样的表现呢?今天就来了解一下吧。

女人想分手会怎样 女人铁了心分手的表现

女人想分手会怎样

1、她不再和你相见。

如果一个女人铁了心要和你分手,那么她会拒绝和你相见。小芳和男友在北京认识的。他们在北京交往了三年。北京的大街小巷几乎都留下了他们依偎相拥的甜蜜身影。可是,当小芳发现男友背着她和其他女人暧昧,她果断选择和男友分手,并且辞掉了在北京的工作,跑到广州重新开始找工作。

2、她会把你之前送给她的东西全部退还给你。

如果一个女人铁了心要和男人分手,那么她会把男人之前送给她的东西全部退还给男人。因为她已经决定要和你分手,所以她不想再保留你之前给她的东西。她会打包邮寄给你。如果你不想要,那么她会扔进垃圾堆里,或是直接烧毁。那些东西残留着你的味道,她不想再看到这些东西。

3、她会迅速开始新的感情。

如果一个女人铁了心要和你分手,那么她很可能会在和你分手后,迅速开始一段新的感情。当然,女人没必要为了刺激前任,随便找个男人谈恋爱。这对你自己来说也是不负责任的表现。除非你是真心实意地重新爱上了一个男人,你觉得他是你想要交往的恋爱对象,那么你可以选择和对方交往。

女人想分手会怎样 女人铁了心分手的表现

女人铁了心分手的表现

女人铁了心分手的表现一:不在保存你的任何联系方式

当一个女人铁了心想要和你分手的视乎,她是不会保存你的任何联系方式的。因为她看见你就烦,更不会自己找虐把你的联系放在手机里来烦自己。能够少看到一点你消息就少看一点,就算是你们之间有必须要联系的事情,她也会让朋友来转告你。

女人铁了心分手的表现二:不再参与你的任何事情

她也不会参与你的任何事情,如果你们以前闹分手。但是你们还是会在父母见面的时候,或者有需要的时候,假装和好。但是这次她想要真心分手的时候,你的所有朋友同学聚会,她都不会和你一起参加,也不会和你出去之类的。

女人铁了心分手的表现三:远离你的世界

同时她会把你的东西从她的世界里完全的清理干净。比如搬出你们一起同住的小窝,或者手机里关于你的照片全部删除。甚至会把你们几年前传到朋友圈微博QQ空间的所有照片都会找出来全部删除干净,女人有时候狠起来就是这样。

女人铁了心分手的表现四:忽视你的存在

最后一个表现就是她会完全的忽视你的存在,就算亲自去找到她的公司或者家里面,她也不会理你。直接从你面前路过,更不会回头看你一眼,无论你在过着什么样的生活,或者找一个女人暧昧的出现在她面前,她也会淡定从容在你们面前吃饭。

原文转载:http://lady.shaoqun.com/a/265112.html

跨境电商:https://www.ikjzd.com/

敏思达:https://www.ikjzd.com/w/2304

折扣网:https://www.ikjzd.com/w/74


在感情当中,一个女孩想要分手,到底会有什么样的表现呢?今天就来了解一下吧。女人想分手会怎样1、她不再和你相见。如果一个女人铁了心要和你分手,那么她会拒绝和你相见。小芳和男友在北京认识的。他们在北京交往了三年。北京的大街小巷几乎都留下了他们依偎相拥的甜蜜身影。可是,当小芳发现男友背着她和其他女人暧昧,她果断选择和男友分手,并且辞掉了在北京的工作,跑到广州重新开始找工作。2、她会把你之前送给她的东西全
retriever:retriever
转运中国:转运中国
亚马逊经营十大基本要点:亚马逊经营十大基本要点
口述:老公行房力不从心竟让我改嫁老公行房身体:口述:老公行房力不从心竟让我改嫁老公行房身体
干货:Lazada五大站点热销品类及爆品预测!:干货:Lazada五大站点热销品类及爆品预测!

Java SPI 与 Dubbo SPI

SPI(Service Provider Interface)是JDK内置的一种服务提供发现机制。本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。

在Java中SPI是被用来设计给服务提供商做插件使用的。基于策略模式来实现动态加载的机制。我们在程序只定义一个接口,具体的实现交个不同的服务提供者;在程序启动的时候,读取配置文件,由配置确定要调用哪一个实现。有很多组件的实现,如日志、数据库访问等都是采用这样的方式,最常用的就是 JDBC 驱动。

1.  Java SPI

核心类:java.util.ServiceLoader

服务是一组众所周知的接口和(通常是抽象的)类。服务提供者是服务的特定实现。提供者中的类通常实现接口,并子类化服务本身中定义的类。服务提供者可以以扩展的形式安装在Java平台的实现中,即放置在任何常见扩展目录中的jar文件。提供程序也可以通过将它们添加到应用程序的类路径或其他特定于平台的方法来提供。

通过在资源目录META-INF/services中放置一个提供程序配置文件来识别服务提供程序。文件名是服务类型的完全限定二进制名称。该文件包含具体提供程序类的完全限定二进制名的列表,每行一个。每个名称周围的空格和制表符以及空白行将被忽略。注释字符是'#';在每一行中,第一个注释字符之后的所有字符都将被忽略。文件必须用UTF-8编码。

按照上面的方法,我们来写个例子试一下

首先,定义一个接口Car

package org.example;public interface Car { void run();}

两个实现类

ToyotaCar.java

package org.example;public class ToyotaCar implements Car { @Override public void run() {  System.out.println("Toyota"); }}

HondaCar.java

package org.example;public class HondaCar implements Car { @Override public void run() {  System.out.println("Honda"); }}

在META-INF/services下创建一个名为org.example.Car的文本文件

org.example.ToyotaCarorg.example.HondaCar

最后,写个测试类运行看一下效果

package org.example;import java.util.ServiceLoader;public class App{ public static void main( String[] args ) {  ServiceLoader<Car> serviceLoader = ServiceLoader.load(Car.class);  serviceLoader.forEach(x->x.run()); }}

跟一下ServiceLoader的代码,看看是怎么找到服务实现的

用当前线程的类加载器加载

接口和类加载器都有了,万事俱备只欠东风

Java SPI 不足之处:

  • 不能按需加载。Java SPI在加载扩展点的时候,会一次性加载所有可用的扩展点,很多是不需要的,会浪费系统资源
  • 获取某个实现类的方式不够灵活,只能通过 Iterator 形式获取,不能根据某个参数来获取对应的实现类
  • 不支持AOP与IOC
  • 如果扩展点加载失败,会导致调用方报错,导致追踪问题很困难

2.  Dubbo SPI

Dubbo重新实现了一套功能更强的SPI机制, 支持了AOP与依赖注入,并且利用缓存提高加载实现类的性能,同时支持实现类的灵活获取。

<dependency>  <groupId>org.apache.dubbo</groupId>  <artifactId>dubbo</artifactId>  <version>2.7.8</version></dependency>

核心类:org.apache.dubbo.common.extension.ExtensionLoader

先来了解一下@SPI注解,@SPI是用来标记接口是一个可扩展的接口

改造一下前面的例子,在Car接口上加上@SPI注解

package org.example;import org.apache.dubbo.common.extension.SPI;@SPIpublic interface Car { void run();}

两个实现类不变

在META-INF/dubbo目录下创建名为org.example.Car的文本文件,内容如下(键值对形式):

toyota=org.example.ToyotaCarhonda=org.example.HondaCar

编写测试类

package org.example;import org.apache.dubbo.common.extension.ExtensionLoader;import java.util.ServiceLoader;public class App{ public static void main( String[] args ) {  // Java SPI  ServiceLoader<Car> serviceLoader = ServiceLoader.load(Car.class);  serviceLoader.forEach(x->x.run());  // Dubbo SPI  ExtensionLoader<Car> extensionLoader = ExtensionLoader.getExtensionLoader(Car.class);  Car car = extensionLoader.getExtension("honda");  car.run(); }}

下面跟一下代码

如果缓存Map中有,直接返回,没有则加载完以后放进去

 

加载策略到底是怎样的呢?

到这里就有点明白了,又看到了熟悉的ServiceLoad.load(),这不是刚才讲的Java SPI嘛

回到之前策略那个地方,将策略按顺序排列,依次遍历所有的策略来加载。就是在那三个目录下查找指定的文件,并读取其中的内容

跟之前的ServiceLoader如出一辙

遇到@Adaptive标注的就缓存起来

下课 









原文转载:http://www.shaoqun.com/a/521162.html

跨境电商:https://www.ikjzd.com/

dmm.adult:https://www.ikjzd.com/w/2026

kili:https://www.ikjzd.com/w/238


SPI(ServiceProviderInterface)是JDK内置的一种服务提供发现机制。本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。在Java中SPI是被用来设计给服务提供商做插件使用的。基于策略模式来实现动态加载的机制。我们在程序只定义一个接口,具体的实现交个不同的服务提供者;在程序启动的时候,读取配置文件,由配
识货:识货
贝贝官网:贝贝官网
上万辆配送卡车滞留!亚马逊大规模退货潮来临!:上万辆配送卡车滞留!亚马逊大规模退货潮来临!
2020 Wish年度卖家云峰会,人、货、运的全面升级!:2020 Wish年度卖家云峰会,人、货、运的全面升级!
Amazon官方PPC广告基础:Amazon官方PPC广告基础