乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 SpringMVC概述与DispatcherServlet

    • 本章导读:Spring MVC概述与DispatcherServlet
    • Spring MVC 是什么
    • MVC 设计模式
    • 前端控制器模式
    • DispatcherServlet
    • 核心组件协作
  • 第2章 控制器与请求映射

    • 本章导读:控制器与请求映射
    • Controller
    • RestController
    • RequestMapping
    • GetMapping
    • PostMapping
    • PutMapping
    • DeleteMapping
    • PathVariable
    • RESTful
    • 请求映射原理
  • 第3章 请求参数获取与转换

    • 本章导读:请求参数获取与转换
    • RequestParam
    • RequestBody
    • RequestHeader
    • CookieValue
    • Model
    • ModelAttribute
    • 数据绑定原理
    • 数据校验
  • 第4章 响应数据与视图解析

    • 本章导读:响应数据与视图解析
    • ResponseBody
    • ResponseEntity
    • ModelAndView
    • ViewResolver
    • HttpMessageConverter
    • forward与redirect
  • 第5章 拦截器过滤器与跨域

    • 本章导读:拦截器、过滤器与跨域
    • HandlerInterceptor
    • WebMvcConfigurer
    • CrossOrigin
    • 登录验证实战
  • 第6章 文件上传与异常处理

    • 本章导读:文件上传与异常处理
    • MultipartFile
    • 文件下载
    • ExceptionHandler
    • ControllerAdvice
    • RestControllerAdvice
    • ResponseStatus
  • 第7章 高级特性与最佳实践

    • 本章导读:高级特性与最佳实践
    • SessionAttributes
    • SessionAttribute
    • RedirectAttributes
    • MockMvc测试
    • 国际化
    • 最佳实践
  • 第8章 扩展与异步机制

    • 本章导读:扩展与异步机制
    • 异步请求处理
    • 自定义参数解析器
    • 内容协商

Controller

本章进入 Spring MVC 的控制器层。DispatcherServlet 负责接收和分发请求,HandlerMapping 负责查找处理器,但真正的业务逻辑入口是 Controller。@Controller 是 Spring MVC 中最基础的注解之一,它标记一个类为 Web 请求处理器,其方法返回值在默认情况下会被 ViewResolver 解析为视图名。理解 @Controller,就理解了 Spring MVC 的视图渲染模式。


定义与作用

@Controller 是 Spring Framework 提供的类级注解,它的职责可以用一句话概括:标记一个类为 Spring MVC 的控制器,使其方法能够处理 HTTP 请求,并将方法返回值作为视图名进行解析。

在 Spring MVC 的组件体系中:

  • @Controller = Web 层组件,负责接收请求、调用业务层、返回视图或数据
  • @Service = 业务层组件,负责业务逻辑(本教程不展开)
  • @Repository = 数据层组件,负责数据访问(本教程不展开)

@Controller 与 @Service 的区别

对比维度@Controller@Service
所属层级Web 层(表现层)业务层
核心职责接收 HTTP 请求、调用 Service、返回响应执行业务逻辑、事务管理
方法返回值默认被 ViewResolver 解析为视图名业务对象或原始数据
是否感知 HTTP是(操作 Request/Response)否(纯业务逻辑)
典型方法String listUsers()List<User> findAll()
是否可被注入是(容器管理)是(容器管理)

关键边界:@Controller 的方法默认走视图渲染流程——返回 "employee/list" 时,ViewResolver 会查找 /WEB-INF/views/employee/list.jsp(或 Thymeleaf 模板)。如果希望方法返回值直接写入响应体(如 JSON),需要额外标注 @ResponseBody。


核心原理

@Controller 的识别与注册

图解:

  • @Controller 类在启动时被注册为 Bean,同时其 @RequestMapping 方法被解析为映射规则
  • 请求到达时,HandlerAdapter 调用 Controller 方法
  • 没有 @ResponseBody 时,返回值走 ViewResolver 流程(视图渲染模式)
  • 有 @ResponseBody 时,返回值走 HttpMessageConverter 流程(数据直写模式)

适用位置与常用属性

@Controller 是元注解 @Component 的特化,本身没有额外属性,但通常与以下注解配合使用:

配合使用的注解

注解作用与 @Controller 的关系
@RequestMapping声明请求映射规则标注在 @Controller 类的方法上
@ResponseBody返回值直接写入响应体标注在方法上,绕过视图解析
@RestController@Controller + @ResponseBody类级组合注解,所有方法默认直写
@Autowired依赖注入注入 Service Bean(容器已提供)

Controller 方法返回值类型对比

返回值类型处理方式典型场景
String作为视图名解析返回 "employee/list" → 渲染列表页
ModelAndView同时携带视图名和数据模型需要显式控制视图和模型
void无视图,由方法自行处理响应直接操作 HttpServletResponse
View直接返回视图对象需要动态选择视图实现
Map / Model作为模型数据,视图名由 RequestToViewNameTranslator 推断简化返回值
任意对象(+ @ResponseBody)HttpMessageConverter 序列化RESTful API 返回 JSON/XML

完整示例

场景

飞翔科技的员工管理系统需要支持页面渲染模式。前端工程师黄俪使用 Thymeleaf 模板引擎,后端工程师小崔编写 @Controller 返回视图名。

控制器代码

package com.feixiang.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/employees")
public class EmployeeController {

    // 容器已注入该 Bean,本教程不展开 Service 实现
    @Autowired
    private EmployeeService employeeService;

    // 示例 1:返回 String 作为视图名
    @GetMapping
    public String listAll(Model model) {
        model.addAttribute("employees", employeeService.findAll());
        return "employee/list"; // 解析为 /templates/employee/list.html
    }

    // 示例 2:返回 ModelAndView
    @GetMapping("/{id}/detail")
    public ModelAndView getDetail(@PathVariable Long id) {
        ModelAndView mav = new ModelAndView("employee/detail");
        mav.addObject("employee", employeeService.findById(id));
        return mav;
    }
}

HTTP 请求示例 1:返回 String 视图名

curl -X GET http://localhost:8080/employees

实际响应(Thymeleaf 渲染后的 HTML):

<!DOCTYPE html>
<html>
<head><title>员工列表</title></head>
<body>
  <h1>飞翔科技员工列表</h1>
  <table>
    <tr><th>ID</th><th>姓名</th><th>部门</th></tr>
    <tr><td>1001</td><td>张伟</td><td>技术部</td></tr>
    <tr><td>1002</td><td>李娜</td><td>市场部</td></tr>
  </table>
</body>
</html>

分析:

  • listAll() 返回 "employee/list"
  • ViewResolver(ThymeleafViewResolver)解析为 classpath:/templates/employee/list.html
  • Model 中的 employees 数据被填充到模板中
  • 最终渲染为完整 HTML 返回给浏览器

HTTP 请求示例 2:返回 ModelAndView

curl -X GET http://localhost:8080/employees/1001/detail

实际响应:

<!DOCTYPE html>
<html>
<head><title>员工详情</title></head>
<body>
  <h1>员工详情</h1>
  <p>ID:1001</p>
  <p>姓名:张伟</p>
  <p>部门:技术部</p>
  <p>职位:高级工程师</p>
</body>
</html>

分析:

  • getDetail() 返回 ModelAndView,同时携带视图名和数据
  • 相比返回 String,ModelAndView 更适合需要显式控制视图和模型的场景
  • 两种方式的最终渲染结果完全一致

易错场景与面试考点

误区一:@Controller 方法返回对象时自动变成 JSON

错误认知:"@Controller 的方法返回 Employee 对象,浏览器会自动看到 JSON。"

纠正:@Controller 的方法返回值默认作为视图名。返回 Employee 对象时,Spring MVC 会尝试把它当作视图名解析,结果通常是 404(找不到名为 com.feixiang.Employee 的视图)。

正确做法:

// 方式一:方法级 @ResponseBody
@GetMapping("/{id}")
@ResponseBody
public Employee getById(@PathVariable Long id) {
    return employeeService.findById(id);
}

// 方式二:使用 @RestController(推荐)
@RestController
public class EmployeeController {
    @GetMapping("/{id}")
    public Employee getById(@PathVariable Long id) {
        return employeeService.findById(id);
    }
}

误区二:@Controller 和 @Component 没有区别

错误认知:"@Controller 就是 @Component 换个名字,随便用哪个都一样。"

纠正:虽然 @Controller 元注解包含 @Component,但 Spring MVC 对 @Controller 有额外处理:

  1. RequestMappingHandlerMapping 只扫描 @Controller(或 @RestController)类中的 @RequestMapping 方法
  2. 标注 @Component 的类即使有 @RequestMapping 方法,也不会被注册为请求处理器
  3. @Controller 还参与 Spring MVC 的异常处理和视图解析流程

面试高频:@Controller 和 @RestController 的区别

标准回答:

  • @Controller 是 Spring MVC 的 Web 层组件注解,方法返回值默认作为视图名由 ViewResolver 解析
  • @RestController 是 @Controller + @ResponseBody 的组合注解,所有方法返回值默认通过 HttpMessageConverter 序列化写入响应体
  • 开发传统服务器渲染页面(如 JSP/Thymeleaf)时使用 @Controller
  • 开发 RESTful API(返回 JSON/XML)时使用 @RestController

小结

@Controller 是 Spring MVC 的 Web 层入口注解,它标记的类会被 Spring MVC 识别为请求处理器,其方法返回值默认作为视图名走 ViewResolver 解析流程。它是视图渲染模式的基石,与 @RestController 的数据直写模式形成互补。

本章与全局的关系:本章讲解了 @Controller 的视图渲染模式。下一章"RestController"将讲解 @RestController 的数据直写模式,以及两者的选择策略。

上一页
本章导读:控制器与请求映射
下一页
RestController