目录

一、先回顾 Servlet 的问题

Servlet 的代码

问题清单

二、Controller 是什么

一句话定义

Controller 在哪里

Controller vs Servlet

三、Controller 怎么解决问题

对比一下

Controller 帮你做了什么

四、Spring MVC 如何封装 Servlet

封装层次

具体封装了什么

注解对应关系

五、核心注解详解

1. @RestController

2. @RequestMapping

3. @PostMapping / @GetMapping

4. @RequestBody

5. @PathVariable

6. @RequestParam

六、完整示例

用户注册接口

对应的 Service

七、总结

Controller 解决的问题

一句话总结


Controller 是 Spring MVC 对 Servlet 的封装,让开发者不用手动处理 HTTP 请求,专注于业务逻辑。


一、先回顾 Servlet 的问题

Servlet 的代码

@WebServlet("/api/user/register")
public class UserServlet extends HttpServlet {
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        // 1. 手动获取请求体
        BufferedReader reader = req.getReader();
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        String json = sb.toString();
        
        // 2. 手动解析 JSON
        JSONObject jsonObject = JSON.parseObject(json);
        String account = jsonObject.getString("account");
        String username = jsonObject.getString("username");
        String password = jsonObject.getString("password");
        
        // 3. 手动创建对象
        User user = new User();
        user.setAccount(account);
        user.setUsername(username);
        user.setPassword(password);
        
        // 4. 手动调用 Service
        UserService userService = new UserService();
        userService.register(user);
        
        // 5. 手动返回响应
        resp.setContentType("application/json");
        resp.getWriter().println("{\"code\":200,\"msg\":\"注册成功\"}");
    }
}

问题清单

问题 描述
手动获取参数 req.getParameter("account")
手动解析 JSON JSON.parseObject(json)
手动返回响应 resp.getWriter().println(...)
代码繁琐 每个接口都要写大量重复代码

二、Controller 是什么

一句话定义

Controller 是 Spring MVC 对 Servlet 的封装,用于接收 HTTP 请求并返回响应。

Controller 在哪里

前端请求
    ↓
Controller(接收请求,返回响应)
    ↓
Service(业务逻辑)
    ↓
Mapper(数据库操作)
    ↓
数据库

Controller vs Servlet

对比项 Servlet Controller
技术 Java Web 原生技术 Spring MVC 封装
获取参数 req.getParameter() @RequestParam@RequestBody
返回响应 resp.getWriter() @ResponseBody
路由映射 @WebServlet @RequestMapping
使用场景 底层技术 实际开发推荐

三、Controller 怎么解决问题

对比一下

Servlet(手动)

@WebServlet("/api/user/register")
public class UserServlet extends HttpServlet {
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            throws ServletException, IOException {
        // 手动获取参数
        String account = req.getParameter("account");
        String password = req.getParameter("password");
        
        // 手动调用 Service
        UserService userService = new UserService();
        userService.register(account, password);
        
        // 手动返回响应
        resp.setContentType("application/json");
        resp.getWriter().println("{\"code\":200}");
    }
}

Controller(自动)

@RestController
@RequestMapping("/api/user")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @PostMapping("/register")
    public Result register(@RequestBody RegisterDTO dto) {
        // 自动获取参数(通过 @RequestBody)
        // 自动调用 Service
        // 自动返回响应(通过 @ResponseBody)
        return userService.register(dto);
    }
}

Controller 帮你做了什么

功能 Servlet(手动) Controller(自动)
获取请求参数 req.getParameter() @RequestParam@RequestBody
获取路径参数 req.getPathInfo() @PathVariable
获取请求头 req.getHeader() @RequestHeader
返回响应 resp.getWriter() @ResponseBody
返回 JSON 手动拼接字符串 自动转换(Jackson)
路由映射 @WebServlet @RequestMapping

四、Spring MVC 如何封装 Servlet

封装层次

Servlet(底层)
    ↓
Spring MVC 封装
    ↓
Controller(你用的)

具体封装了什么

Servlet(底层) Controller(封装后)
HttpServletRequest req @RequestBody RegisterDTO dto
req.getParameter("account") dto.getAccount()
resp.getWriter().println(...) return Result.success()
手动解析请求参数 自动解析(通过注解)
手动返回响应 自动返回(通过 @ResponseBody)

注解对应关系

Servlet Controller 作用
@WebServlet("/api/user") @RequestMapping("/api/user") 路径映射
doPost() @PostMapping 处理 POST 请求
doGet() @GetMapping 处理 GET 请求
req.getParameter() @RequestParam 获取查询参数
req.getReader() @RequestBody 获取请求体
resp.getWriter() @ResponseBody 返回响应

五、核心注解详解

1. @RestController

标记这是一个 Controller,自动返回 JSON:

@RestController  // 等价于 @Controller + @ResponseBody
public class UserController {
    // ...
}

2. @RequestMapping

定义路径前缀:

@RestController
@RequestMapping("/api/user")  // 路径前缀
public class UserController {
    // 所有接口路径都以 /api/user 开头
}

3. @PostMapping / @GetMapping

处理不同类型的请求:

@PostMapping("/register")  // 处理 POST /api/user/register
public Result register(@RequestBody RegisterDTO dto) {
    // ...
}

@GetMapping("/{id}")  // 处理 GET /api/user/{id}
public Result getUser(@PathVariable Long id) {
    // ...
}

4. @RequestBody

自动把 JSON 请求体转换成 Java 对象:

@PostMapping("/register")
public Result register(@RequestBody RegisterDTO dto) {
    // dto 已经自动填充好了
    System.out.println(dto.getAccount());    // zhangsan
    System.out.println(dto.getUsername());   // 张三
}

5. @PathVariable

获取路径参数:

@GetMapping("/{id}")
public Result getUser(@PathVariable Long id) {
    // id = 路径中的值
    // 例如:GET /api/user/123 → id = 123
}

6. @RequestParam

获取查询参数:

@GetMapping("/list")
public Result list(@RequestParam String name, @RequestParam Integer page) {
    // GET /api/user/list?name=张三&page=1
    // name = "张三", page = 1
}

六、完整示例

用户注册接口

@RestController
@RequestMapping("/api/user")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    /**
     * 用户注册
     * POST /api/user/register
     */
    @PostMapping("/register")
    public Result register(@Valid @RequestBody RegisterDTO dto) {
        return userService.register(dto);
    }
    
    /**
     * 用户登录
     * POST /api/user/login
     */
    @PostMapping("/login")
    public Result login(@Valid @RequestBody LoginDTO dto) {
        return userService.login(dto);
    }
    
    /**
     * 查询用户信息
     * GET /api/user/{id}
     */
    @GetMapping("/{id}")
    public Result getUser(@PathVariable Long id) {
        return userService.getUser(id);
    }
    
    /**
     * 更新用户信息
     * PUT /api/user
     */
    @PutMapping
    public Result updateUser(
            @RequestHeader("Authorization") String token,
            @RequestBody UpdateUserDTO dto) {
        Long userId = getUserIdFromToken(token);
        return userService.updateUser(userId, dto);
    }
}

对应的 Service

@Service
public class UserServiceImpl implements UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    @Override
    public Result register(RegisterDTO dto) {
        // 1. 检查账号是否已存在
        User existing = userMapper.findByAccount(dto.getAccount());
        if (existing != null) {
            return Result.error(400, "账号已存在");
        }
        
        // 2. 创建用户
        User user = new User();
        user.setAccount(dto.getAccount());
        user.setUsername(dto.getUsername());
        user.setPassword(encrypt(dto.getPassword()));
        
        // 3. 保存到数据库
        userMapper.insert(user);
        
        return Result.success("注册成功");
    }
}

七、总结

Controller 解决的问题

问题 Servlet Controller
获取参数 手动 自动(注解)
解析 JSON 手动 自动(@RequestBody)
返回响应 手动 自动(@ResponseBody)
路由映射 @WebServlet @RequestMapping

一句话总结

Controller 是 Spring MVC 对 Servlet 的封装,它自动处理 HTTP 请求解析和响应构建,让开发者专注于业务逻辑。


参考资料

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐