一、Spring MVC 核心定位
Spring MVC 是 Spring 框架提供的轻量级、基于MVC设计模式的Web框架,全称为 Spring Web MVC,是目前Java EE领域主流的Web开发框架之一。
- 核心目标:简化Web层开发,实现请求与响应的解耦、数据绑定、视图渲染、异常处理等核心能力;
- 核心优势:
- 松耦合:基于IoC容器管理组件,控制器、服务、视图解耦;
- 灵活性:支持多种视图技术(JSP、Thymeleaf、Freemarker)、多种请求参数绑定方式;
- 扩展性:内置拦截器、异常处理器,支持自定义扩展;
- 无缝集成:与Spring Core、Spring Boot、Spring Security等生态组件无缝整合;
- 应用场景:所有Java Web应用(单体应用、微服务Web层),是Spring Boot Web开发的默认选择。
二、Spring MVC 核心架构
2.1 MVC设计模式核心思想
MVC(Model-View-Controller)将Web应用分为三层,职责边界清晰:
- Model(模型):封装业务数据和业务逻辑,对应POJO、Service、DAO等;
- View(视图):负责数据展示,对应JSP、Thymeleaf模板、JSON/XML响应等;
- Controller(控制器) :接收请求、处理参数、调用业务逻辑、返回响应,对应
@Controller注解的类。
2.2 Spring MVC 整体架构分层
Spring MVC在MVC基础上扩展了核心组件,形成完整的请求处理链路:
2.3 核心组件解析
2.3.1 DispatcherServlet(前端控制器)
- 本质:核心Servlet,是Spring MVC的「中央调度器」,所有请求的入口;
- 核心职责:
- 接收所有客户端请求(通过web.xml/Spring Boot自动配置映射);
- 协调其他组件(HandlerMapping、HandlerAdapter等)完成请求处理;
- 统一处理异常、渲染视图、返回响应;
- 生命周期:随Web容器启动初始化,销毁时释放资源,全局单例。
2.3.2 HandlerMapping(处理器映射器)
- 本质:根据请求URL匹配对应的Handler(控制器方法);
- 核心实现:
RequestMappingHandlerMapping:处理@RequestMapping注解的映射(主流);SimpleUrlHandlerMapping:基于XML配置URL与Handler的映射(传统方式);
- 核心逻辑:解析请求URL、请求方法(GET/POST)、请求头,匹配到对应的
HandlerMethod(控制器方法封装对象)。
2.3.3 HandlerAdapter(处理器适配器)
- 本质:适配不同类型的Handler,统一调用处理器方法;
- 核心实现:
RequestMappingHandlerAdapter:适配@RequestMapping注解的控制器方法(主流);HttpRequestHandlerAdapter:适配实现HttpRequestHandler接口的处理器;
- 核心能力:参数绑定、类型转换、调用处理器方法、返回
ModelAndView。
2.3.4 Handler(处理器/控制器)
- 本质:处理具体业务逻辑的组件,通常是
@Controller注解的类中的方法; - 核心形式:
- 基于注解:
@Controller+@RequestMapping(主流); - 基于接口:实现
Controller/HttpRequestHandler接口(传统方式);
- 基于注解:
- 核心职责:接收请求参数、调用Service层、封装Model数据、指定视图名称。
2.3.5 ViewResolver(视图解析器)
- 本质:根据视图名称解析为具体的View对象;
- 核心实现:
InternalResourceViewResolver:解析JSP视图(传统);ThymeleafViewResolver:解析Thymeleaf模板(主流);MappingJackson2JsonView:解析JSON响应(无视图场景);
- 核心逻辑:拼接视图前缀/后缀(如
/WEB-INF/views/+ 视图名 +.jsp),生成View对象。
2.3.6 HandlerInterceptor(拦截器)
- 本质:请求处理的切面扩展点,基于AOP思想实现;
- 核心方法:
preHandle:请求到达处理器前执行(返回false则中断请求);postHandle:处理器执行完成后、视图渲染前执行;afterCompletion:视图渲染完成后执行(用于资源清理);
- 核心场景:登录校验、权限控制、日志记录、性能监控。
2.3.7 HandlerExceptionResolver(异常处理器)
- 本质:统一处理请求过程中抛出的异常;
- 核心实现:
SimpleMappingExceptionResolver:映射异常到指定视图;@ControllerAdvice+@ExceptionHandler:注解式全局异常处理(主流);
- 核心职责:捕获异常、封装错误信息、返回友好响应。
三、Spring MVC 核心工作流程
客户端请求从进入到响应的完整流程(共10步):
- 请求接收 :客户端发送HTTP请求,由
DispatcherServlet接收; - 处理器映射 :
DispatcherServlet调用HandlerMapping,根据URL匹配到对应的HandlerMethod; - 处理器适配 :
DispatcherServlet调用HandlerAdapter,适配找到的HandlerMethod; - 拦截器前置处理 :执行
HandlerInterceptor的preHandle方法(若返回false,流程终止); - 处理器执行 :
HandlerAdapter调用控制器方法,完成参数绑定、业务逻辑处理,返回ModelAndView; - 拦截器后置处理 :执行
HandlerInterceptor的postHandle方法; - 异常处理 :若步骤5抛出异常,由
HandlerExceptionResolver统一处理; - 视图解析 :
DispatcherServlet调用ViewResolver,将ModelAndView中的视图名解析为View对象; - 视图渲染:View对象渲染模型数据(Model),生成响应内容(HTML/JSON/XML);
- 拦截器完成处理 :执行
HandlerInterceptor的afterCompletion方法,DispatcherServlet返回响应给客户端。
核心关键点:
DispatcherServlet是整个流程的核心,负责协调所有组件,自身不处理具体业务,仅做调度。
四、Spring MVC 关键特性解析
4.1 请求映射(@RequestMapping)
@RequestMapping是Spring MVC核心注解,用于映射请求URL、方法、请求头等:
4.1.1 核心属性
| 属性 | 作用 | 示例 |
|---|---|---|
value/path |
映射URL路径 | @RequestMapping("/user/list") |
method |
映射请求方法 | method = RequestMethod.GET |
params |
映射请求参数 | params = "id!=1"(id不等于1) |
headers |
映射请求头 | headers = "Content-Type=application/json" |
consumes |
接收的Content-Type | consumes = "application/json" |
produces |
返回的Content-Type | produces = "application/json;charset=UTF-8" |
4.1.2 简化注解(Spring 4.3+)
为常用请求方法提供简化注解,替代method属性:
@GetMapping:等价于@RequestMapping(method = RequestMethod.GET);@PostMapping:等价于@RequestMapping(method = RequestMethod.POST);@PutMapping/@DeleteMapping/@PatchMapping:对应PUT/DELETE/PATCH方法。
java
// 简化注解示例
@RestController
@RequestMapping("/user")
public class UserController {
// GET请求:/user/1
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userService.getById(id);
}
// POST请求:/user
@PostMapping
public Result saveUser(@RequestBody User user) {
userService.save(user);
return Result.success();
}
}
4.2 请求参数绑定
Spring MVC支持多种参数绑定方式,自动将请求参数转换为Java对象:
4.2.1 核心参数注解
| 注解 | 作用 | 示例 |
|---|---|---|
@PathVariable |
绑定URL路径参数 | @PathVariable Long id |
@RequestParam |
绑定请求参数(QueryString/Form) | @RequestParam(required = false) String name |
@RequestBody |
绑定请求体(JSON/XML) | @RequestBody User user |
@RequestHeader |
绑定请求头 | @RequestHeader("token") String token |
@CookieValue |
绑定Cookie | @CookieValue("JSESSIONID") String sessionId |
@ModelAttribute |
绑定表单数据到模型对象 | @ModelAttribute User user |
4.2.2 类型转换
- 内置转换器:支持基本类型(String→int/long)、日期类型(String→Date/LocalDateTime);
- 自定义转换器:实现
Converter<S, T>接口,注册到Spring容器;
java
// 自定义日期转换器示例
@Component
public class StringToLocalDateTimeConverter implements Converter<String, LocalDateTime> {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@Override
public LocalDateTime convert(String source) {
return LocalDateTime.parse(source, FORMATTER);
}
}
4.3 视图与响应
Spring MVC支持多种响应类型,满足不同场景需求:
4.3.1 视图响应(传统Web)
- 基于JSP/Thymeleaf:返回视图名,由
ViewResolver解析为页面; - 核心返回值:
ModelAndView/String(视图名);
java
@Controller
@RequestMapping("/page")
public class PageController {
// 返回Thymeleaf视图:templates/index.html
@GetMapping("/index")
public String index(Model model) {
model.addAttribute("name", "Spring MVC");
return "index"; // 视图名
}
}
4.3.2 数据响应(前后端分离)
- 基于JSON:使用
@RestController(等价于@Controller + @ResponseBody),自动将返回值序列化为JSON; - 核心依赖:
jackson-databind(Spring Boot自动引入);
java
@RestController
@RequestMapping("/api")
public class ApiController {
// 返回JSON响应
@GetMapping("/data")
public Result<Map<String, Object>> getData() {
Map<String, Object> data = new HashMap<>();
data.put("code", 200);
data.put("msg", "success");
return Result.success(data);
}
}
4.4 拦截器(HandlerInterceptor)
4.4.1 自定义拦截器步骤
- 实现
HandlerInterceptor接口(或继承HandlerInterceptorAdapter); - 注册拦截器到Spring容器,指定拦截路径;
java
// 1. 自定义拦截器
@Component
public class LoginInterceptor implements HandlerInterceptor {
// 请求到达处理器前执行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");
if (token == null || !token.equals("valid_token")) {
response.setStatus(401);
response.getWriter().write("未登录");
return false; // 中断请求
}
return true; // 放行
}
// 处理器执行后、视图渲染前执行
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("处理器执行完成:" + request.getRequestURI());
}
// 视图渲染完成后执行
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("请求处理完成:" + request.getRequestURI());
}
}
// 2. 注册拦截器(Spring Boot配置)
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/api/**") // 拦截/api/**路径
.excludePathPatterns("/api/login"); // 排除登录接口
}
}
4.5 全局异常处理
4.5.1 注解式全局异常处理(主流)
使用@ControllerAdvice + @ExceptionHandler实现全局异常捕获:
java
// 全局异常处理器
@RestControllerAdvice // 等价于@ControllerAdvice + @ResponseBody
public class GlobalExceptionHandler {
// 处理自定义业务异常
@ExceptionHandler(BusinessException.class)
public Result handleBusinessException(BusinessException e) {
return Result.fail(e.getCode(), e.getMessage());
}
// 处理参数绑定异常
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result handleValidException(MethodArgumentNotValidException e) {
String message = e.getBindingResult().getFieldError().getDefaultMessage();
return Result.fail(400, "参数错误:" + message);
}
// 处理所有未捕获的异常
@ExceptionHandler(Exception.class)
public Result handleException(Exception e) {
log.error("系统异常", e);
return Result.fail(500, "服务器内部错误");
}
}
// 自定义业务异常
public class BusinessException extends RuntimeException {
private int code;
public BusinessException(int code, String message) {
super(message);
this.code = code;
}
// getter/setter
}
五、Spring MVC 核心配置
5.1 Spring Boot 自动配置(主流)
Spring Boot通过spring-boot-starter-web自动配置Spring MVC核心组件,无需手动配置:
5.1.1 核心依赖
xml
<!-- Spring Boot Web Starter(包含Spring MVC核心依赖) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 可选:Thymeleaf视图依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
5.1.2 核心配置(application.yml)
yaml
spring:
# MVC基础配置
mvc:
servlet:
path: /# 请求根路径(默认/)
view:
prefix: /templates/# 视图前缀(Thymeleaf)
suffix: .html# 视图后缀
format:
date: yyyy-MM-dd# 日期格式化
# 静态资源配置
web:
resources:
static-locations: classpath:/static/,classpath:/public/# 静态资源路径
# 国际化配置(可选)
messages:
basename: i18n/messages# 国际化资源文件路径
encoding: UTF-8
server:
port: 8080# 端口
servlet:
context-path: /demo# 应用上下文路径
5.2 传统XML配置(了解即可)
非Spring Boot项目需手动配置DispatcherServlet和核心组件:
5.2.1 web.xml配置DispatcherServlet
xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 配置DispatcherServlet -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 配置Spring MVC配置文件路径 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<!-- 随Web容器启动加载 -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- 映射所有请求 -->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
5.2.2 spring-mvc.xml核心配置
xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 扫描控制器包 -->
<context:component-scan base-package="com.example.controller"/>
<!-- 启用注解驱动(自动注册HandlerMapping/HandlerAdapter) -->
<mvc:annotation-driven/>
<!-- 静态资源放行 -->
<mvc:default-servlet-handler/>
<!-- 视图解析器(JSP) -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 注册拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/login"/>
<bean class="com.example.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
六、Spring MVC 高级用法
6.1 跨域配置(CORS)
前后端分离场景下,需配置跨域允许:
6.1.1 全局跨域配置
java
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**") // 允许跨域的路径
.allowedOriginPatterns("*") // 允许的源(Spring Boot 2.4+用allowedOriginPatterns)
.allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的请求方法
.allowedHeaders("*") // 允许的请求头
.allowCredentials(true) // 允许携带Cookie
.maxAge(3600); // 预检请求缓存时间(秒)
}
}
6.1.2 局部跨域配置
使用@CrossOrigin注解在控制器/方法上:
java
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "*", maxAge = 3600)
public class UserController {
// 方法级跨域(覆盖类级配置)
@GetMapping("/user")
@CrossOrigin(origins = "http://localhost:8081")
public Result getUser() {
return Result.success();
}
}
6.2 文件上传
Spring MVC支持单文件/多文件上传:
6.2.1 核心配置(Spring Boot)
yaml
spring:
servlet:
multipart:
max-file-size: 10MB # 单个文件最大大小
max-request-size: 100MB # 请求总文件大小
enabled: true # 启用文件上传
6.2.2 上传接口实现
java
@RestController
@RequestMapping("/upload")
public class UploadController {
// 单文件上传
@PostMapping("/single")
public Result singleUpload(@RequestParam("file") MultipartFile file) throws IOException {
if (file.isEmpty()) {
return Result.fail(400, "文件为空");
}
// 保存文件
String originalFilename = file.getOriginalFilename();
String filePath = "uploads/" + System.currentTimeMillis() + "_" + originalFilename;
File dest = new File(filePath);
Files.copy(file.getInputStream(), dest.toPath());
return Result.success("文件上传成功:" + filePath);
}
// 多文件上传
@PostMapping("/multiple")
public Result multipleUpload(@RequestParam("files") MultipartFile[] files) {
List<String> paths = new ArrayList<>();
for (MultipartFile file : files) {
if (!file.isEmpty()) {
try {
String filePath = "uploads/" + System.currentTimeMillis() + "_" + file.getOriginalFilename();
Files.copy(file.getInputStream(), new File(filePath).toPath());
paths.add(filePath);
} catch (IOException e) {
e.printStackTrace();
}
}
}
return Result.success("上传成功:" + paths);
}
}
6.3 自定义参数解析器
实现HandlerMethodArgumentResolver接口,自定义参数绑定逻辑:
java
// 1. 自定义注解
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUser {
}
// 2. 自定义参数解析器
@Component
public class CurrentUserArgumentResolver implements HandlerMethodArgumentResolver {
// 判断是否支持该参数
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(CurrentUser.class);
}
// 解析参数
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
String token = request.getHeader("token");
// 从token解析用户信息(示例)
User user = userService.getUserByToken(token);
return user;
}
}
// 3. 注册参数解析器
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private CurrentUserArgumentResolver currentUserArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(currentUserArgumentResolver);
}
}
// 4. 使用自定义参数
@GetMapping("/info")
public Result getUserInfo(@CurrentUser User user) {
return Result.success(user);
}
七、Spring MVC 性能优化要点
7.1 基础优化
- 减少拦截器开销:避免在拦截器中编写耗时逻辑(如远程调用),仅保留核心逻辑;
- 静态资源优化 :
- 将静态资源(JS/CSS/图片)部署到CDN;
- 启用静态资源缓存(设置
Cache-Control响应头);
- 视图优化 :
- 前后端分离场景使用
@RestController,避免视图渲染开销; - Thymeleaf启用缓存(生产环境):
spring.thymeleaf.cache=true;
- 前后端分离场景使用
- 参数绑定优化:避免复杂对象的深度绑定,减少反射开销。
7.2 高级优化
- 启用异步请求 :使用
Callable/DeferredResult实现异步处理,提高吞吐量;
java
// 异步请求示例
@GetMapping("/async")
public Callable<Result> asyncRequest() {
return () -> {
// 异步执行耗时任务
Thread.sleep(1000);
return Result.success("异步响应");
};
}
- 请求体缓存 :多次读取请求体时,使用
ContentCachingRequestWrapper包装请求; - 连接池优化 :调整Tomcat连接池参数(如
server.tomcat.max-threads),适配并发量; - 日志优化:生产环境关闭DEBUG日志,减少IO开销。
八、Spring MVC 常见问题
8.1 基础概念类
-
Spring MVC 的核心组件有哪些?各自的作用是什么?
- 核心组件:
DispatcherServlet(前端控制器)、HandlerMapping(处理器映射器)、HandlerAdapter(处理器适配器)、Handler(处理器)、ViewResolver(视图解析器); - 核心作用:
DispatcherServlet调度所有组件,HandlerMapping匹配URL,HandlerAdapter适配执行处理器,ViewResolver解析视图。
- 核心组件:
-
@Controller和@RestController的区别?@Controller:标记控制器,返回值为视图名(需配合@ResponseBody返回JSON);@RestController:等价于@Controller + @ResponseBody,返回值自动序列化为JSON,无视图渲染。
-
Spring MVC 的拦截器和过滤器的区别?
维度 拦截器(HandlerInterceptor) 过滤器(Filter) 所属框架 Spring MVC Servlet规范 执行时机 DispatcherServlet之后 DispatcherServlet之前 拦截范围 仅拦截控制器请求 拦截所有请求(包括静态资源) 控制方式 Spring容器管理,支持依赖注入 容器独立管理,无法注入Spring Bean 核心方法 preHandle/postHandle/afterCompletion doFilter
8.2 核心原理类
-
Spring MVC 的请求处理流程?
- 核心流程:请求→DispatcherServlet→HandlerMapping→HandlerAdapter→Handler→ModelAndView→ViewResolver→View→响应;
- 关键节点:拦截器的三个方法执行时机、异常处理器的触发时机。
-
@RequestMapping的工作原理?- 启动时,
RequestMappingHandlerMapping扫描所有@RequestMapping注解,解析URL、方法、参数等信息,存入映射注册表; - 请求到达时,根据URL、请求方法等匹配注册表中的
HandlerMethod,交由HandlerAdapter执行。
- 启动时,
-
Spring MVC 如何实现参数绑定?
- 核心原理:
HandlerAdapter通过WebDataBinder将请求参数转换为Java对象; - 关键组件:
Converter(类型转换)、Validator(参数校验)、ArgumentResolver(参数解析器)。
- 核心原理:
8.3 实战应用类
-
如何实现Spring MVC的全局异常处理?
- 主流方案:
@ControllerAdvice + @ExceptionHandler,捕获指定异常类型,返回统一格式响应; - 补充方案:实现
HandlerExceptionResolver接口,重写resolveException方法。
- 主流方案:
-
如何解决Spring MVC的跨域问题?
- 全局方案:实现
WebMvcConfigurer的addCorsMappings方法,配置跨域规则; - 局部方案:使用
@CrossOrigin注解在控制器/方法上; - 底层原理:设置
Access-Control-Allow-Origin等响应头。
- 全局方案:实现
-
Spring Boot 中Spring MVC的自动配置原理?
- 核心类:
WebMvcAutoConfiguration,自动配置DispatcherServlet、HandlerMapping、HandlerAdapter、ViewResolver等核心组件; - 核心条件:引入
spring-boot-starter-web依赖,自动启用WebMvcAutoConfiguration。
- 核心类:
九、总结
核心关键点
- 核心定位:Spring MVC是基于MVC模式的Web框架,DispatcherServlet是核心调度器,负责协调所有组件;
- 核心流程:请求→DispatcherServlet→HandlerMapping→HandlerAdapter→Handler→ModelAndView→ViewResolver→View→响应;
- 核心特性 :
- 请求映射:
@RequestMapping及简化注解(@GetMapping/@PostMapping); - 参数绑定:支持
@PathVariable/@RequestParam/@RequestBody等多种方式; - 扩展能力:拦截器、全局异常处理、自定义参数解析器;
- 请求映射:
- 配置方式 :Spring Boot中通过
spring-boot-starter-web自动配置,无需手动配置核心组件; - 最佳实践 :
- 前后端分离场景使用
@RestController,返回JSON响应; - 全局异常处理使用
@ControllerAdvice + @ExceptionHandler; - 跨域配置优先使用全局配置,减少重复代码;
- 性能优化:启用异步请求、优化静态资源、减少拦截器开销。
- 前后端分离场景使用