Spring Boot 的注解机制极大简化了开发流程,尤其在 Mapper(数据访问层)、Service(业务逻辑层)、Controller(控制层)三层架构中,注解承担着组件标识、依赖注入、功能增强等核心作用。本文聚焦各层高频注解,结合实例详解其用法与避坑指南。
Mapper 层负责与数据库交互,核心依赖 MyBatis 注解与 Spring 扫描注解,无需 XML 配置即可实现数据操作。
标识接口为 MyBatis 的 Mapper 接口,Spring 会自动扫描并生成代理实现类,无需手动配置 Mapper 映射。
// UserMapper.java
import org.apache.ibatis.annotations.Mapper;
import cn.varin.demo.entity.User;
@Mapper // 标识为Mapper接口
public interface UserMapper {
// 根据ID查询用户
User selectById(Long id);
}
单个 Mapper 接口的标识,适用于 Mapper 数量较少的项目。
批量扫描指定包下的所有 Mapper 接口,替代单个 @Mapper 注解,简化配置。
// 启动类 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 接口数量较多的项目,是企业开发的首选配置方式。
为 Mapper 接口方法的参数命名,便于在 SQL 语句(注解式或 XML)中引用参数。
// 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);
}
arg0
/param1
引用,不推荐);#{}
占位符需完全一致。多参数的数据查询、新增、修改操作。
MyBatis 的 SQL 映射注解,直接在接口方法上编写 SQL 语句,替代 XML 配置。
// 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);
}
<script>
标签包裹,配合<if>
<foreach>
等标签;@Options
可配置自增 ID、缓存等属性,新增操作常用。Service 层负责核心业务逻辑,注解主要用于组件标识、事务管理与依赖注入。
标识类为 Spring 管理的 Service 层组件,Spring 会自动扫描并纳入 IOC 容器,便于依赖注入。
// 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);
}
}
@Qualifier("beanName")
指定注入对象。所有业务逻辑实现类的标识,是 Service 层的基础注解。
声明事务管理,Spring 会自动为标注方法添加事务支持,保证数据一致性。
// 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 方法注解无效;需保证数据一致性的业务,如订单创建、转账、支付等。
Controller 层负责接收前端请求、返回响应,注解核心用于请求映射、参数绑定与响应处理。
标识类为 Spring MVC 的控制器组件,处理 HTTP 请求,需配合@ResponseBody
返回数据。
// 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
替代;@ResponseBody
,返回视图名即可。传统 MVC 开发(页面 + 接口混合)或需灵活控制响应类型的场景。
@Controller + @ResponseBody
的组合注解,默认所有方法返回 JSON 格式数据,无需重复加@ResponseBody
。
// 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);
}
}
前后端分离项目的接口开发(主流用法)。
核心请求映射注解,关联 HTTP 请求与控制器方法,可标注在类或方法上。
// 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"
指定请求类型。所有请求映射场景,尤其需要统一路径前缀或自定义请求 / 响应类型时。
@RequestMapping
的简化版注解,直接指定请求方式,无需配置method
属性。
// 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 接口开发,简化请求映射配置(企业首选)。
绑定 HTTP 请求参数(URL 中的?key=value
)到控制器方法的参数。
// 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
时生效;name
或value
指定别名。接收 URL 查询参数(如分页、条件筛选)。
绑定 URL 路径中的动态参数(如`/user/123`中的`123`)到方法参数,支持 RESTful 风格。
// 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 接口中通过路径标识资源(如查询单个用户、单个订单)。
绑定 HTTP 请求体(通常是 JSON 格式)到 Java 实体类或 Map,用于接收复杂参数。
// 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
,否则无法解析;接收复杂参数(如新增用户的完整信息、修改订单的多字段数据)。
解决跨域问题(浏览器的同源策略限制),允许指定域名的请求访问接口。
// 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 三层架构的注解各司其职:
@MapperScan
批量扫描、@Select
等注解简化 SQL 操作为核心;@Service
标识组件,@Transactional
保障事务一致性;@RestController
+@GetMapping
等实现接口映射,@RequestParam
/@RequestBody
处理参数。掌握注解的核心用法与注意事项,能大幅提升开发效率,同时规避事务失效、跨域失败等常见问题。实际开发中需结合业务场景合理选型,遵循 “简化配置、明确层次” 的原则。