Java 后端技术总结

01、HashMap的特性

Map 集合特点:

  • Map 是一个双列集合,键值对映射
  • 键不能重复,一个键只能映射一个值
  • Map 集合的数据结构是指键的数据结构,跟值没有关系
    HashMap 的数据结构:
  • 哈希表结构:数组 + 链表
  • 通过哈希表结构配合对象的 hashCode 和 equals 方法就可以保证键的唯一性

02、HashMap集合的扩展

  • jdk8 之后,引入了二叉树数据结构
  • 在链接达到一定长度后,会将链表结构转为二叉树,提高查询速度

03、Java虚拟机中的内存模型

jvm 有以下几种内存空间

  • 1、栈内存:方法运行时会进入栈内存,局部变量也在栈内存
  • 2、堆内存:new 出来的对象
  • 3、方法区:字节码文件加载后进入的内存
  • 4、本地方法区:主要是操作系统相关资源
  • 5、寄存器:CPU 使用

04、线程内存空间(扩展)

  • 每一个线程都有自己独立的栈内存空间
  • 堆内存中的数据被多个线程共享

05、Java中的异常处理机制的简单原理和应用。

基类:Throwable,派生了两个子类:Error 和 Exception
Error 是 JVM 本身的错误,不能被程序员处理,如内存溢出等
Exception 分为:IOException 和 RuntimeException
Error 和 RuntimeException 及它们的子类,是非检查异常,即编译时不会发现这些可能的异常,不需要特殊处理;
而检查异常在编译时即可检查出可能存在,需要用 try.catch 处理,或者用 throws 抛给上一层处理;
扩展:Spring 框架的事务默认是 RuntimeException 才回滚,可以通过修改 @Transaction 注解中的 rollbackFor 属性来指定为 Exception 回滚

06、创建线程的几种方式?

  • 1)继承自 Thread 类
    • 优点:代码简单, this 就是当前线程
    • 缺点:不能继承其他类,
  • 2)实现 Runnable 接口:
    • 优点:多个线程可以共享一个 task 对象,适合处理多个线程共享同一份数据
    • 缺点:代码稍微复杂,获取当前线程需要用 Thread.currentThread()
  • 3)实现 Callable 接口:
    • 优点:可以有返回值,可以抛出异常,多个线程可以共享一个 task 对象,适合处理多个线程共享同一份数据
    • 缺点:代码稍微复杂,获取当前线程需要用 Thread.currentThread()
  • 4)使用线程池(需要依赖 Runnable 和 Callable)
    优点:管理复用创建的线程,减少线程创建和销毁的开销,提高性能
    缺点:代码稍复杂

07、垃圾回收机制

  • 当一个对象的引用(地址)没有变量记录时,该对象就成为垃圾对象,在垃圾回收器空闲时对其回收
  • 重写 finalize 方法,对象被垃圾回收器回收时,该方法会被调用,即可以通过观察 finalize 方法有没有调用来确定对象有没有被回收
  • 主动通知垃圾回收器回收对象:调用 System.gc() 通知,但不一定立刻回收

如何判断哪些对象需要回收(内存管理)

  • 引用计数:每个对象有一个引用计数器,被引用一次,计数器就加1,不引用就减1,当计数器为0时对象会被当做垃圾
  • 根搜索(JVM 用的):从根节点 GC ROOT 开始查找引用的节点,再继续查找每个引用节点的引用节点,查找到所有的引用节点之后,剩余的节点上的对象则被认为是需要回收的垃圾

08、HashCode()、equals()的区别

  • HashCode() 返回一个整数,即对象的哈希值

  • equals() 根据指定的计算方法判断两个对象是否相等

  • 两个方法,共同作为 hash 类型的结构唯一性的判断条件

  • hashCode() 在 Object 中的默认实现:取对象地址的 hash 值

  • equals() 在 Object 中的默认实现:直接判断两个对象是否地址相同 ==

  • 重写 hashCode() 的方式一般是返回属性的综合 hash 值

  • 重写 equals() 的方式一般是先判断是否是同一个对象,再判断属性是否相等

  • 重写两个方法的规则:hashCode() 返回的值对同一个对象来说是固定的;equals() 返回 true,则 hashCode() 必须相同;hashCode() 相同 equals()不一定返回 true

09、String,StringBuilder,StringBuffer三者的区别

  • String 和 StringBuilder 的区别
    • String:不可变字符串
    • StringBuilder:可变字符串
      如果需要拼接字符串,尽可能使用 StringBuilder,因为 StringBuilder 拼接性能远高于 String,尤其是拼接次数很多的时候;如果是简单拼接,使用 String 也是可以的
  • StringBuilder 和 StringBuffer 的区别
    • 用法完全一致
    • StringBuilder jdk1.5 出现,线程不同步(不安全),效率较高
    • StringBuffer jdk1.0 出现,线程同步(安全),效率低
      一般情况下推荐使用 StringBuilder

10、是否可以从一个static方法内部发出对非static方法的调用

  • 直接调用不可以,非 static 方法是绑定对象的,所以必须通过对象来调用
  • 可以在 static 方法中通过创建对象,再调用非 static 方法
  • static 是静态方法,或者类方法,不需要创建对象,而是通过类名直接调用,所以在非 static 方法中可以调用 static 方法

11、wait方法和sleep方法的区别

  • sleep() 是 Thread 类中的方法,使线程暂停执行指定的时间,让出 cpu 给其他线程,且不会释放锁对象,时间到之后会恢复执行
  • wait() 是 Object 中的方法,它必须在加锁的代码中被调用,而且是由锁对象调用;
    当 wait() 被调用时,会释放锁对象,方法此时不会返回,等到其它线程中同一个锁对象调用 notify() 方法后,wait() 才会返回,线程继续执行;
    所以 wait() 和 notify() 配对使用,可以实现线程之间的通讯

12、问题扩展&应用场景

线程的生命周期:

  • 新建状态:new 的时候
  • 就绪状态:调用了 start,等待 cpu调度执行
  • 运行状态:被 cpu 调度执行
  • 阻塞状态:放弃 cpu 使用权,暂停执行,如 wait()、获取锁失败、sleep()、join()
  • 死亡:执行完毕或异常退出

13、new String("xyz") 创建了几个StringObject?是否可以继承String类?

  • String 类是被 final 修饰的,所以不能被继承
  • 若常量池中不存在字符串 "xyz",则创建了 2 个对象,一个是 "xyz",另外一个是 new String("xyz")
  • 若常量池中已经存在 "xyz",则只创建了 1 个对象,即 new String("xyz")

14、多线程中解决同步问题的方式

  • synchronized:给需要同步的代码块加锁 synchronized(Object obj), 参数可以是任意对象,若是方法加锁,锁对象是当前对象 this,声明 synchronized 即可
  • ReentrantLock(),加锁 lock.lock(),解锁 lock.unlock()
  • volatile:对变量访问实现线程同步,每次使用重新计算,不使用寄存器的值
  • 队列:LinkedBlockingQueue

15、这两行代码执行后,原始的String对象中的内容到底变了没有

String s = "Hello";
s = s + "world!";

原始的 String 对象有 "Hello" 和 "world!", + 运算符运算之后会创建新的 String 对象 "Helloworld!",而原有的 String 不会改变
String 是不可变字符串,如需可变字符串,可以用 StringBuilder 或 StringBuffer

16、HashMap和Hashtable的区别

HashMap:

  • jdk1.2,允许 null 键和 null 值
  • 不同步,线程不安全,效率高

HashTable:

  • jdk1.0,不允许 null 键和 null 值
  • 同步,线程安全,效率低

17、单例设计模式中懒汉式和饿汉式的区别

  • 饿汉式是类加载时就对单例对象初始化,加载较慢,第一次获取单例较快,线程安全
  • 懒汉式是类加载时不初始化,加载较快,第一次获取单例时进行初始化,若不加锁 synchronized,线程不安全;但是在方法上加锁之后性能会降低,所以在方法体中加锁,且先判断单例变量是否为 null

18、类加载机制

类装载器将 Class 文件装载后,形成描述 Class 结构的元信息对象,包含 Class 的结构信息:如构造函数、属性和方法等;
虚拟机把描述类的数据加载到内存,并对数据校验、转换解析和初始化,最终形成可以被虚拟机直接使用的 Java类型

19、cookie和session的区别与联系

  • cookie 和 session 都是在 http 请求中保存数据
  • cookie 存在于客户端浏览器,session 保存在服务器
  • 单个 cookie 最大为 4k
  • cookie 可能会被分析,不安全,敏感信息应该存在服务器中的 session
  • session 的唯一标识 sessionId,可以放到 cookie 中,用于确定是同一个会话

20、在HTTP请求中,如何选择 GET 和 POST

  • GET 一般用于查询资源
  • POST 一般用于更新资源
  • GET 请求 url 长度有限制(浏览器或者服务器限制),提交大量数据需要用 post
  • 如果需要提交账号密码等敏感信息,最好用 post,因为 post 不会把参数显示到浏览器的地址栏,相对安全,get 会显示完整 url,包括所有参数

22、servlet的生命周期及常用方法

  • init 方法:应用程序启动或者 service 第一次被访问时(取决于配置),servlet 被初始化,init 方法被调用,这个方法只会被调用一次
  • service 方法:客户端发起请求时,service 方法被调用,在这个方法里处理业务逻辑
  • destroy 方法:程序正常退出时,servlet 被销毁,destroy 方法被调用,只会调用一次

如何保证 servlet 线程安全:
servlet 是单例,所以可能会有线程安全问题,可以通过不使用全局变量来避免线程安全问题
servlet 也可以配置多例模式,但已被废弃;还可以加锁,但是对性能影响较大,不推荐

23、转发和重定向的区别

  • 转发:服务端访问其他资源的 url, 以响应客户端,对于客户端来说只有一次请求,地址栏地址不会改变
  • 重定向:一次请求完成之后,客户端根据服务端返回的重定向地址再次发起请求,所以是两次请求,地址栏地址会改变
  • 转发可以共享 request 里的数据,重定向不共享
  • 转发 request.getRequestDispatcher();重定向:response.sendRedirect()

32、http,https,ftp,talnet的默认端口

  • http:80
  • https:443
  • ftp:21
  • talnet:23

33、常见的http返回状态码

  • 200:响应成功
  • 301:重定向,资源永久转移到新的地址,告诉搜索引擎抓取的新内容保存到新地址
  • 302:也是重定向,不同的是,302 表示资源只是暂时转移到新的地址,原有的地址还有效,搜索引擎抓取的新内容仍保存到旧的地址
  • 400:错误请求,服务器不理解请求的语法
  • 404:资源不存在
  • 500:服务器内部错误

34、TCP和UDP区别,HTTP协议

  • TCP 是面向连接的传输协议,传输较为安全可靠,但是效率会相对 UDP 较低,适合传输对可靠性要求较高的数据
  • UDP 是一种数据报文协议,无需建立连接,只发出报文,而不用关心对方是否收到,传输效率较高,适合传输大量数据
  • http 超文本传输协议,是应用层协议,基于 TCP/IP 协议;短连接,传输完数据即断开(新版本的 http 协议可以复用连接),javaweb 就是通过 http 协议来通信

36、Spring AOP的实现原理

  • AOP 就是面向切面编程
  • 底层是通过 JDK 或者 cglib 进行动态代理;JDK 是通过接口进行代理,要求被代理的类需要实现接口,cglib 是继承的方式;
  • 运行时会创建一个新的类,包含被代理类的所有方法, 对原有方法增强,并回调原有方法;JDK 实现动态代理核心是 InvocationHandler 和 Proxy 类; cglib 动态生成子类,如果被代理类用 final 关键字修饰,则无法使用 cglib
  • 对原有切点(也就是方法)进行增强
  • 在不修改原有代码逻辑的情况下对方法增强,降低耦合度,更容易扩展和维护
  • 代码复用
  • 用法:前置通知(被增强方法调用之前发送通知);后置通知;环绕通知;返回后通知(被增强方法抛异常后发送通知);异常通知
  • 应用场景:日志管理、事务管理

37、IOC和DI的关系

  • 概念:IOC Inverse Of Control 是反转控制,即类中的内置对象不再由本类创建,而是交由第三方创建(如 Spring);DI Dependency Injection 是依赖注入,类中的内置对象从第三方直接注入来创建
  • 关系:IOC 是容器,DI 是注入行为,也可以说 IOC 是平台和空间,DI 是 IOC 的具体实现;两者相辅相成,共同实现解耦;
  • DI 如何实现:setter 注入、构造器注入、接口注入,Spring 支持 setter 和构造器
  • 举例:A 类需要引用 B 接口的方法,传统方式是在 A 类中引用 B 接口的实现类 C,并创建对象,如果实现类需要更新,则 A 类中的代码也需要修改,系统需要重新构建;如果使用 IOC 和 DI 的方式,则可以将实现类的创建、及实现类和接口的关联关系交给 IOC 容器管理,在 A 类中只需要引入接口 B,注入对象就可以了,即使实现类有变化也不需要修改代码

38、Spring 中的设计模式

  • 1.代理模式:AOP 中实现了 JDK 的动态代理
  • 2.观察者模式:JavaEE 项目中,通过监听器 ContextLoaderListener,创建 WebApplicationContext;监听器就是观察者模式的具体体现
  • 3.工厂模式:BeanFactory 中用到
  • 4.适配器模式:如在使用 SpringMVC 创建控制器 controller 时,可以用 @Controller 注解,也可以实现 Controller 接口或者 HttpRequestHandler 接口等,但是前端控制器 DispatcherServlet 都可以通过适配器去识别适配不同实现方式的 controller
  • 5.单例模式:bean 的创建默认就是单例模式,可以配置成多例模式等其他模式
  • 6.模板模式
  • 7.策略模式
  • 应用:如用代理模式,对方法增强,解决乱码问题

39、Spring中Bean的作用域

  • singleton:单例模式,只有一个对象,Spring 中 bean 的默认作用域
  • prototype:原型模式,即多例模式
  • session:在一个 session 中有效,session 关闭后,bean 等待垃圾回收
  • global-session:全局 session 模式, 5.x 已经废弃
  • request:同一个 http 请求

40、spring框架实现实例化和依赖注入的方式

- spring 实现实例化的方式:spring 获取类字节码文件,并通过构造函数进行实例化

  • spring 实例化的方式:

    • 构造方法实例化
    • 静态工厂方式实例化
    • 实例工厂方式实例化
  • 依赖注入概念:依赖注入是 spring 协调不同实例之间合作的一种工作机制,确保 bean 之间合作的同时,也保持每个 bean 的相对独立

  • spring 实现依赖注入的方式:

    • 基于构造函数的注入:在 <bean> 标签内配置 <constructor-arg> 标签,传入需要注入的 bean,需要是有参构造函数;
    • 基于 set 方法的注入:在 <bean> 标签内配置 <property> 标签
    • 基于自动装配的注入:根据依赖注入对象属性名称或者类型,自动从 IOC 容器查找对应的对象并进行注入。bean 的配置需设置 autowire 的值为 byName、byType 或者 constructor。不推荐自动状态,应该显式的注入 bean
    • 基于注解的依赖注入:
      • @Autowired :默认按类型装配,可结合 @Qualifier 按名称装配
      • @Resource:按指定的 name 和 type 装配,若无指定则按名称、类型的顺序装配

41、springMVC的执行流程

  • 1、前端控制器 DispatcherServlet 接收 request
  • 2、通过处理器映射器 HandlerMapping 获取执行链条
  • 3、通过处理器适配器 HandlerAdapter 找到指定的 Handler,也即是代码编写的 Controller
  • 4、处理结果由视图解析器 ViewResolver 解析为 Model 和 View 返回给客户端浏览器

42、spring和springMVC中的常用注解

  • @Bean: 声明方法返回的对象放到 IOC 容器中
  • @Autowired @Qualifier @Resource :注入 bean
  • @Component @Repository @Service @Controller:声明该类为一个 bean,由 IOC 容器创建实例;其中 @Service 和 @Controller 都继承自 @Component,分别对应 dao 层、 service 层和 controller 层的业务场景
  • @RequestMapping @GetMapping @PostMapping : 路径映射,可用于类和方法,用于类上则对所有方法有效,值作为路径的前缀;用于方法则仅对当前方法有效
  • @ResponseBody :用于类和方法上,表示返回结果为某种格式数据,如 xml、json, 对应 response 的 body,而不是返回页面字符串或对象,而不是重定向,
  • @PathVariable : 解析 RESTful 风格的路径中的参数
  • @RequestParam : 绑定参数
  • @RestController:组合注解,相当于 @Controller 和 @ResponseBody

43、springMVC和structs2的区别

  • 相同点:
    • 底层都是 Servlet API
    • 都是表现层的 MVC 框架
  • 不同点:
    • SpringMVC 是基于方法的,Structs2 是基于类的,每次请求都会创建一个动作类,所以 SpringMVC 快一些

44、springMVC中的前端控制器和处理器映射器

  • 前端控制器,DispatcherServlet
    • 用户请求先到达 DispatcherServlet,再由 DispatcherServlet 调用其他组件,如 HandlerMapping、ViewResolver 等,降低各组件的耦合性
  • 处理器映射器 HandlerMapping
    • DispatcherServlet 调用 HandlerMapping 获取执行的链条,即映射到对应的 Handler,就是自己编写的 controller

45、springMVC如何实现请求参数绑定

  • 借助 controller 中的方法的形参来进行参数绑定
  • 形参支持的数据类型
    • 基本数据类型和 String 类型:参数名称和 controller 中方法形参相同,如不同,则需要用 @RequestParam 注解来绑定
    • 实体类 POJO,包括实体类,及关联实体类:参数名称需要和实体类的属性名(实际上是 get 和 set 方法)相同,controller 方法形参的类型为实体类的类型
    • 数组和集合类型:1)将集合类型参数封装到实体类中,形参为实体类,请求参数名为集合的属性名,给 List 元素赋值用下标形式,给 Map 赋值用键值对形式;2)可以用 @RequestBody 注解实现,传参为 JSON格式;其他数据类型的形参也可以用 @RequestBody 注解来进行参数绑定
  • Spring MVC 内置了一些类型转换器,我们可以自定义,实现 Converter 接口

46、springMVC获取表单数据的几种方式

  • 1.原始 servlet API:controller 方法添加 HttpServletRequest 入参,调用 HttpServletRequest.getParameter() 获取参数
  • 2.controller 方法形参:
    • 基本数据类型和 String
    • 实体类类型 POJO
    • 实体类关联对象
    • 实体类关联集合
  • 3.controller 方法接收实体类类型参数,用 @RequestBody 接收 json 数据,通过 jackson 组件转换成实体类,json 数据的 key 与实体类的属性保持一致

47、ssm整合流程

  • 1.创建 Maven 工程
  • 2.导入 Spring、SpringMVC、MyBatis、MySql Connector、数据库连接池 druid,fastjson,等坐标
  • 3.创建 controller,service,mapper 接口和对应的 sql 语句的 xml 文件
  • 4.配置文件
    • web.xml:配置 DispatcherServlet
    • Spring 核心配置文件:扫描 controller,service
    • SpringMVC 核心配置文件: annotation-driven 配置 json 转换工具
    • jdbc.properties, jdbc 连接属性
    • dao 配置文件:数据源,Spring 整合 MyBatis 的工厂 bean:SqlSessionFactory,扫描 mapper 接口

49、mybatis中#和$传参的区别

  • 使用 #:sql 语句解析时会自动将参数加上双引号,当做字符串来用,防止 sql 注入
  • 如果要动态排序,传入的参数为数据库字段名,即 order by column,这种情况下必须使用 $

50、mybatis中的动态sql语句

  • 在程序运行时,根据传入参数的不同来确定 sql 语句的格式,可以通过 < where> < if> < foreach> 等标签来组装 sql 语句
  • 应用场景主要是条件查询

51、mybatis映射配置文件的编写规范

  • xml 映射文件中 namespace 与 mapper 接口的全类名相同
  • xml 映射文件中的 statement 的 id 值与 mapper 接口定义的方法相同
  • xml 映射文件中的 sql 返回值类型 resultType 与 mapper 接口方法返回值类型相同(若为 List 集合类型,则与集合中的元素类型相同)
  • xml 映射文件中的 sql 参数类型 parameterType 与 mapper 接口方法的参数类型相同
  • mapper 接口的工作原理是 JDK 动态代理,Mybatis 在运行时会使用 JDK 动态代理为 mapper 接口生成代理对象,代理对象拦截接口方法,执行 sql 语句,并返回结果

52、mybatis的执行过程分析

  • 读取配置文件
  • 创建 SqlSessionFactory
  • 获取 SqlSession
  • 获取 Mapper 代理对象
  • MyBatis 底层是对 jdbc api 的封装

53、常见设计模式及应用场景?

  • 单例模式:保证一个类只有一个实例,比如配置文件或者管理类,供全局访问
  • 观察者模式:监听器就是观察者模式,如 Spring 的 ContextLoaderListener
  • 代理模式:面向切面编程 AOP 就是基于动态代理实现的
  • 工厂模式:Spring 中创建 Bean 的工厂 BeanFactory

54、两种动态代理的区别

  • 基于 JDK 动态代理:用接口实现代理,要求被代理对象必须实现接口;核心是 InvocationHandler 和 Proxy 类
  • 基于 cglib 代理:运行时创建一个继承自被代理对象的子类对象,包含被代理对象的所有方法;被代理的类不能用 final 修饰,否则无法使用 cglib 代理,因为不能被继承

56、日志文件的管理

日志文件的管理

  • 用 log4j、slf4j框架收集日志,输出到控制台和文件
  • 借助 AOP 技术对请求 controller 进行拦截,在定义的切面 aspect 中输出日志

57、分布式开发的缺点

  • 架构复杂,尤其需要考虑分布式事务
  • 不同服务之间通过网络交互,测试难度大
  • 技术门槛较高
  • 运维部署复杂

58、支付接口

  • 比如微信支付,根据购物车信息和金额,调用微信的统一下单 api,获取到预支付 url,然后前端根据 url 生成二维码,用户扫码支付。
  • 下单的时候会给微信提供一个支付结果回调的 url,微信可以调用这个 url 通知支付结果
  • 同时微信提供查询支付状态的 api,前端就可以通过轮询的方式去查询支付状态。
  • 另外微信也有关闭订单、退款相关的 api

60、RabbitMQ 在项目中的应用

订单超时处理,死信队列(交换机)

61、RabbitMQ 数据提交不成功

有消息回执机制

63、dubbo服务开发流程,运行流程

  • 开发流程

    • 选用注册中心,如 zookeeper,安装部署 zookeeper
    • 导入 dubbo 依赖坐标
    • 服务端:
      • 用 dubbo 框架的 @Service 注解标记需要被注册的服务
      • 在 spring 配置文件中配置 dubbo 应用名称、zookeeper 注册中心地址、扫描要发布的服务所在的 package
    • 客户端:
      • dubbo 客户端配置,关联 zookeeper
      • @Reference 注解注入 dubbo 中注册的服务
      • 配置扫描需要用到 dubbo 服务的 package
  • 运行流程

    • 启动 zookeeper 注册中心
    • 部署 dubbo 服务提供方和服务消费方
    • dubbo 服务提供方注册到 zookeeper 注册中心
    • dubbo 服务消费方从 zookeeper 获取服务列表
    • 服务消费方根据服务列表中的地址调用服务提供方

65、广告数据用 redis 缓存

用 redis 的 hash 类型数据存储不同类型的广告, redisTemp late.boundHashOps("").get("");

66、权限控制

后台管理系统用到权限控制;
用 Spring Security 框架,包含用户、角色、权限的概念,对应数据库表用户表、角色表、权限表,由于是多对多的关系,所有还有用户角色表、和角色权限表两个中间表

67、RabbitMQ 消息丢失问题

  • 1、消息生产者弄丢消息:可以开启 mq 的事务机制,如果发送失败,可以回滚并重新发送,事务机制是同步的,会影响性能,降低并发量,替换的方案是 confirm 机制,是异步的,mq 会回调处理的结果,失败则可以重发;
  • 2、mq 弄丢数据:可以开启持久化,即使 mq 挂掉,重启的时候也会从本地重新读取消息
  • 3、消费者弄丢消息:比如取到消息,没处理完就挂了,会导致丢失,可以使用 ack 机制

68、token 校验

用到 jwt 令牌作为 token,用户登录,服务端生成 jwt 令牌返回给客户端,客户端下次请求时带上 jwt 令牌,服务端校验 jwt 令牌是否合法,并判断用户的权限

70、redis 缓存与数据库同步

客户端请求进来,如果 redis 中有数据,则直接返回,若 redis 中没有数据,则从 mysql 中查询并保存到 redis中。
若数据库中数据有更新,则同步更新 redis 数据。
如广告数据,商品搜索(redis 中存储分类对应的品牌、分类对应的规格)

71、fastDFS 的执行流程

fastDFS 是分布式文件系统,分为 tracker 和 storage 两层,storage 是存储文件的服务器,tracker 是用来决定存储到哪个 storage 的;
storage 会定时发送心跳给 tracker。
存储文件时,客户端先请求 tracker,tracker 根据负载均衡,返回一台 storage 的 ip 地址和端口,客户端根据 ip 和端口访问 storage,并传输存储文件,storage 生成文件的 file id 并返回给客户端,客户端存储 file id;
查询文件时,客户端同样请求 tracker,tracker 返回 storage 的 ip 和端口,客户端再去访问 storage 获取文件

72、zookeeper集群全部都挂了处理方式

消费者会把服务提供者的地址列表缓存,所以即使 zookeeper 挂了,消费者也可以直接从地址列表中选一个去访问服务提供者;
如果服务提供者地址改变,而 zookeeper 挂了,则消费者无法从 zookeeper 获取新的地址,也就无法访问服务提供者

73、解决购物车内存大小问题

如果没有登录,购物车可以用 cookie 来存储,大小限制 4k,替代的方式是用 session,最大支持 1M,前端的 localStorage 5M,或者服务端的 redis,mysql;
一般没有登录就用 cookie,登录后就用 redis

74、springboot 和 springcloud 的关系

  • springboot 是 spring 和 springMVC 项目的脚手架,简化项目的搭建,简化坐标依赖管理,自动化配置,提高开发效率
  • springcloud 是微服务框架,基于 springboot;
  • springboot可以独立使用,springcloud 必须依赖 springboot存在。
  • springcloud 包含 Eureka 注册中心,Feign 微服间便捷调用,Hystrix 熔断器,Zuul 微服务网关,不需要根据 ip 和端口直接访问各个微服务,而是直接访问微服务,再路由到指定微服务

76、Java 的四个基本特性(抽象、封装、继承,多态)

  • 封装:面向对象的核心思想,将对象的属性和行为封装起来,供外界使用,外界无需关心内部的实现细节
  • 继承:父类与子类的关系,子类继承父类,可以获得父类原有的属性和方法,对功能进行扩展,且无需修改父类
  • 多态:不同类的对象可以对同一消息作出不同的响应
  • 抽象:将一类对象的共同特征抽象出来,包括数据抽象和行为抽象,而且只关注有哪些属性和行为,而不关注具体细节

77、构造器 Constructor 是否可被 override

构造器不能被 override,因为构造器不能被继承
但是可以被重载 overload

79、多线程与死锁

实现多线程的方式:

- 1、继承自 Thread 类,重写 run() 方法, 调用 start() 方法开启一个线程
- 2、实现 Runnable 接口,重写 run() 方法,new 一个 Thread 对象,自定义的类创建的实例传入,调用 Thread 的 start() 方法开启一个线程; 或者通过 ExecutorService 来开启一个线程
- 3、实现 Callable 接口,重写 call() 方法, 通过 ExecutorService 来开启一个线程 

多线程相关的方法:

- sleep : 休眠
- join : 阻塞当前线程,执行传入的线程,可以用来实现等待其他线程执行完之后再继续执行当前线程
- yield : 暂时不继续执行,但是后续会继续执行,由任务调动者决定

死锁:
两个线程在互相等待对方释放锁,而双方都没有释放自己所持有的锁,导致两个线程都阻塞,也就是死锁

80、产生死锁的方式

两个线程在互相等待对方释放锁,而双方都没有释放自己所持有的锁,导致两个线程都阻塞,也就是死锁

81、内存溢出和内存泄漏

内存溢出:程序可用的内存已全部被占用,不能申请更多内存,导致内存溢出
内存泄漏:应该被释放的内存没有被释放,且不能被当前程序或其他程序使用,即是内存泄漏

83、Spring 事务的传播特性

参考:https://juejin.cn/post/6844903938928427022

  • 事务传播特性:有两个事务方法,其中一个方法被另一个方法调用,采用的事务形式就叫做事务的传播特性
  • 举例:如 A 方法调用 B 方法,那么 B 事务可以是 A 中的嵌套事务,也可以不使用事务,也可以使用与 A 事务相同的事务,这些可以通过指定事务传播特性来实现
  • 如何配置事务的传播特性:
    @Transactional(propagation = Propagation.REQUIRED)
  • 事务传播特性有哪几种:
    • REQUIRED
    • SUPPORTS
    • MANDATORY
    • REQUIRES_NEW
    • NOT_SUPPORTED
    • NEVER
    • NESTED

84、SpringMVC 原理

SpringMVC 基于 servlet,将 servlet 封装,请求派发给控制器,并通过模型对象封装响应视图,我们只需关注 controller 的业务实现;SpringMVC 的核心类是 DispatcherServlet,前端控制器,我们所编写的 controller 也叫后端控制器

85、linux常用命令

  • cd 进入目录
  • ls 列出目录或文件
  • pwd 当前目录
  • systemctl start/stop 启动/停止服务
  • sudo su 切换用户
  • mkdir 创建目录
  • touch 创建文件
  • cp 拷贝
  • grep 过滤
  • ps 当前进程
  • cat 查看文件
  • tail 查看文件最后几行,实时更新,方便查日志
  • find 查找文件

86、数据库事务隔离级别

讨论事务隔离级别之前先讨论事务并发可能出现的情况(问题)

- 脏读:一个事务读到另一个未提交事务修改过的数据
- 不可重复读:一个事务执行过程中读同一条数据出现了不同的结果,因为其他的事务对这条数据进行了修改操作
- 幻读:一个事务根据某些条件查询一些记录,过程中其他事务插入了符合条件的记录,则这个事务再次根据同样的条件查询会得到不同数量的记录

数据库隔离级别

隔离级别的作用是让不同的事务相互隔离,互不影响,保证事务的一致性,分为以下四个级别

- 读未提交:可能出现 脏读、不可重复读、幻读(都能出现,一般不用)
- 读已提交:可能出现 不可重复读、幻读(解决脏读,一般不用)
- 可重复读:可能出现 幻读(解决脏读、不可重复读),一个事务只能在当前事务提交后,才能读到其他提交后的事务修改后的数据;这是 MySQL 的默认事务隔离级别
    问:为什么上了写锁(写操作),其他事务还可以进行读操作?
    答:InnoDB 有多版本并发控制,可以读快照,不会阻塞
- 可串行化:问题都不会出现,但对性能影响较大

隔离级别比较:可串行化 > 可重复读 > 读已提交 > 读未提交
对性能的影响:可串行化 > 可重复读 > 读已提交 > 读未提交

87、SQL 注入的原理,如何预防

注入原理:传入参数中包含 sql 语句关键字,从而修改 sql 语句的条件
如删除指定 username 的记录: delete from t_user where username = ?;
传入参数:zhangsan or 1 = 1
完整语句:delete from t_user where username = zhangsan or 1 = 1;
这样判断条件对所有记录都成立,会删除所有数据,username 的判断没有作用

如何预防:

  • 不要使用动态字符串拼接 sql 语句,而是使用参数化的 sql 执行
  • 不要将数据库表相关异常信息响应给用户

88、SQL性能优化

SQL 语句优化:

  • 1、查询不要直接写 select * ...,而是需要哪个字段就写哪个字段
  • 2、给常用来过滤的字段添加索引
  • 3、数据量大的时候分页,页码越往后效率越低,因为会逐行查找
    • 1)若有字段如 id 是连续的,则可以通过 id > 某个值来优化,前提是必须是连续的
    • 2)可以通过延迟关联的方式,先根据分页条件查询出某个字段如 select id from ...,而不是 select * from ...,再通过内连接查询每条记录的详细信息
  • 4、尽可能使用 varchar,而不是 char,因为变长字段存储空间小,查询效率高
  • 5、尽量使用数字型字段:字符类型在查询时会逐字符比较,效率较低;而数字型的只需要比较一次,效率较高

89、myBatis 常用标签,批量操作

  • < insert>:增
  • < select>:查
  • < update>:改
  • < delete>:删
  • < if>:判断参数是否符合条件(如是否为 null),已确定是否用于拼接动态 sql
  • < where>:动态 sql 拼接条件判断 where 部分
  • < resultMap>、< result>:设置数据库字段与 pojo 对象属性的映射关系
  • < collection>:用于映射 pojo 对象的 List 类型属性
  • < selectKey>:添加一条记录时返回主键

批量操作:

  • 1)可以使用 < foreach> 标签
  • 2)设置 SqlSession 为批量操作类型:ExecutorType.Batch
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容