关注

Spring + SpringMVC 面试题整理笔记(二)

SpringMVC 面试题整理

一、基础概念类

28. MVC 分层介绍一下?

MVC 是一种设计模式,将应用程序分为三层:

  • Model(模型):负责数据和业务逻辑。包括数据承载对象(POJO)和业务处理对象(Service、DAO)。

  • View(视图):负责展示数据,与用户交互。如 JSP、Thymeleaf 等。

  • Controller(控制器):接收用户请求,调用 Model 处理,并选择合适的 View 响应。

流程:用户通过 View 发起请求 -> Controller 接收请求 -> 调用相应 Model 处理 -> 根据处理结果选择 View 渲染 -> 返回响应。

29. 了解 Spring MVC 的处理流程吗?

Spring MVC 的核心是 DispatcherServlet,处理流程如下:

  1. 用户发送请求到 DispatcherServlet(前端控制器)。

  2. DispatcherServlet 调用 HandlerMapping,根据请求 URL 找到对应的 Handler(Controller) 和拦截器,返回执行链。

  3. DispatcherServlet 根据 Handler 类型找到对应的 HandlerAdapter

  4. HandlerAdapter 调用 Handler 的方法(执行业务逻辑),并返回 ModelAndView

  5. DispatcherServlet 将 ModelAndView 交给 ViewResolver 解析,得到具体的 View 对象。

  6. DispatcherServlet 对 View 进行渲染(将 Model 数据填充到视图中)。

  7. 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 中如何使用拦截器?

  1. 实现 HandlerInterceptor 接口。

  2. 在配置类中重写 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)。使用步骤:

  1. 在实体类属性上添加验证注解(如 @NotNull@Size)。

  2. 在控制器方法参数前加 @Valid@Validated 注解,并紧跟 BindingResult 参数获取验证结果。

  3. 可通过全局异常处理 @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 如何处理文件上传?

  1. 配置 CommonsMultipartResolverStandardServletMultipartResolver

  2. 控制器方法参数使用 MultipartFile 接收文件。

    @PostMapping("/upload")
    public String upload(@RequestParam("file") MultipartFile file) {
        // 处理文件
    }
  3. 注意设置表单的 enctype="multipart/form-data"

四、异常与配置

45. Spring MVC 的异常处理机制有哪些?

  1. 局部处理:在控制器内部使用 @ExceptionHandler 处理该控制器抛出的异常。

  2. 全局处理:使用 @ControllerAdvice + @ExceptionHandler 统一处理所有控制器异常。

  3. 实现 HandlerExceptionResolver 接口:自定义全局异常解析器。

  4. 配置 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() { ... }
  • 全局配置实现 WebMvcConfigureraddCorsMappings 方法。

    @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

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--