常见springboot相关注解
Spring 注解大全
本文档详细介绍了 Spring 框架中常用的核心注解,帮助开发者更好地理解和使用这些注解。Spring 注解极大地简化了配置,提高了开发效率,是现代 Spring 应用开发的基础。
1. @Controller
@Controller 是 Spring Framework 中用于标记Web 控制器的核心注解,属于 Spring MVC 的核心组件。它用于定义一个类作为处理 HTTP 请求的入口点,负责接收请求、调用业务逻辑并返回视图或数据。
核心作用
- 请求映射:通过 @RequestMapping 或其派生注解(如 @GetMapping、@PostMapping)将 HTTP 请求映射到控制器的方法。
- 视图解析:返回字符串时,Spring 会使用视图解析器(如 Thymeleaf、JSP)将其转换为实际的视图(如 HTML 页面)。
- 数据绑定:自动将请求参数、表单数据或路径变量绑定到方法参数(结合 @RequestParam、@PathVariable 等注解)。
基础用法示例
场景 1:返回视图
@Controller
@RequestMapping("/users")
public class UserController {// 处理 GET /users/profile?name=John@GetMapping("/profile")public String getProfile(@RequestParam String name, Model model) {model.addAttribute("userName", name); // 将数据传递给视图return "userProfile"; // 对应视图解析器配置的模板(如 userProfile.html)}
}
场景 2:返回 JSON 数据(需配合 @ResponseBody)
@Controller
@RequestMapping("/api")
public class ApiController {// 返回 JSON 数据(需要手动添加 @ResponseBody)@GetMapping("/data")@ResponseBodypublic User getData() {return new User("Alice", 30); // 自动转换为 JSON}
}
@Controller vs @RestController
-
@Controller:
- 传统 MVC 控制器,默认返回视图名称。若需返回 JSON/XML 等数据,需在方法上添加 @ResponseBody。
-
@RestController:
- @Controller + @ResponseBody 的组合注解,所有方法默认返回数据而非视图(自动序列化为 JSON/XML)。
@RestController
@RequestMapping("/api")
public class UserRestController {@GetMapping("/user")public User getUser() {return new User("Bob", 25); // 自动返回 JSON}
}
关键注解配合使用
注解 | 作用 | 示例 |
---|---|---|
@RequestMapping | 类/方法级请求映射 | @RequestMapping(“/home”) |
@GetMapping | 快捷注解(GET 请求) | @GetMapping(“/list”) |
@PostMapping | 快捷注解(POST 请求) | @PostMapping(“/save”) |
@PathVariable | 绑定 URI 模板变量 | @GetMapping(“/users/{id}”) public User getUser(@PathVariable Long id) |
@RequestParam | 绑定请求参数 | @RequestParam String name |
@RequestBody | 绑定请求体数据(JSON/XML) | public void saveUser(@RequestBody User user) |
@ModelAttribute | 绑定表单数据到对象 | public String handleForm(@ModelAttribute User user) |
高级特性
视图解析器配置
在 Spring Boot 中,默认集成 Thymeleaf 或 FreeMarker,通过 application.properties 配置:
spring.mvc.view.prefix=/WEB-INF/views/ # 视图模板前缀
spring.mvc.view.suffix=.html # 视图模板后缀
会话管理
@SessionAttributes:在控制器类上声明需要存储到会话中的模型属性。
@Controller
@SessionAttributes("user") // 将 "user" 属性存储到会话中
public class SessionController {@GetMapping("/set")public String setSession(Model model) {model.addAttribute("user", new User("Alice"));return "sessionPage";}
}
异常处理
@ExceptionHandler:在控制器内处理局部异常。
@Controller
public class ErrorController {@ExceptionHandler(Exception.class)public String handleException() {return "errorPage"; // 异常时返回错误页面}
}
最佳实践
-
明确职责分离:
- 控制器负责接收请求和调用服务层,业务逻辑应放在 Service 层。
- 避免在控制器中编写复杂逻辑。
-
合理使用注解:
- RESTful API 优先使用 @RestController。
- 传统 Web 应用使用 @Controller + 视图解析器。
-
参数校验:
- 结合 @Valid 和 BindingResult 进行请求参数校验。
@PostMapping("/save")
public String saveUser(@Valid @ModelAttribute User user, BindingResult result) {if (result.hasErrors()) {return "formPage"; // 校验失败返回表单}// 保存用户...
}
- 静态资源处理:
- 确保静态资源(如 CSS、JS)路径不被控制器拦截,通过 WebMvcConfigurer 配置。
完整示例代码
@Controller
@RequestMapping("/products")
public class ProductController {// 返回视图(需配置视图解析器)@GetMapping("/list")public String listProducts(Model model) {model.addAttribute("products", productService.getAll());return "products/list"; // 对应 /templates/products/list.html}// 返回 JSON 数据@GetMapping("/{id}")@ResponseBodypublic Product getProduct(@PathVariable Long id) {return productService.getById(id);}// 处理表单提交@PostMapping("/save")public String saveProduct(@Valid @ModelAttribute Product product, BindingResult result) {if (result.hasErrors()) {return "products/form";}productService.save(product);return "redirect:/products/list";}
}
通过合理使用 @Controller 及其相关注解,可以构建出结构清晰、职责分明的 Web 应用,同时兼顾传统 MVC 和 RESTful API 的开发需求。
2. @RestController
@RestController 是 Spring 4.0 引入的组合注解,等价于 @Controller + @ResponseBody。它是构建 RESTful Web 服务的核心注解,专门用于创建 REST API。
核心作用
- 简化 REST API 开发:无需在每个方法上添加 @ResponseBody
- 自动序列化:方法返回值自动序列化为 JSON/XML 格式
- 前后端分离支持:适用于前后端分离架构的后端 API 开发
基本用法
简单 REST 控制器
@RestController
@RequestMapping("/api/users")
public class UserRestController {@GetMappingpublic List<User> getUsers() {return userService.getAllUsers();}@GetMapping("/{id}")public User getUser(@PathVariable Long id) {return userService.getUserById(id);}@PostMappingpublic User createUser(@RequestBody User user) {return userService.createUser(user);}@PutMapping("/{id}")public User updateUser(@PathVariable Long id, @RequestBody User user) {return userService.updateUser(id, user);}@DeleteMapping("/{id}")public void deleteUser(@PathVariable Long id) {userService.deleteUser(id);}
}
与其他注解配合使用
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://localhost:3000") // 支持跨域
public class UserRestController {@GetMapping("/user")public User getUser() {return new User("Bob", 25); // 自动返回 JSON}// 特定方法覆盖类级别的映射@GetMapping("/admin/user")@CrossOrigin(origins = "http://admin.example.com")public User getAdminUser() {return new User("Admin", 30);}
}
特点
- 组合注解特性:@RestController = @Controller + @ResponseBody
- 默认返回数据:所有方法默认返回数据而非视图
- 自动序列化:方法返回值会自动序列化为 JSON/XML
- 适用于 RESTful API:专门为 RESTful Web 服务设计
- 减少样板代码:无需在每个方法上添加 @ResponseBody
高级用法示例
1. 自定义响应格式
// 统一响应结果类
public class Result<T> {private int code;private String message;private T data;// 构造方法、getter 和 setter...public static <T> Result<T> success(T data) {Result<T> result = new Result<>();result.setCode(200);result.setMessage("success");result.setData(data);return result;}
}@RestController
@RequestMapping("/api/users")
public class UserRestController {@GetMappingpublic Result<List<User>> getUsers() {List<User> users = userService.getAllUsers();return Result.success(users);}@GetMapping("/{id}")public Result<User> getUser(@PathVariable Long id) {User user = userService.getUserById(id);return Result.success(user);}
}
2. 异常处理
@RestController
@RequestMapping("/api/users")
public class UserRestController {@GetMapping("/{id}")public User getUser(@PathVariable Long id) {User user = userService.getUserById(id);if (user == null) {throw new UserNotFoundException("User not found with id: " + id);}return user;}
}// 全局异常处理器
@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(UserNotFoundException.class)public ResponseEntity<Result<String>> handleUserNotFound(UserNotFoundException e) {Result<String> result = new Result<>();result.setCode(404);result.setMessage(e.getMessage());return ResponseEntity.status(404).body(result);}
}
最佳实践
-
专门用于 API 开发:@RestController 专门用于构建 RESTful API,不适用于需要返回视图的场景。
-
合理组织 URL 结构:使用 @RequestMapping 在类级别定义基础路径,方法级别定义具体操作。
-
统一响应格式:建议使用统一的响应格式,方便前端处理。
-
配合异常处理:结合 @RestControllerAdvice 进行全局异常处理,提供一致的错误响应。
-
启用 CORS:对于前后端分离的应用,合理配置跨域支持。
// 推荐的 RESTful 控制器结构
@RestController
@RequestMapping("/api/v1/users")
@CrossOrigin
public class UserRestController {@Autowiredprivate UserService userService;@GetMappingpublic ResponseEntity<List<User>> getAllUsers() {List<User> users = userService.findAll();return ResponseEntity.ok(users);}@GetMapping("/{id}")public ResponseEntity<User> getUserById(@PathVariable Long id) {return userService.findById(id).map(ResponseEntity::ok).orElse(ResponseEntity.notFound().build());}@PostMappingpublic ResponseEntity<User> createUser(@Valid @RequestBody User user) {User savedUser = userService.save(user);return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);}@PutMapping("/{id}")public ResponseEntity<User> updateUser(@PathVariable Long id, @Valid @RequestBody User user) {return userService.update(id, user).map(ResponseEntity::ok).orElse(ResponseEntity.notFound().build());}@DeleteMapping("/{id}")public ResponseEntity<Void> deleteUser(@PathVariable Long id) {userService.deleteById(id);return ResponseEntity.noContent().build();}
}
通过合理使用 @RestController 注解,可以快速构建符合 RESTful 设计规范的 Web API,满足现代 Web 应用的开发需求。
3. @RequestMapping
@RequestMapping 是 Spring MVC 中最基础和重要的注解之一,用于将 Web 请求映射到具体的处理方法上。它可以应用在类级别或方法级别,提供灵活的请求映射配置。
核心作用
- URL 映射:将特定 URL 路径的请求映射到处理方法
- HTTP 方法限定:指定处理的 HTTP 请求方法(GET、POST、PUT、DELETE 等)
- 请求条件匹配:基于请求参数、请求头等条件进行匹配
- 内容类型控制:指定可处理的请求内容类型和返回的内容类型
基本用法
类级别使用
@Controller
@RequestMapping("/users")
public class UserController {// 实际映射路径为 /users@RequestMapping("")public String getUsers() {return "userList";}// 实际映射路径为 /users/create@RequestMapping("/create")public String createUserForm() {return "userCreateForm";}// 实际映射路径为 /users@RequestMapping(method = RequestMethod.POST)public String createUser() {// 创建用户逻辑return "userCreated";}
}
方法级别使用
@Controller
public class UserController {@RequestMapping("/users")public String getUsers() {return "userList";}@RequestMapping(value = "/users", method = RequestMethod.POST)public String createUser() {// 创建用户逻辑return "userCreated";}@RequestMapping(value = "/users/{id}", method = RequestMethod.GET)public String getUser(@PathVariable Long id) {// 获取用户逻辑return "userDetail";}
}
主要属性
属性 | 类型 | 说明 |
---|---|---|
value/path | String[] | 指定请求的 URL 路径,支持 Ant 风格模式(如 /users/*、/users/**) |
method | RequestMethod[] | 指定请求的方法类型(GET、POST、PUT、DELETE、PATCH 等) |
params | String[] | 指定请求参数条件(如 “version=1”、“!version”) |
headers | String[] | 指定请求头条件(如 “Accept=text/plain”) |
consumes | String[] | 指定处理请求的提交内容类型(Content-Type) |
produces | String[] | 指定返回内容的类型(Accept) |
高级用法示例
1. Ant 风格路径匹配
@Controller
@RequestMapping("/files")
public class FileController {// 匹配 /files/anyfile.txt@RequestMapping("/*.txt")public String getTextFile() {return "textFileView";}// 匹配 /files/path/to/anyfile.json@RequestMapping("/**/*.json")public String getJsonFile() {return "jsonFileView";}// 匹配 /files/abc 或 /files/def 等@RequestMapping("/{fileName:^[a-z]+}")public String getFile(@PathVariable String fileName) {return "fileView";}
}
2. 请求参数和头部条件
@Controller
public class ApiController {// 仅匹配带有 version=2 参数的请求@RequestMapping(value = "/api/data", params = "version=2")public String getDataV2() {return "dataV2";}// 仅匹配 Accept 头部为 application/json 的请求@RequestMapping(value = "/api/data", headers = "Accept=application/json")@ResponseBodypublic String getJsonData() {return "{\"data\":\"json\"}";}// 仅匹配 Content-Type 为 application/json 且 Accept 为 text/html 的请求@RequestMapping(value = "/api/data", consumes = "application/json", produces = "text/html")public String processData() {return "processedData";}
}
3. 多种 HTTP 方法支持
@Controller
@RequestMapping("/api/users")
public class UserController {// 支持 GET 和 POST 方法@RequestMapping(method = {RequestMethod.GET, RequestMethod.POST})public String handleUsers(HttpServletRequest request) {if ("GET".equals(request.getMethod())) {return "userList";} else {return "userCreated";}}// 支持所有 HTTP 方法@RequestMapping("/{id}")public String handleUser(@PathVariable Long id, HttpServletRequest request) {switch (request.getMethod()) {case "GET": return "userDetail";case "PUT": return "userUpdated";case "DELETE": return "userDeleted";default: return "error";}}
}
最佳实践
-
优先使用派生注解:对于简单的 RESTful API,推荐使用 @GetMapping、@PostMapping 等派生注解,使代码更清晰。
-
合理组织类级别和方法级别映射:将通用路径前缀放在类级别,具体操作放在方法级别。
-
避免过于复杂的映射规则:复杂的映射会增加维护难度,应尽量保持简洁。
-
使用 produces 和 consumes 明确内容类型:有助于提高 API 的可读性和正确性。
// 推荐的 RESTful 风格
@RestController
@RequestMapping("/api/users")
public class UserController {@GetMappingpublic List<User> getUsers() {return userService.getAllUsers();}@GetMapping("/{id}")public User getUser(@PathVariable Long id) {return userService.getUserById(id);}@PostMapping(consumes = "application/json")public User createUser(@RequestBody User user) {return userService.createUser(user);}@PutMapping("/{id}")public User updateUser(@PathVariable Long id, @RequestBody User user) {return userService.updateUser(id, user);}@DeleteMapping("/{id}")public void deleteUser(@PathVariable Long id) {userService.deleteUser(id);}
}
通过合理使用 @RequestMapping 注解及其派生注解,可以构建出清晰、规范的 Web API 接口。
4. @RequestParam
@RequestParam 注解用于将 HTTP 请求参数(查询参数或表单参数)绑定到方法参数上。它是处理客户端传递参数的重要注解。
核心作用
- 参数绑定:将请求中的参数值自动绑定到方法参数
- 类型转换:自动将字符串参数转换为相应的 Java 类型
- 参数验证:通过 required 属性控制参数是否必须
- 默认值设置:通过 defaultValue 属性设置参数默认值
基本用法
简单参数绑定
@GetMapping("/users/search")
public String searchUsers(@RequestParam("name") String name, @RequestParam("age") Integer age) {// 处理请求参数// 例如:/users/search?name=Tom&age=25return "userList";
}
可选参数和默认值
@GetMapping("/users")
public String getUsers(@RequestParam(value = "page", defaultValue = "1") Integer page,@RequestParam(value = "size", defaultValue = "10") Integer size,@RequestParam(value = "sort", required = false) String sort) {// page 和 size 参数有默认值,即使不传也会有值// sort 参数是可选的,不传时为 nullreturn "userList";
}
数组和集合参数
@GetMapping("/users/batch")
public String batchDelete(@RequestParam("ids") Long[] ids) {// 处理多个 ID// 例如:/users/batch?ids=1&ids=2&ids=3return "batchDeleted";
}@GetMapping("/users/filter")
public String filterUsers(@RequestParam("tags") List<String> tags) {// 处理标签列表// 例如:/users/filter?tags=VIP&tags=Activereturn "filteredList";
}
主要属性
属性 | 类型 | 说明 |
---|---|---|
value/name | String | 指定要绑定的请求参数名称 |
required | boolean | 是否必须存在该参数,默认为 true |
defaultValue | String | 默认值,当参数不存在时使用(设置后 required 自动为 false) |
高级用法示例
1. 复杂对象参数绑定
// 用户搜索条件类
public class UserSearchCriteria {private String name;private Integer age;private String email;// getter 和 setter 方法...
}@Controller
public class UserController {// 通过 @RequestParam 绑定复杂对象的属性@GetMapping("/users/search")public String searchUsers(@RequestParam(required = false) String name,@RequestParam(required = false) Integer age,@RequestParam(required = false) String email,Model model) {UserSearchCriteria criteria = new UserSearchCriteria();criteria.setName(name);criteria.setAge(age);criteria.setEmail(email);List<User> users = userService.searchUsers(criteria);model.addAttribute("users", users);return "userList";}
}
2. 参数验证
@GetMapping("/users/page")
public String getUsersPaginated(@RequestParam(value = "page", defaultValue = "1") @Min(1) Integer page,@RequestParam(value = "size", defaultValue = "10") @Min(1) @Max(100) Integer size) {// 使用 Bean Validation 进行参数验证// page 必须大于等于 1// size 必须在 1-100 之间return "userList";
}
最佳实践
-
合理使用 defaultValue:对于分页、排序等场景,设置合理的默认值可以提高用户体验。
-
注意 required 属性:设置了 defaultValue 后,required 属性会自动设为 false。
-
类型转换注意事项:确保请求参数能够正确转换为目标类型,避免类型转换异常。
-
处理集合参数:对于需要传递多个同名参数的场景,可以使用数组或集合类型。
// 推荐的参数处理方式
@RestController
@RequestMapping("/api/users")
public class UserController {// 分页查询@GetMappingpublic Page<User> getUsers(@RequestParam(value = "page", defaultValue = "0") int page,@RequestParam(value = "size", defaultValue = "20") int size,@RequestParam(value = "sort", defaultValue = "id") String sort) {return userService.getUsers(PageRequest.of(page, size, Sort.by(sort)));}// 搜索功能@GetMapping("/search")public List<User> searchUsers(@RequestParam(value = "keyword", required = false) String keyword,@RequestParam(value = "department", required = false) String department) {return userService.searchUsers(keyword, department);}
}
通过合理使用 @RequestParam 注解,可以轻松处理各种请求参数场景,使 Web 接口更加灵活和易用。
5. @PathVariable
@PathVariable 注解用于将 URI 模板变量绑定到方法参数上,是 RESTful API 设计中的重要注解。它允许从 URL 路径中提取变量值。
核心作用
- 路径变量提取:从 URL 路径中提取指定的变量值
- RESTful 风格支持:支持 RESTful 风格的 URL 设计
- 类型自动转换:自动将路径变量转换为相应的 Java 类型
- 正则表达式支持:支持使用正则表达式对路径变量进行约束
基本用法
简单路径变量
@GetMapping("/users/{id}")
public String getUser(@PathVariable("id") Long id) {// 处理 /users/123 这样的请求// id 参数值为 123return "userDetail";
}// 当方法参数名与路径变量名一致时,可以省略 value 属性
@GetMapping("/users/{id}")
public String getUser(@PathVariable Long id) {return "userDetail";
}
多个路径变量
// 多个路径变量
@GetMapping("/users/{userId}/orders/{orderId}")
public String getOrder(@PathVariable("userId") Long userId, @PathVariable("orderId") Long orderId) {return "orderDetail";
}// 混合使用路径变量和请求参数
@GetMapping("/users/{userId}/orders")
public String getUserOrders(@PathVariable("userId") Long userId,@RequestParam(value = "status", required = false) String status) {return "orderList";
}
主要属性
属性 | 类型 | 说明 |
---|---|---|
value/name | String | 指定要绑定的路径变量名称 |
required | boolean | 是否必须存在该路径变量,默认为 true |
高级用法示例
1. 正则表达式约束
@RestController
public class FileController {// 限制 id 只能是数字@GetMapping("/files/{id:\\d+}")public String getFile(@PathVariable Long id) {return "fileContent";}// 限制文件名格式@GetMapping("/images/{filename:.+\\.(jpg|png|gif)}")public String getImage(@PathVariable String filename) {return "imageContent";}// 日期格式约束@GetMapping("/events/{date:\\d{4}-\\d{2}-\\d{2}}")public String getEvent(@PathVariable("date") String date) {return "eventDetail";}
}
2. 复杂路径变量处理
@RestController
@RequestMapping("/api")
public class ResourceController {// 处理版本化的 API@GetMapping("/v{version:\\d+}/users/{userId}")public String getUser(@PathVariable Integer version,@PathVariable Long userId) {if (version < 2) {// 返回旧版本数据格式return "userOldFormat";} else {// 返回新版本数据格式return "userNewFormat";}}// 处理多级路径@GetMapping("/categories/{categoryPath:.+}")public String getCategory(@PathVariable String categoryPath) {// categoryPath 可以包含多级路径,如 "electronics/computers/laptops"String[] paths = categoryPath.split("/");return "categoryDetail";}
}
最佳实践
-
路径变量命名规范:使用有意义的变量名,提高代码可读性。
-
类型安全:选择合适的 Java 类型,避免类型转换异常。
-
正则表达式约束:对路径变量使用正则表达式进行约束,提高 API 的健壮性。
-
避免敏感信息:不要在路径变量中传递敏感信息,如密码、密钥等。
// 推荐的 RESTful 风格设计
@RestController
@RequestMapping("/api")
public class UserController {// 获取用户信息@GetMapping("/users/{id}")public User getUser(@PathVariable Long id) {return userService.getUserById(id);}// 获取用户的订单@GetMapping("/users/{userId}/orders")public List<Order> getUserOrders(@PathVariable Long userId) {return orderService.getOrdersByUserId(userId);}// 获取订单详情@GetMapping("/users/{userId}/orders/{orderId}")public Order getOrder(@PathVariable Long userId, @PathVariable Long orderId) {return orderService.getOrder(userId, orderId);}
}
通过合理使用 @PathVariable 注解,可以构建出符合 RESTful 设计规范的 Web API,使 URL 更加直观和易于理解。
6. @GetMapping
@GetMapping 是 Spring 4.3 引入的组合注解,等价于 @RequestMapping(method = RequestMethod.GET)。它是处理 HTTP GET 请求的快捷方式,专门用于数据查询操作。
核心作用
- 简化 GET 请求映射:替代 @RequestMapping(method = RequestMethod.GET)
- 语义明确:明确表示该方法处理 GET 请求
- 提高可读性:使代码更加简洁和易读
基本用法
简单查询操作
@RestController
@RequestMapping("/api/users")
public class UserController {// 查询所有用户@GetMappingpublic List<User> getUsers() {return userService.getAllUsers();}// 根据 ID 查询用户@GetMapping("/{id}")public User getUser(@PathVariable Long id) {return userService.getUserById(id);}// 带查询参数的 GET 请求@GetMapping(params = "name")public List<User> getUsersByName(@RequestParam String name) {return userService.getUsersByName(name);}
}
复杂查询场景
@RestController
@RequestMapping("/api/products")
public class ProductController {// 分页查询@GetMappingpublic Page<Product> getProducts(@RequestParam(defaultValue = "0") int page,@RequestParam(defaultValue = "10") int size,@RequestParam(defaultValue = "name") String sortBy) {return productService.getProducts(PageRequest.of(page, size, Sort.by(sortBy)));}// 条件查询@GetMapping("/search")public List<Product> searchProducts(@RequestParam(required = false) String keyword,@RequestParam(required = false) String category,@RequestParam(required = false) BigDecimal minPrice,@RequestParam(required = false) BigDecimal maxPrice) {return productService.searchProducts(keyword, category, minPrice, maxPrice);}// 查询统计信息@GetMapping("/count")public long getProductCount() {return productService.count();}
}
主要属性
@GetMapping 注解继承了 @RequestMapping 的所有属性:
属性 | 类型 | 说明 |
---|---|---|
value/path | String[] | 指定请求的 URL 路径 |
params | String[] | 指定请求参数条件 |
headers | String[] | 指定请求头条件 |
consumes | String[] | 指定处理请求的提交内容类型 |
produces | String[] | 指定返回内容的类型 |
高级用法示例
1. 条件映射
@RestController
@RequestMapping("/api/data")
public class DataController {// 仅当请求包含 version=2 参数时匹配@GetMapping(params = "version=2")public String getDataV2() {return "data version 2";}// 仅当请求包含 format=json 参数时匹配@GetMapping(params = "format=json", produces = "application/json")@ResponseBodypublic Map<String, Object> getJsonData() {Map<String, Object> data = new HashMap<>();data.put("message", "json data");return data;}// 仅当 Accept 头部为 text/xml 时匹配@GetMapping(produces = "text/xml")public String getXmlData() {return "<data>xml data</data>";}
}
2. 与其他注解配合
@RestController
@RequestMapping("/api/users")
public class UserController {// 结合缓存注解@GetMapping("/{id}")@Cacheable(value = "users", key = "#id")public User getUser(@PathVariable Long id) {return userService.getUserById(id);}// 结合权限控制@GetMapping("/admin")@PreAuthorize("hasRole('ADMIN')")public List<User> getAllUsers() {return userService.getAllUsers();}// 异步处理@GetMapping("/async")public Callable<String> getAsyncData() {return () -> {// 模拟耗时操作Thread.sleep(1000);return "async data";};}
}
最佳实践
-
专门用于查询操作:@GetMapping 专门用于处理查询请求,符合 HTTP 方法语义。
-
幂等性保证:GET 请求应该是幂等的,不应产生副作用。
-
合理使用缓存:对于频繁查询的数据,可以结合缓存机制提高性能。
-
避免敏感信息:不要在 GET 请求的 URL 中传递敏感信息,因为 URL 可能被记录在日志中。
-
参数验证:对于复杂的查询参数,应进行适当的验证。
// 推荐的查询接口设计
@RestController
@RequestMapping("/api/users")
public class UserController {@Autowiredprivate UserService userService;// 基础查询@GetMappingpublic ResponseEntity<Page<User>> getUsers(@RequestParam(defaultValue = "0") @Min(0) int page,@RequestParam(defaultValue = "10") @Min(1) @Max(100) int size) {Page<User> users = userService.findAll(PageRequest.of(page, size));return ResponseEntity.ok(users);}// 条件查询@GetMapping(params = "name")public ResponseEntity<List<User>> getUsersByName(@RequestParam String name,@RequestParam(defaultValue = "false") boolean exact) {List<User> users = exact ? userService.findByName(name) : userService.findByNameContaining(name);return ResponseEntity.ok(users);}// 统计查询@GetMapping("/statistics")public ResponseEntity<Map<String, Object>> getUserStatistics() {Map<String, Object> statistics = userService.getStatistics();return ResponseEntity.ok(statistics);}
}
通过合理使用 @GetMapping 注解,可以构建出语义清晰、易于维护的查询接口,提高 Web API 的质量和可读性。
7. @PostMapping
@PostMapping 是 Spring 4.3 引入的组合注解,等价于 @RequestMapping(method = RequestMethod.POST)。它是处理 HTTP POST 请求的快捷方式,专门用于创建资源和提交数据操作。
核心作用
- 简化 POST 请求映射:替代 @RequestMapping(method = RequestMethod.POST)
- 语义明确:明确表示该方法处理 POST 请求
- 提高可读性:使代码更加简洁和易读
- 资源创建:主要用于创建新资源
基本用法
创建资源
@RestController
@RequestMapping("/api/users")
public class UserController {// 创建新用户@PostMappingpublic ResponseEntity<User> createUser(@RequestBody User user) {User savedUser = userService.save(user);return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);}// 创建用户的订单@PostMapping("/{userId}/orders")public ResponseEntity<Order> createOrder(@PathVariable Long userId, @RequestBody Order order) {Order savedOrder = orderService.createOrder(userId, order);return ResponseEntity.status(HttpStatus.CREATED).body(savedOrder);}
}
表单提交处理
@Controller
@RequestMapping("/users")
public class UserController {// 处理表单提交@PostMapping("/register")public String registerUser(@ModelAttribute User user, BindingResult result) {if (result.hasErrors()) {return "registerForm";}userService.save(user);return "redirect:/users/" + user.getId();}// 文件上传@PostMapping("/upload")public String handleFileUpload(@RequestParam("file") MultipartFile file,RedirectAttributes redirectAttributes) {// 处理文件上传逻辑redirectAttributes.addFlashAttribute("message", "文件上传成功: " + file.getOriginalFilename());return "redirect:/users/status";}
}
主要属性
@PostMapping 注解继承了 @RequestMapping 的所有属性:
属性 | 类型 | 说明 |
---|---|---|
value/path | String[] | 指定请求的 URL 路径 |
params | String[] | 指定请求参数条件 |
headers | String[] | 指定请求头条件 |
consumes | String[] | 指定处理请求的提交内容类型 |
produces | String[] | 指定返回内容的类型 |
高级用法示例
1. 内容类型限定
@RestController
@RequestMapping("/api/data")
public class DataController {// 仅处理 JSON 格式的请求@PostMapping(consumes = "application/json")public ResponseEntity<String> handleJsonData(@RequestBody Map<String, Object> data) {// 处理 JSON 数据return ResponseEntity.ok("JSON data processed");}// 仅处理 XML 格式的请求@PostMapping(consumes = "application/xml", produces = "application/xml")public ResponseEntity<String> handleXmlData(@RequestBody String xmlData) {// 处理 XML 数据String response = "<response>XML data processed</response>";return ResponseEntity.ok(response);}// 仅处理表单数据@PostMapping(consumes = "application/x-www-form-urlencoded")public ResponseEntity<String> handleFormData(@RequestParam Map<String, String> formData) {// 处理表单数据return ResponseEntity.ok("Form data processed");}
}
2. 与其他注解配合
@RestController
@RequestMapping("/api/users")
public class UserController {// 结合验证注解@PostMappingpublic ResponseEntity<User> createUser(@Valid @RequestBody User user, BindingResult result) {if (result.hasErrors()) {return ResponseEntity.badRequest().build();}User savedUser = userService.save(user);return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);}// 结合事务注解@PostMapping("/batch")@Transactionalpublic ResponseEntity<List<User>> createUsers(@RequestBody List<User> users) {List<User> savedUsers = userService.saveAll(users);return ResponseEntity.status(HttpStatus.CREATED).body(savedUsers);}// 结合安全注解@PostMapping("/admin")@PreAuthorize("hasRole('ADMIN')")public ResponseEntity<User> createAdminUser(@RequestBody User user) {user.setRole("ADMIN");User savedUser = userService.save(user);return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);}
}
最佳实践
-
幂等性考虑:POST 请求通常不是幂等的,多次执行会产生不同的结果。
-
返回 201 状态码:创建资源成功时应返回 HTTP 201 (CREATED) 状态码。
-
返回 Location 头部:创建资源后,应在响应中包含 Location 头部,指向新创建的资源。
-
参数验证:对传入的数据进行验证,确保数据的完整性和正确性。
-
事务处理:对于涉及多个操作的复杂创建逻辑,应使用事务确保数据一致性。
// 推荐的资源创建接口设计
@RestController
@RequestMapping("/api/users")
public class UserController {@Autowiredprivate UserService userService;@PostMappingpublic ResponseEntity<User> createUser(@Valid @RequestBody User user, HttpServletRequest request) {// 保存用户User savedUser = userService.save(user);// 构建资源 URIURI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(savedUser.getId()).toUri();// 返回 201 状态码和 Location 头部return ResponseEntity.created(location).body(savedUser);}// 批量创建@PostMapping("/batch")public ResponseEntity<List<User>> createUsers(@Valid @RequestBody List<User> users) {if (users.size() > 100) {return ResponseEntity.badRequest().build();}List<User> savedUsers = userService.saveAll(users);return ResponseEntity.status(HttpStatus.CREATED).body(savedUsers);}
}
通过合理使用 @PostMapping 注解,可以构建出符合 HTTP 语义的资源创建接口,提供良好的 RESTful API 体验。
8. @DeleteMapping
@DeleteMapping 是 Spring 4.3 引入的组合注解,等价于 @RequestMapping(method = RequestMethod.DELETE)。它是处理 HTTP DELETE 请求的快捷方式,专门用于删除资源操作。
核心作用
- 简化 DELETE 请求映射:替代 @RequestMapping(method = RequestMethod.DELETE)
- 语义明确:明确表示该方法处理 DELETE 请求
- 提高可读性:使代码更加简洁和易读
- 资源删除:主要用于删除指定资源
基本用法
删除单个资源
@RestController
@RequestMapping("/api/users")
public class UserController {// 根据 ID 删除用户@DeleteMapping("/{id}")public ResponseEntity<Void> deleteUser(@PathVariable Long id) {userService.deleteById(id);return ResponseEntity.noContent().build();}// 条件删除@DeleteMapping(params = "status")public ResponseEntity<Void> deleteUsersByStatus(@RequestParam String status) {userService.deleteByStatus(status);return ResponseEntity.noContent().build();}
}
批量删除
@RestController
@RequestMapping("/api/users")
public class UserController {// 批量删除用户@DeleteMapping("/batch")public ResponseEntity<Void> deleteUsers(@RequestBody List<Long> ids) {userService.deleteAllById(ids);return ResponseEntity.noContent().build();}// 删除所有用户(谨慎使用)@DeleteMapping@PreAuthorize("hasRole('ADMIN')")public ResponseEntity<Void> deleteAllUsers() {userService.deleteAll();return ResponseEntity.noContent().build();}
}
主要属性
@DeleteMapping 注解继承了 @RequestMapping 的所有属性:
属性 | 类型 | 说明 |
---|---|---|
value/path | String[] | 指定请求的 URL 路径 |
params | String[] | 指定请求参数条件 |
headers | String[] | 指定请求头条件 |
consumes | String[] | 指定处理请求的提交内容类型 |
produces | String[] | 指定返回内容的类型 |
高级用法示例
1. 软删除实现
@RestController
@RequestMapping("/api/users")
public class UserController {// 软删除:标记为已删除而不是物理删除@DeleteMapping("/{id}")public ResponseEntity<Void> softDeleteUser(@PathVariable Long id) {userService.softDelete(id);return ResponseEntity.noContent().build();}// 永久删除@DeleteMapping("/{id}/permanent")@PreAuthorize("hasRole('ADMIN')")public ResponseEntity<Void> permanentDeleteUser(@PathVariable Long id) {userService.permanentDelete(id);return ResponseEntity.noContent().build();}
}
2. 关联删除
@RestController
@RequestMapping("/api/users")
public class UserController {// 删除用户及其关联数据@DeleteMapping("/{id}")@Transactionalpublic ResponseEntity<Void> deleteUserWithRelations(@PathVariable Long id, @RequestParam(defaultValue = "false") boolean cascade) {if (cascade) {// 级联删除关联数据orderService.deleteByUserId(id);userService.deleteById(id);} else {// 检查是否有关联数据if (orderService.existsByUserId(id)) {return ResponseEntity.status(HttpStatus.CONFLICT).build();}userService.deleteById(id);}return ResponseEntity.noContent().build();}
}
最佳实践
-
幂等性:DELETE 请求应该是幂等的,多次删除同一个资源应该返回相同的结果。
-
返回 204 状态码:删除成功时通常返回 HTTP 204 (NO CONTENT) 状态码。
-
安全性考虑:删除操作应该谨慎处理,特别是批量删除和删除所有数据的操作。
-
权限控制:删除敏感资源时应进行权限验证。
-
软删除:对于重要数据,建议使用软删除而不是物理删除。
// 推荐的删除接口设计
@RestController
@RequestMapping("/api/users")
public class UserController {@Autowiredprivate UserService userService;@DeleteMapping("/{id}")public ResponseEntity<Void> deleteUser(@PathVariable Long id, Authentication authentication) {// 检查资源是否存在if (!userService.existsById(id)) {return ResponseEntity.notFound().build();}// 检查权限if (!userService.canDelete(id, authentication)) {return ResponseEntity.status(HttpStatus.FORBIDDEN).build();}// 执行删除userService.deleteById(id);// 返回 204 状态码return ResponseEntity.noContent().build();}// 批量删除@DeleteMapping("/batch")public ResponseEntity<Map<String, Object>> deleteUsers(@RequestBody List<Long> ids) {Map<String, Object> result = new HashMap<>();try {int deletedCount = userService.deleteAllById(ids);result.put("deletedCount", deletedCount);result.put("totalCount", ids.size());return ResponseEntity.ok(result);} catch (Exception e) {result.put("error", e.getMessage());return ResponseEntity.badRequest().body(result);}}
}
通过合理使用 @DeleteMapping 注解,可以构建出符合 HTTP 语义的资源删除接口,提供安全可靠的删除操作。
9. @ResponseBody
@ResponseBody 是 Spring MVC 中的重要注解,用于指示方法返回值应直接写入 HTTP 响应体中,而不是被视图解析器解析为视图名称。它是构建 RESTful API 的关键注解之一。
核心作用
- 响应体直接输出:将方法返回值直接写入 HTTP 响应体
- 自动序列化:自动将 Java 对象序列化为 JSON、XML 等格式
- 视图解析绕过:跳过视图解析器,直接返回数据
- RESTful 支持:支持构建 RESTful Web 服务
基本用法
在方法上使用
@Controller
@RequestMapping("/api")
public class ApiController {// 返回 JSON 数据@GetMapping("/user")@ResponseBodypublic User getUser() {return new User("Alice", 30); // 自动转换为 JSON}// 返回字符串数据@GetMapping("/message")@ResponseBodypublic String getMessage() {return "Hello, World!";}// 返回集合数据@GetMapping("/users")@ResponseBodypublic List<User> getUsers() {return Arrays.asList(new User("Alice", 30), new User("Bob", 25));}
}
在类上使用
// 等价于在每个方法上添加 @ResponseBody
@RestController // @RestController = @Controller + @ResponseBody
@RequestMapping("/api/users")
public class UserRestController {@GetMappingpublic List<User> getUsers() {return userService.getAllUsers();}@GetMapping("/{id}")public User getUser(@PathVariable Long id) {return userService.getUserById(id);}
}
特点
- 自动序列化:返回值会自动序列化为 JSON/XML
- 绕过视图解析:不经过视图解析器
- 适用于 RESTful API:专门用于构建 RESTful Web 服务
- 内容协商:根据请求的 Accept 头部返回相应格式的数据
高级用法示例
1. 自定义序列化
@Controller
public class DataController {// 返回自定义格式的数据@GetMapping(value = "/data", produces = "application/json")@ResponseBodypublic String getJsonData() {return "{"name": "Alice", "age": 30}";}// 返回 XML 数据@GetMapping(value = "/data.xml", produces = "application/xml")@ResponseBodypublic String getXmlData() {return "<user><name>Alice</name><age>30</age></user>";}// 返回二进制数据@GetMapping(value = "/image", produces = "image/png")@ResponseBodypublic byte[] getImage() throws IOException {// 返回图片数据return Files.readAllBytes(Paths.get("path/to/image.png"));}
}
2. ResponseEntity 结合使用
@Controller
public class UserController {// 使用 ResponseEntity 提供更多控制@GetMapping("/user/{id}")@ResponseBodypublic ResponseEntity<User> getUser(@PathVariable Long id) {User user = userService.getUserById(id);if (user != null) {return ResponseEntity.ok(user);} else {return ResponseEntity.notFound().build();}}// 带自定义头部的响应@PostMapping("/user")@ResponseBodypublic ResponseEntity<User> createUser(@RequestBody User user) {User savedUser = userService.save(user);return ResponseEntity.created(URI.create("/api/user/" + savedUser.getId())).header("X-Custom-Header", "CustomValue").body(savedUser);}
}
最佳实践
-
优先使用 @RestController:对于 RESTful API,优先使用 @RestController 而不是在每个方法上添加 @ResponseBody。
-
合理设置 Content-Type:使用 produces 属性明确指定返回内容类型。
-
异常处理:结合 @ExceptionHandler 或 @ControllerAdvice 处理序列化异常。
-
大数据处理:对于大文件下载等场景,考虑使用 StreamingResponseBody。
// 推荐的 RESTful API 设计
@RestController
@RequestMapping("/api/users")
public class UserController {@Autowiredprivate UserService userService;// 查询所有用户@GetMapping(produces = "application/json")public ResponseEntity<List<User>> getUsers() {List<User> users = userService.findAll();return ResponseEntity.ok(users);}// 根据 ID 查询用户@GetMapping(value = "/{id}", produces = "application/json")public ResponseEntity<User> getUser(@PathVariable Long id) {return userService.findById(id).map(ResponseEntity::ok).orElse(ResponseEntity.notFound().build());}// 创建用户@PostMapping(consumes = "application/json", produces = "application/json")public ResponseEntity<User> createUser(@Valid @RequestBody User user, HttpServletRequest request) {User savedUser = userService.save(user);// 构建资源 URIURI location = ServletUriComponentsBuilder.fromContextPath(request).path("/api/users/{id}").buildAndExpand(savedUser.getId()).toUri();return ResponseEntity.created(location).body(savedUser);}
}
通过合理使用 @ResponseBody 注解,可以轻松构建出能够返回各种格式数据的 Web API,满足现代 Web 应用的多样化需求。
10. @Service
@Service 是 Spring Framework 中用于标记业务逻辑层组件的核心注解,属于 Spring 的典型分层架构注解之一。它将类标识为 Spring 容器管理的服务 Bean,通常用于处理业务逻辑。
核心作用
- 业务逻辑标识:明确标识业务逻辑层组件,提高代码可读性
- 自动注册:标记的类会自动注册为 Spring 容器中的 Bean
- 依赖注入支持:可被其他组件通过 @Autowired 等注解注入使用
- 事务管理集成:与 Spring 事务管理机制无缝集成
基本用法
简单服务类
@Service
public class UserService {public User queryById(Long id) {return userMapper.findById(id);}public List<User> getAllUsers() {return userMapper.findAll();}public User saveUser(User user) {return userMapper.save(user);}
}
带名称的服务类
@Service("userService")
public class UserServiceImpl implements UserService {@Overridepublic User queryById(Long id) {return userMapper.findById(id);}
}
特点
- 组件扫描支持:@Service 是 @Component 的特化,会被组件扫描自动发现
- 默认单例模式:Spring 容器中默认以单例模式管理服务 Bean
- 依赖注入支持:可被其他组件通过 @Autowired、@Resource 等注解注入
- 生命周期管理:支持 @PostConstruct 和 @PreDestroy 等生命周期注解
高级用法示例
1. 事务管理
@Service
@Transactional
public class UserService {@Autowiredprivate UserMapper userMapper;@Transactional(readOnly = true)public User findById(Long id) {return userMapper.findById(id);}// 默认具有事务支持public User save(User user) {User savedUser = userMapper.save(user);// 可能的其他业务逻辑return savedUser;}// 需要新事务的方法@Transactional(propagation = Propagation.REQUIRES_NEW)public void logUserAction(Long userId, String action) {// 记录用户操作日志}
}
2. 与其他注解配合
@Service
@Scope("prototype") // 每次请求创建新实例
@Primary // 标记为主要实现
public class DefaultUserService implements UserService {@Autowiredprivate UserRepository userRepository;@Override@Cacheable("users") // 启用缓存public User findById(Long id) {return userRepository.findById(id);}@Override@CacheEvict(value = "users", key = "#user.id") // 更新时清除缓存public User save(User user) {return userRepository.save(user);}
}
最佳实践
-
明确业务边界:每个服务类应该具有明确的业务职责,遵循单一职责原则。
-
合理使用事务:
- 在服务层配置事务管理
- 根据业务需求设置合适的事务传播行为
- 读取操作使用 readOnly = true 提高性能
-
异常处理:在服务层处理业务异常,避免将底层异常直接抛出。
-
接口与实现分离:定义服务接口,通过实现类添加 @Service 注解。
// 推荐的服务层设计
@Service
@Transactional(readOnly = true)
public class UserServiceImpl implements UserService {@Autowiredprivate UserRepository userRepository;@Autowiredprivate UserValidator userValidator;@Overridepublic User findById(Long id) {return userRepository.findById(id).orElseThrow(() -> new UserNotFoundException("User not found: " + id));}@Override@Transactionalpublic User save(User user) {// 参数验证userValidator.validate(user);// 保存用户User savedUser = userRepository.save(user);// 发布事件applicationEventPublisher.publishEvent(new UserSavedEvent(savedUser));return savedUser;}@Override@Transactionalpublic void deleteById(Long id) {User user = findById(id);userRepository.delete(user);// 清理相关资源cleanupRelatedResources(user);}private void cleanupRelatedResources(User user) {// 清理用户相关的资源}
}
通过合理使用 @Service 注解,可以构建出结构清晰、职责分明的业务逻辑层,提高代码的可维护性和可测试性。
11. @Autowired
@Autowired 是 Spring Framework 中实现依赖注入(DI)的核心注解之一。它用于自动装配 Bean 之间的依赖关系,是 Spring IoC 容器实现控制反转的关键机制。
核心作用
- 自动装配:自动将匹配的 Bean 注入到字段、构造函数或方法中
- 解耦合:降低组件间的耦合度,提高代码的可测试性和可维护性
- 简化配置:减少 XML 配置或 Java 配置的工作量
- 类型安全:基于类型进行装配,提供编译时和运行时的安全性
基本用法
字段注入
@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public User queryById(Long id) {return userMapper.findById(id);}
}
构造函数注入
@Service
public class UserService {private final UserMapper userMapper;// Spring 4.3+ 后,单构造函数场景下可省略 @Autowired@Autowiredpublic UserService(UserMapper userMapper) {this.userMapper = userMapper;}public User queryById(Long id) {return userMapper.findById(id);}
}
方法注入
@Service
public class UserService {private UserMapper userMapper;@Autowiredpublic void setUserMapper(UserMapper userMapper) {this.userMapper = userMapper;}public User queryById(Long id) {return userMapper.findById(id);}
}
主要属性
属性 | 类型 | 说明 |
---|---|---|
required | boolean | 是否必须找到匹配的 Bean,默认为 true。设置为 false 时,找不到匹配的 Bean 不会抛出异常 |
高级用法示例
1. 集合注入
@Service
public class PaymentService {// 注入所有 PaymentProcessor 的实现@Autowiredprivate List<PaymentProcessor> paymentProcessors;// 注入所有 PaymentProcessor 实现及其名称@Autowiredprivate Map<String, PaymentProcessor> paymentProcessorMap;public void processPayment(String type, BigDecimal amount) {PaymentProcessor processor = paymentProcessorMap.get(type + "PaymentProcessor");if (processor != null) {processor.process(amount);}}
}
2. 泛型注入
@Service
public class GenericService {// 注入 String 类型的 Repository@Autowiredprivate GenericRepository<String> stringRepository;// 注入 Integer 类型的 Repository@Autowiredprivate GenericRepository<Integer> integerRepository;
}
3. 条件注入
@Service
public class ConditionalService {// 可选注入,如果找不到 Bean 则为 null@Autowired(required = false)private OptionalFeature optionalFeature;public void performOperation() {// 使用可选功能if (optionalFeature != null) {optionalFeature.perform();}// 其他操作}
}
最佳实践
-
优先使用构造函数注入:
- 保证依赖不可变性(final 字段)
- 确保依赖完整性(避免 NullPointerException)
- 提高类的可测试性
-
避免循环依赖:
- 重新设计组件结构
- 使用 @Lazy 注解延迟加载
- 考虑使用 Setter 注入解决循环依赖
-
合理使用 required 属性:
- 对于必须的依赖保持 required = true(默认值)
- 对于可选的依赖设置 required = false
// 推荐的依赖注入方式
@Service
public class UserService {private final UserRepository userRepository;private final EmailService emailService;// 构造函数注入(推荐)public UserService(UserRepository userRepository, @Autowired(required = false) EmailService emailService) {this.userRepository = userRepository;this.emailService = emailService;}public User createUser(User user) {User savedUser = userRepository.save(user);// 可选功能if (emailService != null) {emailService.sendWelcomeEmail(savedUser);}return savedUser;}
}
通过合理使用 @Autowired 注解,可以实现松耦合、高内聚的组件设计,提高代码的可维护性和可测试性。
12. @Resource
@Resource 是 Java 标准注解(JSR-250)中用于依赖注入的注解,与 Spring 的 @Autowired 注解功能相似但装配机制不同。它提供了更灵活的装配方式,支持按名称或类型进行装配。
核心作用
- 标准化依赖注入:作为 Java 标准注解,提供跨框架的依赖注入能力
- 灵活装配机制:支持按名称或类型装配,优先按名称装配
- 减少框架绑定:使用标准注解降低对特定框架的依赖
- 兼容性支持:在不同 Java EE 兼容框架中保持一致性
基本用法
默认装配
@Service
public class UserService {// 按字段名称装配,如果找不到则按类型装配@Resourceprivate UserMapper userMapper;public User queryById(Long id) {return userMapper.findById(id);}
}
按名称装配
@Service
public class UserService {// 明确按名称装配@Resource(name = "userDatabaseMapper")private UserMapper userMapper;// 装配特定名称的 DAO@Resource(name = "jdbcUserDao")private UserDao userDao;
}
按类型装配
@Service
public class UserService {// 按类型装配,忽略字段名称@Resource(type = UserMapper.class)private UserMapper userMapper;
}
主要属性
属性 | 类型 | 说明 |
---|---|---|
name | String | 指定要注入的 Bean 名称,按名称装配 |
type | Class | 指定要注入的 Bean 类型,按类型装配 |
@Autowired 与 @Resource 的区别
特性 | @Autowired | @Resource |
---|---|---|
来源 | Spring 框架 | Java 标准 (JSR-250) |
装配方式 | 默认按类型装配 | 默认按名称装配,名称不存在时按类型装配 |
属性 | required | name, type |
适用场景 | Spring 特定项目 | 跨框架通用项目 |
性能 | 略快 | 略慢(需解析名称和类型) |
高级用法示例
1. 混合使用场景
@Service
public class PaymentService {// 使用 @Resource 按名称装配特定支付处理器@Resource(name = "alipayProcessor")private PaymentProcessor alipayProcessor;// 使用 @Autowired 按类型装配所有支付处理器@Autowiredprivate List<PaymentProcessor> allProcessors;public void processPayment(String type, BigDecimal amount) {switch (type) {case "alipay":alipayProcessor.process(amount);break;default:// 使用其他处理器break;}}
}
2. 在不同环境中切换实现
@Component
@Profile("production")
public class ProductionEmailService implements EmailService {// 生产环境实现
}@Component
@Profile("development")
public class DevelopmentEmailService implements EmailService {// 开发环境实现
}@Service
public class NotificationService {// 在不同环境中自动切换实现@Resourceprivate EmailService emailService;public void sendNotification(String message) {emailService.send(message);}
}
最佳实践
-
选择合适的注解:
- 在纯 Spring 项目中优先使用 @Autowired
- 在需要跨框架兼容的项目中使用 @Resource
-
明确装配策略:
- 需要精确控制时使用 name 或 type 属性
- 一般情况下可依赖默认装配机制
-
保持一致性:
- 在同一项目中保持依赖注入注解的使用一致性
- 团队内部应制定明确的编码规范
// 推荐的 @Resource 使用方式
@Service
public class OrderService {// 明确按名称装配@Resource(name = "orderRepository")private OrderRepository orderRepository;// 按类型装配(适用于单一实现)@Resource(type = PaymentService.class)private PaymentService paymentService;// 默认装配(适用于名称匹配的场景)@Resourceprivate InventoryService inventoryService;public void processOrder(Order order) {// 处理订单逻辑orderRepository.save(order);paymentService.processPayment(order);inventoryService.updateInventory(order);}
}
通过合理使用 @Resource 注解,可以在享受依赖注入便利的同时,保持代码的标准化和框架无关性。
13. @CrossOrigin
@CrossOrigin 是 Spring MVC 中用于处理跨域资源共享(CORS)的注解。它允许您在 Web 应用中轻松配置跨域请求策略,解决浏览器同源策略限制。
核心作用
- 跨域访问控制:允许指定域的请求访问当前服务的资源
- HTTP 方法控制:限制允许的 HTTP 请求方法
- 请求头管理:控制允许的请求头和暴露的响应头
- 预检请求缓存:通过 maxAge 属性优化预检请求性能
基本用法
类级别使用
@RestController
@RequestMapping("/api/users")
@CrossOrigin(origins = "http://localhost:3000")
public class UserController {@GetMappingpublic List<User> getUsers() {return userService.getAllUsers();}@GetMapping("/{id}")public User getUser(@PathVariable Long id) {return userService.getUserById(id);}
}
方法级别使用
@RestController
@RequestMapping("/api")
public class ApiController {// 允许来自特定域的请求@CrossOrigin(origins = "http://localhost:3000")@GetMapping("/user")public User getUser() {return new User("Bob", 25);}// 允许多个域的请求@CrossOrigin(origins = {"http://localhost:3000", "http://localhost:4000"})@GetMapping("/admin")public User getAdmin() {return new User("Admin", 30);}
}
主要属性
属性 | 类型 | 说明 |
---|---|---|
origins | String[] | 允许的源地址,支持通配符"*"表示允许所有域 |
methods | RequestMethod[] | 允许的 HTTP 方法,默认允许所有标准方法 |
allowedHeaders | String[] | 允许的请求头,"*"表示允许所有头 |
exposedHeaders | String[] | 浏览器可以访问的响应头 |
maxAge | long | 预检请求的缓存时间(秒),默认为 1800 秒 |
allowCredentials | boolean | 是否允许携带凭证(如 Cookie),默认为 false |
高级用法示例
1. 全局 CORS 配置
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/api/**").allowedOrigins("http://localhost:3000", "http://localhost:4000").allowedMethods("GET", "POST", "PUT", "DELETE").allowedHeaders("*").exposedHeaders("X-Custom-Header").allowCredentials(true).maxAge(3600);}
}
2. 复杂的跨域配置
@RestController
@RequestMapping("/api")
public class ComplexController {// 允许所有域,但限制方法和头@CrossOrigin(origins = "*",methods = {RequestMethod.GET, RequestMethod.POST},allowedHeaders = {"Content-Type", "Authorization"},exposedHeaders = {"X-Total-Count"},maxAge = 3600)@GetMapping("/data")public List<Data> getData() {return dataService.getAll();}// 需要携带凭证的跨域请求@CrossOrigin(origins = "http://trusted-domain.com",allowCredentials = "true")@PostMapping("/secure")public ResponseEntity<String> secureOperation() {return ResponseEntity.ok("Secure operation completed");}
}
最佳实践
-
安全性考虑:
- 避免在生产环境中使用 origins = “*”,除非确实需要
- 对于需要携带凭证的请求,必须指定具体的源地址
- 限制允许的 HTTP 方法和请求头
-
性能优化:
- 合理设置 maxAge 值,减少预检请求次数
- 尽量在类级别而非方法级别配置 CORS
-
配置方式选择:
- 全局配置适用于统一的跨域策略
- 局部配置适用于特殊接口的跨域需求
// 推荐的生产环境 CORS 配置
@RestController
@RequestMapping("/api/users")
@CrossOrigin(origins = {"https://myapp.example.com", "https://admin.example.com"},methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE},allowedHeaders = {"Content-Type", "Authorization", "X-Requested-With"},exposedHeaders = {"X-Total-Count"},maxAge = 3600
)
public class UserController {@Autowiredprivate UserService userService;@GetMappingpublic ResponseEntity<List<User>> getUsers() {List<User> users = userService.findAll();return ResponseEntity.ok(users);}@PostMappingpublic ResponseEntity<User> createUser(@RequestBody User user) {User savedUser = userService.save(user);return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);}
}
通过合理使用 @CrossOrigin 注解,可以有效解决跨域问题,同时确保应用的安全性和性能。
14. @Configuration
@Configuration 是 Spring Framework 中用于定义配置类的核心注解。它标识一个类作为 Spring IoC 容器的配置源,通常与 [@Bean](file:///D:/workspace/spring_clouds/09-spring/src/main/java/com/spring/spring_14_annotation_third_bean_manager/src/main/java/com/itheima/config/JdbcConfig.java#L22-L22) 注解配合使用来定义和管理 Bean。
核心作用
- 配置类标识:标识一个类作为配置类,替代传统的 XML 配置文件
- Bean 定义:与 [@Bean](file:///D:/workspace/spring_clouds/09-spring/src/main/java/com/spring/spring_14_annotation_third_bean_manager/src/main/java/com/itheima/config/JdbcConfig.java#L22-L22) 注解配合,定义和配置 Spring Bean
- 组件扫描支持:作为 [@Component](file:///D:/workspace/spring_clouds/10-riskmgmt/perisk/src/main/java/com/citics/riskmgnt/perisk/common/ThreadPoolUtil.java#L23-L23) 的特化版本,可被组件扫描自动发现
- 条件化配置:可与 [@Profile](file:///D:/workspace/spring_clouds/10-riskmgmt/amxrisk/src/main/java/com/citics/riskmgnt/amxrisk/config/RestTemplateConfig.java#L23-L23)、[@Conditional](file:///D:/workspace/spring_clouds/09-spring/src/main/java/com/spring/spring_11_annotation_aop/src/main/java/com/itheima/config/SpringConfig.java#L9-L9) 等注解结合,实现条件化配置
基本用法示例
简单配置类
@Configuration
public class AppConfig {@Beanpublic UserService userService() {return new UserServiceImpl();}@Beanpublic UserMapper userMapper() {return new UserMapperImpl();}
}
带属性注入的配置类
@Configuration
public class DatabaseConfig {@Value("${database.url}")private String databaseUrl;@Value("${database.username}")private String username;@Value("${database.password}")private String password;@Beanpublic DataSource dataSource() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setUrl(databaseUrl);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}@Beanpublic JdbcTemplate jdbcTemplate(DataSource dataSource) {return new JdbcTemplate(dataSource);}
}
主要属性
@Configuration 注解本身没有属性,但通常与其他注解配合使用:
注解 | 作用 | 示例 |
---|---|---|
[@PropertySource](file:///D:/workspace/spring_clouds/09-spring/src/main/java/com/spring/spring_13_annotation_di/src/main/java/com/itheima/config/SpringConfig.java#L9-L9) | 加载属性文件 | @PropertySource(“classpath:jdbc.properties”) |
[@ComponentScan](file:///D:/workspace/spring_clouds/09-spring/src/main/java/com/spring/spring_12_annotation_bean_manager/src/main/java/com/itheima/config/SpringConfig.java#L8-L8) | 指定组件扫描路径 | @ComponentScan(“com.example”) |
[@Import](file:///D:/workspace/spring_clouds/09-spring/src/main/java/com/spring/spring_14_annotation_third_bean_manager/src/main/java/com/itheima/config/SpringConfig.java#L11-L11) | 导入其他配置类 | @Import({ServiceConfig.class, DaoConfig.class}) |
高级特性
条件化配置
@Configuration
@Profile("production")
public class ProductionDatabaseConfig {@Beanpublic DataSource dataSource() {// 生产环境数据源配置return new HikariDataSource();}
}@Configuration
@Profile("development")
public class DevelopmentDatabaseConfig {@Beanpublic DataSource dataSource() {// 开发环境数据源配置return new DriverManagerDataSource();}
}
导入其他配置
@Configuration
@ComponentScan("com.example")
@Import({DatabaseConfig.class, SecurityConfig.class})
@PropertySource("classpath:application.properties")
public class MainConfig {@Beanpublic ApplicationService applicationService() {return new ApplicationServiceImpl();}
}
最佳实践
- 明确配置职责:每个配置类应该有明确的职责,如数据库配置、安全配置等
- 合理使用 [@Import](file:///D:/workspace/spring_clouds/09-spring/src/main/java/com/spring/spring_14_annotation_third_bean_manager/src/main/java/com/itheima/config/SpringConfig.java#L11-L11):通过 [@Import](file:///D:/workspace/spring_clouds/09-spring/src/main/java/com/spring/spring_14_annotation_third_bean_manager/src/main/java/com/itheima/config/SpringConfig.java#L11-L11) 注解组合多个配置类,提高配置的模块化
- 属性注入:使用 [@Value](file:///D:/workspace/spring_clouds/09-spring/src/main/java/com/spring/spring_16_spring_junit/src/main/java/com/itheima/config/JdbcConfig.java#L13-L13) 注解注入配置属性,实现配置与代码的分离
- 避免复杂逻辑:配置类中应避免复杂的业务逻辑,专注于 Bean 的配置
// 推荐的配置类设计
@Configuration
@PropertySource("classpath:app.properties")
@ComponentScan(basePackages = "com.example")
@Import({DatabaseConfig.class, SecurityConfig.class})
public class ApplicationConfig {@Value("${app.name:MyApplication}")private String applicationName;@Beanpublic ApplicationService applicationService(UserService userService, NotificationService notificationService) {ApplicationServiceImpl service = new ApplicationServiceImpl();service.setUserService(userService);service.setNotificationService(notificationService);service.setApplicationName(applicationName);return service;}
}
通过合理使用 @Configuration 注解,可以构建出结构清晰、模块化的配置体系,提高应用的可维护性和可测试性。
15. @Bean
@Bean 是 Spring Framework 中用于在配置类中定义 Bean 的核心注解。它告诉 Spring 容器,被注解的方法将返回一个对象,该对象应该被注册为 Spring 应用上下文中的 Bean。
核心作用
- Bean 定义:在配置类中定义和配置 Spring Bean
- 生命周期管理:通过 initMethod 和 destroyMethod 属性管理 Bean 的生命周期
- 依赖注入:方法参数会自动从容器中获取并注入
- Bean 名称定制:通过 name 属性自定义 Bean 的名称
基本用法
简单 Bean 定义
@Configuration
public class AppConfig {@Beanpublic UserService userService() {return new UserServiceImpl();}@Beanpublic UserMapper userMapper() {return new UserMapperImpl();}
}
依赖其他 Bean
@Configuration
public class AppConfig {@Beanpublic UserMapper userMapper() {return new UserMapperImpl();}// 方法参数会自动从容器中获取并注入@Beanpublic UserService userService(UserMapper userMapper) {UserServiceImpl service = new UserServiceImpl();service.setUserMapper(userMapper);return service;}
}
主要属性
属性 | 类型 | 说明 |
---|---|---|
name | String[] | Bean 的名称,默认为方法名 |
initMethod | String | 初始化方法名,在 Bean 初始化时调用 |
destroyMethod | String | 销毁方法名,在 Bean 销毁时调用 |
autowireCandidate | boolean | 是否作为自动装配的候选者,默认为 true |
高级用法示例
自定义 Bean 名称和生命周期方法
@Configuration
public class AppConfig {@Bean(name = "customUserService", initMethod = "initialize", destroyMethod = "cleanup")public UserService userService() {UserServiceImpl userService = new UserServiceImpl();userService.setSomeProperty("value");return userService;}@Bean("namedMapper")public UserMapper userMapper() {return new UserMapperImpl();}
}
作用域配置
@Configuration
public class AppConfig {@Bean@Scope("singleton") // 默认作用域public UserService singletonUserService() {return new UserServiceImpl();}@Bean@Scope("prototype")public UserMapper prototypeUserMapper() {return new UserMapperImpl();}@Bean@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)public ShoppingCart sessionCart() {return new ShoppingCart();}
}
最佳实践
- 方法参数注入:利用方法参数自动注入依赖,比手动从容器获取更简洁
- 合理命名:对于需要自定义名称的 Bean,使用 name 属性明确指定
- 生命周期管理:对于需要初始化或清理操作的 Bean,配置 initMethod 和 destroyMethod
- 作用域选择:根据 Bean 的使用场景选择合适的作用域
// 推荐的 @Bean 使用方式
@Configuration
public class DatabaseConfig {@Value("${database.pool.size:10}")private int poolSize;@Bean(name = "primaryDataSource", initMethod = "init", destroyMethod = "close")public DataSource primaryDataSource() {HikariDataSource dataSource = new HikariDataSource();dataSource.setMaximumPoolSize(poolSize);// 其他配置...return dataSource;}@Bean@Scope("prototype")public JdbcTemplate jdbcTemplate(DataSource primaryDataSource) {return new JdbcTemplate(primaryDataSource);}@Beanpublic TransactionTemplate transactionTemplate(PlatformTransactionManager txManager) {return new TransactionTemplate(txManager);}
}
通过合理使用 @Bean 注解,可以灵活地定义和配置 Spring 容器中的各种 Bean,满足不同场景的需求。
16. @Component
@Component 是 Spring Framework 中最基本的组件注解,用于标记任何 Spring 管理的组件。它是其他特定组件注解(如 [@Controller](file:///D:/workspace/spring_clouds/09-spring/src/main/java/com/spring/spring_19_springmvc_demo/src/main/java/com/itheima/controller/UserController.java#L9-L9)、[@Service](file:///D:/workspace/spring_clouds/10-riskmgmt/spec/src/main/java/com/citics/riskmgnt/spec/userauth/service/impl/UserAuthServiceImpl.java#L17-L17)、[@Repository](file:///D:/workspace/spring_clouds/10-riskmgmt/spec/src/main/java/com/citics/riskmgnt/spec/citicRuleCheck/dao/CiticRuleCheckDao.java#L10-L10))的基础注解。
核心作用
- 通用组件标识:标记一个类作为 Spring 容器管理的组件
- 自动注册:被 [@ComponentScan](file:///D:/workspace/spring_clouds/09-spring/src/main/java/com/spring/spring_12_annotation_bean_manager/src/main/java/com/itheima/config/SpringConfig.java#L8-L8) 扫描并注册为 Bean
- 依赖注入支持:可被其他组件通过 [@Autowired](file:///D:/workspace/spring_clouds/09-spring/src/main/java/com/spring/spring_13_annotation_di/src/main/java/com/itheima/service/impl/UserServiceImpl.java#L12-L12)、[@Resource](file:///D:/workspace/spring_clouds/10-riskmgmt/auth/src/main/java/com/citics/auth/login/service/impl/LoginServiceImpl.java#L29-L29) 等注解注入使用
- 基础注解:是 [@Controller](file:///D:/workspace/spring_clouds/09-spring/src/main/java/com/spring/spring_19_springmvc_demo/src/main/java/com/itheima/controller/UserController.java#L9-L9)、[@Service](file:///D:/workspace/spring_clouds/10-riskmgmt/spec/src/main/java/com/citics/riskmgnt/spec/userauth/service/impl/UserAuthServiceImpl.java#L17-L17)、[@Repository](file:///D:/workspace/spring_clouds/10-riskmgmt/spec/src/main/java/com/citics/riskmgnt/spec/citicRuleCheck/dao/CiticRuleCheckDao.java#L10-L10) 等注解的基础
基本用法
简单组件
@Component
public class MyComponent {public void doSomething() {System.out.println("执行某些操作");}
}
带名称的组件
@Component("myCustomComponent")
public class MyComponent {public void performAction() {System.out.println("执行操作");}
}
特点
- 通用性:适用于任何 Spring 管理的组件
- 自动发现:配合 [@ComponentScan](file:///D:/workspace/spring_clouds/09-spring/src/main/java/com/spring/spring_12_annotation_bean_manager/src/main/java/com/itheima/config/SpringConfig.java#L8-L8) 可自动注册为 Bean
- 可注入性:可被其他组件注入使用
- 继承性:其他组件注解的基础注解
与其他注解的关系
注解 | 用途 | 说明 |
---|---|---|
[@Repository](file:///D:/workspace/spring_clouds/10-riskmgmt/spec/src/main/java/com/citics/riskmgnt/spec/citicRuleCheck/dao/CiticRuleCheckDao.java#L10-L10) | 持久层组件 | 专门用于数据访问层,提供持久层异常转换 |
[@Service](file:///D:/workspace/spring_clouds/10-riskmgmt/spec/src/main/java/com/citics/riskmgnt/spec/userauth/service/impl/UserAuthServiceImpl.java#L17-L17) | 业务层组件 | 专门用于业务逻辑层 |
[@Controller](file:///D:/workspace/spring_clouds/09-spring/src/main/java/com/spring/spring_19_springmvc_demo/src/main/java/com/itheima/controller/UserController.java#L9-L9) | 控制层组件 | 专门用于 Web 控制层 |
[@Component](file:///D:/workspace/spring_clouds/10-riskmgmt/perisk/src/main/java/com/citics/riskmgnt/perisk/common/ThreadPoolUtil.java#L23-L23) | 通用组件 | 适用于任何组件,是上述注解的基础 |
这些注解都是 @Component 的特化版本,具有相同的功能但语义更明确。
高级用法示例
条件化组件
@Component
@Profile("development")
public class DevelopmentService {public void performAction() {System.out.println("开发环境下的操作");}
}@Component
@Profile("production")
public class ProductionService {public void performAction() {System.out.println("生产环境下的操作");}
}
带作用域的组件
@Component
@Scope("prototype")
public class PrototypeComponent {public void doSomething() {System.out.println("原型组件操作");}
}@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class SessionScopedComponent {public void doSessionWork() {System.out.println("会话范围组件操作");}
}
最佳实践
- 语义化选择:优先使用语义更明确的注解([@Repository](file:///D:/workspace/spring_clouds/10-riskmgmt/spec/src/main/java/com/citics/riskmgnt/spec/citicRuleCheck/dao/CiticRuleCheckDao.java#L10-L10)、[@Service](file:///D:/workspace/spring_clouds/10-riskmgmt/spec/src/main/java/com/citics/riskmgnt/spec/userauth/service/impl/UserAuthServiceImpl.java#L17-L17)、[@Controller](file:///D:/workspace/spring_clouds/09-spring/src/main/java/com/spring/spring_19_springmvc_demo/src/main/java/com/itheima/controller/UserController.java#L9-L9)),只在没有合适注解时使用 [@Component](file:///D:/workspace/spring_clouds/10-riskmgmt/perisk/src/main/java/com/citics/riskmgnt/perisk/common/ThreadPoolUtil.java#L23-L23)
- 命名规范:对于需要自定义名称的组件,明确指定名称
- 组件职责:每个组件应有明确的职责,遵循单一职责原则
// 推荐的组件设计
@Component
public class FileStorageService {private final StorageProperties storageProperties;// 构造函数注入(推荐)public FileStorageService(StorageProperties storageProperties) {this.storageProperties = storageProperties;}public void saveFile(MultipartFile file) {// 文件保存逻辑String location = storageProperties.getLocation();// 实际保存操作}public byte[] loadFile(String filename) {// 文件加载逻辑return new byte[0];}
}
通过合理使用 @Component 及其特化注解,可以构建出结构清晰、职责明确的 Spring 应用程序,提高代码的可维护性和可读性。
17. @Value
@Value 是 Spring Framework 中用于注入属性值的核心注解。它可以将配置文件中的属性值、系统属性、环境变量等注入到 Spring 管理的 Bean 属性中。
核心作用
- 属性注入:将外部配置属性注入到 Bean 的字段或方法参数中
- 表达式支持:支持 Spring Expression Language (SpEL) 表达式
- 默认值设置:可以为属性设置默认值,提高应用的健壮性
- 配置分离:实现配置与代码的分离,便于维护和部署
基本用法
注入简单属性值
@Component
public class DatabaseConfig {@Value("${database.url}")private String databaseUrl;@Value("${database.username}")private String username;@Value("${database.password}")private String password;// 使用注入的属性public DataSource createDataSource() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setUrl(databaseUrl);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}
}
设置默认值
@Component
public class AppConfig {// 如果配置文件中没有定义 server.port,则使用默认值 8080@Value("${server.port:8080}")private int serverPort;// 字符串默认值@Value("${app.name:MyApplication}")private String appName;// 数组默认值@Value("${app.servers:server1,server2,server3}")private String[] servers;
}
主要属性
@Value 注解只有一个 value 属性,用于指定要注入的值:
属性 | 类型 | 说明 |
---|---|---|
value | String | 指定要注入的属性值或表达式 |
高级用法示例
使用 SpEL 表达式
@Component
public class ExpressionConfig {// 字面量表达式@Value("#{10 * 20}")private int calculationResult;// 系统属性@Value("#{systemProperties['java.home']}")private String javaHome;// 随机值@Value("#{T(java.lang.Math).random() * 100.0}")private double randomNumber;// 调用其他 Bean 的方法@Value("#{databaseConfig.databaseUrl}")private String dbUrlFromBean;// 三元操作符@Value("#{systemProperties['app.dev'] == 'true' ? 'dev' : 'prod'}")private String environment;
}
注入集合类型
@Component
public class CollectionConfig {// 注入列表(逗号分隔)@Value("${app.roles:admin,user,guest}")private List<String> roles;// 注入集合@Value("${app.permissions:read,write,execute}")private Set<String> permissions;// 注入映射(需要特殊格式)@Value("#{${app.settings}}")private Map<String, String> settings;
}
条件化注入
@Component
public class ConditionalConfig {// 根据系统属性决定是否启用某个功能@Value("#{systemProperties['feature.enabled'] ?: false}")private boolean featureEnabled;// 根据配置文件决定超时时间@Value("#{${app.timeout:30} * 1000}")private long timeoutInMillis;
}
最佳实践
-
合理使用默认值:为配置属性提供合理的默认值,增强应用的健壮性,避免因缺少配置导致应用启动失败。
-
类型安全:确保配置值能够正确转换为目标类型,避免类型转换异常。
-
配置分组:对于相关的配置项,考虑使用配置类进行分组管理。
-
避免硬编码:不要在 @Value 注解中硬编码敏感信息,应该使用配置文件或环境变量。
// 推荐的配置管理方式
@Component
@PropertySource("classpath:app.properties")
public class ApplicationConfig {@Value("${app.name:DefaultApp}")private String appName;@Value("${app.version:1.0.0}")private String appVersion;@Value("${app.debug:false}")private boolean debugMode;@Value("${app.max-connections:100}")private int maxConnections;// 对于复杂配置,建议使用 @ConfigurationProperties@Value("${app.whitelist:127.0.0.1,localhost}")private List<String> whitelist;// 提供 getter 方法供其他组件使用public String getAppName() {return appName;}public String getAppVersion() {return appVersion;}public boolean isDebugMode() {return debugMode;}public int getMaxConnections() {return maxConnections;}public List<String> getWhitelist() {return whitelist;}
}
与其他注解的配合使用
与 @PropertySource 配合
@Configuration
@PropertySource("classpath:database.properties")
public class DatabaseConfiguration {@Value("${database.driver:com.mysql.cj.jdbc.Driver}")private String driverClassName;@Value("${database.url}")private String url;@Value("${database.username}")private String username;@Value("${database.password}")private String password;@Beanpublic DataSource dataSource() {HikariDataSource dataSource = new HikariDataSource();dataSource.setDriverClassName(driverClassName);dataSource.setJdbcUrl(url);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}
}
在构造函数中使用
@Component
public class EmailService {private final String smtpHost;private final int smtpPort;private final boolean useSSL;// 构造函数注入配置值public EmailService(@Value("${mail.smtp.host:localhost}") String smtpHost,@Value("${mail.smtp.port:25}") int smtpPort,@Value("${mail.smtp.ssl:false}") boolean useSSL) {this.smtpHost = smtpHost;this.smtpPort = smtpPort;this.useSSL = useSSL;}// 邮件发送逻辑public void sendEmail(String to, String subject, String content) {// 实现邮件发送逻辑}
}
通过合理使用 @Value 注解,可以轻松地将外部配置注入到 Spring 应用中,实现配置与代码的分离,提高应用的灵活性和可维护性。