SpringMVC 面试题整理
一、基础概念类
28. MVC 分层介绍一下?
MVC 是一种设计模式,将应用程序分为三层:
-
Model(模型):负责数据和业务逻辑。包括数据承载对象(POJO)和业务处理对象(Service、DAO)。
-
View(视图):负责展示数据,与用户交互。如 JSP、Thymeleaf 等。
-
Controller(控制器):接收用户请求,调用 Model 处理,并选择合适的 View 响应。
流程:用户通过 View 发起请求 -> Controller 接收请求 -> 调用相应 Model 处理 -> 根据处理结果选择 View 渲染 -> 返回响应。
29. 了解 Spring MVC 的处理流程吗?
Spring MVC 的核心是 DispatcherServlet,处理流程如下:
-
用户发送请求到
DispatcherServlet(前端控制器)。 -
DispatcherServlet调用 HandlerMapping,根据请求 URL 找到对应的 Handler(Controller) 和拦截器,返回执行链。 -
DispatcherServlet根据 Handler 类型找到对应的 HandlerAdapter。 -
HandlerAdapter调用 Handler 的方法(执行业务逻辑),并返回 ModelAndView。 -
DispatcherServlet将 ModelAndView 交给 ViewResolver 解析,得到具体的 View 对象。 -
DispatcherServlet对 View 进行渲染(将 Model 数据填充到视图中)。 -
DispatcherServlet将最终结果响应给用户。
30. HandlerMapping 和 HandlerAdapter 有了解吗?
-
HandlerMapping:负责将请求映射到处理器(Controller)。根据请求 URL、参数等信息找到对应的 Handler 对象(通常是 Controller 的方法)。常用实现有
RequestMappingHandlerMapping(基于@RequestMapping)。 -
HandlerAdapter:负责调用处理器的方法。不同类型的处理器(如实现
Controller接口的类、@RequestMapping方法等)需要不同的适配器。HandlerAdapter统一调用逻辑,并处理参数解析、返回值处理等。常用实现有RequestMappingHandlerAdapter。
它们协同工作:HandlerMapping 找到 Handler,HandlerAdapter 调用 Handler。
31. Spring MVC 常用注解有哪些?
-
@Controller:标记类为控制器。 -
@RestController=@Controller+@ResponseBody,用于 RESTful API。 -
@RequestMapping:映射 URL 到方法或类,支持 method、params、headers 等属性。 -
@GetMapping、@PostMapping等:组合注解,简化常用请求方法。 -
@RequestParam:绑定请求参数到方法参数。 -
@PathVariable:绑定 URL 路径变量。 -
@RequestBody:将请求体绑定到方法参数(常用于 JSON)。 -
@ResponseBody:将方法返回值直接写入响应体(非视图)。 -
@ModelAttribute:绑定表单数据到模型对象,或作为方法前置数据提供。 -
@SessionAttributes:将模型属性暂存到 Session 中。 -
@InitBinder:自定义数据绑定、类型转换。 -
@ExceptionHandler:局部异常处理。
32. @Controller 和 @RestController 的区别?
-
@Controller:用于声明控制器,返回的是视图名称(或ModelAndView),通常配合视图解析器使用。如果方法需要返回 JSON 数据,需额外添加@ResponseBody。 -
@RestController:是@Controller和@ResponseBody的组合,所有方法默认返回 JSON/XML 等数据,不进行视图解析。适合构建 RESTful API。
33. @RequestParam 和 @PathVariable 的区别?
-
@RequestParam:用于获取请求参数(如?id=1)。常用于 GET/POST 表单提交。 -
@PathVariable:用于获取 URL 路径中的模板变量(如/user/{id})。常用于 RESTful 风格。
34. @RequestBody 和 @ResponseBody 的作用?
-
@RequestBody:将 HTTP 请求体(如 JSON/XML)反序列化为 Java 对象,通常与 POST/PUT 配合。 -
@ResponseBody:将 Java 对象序列化为指定格式(如 JSON/XML)直接写入 HTTP 响应体,而不是返回视图。
二、核心组件
35. 什么是 DispatcherServlet?它的作用是什么?
DispatcherServlet 是 Spring MVC 的前端控制器,是整个流程的核心。它接收所有请求,并通过 HandlerMapping 找到对应处理器,再通过 HandlerAdapter 调用处理器,最后通过 ViewResolver 解析视图并渲染。它封装了请求处理流程,实现了松耦合的设计。
36. 什么是视图解析器(ViewResolver)?举例说明。
ViewResolver 是 Spring MVC 中负责根据视图名解析为具体视图对象的组件。例如:
-
InternalResourceViewResolver:解析 JSP 视图,配置前缀和后缀,如/WEB-INF/views/和.jsp。 -
BeanNameViewResolver:根据视图名找同名的 Bean 作为视图。 -
ContentNegotiatingViewResolver:根据请求的 MIME 类型选择合适的视图。
37. Spring MVC 的控制器是单例还是多例?如何保证线程安全?
控制器默认是单例的(由 Spring 容器管理)。由于单例可能被多个线程共享,需要保证线程安全:
-
不要在控制器中定义可变成员变量(除非使用
ThreadLocal)。 -
方法内局部变量是线程安全的。
-
若必须使用状态,可以考虑将作用域改为
prototype(@Scope("prototype"))或使用@SessionAttributes等。
38. 过滤器和拦截器有什么区别?
-
过滤器(Filter):属于 Servlet 规范,对所有请求(包括静态资源)生效,基于回调函数,可修改请求/响应。常用于字符编码、跨域、XSS 过滤等。
-
拦截器(Interceptor):属于 Spring MVC 框架,只拦截控制器方法(Handler),基于反射,可访问 Spring 上下文。常用于权限校验、日志记录等。拦截器有三个方法:
preHandle(控制器执行前)、postHandle(控制器执行后、视图渲染前)、afterCompletion(视图渲染后)。
39. Spring MVC 中如何使用拦截器?
-
实现
HandlerInterceptor接口。 -
在配置类中重写
addInterceptors方法,注册拦截器并指定拦截路径。@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()) .addPathPatterns("/**") .excludePathPatterns("/login"); } }
三、数据绑定与验证
40. Spring MVC 如何实现数据验证?
Spring MVC 支持 JSR-303/JSR-380 Bean Validation(如 Hibernate Validator)。使用步骤:
-
在实体类属性上添加验证注解(如
@NotNull、@Size)。 -
在控制器方法参数前加
@Valid或@Validated注解,并紧跟BindingResult参数获取验证结果。 -
可通过全局异常处理
@ExceptionHandler统一处理验证失败异常。
示例:
public class User {
@NotNull(message = "姓名不能为空")
private String name;
@Min(value = 18, message = "年龄必须大于等于18")
private Integer age;
}
@PostMapping("/user")
public String addUser(@Valid User user, BindingResult result) {
if (result.hasErrors()) {
return "error";
}
// 业务逻辑
}
41. @InitBinder 注解的作用?
@InitBinder 用于在控制器中自定义数据绑定、类型转换、格式化规则。例如,将字符串格式的日期转换为 Date 对象:
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
}
42. Spring MVC 如何获取请求头信息?
使用 @RequestHeader 注解:
@GetMapping("/header")
public String getHeader(@RequestHeader("User-Agent") String userAgent) {
// ...
}
43. Spring MVC 如何获取 Cookie?
使用 @CookieValue 注解:
@GetMapping("/cookie")
public String getCookie(@CookieValue(value = "JSESSIONID", defaultValue = "") String sessionId) {
// ...
}
44. Spring MVC 如何处理文件上传?
-
配置
CommonsMultipartResolver或StandardServletMultipartResolver。 -
控制器方法参数使用
MultipartFile接收文件。@PostMapping("/upload") public String upload(@RequestParam("file") MultipartFile file) { // 处理文件 } -
注意设置表单的
enctype="multipart/form-data"。
四、异常与配置
45. Spring MVC 的异常处理机制有哪些?
-
局部处理:在控制器内部使用
@ExceptionHandler处理该控制器抛出的异常。 -
全局处理:使用
@ControllerAdvice+@ExceptionHandler统一处理所有控制器异常。 -
实现
HandlerExceptionResolver接口:自定义全局异常解析器。 -
配置 SimpleMappingExceptionResolver:基于 XML 配置异常与视图的映射。
46. Spring MVC 中如何统一处理全局异常?
使用 @ControllerAdvice + @ExceptionHandler 注解。
-
创建一个类,标注
@ControllerAdvice。 -
在类中定义方法,标注
@ExceptionHandler,方法参数可指定要处理的异常类型。 -
方法返回值和普通控制器类似,可以返回 ModelAndView 或
@ResponseBody数据。
例如:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
public ModelAndView handleException(Exception e) {
ModelAndView mv = new ModelAndView("error");
mv.addObject("msg", e.getMessage());
return mv;
}
}
47. Spring MVC 如何配置静态资源访问?
在配置类中重写 addResourceHandlers 方法:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/");
}
或者在 XML 中配置 <mvc:resources>。
48. Spring MVC 中如何实现重定向和转发?
-
转发:返回视图字符串时,使用
forward:前缀,如return "forward:/index",表示请求转发到另一个 URL。 -
重定向:使用
redirect:前缀,如return "redirect:/user/list",返回 302 响应,客户端重新请求。
49. Spring MVC 的父子容器是什么?
在 Spring + Spring MVC 整合时,通常会存在两个容器:
-
父容器:由
ContextLoaderListener创建,负责加载除控制器外的 Bean(如 Service、DAO、数据源等)。 -
子容器:由
DispatcherServlet创建,负责加载控制器(@Controller)等 Web 层 Bean。
子容器可以访问父容器的 Bean,反之则不能。这种设计有利于分层和隔离,但需要注意事务扫描时需包含 Service 层,避免事务失效。
50. Spring MVC 如何实现跨域请求?
-
使用
@CrossOrigin注解在控制器或方法上。@CrossOrigin(origins = "http://example.com") @GetMapping("/api") public String api() { ... } -
全局配置实现
WebMvcConfigurer的addCorsMappings方法。@Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**").allowedOrigins("*"); } -
或使用 Filter 配置 CORS 响应头。
五、高级特性
51. Spring MVC 的异步处理支持?
Spring MVC 3.2 开始支持异步处理,主要通过:
-
Callable:控制器返回
Callable,Spring 将在独立线程中执行,不阻塞 Servlet 线程。 -
DeferredResult:允许在另一个线程(如消息队列)中设置返回值,更灵活。
-
WebAsyncTask:可配置超时、任务执行器等。
示例:
@GetMapping("/async")
public Callable<String> async() {
return () -> {
Thread.sleep(2000);
return "result";
};
}
52. @ModelAttribute 注解的作用?
-
标记在方法上:在当前控制器所有方法执行前调用,将返回值存入模型(Model)中,供后续视图使用。
-
标记在参数上:从模型(或表单)中获取指定属性绑定到参数,也可用于数据绑定。
53. Spring MVC 支持哪些类型的返回值?
-
ModelAndView:包含模型和视图信息。
-
String:视图名称(可配合
@ModelAttribute等隐含模型)。 -
void:通常配合
HttpServletResponse直接输出。 -
HttpEntity / ResponseEntity:可自定义响应头、状态码和体。
-
业务对象:若方法上标注
@ResponseBody,则返回对象被序列化输出。 -
Callable / DeferredResult:用于异步处理。
转载自CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/2301_82251392/article/details/158849641



