1. Spring MVC面试核心要点解析
作为Java Web开发中最经典的框架之一,Spring MVC的面试问题往往围绕着其核心架构和设计思想展开。我在技术面试中经常发现,很多候选人对基础概念倒背如流,但一旦问到实际场景下的设计考量就会卡壳。今天我们就来拆解那些高频出现的Spring MVC面试题,不仅告诉你标准答案,更会解释背后的设计哲学。
2. 核心组件工作原理
2.1 DispatcherServlet的请求处理流程
当HTTP请求到达时,DispatcherServlet作为前端控制器会按固定流程处理:
- 首先通过HandlerMapping定位到具体的Controller
- 然后通过HandlerAdapter执行目标方法
- 方法返回的ModelAndView会交给ViewResolver解析
- 最终渲染视图返回响应
这个过程中有个容易忽略的细节:HandlerMapping的优先级问题。默认情况下,RequestMappingHandlerMapping的优先级高于BeanNameUrlHandlerMapping,这意味着注解驱动的控制器会优先被匹配。
实际开发中遇到过由于多个HandlerMapping冲突导致的404问题,建议在配置时显式指定order属性
2.2 参数绑定的魔法
Spring MVC的参数绑定机制远比表面看到的复杂:
- 基本类型和String通过DataBinder自动转换
- 复杂对象使用PropertyEditor或Converter
- @RequestParam用于简单参数
- @ModelAttribute处理表单对象
- @RequestBody处理JSON/XML
我曾经遇到一个坑:当方法参数是Optional时,如果请求参数缺失会注入Optional.empty()而不是报错,这个特性在接口版本兼容时很有用。
3. 高级特性深度剖析
3.1 拦截器vs过滤器
很多面试者分不清这两者的区别,其实关键差异在于:
- 过滤器是Servlet规范层面的,拦截器是Spring MVC层面的
- 过滤器可以处理所有请求,拦截器只能处理DispatcherServlet分发的请求
- 拦截器可以获取到HandlerMethod信息
一个实用的拦截器配置技巧:
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LogInterceptor()) .addPathPatterns("/api/**") .excludePathPatterns("/api/public/**"); }3.2 异常处理机制
Spring MVC提供了多种异常处理方式:
- @ExceptionHandler注解处理控制器内部异常
- @ControllerAdvice实现全局异常处理
- HandlerExceptionResolver接口自定义解析器
- SimpleMappingExceptionResolver配置异常视图
在微服务架构下,我推荐使用@ControllerAdvice统一返回错误JSON:
@ControllerAdvice public class GlobalExceptionHandler { @ResponseBody @ExceptionHandler(Exception.class) public Result handleException(Exception e) { return Result.error(e.getMessage()); } }4. 性能优化实战技巧
4.1 静态资源处理
不当的静态资源配置会导致不必要的控制器匹配:
@Override public void configureDefaultServletHandling( DefaultServletHandlerConfigurer configurer) { configurer.enable(); }更高效的做法是使用资源处理器:
@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**") .addResourceLocations("classpath:/static/"); }4.2 异步处理
从Spring 3.2开始支持的异步处理能显著提升吞吐量:
@GetMapping("/async") public Callable<String> asyncRequest() { return () -> { Thread.sleep(1000); return "Async Result"; }; }注意:异步请求需要配置AsyncSupportConfigurer,否则会退化为同步处理。
5. 常见面试问题精讲
5.1 谈谈Spring MVC的工作流程
这个问题考察对整体架构的理解,建议分步骤说明:
- 用户发送请求到DispatcherServlet
- 查询HandlerMapping找到处理器
- 通过HandlerAdapter执行处理器
- 处理业务逻辑后返回ModelAndView
- 解析视图并渲染返回
加分项是能说出每个步骤可扩展的点,比如自定义ViewResolver等。
5.2 如何实现文件上传
标准实现方式:
@PostMapping("/upload") public String handleUpload(@RequestParam MultipartFile file) { file.transferTo(new File("/path/to/save")); return "success"; }需要配合配置:
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="10485760"/> </bean>6. 设计思想与最佳实践
6.1 RESTful设计原则
Spring MVC对REST的支持非常完善:
- @RestController组合注解
- @RequestMapping的method属性
- @PathVariable路径变量
- ResponseEntity返回响应实体
一个标准的REST控制器示例:
@RestController @RequestMapping("/api/users") public class UserController { @GetMapping("/{id}") public User getById(@PathVariable Long id) { return userService.findById(id); } @PostMapping public ResponseEntity<Void> create(@RequestBody User user) { userService.save(user); return ResponseEntity.created(URI.create("/users/"+user.getId())).build(); } }6.2 测试策略
Spring MVC测试框架非常强大:
@RunWith(SpringRunner.class) @WebMvcTest(UserController.class) public class UserControllerTest { @Autowired private MockMvc mockMvc; @Test public void testGetUser() throws Exception { mockMvc.perform(get("/users/1")) .andExpect(status().isOk()) .andExpect(jsonPath("$.name").value("张三")); } }MockMvc可以模拟完整的HTTP请求而不需要启动服务器,非常适合单元测试。