Spring 面试题
Spring 面试题
SpringBoot可以同时处理多少个请求
该项可配置 配置项为:
server.tomcat.max-threads:Tomcat线程池最大线程数server.tomcat.max-connections:Tomcat最大连接数server.tomcat.accept-count:Tomcat最大等待连接数server.tomcat.connection-timeout:Tomcat连接超时时间 最大连接数为 Tomcat最大连接数 + Tomcat最大等待连接数
SpringBoot如何优化启动速度
延迟初始化bean 设置所有的bean为懒加载
当SpringBoot启动时,会加载许多耗时任务,比如数据库建立链接、初始线程池的创建等
spring:
main:
lazy-initialization: true # 设置所有的bean为懒加载
创建扫描bean的索引
依赖坐标:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-indexer</artifactId>
</dependency>
在启动类中添加@Indexed注解,编译打包时会在项目中自动生成META-INF/spring.components文件 当Spring 应用上下文执行ComponentScan扫描时,索引文件会被读取并加载
其他方法
- 减少
@ComponentScan、@SpringBootApplication的扫描类时候的范围 - 关闭
SpringBoot的JMX监控,设置spring.jmx.enabled=false - 设置
JVM参数,不对类进行验证 - 对非必要启动时加载的
bean延迟加载 AOPQ切面尽量不使用注解方式,这会导致启动时扫描所有方法- 关闭
Endpoint的一些监控功能 - 排除项目多余的依赖
jar swagger扫描接口时,指定只扫描某个路径下的类Feign客户端缩小扫描包的扫描范围
启动优化中级
使用JDK17与SpringBoot3
JDK17支持G1与ZGC垃圾回收器SpringBoot3支持Spring-graalvm-native,他使用GraalVM将SpringBoot应用编译成Native本地可执行的镜像文件,可以显著的提升启动速度减少内存的使用
读取配置的六种方式
使用@Value注解读取
注意
- 所在类必须由Spring 容器管理
- 读取的配置 在配置文件中必须有 否则在启动时会报错 默认值可增加容错
- 只支持单个定义 如果配置项过多 则比较繁琐
class ValueText {
@Value("${qiranqi.name:默认值}")
private String name;
}
使用@ConfigurationProperties注解读取
@ConfigurationProperties(prefix = "qiranqi")
public class ConfigPropertiesText {
private String name;
private Integer age;
}
在代码中实时获取配置
使用Environment
class EnvironmentText {
@Autowired
private Environment environment;
@Text
public void getEnvironmentText() {
String name = environment.getProperty("qiranqi.name");
}
}
获取自定义的配置文件
通过@PropetrySources注解
注意
@PropetrySources只能获取.properties文件
@PropertySources(
{@PropertySource(value = ("classpath:qiranqi.properties", encoding = "utf-8")}
)
public class CustomPropertiesText {
@Value("${qiranqi.name}")
private String name;
}
java原生方式获取配置
通过输入流的方式
解决跨域的五种方式
为什么会出现跨域
浏览器同源策略:同源策略是浏览器提供的安全策略,浏览器会阻止不同源的脚本访问,比如:
- 域名不同 www.baidu.com != www.google.com
- 端口不同 80 != 90
- 协议不同 http != https
- 域名不同 www.baidu.com != 192.168.1.1
- ip 不同 192.168.1.1 != 192.168.1.2
跨域异常只有前端才会发生
使用JSONP方式
缺点:
- 只支持get请求
- 前后端都需要编写代码,存在耦合
前端dataType指定为jsonp
默认会将callback参数传给后端 后端需要再返回callback
$.ajax({
url: 'http://www.baidu.com',
type: 'get',
dataType: 'jsonp',
success: function (data) {
console.log(data)
}
})
后端
@Controller
public class JsonpController {
@GetMapping("/jsonp")
public String jsonp(String callback) {
return new JSONPObject(callback, new Result(200, "success"));
}
}
CORS方式 推荐
设置单个接口
使用@CrossOrigin注解,配置跨域的来源
@Controller
@CrossOrigin("http://www.baidu.com:8080")
public class CorsController {
}
配置全局跨域
编写全局配置类,实现WebMvcConfigurer接口,重写addCorsMappings方法
//全局cors配置类
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/user/*")// 设置那一批接口支持跨域
.allowedOrigins("http://www.baidu.com:8080")//设置跨域的来源
.allowCredentials(true)// 允许携带cookie
.allowedMethods("GET", "POST", "PUT", "DELETE")// 设置允许的请求方式
.maxAge(3600);// 设置缓存时间
}
}
设置所有接口都支持跨域(不支持ie8)
通过CorsFilter设置所有接口都支持跨域
@Configuration
public class MyCorsFilter {
@Bean
public CorsFilter corsFilter() {
//创建cors配置对象
CorsConfiguration config = new CorsConfiguration();
//设置跨域的来源
config.addAllowedOriginPattern("*");
//是否发送cookie
config.setAllowCredentials(true);
//允许的请求方式
config.addAllowedMethod("*");
//添加地址映射
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
//返回corsFilter 对象
return new CorsFilter(source);
}
}
使用Nginx反向代理
location /api/ {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8080/user/;
}