首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Spring Boot三层架构核心注解全解析:Mapper_Service_Controller

Spring Boot三层架构核心注解全解析:Mapper_Service_Controller

作者头像
varin
发布2025-09-28 13:15:14
发布2025-09-28 13:15:14
2900
代码可运行
举报
文章被收录于专栏:/root/root
运行总次数:0
代码可运行
引言

Spring Boot 的注解机制极大简化了开发流程,尤其在 Mapper(数据访问层)、Service(业务逻辑层)、Controller(控制层)三层架构中,注解承担着组件标识、依赖注入、功能增强等核心作用。本文聚焦各层高频注解,结合实例详解其用法与避坑指南。

一、Mapper 层:数据访问的注解魔法

Mapper 层负责与数据库交互,核心依赖 MyBatis 注解与 Spring 扫描注解,无需 XML 配置即可实现数据操作。

1. @Mapper
注解解释

标识接口为 MyBatis 的 Mapper 接口,Spring 会自动扫描并生成代理实现类,无需手动配置 Mapper 映射。

代码示例
代码语言:javascript
代码运行次数:0
运行
复制
// UserMapper.java

import org.apache.ibatis.annotations.Mapper;

import cn.varin.demo.entity.User;

@Mapper // 标识为Mapper接口

public interface UserMapper {

      // 根据ID查询用户

      User selectById(Long id);

}
注意点
  • 接口无需实现类,MyBatis 会通过动态代理生成实现;
  • 若接口与 XML 映射文件配合使用,需保证接口全类名与 XML 的 namespace 一致。
应用场景

单个 Mapper 接口的标识,适用于 Mapper 数量较少的项目。

2. @MapperScan
注解解释

批量扫描指定包下的所有 Mapper 接口,替代单个 @Mapper 注解,简化配置。

代码示例
代码语言:javascript
代码运行次数:0
运行
复制
// 启动类 DemoApplication.java

import org.mybatis.spring.annotation.MapperScan;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication

@MapperScan("cn.varin.demo.mapper") // 扫描mapper包下所有接口

public class DemoApplication {

       public static void main(String\[] args) {

               SpringApplication.run(DemoApplication.class, args);

           }

}
注意点
  • 扫描路径需精准(建议到具体包,如cn.varin.demo.mapper),避免扫描冗余类;
  • 若项目包含多模块,可通过@MapperScan({"包1","包2"})扫描多个包。
应用场景

Mapper 接口数量较多的项目,是企业开发的首选配置方式。

3. @Param
注解解释

为 Mapper 接口方法的参数命名,便于在 SQL 语句(注解式或 XML)中引用参数。

代码示例
代码语言:javascript
代码运行次数:0
运行
复制
// UserMapper.java

import org.apache.ibatis.annotations.Mapper;

import org.apache.ibatis.annotations.Select;

import cn.varin.demo.entity.User;

@Mapper

public interface UserMapper {

    // 多参数查询,用@Param命名参数

    @Select("SELECT \* FROM user WHERE username = #{name} AND age = #{userAge}")

    User selectByUsernameAndAge(@Param("name") String username, @Param("userAge") Integer age);

}
注意点
  • 当方法参数≥2 个时,必须添加 @Param(MyBatis 3.4.0 + 支持无注解但需用arg0/param1引用,不推荐);
  • 参数名与 SQL 中的#{}占位符需完全一致。
应用场景

多参数的数据查询、新增、修改操作。

4. @Select/@Insert/@Update/@Delete
注解解释

MyBatis 的 SQL 映射注解,直接在接口方法上编写 SQL 语句,替代 XML 配置。

代码示例
代码语言:javascript
代码运行次数:0
运行
复制
// UserMapper.java

import org.apache.ibatis.annotations.\*;

import cn.varin.demo.entity.User;

@Mapper

public interface UserMapper {

    // 查询:根据ID查用户

    @Select("SELECT id, username, age FROM user WHERE id = #{id}")

    User selectById(Long id);

    // 新增:插入用户并返回自增ID

    @Insert("INSERT INTO user(username, age) VALUES(#{username}, #{age})")

    @Options(useGeneratedKeys = true, keyProperty = "id") // 启用自增ID,映射到实体的id字段

    int insert(User user);

    // 修改:更新用户年龄

    @Update("UPDATE user SET age = #{age} WHERE id = #{id}")

    int updateAge(@Param("id") Long id, @Param("age") Integer age);

    // 删除:根据ID删用户

    @Delete("DELETE FROM user WHERE id = #{id}")

    int deleteById(Long id);

}
注意点
  • 复杂 SQL(如动态条件、联表查询)建议用<script>标签包裹,配合<if> <foreach>等标签;
  • @Options可配置自增 ID、缓存等属性,新增操作常用。
应用场景
简单 SQL 逻辑(单表 CRUD),无需维护 XML 映射文件的场景。

二、Service 层:业务逻辑的注解支撑

Service 层负责核心业务逻辑,注解主要用于组件标识、事务管理与依赖注入。

1. @Service
注解解释

标识类为 Spring 管理的 Service 层组件,Spring 会自动扫描并纳入 IOC 容器,便于依赖注入。

代码示例
代码语言:javascript
代码运行次数:0
运行
复制
// UserServiceImpl.java

import org.springframework.stereotype.Service;

import cn.varin.demo.mapper.UserMapper;

import cn.varin.demo.entity.User;

import javax.annotation.Resource;

@Service // 标识为Service组件

public class UserServiceImpl implements UserService {

    // 注入Mapper(也可用@Autowired)

    @Resource

    private UserMapper userMapper;

    @Override

    public User getUserById(Long id) {

        return userMapper.selectById(id);

    }

}
注意点
  • 类需实现对应 Service 接口(或直接写实现类),遵循 “面向接口编程” 规范;
  • 若同一接口有多个实现类,需配合@Qualifier("beanName")指定注入对象。
应用场景

所有业务逻辑实现类的标识,是 Service 层的基础注解。

2. @Transactional
注解解释

声明事务管理,Spring 会自动为标注方法添加事务支持,保证数据一致性。

代码示例
代码语言:javascript
代码运行次数:0
运行
复制
// OrderServiceImpl.java

import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;

import cn.varin.demo.mapper.OrderMapper;

import cn.varin.demo.mapper.UserMapper;

import javax.annotation.Resource;

@Service

public class OrderServiceImpl implements OrderService {

    @Resource

    private OrderMapper orderMapper;

    @Resource

    private UserMapper userMapper;

    // 声明事务:创建订单+扣减余额,要么全成功要么全失败

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)

    @Override

    public void createOrder(Long userId, String orderNo) {

        // 1. 创建订单

        orderMapper.insertOrder(orderNo, userId);

        // 2. 扣减用户余额(模拟异常场景)

        userMapper.reduceBalance(userId, 100);

        // 若此处抛出异常,事务会回滚,订单与余额操作均失效

    }

}
注意点
  • 传播行为:默认REQUIRED(无事务则新建,有则加入),根据业务选SUPPORTS REQUIRES_NEW等;
  • 回滚策略:默认仅回滚RuntimeException,需显式配置rollbackFor = Exception.class覆盖所有异常;
  • 事务仅对**<font style="color:#DF2A3F;">public</font>**方法生效,非 public 方法注解无效;
  • 避免 “自调用”(同一类中方法调用),会导致事务失效(需通过 Spring 代理调用)。
应用场景

需保证数据一致性的业务,如订单创建、转账、支付等。

三、Controller 层:请求响应的注解管控

Controller 层负责接收前端请求、返回响应,注解核心用于请求映射、参数绑定与响应处理。

1. @Controller
注解解释

标识类为 Spring MVC 的控制器组件,处理 HTTP 请求,需配合@ResponseBody返回数据。

代码示例
代码语言:javascript
代码运行次数:0
运行
复制
// UserController.java

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.ResponseBody;

import cn.varin.demo.service.UserService;

import cn.varin.demo.entity.User;

import javax.annotation.Resource;

@Controller // 标识为控制器

public class UserController {

    @Resource

    private UserService userService;

    // 配合@ResponseBody返回JSON数据

    @GetMapping("/user/{id}")

    @ResponseBody

    public User getUserById(Long id) {

        return userService.getUserById(id);

    }

}
注意点
  • 纯接口开发(前后端分离)中,@Controller + @ResponseBody可被@RestController替代;
  • 若用于页面跳转(如 JSP),无需加@ResponseBody,返回视图名即可。
应用场景

传统 MVC 开发(页面 + 接口混合)或需灵活控制响应类型的场景。

2. @RestController
注解解释

@Controller + @ResponseBody的组合注解,默认所有方法返回 JSON 格式数据,无需重复加@ResponseBody

代码示例
代码语言:javascript
代码运行次数:0
运行
复制
// UserController.java

import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.bind.annotation.GetMapping;

import cn.varin.demo.service.UserService;

import cn.varin.demo.entity.User;

import javax.annotation.Resource;

@RestController // 替代@Controller + @ResponseBody

@RequestMapping("/api/user") // 类级请求路径

public class UserController {

    @Resource

    private UserService userService;

    // 方法级请求路径:/api/user/{id}

    @GetMapping("/{id}")

    public User getUserById(Long id) {

        return userService.getUserById(id);

    }

}
注意点
  • 无法用于页面跳转,仅适用于接口开发;
  • 返回数据默认用 Jackson 序列化,可通过配置修改日期格式等序列化规则。
应用场景

前后端分离项目的接口开发(主流用法)。

3. @RequestMapping
注解解释

核心请求映射注解,关联 HTTP 请求与控制器方法,可标注在类或方法上。

代码示例
代码语言:javascript
代码运行次数:0
运行
复制
// OrderController.java

import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RequestMethod;

@RestController

// 类级映射:所有方法路径前缀为/api/order

@RequestMapping("/api/order")

public class OrderController {

    // 方法级映射:处理GET请求,完整路径为/api/order/list

    @RequestMapping(value = "/list", method = RequestMethod.GET)

    public String getOrderList() {

        return "order1,order2,order3";

    }

    // 处理POST请求,完整路径为/api/order/create

    @RequestMapping(value = "/create", method = RequestMethod.POST)

    public String createOrder() {

        return "order created success";

    }

}
注意点
  • 类级注解用于统一路径前缀,方法级注解细化具体路径;
  • method属性指定请求方式(GET/POST/PUT/DELETE),不指定则支持所有方式;
  • 可通过produces = "application/json"指定响应类型,consumes = "application/json"指定请求类型。
应用场景

所有请求映射场景,尤其需要统一路径前缀或自定义请求 / 响应类型时。

4. @GetMapping/@PostMapping/@PutMapping/@DeleteMapping
注解解释

@RequestMapping的简化版注解,直接指定请求方式,无需配置method属性。

代码示例
代码语言:javascript
代码运行次数:0
运行
复制
// OrderController.java

import org.springframework.web.bind.annotation.\*;

@RestController

@RequestMapping("/api/order")

public class OrderController {

    // 替代@RequestMapping(method = RequestMethod.GET)

    @GetMapping("/list")

    public String getOrderList() {

        return "order list";

    }

    // 替代@RequestMapping(method = RequestMethod.POST)

    @PostMapping("/create")

    public String createOrder() {

        return "create success";

    }

    // 替代@RequestMapping(method = RequestMethod.PUT)

    @PutMapping("/update")

    public String updateOrder() {

        return "update success";

    }

    // 替代@RequestMapping(method = RequestMethod.DELETE)

    @DeleteMapping("/delete/{id}")

    public String deleteOrder() {

        return "delete success";

    }

}
注意点
  • 功能与@RequestMapping一致,仅简化了请求方式配置;
  • 遵循 RESTful 风格,GET 查、POST 增、PUT 改、DELETE 删。
应用场景

RESTful 接口开发,简化请求映射配置(企业首选)。

5. @RequestParam
注解解释

绑定 HTTP 请求参数(URL 中的?key=value)到控制器方法的参数。

代码示例
代码语言:javascript
代码运行次数:0
运行
复制
// UserController.java

import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestParam;

@RestController

public class UserController {

    // 基础用法:绑定username参数

    @GetMapping("/user/query")

    public String queryUser(@RequestParam String username) {

        return "query user: " + username;

    }

    // 完整配置:必填性+默认值+别名

    @GetMapping("/user/page")

    public String getUserPage(

        @RequestParam(required = true, name = "pageNum") Integer page, // 必传,别名pageNum

        @RequestParam(defaultValue = "10") Integer pageSize) { // 非必传,默认10条/页

        return "page: " + page + ", pageSize: " + pageSize;

    }

}
注意点
  • required默认true(参数必传),缺失会抛 400 异常;
  • defaultValue仅在required = false时生效;
  • 参数名与请求参数名不一致时,用namevalue指定别名。
应用场景

接收 URL 查询参数(如分页、条件筛选)。

6. @PathVariable
注解解释

绑定 URL 路径中的动态参数(如`/user/123`中的`123`)到方法参数,支持 RESTful 风格。

代码示例
代码语言:javascript
代码运行次数:0
运行
复制
// UserController.java

import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PathVariable;

@RestController

public class UserController {

    // 单个路径参数:/user/123 → id=123

    @GetMapping("/user/{id}")

    public String getUserById(@PathVariable Long id) {

        return "user id: " + id;

    }

    // 多个路径参数:/user/123/order/456 → userId=123, orderId=456

    @GetMapping("/user/{userId}/order/{orderId}")

    public String getUserOrder(

        @PathVariable("userId") Long uid, // 别名绑定

        @PathVariable Long orderId) {

        return "user " + uid + ", order " + orderId;

    }

}
注意点
  • 路径中的{参数名}需与@PathVariable的参数名(或别名)一致;
  • 路径参数不可缺失,否则请求无法匹配(如/user/会 404)。
应用场景

RESTful 接口中通过路径标识资源(如查询单个用户、单个订单)。

7. @RequestBody
注解解释

绑定 HTTP 请求体(通常是 JSON 格式)到 Java 实体类或 Map,用于接收复杂参数。

代码示例
代码语言:javascript
代码运行次数:0
运行
复制
// UserController.java

import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestBody;

import cn.varin.demo.entity.User;

@RestController

public class UserController {

    // 接收JSON请求体,转换为User实体

    @PostMapping("/user/add")

    public String addUser(@RequestBody User user) {

        return "add user: " + user.getUsername() + ", age: " + user.getAge();

    }

    // 接收JSON请求体,转换为Map(无需实体类场景)

    @PostMapping("/user/update")

    public String updateUser(@RequestBody Map\<String, Object> userMap) {

        return "update user id: " + userMap.get("id");

    }

}
注意点
  • 前端请求需设置Content-Type: application/json,否则无法解析;
  • 实体类属性需与 JSON 键名一致(支持驼峰与下划线转换,需配置);
  • 不可用于 GET 请求(GET 无请求体),仅支持 POST/PUT 等有请求体的方法。
应用场景

接收复杂参数(如新增用户的完整信息、修改订单的多字段数据)。

8. @CrossOrigin
注解解释

解决跨域问题(浏览器的同源策略限制),允许指定域名的请求访问接口。

代码示例
代码语言:javascript
代码运行次数:0
运行
复制
// UserController.java

import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.CrossOrigin;

// 类级跨域:允许所有域名访问该控制器的所有接口

@RestController

@CrossOrigin

public class UserController {

    // 方法级跨域:仅允许http://localhost:8080访问该接口

    @GetMapping("/user/list")

    @CrossOrigin(origins = "http://localhost:8080")

    public String getUserList() {

        return "user list";

    }

}
注意点
  • 类级注解作用于所有方法,方法级注解优先级更高;
  • origins = "*"允许所有域名(生产环境不推荐,存在安全风险);
  • 可配置maxAge(预检请求缓存时间)、methods(允许的请求方式)等属性。
应用场景

前后端分离项目(前端部署在不同域名 / 端口,如前端8080、后端8081)。

总结

Spring Boot 三层架构的注解各司其职:

  • Mapper 层:以@MapperScan批量扫描、@Select等注解简化 SQL 操作为核心;
  • Service 层@Service标识组件,@Transactional保障事务一致性;
  • Controller 层@RestController+@GetMapping等实现接口映射,@RequestParam/@RequestBody处理参数。

掌握注解的核心用法与注意事项,能大幅提升开发效率,同时规避事务失效、跨域失败等常见问题。实际开发中需结合业务场景合理选型,遵循 “简化配置、明确层次” 的原则。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-09-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 一、Mapper 层:数据访问的注解魔法
    • 1. @Mapper
      • 注解解释
      • 代码示例
      • 注意点
      • 应用场景
    • 2. @MapperScan
      • 注解解释
      • 代码示例
      • 注意点
      • 应用场景
    • 3. @Param
      • 注解解释
      • 代码示例
      • 注意点
      • 应用场景
    • 4. @Select/@Insert/@Update/@Delete
      • 注解解释
      • 代码示例
      • 注意点
      • 应用场景
      • 简单 SQL 逻辑(单表 CRUD),无需维护 XML 映射文件的场景。
  • 二、Service 层:业务逻辑的注解支撑
    • 1. @Service
      • 注解解释
      • 代码示例
      • 注意点
      • 应用场景
    • 2. @Transactional
      • 注解解释
      • 代码示例
      • 注意点
      • 应用场景
  • 三、Controller 层:请求响应的注解管控
    • 1. @Controller
      • 注解解释
      • 代码示例
      • 注意点
      • 应用场景
    • 2. @RestController
      • 注解解释
      • 代码示例
      • 注意点
      • 应用场景
    • 3. @RequestMapping
      • 注解解释
      • 代码示例
      • 注意点
      • 应用场景
    • 4. @GetMapping/@PostMapping/@PutMapping/@DeleteMapping
      • 注解解释
      • 代码示例
      • 注意点
      • 应用场景
    • 5. @RequestParam
      • 注解解释
      • 代码示例
      • 注意点
      • 应用场景
    • 6. @PathVariable
      • 注解解释
      • 代码示例
      • 注意点
      • 应用场景
    • 7. @RequestBody
      • 注解解释
      • 代码示例
      • 注意点
      • 应用场景
    • 8. @CrossOrigin
      • 注解解释
      • 代码示例
      • 注意点
      • 应用场景
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档