springboot常見的一些相關(guān)注解總結(jié)
Spring 注解大全
本文檔詳細介紹了 Spring 框架中常用的核心注解,幫助開發(fā)者更好地理解和使用這些注解。Spring 注解極大地簡化了配置,提高了開發(fā)效率,是現(xiàn)代 Spring 應用開發(fā)的基礎。
1. @Controller
@Controller 是 Spring Framework 中用于標記Web 控制器的核心注解,屬于 Spring MVC 的核心組件。它用于定義一個類作為處理 HTTP 請求的入口點,負責接收請求、調(diào)用業(yè)務邏輯并返回視圖或數(shù)據(jù)。
核心作用
- 請求映射:通過 @RequestMapping 或其派生注解(如 @GetMapping、@PostMapping)將 HTTP 請求映射到控制器的方法。
- 視圖解析:返回字符串時,Spring 會使用視圖解析器(如 Thymeleaf、JSP)將其轉(zhuǎn)換為實際的視圖(如 HTML 頁面)。
- 數(shù)據(jù)綁定:自動將請求參數(shù)、表單數(shù)據(jù)或路徑變量綁定到方法參數(shù)(結(jié)合 @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); // 將數(shù)據(jù)傳遞給視圖
return "userProfile"; // 對應視圖解析器配置的模板(如 userProfile.html)
}
}
場景 2:返回 JSON 數(shù)據(jù)(需配合 @ResponseBody)
@Controller
@RequestMapping("/api")
public class ApiController {
// 返回 JSON 數(shù)據(jù)(需要手動添加 @ResponseBody)
@GetMapping("/data")
@ResponseBody
public User getData() {
return new User("Alice", 30); // 自動轉(zhuǎn)換為 JSON
}
}
@Controller vs @RestController
@Controller:
- 傳統(tǒng) MVC 控制器,默認返回視圖名稱。若需返回 JSON/XML 等數(shù)據(jù),需在方法上添加 @ResponseBody。
@RestController:
- @Controller + @ResponseBody 的組合注解,所有方法默認返回數(shù)據(jù)而非視圖(自動序列化為 JSON/XML)。
@RestController
@RequestMapping("/api")
public class UserRestController {
@GetMapping("/user")
public User getUser() {
return new User("Bob", 25); // 自動返回 JSON
}
}
關(guān)鍵注解配合使用
| 注解 | 作用 | 示例 |
|---|---|---|
| @RequestMapping | 類/方法級請求映射 | @RequestMapping(“/home”) |
| @GetMapping | 快捷注解(GET 請求) | @GetMapping(“/list”) |
| @PostMapping | 快捷注解(POST 請求) | @PostMapping(“/save”) |
| @PathVariable | 綁定 URI 模板變量 | @GetMapping(“/users/{id}”) public User getUser(@PathVariable Long id) |
| @RequestParam | 綁定請求參數(shù) | @RequestParam String name |
| @RequestBody | 綁定請求體數(shù)據(jù)(JSON/XML) | public void saveUser(@RequestBody User user) |
| @ModelAttribute | 綁定表單數(shù)據(jù)到對象 | 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:在控制器內(nèi)處理局部異常。
@Controller
public class ErrorController {
@ExceptionHandler(Exception.class)
public String handleException() {
return "errorPage"; // 異常時返回錯誤頁面
}
}
最佳實踐
明確職責分離:
- 控制器負責接收請求和調(diào)用服務層,業(yè)務邏輯應放在 Service 層。
- 避免在控制器中編寫復雜邏輯。
合理使用注解:
- RESTful API 優(yōu)先使用 @RestController。
- 傳統(tǒng) Web 應用使用 @Controller + 視圖解析器。
參數(shù)校驗:
- 結(jié)合 @Valid 和 BindingResult 進行請求參數(shù)校驗。
@PostMapping("/save")
public String saveUser(@Valid @ModelAttribute User user, BindingResult result) {
if (result.hasErrors()) {
return "formPage"; // 校驗失敗返回表單
}
// 保存用戶...
}
- 靜態(tài)資源處理:
- 確保靜態(tài)資源(如 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 數(shù)據(jù)
@GetMapping("/{id}")
@ResponseBody
public 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 及其相關(guān)注解,可以構(gòu)建出結(jié)構(gòu)清晰、職責分明的 Web 應用,同時兼顧傳統(tǒng) MVC 和 RESTful API 的開發(fā)需求。
2. @RestController
@RestController 是 Spring 4.0 引入的組合注解,等價于 @Controller + @ResponseBody。它是構(gòu)建 RESTful Web 服務的核心注解,專門用于創(chuàng)建 REST API。
核心作用
- 簡化 REST API 開發(fā):無需在每個方法上添加 @ResponseBody
- 自動序列化:方法返回值自動序列化為 JSON/XML 格式
- 前后端分離支持:適用于前后端分離架構(gòu)的后端 API 開發(fā)
基本用法
簡單 REST 控制器
@RestController
@RequestMapping("/api/users")
public class UserRestController {
@GetMapping
public List<User> getUsers() {
return userService.getAllUsers();
}
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.getUserById(id);
}
@PostMapping
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);
}
}
與其他注解配合使用
@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
- 默認返回數(shù)據(jù):所有方法默認返回數(shù)據(jù)而非視圖
- 自動序列化:方法返回值會自動序列化為 JSON/XML
- 適用于 RESTful API:專門為 RESTful Web 服務設計
- 減少樣板代碼:無需在每個方法上添加 @ResponseBody
高級用法示例
1. 自定義響應格式
// 統(tǒng)一響應結(jié)果類
public class Result<T> {
private int code;
private String message;
private T data;
// 構(gòu)造方法、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 {
@GetMapping
public 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 開發(fā):@RestController 專門用于構(gòu)建 RESTful API,不適用于需要返回視圖的場景。
合理組織 URL 結(jié)構(gòu):使用 @RequestMapping 在類級別定義基礎路徑,方法級別定義具體操作。
統(tǒng)一響應格式:建議使用統(tǒng)一的響應格式,方便前端處理。
配合異常處理:結(jié)合 @RestControllerAdvice 進行全局異常處理,提供一致的錯誤響應。
啟用 CORS:對于前后端分離的應用,合理配置跨域支持。
// 推薦的 RESTful 控制器結(jié)構(gòu)
@RestController
@RequestMapping("/api/v1/users")
@CrossOrigin
public class UserRestController {
@Autowired
private UserService userService;
@GetMapping
public 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());
}
@PostMapping
public 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 注解,可以快速構(gòu)建符合 RESTful 設計規(guī)范的 Web API,滿足現(xiàn)代 Web 應用的開發(fā)需求。
3. @RequestMapping
@RequestMapping 是 Spring MVC 中最基礎和重要的注解之一,用于將 Web 請求映射到具體的處理方法上。它可以應用在類級別或方法級別,提供靈活的請求映射配置。
核心作用
- URL 映射:將特定 URL 路徑的請求映射到處理方法
- HTTP 方法限定:指定處理的 HTTP 請求方法(GET、POST、PUT、DELETE 等)
- 請求條件匹配:基于請求參數(shù)、請求頭等條件進行匹配
- 內(nèi)容類型控制:指定可處理的請求內(nèi)容類型和返回的內(nèi)容類型
基本用法
類級別使用
@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() {
// 創(chuàng)建用戶邏輯
return "userCreated";
}
}
方法級別使用
@Controller
public class UserController {
@RequestMapping("/users")
public String getUsers() {
return "userList";
}
@RequestMapping(value = "/users", method = RequestMethod.POST)
public String createUser() {
// 創(chuàng)建用戶邏輯
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[] | 指定請求參數(shù)條件(如 “version=1”、“!version”) |
| headers | String[] | 指定請求頭條件(如 “Accept=text/plain”) |
| consumes | String[] | 指定處理請求的提交內(nèi)容類型(Content-Type) |
| produces | String[] | 指定返回內(nèi)容的類型(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. 請求參數(shù)和頭部條件
@Controller
public class ApiController {
// 僅匹配帶有 version=2 參數(shù)的請求
@RequestMapping(value = "/api/data", params = "version=2")
public String getDataV2() {
return "dataV2";
}
// 僅匹配 Accept 頭部為 application/json 的請求
@RequestMapping(value = "/api/data", headers = "Accept=application/json")
@ResponseBody
public 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";
}
}
}
最佳實踐
優(yōu)先使用派生注解:對于簡單的 RESTful API,推薦使用 @GetMapping、@PostMapping 等派生注解,使代碼更清晰。
合理組織類級別和方法級別映射:將通用路徑前綴放在類級別,具體操作放在方法級別。
避免過于復雜的映射規(guī)則:復雜的映射會增加維護難度,應盡量保持簡潔。
使用 produces 和 consumes 明確內(nèi)容類型:有助于提高 API 的可讀性和正確性。
// 推薦的 RESTful 風格
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping
public 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 注解及其派生注解,可以構(gòu)建出清晰、規(guī)范的 Web API 接口。
4. @RequestParam
@RequestParam 注解用于將 HTTP 請求參數(shù)(查詢參數(shù)或表單參數(shù))綁定到方法參數(shù)上。它是處理客戶端傳遞參數(shù)的重要注解。
核心作用
- 參數(shù)綁定:將請求中的參數(shù)值自動綁定到方法參數(shù)
- 類型轉(zhuǎn)換:自動將字符串參數(shù)轉(zhuǎn)換為相應的 Java 類型
- 參數(shù)驗證:通過 required 屬性控制參數(shù)是否必須
- 默認值設置:通過 defaultValue 屬性設置參數(shù)默認值
基本用法
簡單參數(shù)綁定
@GetMapping("/users/search")
public String searchUsers(@RequestParam("name") String name,
@RequestParam("age") Integer age) {
// 處理請求參數(shù)
// 例如:/users/search?name=Tom&age=25
return "userList";
}
可選參數(shù)和默認值
@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 參數(shù)有默認值,即使不傳也會有值
// sort 參數(shù)是可選的,不傳時為 null
return "userList";
}
數(shù)組和集合參數(shù)
@GetMapping("/users/batch")
public String batchDelete(@RequestParam("ids") Long[] ids) {
// 處理多個 ID
// 例如:/users/batch?ids=1&ids=2&ids=3
return "batchDeleted";
}
@GetMapping("/users/filter")
public String filterUsers(@RequestParam("tags") List<String> tags) {
// 處理標簽列表
// 例如:/users/filter?tags=VIP&tags=Active
return "filteredList";
}
主要屬性
| 屬性 | 類型 | 說明 |
|---|---|---|
| value/name | String | 指定要綁定的請求參數(shù)名稱 |
| required | boolean | 是否必須存在該參數(shù),默認為 true |
| defaultValue | String | 默認值,當參數(shù)不存在時使用(設置后 required 自動為 false) |
高級用法示例
1. 復雜對象參數(shù)綁定
// 用戶搜索條件類
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. 參數(shù)驗證
@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 進行參數(shù)驗證
// page 必須大于等于 1
// size 必須在 1-100 之間
return "userList";
}
最佳實踐
合理使用 defaultValue:對于分頁、排序等場景,設置合理的默認值可以提高用戶體驗。
注意 required 屬性:設置了 defaultValue 后,required 屬性會自動設為 false。
類型轉(zhuǎn)換注意事項:確保請求參數(shù)能夠正確轉(zhuǎn)換為目標類型,避免類型轉(zhuǎn)換異常。
處理集合參數(shù):對于需要傳遞多個同名參數(shù)的場景,可以使用數(shù)組或集合類型。
// 推薦的參數(shù)處理方式
@RestController
@RequestMapping("/api/users")
public class UserController {
// 分頁查詢
@GetMapping
public 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 注解,可以輕松處理各種請求參數(shù)場景,使 Web 接口更加靈活和易用。
5. @PathVariable
@PathVariable 注解用于將 URI 模板變量綁定到方法參數(shù)上,是 RESTful API 設計中的重要注解。它允許從 URL 路徑中提取變量值。
核心作用
- 路徑變量提取:從 URL 路徑中提取指定的變量值
- RESTful 風格支持:支持 RESTful 風格的 URL 設計
- 類型自動轉(zhuǎn)換:自動將路徑變量轉(zhuǎn)換為相應的 Java 類型
- 正則表達式支持:支持使用正則表達式對路徑變量進行約束
基本用法
簡單路徑變量
@GetMapping("/users/{id}")
public String getUser(@PathVariable("id") Long id) {
// 處理 /users/123 這樣的請求
// id 參數(shù)值為 123
return "userDetail";
}
// 當方法參數(shù)名與路徑變量名一致時,可以省略 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";
}
// 混合使用路徑變量和請求參數(shù)
@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 只能是數(shù)字
@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) {
// 返回舊版本數(shù)據(jù)格式
return "userOldFormat";
} else {
// 返回新版本數(shù)據(jù)格式
return "userNewFormat";
}
}
// 處理多級路徑
@GetMapping("/categories/{categoryPath:.+}")
public String getCategory(@PathVariable String categoryPath) {
// categoryPath 可以包含多級路徑,如 "electronics/computers/laptops"
String[] paths = categoryPath.split("/");
return "categoryDetail";
}
}
最佳實踐
路徑變量命名規(guī)范:使用有意義的變量名,提高代碼可讀性。
類型安全:選擇合適的 Java 類型,避免類型轉(zhuǎn)換異常。
正則表達式約束:對路徑變量使用正則表達式進行約束,提高 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 注解,可以構(gòu)建出符合 RESTful 設計規(guī)范的 Web API,使 URL 更加直觀和易于理解。
6. @GetMapping
@GetMapping 是 Spring 4.3 引入的組合注解,等價于 @RequestMapping(method = RequestMethod.GET)。它是處理 HTTP GET 請求的快捷方式,專門用于數(shù)據(jù)查詢操作。
核心作用
- 簡化 GET 請求映射:替代 @RequestMapping(method = RequestMethod.GET)
- 語義明確:明確表示該方法處理 GET 請求
- 提高可讀性:使代碼更加簡潔和易讀
基本用法
簡單查詢操作
@RestController
@RequestMapping("/api/users")
public class UserController {
// 查詢所有用戶
@GetMapping
public List<User> getUsers() {
return userService.getAllUsers();
}
// 根據(jù) ID 查詢用戶
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.getUserById(id);
}
// 帶查詢參數(shù)的 GET 請求
@GetMapping(params = "name")
public List<User> getUsersByName(@RequestParam String name) {
return userService.getUsersByName(name);
}
}
復雜查詢場景
@RestController
@RequestMapping("/api/products")
public class ProductController {
// 分頁查詢
@GetMapping
public 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);
}
// 查詢統(tǒng)計信息
@GetMapping("/count")
public long getProductCount() {
return productService.count();
}
}
主要屬性
@GetMapping 注解繼承了 @RequestMapping 的所有屬性:
| 屬性 | 類型 | 說明 |
|---|---|---|
| value/path | String[] | 指定請求的 URL 路徑 |
| params | String[] | 指定請求參數(shù)條件 |
| headers | String[] | 指定請求頭條件 |
| consumes | String[] | 指定處理請求的提交內(nèi)容類型 |
| produces | String[] | 指定返回內(nèi)容的類型 |
高級用法示例
1. 條件映射
@RestController
@RequestMapping("/api/data")
public class DataController {
// 僅當請求包含 version=2 參數(shù)時匹配
@GetMapping(params = "version=2")
public String getDataV2() {
return "data version 2";
}
// 僅當請求包含 format=json 參數(shù)時匹配
@GetMapping(params = "format=json", produces = "application/json")
@ResponseBody
public 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 {
// 結(jié)合緩存注解
@GetMapping("/{id}")
@Cacheable(value = "users", key = "#id")
public User getUser(@PathVariable Long id) {
return userService.getUserById(id);
}
// 結(jié)合權(quán)限控制
@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 請求應該是冪等的,不應產(chǎn)生副作用。
合理使用緩存:對于頻繁查詢的數(shù)據(jù),可以結(jié)合緩存機制提高性能。
避免敏感信息:不要在 GET 請求的 URL 中傳遞敏感信息,因為 URL 可能被記錄在日志中。
參數(shù)驗證:對于復雜的查詢參數(shù),應進行適當?shù)尿炞C。
// 推薦的查詢接口設計
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
// 基礎查詢
@GetMapping
public 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);
}
// 統(tǒng)計查詢
@GetMapping("/statistics")
public ResponseEntity<Map<String, Object>> getUserStatistics() {
Map<String, Object> statistics = userService.getStatistics();
return ResponseEntity.ok(statistics);
}
}
通過合理使用 @GetMapping 注解,可以構(gòu)建出語義清晰、易于維護的查詢接口,提高 Web API 的質(zhì)量和可讀性。
7. @PostMapping
@PostMapping 是 Spring 4.3 引入的組合注解,等價于 @RequestMapping(method = RequestMethod.POST)。它是處理 HTTP POST 請求的快捷方式,專門用于創(chuàng)建資源和提交數(shù)據(jù)操作。
核心作用
- 簡化 POST 請求映射:替代 @RequestMapping(method = RequestMethod.POST)
- 語義明確:明確表示該方法處理 POST 請求
- 提高可讀性:使代碼更加簡潔和易讀
- 資源創(chuàng)建:主要用于創(chuàng)建新資源
基本用法
創(chuàng)建資源
@RestController
@RequestMapping("/api/users")
public class UserController {
// 創(chuàng)建新用戶
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
User savedUser = userService.save(user);
return ResponseEntity.status(HttpStatus.CREATED).body(savedUser);
}
// 創(chuàng)建用戶的訂單
@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[] | 指定請求參數(shù)條件 |
| headers | String[] | 指定請求頭條件 |
| consumes | String[] | 指定處理請求的提交內(nèi)容類型 |
| produces | String[] | 指定返回內(nèi)容的類型 |
高級用法示例
1. 內(nèi)容類型限定
@RestController
@RequestMapping("/api/data")
public class DataController {
// 僅處理 JSON 格式的請求
@PostMapping(consumes = "application/json")
public ResponseEntity<String> handleJsonData(@RequestBody Map<String, Object> data) {
// 處理 JSON 數(shù)據(jù)
return ResponseEntity.ok("JSON data processed");
}
// 僅處理 XML 格式的請求
@PostMapping(consumes = "application/xml", produces = "application/xml")
public ResponseEntity<String> handleXmlData(@RequestBody String xmlData) {
// 處理 XML 數(shù)據(jù)
String response = "<response>XML data processed</response>";
return ResponseEntity.ok(response);
}
// 僅處理表單數(shù)據(jù)
@PostMapping(consumes = "application/x-www-form-urlencoded")
public ResponseEntity<String> handleFormData(@RequestParam Map<String, String> formData) {
// 處理表單數(shù)據(jù)
return ResponseEntity.ok("Form data processed");
}
}
2. 與其他注解配合
@RestController
@RequestMapping("/api/users")
public class UserController {
// 結(jié)合驗證注解
@PostMapping
public 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);
}
// 結(jié)合事務注解
@PostMapping("/batch")
@Transactional
public ResponseEntity<List<User>> createUsers(@RequestBody List<User> users) {
List<User> savedUsers = userService.saveAll(users);
return ResponseEntity.status(HttpStatus.CREATED).body(savedUsers);
}
// 結(jié)合安全注解
@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 請求通常不是冪等的,多次執(zhí)行會產(chǎn)生不同的結(jié)果。
返回 201 狀態(tài)碼:創(chuàng)建資源成功時應返回 HTTP 201 (CREATED) 狀態(tài)碼。
返回 Location 頭部:創(chuàng)建資源后,應在響應中包含 Location 頭部,指向新創(chuàng)建的資源。
參數(shù)驗證:對傳入的數(shù)據(jù)進行驗證,確保數(shù)據(jù)的完整性和正確性。
事務處理:對于涉及多個操作的復雜創(chuàng)建邏輯,應使用事務確保數(shù)據(jù)一致性。
// 推薦的資源創(chuàng)建接口設計
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public ResponseEntity<User> createUser(@Valid @RequestBody User user,
HttpServletRequest request) {
// 保存用戶
User savedUser = userService.save(user);
// 構(gòu)建資源 URI
URI location = ServletUriComponentsBuilder
.fromCurrentRequest()
.path("/{id}")
.buildAndExpand(savedUser.getId())
.toUri();
// 返回 201 狀態(tài)碼和 Location 頭部
return ResponseEntity.created(location).body(savedUser);
}
// 批量創(chuàng)建
@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 注解,可以構(gòu)建出符合 HTTP 語義的資源創(chuàng)建接口,提供良好的 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 {
// 根據(jù) 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[] | 指定請求參數(shù)條件 |
| headers | String[] | 指定請求頭條件 |
| consumes | String[] | 指定處理請求的提交內(nèi)容類型 |
| produces | String[] | 指定返回內(nèi)容的類型 |
高級用法示例
1. 軟刪除實現(xiàn)
@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. 關(guān)聯(lián)刪除
@RestController
@RequestMapping("/api/users")
public class UserController {
// 刪除用戶及其關(guān)聯(lián)數(shù)據(jù)
@DeleteMapping("/{id}")
@Transactional
public ResponseEntity<Void> deleteUserWithRelations(
@PathVariable Long id,
@RequestParam(defaultValue = "false") boolean cascade) {
if (cascade) {
// 級聯(lián)刪除關(guān)聯(lián)數(shù)據(jù)
orderService.deleteByUserId(id);
userService.deleteById(id);
} else {
// 檢查是否有關(guān)聯(lián)數(shù)據(jù)
if (orderService.existsByUserId(id)) {
return ResponseEntity.status(HttpStatus.CONFLICT).build();
}
userService.deleteById(id);
}
return ResponseEntity.noContent().build();
}
}
最佳實踐
冪等性:DELETE 請求應該是冪等的,多次刪除同一個資源應該返回相同的結(jié)果。
返回 204 狀態(tài)碼:刪除成功時通常返回 HTTP 204 (NO CONTENT) 狀態(tài)碼。
安全性考慮:刪除操作應該謹慎處理,特別是批量刪除和刪除所有數(shù)據(jù)的操作。
權(quán)限控制:刪除敏感資源時應進行權(quán)限驗證。
軟刪除:對于重要數(shù)據(jù),建議使用軟刪除而不是物理刪除。
// 推薦的刪除接口設計
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(
@PathVariable Long id,
Authentication authentication) {
// 檢查資源是否存在
if (!userService.existsById(id)) {
return ResponseEntity.notFound().build();
}
// 檢查權(quán)限
if (!userService.canDelete(id, authentication)) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
}
// 執(zhí)行刪除
userService.deleteById(id);
// 返回 204 狀態(tài)碼
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 注解,可以構(gòu)建出符合 HTTP 語義的資源刪除接口,提供安全可靠的刪除操作。
9. @ResponseBody
@ResponseBody 是 Spring MVC 中的重要注解,用于指示方法返回值應直接寫入 HTTP 響應體中,而不是被視圖解析器解析為視圖名稱。它是構(gòu)建 RESTful API 的關(guān)鍵注解之一。
核心作用
- 響應體直接輸出:將方法返回值直接寫入 HTTP 響應體
- 自動序列化:自動將 Java 對象序列化為 JSON、XML 等格式
- 視圖解析繞過:跳過視圖解析器,直接返回數(shù)據(jù)
- RESTful 支持:支持構(gòu)建 RESTful Web 服務
基本用法
在方法上使用
@Controller
@RequestMapping("/api")
public class ApiController {
// 返回 JSON 數(shù)據(jù)
@GetMapping("/user")
@ResponseBody
public User getUser() {
return new User("Alice", 30); // 自動轉(zhuǎn)換為 JSON
}
// 返回字符串數(shù)據(jù)
@GetMapping("/message")
@ResponseBody
public String getMessage() {
return "Hello, World!";
}
// 返回集合數(shù)據(jù)
@GetMapping("/users")
@ResponseBody
public 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 {
@GetMapping
public List<User> getUsers() {
return userService.getAllUsers();
}
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.getUserById(id);
}
}
特點
- 自動序列化:返回值會自動序列化為 JSON/XML
- 繞過視圖解析:不經(jīng)過視圖解析器
- 適用于 RESTful API:專門用于構(gòu)建 RESTful Web 服務
- 內(nèi)容協(xié)商:根據(jù)請求的 Accept 頭部返回相應格式的數(shù)據(jù)
高級用法示例
1. 自定義序列化
@Controller
public class DataController {
// 返回自定義格式的數(shù)據(jù)
@GetMapping(value = "/data", produces = "application/json")
@ResponseBody
public String getJsonData() {
return "{"name": "Alice", "age": 30}";
}
// 返回 XML 數(shù)據(jù)
@GetMapping(value = "/data.xml", produces = "application/xml")
@ResponseBody
public String getXmlData() {
return "<user><name>Alice</name><age>30</age></user>";
}
// 返回二進制數(shù)據(jù)
@GetMapping(value = "/image", produces = "image/png")
@ResponseBody
public byte[] getImage() throws IOException {
// 返回圖片數(shù)據(jù)
return Files.readAllBytes(Paths.get("path/to/image.png"));
}
}
2. ResponseEntity 結(jié)合使用
@Controller
public class UserController {
// 使用 ResponseEntity 提供更多控制
@GetMapping("/user/{id}")
@ResponseBody
public 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")
@ResponseBody
public 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);
}
}
最佳實踐
優(yōu)先使用 @RestController:對于 RESTful API,優(yōu)先使用 @RestController 而不是在每個方法上添加 @ResponseBody。
合理設置 Content-Type:使用 produces 屬性明確指定返回內(nèi)容類型。
異常處理:結(jié)合 @ExceptionHandler 或 @ControllerAdvice 處理序列化異常。
大數(shù)據(jù)處理:對于大文件下載等場景,考慮使用 StreamingResponseBody。
// 推薦的 RESTful API 設計
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
// 查詢所有用戶
@GetMapping(produces = "application/json")
public ResponseEntity<List<User>> getUsers() {
List<User> users = userService.findAll();
return ResponseEntity.ok(users);
}
// 根據(jù) 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());
}
// 創(chuàng)建用戶
@PostMapping(consumes = "application/json", produces = "application/json")
public ResponseEntity<User> createUser(@Valid @RequestBody User user,
HttpServletRequest request) {
User savedUser = userService.save(user);
// 構(gòu)建資源 URI
URI location = ServletUriComponentsBuilder
.fromContextPath(request)
.path("/api/users/{id}")
.buildAndExpand(savedUser.getId())
.toUri();
return ResponseEntity.created(location).body(savedUser);
}
}
通過合理使用 @ResponseBody 注解,可以輕松構(gòu)建出能夠返回各種格式數(shù)據(jù)的 Web API,滿足現(xiàn)代 Web 應用的多樣化需求。
10. @Service
@Service 是 Spring Framework 中用于標記業(yè)務邏輯層組件的核心注解,屬于 Spring 的典型分層架構(gòu)注解之一。它將類標識為 Spring 容器管理的服務 Bean,通常用于處理業(yè)務邏輯。
核心作用
- 業(yè)務邏輯標識:明確標識業(yè)務邏輯層組件,提高代碼可讀性
- 自動注冊:標記的類會自動注冊為 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 {
@Override
public User queryById(Long id) {
return userMapper.findById(id);
}
}
特點
- 組件掃描支持:@Service 是 @Component 的特化,會被組件掃描自動發(fā)現(xiàn)
- 默認單例模式:Spring 容器中默認以單例模式管理服務 Bean
- 依賴注入支持:可被其他組件通過 @Autowired、@Resource 等注解注入
- 生命周期管理:支持 @PostConstruct 和 @PreDestroy 等生命周期注解
高級用法示例
1. 事務管理
@Service
@Transactional
public class UserService {
@Autowired
private UserMapper userMapper;
@Transactional(readOnly = true)
public User findById(Long id) {
return userMapper.findById(id);
}
// 默認具有事務支持
public User save(User user) {
User savedUser = userMapper.save(user);
// 可能的其他業(yè)務邏輯
return savedUser;
}
// 需要新事務的方法
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logUserAction(Long userId, String action) {
// 記錄用戶操作日志
}
}
2. 與其他注解配合
@Service
@Scope("prototype") // 每次請求創(chuàng)建新實例
@Primary // 標記為主要實現(xiàn)
public class DefaultUserService implements UserService {
@Autowired
private 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);
}
}
最佳實踐
明確業(yè)務邊界:每個服務類應該具有明確的業(yè)務職責,遵循單一職責原則。
合理使用事務:
- 在服務層配置事務管理
- 根據(jù)業(yè)務需求設置合適的事務傳播行為
- 讀取操作使用 readOnly = true 提高性能
異常處理:在服務層處理業(yè)務異常,避免將底層異常直接拋出。
接口與實現(xiàn)分離:定義服務接口,通過實現(xiàn)類添加 @Service 注解。
// 推薦的服務層設計
@Service
@Transactional(readOnly = true)
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private UserValidator userValidator;
@Override
public User findById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException("User not found: " + id));
}
@Override
@Transactional
public User save(User user) {
// 參數(shù)驗證
userValidator.validate(user);
// 保存用戶
User savedUser = userRepository.save(user);
// 發(fā)布事件
applicationEventPublisher.publishEvent(new UserSavedEvent(savedUser));
return savedUser;
}
@Override
@Transactional
public void deleteById(Long id) {
User user = findById(id);
userRepository.delete(user);
// 清理相關(guān)資源
cleanupRelatedResources(user);
}
private void cleanupRelatedResources(User user) {
// 清理用戶相關(guān)的資源
}
}
通過合理使用 @Service 注解,可以構(gòu)建出結(jié)構(gòu)清晰、職責分明的業(yè)務邏輯層,提高代碼的可維護性和可測試性。
11. @Autowired
@Autowired 是 Spring Framework 中實現(xiàn)依賴注入(DI)的核心注解之一。它用于自動裝配 Bean 之間的依賴關(guān)系,是 Spring IoC 容器實現(xiàn)控制反轉(zhuǎn)的關(guān)鍵機制。
核心作用
- 自動裝配:自動將匹配的 Bean 注入到字段、構(gòu)造函數(shù)或方法中
- 解耦合:降低組件間的耦合度,提高代碼的可測試性和可維護性
- 簡化配置:減少 XML 配置或 Java 配置的工作量
- 類型安全:基于類型進行裝配,提供編譯時和運行時的安全性
基本用法
字段注入
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User queryById(Long id) {
return userMapper.findById(id);
}
}
構(gòu)造函數(shù)注入
@Service
public class UserService {
private final UserMapper userMapper;
// Spring 4.3+ 后,單構(gòu)造函數(shù)場景下可省略 @Autowired
@Autowired
public UserService(UserMapper userMapper) {
this.userMapper = userMapper;
}
public User queryById(Long id) {
return userMapper.findById(id);
}
}
方法注入
@Service
public class UserService {
private UserMapper userMapper;
@Autowired
public 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 的實現(xiàn)
@Autowired
private List<PaymentProcessor> paymentProcessors;
// 注入所有 PaymentProcessor 實現(xiàn)及其名稱
@Autowired
private 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
@Autowired
private GenericRepository<String> stringRepository;
// 注入 Integer 類型的 Repository
@Autowired
private GenericRepository<Integer> integerRepository;
}
3. 條件注入
@Service
public class ConditionalService {
// 可選注入,如果找不到 Bean 則為 null
@Autowired(required = false)
private OptionalFeature optionalFeature;
public void performOperation() {
// 使用可選功能
if (optionalFeature != null) {
optionalFeature.perform();
}
// 其他操作
}
}
最佳實踐
優(yōu)先使用構(gòu)造函數(shù)注入:
- 保證依賴不可變性(final 字段)
- 確保依賴完整性(避免 NullPointerException)
- 提高類的可測試性
避免循環(huán)依賴:
- 重新設計組件結(jié)構(gòu)
- 使用 @Lazy 注解延遲加載
- 考慮使用 Setter 注入解決循環(huán)依賴
合理使用 required 屬性:
- 對于必須的依賴保持 required = true(默認值)
- 對于可選的依賴設置 required = false
// 推薦的依賴注入方式
@Service
public class UserService {
private final UserRepository userRepository;
private final EmailService emailService;
// 構(gòu)造函數(shù)注入(推薦)
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 注解,可以實現(xiàn)松耦合、高內(nèi)聚的組件設計,提高代碼的可維護性和可測試性。
12. @Resource
@Resource 是 Java 標準注解(JSR-250)中用于依賴注入的注解,與 Spring 的 @Autowired 注解功能相似但裝配機制不同。它提供了更靈活的裝配方式,支持按名稱或類型進行裝配。
核心作用
- 標準化依賴注入:作為 Java 標準注解,提供跨框架的依賴注入能力
- 靈活裝配機制:支持按名稱或類型裝配,優(yōu)先按名稱裝配
- 減少框架綁定:使用標準注解降低對特定框架的依賴
- 兼容性支持:在不同 Java EE 兼容框架中保持一致性
基本用法
默認裝配
@Service
public class UserService {
// 按字段名稱裝配,如果找不到則按類型裝配
@Resource
private 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 的區(qū)別
| 特性 | @Autowired | @Resource |
|---|---|---|
| 來源 | Spring 框架 | Java 標準 (JSR-250) |
| 裝配方式 | 默認按類型裝配 | 默認按名稱裝配,名稱不存在時按類型裝配 |
| 屬性 | required | name, type |
| 適用場景 | Spring 特定項目 | 跨框架通用項目 |
| 性能 | 略快 | 略慢(需解析名稱和類型) |
高級用法示例
1. 混合使用場景
@Service
public class PaymentService {
// 使用 @Resource 按名稱裝配特定支付處理器
@Resource(name = "alipayProcessor")
private PaymentProcessor alipayProcessor;
// 使用 @Autowired 按類型裝配所有支付處理器
@Autowired
private List<PaymentProcessor> allProcessors;
public void processPayment(String type, BigDecimal amount) {
switch (type) {
case "alipay":
alipayProcessor.process(amount);
break;
default:
// 使用其他處理器
break;
}
}
}
2. 在不同環(huán)境中切換實現(xiàn)
@Component
@Profile("production")
public class ProductionEmailService implements EmailService {
// 生產(chǎn)環(huán)境實現(xiàn)
}
@Component
@Profile("development")
public class DevelopmentEmailService implements EmailService {
// 開發(fā)環(huán)境實現(xiàn)
}
@Service
public class NotificationService {
// 在不同環(huán)境中自動切換實現(xiàn)
@Resource
private EmailService emailService;
public void sendNotification(String message) {
emailService.send(message);
}
}
最佳實踐
選擇合適的注解:
- 在純 Spring 項目中優(yōu)先使用 @Autowired
- 在需要跨框架兼容的項目中使用 @Resource
明確裝配策略:
- 需要精確控制時使用 name 或 type 屬性
- 一般情況下可依賴默認裝配機制
保持一致性:
- 在同一項目中保持依賴注入注解的使用一致性
- 團隊內(nèi)部應制定明確的編碼規(guī)范
// 推薦的 @Resource 使用方式
@Service
public class OrderService {
// 明確按名稱裝配
@Resource(name = "orderRepository")
private OrderRepository orderRepository;
// 按類型裝配(適用于單一實現(xiàn))
@Resource(type = PaymentService.class)
private PaymentService paymentService;
// 默認裝配(適用于名稱匹配的場景)
@Resource
private InventoryService inventoryService;
public void processOrder(Order order) {
// 處理訂單邏輯
orderRepository.save(order);
paymentService.processPayment(order);
inventoryService.updateInventory(order);
}
}
通過合理使用 @Resource 注解,可以在享受依賴注入便利的同時,保持代碼的標準化和框架無關(guān)性。
13. @CrossOrigin
@CrossOrigin 是 Spring MVC 中用于處理跨域資源共享(CORS)的注解。它允許您在 Web 應用中輕松配置跨域請求策略,解決瀏覽器同源策略限制。
核心作用
- 跨域訪問控制:允許指定域的請求訪問當前服務的資源
- HTTP 方法控制:限制允許的 HTTP 請求方法
- 請求頭管理:控制允許的請求頭和暴露的響應頭
- 預檢請求緩存:通過 maxAge 屬性優(yōu)化預檢請求性能
基本用法
類級別使用
@RestController
@RequestMapping("/api/users")
@CrossOrigin(origins = "http://localhost:3000")
public class UserController {
@GetMapping
public 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 {
@Override
public 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");
}
}
最佳實踐
安全性考慮:
- 避免在生產(chǎn)環(huán)境中使用 origins = “*”,除非確實需要
- 對于需要攜帶憑證的請求,必須指定具體的源地址
- 限制允許的 HTTP 方法和請求頭
性能優(yōu)化:
- 合理設置 maxAge 值,減少預檢請求次數(shù)
- 盡量在類級別而非方法級別配置 CORS
配置方式選擇:
- 全局配置適用于統(tǒng)一的跨域策略
- 局部配置適用于特殊接口的跨域需求
// 推薦的生產(chǎn)環(huán)境 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 {
@Autowired
private UserService userService;
@GetMapping
public ResponseEntity<List<User>> getUsers() {
List<User> users = userService.findAll();
return ResponseEntity.ok(users);
}
@PostMapping
public 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。
核心作用
- 配置類標識:標識一個類作為配置類,替代傳統(tǒng)的 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) 的特化版本,可被組件掃描自動發(fā)現(xiàn)
- 條件化配置:可與 [@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) 等注解結(jié)合,實現(xiàn)條件化配置
基本用法示例
簡單配置類
@Configuration
public class AppConfig {
@Bean
public UserService userService() {
return new UserServiceImpl();
}
@Bean
public 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;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(databaseUrl);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
@Bean
public 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 {
@Bean
public DataSource dataSource() {
// 生產(chǎn)環(huán)境數(shù)據(jù)源配置
return new HikariDataSource();
}
}
@Configuration
@Profile("development")
public class DevelopmentDatabaseConfig {
@Bean
public DataSource dataSource() {
// 開發(fā)環(huán)境數(shù)據(jù)源配置
return new DriverManagerDataSource();
}
}
導入其他配置
@Configuration
@ComponentScan("com.example")
@Import({DatabaseConfig.class, SecurityConfig.class})
@PropertySource("classpath:application.properties")
public class MainConfig {
@Bean
public ApplicationService applicationService() {
return new ApplicationServiceImpl();
}
}
最佳實踐
- 明確配置職責:每個配置類應該有明確的職責,如數(shù)據(jù)庫配置、安全配置等
- 合理使用 [@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) 注解注入配置屬性,實現(xiàn)配置與代碼的分離
- 避免復雜邏輯:配置類中應避免復雜的業(yè)務邏輯,專注于 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;
@Bean
public ApplicationService applicationService(
UserService userService,
NotificationService notificationService) {
ApplicationServiceImpl service = new ApplicationServiceImpl();
service.setUserService(userService);
service.setNotificationService(notificationService);
service.setApplicationName(applicationName);
return service;
}
}
通過合理使用 @Configuration 注解,可以構(gòu)建出結(jié)構(gòu)清晰、模塊化的配置體系,提高應用的可維護性和可測試性。
15. @Bean
@Bean 是 Spring Framework 中用于在配置類中定義 Bean 的核心注解。它告訴 Spring 容器,被注解的方法將返回一個對象,該對象應該被注冊為 Spring 應用上下文中的 Bean。
核心作用
- Bean 定義:在配置類中定義和配置 Spring Bean
- 生命周期管理:通過 initMethod 和 destroyMethod 屬性管理 Bean 的生命周期
- 依賴注入:方法參數(shù)會自動從容器中獲取并注入
- Bean 名稱定制:通過 name 屬性自定義 Bean 的名稱
基本用法
簡單 Bean 定義
@Configuration
public class AppConfig {
@Bean
public UserService userService() {
return new UserServiceImpl();
}
@Bean
public UserMapper userMapper() {
return new UserMapperImpl();
}
}
依賴其他 Bean
@Configuration
public class AppConfig {
@Bean
public UserMapper userMapper() {
return new UserMapperImpl();
}
// 方法參數(shù)會自動從容器中獲取并注入
@Bean
public UserService userService(UserMapper userMapper) {
UserServiceImpl service = new UserServiceImpl();
service.setUserMapper(userMapper);
return service;
}
}
主要屬性
| 屬性 | 類型 | 說明 |
|---|---|---|
| name | String[] | Bean 的名稱,默認為方法名 |
| initMethod | String | 初始化方法名,在 Bean 初始化時調(diào)用 |
| destroyMethod | String | 銷毀方法名,在 Bean 銷毀時調(diào)用 |
| 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();
}
}
最佳實踐
- 方法參數(shù)注入:利用方法參數(shù)自動注入依賴,比手動從容器獲取更簡潔
- 合理命名:對于需要自定義名稱的 Bean,使用 name 屬性明確指定
- 生命周期管理:對于需要初始化或清理操作的 Bean,配置 initMethod 和 destroyMethod
- 作用域選擇:根據(jù) 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);
}
@Bean
public 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("執(zhí)行某些操作");
}
}
帶名稱的組件
@Component("myCustomComponent")
public class MyComponent {
public void performAction() {
System.out.println("執(zhí)行操作");
}
}
特點
- 通用性:適用于任何 Spring 管理的組件
- 自動發(fā)現(xiàn):配合 [@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
- 可注入性:可被其他組件注入使用
- 繼承性:其他組件注解的基礎注解
與其他注解的關(guān)系
| 注解 | 用途 | 說明 |
|---|---|---|
| [@Repository](file:///D:/workspace/spring_clouds/10-riskmgmt/spec/src/main/java/com/citics/riskmgnt/spec/citicRuleCheck/dao/CiticRuleCheckDao.java#L10-L10) | 持久層組件 | 專門用于數(shù)據(jù)訪問層,提供持久層異常轉(zhuǎn)換 |
| [@Service](file:///D:/workspace/spring_clouds/10-riskmgmt/spec/src/main/java/com/citics/riskmgnt/spec/userauth/service/impl/UserAuthServiceImpl.java#L17-L17) | 業(yè)務層組件 | 專門用于業(yè)務邏輯層 |
| [@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("開發(fā)環(huán)境下的操作");
}
}
@Component
@Profile("production")
public class ProductionService {
public void performAction() {
System.out.println("生產(chǎn)環(huán)境下的操作");
}
}
帶作用域的組件
@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("會話范圍組件操作");
}
}
最佳實踐
- 語義化選擇:優(yōu)先使用語義更明確的注解([@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)
- 命名規(guī)范:對于需要自定義名稱的組件,明確指定名稱
- 組件職責:每個組件應有明確的職責,遵循單一職責原則
// 推薦的組件設計
@Component
public class FileStorageService {
private final StorageProperties storageProperties;
// 構(gòu)造函數(shù)注入(推薦)
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 及其特化注解,可以構(gòu)建出結(jié)構(gòu)清晰、職責明確的 Spring 應用程序,提高代碼的可維護性和可讀性。
17. @Value
@Value 是 Spring Framework 中用于注入屬性值的核心注解。它可以將配置文件中的屬性值、系統(tǒng)屬性、環(huán)境變量等注入到 Spring 管理的 Bean 屬性中。
核心作用
- 屬性注入:將外部配置屬性注入到 Bean 的字段或方法參數(shù)中
- 表達式支持:支持 Spring Expression Language (SpEL) 表達式
- 默認值設置:可以為屬性設置默認值,提高應用的健壯性
- 配置分離:實現(xiàn)配置與代碼的分離,便于維護和部署
基本用法
注入簡單屬性值
@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;
// 數(shù)組默認值
@Value("${app.servers:server1,server2,server3}")
private String[] servers;
}
主要屬性
@Value 注解只有一個 value 屬性,用于指定要注入的值:
| 屬性 | 類型 | 說明 |
|---|---|---|
| value | String | 指定要注入的屬性值或表達式 |
高級用法示例
使用 SpEL 表達式
@Component
public class ExpressionConfig {
// 字面量表達式
@Value("#{10 * 20}")
private int calculationResult;
// 系統(tǒng)屬性
@Value("#{systemProperties['java.home']}")
private String javaHome;
// 隨機值
@Value("#{T(java.lang.Math).random() * 100.0}")
private double randomNumber;
// 調(diào)用其他 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 {
// 根據(jù)系統(tǒng)屬性決定是否啟用某個功能
@Value("#{systemProperties['feature.enabled'] ?: false}")
private boolean featureEnabled;
// 根據(jù)配置文件決定超時時間
@Value("#{${app.timeout:30} * 1000}")
private long timeoutInMillis;
}
最佳實踐
合理使用默認值:為配置屬性提供合理的默認值,增強應用的健壯性,避免因缺少配置導致應用啟動失敗。
類型安全:確保配置值能夠正確轉(zhuǎn)換為目標類型,避免類型轉(zhuǎn)換異常。
配置分組:對于相關(guān)的配置項,考慮使用配置類進行分組管理。
避免硬編碼:不要在 @Value 注解中硬編碼敏感信息,應該使用配置文件或環(huán)境變量。
// 推薦的配置管理方式
@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;
@Bean
public DataSource dataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setJdbcUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
在構(gòu)造函數(shù)中使用
@Component
public class EmailService {
private final String smtpHost;
private final int smtpPort;
private final boolean useSSL;
// 構(gòu)造函數(shù)注入配置值
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;
}
// 郵件發(fā)送邏輯
public void sendEmail(String to, String subject, String content) {
// 實現(xiàn)郵件發(fā)送邏輯
}
}
通過合理使用 @Value 注解,可以輕松地將外部配置注入到 Spring 應用中,實現(xiàn)配置與代碼的分離,提高應用的靈活性和可維護性。
總結(jié)
到此這篇關(guān)于springboot常見的一些相關(guān)注解總結(jié)的文章就介紹到這了,更多相關(guān)springboot相關(guān)注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java面試中經(jīng)常會問到的mysql問題有哪些總結(jié)(基礎版)
MySQL作為常見的數(shù)據(jù)庫技術(shù),其掌握程度往往是評估候選人綜合能力的重要組成部分,下面這篇文章主要介紹了java面試中經(jīng)常會問到的mysql問題有哪些的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2025-10-10
SpringMVC高級開發(fā)功能實現(xiàn)過程解析
這篇文章主要介紹了SpringMVC高級開發(fā)功能實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-06-06
Spring?Validation實現(xiàn)數(shù)據(jù)校驗的示例
Spring?Validation其實就是對Hibernate?Validator進一步的封裝,方便在Spring中使用,這篇文章主要介紹了Spring?Validation實現(xiàn)數(shù)據(jù)校驗的示例,需要的朋友可以參考下2023-03-03
AsyncHttpClient的ConnectionSemaphore方法源碼流程解讀
這篇文章主要為大家介紹了AsyncHttpClient的ConnectionSemaphore方法源碼流程解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12

