整理Java面试题

本文主要探讨了Java面试中常见的核心技术点,包括Spring MVC、Struts2的工作原理,Spring AOP和IOC概念,以及多种Spring Bean注入方式。还对比了Spring和SpringBoot的区别,并深入讲解了SQL优化、线程管理、多线程实现、MyBatis工作原理及其缓存。此外,还涵盖了SSH和SSM框架对比、日期转换、过滤器、拦截器、切面编程的区别,以及Git和数据库时区问题等。通过对JVM类加载过程的简述,展示了Java开发中的一些重要概念和最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这里是引用

只为成功找方法,不为失败找借口!

spring mvc运行原理

  • Spring是一个模块,基于MVC的一个框架。MVC是一种设计模式。M:Model;V:View,C:Controller
  • 用户发送请求由前端控制器DispatcherServlet来决定哪个页面的控制器进行处理,由HandlerMapping查找与请求匹配的Handler,再由DispatcherServlet来调用HandlerAdaper中Handler来处理,处理完会返回一个ModelAndView,HandlerAdapter发送给DispatcherServlet进行视图的解析(ViewResolver),ViewResolver将逻辑视图解析成具体的视图,返回给DispatcherServlet,再进行视图渲染(View),最后通过DispatcherServlet返回给用户。
    #spring mvc工作流程图

Struts2原理

SSH 通常指的是 Struts2 做前端控制器,Spring 管理各层的组件,Hibernate 负责持久化层。
SSM 则指的是 SpringMVC 做前端控制器,Spring 管理各层的组件,MyBatis 负责持久化层。
在这里插入图片描述
1、客户端初始化一个指向Servlet容器(例如Tomcat)的请求
2、这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做ActionContextCleanUp的可选过滤器,这个过滤器对于Struts2和其他框架的集成很有帮助,例如:SiteMesh Plugin
3、接着FilterDispatcher被调用,FilterDispatcher询问ActionMapper来决定这个请求是否需要调用某个Action,FilterDispatcher是控制器的核心,就是mvc中c控制层的核心
4、如果ActionMapper决定需要调用某个Action,FilterDispatcher把请求的处理交给ActionProxy
5、ActionProxy通过Configuration Manager询问框架的配置文件,找到需要调用的Action类
6、ActionProxy创建一个ActionInvocation的实例
7、ActionInvocation实例使用命名模式来调用,在调用Action的过程前后,涉及到相关拦截器(Intercepter)的调用
8、一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果。返回结果通常是(但不总是,也可 能是另外的一个Action链)一个需要被表示的JSP或者FreeMarker的模版
9、将处理结果返回给客户端

Struts2和SpringMVC两种框架对比
1.springmvc和struts2都是负责取转发的,但是两者针对request的请求上面区别很大。springmvc是针对于方法级别的请求的,也就是一个方法对应于一个请求,属于方法拦截,请求的数据方法不共享;而struts2则是针对一个Action类来进行请求的,即一个Action类对应于一个请求,所以类拦截,请求的数据类共享
2.springmvc入口是一个servlet前端控制器(DispatcherServlet),struts2入口是一filter过滤器
3.springmvc的配置文件相对struts2来说较为少,容易上手,可以加快软件开发的速度

介绍spring aop 和 ioc

  • IOC: 控制反转 对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系,所有的类的创建、销毁都由 spring来控制,IOC在系统的运行中,动态的向某个对象提供它所需要的其他对象
    由IOC容器帮对象找相应的依赖对象并注入(依赖注入)【注入对象所需要的对象,资源或者常量数据】
    IOC控制反转
    AOP:面向切面编程,可以动态地添加和删除在切面上的逻辑而不影响原来的代码,可以用作日志记录,统一异常处理,事务处理,权限检查等方面
@Aspect
@Component
public class RequestLogAspect {
    private static final Logger logger = LoggerFactory.getLogger(RequestLogAspect.class);

    @Pointcut("execution(public * com.ckq.controller..*.*(..))")
    public void webLog() {

    }
    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) {
        //接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes)joinPoint;
        HttpServletRequest request = attributes.getRequest();
        //记录下请求的内容
        logger.info("URL : " + request.getRequestURL().toString());
        logger.info("IP :" + request.getRemoteAddr());
    }
    
    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void AfterRetuning(Object ret) {
        // 处理完请求,返回内容
        logger.info("RESPONSE : " + ret);
    }
}

spring中bean注入的几种方式

三种bean配置方式

  • 基于xml 配置
<bean id="logDao" class="com.baobaotao.anno.LogDao"/>
    <bean id="userDao" class="com.baobaotao.anno.UserDao"/>
   <bean class="com.baobaotao.anno.LogonService">
       <property name="logDao" ref="logDao"></property>
       <property name="userDao" ref="userDao"></property>
   </bean>
  • 基于注解
@Autowired
@Qualifier 指定注入Bean名称
@Resource
  • 基于Java类提供的bean定义
@Configuration
@Component(默认单例模式)

spring 和 springboot 的区别

  1. spring boot中的一些特性
    • 创建独立的spring 应用
    • 嵌入Tomcat,Jetty,Undertow 容器
    • 提供starters 建华构建配置
    • 尽可能的自动配置spring 应用
    • 提供生成指标,健康检查配置
    • 没有代码生成和xml 配置要求
  2. Maven依赖
    spring 创建的web 应用需要最小依赖项
    springboot 只需要一个依赖项启动和运行web 应用程序
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
      <version>2.0.6.RELEASE</version>
    </dependency>
    spring-boot-starter-data-jpa
    spring-boot-starter-security
    spring-boot-starter-test
    spring-boot-starter-web
    spring-boot-starter-thymeleaf
    

一条sql执行过长时间,你如何优化,从哪些方面

1、查看sql是否涉及多表的联表或者子查询,如果有,看是否能进行业务拆分,相关字段冗余或者合并成临时表(业务和算法的优化)

2、涉及链表的查询,是否能进行分表查询,单表查询之后的结果进行字段整合

3、如果以上两种都不能操作,非要链表查询,那么考虑对相对应的查询条件做索引。加快查询速度

4、Explain 分析语句是否用上索引,分析扫描行数

5、数据库主从分离,读写分离,降低读写针对同一表同时的压力,至于主从同步,mysql有自带的binlog实现 主从同步

6、explain分析sql语句,查看执行计划,分析索引是否用上,分析扫描行数等等

线程的生命周期,线程的状态

新建 new
运行 Runnable(Running,Ready)
无限期等待 Wait
限期等待 Timed Wait
阻塞 Block
结束 Terminated
在这里插入图片描述

多线程的实现方式

  1. 继承-Thread类,重写run 方法
  2. 实现Runnable 接口,重写run方法,实现Runnable 接口的实现类的实例对象作为Thread构造函数的target
  3. 通过Callable 和 FutureTask 创建线程
  4. 通过线程池创建线程

MyBatis 工作原理

  • Mybatis 执行过程
    • 加载配置文件
    • 创建sqlsessionfactory
    • 创建sqlsession
    • sqlsession进行数据库操作
    • 释放资源

mybatis 运行过程

MyBatis 缓存

一、MyBatis缓存介绍
正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持

  1. 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close之后,该Session中的所有 Cache 就将清空。

  2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。

  3. 对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。

先查二级缓存,再查一级缓存,再查数据库;即使在一个sqlSession中,也会先查二级缓存;一个namespace中的查询更是如此

SSH 和 SSM对比

1.两者的相同点
Hibernate与MyBatis都可以是通过SessionFactoryBuider由XML配置文件生成SessionFactory,然后由SessionFactory 生成Session,最后由Session来开启执行事务和SQL语句。其中SessionFactoryBuider,SessionFactory,Session的生命周期都是差不多的。

Hibernate和MyBatis都支持JDBC和JTA事务处理。

  1. 不同点
    1. Hibernate把数据库给封装好以后,可以调用相应的数据库操作语句HQL,而MyBitas则是用的原始的数据库操作语句
    2. 针对高级查询,Mybatis需要手动编写SQL语句,以及ResultMap。而Hibernate有良好的映射机制,开发者无需关心SQL的生成与结果映射,可以更专注于业务流程
    3. 优化,Hibernate优化起来相对MyBitas较难,而且Hibernate掌握起来相对MyBitas较难,但是Hibernate数据库移植性很好,MyBatis的数据库移植性不好,不同的数据库需要写不同SQL

日期转换

@DateTimeFormat(pattern = “yyyy-MM-dd”)
@JsonFormat(pattern = “yyyy-MM-dd”)
private Date birth;

Filter , interceptor, aspect 的区别

拦截器:filter ,intercepter, aspect 执行顺序 filter interception aspect , filter:request,response,interceptor:获取执行的类和方法的名称 aspect: 能够拿到具体方法的参数

Restfuk API 拦截

mvn clean package -Dmaven.test.skip=true 和mvn clean package

1. mvn package
2. mvn install
3. deploay

mvn clean package依次执行了clean、resources、compile、testResources、testCompile、test、jar(打包)等7个阶段。
mvn clean install依次执行了clean、resources、compile、testResources、testCompile、test、jar(打包)、install等8个阶段。
mvn clean deploy依次执行了clean、resources、compile、testResources、testCompile、test、jar(打包)、install、deploy等9个阶段。

Servlet 生命周期

init()
service()
doGet()
doPost()
destory()

URI 中的 // 有什么用?

URI-URL-URN
URI:统一资源标识符,用来唯一的标识一个资源
URL:统一资源定位符,URI一种, 定位某个资源
URN:统一资源命名,是通过名字来标识资源,比如mailto:java-net@java.sun.com

数据库时区和服务器时区的问题

修改mysql 默认时区

show variables like "%time_zone%";
set global time_zone = "+8:00"; 设置为东8区
flush privileges; 
修改my.cnf实现永久修改MySQL时区
my.cnf 重启mysql 服务

数据库连接配置

serverTimezone=Asia/Shanghai
serverTimezone=GMT%2B8
spring.datasource.url=jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true

修改linux 系统时区
查看和修改Linux服务器上的时区

SimpleDateFormat 有线程安全性问题,如何解决

SimpleDateFormat
替代:DateTimeFormatter
LocalDateTime localDateTime = LocalDateTime().now();

  1. String -> Date
//1. 默认格式 2019-05-06T11:16:12.361
LocalDateTime.parse("2019-05-06T11:16:12.361") 
//2. 指定转换的类型
String pattern = "yyyy-MM-dd HH:mm:ss";
String date = "2020-04-21 14:43:33";
LocalDateTime localDateTime = LocalDateTime.parse(date, DateTimeFormatter.ofPattern(pattern));

2.Date -> String

DateTimeFormatter formatter =
 DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒");
String format = formatter.format(LocalDateTime.now());
return format;
  1. LocalDateTime 和 时间戳之间相互转换
  // toTimeStamp
    public Long localDateTimeToTimeStamp(LocalDateTime localDateTime) {
        //ZoneOffset.of("+8")
        return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }
    
    // toLocalDateTime
    public LocalDateTime toLocalDateTime(long timeStamp) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timeStamp), ZoneOffset.of("+8"));
    }

集群session 管理如何实现

集群session 管理
使用Redis 存储session 信息,而不是与服务器存储在一起
使用 redis 存储的优势:

 - session 访问比较频繁,redis 适合此场景
 - session 带有失效时间,redis 可以设置失效时间, 较少数据库操作

定时处理一个大表的积分字段清零

  1. update table user set xxx=0;
  2. 如果时间太长不允许就 alter table user drop column score ;
    alter table user add column score int ;
  3. 定时任务使用Quartz 或者 Task【schedule】 实现

Quartz 和 Task比较

Quartz

  1. 默认多线程异步执行
  2. 单个任务时,在上一个调度未完成时,下一个调度时间到时,会另起一个线程开始新的调度。业务繁忙时,一个任务会有多个调度,可能导致数据处理异常。
  3. 多个任务时,任务之间没有直接影响,多任务执行的快慢取决于CPU的性能
    触发方式
    1. SimpleTrigger:value=2000 每隔两秒触发
    2. CronTrigger:value=”0 0 12 * * ?” 每天中午12点触发
  4. 需要在配置文件中实现配置Job
  5. 能被集群实例化,支持分布式部署
  6. 使用JobStoreCMT(JDBCJobStore的子类),Quartz 能参与JTA事务;Quartz 能管理JTA事务(开始和提交)在执行任务之间,这样,任务做的事就可以发生在JTA事务里。
    Task
  7. 默认单线程同步执行
  8. 单个任务时,当前次的调度完成后,再执行下一次任务调度
  9. 多个任务时,一个任务执行完成后才会执行下一个任务。若需要任务能够并发执行,需手动设置线程池
  10. 触发方式:
    与Quartz的CronTrigger的表达式类似
    可以使用注解标注定时任务
    总结
  11. 实现,Task注解实现方式,比较简单。Quartz需要手动配置Jobs。
  12. 任务执行,Task默认单线程串行执行任务,多任务时若某个任务执行时间过长,后续任务会无法及时执行。Quartz采用多线程,无这个问题。
  13. 调度,Task采用顺序执行,若当前调度占用时间过长,下一个调度无法及时执行;
    Quartz采用异步,下一个调度时间到达时,会另一个线程执行调度,不会发生阻塞问题,但调度过多时可能导致数据处理异常
  14. 部署,Quartz可以采用集群方式,分布式部署到多台机器,分配执行定时任务

Git

git

如何实现一个抽奖系统

  1. 抽奖的总数和奖品总数读取配置
  2. 将需要抽奖的用户放入队列中,再一个一个取出来,进行抽奖逻辑判断
  3. 将中奖的用户和奖品绑定,对奖品库存状态数量改变
  4. 奖品和用户绑定的操作需要同步,避免并发情况下一个奖品绑定多个用户。

1,简单描述下JVM类加载过程

2,请简单说说对泛型的理解,以及使用场景
3,请描述下ConcurrentHashMap的内部结构,以及它是如何对大小进行统计
4,请描述一下阻塞队列BlockingQueue的使用及实现原理
5,如何优化表查询的执行效率
6,请描述一下观察者模式定义以及使用场景,并画出观察者模式UML类图
7,java中有哪几种线程池,分别说说什么作用
8,多线程环境中如何进行线程间通信

SpringSecurity 记住我功能实现

记住我功能实现
在认证完成,将token 存入数据库【Spring 框架自带的JdbcTokenRespository 里面有建表语句】
PersisitentTokenRepositiory 记住我功能的token 存取器配置,配置数据源。

WebSecurityConfigurerAdapter 实现类
HttpSecurity http
.rememberMe()
.tokenRepository(token存取器配置)
.tokenValiditySecond(过期时间)
.userDetailsSerice(userDetailsService)

短信验证码方式认证

短信验证码方式登录
模拟SpringSecurity 实现的UsernamePassword 流程,实现SmsAuthenticationFilter, 继承OncePerRequestFilter, 确保一次请求只通过一次filter,implements InitializingBean
http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)

OAuth2协议

OAuth2 第三方登录
四种模式

  • 授权码模式【最常见】:
    在这里插入图片描述
  • 简化模式:认证服务器直接返回token, client 直接用token 请求资源服务器
  • 密码模式:client 携带用户名和密码,获取token
  • 客户端模式:

Spring Security OAuth2 开发App认证框架

Token 方式认证

app
与传统的浏览器认证相比,如果app 同样使用session 方式认证,会使开发繁琐,用户体验差
有的前端技术不支持cookie

使用Token 方式则解决了这些问题,token 自己携带了认证数据,用户信息和自定义的数据,只需要在Http请求头部信息携带 token 就可能够实现认证逻辑.

Spring Security OAuth 框架介绍

Spring Security OAuth 框架介绍

SpringSecurity 实现 用户名、手机号、第三方token 认证

SpringSecurity OAuth实现原理
SpringSecurity实现原理
重构认证逻辑
重构认证逻辑
验证码之前是放在session 中,token 方式没有session, 需要修改验证码的存储逻辑,记录用户的设备divideId,存储到第三方数据库,根据divideId 来校验验证码
验证码存储逻辑

OAuth + JWT

SpringOAuth 默认的Token 是UUID方式生成,没有意义,当有用户请求时根据token 去查询数据库等将用户的信息查询出来
依赖存储

JWT介绍:
   自包含
   密签
   可拓展

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值